From aedde65362fa811d5c17915cc1e569f5fc12e2a7 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 17 Jan 2026 12:52:30 +0100 Subject: [PATCH] Refactor media --- g29-wheel/Makefile | 14 ++ .../g29_media_usb.c => g29-wheel/g29_usb.c | 189 ++++++------------ g29_media_usb/Makefile | 28 --- 3 files changed, 76 insertions(+), 155 deletions(-) create mode 100644 g29-wheel/Makefile rename g29_media_usb/g29_media_usb.c => g29-wheel/g29_usb.c (64%) delete mode 100644 g29_media_usb/Makefile diff --git a/g29-wheel/Makefile b/g29-wheel/Makefile new file mode 100644 index 0000000..b535ba1 --- /dev/null +++ b/g29-wheel/Makefile @@ -0,0 +1,14 @@ + +.PHONY: all clean install uninstall + +obj-m += g29_usb.o +PWD := $(CURDIR) + +all: + $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + mkdir -p build + -mv -f -- *.ko *.mod.c *.o .*.o *.mod modules.order .*.cmd *.symvers build/ + +clean: + $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + rm -rf build diff --git a/g29_media_usb/g29_media_usb.c b/g29-wheel/g29_usb.c similarity index 64% rename from g29_media_usb/g29_media_usb.c rename to g29-wheel/g29_usb.c index 9775eaa..b3c2ba5 100644 --- a/g29_media_usb/g29_media_usb.c +++ b/g29-wheel/g29_usb.c @@ -21,21 +21,15 @@ #include #include #include -#include -MODULE_AUTHOR("LLP group 32"); -MODULE_DESCRIPTION("Logitech G29 -> Media keys (USB driver)"); +MODULE_AUTHOR("LLP group 16"); +MODULE_DESCRIPTION("Logitech G29 USB driver"); MODULE_LICENSE("GPL"); #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_G29 0xc24f #define USB_DEVICE_ID_LOGITECH_G29_ALT 0xc260 -#define G29_REPORT_LEN 12 - -/* - * Button masks - */ #define G29_BTN_PLUS 0x00800000u #define G29_BTN_MINUS 0x01000000u #define G29_BTN_RED_CW 0x02000000u @@ -53,19 +47,16 @@ module_param(mode, int, 0444); MODULE_PARM_DESC(mode, "Mapping mode (0=MEDIA)"); struct g29_state { - u32 buttons; - u16 rot; + u32 buttons_le; + u16 rot_le; u8 gas; u8 brk; u8 clt; - u8 grx; - u8 gry; - u8 grz; + u8 gr_x; + u8 gr_y; + u8 gr_z; }; -/* - * Mapping table entry - */ struct g29_keymap_edge { u32 mask; unsigned short keycode; @@ -94,79 +85,41 @@ struct g29_dev { struct urb *urb; u8 *buf; dma_addr_t buf_dma; + int maxp; + int interval; + int endpoint; struct g29_state last; }; -/* Parsing */ - -static bool g29_parse_report(struct g29_state *out, const u8 *data, int len) -{ - if (len < G29_REPORT_LEN) - return false; - - /* bytes 0..3 buttons bitfield */ - out->buttons = get_unaligned_le32(&data[0]); - - /* bytes 4..5 rotation */ - out->rot = get_unaligned_le16(&data[4]); - - out->gas = data[6]; - out->brk = data[7]; - out->clt = data[8]; - out->grx = data[9]; - out->gry = data[10]; - out->grz = data[11]; - - return true; -} - -/* Mapping policy */ - -static void g29_pulse_key(struct input_dev *input, unsigned short keycode) -{ - /* A pulse is a press+release within one report frame. */ - input_report_key(input, keycode, 1); - input_report_key(input, keycode, 0); -} - -static void g29_apply_media_mode(struct g29_dev *g29, - const struct g29_state *prev, - const struct g29_state *cur) -{ - u32 pressed = cur->buttons & ~prev->buttons; - size_t i; - - for (i = 0; i < ARRAY_SIZE(g29_media_edge_map); i++) { +static void g29_apply_media_mode(struct g29_dev *g29, const struct g29_state *cur, const struct g29_state *prev) { + u32 pressed = le32_to_cpu(cur->buttons_le & ~prev->buttons_le); + for (int i = 0; i < ARRAY_SIZE(g29_media_edge_map); i++) { const struct g29_keymap_edge *e = &g29_media_edge_map[i]; - if (pressed & e->mask) - g29_pulse_key(g29->input, e->keycode); + if (pressed & e->mask) { + input_report_key(g29->input, e->keycode, 1); + input_report_key(g29->input, e->keycode, 0); + } } input_sync(g29->input); } -static void g29_process_report(struct g29_dev *g29, const u8 *data, int len) -{ - struct g29_state cur; - - if (!g29_parse_report(&cur, data, len)) - return; +static void g29_process_report(struct g29_dev *g29, const u8 *data, unsigned int len) { + if (len < 12) return; + struct g29_state *cur = (void *) data; switch (mode) { case G29_MODE_MEDIA: default: - g29_apply_media_mode(g29, &g29->last, &cur); + g29_apply_media_mode(g29, cur, &g29->last); break; } - g29->last = cur; + g29->last = *cur; } -/* URB plumbing */ - -static void g29_urb_complete(struct urb *urb) -{ +static void g29_urb_complete(struct urb *urb) { struct g29_dev *g29 = urb->context; int ret; @@ -189,8 +142,7 @@ resubmit: dev_err(&g29->udev->dev, "usb_submit_urb failed: %d\n", ret); } -static int g29_input_open(struct input_dev *input) -{ +static int g29_input_open(struct input_dev *input) { struct g29_dev *g29 = input_get_drvdata(input); g29->urb->dev = g29->udev; @@ -200,68 +152,58 @@ static int g29_input_open(struct input_dev *input) return 0; } -static void g29_input_close(struct input_dev *input) -{ +static void g29_input_close(struct input_dev *input) { struct g29_dev *g29 = input_get_drvdata(input); - usb_kill_urb(g29->urb); } -/* USB driver binding */ - -static int g29_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ +static int g29_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_interface *alts = intf->cur_altsetting; - struct usb_endpoint_descriptor *ep = NULL; - struct g29_dev *g29; - struct input_dev *input; - int i, pipe, maxp, error; + int ret; /* Find an interrupt IN endpoint capable of carrying the 12-byte report. */ - for (i = 0; i < alts->desc.bNumEndpoints; i++) { - struct usb_endpoint_descriptor *cand = &alts->endpoint[i].desc; - if (!usb_endpoint_is_int_in(cand)) + struct usb_endpoint_descriptor *ep = NULL; + const struct usb_host_interface *alts = intf->cur_altsetting; + for (int i = 0; i < alts->desc.bNumEndpoints; i++) { + struct usb_endpoint_descriptor *d = &alts->endpoint[i].desc; + if (!usb_endpoint_is_int_in(d)) continue; - pipe = usb_rcvintpipe(udev, cand->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe); - if (maxp >= G29_REPORT_LEN) { - ep = cand; + if (usb_maxpacket(udev, usb_rcvintpipe(udev, d->bEndpointAddress)) >= 12) { + ep = d; break; } } + if (!ep) return -ENODEV; - if (!ep) - return -ENODEV; - - g29 = kzalloc(sizeof(*g29), GFP_KERNEL); - if (!g29) + struct g29_dev *g29; + if ((g29 = kzalloc(sizeof(*g29), GFP_KERNEL)) == NULL) { return -ENOMEM; + } - input = input_allocate_device(); - if (!input) { - error = -ENOMEM; + struct input_dev *input; + if ((input = input_allocate_device()) == NULL) { + ret = -ENOMEM; goto err_free_g29; } g29->udev = udev; g29->input = input; + + g29->endpoint = usb_endpoint_num(ep); + g29->maxp = usb_endpoint_maxp(ep); + g29->interval = ep->bInterval; memset(&g29->last, 0, sizeof(g29->last)); - /* Allocate a fixed-size report buffer (12 bytes). */ - g29->buf = usb_alloc_coherent(udev, G29_REPORT_LEN, GFP_KERNEL, &g29->buf_dma); - if (!g29->buf) { - error = -ENOMEM; + if ((g29->buf = usb_alloc_coherent(udev, g29->maxp, GFP_KERNEL, &g29->buf_dma)) == NULL) { + ret = -ENOMEM; goto err_free_input; } - g29->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!g29->urb) { - error = -ENOMEM; + if ((g29->urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) { + ret = -ENOMEM; goto err_free_buf; } - /* Build a friendly input device name. */ if (udev->manufacturer) strscpy(g29->name, udev->manufacturer, sizeof(g29->name)); if (udev->product) { @@ -271,7 +213,7 @@ static int g29_probe(struct usb_interface *intf, const struct usb_device_id *id) } if (!strlen(g29->name)) snprintf(g29->name, sizeof(g29->name), - "Logitech G29 Media %04x:%04x", + "Logitech G29 USB %04x:%04x", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); @@ -296,16 +238,15 @@ static int g29_probe(struct usb_interface *intf, const struct usb_device_id *id) input->open = g29_input_open; input->close = g29_input_close; - pipe = usb_rcvintpipe(udev, ep->bEndpointAddress); - usb_fill_int_urb(g29->urb, udev, pipe, - g29->buf, G29_REPORT_LEN, + usb_fill_int_urb(g29->urb, udev, usb_rcvintpipe(udev, ep->bEndpointAddress), + g29->buf, g29->maxp, g29_urb_complete, g29, ep->bInterval); g29->urb->transfer_dma = g29->buf_dma; g29->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - error = input_register_device(input); - if (error) + if ((ret = input_register_device(input)) != 0) { goto err_free_urb; + } usb_set_intfdata(intf, g29); @@ -318,30 +259,24 @@ static int g29_probe(struct usb_interface *intf, const struct usb_device_id *id) err_free_urb: usb_free_urb(g29->urb); err_free_buf: - usb_free_coherent(udev, G29_REPORT_LEN, g29->buf, g29->buf_dma); + usb_free_coherent(udev, g29->maxp, g29->buf, g29->buf_dma); err_free_input: input_free_device(input); err_free_g29: kfree(g29); - return error; + return ret; } -static void g29_disconnect(struct usb_interface *intf) -{ +static void g29_disconnect(struct usb_interface *intf) { struct g29_dev *g29 = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); - if (!g29) - return; - + if (!g29) return; usb_kill_urb(g29->urb); input_unregister_device(g29->input); usb_free_urb(g29->urb); - usb_free_coherent(interface_to_usbdev(intf), G29_REPORT_LEN, - g29->buf, g29->buf_dma); + usb_free_coherent(interface_to_usbdev(intf), g29->maxp, g29->buf, g29->buf_dma); kfree(g29); - - dev_info(&intf->dev, "G29 media driver disconnected\n"); + dev_info(&intf->dev, "G29 driver disconnected\n"); } static const struct usb_device_id g29_id_table[] = { @@ -352,10 +287,10 @@ static const struct usb_device_id g29_id_table[] = { MODULE_DEVICE_TABLE(usb, g29_id_table); static struct usb_driver g29_driver = { - .name = "g29_media_usb", + .name = "g29_usb", + .id_table = g29_id_table, .probe = g29_probe, .disconnect = g29_disconnect, - .id_table = g29_id_table, }; module_usb_driver(g29_driver); diff --git a/g29_media_usb/Makefile b/g29_media_usb/Makefile deleted file mode 100644 index 8cf0250..0000000 --- a/g29_media_usb/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -obj-m += g29_media_usb.o - -PWD := $(CURDIR) - -.PHONY: all clean install uninstall - -all: - $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules - mkdir -p build - mv -f *.ko build/ 2>/dev/null || true - -clean: - $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean - rm -rf build - -install: - $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules_install - depmod -a - -uninstall: - @modpath=$$(modinfo -n g29_media_usb 2>/dev/null); \ - if [ -z "$$modpath" ]; then \ - echo "Module g29_media_usb not found via modinfo (not installed?)"; \ - exit 1; \ - fi; \ - echo "Removing $$modpath"; \ - rm -f "$$modpath"; \ - depmod -a