xref: /linux/drivers/hid/hid-sony.c (revision 93c10132a7ac160df3175b53f7ee857625412165)
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) 2006-2007 Jiri Kosina
8bd28ce00SJiri Slaby  *  Copyright (c) 2007 Paul Walmsley
9bd28ce00SJiri Slaby  *  Copyright (c) 2008 Jiri Slaby
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>
22bd28ce00SJiri Slaby #include <linux/usb.h>
23bd28ce00SJiri Slaby 
24bd28ce00SJiri Slaby #include "hid-ids.h"
25bd28ce00SJiri Slaby 
26bd28ce00SJiri Slaby /*
27bd28ce00SJiri Slaby  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
28bd28ce00SJiri Slaby  * to "operational".  Without this, the ps3 controller will not report any
29bd28ce00SJiri Slaby  * events.
30bd28ce00SJiri Slaby  */
31bd28ce00SJiri Slaby static int sony_set_operational(struct hid_device *hdev)
32bd28ce00SJiri Slaby {
33bd28ce00SJiri Slaby 	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
34bd28ce00SJiri Slaby 	struct usb_device *dev = interface_to_usbdev(intf);
35bd28ce00SJiri Slaby 	__u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
36bd28ce00SJiri Slaby 	int ret;
37bd28ce00SJiri Slaby 	char *buf = kmalloc(18, GFP_KERNEL);
38bd28ce00SJiri Slaby 
39bd28ce00SJiri Slaby 	if (!buf)
40bd28ce00SJiri Slaby 		return -ENOMEM;
41bd28ce00SJiri Slaby 
42bd28ce00SJiri Slaby 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
43bd28ce00SJiri Slaby 				 HID_REQ_GET_REPORT,
44bd28ce00SJiri Slaby 				 USB_DIR_IN | USB_TYPE_CLASS |
45bd28ce00SJiri Slaby 				 USB_RECIP_INTERFACE,
46bd28ce00SJiri Slaby 				 (3 << 8) | 0xf2, ifnum, buf, 17,
47bd28ce00SJiri Slaby 				 USB_CTRL_GET_TIMEOUT);
48bd28ce00SJiri Slaby 	if (ret < 0)
49bd28ce00SJiri Slaby 		dev_err(&hdev->dev, "can't set operational mode\n");
50bd28ce00SJiri Slaby 
51bd28ce00SJiri Slaby 	kfree(buf);
52bd28ce00SJiri Slaby 
53bd28ce00SJiri Slaby 	return ret;
54bd28ce00SJiri Slaby }
55bd28ce00SJiri Slaby 
56bd28ce00SJiri Slaby static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
57bd28ce00SJiri Slaby {
58bd28ce00SJiri Slaby 	int ret;
59bd28ce00SJiri Slaby 
60bd28ce00SJiri Slaby 	ret = hid_parse(hdev);
61bd28ce00SJiri Slaby 	if (ret) {
62bd28ce00SJiri Slaby 		dev_err(&hdev->dev, "parse failed\n");
63bd28ce00SJiri Slaby 		goto err_free;
64bd28ce00SJiri Slaby 	}
65bd28ce00SJiri Slaby 
66*93c10132SJiri Slaby 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
67*93c10132SJiri Slaby 			HID_CONNECT_HIDDEV_FORCE);
68bd28ce00SJiri Slaby 	if (ret) {
69bd28ce00SJiri Slaby 		dev_err(&hdev->dev, "hw start failed\n");
70bd28ce00SJiri Slaby 		goto err_free;
71bd28ce00SJiri Slaby 	}
72bd28ce00SJiri Slaby 
73bd28ce00SJiri Slaby 	ret = sony_set_operational(hdev);
74bd28ce00SJiri Slaby 	if (ret)
75bd28ce00SJiri Slaby 		goto err_stop;
76bd28ce00SJiri Slaby 
77bd28ce00SJiri Slaby 	return 0;
78bd28ce00SJiri Slaby err_stop:
79bd28ce00SJiri Slaby 	hid_hw_stop(hdev);
80bd28ce00SJiri Slaby err_free:
81bd28ce00SJiri Slaby 	return ret;
82bd28ce00SJiri Slaby }
83bd28ce00SJiri Slaby 
84bd28ce00SJiri Slaby static const struct hid_device_id sony_devices[] = {
85bd28ce00SJiri Slaby 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
86bd28ce00SJiri Slaby 	{ }
87bd28ce00SJiri Slaby };
88bd28ce00SJiri Slaby MODULE_DEVICE_TABLE(hid, sony_devices);
89bd28ce00SJiri Slaby 
90bd28ce00SJiri Slaby static struct hid_driver sony_driver = {
91bd28ce00SJiri Slaby 	.name = "sony",
92bd28ce00SJiri Slaby 	.id_table = sony_devices,
93bd28ce00SJiri Slaby 	.probe = sony_probe,
94bd28ce00SJiri Slaby };
95bd28ce00SJiri Slaby 
96bd28ce00SJiri Slaby static int sony_init(void)
97bd28ce00SJiri Slaby {
98bd28ce00SJiri Slaby 	return hid_register_driver(&sony_driver);
99bd28ce00SJiri Slaby }
100bd28ce00SJiri Slaby 
101bd28ce00SJiri Slaby static void sony_exit(void)
102bd28ce00SJiri Slaby {
103bd28ce00SJiri Slaby 	hid_unregister_driver(&sony_driver);
104bd28ce00SJiri Slaby }
105bd28ce00SJiri Slaby 
106bd28ce00SJiri Slaby module_init(sony_init);
107bd28ce00SJiri Slaby module_exit(sony_exit);
108bd28ce00SJiri Slaby MODULE_LICENSE("GPL");
109bd28ce00SJiri Slaby 
110bd28ce00SJiri Slaby HID_COMPAT_LOAD_DRIVER(sony);
111