aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Pagani <dariopag45@gmail.com>2020-08-16 12:05:48 +0200
committerGitHub <noreply@github.com>2020-08-16 12:05:48 +0200
commit6c41e8fb0f5a73b1dd45685a9da5818679f8524f (patch)
treef5991273670ff706bfd40b1f41174fc589f03c52
parent16bfd88198de32bd747fcc0d2f029890994c3d8d (diff)
parentd1835027f64168b78e126944c1b84ce846084d99 (diff)
downloadhid-tminit-6c41e8fb0f5a73b1dd45685a9da5818679f8524f.tar.gz
hid-tminit-6c41e8fb0f5a73b1dd45685a9da5818679f8524f.zip
Merge pull request #1 from Kimplul/panicfix
fix for kernel panic when initializing T300RS on some setups
-rw-r--r--hid-tminit.c46
-rw-r--r--hid-tminit.h17
2 files changed, 62 insertions, 1 deletions
diff --git a/hid-tminit.c b/hid-tminit.c
index 219d78c..7adabd1 100644
--- a/hid-tminit.c
+++ b/hid-tminit.c
@@ -17,6 +17,46 @@
#include <linux/module.h>
#include "hid-tminit.h"
+/**
+ * On some setups initializing the T300RS crashes the kernel,
+ * these interrupts fix that particular issue. So far they haven't caused any
+ * adverse effects in other wheels.
+ */
+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);
+
+ if(!send_buf){
+ hid_err(hdev, "failed allocating send buffer\n");
+ return;
+ }
+
+ 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;
+ }
+ }
+
+ kzfree(send_buf);
+}
+
static void tminit_change_handler(struct urb *urb)
{
struct hid_device *hdev = urb->context;
@@ -28,6 +68,8 @@ static void tminit_change_handler(struct urb *urb)
hid_err(hdev, "URB to change wheel mode failed with error %d\n", urb->status);
}
+
+
/**
* Called by the USB subsystem when the wheel respons to our request
* to get [what it seems to be] the wheel's model.
@@ -166,10 +208,12 @@ static int tminit_probe(struct hid_device *hdev, const struct hid_device_id *id)
tm_wheel->usb_dev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
hid_set_drvdata(hdev, tm_wheel);
+ tminit_interrupts(hdev);
+
usb_fill_control_urb(
tm_wheel->urb,
tm_wheel->usb_dev,
- usb_sndctrlpipe(tm_wheel->usb_dev, 0),
+ usb_rcvctrlpipe(tm_wheel->usb_dev, 0),
(char*)tm_wheel->model_request,
tm_wheel->response,
sizeof(struct tm_wheel_response),
diff --git a/hid-tminit.h b/hid-tminit.h
index 820ca86..c8b664e 100644
--- a/hid-tminit.h
+++ b/hid-tminit.h
@@ -1,4 +1,21 @@
/**
+ * These interrupts are used to prevent a nasty crash when initializing the
+ * T300RS. Used in tminit_interrupts().
+ */
+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)
+};
+/**
* This struct contains for each type of
* Thrustmaster wheel
*