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) 2007 Paul Walmsley 8bd28ce00SJiri Slaby * Copyright (c) 2008 Jiri Slaby 9cc6e0bbbSJiri Kosina * Copyright (c) 2006-2008 Jiri Kosina 10bd28ce00SJiri Slaby */ 11bd28ce00SJiri Slaby 12bd28ce00SJiri Slaby /* 13bd28ce00SJiri Slaby * This program is free software; you can redistribute it and/or modify it 14bd28ce00SJiri Slaby * under the terms of the GNU General Public License as published by the Free 15bd28ce00SJiri Slaby * Software Foundation; either version 2 of the License, or (at your option) 16bd28ce00SJiri Slaby * any later version. 17bd28ce00SJiri Slaby */ 18bd28ce00SJiri Slaby 19bd28ce00SJiri Slaby #include <linux/device.h> 20bd28ce00SJiri Slaby #include <linux/hid.h> 21bd28ce00SJiri Slaby #include <linux/module.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 23bd28ce00SJiri Slaby #include <linux/usb.h> 24bd28ce00SJiri Slaby 25bd28ce00SJiri Slaby #include "hid-ids.h" 26bd28ce00SJiri Slaby 27816651a7SAntonio Ospite #define VAIO_RDESC_CONSTANT (1 << 0) 28816651a7SAntonio Ospite #define SIXAXIS_CONTROLLER_USB (1 << 1) 29816651a7SAntonio Ospite #define SIXAXIS_CONTROLLER_BT (1 << 2) 30cc6e0bbbSJiri Kosina 31cc6e0bbbSJiri Kosina struct sony_sc { 32cc6e0bbbSJiri Kosina unsigned long quirks; 33cc6e0bbbSJiri Kosina }; 34cc6e0bbbSJiri Kosina 35cc6e0bbbSJiri Kosina /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ 36cc6e0bbbSJiri Kosina static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 37cc6e0bbbSJiri Kosina unsigned int rsize) 38cc6e0bbbSJiri Kosina { 39cc6e0bbbSJiri Kosina struct sony_sc *sc = hid_get_drvdata(hdev); 40cc6e0bbbSJiri Kosina 41cc6e0bbbSJiri Kosina if ((sc->quirks & VAIO_RDESC_CONSTANT) && 42cc6e0bbbSJiri Kosina rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { 43cc6e0bbbSJiri Kosina dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " 44cc6e0bbbSJiri Kosina "descriptor\n"); 45cc6e0bbbSJiri Kosina rdesc[55] = 0x06; 46cc6e0bbbSJiri Kosina } 47cc6e0bbbSJiri Kosina } 48cc6e0bbbSJiri Kosina 49*569b10a5SAntonio Ospite static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf, 50*569b10a5SAntonio Ospite size_t count, unsigned char report_type) 51*569b10a5SAntonio Ospite { 52*569b10a5SAntonio Ospite struct usb_interface *intf = to_usb_interface(hid->dev.parent); 53*569b10a5SAntonio Ospite struct usb_device *dev = interface_to_usbdev(intf); 54*569b10a5SAntonio Ospite struct usb_host_interface *interface = intf->cur_altsetting; 55*569b10a5SAntonio Ospite int report_id = buf[0]; 56*569b10a5SAntonio Ospite int ret; 57*569b10a5SAntonio Ospite 58*569b10a5SAntonio Ospite ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 59*569b10a5SAntonio Ospite HID_REQ_SET_REPORT, 60*569b10a5SAntonio Ospite USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 61*569b10a5SAntonio Ospite ((report_type + 1) << 8) | report_id, 62*569b10a5SAntonio Ospite interface->desc.bInterfaceNumber, buf, count, 63*569b10a5SAntonio Ospite USB_CTRL_SET_TIMEOUT); 64*569b10a5SAntonio Ospite 65*569b10a5SAntonio Ospite return ret; 66*569b10a5SAntonio Ospite } 67*569b10a5SAntonio Ospite 68bd28ce00SJiri Slaby /* 69bd28ce00SJiri Slaby * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 70bd28ce00SJiri Slaby * to "operational". Without this, the ps3 controller will not report any 71bd28ce00SJiri Slaby * events. 72bd28ce00SJiri Slaby */ 73816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev) 74bd28ce00SJiri Slaby { 75bd28ce00SJiri Slaby struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 76bd28ce00SJiri Slaby struct usb_device *dev = interface_to_usbdev(intf); 77bd28ce00SJiri Slaby __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 78bd28ce00SJiri Slaby int ret; 79bd28ce00SJiri Slaby char *buf = kmalloc(18, GFP_KERNEL); 80bd28ce00SJiri Slaby 81bd28ce00SJiri Slaby if (!buf) 82bd28ce00SJiri Slaby return -ENOMEM; 83bd28ce00SJiri Slaby 84bd28ce00SJiri Slaby ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 85bd28ce00SJiri Slaby HID_REQ_GET_REPORT, 86bd28ce00SJiri Slaby USB_DIR_IN | USB_TYPE_CLASS | 87bd28ce00SJiri Slaby USB_RECIP_INTERFACE, 88bd28ce00SJiri Slaby (3 << 8) | 0xf2, ifnum, buf, 17, 89bd28ce00SJiri Slaby USB_CTRL_GET_TIMEOUT); 90bd28ce00SJiri Slaby if (ret < 0) 91bd28ce00SJiri Slaby dev_err(&hdev->dev, "can't set operational mode\n"); 92bd28ce00SJiri Slaby 93bd28ce00SJiri Slaby kfree(buf); 94bd28ce00SJiri Slaby 95bd28ce00SJiri Slaby return ret; 96bd28ce00SJiri Slaby } 97bd28ce00SJiri Slaby 98816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev) 99f9ce7c28SBastien Nocera { 100fddb33f2SAntonio Ospite unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 101f9ce7c28SBastien Nocera return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); 102f9ce7c28SBastien Nocera } 103f9ce7c28SBastien Nocera 104bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 105bd28ce00SJiri Slaby { 106bd28ce00SJiri Slaby int ret; 107cc6e0bbbSJiri Kosina unsigned long quirks = id->driver_data; 108cc6e0bbbSJiri Kosina struct sony_sc *sc; 109cc6e0bbbSJiri Kosina 110cc6e0bbbSJiri Kosina sc = kzalloc(sizeof(*sc), GFP_KERNEL); 111cc6e0bbbSJiri Kosina if (sc == NULL) { 112eabe5c90SBastien Nocera dev_err(&hdev->dev, "can't alloc sony descriptor\n"); 113cc6e0bbbSJiri Kosina return -ENOMEM; 114cc6e0bbbSJiri Kosina } 115cc6e0bbbSJiri Kosina 116cc6e0bbbSJiri Kosina sc->quirks = quirks; 117cc6e0bbbSJiri Kosina hid_set_drvdata(hdev, sc); 118bd28ce00SJiri Slaby 119bd28ce00SJiri Slaby ret = hid_parse(hdev); 120bd28ce00SJiri Slaby if (ret) { 121bd28ce00SJiri Slaby dev_err(&hdev->dev, "parse failed\n"); 122bd28ce00SJiri Slaby goto err_free; 123bd28ce00SJiri Slaby } 124bd28ce00SJiri Slaby 12593c10132SJiri Slaby ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | 12693c10132SJiri Slaby HID_CONNECT_HIDDEV_FORCE); 127bd28ce00SJiri Slaby if (ret) { 128bd28ce00SJiri Slaby dev_err(&hdev->dev, "hw start failed\n"); 129bd28ce00SJiri Slaby goto err_free; 130bd28ce00SJiri Slaby } 131bd28ce00SJiri Slaby 132*569b10a5SAntonio Ospite if (sc->quirks & SIXAXIS_CONTROLLER_USB) { 133*569b10a5SAntonio Ospite hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; 134816651a7SAntonio Ospite ret = sixaxis_set_operational_usb(hdev); 135*569b10a5SAntonio Ospite } 136816651a7SAntonio Ospite else if (sc->quirks & SIXAXIS_CONTROLLER_BT) 137816651a7SAntonio Ospite ret = sixaxis_set_operational_bt(hdev); 138816651a7SAntonio Ospite else 139f9ce7c28SBastien Nocera ret = 0; 140f9ce7c28SBastien Nocera 1414dfdc464SJiri Kosina if (ret < 0) 142bd28ce00SJiri Slaby goto err_stop; 143bd28ce00SJiri Slaby 144bd28ce00SJiri Slaby return 0; 145bd28ce00SJiri Slaby err_stop: 146bd28ce00SJiri Slaby hid_hw_stop(hdev); 147bd28ce00SJiri Slaby err_free: 148cc6e0bbbSJiri Kosina kfree(sc); 149bd28ce00SJiri Slaby return ret; 150bd28ce00SJiri Slaby } 151bd28ce00SJiri Slaby 152cc6e0bbbSJiri Kosina static void sony_remove(struct hid_device *hdev) 153cc6e0bbbSJiri Kosina { 154cc6e0bbbSJiri Kosina hid_hw_stop(hdev); 155cc6e0bbbSJiri Kosina kfree(hid_get_drvdata(hdev)); 156cc6e0bbbSJiri Kosina } 157cc6e0bbbSJiri Kosina 158bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = { 159816651a7SAntonio Ospite { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 160816651a7SAntonio Ospite .driver_data = SIXAXIS_CONTROLLER_USB }, 161816651a7SAntonio Ospite { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), 162816651a7SAntonio Ospite .driver_data = SIXAXIS_CONTROLLER_BT }, 163cc6e0bbbSJiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), 164cc6e0bbbSJiri Kosina .driver_data = VAIO_RDESC_CONSTANT }, 165bd28ce00SJiri Slaby { } 166bd28ce00SJiri Slaby }; 167bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices); 168bd28ce00SJiri Slaby 169bd28ce00SJiri Slaby static struct hid_driver sony_driver = { 170bd28ce00SJiri Slaby .name = "sony", 171bd28ce00SJiri Slaby .id_table = sony_devices, 172bd28ce00SJiri Slaby .probe = sony_probe, 173cc6e0bbbSJiri Kosina .remove = sony_remove, 174cc6e0bbbSJiri Kosina .report_fixup = sony_report_fixup, 175bd28ce00SJiri Slaby }; 176bd28ce00SJiri Slaby 177a24f423bSPeter Huewe static int __init sony_init(void) 178bd28ce00SJiri Slaby { 179bd28ce00SJiri Slaby return hid_register_driver(&sony_driver); 180bd28ce00SJiri Slaby } 181bd28ce00SJiri Slaby 182a24f423bSPeter Huewe static void __exit sony_exit(void) 183bd28ce00SJiri Slaby { 184bd28ce00SJiri Slaby hid_unregister_driver(&sony_driver); 185bd28ce00SJiri Slaby } 186bd28ce00SJiri Slaby 187bd28ce00SJiri Slaby module_init(sony_init); 188bd28ce00SJiri Slaby module_exit(sony_exit); 189bd28ce00SJiri Slaby MODULE_LICENSE("GPL"); 190