drivers/hid/hid-cypress.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hid/hid-cypress.c
Extension
.c
Size
5044 bytes
Lines
193
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 cp_device {
	unsigned long quirks;
};

/*
 * Some USB barcode readers from cypress have usage min and usage max in
 * the wrong order
 */
static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	unsigned int i;

	if (*rsize < 4)
		return rdesc;

	for (i = 0; i < *rsize - 4; i++)
		if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
			rdesc[i] = 0x19;
			rdesc[i + 2] = 0x29;
			swap(rdesc[i + 3], rdesc[i + 1]);
		}
	return rdesc;
}

static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	/*
	 * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly
	 * reports Logical Minimum of its Consumer Control device as 572
	 * (0x02 0x3c). Fix this by setting its Logical Minimum to zero.
	 */
	if (*rsize == 25 &&
			rdesc[0] == 0x05 && rdesc[1] == 0x0c &&
			rdesc[2] == 0x09 && rdesc[3] == 0x01 &&
			rdesc[6] == 0x19 && rdesc[7] == 0x00 &&
			rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) {
		hid_info(hdev,
			 "fixing up varmilo VA104M consumer control report descriptor\n");
		rdesc[12] = 0x00;
		rdesc[13] = 0x00;
	}
	return rdesc;
}

static const __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	const struct cp_device *cp_device = hid_get_drvdata(hdev);
	unsigned long quirks = cp_device->quirks;

	if (quirks & CP_RDESC_SWAPPED_MIN_MAX)
		rdesc = cp_rdesc_fixup(hdev, rdesc, rsize);
	if (quirks & VA_INVAL_LOGICAL_BOUNDARY)
		rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize);

	return rdesc;
}

static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	const struct cp_device *cp_device = hid_get_drvdata(hdev);
	unsigned long quirks = cp_device->quirks;

	if (!(quirks & CP_2WHEEL_MOUSE_HACK))
		return 0;

	if (usage->type == EV_REL && usage->code == REL_WHEEL)
		set_bit(REL_HWHEEL, *bit);
	if (usage->hid == 0x00090005)
		return -1;

	return 0;
}

static int cp_event(struct hid_device *hdev, struct hid_field *field,
		struct hid_usage *usage, __s32 value)
{
	struct cp_device *cp_device = hid_get_drvdata(hdev);

	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
			!usage->type || !(cp_device->quirks & CP_2WHEEL_MOUSE_HACK))
		return 0;

	if (usage->hid == 0x00090005) {
		if (value)
			cp_device->quirks |= CP_2WHEEL_MOUSE_HACK_ON;

Annotation

Implementation Notes