drivers/hid/hid-rmi.c

Source file repositories/reference/linux-study-clean/drivers/hid/hid-rmi.c

File Facts

System
Linux kernel
Corpus path
drivers/hid/hid-rmi.c
Extension
.c
Size
19283 bytes
Lines
785
Domain
Driver Families
Bucket
drivers/hid
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 rmi_data {
	struct mutex page_mutex;
	int page;
	struct rmi_transport_dev xport;

	wait_queue_head_t wait;

	u8 *writeReport;
	u8 *readReport;

	u32 input_report_size;
	u32 output_report_size;

	unsigned long flags;

	struct work_struct reset_work;
	struct hid_device *hdev;

	unsigned long device_flags;

	struct irq_domain *domain;
	int rmi_irq;
};

#define RMI_PAGE(addr) (((addr) >> 8) & 0xff)

static int rmi_write_report(struct hid_device *hdev, u8 *report, int len);

/**
 * rmi_set_page - Set RMI page
 * @hdev: The pointer to the hid_device struct
 * @page: The new page address.
 *
 * RMI devices have 16-bit addressing, but some of the physical
 * implementations (like SMBus) only have 8-bit addressing. So RMI implements
 * a page address at 0xff of every page so we can reliable page addresses
 * every 256 registers.
 *
 * The page_mutex lock must be held when this function is entered.
 *
 * Returns zero on success, non-zero on failure.
 */
static int rmi_set_page(struct hid_device *hdev, u8 page)
{
	struct rmi_data *data = hid_get_drvdata(hdev);
	int retval;

	data->writeReport[0] = RMI_WRITE_REPORT_ID;
	data->writeReport[1] = 1;
	data->writeReport[2] = 0xFF;
	data->writeReport[4] = page;

	retval = rmi_write_report(hdev, data->writeReport,
			data->output_report_size);
	if (retval != data->output_report_size) {
		dev_err(&hdev->dev,
			"%s: set page failed: %d.", __func__, retval);
		return retval;
	}

	data->page = page;
	return 0;
}

static int rmi_set_mode(struct hid_device *hdev, u8 mode)
{
	int ret;
	const u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode};
	u8 *buf;

	buf = kmemdup(txbuf, sizeof(txbuf), GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, buf,
			sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
	kfree(buf);
	if (ret < 0) {
		dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode,
			ret);
		return ret;
	}

	return 0;
}

static int rmi_write_report(struct hid_device *hdev, u8 *report, int len)
{
	struct rmi_data *data = hid_get_drvdata(hdev);
	int ret;

Annotation

Implementation Notes