<commit_before>/*
 * Copyright (C) 2015-2019 <NAME> <<EMAIL>>
 * Copyright (C) 2016 <NAME> <<EMAIL>>
 * Copyright (C) 2017 <NAME> <<EMAIL>>
 * Copyright (C) 2018 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <fcntl.h>

#include "fu-synaptics-mst-common.h"
#include "fu-synaptics-mst-connection.h"
#include "fu-synaptics-mst-device.h"

#define FU_SYNAPTICS_MST_ID_CTRL_SIZE	0x1000
#define SYNAPTICS_UPDATE_ENUMERATE_TRIES 3

#define BIT(n)				(1 << (n))
#define FLASH_SECTOR_ERASE_4K		0x1000
#define FLASH_SECTOR_ERASE_32K		0x2000
#define FLASH_SECTOR_ERASE_64K		0x3000
#define EEPROM_TAG_OFFSET		0x1FFF0
#define EEPROM_BANK_OFFSET		0x20000
#define EEPROM_ESM_OFFSET		0x40000
#define ESM_CODE_SIZE			0x40000
#define PAYLOAD_SIZE_512K		0x80000
#define PAYLOAD_SIZE_64K		0x10000
#define MAX_RETRY_COUNTS		10
#define BLOCK_UNIT			64
#define BANKTAG_0			0
#define BANKTAG_1			1
#define CRC_8				8
#define CRC_16				16
#define REG_ESM_DISABLE			0x2000fc
#define REG_QUAD_DISABLE		0x200fc0
#define REG_HDCP22_DISABLE		0x200f90

#define FLASH_SETTLE_TIME		5000000	/* us */

struct _FuSynapticsMstDevice {
	FuUdevDevice		 parent_instance;
	gchar			*system_type;
	guint64			 write_block_size;
	FuSynapticsMstFamily	 family;
	FuSynapticsMstMode	 mode;
	guint8			 active_bank;
	guint8			 layer;
	guint16			 rad;		/* relative address */
	guint32			 board_id;
	guint16			 chip_id;
};

G_DEFINE_TYPE (FuSynapticsMstDevice, fu_synaptics_mst_device, FU_TYPE_UDEV_DEVICE)

static void
fu_synaptics_mst_device_finalize (GObject *object)
{
	FuSynapticsMstDevice *self = FU_SYNAPTICS_MST_DEVICE (object);

	g_free (self->system_type);

	G_OBJECT_CLASS (fu_synaptics_mst_device_parent_class)->finalize (object);
}

static void
fu_synaptics_mst_device_init (FuSynapticsMstDevice *self)
{
	fu_device_set_protocol (FU_DEVICE (self), "com.synaptics.mst");
	fu_device_set_vendor (FU_DEVICE (self), "Synaptics");
	fu_device_set_vendor_id (FU_DEVICE (self), "DRM_DP_AUX_DEV:0x06CB");
	fu_device_set_summary (FU_DEVICE (self), "Multi-Stream Transport Device");
	fu_device_add_icon (FU_DEVICE (self), "video-display");
	fu_udev_device_set_flags (FU_UDEV_DEVICE (self),
				  FU_UDEV_DEVICE_FLAG_OPEN_READ |
				  FU_UDEV_DEVICE_FLAG_OPEN_WRITE |
				  FU_UDEV_DEVICE_FLAG_VENDOR_FROM_PARENT);
}

static void
fu_synaptics_mst_device_to_string (FuDevice *device, guint idt, GString *str)
{
	FuSynapticsMstDevice *self = FU_SYNAPTICS_MST_DEVICE (device);
	if (self->mode != FU_SYNAPTICS_MST_MODE_UNKNOWN) {
		fu_common_string_append_kv (str, idt, "Mode",
					    fu_synaptics_mst_mode_to_string (self->mode));
	}
	if (self->family == FU_SYNAPTICS_MST_FAMILY_PANAMERA)
		fu_common_string_append_kx (str, idt, "ActiveBank", self->active_bank);
	fu_common_string_append_kx (str, idt, "Layer", self->layer);
	fu_common_string_append_kx (str, idt, "Rad", self->rad);
	if (self->board_id != 0x0)
		fu_common_string_append_ku (str, idt, "BoardId", self->board_id);
	if (self->chip_id != 0x0)
		fu_common_string_append_kx (str, idt, "ChipId", self->chip_id);
}

