drivers/hid/hid-winwing.c

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

File Facts

System
Linux kernel
Corpus path
drivers/hid/hid-winwing.c
Extension
.c
Size
9053 bytes
Lines
437
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 winwing_led {
	struct led_classdev cdev;
	struct hid_device *hdev;
	int number;
};

struct winwing_led_info {
	int number;
	int max_brightness;
	const char *led_name;
};

static const struct winwing_led_info led_info[3] = {
	{ 0, 255, "backlight" },
	{ 1, 1, "a-a" },
	{ 2, 1, "a-g" },
};

struct winwing_drv_data {
	struct hid_device *hdev;
	struct mutex lights_lock;
	__u8 *report_lights;
	__u8 *report_rumble;
	struct work_struct rumble_work;
	struct ff_rumble_effect rumble;
	int rumble_left;
	int rumble_right;
	int has_grip15;
	struct winwing_led leds[];
};

static int winwing_led_write(struct led_classdev *cdev,
		enum led_brightness br)
{
	struct winwing_led *led = (struct winwing_led *) cdev;
	struct winwing_drv_data *data = hid_get_drvdata(led->hdev);
	__u8 *buf = data->report_lights;
	int ret;

	mutex_lock(&data->lights_lock);

	/*
	 * Mimicking requests captured by usbmon when LEDs
	 * are controlled by the vendor's app in a VM.
	 */
	buf[0] = 0x02;
	buf[1] = 0x60;
	buf[2] = 0xbe;
	buf[3] = 0x00;
	buf[4] = 0x00;
	buf[5] = 0x03;
	buf[6] = 0x49;
	buf[7] = led->number;
	buf[8] = br;
	buf[9] = 0x00;
	buf[10] = 0;
	buf[11] = 0;
	buf[12] = 0;
	buf[13] = 0;

	ret = hid_hw_output_report(led->hdev, buf, 14);

	mutex_unlock(&data->lights_lock);

	return ret;
}

static int winwing_init_led(struct hid_device *hdev,
		struct input_dev *input)
{
	struct winwing_drv_data *data;
	struct winwing_led *led;
	int ret;
	int i;

	data = hid_get_drvdata(hdev);

	if (!data)
		return -EINVAL;

	data->report_lights = devm_kzalloc(&hdev->dev, MAX_REPORT, GFP_KERNEL);

	if (!data->report_lights)
		return -ENOMEM;

	for (i = 0; i < 3; i += 1) {
		const struct winwing_led_info *info = &led_info[i];

		led = &data->leds[i];
		led->hdev = hdev;

Annotation

Implementation Notes