ps3 controller clone
PATCH 1/1 ps3 controller clone
Hi this is my first kernel patch.
I have a ps3 controller clone that dmesg calls "Gasia Co.,Ltd PS(R) Gamepad." When I plugged it in it was recognized but did not send any output. After some searching I found http://www.spinics.net/lists/linux-input/msg18172.html and changed my kernel according to the patch on that email which didn't fix the problem. I installed wireshark and connected the controller to Windows(VirtualBox) and came up with the solution in the attached patch.
My controller needed the additional hdev->hid_get_raw_report(hdev, 0xf5, buf, 64, HID_FEATURE_REPORT) and an interrupt set.
I tried to use the newer hdev->hid_output_raw_report rather than calling usb_interrupt_msg but I think usbhid->urbout is null in usbhid_output_raw_report since it gets sent as a SET_REPORT instead of URB_INTERRUPT out.
I did a little testing and running testrumble just after the controller is attached does initialize the controller so that the buttons send output. (Only with the additional hid_get_raw_report(hdev, 0xf5...)
I'm completely new to the kernel and have no idea how to allocate urbout. I did some searching but I'm not sure where to look.
Regards,
Andrew Haines
drivers/hid/hid-sony.c +32 -2
@@ -426,16 +426,46 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,*/ static int sixaxis_set_operational_usb (struct hid_device *hdev) { +struct usb_interface *intf =to_usb_interface (hdev->dev.parent); +struct usb_device *dev =interface_to_usbdev (intf); +//struct usbhid_device *usbhid = hdev->driver_data; int ret; -char *buf =kmalloc (18 ,GFP_KERNEL ); +int transfered; +char *buf =kmalloc (65 ,GFP_KERNEL ); +unsigned char buf2[] = { +0x01 , +0x00 ,0xff ,0x00 ,0xff ,0x00 , +0x00 ,0x00 ,0x00 ,0x00 ,0x1e ,// led flags 1e = all +0xff ,0x27 ,0x10 ,0x00 ,0x32 , +0xff ,0x27 ,0x10 ,0x00 ,0x32 , +0xff ,0x27 ,0x10 ,0x00 ,0x32 , +0xff ,0x27 ,0x10 ,0x00 ,0x32 , +0x00 ,0x00 ,0x00 ,0x00 ,0x00 + };if (!buf)return -ENOMEM ; ret = hdev->hid_get_raw_report (hdev,0xf2 , buf,17 ,HID_FEATURE_REPORT ); - +if (ret <0 )hid_err (hdev,"can't set operational mode\n" ); +else { +/* Some compatible controllers like the Speedlink Strike FX and +* Gasia need a write to the Interrupt EP to get operational */ + hdev->hid_get_raw_report (hdev,0xf5 , buf,64 ,HID_FEATURE_REPORT ); + +// doesn't work. gets sent as a SET_REPORT Request intstead of a +// URB_INTERRUPT out. I guess usbhid->urbout is null +//if ( hdev->hid_output_raw_report(hdev, buf2, sizeof(buf2), +// HID_OUTPUT_REPORT) < 0 ) +// hid_err(hdev, "can't set initial interrupt. Cloned controllers may not operate\n"); + +if (usb_interrupt_msg (dev,usb_sndintpipe (dev,0x02 ), + buf2,sizeof (buf2), + &transfered,USB_CTRL_SET_TIMEOUT )) +hid_err (hdev,"can't set initial interrupt. Cloned controllers may not operate\n" ); + }kfree (buf);