[PATCH] ps3 controller clone

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 098af2f8..c2bab2b 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -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);
 

[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux