drivers/input/mouse/synaptics_usb.c

Source file repositories/reference/linux-study-clean/drivers/input/mouse/synaptics_usb.c

File Facts

System
Linux kernel
Corpus path
drivers/input/mouse/synaptics_usb.c
Extension
.c
Size
14522 bytes
Lines
547
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 synusb {
	struct usb_device *udev;
	struct usb_interface *intf;
	struct urb *urb;
	unsigned char *data;

	/* serialize access to open/suspend */
	struct mutex pm_mutex;
	bool is_open;

	/* input device related data structures */
	struct input_dev *input;
	char name[128];
	char phys[64];

	/* characteristics of the device */
	unsigned long flags;
};

static void synusb_report_buttons(struct synusb *synusb)
{
	struct input_dev *input_dev = synusb->input;

	input_report_key(input_dev, BTN_LEFT, synusb->data[1] & 0x04);
	input_report_key(input_dev, BTN_RIGHT, synusb->data[1] & 0x01);
	input_report_key(input_dev, BTN_MIDDLE, synusb->data[1] & 0x02);
}

static void synusb_report_stick(struct synusb *synusb)
{
	struct input_dev *input_dev = synusb->input;
	int x, y;
	unsigned int pressure;

	pressure = synusb->data[6];
	x = (s16)(be16_to_cpup((__be16 *)&synusb->data[2]) << 3) >> 7;
	y = (s16)(be16_to_cpup((__be16 *)&synusb->data[4]) << 3) >> 7;

	if (pressure > 0) {
		input_report_rel(input_dev, REL_X, x);
		input_report_rel(input_dev, REL_Y, -y);
	}

	input_report_abs(input_dev, ABS_PRESSURE, pressure);

	synusb_report_buttons(synusb);

	input_sync(input_dev);
}

static void synusb_report_touchpad(struct synusb *synusb)
{
	struct input_dev *input_dev = synusb->input;
	unsigned int num_fingers, tool_width;
	unsigned int x, y;
	unsigned int pressure, w;

	pressure = synusb->data[6];
	x = be16_to_cpup((__be16 *)&synusb->data[2]);
	y = be16_to_cpup((__be16 *)&synusb->data[4]);
	w = synusb->data[0] & 0x0f;

	if (pressure > 0) {
		num_fingers = 1;
		tool_width = 5;
		switch (w) {
		case 0 ... 1:
			num_fingers = 2 + w;
			break;

		case 2:	                /* pen, pretend its a finger */
			break;

		case 4 ... 15:
			tool_width = w;
			break;
		}
	} else {
		num_fingers = 0;
		tool_width = 0;
	}

	/*
	 * Post events
	 * BTN_TOUCH has to be first as mousedev relies on it when doing
	 * absolute -> relative conversion
	 */

	if (pressure > 30)
		input_report_key(input_dev, BTN_TOUCH, 1);

Annotation

Implementation Notes