static gboolean
fu_synaptics_mst_device_enable_rc (FuSynapticsMstDevice *self, GError **error)
{
	g_autoptr(FuSynapticsMstConnection) connection = NULL;

	/* in test mode */
	if (fu_udev_device_get_dev (FU_UDEV_DEVICE (self)) == NULL)
		return TRUE;

	connection = fu_synaptics_mst_connection_new (fu_udev_device_get_fd (FU_UDEV_DEVICE (self)),
						      self->layer, self->rad);
	return fu_synaptics_mst_connection_enable_rc (connection, error);
}

static gboolean
fu_synaptics_mst_device_disable_rc (FuSynapticsMstDevice *self, GError **error)
{
	g_autoptr(FuSynapticsMstConnection) connection = NULL;

	/* in test mode */
	if (fu_udev_device_get_dev (FU_UDEV_DEVICE (self)) == NULL)
		return TRUE;

	connection = fu_synaptics_mst_connection_new (fu_udev_device_get_fd (FU_UDEV_DEVICE (self)),
						      self->layer, self->rad);
	return fu_synaptics_mst_connection_disable_rc (connection, error);
}

static gboolean
fu_synaptics_mst_device_probe (FuUdevDevice *device, GError **error)
{
	g_autofree gchar *logical_id = NULL;
	logical_id = g_path_get_basename (fu_udev_device_get_sysfs_path(device));
	fu_device_set_logical_id (FU_DEVICE (device), logical_id);
	if (!fu_udev_device_set_physical_id (device, "pci", error))
		return FALSE;<commit_msg>synaptics-mst: Allow MST to fall back if no PCI device is marked as parent<commit_after>/*
 * Copyright (C) 2015-2019 <NAME> <<EMAIL>>
 * Copyright (C) 2016 <NAME> <<EMAIL>>
 * Copyright (C) 2017 <NAME> <<EMAIL>>
 * Copyright (C) 2018 <NAME> <<EMAIL>>
 *
 * SPDX-License-Identifier: LGPL-2.1+
 */

#include "config.h"

#include <fcntl.h>

#include "fu-synaptics-mst-common.h"
#include "fu-synaptics-mst-connection.h"
#include "fu-synaptics-mst-device.h"

#define FU_SYNAPTICS_MST_ID_CTRL_SIZE	0x1000
#define SYNAPTICS_UPDATE_ENUMERATE_TRIES 3

#define BIT(n)				(1 << (n))
#define FLASH_SECTOR_ERASE_4K		0x1000
#define FLASH_SECTOR_ERASE_32K		0x2000
#define FLASH_SECTOR_ERASE_64K		0x3000
#define EEPROM_TAG_OFFSET		0x1FFF0
#define EEPROM_BANK_OFFSET		0x20000
#define EEPROM_ESM_OFFSET		0x40000
#define ESM_CODE_SIZE			0x40000
#define PAYLOAD_SIZE_512K		0x80000
#define PAYLOAD_SIZE_64K		0x10000
#define MAX_RETRY_COUNTS		10
#define BLOCK_UNIT			64
#define BANKTAG_0			0
#define BANKTAG_1			1
#define CRC_8				8
#define CRC_16				16
#define REG_ESM_DISABLE			0x2000fc
#define REG_QUAD_DISABLE		0x200fc0
#define REG_HDCP22_DISABLE		0x200f90

#define FLASH_SETTLE_TIME		5000000	/* us */

struct _FuSynapticsMstDevice {
	FuUdevDevice		 parent_instance;
	gchar			*system_type;
	guint64			 write_block_size;
	FuSynapticsMstFamily	 family;
	FuSynapticsMstMode	 mode;
	guint8			 active_bank;
	guint8			 layer;
	guint16			 rad;		/* relative address */
	guint32			 board_id;
	guint16			 chip_id;
};

G_DEFINE_TYPE (FuSynapticsMstDevice, fu_synaptics_mst_device, FU_TYPE_UDEV_DEVICE)

static void
fu_synaptics_mst_device_finalize (GObject *object)
{
	FuSynapticsMstDevice *self = FU_SYNAPTICS_MST_DEVICE (object);

	g_free (self->system_type);

	G_OBJECT_CLASS (fu_synaptics_mst_device_parent_class)->finalize (object);
}

static void
fu_synaptics_mst_device_init (FuSynapticsMstDevice *self)
{
	fu_device_set_protocol (FU_DEVICE (self), "com.synaptics.mst");
	fu_device_set_vendor (FU_DEVICE (self), "Synaptics");
	fu_device_set_vendor_id (FU_DEVICE (self), "DRM_DP_AUX_DEV:0x06CB");
	fu_device_set_summary (FU_DEVICE (self), "Multi-Stream Transport Device");
	fu_device_add_icon (FU_DEVICE (self), "video-display");
	fu_udev_device_set_flags (FU_UDEV_DEVICE (self),
				  FU_UDEV_DEVICE_FLAG_OPEN_READ |
				  FU_UDEV_DEVICE_FLAG_OPEN_WRITE |
				  FU_UDEV_DEVICE_FLAG_VENDOR_FROM_PARENT);
}

static void
fu_synaptics_mst_device_to_string (FuDevice *device, guint idt, GString *str)
{
	FuSynapticsMstDevice *self = FU_SYNAPTICS_MST_DEVICE (device);
	if (self->mode != FU_SYNAPTICS_MST_MODE_UNKNOWN) {
		fu_common_string_append_kv (str, idt, "Mode",
					    fu_synaptics_mst_mode_to_string (self->mode));
	}
	if (self->family == FU_SYNAPTICS_MST_FAMILY_PANAMERA)
		fu_common_string_append_kx (str, idt, "ActiveBank", self->active_bank);
	fu_common_string_append_kx (str, idt, "Layer", self->layer);
	fu_common_string_append_kx (str, idt, "Rad", self->rad);
	if (self->board_id != 0x0)
		fu_common_string_append_ku (str, idt, "BoardId", self->board_id);
	if (self->chip_id != 0x0)
		fu_common_string_append_kx (str, idt, "ChipId", self->chip_id);
}

static gboolean
fu_synaptics_mst_device_enable_rc (FuSynapticsMstDevice *self, GError **error)
{
	g_autoptr(FuSynapticsMstConnection) connection = NULL;

	/* in test mode */
	if (fu_udev_device_get_dev (FU_UDEV_DEVICE (self)) == NULL)
		return TRUE;

	connection = fu_synaptics_mst_connection_new (fu_udev_device_get_fd (FU_UDEV_DEVICE (self)),
						      self->layer, self->rad);
	return fu_synaptics_mst_connection_enable_rc (connection, error);
}

static gboolean
fu_synaptics_mst_device_disable_rc (FuSynapticsMstDevice *self, GError **error)
{
	g_autoptr(FuSynapticsMstConnection) connection = NULL;

	/* in test mode */
	if (fu_udev_device_get_dev (FU_UDEV_DEVICE (self)) == NULL)
		return TRUE;

	connection = fu_synaptics_mst_connection_new (fu_udev_device_get_fd (FU_UDEV_DEVICE (self)),
						      self->layer, self->rad);
	return fu_synaptics_mst_connection_disable_rc (connection, error);
}

static gboolean
fu_synaptics_mst_device_probe (FuUdevDevice *device, GError **error)
{
	g_autofree gchar *logical_id = NULL;
	logical_id = g_path_get_basename (fu_udev_device_get_sysfs_path(device));
	fu_device_set_logical_id (FU_DEVICE (device), logical_id);
	if (!fu_udev_device_set_physical_id (device, "pci,drm_dp_aux_dev", error))
		return FALSE;
{'fraction_non_alphanumeric': 0.1003440366972477, 'fraction_numerical': 0.03279816513761468, 'mean_word_length': 6.142506142506143, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1452849', 'n_tokens_mistral': 3992, 'n_tokens_neox': 3585, 'n_words': 650}