commit bfe77dbe567b556b530f54f420e878bbdb8a17a5
parent bc329fef93b08a7c7e23e984fd8c36c8c0f411d9
Author: Jake Koroman <jakekoroman@proton.me>
Date: Tue, 11 Feb 2025 18:38:20 -0500
shifter.c: make device show up as a joystick to work within wine/proton.
Diffstat:
M | shifter.c | | | 247 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
1 file changed, 123 insertions(+), 124 deletions(-)
diff --git a/shifter.c b/shifter.c
@@ -3,7 +3,7 @@
#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/input.h>
-#include <linux/slab.h> // For kmalloc
+#include <linux/slab.h>
#include <linux/interrupt.h>
#define DEVICE_VENDOR_ID 0x1020
@@ -11,165 +11,164 @@
#define DEVICE_NAME "ODOR-TRUCKSHIFT"
static struct usb_device_id usb_device_table[] = {
- { USB_DEVICE(DEVICE_VENDOR_ID, DEVICE_PRODUCT_ID) },
- {}
+ { USB_DEVICE(DEVICE_VENDOR_ID, DEVICE_PRODUCT_ID) },
+ {}
};
MODULE_DEVICE_TABLE(usb, usb_device_table);
struct truckshifter {
- struct usb_device *udev;
- struct input_dev *input_device;
- unsigned char *input_buffer;
+ struct usb_device *udev;
+ struct input_dev *input_device;
+ unsigned char *input_buffer;
};
static void parse_hid_report(struct truckshifter *truckshifter, unsigned char *data) {
- // the magic byte
- unsigned char button_data = data[0];
+ unsigned char button_data = data[0];
if (button_data & 0x01) {
- input_event(truckshifter->input_device, EV_KEY, BTN_0, 1);
- } else {
- input_event(truckshifter->input_device, EV_KEY, BTN_0, 0);
- }
-
- if (button_data & 0x02) {
- input_event(truckshifter->input_device, EV_KEY, BTN_1, 1);
- } else {
- input_event(truckshifter->input_device, EV_KEY, BTN_1, 0);
- }
-
- if (button_data & 0x04) {
- input_event(truckshifter->input_device, EV_KEY, BTN_2, 1);
- } else {
- input_event(truckshifter->input_device, EV_KEY, BTN_2, 0);
- }
-
- input_sync(truckshifter->input_device);
+ input_event(truckshifter->input_device, EV_KEY, BTN_A, 1);
+ } else {
+ input_event(truckshifter->input_device, EV_KEY, BTN_A, 0);
+ }
+
+ if (button_data & 0x02) {
+ input_event(truckshifter->input_device, EV_KEY, BTN_B, 1);
+ } else {
+ input_event(truckshifter->input_device, EV_KEY, BTN_B, 0);
+ }
+
+ if (button_data & 0x04) {
+ input_event(truckshifter->input_device, EV_KEY, BTN_X, 1);
+ } else {
+ input_event(truckshifter->input_device, EV_KEY, BTN_X, 0);
+ }
+
+ input_sync(truckshifter->input_device);
}
static void read_hid_report(struct urb *urb) {
struct truckshifter *truckshifter = urb->context;
- if (urb->status) {
- printk(KERN_ERR "USB HID report error: %d\n", urb->status);
- return;
- }
+ if (urb->status) {
+ printk(KERN_ERR "USB HID report error: %d\n", urb->status);
+ return;
+ }
- parse_hid_report(truckshifter, urb->transfer_buffer);
+ parse_hid_report(truckshifter, urb->transfer_buffer);
- int retval = usb_submit_urb(urb, GFP_KERNEL);
- if (retval) {
- printk(KERN_ERR "Failed to resubmit URB\n");
- }
+ int retval = usb_submit_urb(urb, GFP_KERNEL);
+ if (retval) {
+ printk(KERN_ERR "Failed to resubmit URB\n");
+ }
}
static int start_reading_hid_report(struct truckshifter *truckshifter) {
- struct usb_interface *interface = truckshifter->udev->actconfig->interface[0];
- struct usb_endpoint_descriptor *endpoint;
- struct urb *urb;
- int pipe;
- int max_packet_size;
-
- endpoint = &interface->cur_altsetting->endpoint[0].desc;
- pipe = usb_rcvintpipe(truckshifter->udev, endpoint->bEndpointAddress);
- max_packet_size = usb_endpoint_maxp(endpoint);
-
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- printk(KERN_ERR "Failed to allocate URB\n");
- return -ENOMEM;
- }
-
- truckshifter->input_buffer = kmalloc(max_packet_size, GFP_KERNEL);
- if (!truckshifter->input_buffer) {
- printk(KERN_ERR "Failed to allocate buffer\n");
- usb_free_urb(urb);
- return -ENOMEM;
- }
-
- usb_fill_int_urb(urb, truckshifter->udev, pipe, truckshifter->input_buffer, max_packet_size,
- read_hid_report, truckshifter, endpoint->bInterval);
-
- return usb_submit_urb(urb, GFP_KERNEL);
+ struct usb_interface *interface = truckshifter->udev->actconfig->interface[0];
+ struct usb_endpoint_descriptor *endpoint;
+ struct urb *urb;
+ int pipe;
+ int max_packet_size;
+
+ endpoint = &interface->cur_altsetting->endpoint[0].desc;
+ pipe = usb_rcvintpipe(truckshifter->udev, endpoint->bEndpointAddress);
+ max_packet_size = usb_endpoint_maxp(endpoint);
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ printk(KERN_ERR "Failed to allocate URB\n");
+ return -ENOMEM;
+ }
+
+ truckshifter->input_buffer = kmalloc(max_packet_size, GFP_KERNEL);
+ if (!truckshifter->input_buffer) {
+ printk(KERN_ERR "Failed to allocate buffer\n");
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ usb_fill_int_urb(urb, truckshifter->udev, pipe, truckshifter->input_buffer, max_packet_size,
+ read_hid_report, truckshifter, endpoint->bInterval);
+
+ return usb_submit_urb(urb, GFP_KERNEL);
}
static int usb_driver_probe(struct usb_interface *interface, const struct usb_device_id *id) {
- struct truckshifter *hid_device;
- struct usb_device *dev = interface_to_usbdev(interface);
- struct input_dev *input_device;
- int retval;
-
- hid_device = kzalloc(sizeof(struct truckshifter), GFP_KERNEL);
- if (!hid_device) {
- printk(KERN_ERR "Failed to allocate memory for HID device\n");
- return -ENOMEM;
- }
-
- hid_device->udev = dev;
-
- input_device = input_allocate_device();
- if (!input_device) {
- printk(KERN_ERR "Failed to allocate input device\n");
- kfree(hid_device);
- return -ENOMEM;
- }
-
- hid_device->input_device = input_device;
-
- input_device->name = DEVICE_NAME;
- input_device->evbit[0] = BIT_MASK(EV_KEY);
- input_device->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
- input_device->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
- input_device->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
-
- retval = input_register_device(input_device);
- if (retval) {
- printk(KERN_ERR "Failed to register input device\n");
- input_free_device(input_device);
- kfree(hid_device);
- return retval;
- }
-
- retval = start_reading_hid_report(hid_device);
- if (retval) {
- printk(KERN_ERR "Failed to start reading HID report\n");
- input_unregister_device(input_device);
- kfree(hid_device);
- return retval;
- }
-
- usb_set_intfdata(interface, hid_device);
-
- printk(KERN_INFO "ODOR-Truckshift connected\n");
- return 0;
+ struct truckshifter *truckshifter;
+ struct usb_device *dev = interface_to_usbdev(interface);
+ struct input_dev *input_device;
+ int retval;
+
+ truckshifter = kzalloc(sizeof(struct truckshifter), GFP_KERNEL);
+ if (!truckshifter) {
+ printk(KERN_ERR "Failed to allocate memory for HID device\n");
+ return -ENOMEM;
+ }
+
+ truckshifter->udev = dev;
+
+ input_device = input_allocate_device();
+ if (!input_device) {
+ printk(KERN_ERR "Failed to allocate input device\n");
+ kfree(truckshifter);
+ return -ENOMEM;
+ }
+
+ truckshifter->input_device = input_device;
+
+ input_device->name = DEVICE_NAME;
+ input_device->evbit[0] = BIT_MASK(EV_KEY);
+ input_device->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A);
+ input_device->keybit[BIT_WORD(BTN_B)] |= BIT_MASK(BTN_B);
+ input_device->keybit[BIT_WORD(BTN_X)] |= BIT_MASK(BTN_X);
+
+ retval = input_register_device(input_device);
+ if (retval) {
+ printk(KERN_ERR "Failed to register "DEVICE_NAME" \n");
+ input_free_device(input_device);
+ kfree(truckshifter);
+ return retval;
+ }
+
+ retval = start_reading_hid_report(truckshifter);
+ if (retval) {
+ printk(KERN_ERR "Failed to start reading HID report\n");
+ input_unregister_device(input_device);
+ kfree(truckshifter);
+ return retval;
+ }
+
+ usb_set_intfdata(interface, truckshifter);
+
+ printk(KERN_INFO DEVICE_NAME" connected\n");
+ return 0;
}
static void usb_driver_disconnect(struct usb_interface *interface) {
- struct truckshifter *hid_device = usb_get_intfdata(interface);
+ struct truckshifter *hid_device = usb_get_intfdata(interface);
- if (hid_device) {
- if (hid_device->input_buffer)
- kfree(hid_device->input_buffer);
- input_unregister_device(hid_device->input_device);
- kfree(hid_device);
- }
+ if (hid_device) {
+ if (hid_device->input_buffer)
+ kfree(hid_device->input_buffer);
+ input_unregister_device(hid_device->input_device);
+ kfree(hid_device);
+ }
- printk(KERN_INFO "ODOR-Truckshift disconnected\n");
+ printk(KERN_INFO DEVICE_NAME" disconnected\n");
}
static struct usb_driver custom_hid_driver = {
- .name = DEVICE_NAME,
- .id_table = usb_device_table,
- .probe = usb_driver_probe,
- .disconnect = usb_driver_disconnect,
+ .name = DEVICE_NAME,
+ .id_table = usb_device_table,
+ .probe = usb_driver_probe,
+ .disconnect = usb_driver_disconnect,
};
static int __init usb_driver_init(void) {
- return usb_register(&custom_hid_driver);
+ return usb_register(&custom_hid_driver);
}
static void __exit usb_driver_exit(void) {
- usb_deregister(&custom_hid_driver);
+ usb_deregister(&custom_hid_driver);
}
module_init(usb_driver_init);