xref: /linux/drivers/hid/hid-sony.c (revision f425458eafd51b6b5ab64f407922e1198c567cb2)
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 
36cc6e0bbbSJiri Kosina struct sony_sc {
37cc6e0bbbSJiri Kosina 	unsigned long quirks;
38cc6e0bbbSJiri Kosina };
39cc6e0bbbSJiri Kosina 
40cc6e0bbbSJiri Kosina /* Sony Vaio VGX has wrongly mouse pointer declared as constant */
4173e4008dSNikolai Kondrashov static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
4273e4008dSNikolai Kondrashov 		unsigned int *rsize)
43cc6e0bbbSJiri Kosina {
44cc6e0bbbSJiri Kosina 	struct sony_sc *sc = hid_get_drvdata(hdev);
45cc6e0bbbSJiri Kosina 
46cc6e0bbbSJiri Kosina 	if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
4773e4008dSNikolai Kondrashov 			*rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
484291ee30SJoe Perches 		hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
49cc6e0bbbSJiri Kosina 		rdesc[55] = 0x06;
50cc6e0bbbSJiri Kosina 	}
5161ab44beSSimon Wood 
5261ab44beSSimon Wood 	/* The HID descriptor exposed over BT has a trailing zero byte */
5361ab44beSSimon Wood 	if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
5461ab44beSSimon Wood 			((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
5561ab44beSSimon Wood 			rdesc[83] == 0x75) {
5661ab44beSSimon Wood 		hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
5761ab44beSSimon Wood 		memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
5861ab44beSSimon Wood 			sizeof(sixaxis_rdesc_fixup));
5961ab44beSSimon Wood 	}
6073e4008dSNikolai Kondrashov 	return rdesc;
61cc6e0bbbSJiri Kosina }
62cc6e0bbbSJiri Kosina 
63c9e4d877SSimon Wood static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
64c9e4d877SSimon Wood 		__u8 *rd, int size)
65c9e4d877SSimon Wood {
66c9e4d877SSimon Wood 	struct sony_sc *sc = hid_get_drvdata(hdev);
67c9e4d877SSimon Wood 
68c9e4d877SSimon Wood 	/* Sixaxis HID report has acclerometers/gyro with MSByte first, this
69c9e4d877SSimon Wood 	 * has to be BYTE_SWAPPED before passing up to joystick interface
70c9e4d877SSimon Wood 	 */
71c9e4d877SSimon Wood 	if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) &&
72c9e4d877SSimon Wood 			rd[0] == 0x01 && size == 49) {
73c9e4d877SSimon Wood 		swap(rd[41], rd[42]);
74c9e4d877SSimon Wood 		swap(rd[43], rd[44]);
75c9e4d877SSimon Wood 		swap(rd[45], rd[46]);
76c9e4d877SSimon Wood 		swap(rd[47], rd[48]);
77c9e4d877SSimon Wood 	}
78c9e4d877SSimon Wood 
79c9e4d877SSimon Wood 	return 0;
80c9e4d877SSimon Wood }
81c9e4d877SSimon Wood 
825710fabfSAntonio Ospite /*
835710fabfSAntonio Ospite  * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
845710fabfSAntonio Ospite  * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
855710fabfSAntonio Ospite  * so we need to override that forcing HID Output Reports on the Control EP.
865710fabfSAntonio Ospite  *
875710fabfSAntonio Ospite  * There is also another issue about HID Output Reports via USB, the Sixaxis
885710fabfSAntonio Ospite  * does not want the report_id as part of the data packet, so we have to
895710fabfSAntonio Ospite  * discard buf[0] when sending the actual control message, even for numbered
905710fabfSAntonio Ospite  * reports, humpf!
915710fabfSAntonio Ospite  */
92569b10a5SAntonio Ospite static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
93569b10a5SAntonio Ospite 		size_t count, unsigned char report_type)
94569b10a5SAntonio Ospite {
95569b10a5SAntonio Ospite 	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
96569b10a5SAntonio Ospite 	struct usb_device *dev = interface_to_usbdev(intf);
97569b10a5SAntonio Ospite 	struct usb_host_interface *interface = intf->cur_altsetting;
98569b10a5SAntonio Ospite 	int report_id = buf[0];
99569b10a5SAntonio Ospite 	int ret;
100569b10a5SAntonio Ospite 
1015710fabfSAntonio Ospite 	if (report_type == HID_OUTPUT_REPORT) {
1025710fabfSAntonio Ospite 		/* Don't send the Report ID */
1035710fabfSAntonio Ospite 		buf++;
1045710fabfSAntonio Ospite 		count--;
1055710fabfSAntonio Ospite 	}
1065710fabfSAntonio Ospite 
107569b10a5SAntonio Ospite 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
108569b10a5SAntonio Ospite 		HID_REQ_SET_REPORT,
109569b10a5SAntonio Ospite 		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
110569b10a5SAntonio Ospite 		((report_type + 1) << 8) | report_id,
111569b10a5SAntonio Ospite 		interface->desc.bInterfaceNumber, buf, count,
112569b10a5SAntonio Ospite 		USB_CTRL_SET_TIMEOUT);
113569b10a5SAntonio Ospite 
1145710fabfSAntonio Ospite 	/* Count also the Report ID, in case of an Output report. */
1155710fabfSAntonio Ospite 	if (ret > 0 && report_type == HID_OUTPUT_REPORT)
1165710fabfSAntonio Ospite 		ret++;
1175710fabfSAntonio Ospite 
118569b10a5SAntonio Ospite 	return ret;
119569b10a5SAntonio Ospite }
120569b10a5SAntonio Ospite 
121bd28ce00SJiri Slaby /*
122bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
123bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
124bd28ce00SJiri Slaby  * events.
125bd28ce00SJiri Slaby  */
126816651a7SAntonio Ospite static int sixaxis_set_operational_usb(struct hid_device *hdev)
127bd28ce00SJiri Slaby {
128bd28ce00SJiri Slaby 	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
129bd28ce00SJiri Slaby 	struct usb_device *dev = interface_to_usbdev(intf);
130bd28ce00SJiri Slaby 	__u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
131bd28ce00SJiri Slaby 	int ret;
132bd28ce00SJiri Slaby 	char *buf = kmalloc(18, GFP_KERNEL);
133bd28ce00SJiri Slaby 
134bd28ce00SJiri Slaby 	if (!buf)
135bd28ce00SJiri Slaby 		return -ENOMEM;
136bd28ce00SJiri Slaby 
137bd28ce00SJiri Slaby 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
138bd28ce00SJiri Slaby 				 HID_REQ_GET_REPORT,
139bd28ce00SJiri Slaby 				 USB_DIR_IN | USB_TYPE_CLASS |
140bd28ce00SJiri Slaby 				 USB_RECIP_INTERFACE,
141bd28ce00SJiri Slaby 				 (3 << 8) | 0xf2, ifnum, buf, 17,
142bd28ce00SJiri Slaby 				 USB_CTRL_GET_TIMEOUT);
143bd28ce00SJiri Slaby 	if (ret < 0)
1444291ee30SJoe Perches 		hid_err(hdev, "can't set operational mode\n");
145bd28ce00SJiri Slaby 
146bd28ce00SJiri Slaby 	kfree(buf);
147bd28ce00SJiri Slaby 
148bd28ce00SJiri Slaby 	return ret;
149bd28ce00SJiri Slaby }
150bd28ce00SJiri Slaby 
151816651a7SAntonio Ospite static int sixaxis_set_operational_bt(struct hid_device *hdev)
152f9ce7c28SBastien Nocera {
153fddb33f2SAntonio Ospite 	unsigned char buf[] = { 0xf4,  0x42, 0x03, 0x00, 0x00 };
154f9ce7c28SBastien Nocera 	return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
155f9ce7c28SBastien Nocera }
156f9ce7c28SBastien Nocera 
157bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
158bd28ce00SJiri Slaby {
159bd28ce00SJiri Slaby 	int ret;
160cc6e0bbbSJiri Kosina 	unsigned long quirks = id->driver_data;
161cc6e0bbbSJiri Kosina 	struct sony_sc *sc;
162cc6e0bbbSJiri Kosina 
163cc6e0bbbSJiri Kosina 	sc = kzalloc(sizeof(*sc), GFP_KERNEL);
164cc6e0bbbSJiri Kosina 	if (sc == NULL) {
1654291ee30SJoe Perches 		hid_err(hdev, "can't alloc sony descriptor\n");
166cc6e0bbbSJiri Kosina 		return -ENOMEM;
167cc6e0bbbSJiri Kosina 	}
168cc6e0bbbSJiri Kosina 
169cc6e0bbbSJiri Kosina 	sc->quirks = quirks;
170cc6e0bbbSJiri Kosina 	hid_set_drvdata(hdev, sc);
171bd28ce00SJiri Slaby 
172bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
173bd28ce00SJiri Slaby 	if (ret) {
1744291ee30SJoe Perches 		hid_err(hdev, "parse failed\n");
175bd28ce00SJiri Slaby 		goto err_free;
176bd28ce00SJiri Slaby 	}
177bd28ce00SJiri Slaby 
17893c10132SJiri Slaby 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
17993c10132SJiri Slaby 			HID_CONNECT_HIDDEV_FORCE);
180bd28ce00SJiri Slaby 	if (ret) {
1814291ee30SJoe Perches 		hid_err(hdev, "hw start failed\n");
182bd28ce00SJiri Slaby 		goto err_free;
183bd28ce00SJiri Slaby 	}
184bd28ce00SJiri Slaby 
185569b10a5SAntonio Ospite 	if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
186569b10a5SAntonio Ospite 		hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
187816651a7SAntonio Ospite 		ret = sixaxis_set_operational_usb(hdev);
188569b10a5SAntonio Ospite 	}
189816651a7SAntonio Ospite 	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
190816651a7SAntonio Ospite 		ret = sixaxis_set_operational_bt(hdev);
191816651a7SAntonio Ospite 	else
192f9ce7c28SBastien Nocera 		ret = 0;
193f9ce7c28SBastien Nocera 
1944dfdc464SJiri Kosina 	if (ret < 0)
195bd28ce00SJiri Slaby 		goto err_stop;
196bd28ce00SJiri Slaby 
197bd28ce00SJiri Slaby 	return 0;
198bd28ce00SJiri Slaby err_stop:
199bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
200bd28ce00SJiri Slaby err_free:
201cc6e0bbbSJiri Kosina 	kfree(sc);
202bd28ce00SJiri Slaby 	return ret;
203bd28ce00SJiri Slaby }
204bd28ce00SJiri Slaby 
205cc6e0bbbSJiri Kosina static void sony_remove(struct hid_device *hdev)
206cc6e0bbbSJiri Kosina {
207cc6e0bbbSJiri Kosina 	hid_hw_stop(hdev);
208cc6e0bbbSJiri Kosina 	kfree(hid_get_drvdata(hdev));
209cc6e0bbbSJiri Kosina }
210cc6e0bbbSJiri Kosina 
211bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
212816651a7SAntonio Ospite 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
213816651a7SAntonio Ospite 		.driver_data = SIXAXIS_CONTROLLER_USB },
21435dca5b4SJiri Kosina 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER),
21535dca5b4SJiri Kosina 		.driver_data = SIXAXIS_CONTROLLER_USB },
216816651a7SAntonio Ospite 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
217816651a7SAntonio Ospite 		.driver_data = SIXAXIS_CONTROLLER_BT },
218cc6e0bbbSJiri Kosina 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
219cc6e0bbbSJiri Kosina 		.driver_data = VAIO_RDESC_CONSTANT },
220bd28ce00SJiri Slaby 	{ }
221bd28ce00SJiri Slaby };
222bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
223bd28ce00SJiri Slaby 
224bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
225bd28ce00SJiri Slaby 	.name = "sony",
226bd28ce00SJiri Slaby 	.id_table = sony_devices,
227bd28ce00SJiri Slaby 	.probe = sony_probe,
228cc6e0bbbSJiri Kosina 	.remove = sony_remove,
229cc6e0bbbSJiri Kosina 	.report_fixup = sony_report_fixup,
230c9e4d877SSimon Wood 	.raw_event = sony_raw_event
231bd28ce00SJiri Slaby };
232*f425458eSH Hartley Sweeten module_hid_driver(sony_driver);
233bd28ce00SJiri Slaby 
234bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
235