drivers/hid/hid-mcp2221.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hid/hid-mcp2221.c
Extension
.c
Size
31032 bytes
Lines
1366
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 mcp_set_gpio {
	u8 cmd;
	u8 dummy;
	struct {
		u8 change_value;
		u8 value;
		u8 change_direction;
		u8 direction;
	} gpio[MCP_NGPIO];
} __packed;

/* MCP GPIO get command layout */
struct mcp_get_gpio {
	u8 cmd;
	u8 dummy;
	struct {
		u8 value;
		u8 direction;
	} gpio[MCP_NGPIO];
} __packed;

/*
 * There is no way to distinguish responses. Therefore next command
 * is sent only after response to previous has been received. Mutex
 * lock is used for this purpose mainly.
 */
struct mcp2221 {
	struct hid_device *hdev;
	struct i2c_adapter adapter;
	struct mutex lock;
	struct completion wait_in_report;
	struct delayed_work init_work;
	u8 *rxbuf;
	u8 txbuf[64];
	int rxbuf_idx;
	int rxbuf_size;
	int status;
	u8 cur_i2c_clk_div;
	struct gpio_chip *gc;
	u8 gp_idx;
	u8 gpio_dir;
	u8 mode[4];
#if IS_REACHABLE(CONFIG_IIO)
	struct iio_chan_spec iio_channels[3];
	u16 adc_values[3];
	u8 adc_scale;
	u8 dac_value;
	u16 dac_scale;
#endif
};

struct mcp2221_iio {
	struct mcp2221 *mcp;
};

/*
 * Default i2c bus clock frequency 400 kHz. Modify this if you
 * want to set some other frequency (min 50 kHz - max 400 kHz).
 */
static uint i2c_clk_freq = 400;

/* Synchronously send output report to the device */
static int mcp_send_report(struct mcp2221 *mcp,
					u8 *out_report, size_t len)
{
	u8 *buf;
	int ret;

	buf = kmemdup(out_report, len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	/* mcp2221 uses interrupt endpoint for out reports */
	ret = hid_hw_output_report(mcp->hdev, buf, len);
	kfree(buf);

	if (ret < 0)
		return ret;
	return 0;
}

/*
 * Send o/p report to the device and wait for i/p report to be
 * received from the device. If the device does not respond,
 * we timeout.
 */
static int mcp_send_data_req_status(struct mcp2221 *mcp,
			u8 *out_report, int len)
{
	int ret;

Annotation

Implementation Notes