From db12c7bead4154929668badaade14db135dab6d9 Mon Sep 17 00:00:00 2001 From: kimi Date: Wed, 8 Jul 2020 11:17:48 -0400 Subject: initial commit for memory --- hid-tminit.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 hid-tminit.c (limited to 'hid-tminit.c') diff --git a/hid-tminit.c b/hid-tminit.c new file mode 100644 index 0000000..464b85c --- /dev/null +++ b/hid-tminit.c @@ -0,0 +1,75 @@ +#include "hid-tm.h" + +u8 hw_rq_in[] = { 0xc1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }; +u8 hw_rq_out[] = { 0x41, 0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static void tminit_callback(struct urb *urb){ return; } + +int tminit(struct hid_device *hdev){ + struct urb *urb; + struct device *dev = &hdev->dev; + struct usb_interface *usbif = to_usb_interface(dev->parent); + struct usb_device *usbdev = interface_to_usbdev(usbif); + + urb = usb_alloc_urb(0, GFP_ATOMIC); + + usb_fill_control_urb(urb, + usbdev, + usb_sndctrlpipe(usbdev, 0), + &hw_rq_in[0], + &hw_rq_out[0], + 0, + tminit_callback, + hdev); + + /* we sort of have to go on faith that the message is sent, because the + * wheel usually completely dies as soon as it gets the message. + */ + return usb_start_wait_urb(urb, USB_CTRL_SET_TIMEOUT, NULL); +} + +static void tminit_remove(struct hid_device *hdev){ + /* we are dead */ + hid_hw_stop(hdev); +} + +static int tminit_probe(struct hid_device *hdev, const struct hid_device_id *id){ + int ret; + + ret = hid_parse(hdev); + if(ret){ + hid_err(hdev, "parse failed\n"); + goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if(ret){ + hid_err(hdev, "hw start failed\n"); + goto err; + } + + ret = tminit(hdev); + if(ret){ + hid_err(hdev, "tminit failed, possibly as it should\n"); + goto err; + } +err: + return ret; +} + +static const struct hid_device_id tminit_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb56d)}, + {} +}; + +MODULE_DEVICE_TABLE(hid, tminit_devices); + +static struct hid_driver tminit_driver = { + .name = "thrustmaster init", + .id_table = tminit_devices, + .probe = tminit_probe, + .remove = tminit_remove, +}; +module_hid_driver(tminit_driver); + +MODULE_LICENSE("GPL"); -- cgit v1.3 From 9d17b5ed83e46122966d663b0bb05e82fb9dd01c Mon Sep 17 00:00:00 2001 From: kimi Date: Wed, 8 Jul 2020 13:38:00 -0400 Subject: added first version of generic Thrustmaster FFB device driver --- hid-tminit.c | 37 +++++++++++++++++++++++++------------ hid-tminit.h | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 hid-tminit.h (limited to 'hid-tminit.c') diff --git a/hid-tminit.c b/hid-tminit.c index 464b85c..e48b419 100644 --- a/hid-tminit.c +++ b/hid-tminit.c @@ -1,35 +1,47 @@ -#include "hid-tm.h" +#include "hid-tminit.h" -u8 hw_rq_in[] = { 0xc1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }; -u8 hw_rq_out[] = { 0x41, 0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -static void tminit_callback(struct urb *urb){ return; } +static void tminit_callback(struct urb *urb){ + ctx.status = urb->status; + hid_info(urb->dev, "urb status %d received\n", urb->status); +} int tminit(struct hid_device *hdev){ struct urb *urb; + u8 *setup_packet, *transfer_buffer; struct device *dev = &hdev->dev; struct usb_interface *usbif = to_usb_interface(dev->parent); struct usb_device *usbdev = interface_to_usbdev(usbif); + int ret; + + setup_packet = kmalloc(8, GFP_ATOMIC); + transfer_buffer = kmalloc(8, GFP_ATOMIC); + + memcpy(setup_packet, hw_rq_out, 8); + memcpy(transfer_buffer, hw_rq_in, 8); urb = usb_alloc_urb(0, GFP_ATOMIC); usb_fill_control_urb(urb, usbdev, usb_sndctrlpipe(usbdev, 0), - &hw_rq_in[0], - &hw_rq_out[0], + setup_packet, + transfer_buffer, 0, tminit_callback, hdev); /* we sort of have to go on faith that the message is sent, because the - * wheel usually completely dies as soon as it gets the message. + * wheel usually completely dies as soon as it receives the message. */ - return usb_start_wait_urb(urb, USB_CTRL_SET_TIMEOUT, NULL); + ret = usb_start_wait_urb(urb, 5, NULL); + + kfree(setup_packet); + kfree(transfer_buffer); + return ret; } static void tminit_remove(struct hid_device *hdev){ - /* we are dead */ + /* we are dead, hopefully without any serious side effects */ hid_hw_stop(hdev); } @@ -50,15 +62,16 @@ static int tminit_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = tminit(hdev); if(ret){ - hid_err(hdev, "tminit failed, possibly as it should\n"); + hid_err(hdev, "tminit exited, error might be intended behaviour\n"); goto err; } + err: return ret; } static const struct hid_device_id tminit_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb56d)}, + { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65d)}, {} }; diff --git a/hid-tminit.h b/hid-tminit.h new file mode 100644 index 0000000..cd12f9b --- /dev/null +++ b/hid-tminit.h @@ -0,0 +1,18 @@ +#include "hid-tm.h" + +u8 hw_rq_in[] = { 0xc1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }; +u8 hw_rq_out[] = { 0x41, 0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +u8 setup_0[] = { 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +u8 setup_1[] = { 0x0a, 0x04, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00 }; +u8 setup_2[] = { 0x0a, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00 }; +u8 setup_3[] = { 0x0a, 0x04, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00 }; +u8 setup_4[] = { 0x0a, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 }; +u8 *setup_arr[] = { setup_0, setup_1, setup_2, setup_3, setup_4 }; +unsigned int setup_arr_sizes[] = { + ARRAY_SIZE(setup_0), + ARRAY_SIZE(setup_1), + ARRAY_SIZE(setup_2), + ARRAY_SIZE(setup_3), + ARRAY_SIZE(setup_4) +}; -- cgit v1.3 From bec11109dd3d5792b54044e04eba044048484dba Mon Sep 17 00:00:00 2001 From: kimi Date: Thu, 9 Jul 2020 06:49:27 -0400 Subject: big changes --- Makefile | 1 + hid-tminit.c | 4 +- hid-tmt300rs.c | 385 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- hid-tmt300rs.h | 50 ++++++++ 4 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 hid-tmt300rs.h (limited to 'hid-tminit.c') diff --git a/Makefile b/Makefile index d666a97..6675c23 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ obj-m += hid-tminit.o +obj-m += hid-tmt300rs.o all: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules diff --git a/hid-tminit.c b/hid-tminit.c index e48b419..e20126b 100644 --- a/hid-tminit.c +++ b/hid-tminit.c @@ -1,5 +1,7 @@ #include "hid-tminit.h" + + static void tminit_callback(struct urb *urb){ ctx.status = urb->status; hid_info(urb->dev, "urb status %d received\n", urb->status); @@ -26,7 +28,7 @@ int tminit(struct hid_device *hdev){ usb_sndctrlpipe(usbdev, 0), setup_packet, transfer_buffer, - 0, + 8, tminit_callback, hdev); diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 3c3684c..1368a62 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1 +1,384 @@ -/* empty for now */ +#include "hid-tmt300rs.h" + +static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev){ + struct t300rs_data *drv_data; + struct t300rs_device_entry *t300rs; + + spin_lock_irqsave(&lock, lock_flags); + drv_data = hid_get_drvdata(hdev); + if(!drv_data){ + hid_err(hdev, "private data not found\n"); + return NULL; + } + + t300rs = drv_data->device_props; + if(!t300rs){ + hid_err(hdev, "device properties not found\n"); + return NULL; + } + spin_unlock_irqrestore(&lock, lock_flags); + + return t300rs; +} + +static int t300rs_send_int(struct input_dev *dev, u8 *send_buffer, int *trans){ + struct hid_device *hdev = input_get_drvdata(dev); + struct t300rs_device_entry *t300rs; + struct usb_device *usbdev; + struct usb_interface *usbif; + struct usb_host_endpoint *ep; + int b_ep; + + t300rs = t300rs_get_device(hdev); + + usbdev = t300rs->usbdev; + usbif = t300rs->usbif; + ep = &usbif->cur_altsetting->endpoint[1]; + b_ep = ep->desc.bEndpointAddress; + + return usb_interrupt_msg(usbdev, + usb_sndintpipe(usbdev, b_ep), + send_buffer, + T300RS_BUFFER_LENGTH, + trans, + USB_CTRL_SET_TIMEOUT); +} + +static int t300rs_upload(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old){ + /* temp */ + return 0; +} + +static int t300rs_play(struct input_dev *dev, int effect_id, int value){ + /* temp */ + return 0; +} + +static ssize_t t300rs_range_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count){ + struct hid_device *hdev = to_hid_device(dev); + struct t300rs_device_entry *t300rs; + u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC); + u16 range = simple_strtoul(buf, NULL, 10); + int ret, trans; + + t300rs = t300rs_get_device(hdev); + + if(range < 0x097b){ + range = 0x097b; + } + + send_buffer[0] = 0x60; + send_buffer[1] = 0x08; + send_buffer[2] = 0x11; + send_buffer[3] = range & 0xff; + send_buffer[4] = range >> 8; + + ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + return -1; + } + + t300rs->range = range; + kfree(send_buffer); + return count; +} + +static ssize_t t300rs_range_show(struct device *dev, struct device_attribute *attr, + char *buf){ + struct hid_device *hdev = to_hid_device(dev); + struct t300rs_device_entry *t300rs; + + t300rs = t300rs_get_device(hdev); + + return t300rs->range; +} + +static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, t300rs_range_show, t300rs_range_store); + +static void t300rs_set_gain(struct input_dev *dev, u16 gain){ + struct hid_device *hdev = input_get_drvdata(dev); + u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC); + int ret, trans; + + send_buffer[0] = 0x60; + send_buffer[1] = 0x02; + send_buffer[2] = SCALE_VALUE_U16(gain, sizeof(char)); + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + } +} + +static void t300rs_destroy(struct ff_device *ff){ + /* maybe not temp? */ + return; +} + + +static int t300rs_open(struct input_dev *dev){ + struct hid_device *hdev = input_get_drvdata(dev); + u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC); + int ret, trans; + + send_buffer[0] = 0x60; + send_buffer[1] = 0x01; + send_buffer[2] = 0x04; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } + memset(send_buffer, 0, T300RS_BUFFER_LENGTH); + + send_buffer[0] = 0x60; + send_buffer[1] = 0x12; + send_buffer[2] = 0xbf; + send_buffer[3] = 0x04; + send_buffer[6] = 0x03; + send_buffer[7] = 0xb7; + send_buffer[8] = 0x1e; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } + memset(send_buffer, 0, T300RS_BUFFER_LENGTH); + + send_buffer[0] = 0x60; + send_buffer[1] = 0x01; + send_buffer[2] = 0x05; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } + +err: + kfree(send_buffer); + return ret; +} + +static void t300rs_close(struct input_dev *dev){ + int ret, trans; + struct hid_device *hdev = input_get_drvdata(dev); + u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC); + + send_buffer[0] = 0x60; + send_buffer[1] = 0x01; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } +err: + kfree(send_buffer); + return; +} + +int t300rs_init(struct hid_device *hdev, const signed short *ff_bits){ + struct t300rs_device_entry *t300rs; + struct t300rs_data *drv_data; + struct list_head *report_list; + struct hid_input *hidinput = list_entry(hdev->inputs.next, + struct hid_input, list); + struct input_dev *input_dev = hidinput->input; + struct device *dev = &hdev->dev; + struct usb_interface *usbif = to_usb_interface(dev->parent); + struct usb_device *usbdev = interface_to_usbdev(usbif); + struct hid_report *report; + struct ff_device *ff; + int i, ret; + + drv_data = hid_get_drvdata(hdev); + if(!drv_data){ + hid_err(hdev, "private driver data not allocated\n"); + ret = -ENOMEM; + goto err; + } + + t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_ATOMIC); + if(!t300rs){ + return -ENOMEM; + } + + t300rs->input_dev = input_dev; + t300rs->hdev = hdev; + t300rs->usbdev = usbdev; + t300rs->usbif = usbif; + spin_lock_init(&t300rs->lock); + + drv_data->device_props = t300rs; + + + report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; + list_for_each_entry(report, report_list, list){ + int fieldnum; + + for(fieldnum = 0; fieldnum < report->maxfield; ++fieldnum){ + struct hid_field *field = report->field[fieldnum]; + + if(field->maxusage <= 0){ + continue; + } + + switch(field->usage[0].hid){ + case 0xff00000a: + if(field->report_count < 2){ + hid_warn(hdev, "ignoring FF field with report_count < 2\n"); + continue; + } + + if(field->logical_maximum == field->logical_minimum){ + hid_warn(hdev, "ignoring FF field with l_max == l_min"); + continue; + } + + if(t300rs->report && t300rs->report != report){ + hid_warn(hdev, "ignoring FF field in other report\n"); + continue; + } + + if(t300rs->ff_field && t300rs->ff_field != field){ + hid_warn(hdev, "ignoring duplicate FF field\n"); + continue; + } + + t300rs->report = report; + t300rs->ff_field = field; + + for(i = 0; ff_bits[i] >= 0; ++i){ + set_bit(ff_bits[i], input_dev->ffbit); + } + + break; + + default: + hid_warn(hdev, "ignoring unknown output usage\n"); + continue; + } + } + } + + if(!t300rs->report){ + hid_err(hdev, "can't find FF field in output reports\n"); + ret = -ENODEV; + goto err; + } + + ret = input_ff_create(input_dev, T300RS_MAX_EFFECTS); + if(ret){ + hid_err(hdev, "could not create input_ff\n"); + goto err; + } + + ff = input_dev->ff; + ff->upload = t300rs_upload; + ff->playback = t300rs_play; + ff->set_gain = t300rs_set_gain; + ff->destroy = t300rs_destroy; + + input_dev->open = t300rs_open; + input_dev->close = t300rs_close; + + ret = device_create_file(&hdev->dev, &dev_attr_range); + if(ret){ + hid_warn(hdev, "unable to create sysfs interface for range\n"); + } + + hid_info(hdev, "force feedback for T300RS\n"); + return 0; +err: + kfree(t300rs); + hid_err(hdev, "failed creating force feedback device\n"); + return ret; + +} + +static int t300rs_probe(struct hid_device *hdev, const struct hid_device_id *id){ + int ret; + struct t300rs_data *drv_data; + + spin_lock_init(&lock); + spin_lock_irqsave(&lock, lock_flags); + + drv_data = kzalloc(sizeof(struct t300rs_data), GFP_ATOMIC); + if(!drv_data){ + hid_err(hdev, "out of memory\n"); + ret = -ENOMEM; + goto err; + } + + drv_data->quirks = id->driver_data; + hid_set_drvdata(hdev, (void*)drv_data); + + ret = hid_parse(hdev); + if(ret){ + hid_err(hdev, "parse failed\n"); + goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if(ret){ + hid_err(hdev, "hw start failed\n"); + goto err; + } + + ret = t300rs_init(hdev, (void*)id->driver_data); + if(ret){ + hid_err(hdev, "t300rs_init failed\n"); + goto err; + } + + spin_unlock_irqrestore(&lock, lock_flags); + return 0; +err: + kfree(drv_data); + spin_unlock_irqrestore(&lock, lock_flags); + return ret; +} + +static void t300rs_remove(struct hid_device *hdev){ + struct t300rs_device_entry *t300rs; + struct t300rs_data *drv_data; + + device_remove_file(&hdev->dev, &dev_attr_range); + + drv_data = hid_get_drvdata(hdev); + t300rs = t300rs_get_device(hdev); + + kfree(drv_data); + kfree(t300rs); + hid_hw_stop(hdev); + return; +} + +static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize){ + rdesc = t300rs_rdesc_fixed; + *rsize = sizeof(t300rs_rdesc_fixed); + return rdesc; +} + +static const struct hid_device_id t300rs_devices[] = { + {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e), + .driver_data = (unsigned long)t300rs_ff_effects}, + {} +}; +MODULE_DEVICE_TABLE(hid, t300rs_devices); + +static struct hid_driver t300rs_driver = { + .name = "t300rs", + .id_table = t300rs_devices, + .probe = t300rs_probe, + .remove = t300rs_remove, + .report_fixup = t300rs_report_fixup, +}; +module_hid_driver(t300rs_driver); + +MODULE_LICENSE("GPL"); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h new file mode 100644 index 0000000..876f778 --- /dev/null +++ b/hid-tmt300rs.h @@ -0,0 +1,50 @@ +#include "hid-tm.h" + +#define T300RS_MAX_EFFECTS FF_MAX_EFFECTS +#define T300RS_BUFFER_LENGTH 64 + +#define CLAMP_VALUE_U16(x) ((unsigned short)((x) > 0xffff ? 0xffff : (x))) +#define SCALE_VALUE_U16(x, bits) (CLAMP_VALUE_U16(x) >> (16 - bits)) + +spinlock_t lock; +unsigned long lock_flags; + +static const signed short t300rs_ff_effects[] = { + FF_CONSTANT, + FF_RAMP, + FF_SPRING, + FF_DAMPER, + FF_FRICTION, + FF_INERTIA, + FF_PERIODIC, + FF_SINE, + FF_TRIANGLE, + FF_SQUARE, + FF_SAW_UP, + FF_SAW_DOWN, + FF_AUTOCENTER, + FF_GAIN, + -1 +}; + +struct t300rs_device_entry { + struct hid_device *hdev; + struct input_dev *input_dev; + struct hid_report *report; + struct hid_field *ff_field; + struct usb_device *usbdev; + struct usb_interface *usbif; + + spinlock_t lock; + unsigned long lock_flags; + + u16 range; +}; + +struct t300rs_data{ + unsigned long quirks; + void *device_props; +}; + +static __u8 t300rs_rdesc_fixed[] = {0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x07, 0x09, 0x30, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00, 0x75, 0x10, 0x95, 0x01, 0x81, 0x02, 0x09, 0x31, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x81, 0x02, 0x09, 0x35, 0x81, 0x02, 0x09, 0x36, 0x81, 0x02, 0x81, 0x03, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0d, 0x25, 0x01, 0x45, 0x01, 0x75, 0x01, 0x95, 0x0d, 0x81, 0x02, 0x75, 0x0b, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x39, 0x25, 0x07, 0x46, 0x3b, 0x01, 0x55, 0x00, 0x65, 0x14, 0x75, 0x04, 0x81, 0x42, 0x65, 0x00, 0x81, 0x03, 0x85, 0x0a, 0x06, 0x00, 0xff, 0x09, 0x0a, 0x75, 0x08, 0x95, 0x3f, 0x26, 0xff, 0x7f, 0x16, 0x00, 0x80, 0x46, 0xff, 0x7f, 0x36, 0x00, 0x80, 0x91, 0x02, 0x85, 0x02, 0x09, 0x02, 0x81, 0x02, 0x09, 0x14, 0x85, 0x14, 0x81, 0x02, 0xc0, 0xc0,}; + -- cgit v1.3 From 64038b9d5fcc7d76191cbf77424bb779ad88390c Mon Sep 17 00:00:00 2001 From: kimi Date: Thu, 9 Jul 2020 14:07:52 -0400 Subject: fixed weird issue that crashed the kernel --- hid-tm.h | 1 - hid-tminit.c | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) (limited to 'hid-tminit.c') diff --git a/hid-tm.h b/hid-tm.h index 17cc741..e0117ae 100644 --- a/hid-tm.h +++ b/hid-tm.h @@ -15,7 +15,6 @@ struct api_context ctx; int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { - unsigned long expire; int retval; diff --git a/hid-tminit.c b/hid-tminit.c index e20126b..9b894f5 100644 --- a/hid-tminit.c +++ b/hid-tminit.c @@ -1,12 +1,41 @@ #include "hid-tminit.h" - - static void tminit_callback(struct urb *urb){ - ctx.status = urb->status; hid_info(urb->dev, "urb status %d received\n", urb->status); } +/* for some godawful reason these interrupts are absolutely necessary, otherwise + * the whole kernel crashes. I have no idea why. + * */ +static void tminit_interrupts(struct hid_device *hdev){ + int ret, trans, i, b_ep; + u8 *send_buf = kmalloc(256, GFP_KERNEL); + + struct usb_host_endpoint *ep; + struct device *dev = &hdev->dev; + struct usb_interface *usbif = to_usb_interface(dev->parent); + struct usb_device *usbdev = interface_to_usbdev(usbif); + + ep = &usbif->cur_altsetting->endpoint[1]; + b_ep = ep->desc.bEndpointAddress; + + for(i = 0; i < ARRAY_SIZE(setup_arr); ++i){ + memcpy(send_buf, setup_arr[i], setup_arr_sizes[i]); + + ret = usb_interrupt_msg(usbdev, + usb_sndintpipe(usbdev, b_ep), + send_buf, + setup_arr_sizes[i], + &trans, + USB_CTRL_SET_TIMEOUT); + + if(ret){ + hid_err(hdev, "setup data couldn't be sent\n"); + return; + } + } +} + int tminit(struct hid_device *hdev){ struct urb *urb; u8 *setup_packet, *transfer_buffer; @@ -14,7 +43,9 @@ int tminit(struct hid_device *hdev){ struct usb_interface *usbif = to_usb_interface(dev->parent); struct usb_device *usbdev = interface_to_usbdev(usbif); int ret; - + + tminit_interrupts(hdev); + setup_packet = kmalloc(8, GFP_ATOMIC); transfer_buffer = kmalloc(8, GFP_ATOMIC); @@ -34,9 +65,9 @@ int tminit(struct hid_device *hdev){ /* we sort of have to go on faith that the message is sent, because the * wheel usually completely dies as soon as it receives the message. + * No need to even check the return value. */ - ret = usb_start_wait_urb(urb, 5, NULL); - + ret = usb_submit_urb(urb, GFP_ATOMIC); kfree(setup_packet); kfree(transfer_buffer); return ret; -- cgit v1.3