aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-sony.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-sony.c')
-rw-r--r--drivers/hid/hid-sony.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 402d5574b574..677bb3da10e8 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -24,24 +24,46 @@
24 24
25#include "hid-ids.h" 25#include "hid-ids.h"
26 26
27#define VAIO_RDESC_CONSTANT 0x0001 27#define VAIO_RDESC_CONSTANT (1 << 0)
28#define SIXAXIS_CONTROLLER_USB (1 << 1)
29#define SIXAXIS_CONTROLLER_BT (1 << 2)
28 30
29struct sony_sc { 31struct sony_sc {
30 unsigned long quirks; 32 unsigned long quirks;
31}; 33};
32 34
33/* Sony Vaio VGX has wrongly mouse pointer declared as constant */ 35/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
34static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 36static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
35 unsigned int rsize) 37 unsigned int *rsize)
36{ 38{
37 struct sony_sc *sc = hid_get_drvdata(hdev); 39 struct sony_sc *sc = hid_get_drvdata(hdev);
38 40
39 if ((sc->quirks & VAIO_RDESC_CONSTANT) && 41 if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
40 rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { 42 *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
41 dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " 43 dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report "
42 "descriptor\n"); 44 "descriptor\n");
43 rdesc[55] = 0x06; 45 rdesc[55] = 0x06;
44 } 46 }
47 return rdesc;
48}
49
50static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
51 size_t count, unsigned char report_type)
52{
53 struct usb_interface *intf = to_usb_interface(hid->dev.parent);
54 struct usb_device *dev = interface_to_usbdev(intf);
55 struct usb_host_interface *interface = intf->cur_altsetting;
56 int report_id = buf[0];
57 int ret;
58
59 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
60 HID_REQ_SET_REPORT,
61 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
62 ((report_type + 1) << 8) | report_id,
63 interface->desc.bInterfaceNumber, buf, count,
64 USB_CTRL_SET_TIMEOUT);
65
66 return ret;
45} 67}
46 68
47/* 69/*
@@ -49,7 +71,7 @@ static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
49 * to "operational". Without this, the ps3 controller will not report any 71 * to "operational". Without this, the ps3 controller will not report any
50 * events. 72 * events.
51 */ 73 */
52static int sony_set_operational_usb(struct hid_device *hdev) 74static int sixaxis_set_operational_usb(struct hid_device *hdev)
53{ 75{
54 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 76 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
55 struct usb_device *dev = interface_to_usbdev(intf); 77 struct usb_device *dev = interface_to_usbdev(intf);
@@ -74,7 +96,7 @@ static int sony_set_operational_usb(struct hid_device *hdev)
74 return ret; 96 return ret;
75} 97}
76 98
77static int sony_set_operational_bt(struct hid_device *hdev) 99static int sixaxis_set_operational_bt(struct hid_device *hdev)
78{ 100{
79 unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 101 unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
80 return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); 102 return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@ -108,16 +130,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
108 goto err_free; 130 goto err_free;
109 } 131 }
110 132
111 switch (hdev->bus) { 133 if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
112 case BUS_USB: 134 hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
113 ret = sony_set_operational_usb(hdev); 135 ret = sixaxis_set_operational_usb(hdev);
114 break;
115 case BUS_BLUETOOTH:
116 ret = sony_set_operational_bt(hdev);
117 break;
118 default:
119 ret = 0;
120 } 136 }
137 else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
138 ret = sixaxis_set_operational_bt(hdev);
139 else
140 ret = 0;
121 141
122 if (ret < 0) 142 if (ret < 0)
123 goto err_stop; 143 goto err_stop;
@@ -137,8 +157,10 @@ static void sony_remove(struct hid_device *hdev)
137} 157}
138 158
139static const struct hid_device_id sony_devices[] = { 159static const struct hid_device_id sony_devices[] = {
140 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, 160 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
141 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, 161 .driver_data = SIXAXIS_CONTROLLER_USB },
162 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
163 .driver_data = SIXAXIS_CONTROLLER_BT },
142 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 164 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
143 .driver_data = VAIO_RDESC_CONSTANT }, 165 .driver_data = VAIO_RDESC_CONSTANT },
144 { } 166 { }