diff options
Diffstat (limited to 'drivers/hid/hid-sony.c')
| -rw-r--r-- | drivers/hid/hid-sony.c | 56 |
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 | ||
| 29 | struct sony_sc { | 31 | struct 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 */ |
| 34 | static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 36 | static __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 | |||
| 50 | static 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 | */ |
| 52 | static int sony_set_operational_usb(struct hid_device *hdev) | 74 | static 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 | ||
| 77 | static int sony_set_operational_bt(struct hid_device *hdev) | 99 | static 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 | ||
| 139 | static const struct hid_device_id sony_devices[] = { | 159 | static 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 | { } |
