1bd28ce00SJiri Slaby /* 2bd28ce00SJiri Slaby * HID driver for some sony "special" devices 3bd28ce00SJiri Slaby * 4bd28ce00SJiri Slaby * Copyright (c) 1999 Andreas Gal 5bd28ce00SJiri Slaby * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 6bd28ce00SJiri Slaby * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 7bd28ce00SJiri Slaby * Copyright (c) 2008 Jiri Slaby 8cc6e0bbbSJiri Kosina * Copyright (c) 2006-2008 Jiri Kosina 9bd28ce00SJiri Slaby */ 10bd28ce00SJiri Slaby 11bd28ce00SJiri Slaby /* 12bd28ce00SJiri Slaby * This program is free software; you can redistribute it and/or modify it 13bd28ce00SJiri Slaby * under the terms of the GNU General Public License as published by the Free 14bd28ce00SJiri Slaby * Software Foundation; either version 2 of the License, or (at your option) 15bd28ce00SJiri Slaby * any later version. 16bd28ce00SJiri Slaby */ 17bd28ce00SJiri Slaby 18bd28ce00SJiri Slaby #include <linux/device.h> 19bd28ce00SJiri Slaby #include <linux/hid.h> 20bd28ce00SJiri Slaby #include <linux/module.h> 215a0e3ad6STejun Heo #include <linux/slab.h> 22bd28ce00SJiri Slaby #include <linux/usb.h> 23bd28ce00SJiri Slaby 24bd28ce00SJiri Slaby #include "hid-ids.h" 25bd28ce00SJiri Slaby 26816651a7SAntonio Ospite #define VAIO_RDESC_CONSTANT (1 << 0) 27816651a7SAntonio Ospite #define SIXAXIS_CONTROLLER_USB (1 << 1) 28816651a7SAntonio Ospite #define SIXAXIS_CONTROLLER_BT (1 << 2) 29cc6e0bbbSJiri Kosina 3061ab44beSSimon Wood static const u8 sixaxis_rdesc_fixup[] = { 3161ab44beSSimon Wood 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, 3261ab44beSSimon Wood 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, 3361ab44beSSimon Wood 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02 3461ab44beSSimon Wood }; 3561ab44beSSimon Wood 36e57a67daSMauro Carvalho Chehab static const u8 sixaxis_rdesc_fixup2[] = { 37e57a67daSMauro Carvalho Chehab 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02, 38e57a67daSMauro Carvalho Chehab 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00, 39e57a67daSMauro Carvalho Chehab 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95, 40e57a67daSMauro Carvalho Chehab 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45, 41e57a67daSMauro Carvalho Chehab 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81, 42e57a67daSMauro Carvalho Chehab 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff, 43e57a67daSMauro Carvalho Chehab 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, 44e57a67daSMauro Carvalho Chehab 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95, 45e57a67daSMauro Carvalho Chehab 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30, 46e57a67daSMauro Carvalho Chehab 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02, 47e57a67daSMauro Carvalho Chehab 0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81, 48e57a67daSMauro Carvalho Chehab 0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95, 49e57a67daSMauro Carvalho Chehab 0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09, 50e57a67daSMauro Carvalho Chehab 0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02, 51e57a67daSMauro Carvalho Chehab 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, 52e57a67daSMauro Carvalho Chehab 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95, 53e57a67daSMauro Carvalho Chehab 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, 54e57a67daSMauro Carvalho Chehab 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 55e57a67daSMauro Carvalho Chehab 0xb1, 0x02, 0xc0, 0xc0, 56e57a67daSMauro Carvalho Chehab }; 57e57a67daSMauro Carvalho Chehab 58cc6e0bbbSJiri Kosina struct sony_sc { 59cc6e0bbbSJiri Kosina unsigned long quirks; 60cc6e0bbbSJiri Kosina }; 61cc6e0bbbSJiri Kosina 62cc6e0bbbSJiri Kosina /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ 6373e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 6473e4008dSNikolai Kondrashov unsigned int *rsize) 65cc6e0bbbSJiri Kosina { 66cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev); 67cc6e0bbbSJiri Kosina 68cc6e0bbbSJiri Kosina if ((sc->quirks & VAIO_RDESC_CONSTANT) && 6973e4008dSNikolai Kondrashov *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { 70*a4649184SFernando Luis Vázquez Cao hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n"); 71cc6e0bbbSJiri Kosina rdesc[55] = 0x06; 72cc6e0bbbSJiri Kosina } 7361ab44beSSimon Wood 7461ab44beSSimon Wood /* The HID descriptor exposed over BT has a trailing zero byte */ 7561ab44beSSimon Wood if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) || 7661ab44beSSimon Wood ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) && 7761ab44beSSimon Wood rdesc[83] == 0x75) { 7861ab44beSSimon Wood hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n"); 7961ab44beSSimon Wood memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup, 8061ab44beSSimon Wood sizeof(sixaxis_rdesc_fixup)); 81e57a67daSMauro Carvalho Chehab } else if (sc->quirks & SIXAXIS_CONTROLLER_USB && 82e57a67daSMauro Carvalho Chehab *rsize > sizeof(sixaxis_rdesc_fixup2)) { 83e57a67daSMauro Carvalho Chehab hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n", 84e57a67daSMauro Carvalho Chehab *rsize, (int)sizeof(sixaxis_rdesc_fixup2)); 85e57a67daSMauro Carvalho Chehab *rsize = sizeof(sixaxis_rdesc_fixup2); 86e57a67daSMauro Carvalho Chehab memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); 8761ab44beSSimon Wood } 8873e4008dSNikolai Kondrashov return rdesc; 89cc6e0bbbSJiri Kosina } 90cc6e0bbbSJiri Kosina 91c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, 92c9e4d877SSimon Wood __u8 *rd, int size) 93c9e4d877SSimon Wood { 94c9e4d877SSimon Wood struct sony_sc *sc = hid_get_drvdata(hdev); 95c9e4d877SSimon Wood 96c9e4d877SSimon Wood /* Sixaxis HID report has acclerometers/gyro with MSByte first, this 97c9e4d877SSimon Wood * has to be BYTE_SWAPPED before passing up to joystick interface 98c9e4d877SSimon Wood */ 99c9e4d877SSimon Wood if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) && 100c9e4d877SSimon Wood rd[0] == 0x01 && size == 49) { 101c9e4d877SSimon Wood swap(rd[41], rd[42]); 102c9e4d877SSimon Wood swap(rd[43], rd[44]); 103c9e4d877SSimon Wood swap(rd[45], rd[46]); 104c9e4d877SSimon Wood swap(rd[47], rd[48]); 105c9e4d877SSimon Wood } 106c9e4d877SSimon Wood 107c9e4d877SSimon Wood return 0; 108c9e4d877SSimon Wood } 109c9e4d877SSimon Wood 1105710fabfSAntonio Ospite /* 1115710fabfSAntonio Ospite * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP 1125710fabfSAntonio Ospite * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() 1135710fabfSAntonio Ospite * so we need to override that forcing HID Output Reports on the Control EP. 1145710fabfSAntonio Ospite * 1155710fabfSAntonio Ospite * There is also another issue about HID Output Reports via USB, the Sixaxis 1165710fabfSAntonio Ospite * does not want the report_id as part of the data packet, so we have to 1175710fabfSAntonio Ospite * discard buf[0] when sending the actual control message, even for numbered 1185710fabfSAntonio Ospite * reports, humpf! 1195710fabfSAntonio Ospite */ 120569b10a5SAntonio Ospite static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf, 121569b10a5SAntonio Ospite size_t count, unsigned char report_type) 122569b10a5SAntonio Ospite { 123569b10a5SAntonio Ospite struct usb_interface *intf = to_usb_interface(hid->dev.parent); 124569b10a5SAntonio Ospite struct usb_device *dev = interface_to_usbdev(intf); 125569b10a5SAntonio Ospite struct usb_host_interface *interface = intf->cur_altsetting; 126569b10a5SAntonio Ospite int report_id = buf[0]; 127569b10a5SAntonio Ospite int ret; 128569b10a5SAntonio Ospite 1295710fabfSAntonio Ospite if (report_type == HID_OUTPUT_REPORT) { 1305710fabfSAntonio Ospite /* Don't send the Report ID */ 1315710fabfSAntonio Ospite buf++; 1325710fabfSAntonio Ospite count--; 1335710fabfSAntonio Ospite } 1345710fabfSAntonio Ospite 135569b10a5SAntonio Ospite ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 136569b10a5SAntonio Ospite HID_REQ_SET_REPORT, 137569b10a5SAntonio Ospite USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 138569b10a5SAntonio Ospite ((report_type + 1) << 8) | report_id, 139569b10a5SAntonio Ospite interface->desc.bInterfaceNumber, buf, count, 140569b10a5SAntonio Ospite USB_CTRL_SET_TIMEOUT); 141569b10a5SAntonio Ospite 1425710fabfSAntonio Ospite /* Count also the Report ID, in case of an Output report. */ 1435710fabfSAntonio Ospite if (ret > 0 && report_type == HID_OUTPUT_REPORT) 1445710fabfSAntonio Ospite ret++; 1455710fabfSAntonio Ospite 146569b10a5SAntonio Ospite return ret; 147569b10a5SAntonio Ospite } 148569b10a5SAntonio Ospite 149bd28ce00SJiri Slaby /* 150bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 151bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any 152bd28ce00SJiri Slaby * events. 153bd28ce00SJiri Slaby */ 154816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev) 155bd28ce00SJiri Slaby { 156bd28ce00SJiri Slaby struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 157bd28ce00SJiri Slaby struct usb_device *dev = interface_to_usbdev(intf); 158bd28ce00SJiri Slaby __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 159bd28ce00SJiri Slaby int ret; 160bd28ce00SJiri Slaby char *buf = kmalloc(18, GFP_KERNEL); 161bd28ce00SJiri Slaby 162bd28ce00SJiri Slaby if (!buf) 163bd28ce00SJiri Slaby return -ENOMEM; 164bd28ce00SJiri Slaby 165bd28ce00SJiri Slaby ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 166bd28ce00SJiri Slaby HID_REQ_GET_REPORT, 167bd28ce00SJiri Slaby USB_DIR_IN | USB_TYPE_CLASS | 168bd28ce00SJiri Slaby USB_RECIP_INTERFACE, 169bd28ce00SJiri Slaby (3 << 8) | 0xf2, ifnum, buf, 17, 170bd28ce00SJiri Slaby USB_CTRL_GET_TIMEOUT); 171bd28ce00SJiri Slaby if (ret < 0) 1724291ee30SJoe Perches hid_err(hdev, "can't set operational mode\n"); 173bd28ce00SJiri Slaby 174bd28ce00SJiri Slaby kfree(buf); 175bd28ce00SJiri Slaby 176bd28ce00SJiri Slaby return ret; 177bd28ce00SJiri Slaby } 178bd28ce00SJiri Slaby 179816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev) 180f9ce7c28SBastien Nocera { 181fddb33f2SAntonio Ospite unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 182f9ce7c28SBastien Nocera return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); 183f9ce7c28SBastien Nocera } 184f9ce7c28SBastien Nocera 185bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 186bd28ce00SJiri Slaby { 187bd28ce00SJiri Slaby int ret; 188cc6e0bbbSJiri Kosina unsigned long quirks = id->driver_data; 189cc6e0bbbSJiri Kosina struct sony_sc *sc; 190cc6e0bbbSJiri Kosina 191cc6e0bbbSJiri Kosina sc = kzalloc(sizeof(*sc), GFP_KERNEL); 192cc6e0bbbSJiri Kosina if (sc == NULL) { 1934291ee30SJoe Perches hid_err(hdev, "can't alloc sony descriptor\n"); 194cc6e0bbbSJiri Kosina return -ENOMEM; 195cc6e0bbbSJiri Kosina } 196cc6e0bbbSJiri Kosina 197cc6e0bbbSJiri Kosina sc->quirks = quirks; 198cc6e0bbbSJiri Kosina hid_set_drvdata(hdev, sc); 199bd28ce00SJiri Slaby 200bd28ce00SJiri Slaby ret = hid_parse(hdev); 201bd28ce00SJiri Slaby if (ret) { 2024291ee30SJoe Perches hid_err(hdev, "parse failed\n"); 203bd28ce00SJiri Slaby goto err_free; 204bd28ce00SJiri Slaby } 205bd28ce00SJiri Slaby 20693c10132SJiri Slaby ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | 20793c10132SJiri Slaby HID_CONNECT_HIDDEV_FORCE); 208bd28ce00SJiri Slaby if (ret) { 2094291ee30SJoe Perches hid_err(hdev, "hw start failed\n"); 210bd28ce00SJiri Slaby goto err_free; 211bd28ce00SJiri Slaby } 212bd28ce00SJiri Slaby 213569b10a5SAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER_USB) { 214569b10a5SAntonio Ospite hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; 215816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev); 216569b10a5SAntonio Ospite } 217816651a7SAntonio Ospite else if (sc->quirks & SIXAXIS_CONTROLLER_BT) 218816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev); 219816651a7SAntonio Ospite else 220f9ce7c28SBastien Nocera ret = 0; 221f9ce7c28SBastien Nocera 2224dfdc464SJiri Kosina if (ret < 0) 223bd28ce00SJiri Slaby goto err_stop; 224bd28ce00SJiri Slaby 225bd28ce00SJiri Slaby return 0; 226bd28ce00SJiri Slaby err_stop: 227bd28ce00SJiri Slaby hid_hw_stop(hdev); 228bd28ce00SJiri Slaby err_free: 229cc6e0bbbSJiri Kosina kfree(sc); 230bd28ce00SJiri Slaby return ret; 231bd28ce00SJiri Slaby } 232bd28ce00SJiri Slaby 233cc6e0bbbSJiri Kosina static void sony_remove(struct hid_device *hdev) 234cc6e0bbbSJiri Kosina { 235cc6e0bbbSJiri Kosina hid_hw_stop(hdev); 236cc6e0bbbSJiri Kosina kfree(hid_get_drvdata(hdev)); 237cc6e0bbbSJiri Kosina } 238cc6e0bbbSJiri Kosina 239bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = { 240816651a7SAntonio Ospite { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 241816651a7SAntonio Ospite .driver_data = SIXAXIS_CONTROLLER_USB }, 24235dca5b4SJiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), 24335dca5b4SJiri Kosina .driver_data = SIXAXIS_CONTROLLER_USB }, 244816651a7SAntonio Ospite { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 245816651a7SAntonio Ospite .driver_data = SIXAXIS_CONTROLLER_BT }, 246cc6e0bbbSJiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 247cc6e0bbbSJiri Kosina .driver_data = VAIO_RDESC_CONSTANT }, 248*a4649184SFernando Luis Vázquez Cao { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), 249*a4649184SFernando Luis Vázquez Cao .driver_data = VAIO_RDESC_CONSTANT }, 250bd28ce00SJiri Slaby { } 251bd28ce00SJiri Slaby }; 252bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices); 253bd28ce00SJiri Slaby 254bd28ce00SJiri Slaby static struct hid_driver sony_driver = { 255bd28ce00SJiri Slaby .name = "sony", 256bd28ce00SJiri Slaby .id_table = sony_devices, 257bd28ce00SJiri Slaby .probe = sony_probe, 258cc6e0bbbSJiri Kosina .remove = sony_remove, 259cc6e0bbbSJiri Kosina .report_fixup = sony_report_fixup, 260c9e4d877SSimon Wood .raw_event = sony_raw_event 261bd28ce00SJiri Slaby }; 262bd28ce00SJiri Slaby 263a24f423bSPeter Huewe static int __init sony_init(void) 264bd28ce00SJiri Slaby { 265bd28ce00SJiri Slaby return hid_register_driver(&sony_driver); 266bd28ce00SJiri Slaby } 267bd28ce00SJiri Slaby 268a24f423bSPeter Huewe static void __exit sony_exit(void) 269bd28ce00SJiri Slaby { 270bd28ce00SJiri Slaby hid_unregister_driver(&sony_driver); 271bd28ce00SJiri Slaby } 272bd28ce00SJiri Slaby 273bd28ce00SJiri Slaby module_init(sony_init); 274bd28ce00SJiri Slaby module_exit(sony_exit); 275bd28ce00SJiri Slaby MODULE_LICENSE("GPL"); 276