drivers/input/rmi4/rmi_smbus.c

Source file repositories/reference/linux-study-clean/drivers/input/rmi4/rmi_smbus.c

File Facts

System
Linux kernel
Corpus path
drivers/input/rmi4/rmi_smbus.c
Extension
.c
Size
11022 bytes
Lines
437
Domain
Driver Families
Bucket
drivers/input
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mapping_table_entry {
	__le16 rmiaddr;
	u8 readcount;
	u8 flags;
};

struct rmi_smb_xport {
	struct rmi_transport_dev xport;
	struct i2c_client *client;

	struct mutex page_mutex;
	int page;
	u8 table_index;
	struct mutex mappingtable_mutex;
	struct mapping_table_entry mapping_table[RMI_SMB2_MAP_SIZE];
};

static int rmi_smb_get_version(struct rmi_smb_xport *rmi_smb)
{
	struct i2c_client *client = rmi_smb->client;
	int retval;

	/* Check if for SMBus new version device by reading version byte. */
	retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS);
	if (retval < 0) {
		dev_err(&client->dev, "failed to get SMBus version number!\n");
		return retval;
	}

	return retval + 1;
}

/* SMB block write - wrapper over ic2_smb_write_block */
static int smb_block_write(struct rmi_transport_dev *xport,
			      u8 commandcode, const void *buf, size_t len)
{
	struct rmi_smb_xport *rmi_smb =
		container_of(xport, struct rmi_smb_xport, xport);
	struct i2c_client *client = rmi_smb->client;
	int retval;

	retval = i2c_smbus_write_block_data(client, commandcode, len, buf);

	rmi_dbg(RMI_DEBUG_XPORT, &client->dev,
		"wrote %zd bytes at %#04x: %d (%*ph)\n",
		len, commandcode, retval, (int)len, buf);

	return retval;
}

/*
 * The function to get command code for smbus operations and keeps
 * records to the driver mapping table
 */
static int rmi_smb_get_command_code(struct rmi_transport_dev *xport,
		u16 rmiaddr, int bytecount, bool isread, u8 *commandcode)
{
	struct rmi_smb_xport *rmi_smb =
		container_of(xport, struct rmi_smb_xport, xport);
	struct mapping_table_entry new_map;
	int i;
	int retval = 0;

	mutex_lock(&rmi_smb->mappingtable_mutex);

	for (i = 0; i < RMI_SMB2_MAP_SIZE; i++) {
		struct mapping_table_entry *entry = &rmi_smb->mapping_table[i];

		if (le16_to_cpu(entry->rmiaddr) == rmiaddr) {
			if (isread) {
				if (entry->readcount == bytecount)
					goto exit;
			} else {
				if (entry->flags & RMI_SMB2_MAP_FLAGS_WE) {
					goto exit;
				}
			}
		}
	}

	i = rmi_smb->table_index;
	rmi_smb->table_index = (i + 1) % RMI_SMB2_MAP_SIZE;

	/* constructs mapping table data entry. 4 bytes each entry */
	memset(&new_map, 0, sizeof(new_map));
	new_map.rmiaddr = cpu_to_le16(rmiaddr);
	new_map.readcount = bytecount;
	new_map.flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0;

	retval = smb_block_write(xport, i + 0x80, &new_map, sizeof(new_map));

Annotation

Implementation Notes