1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/device.h>
24#include <linux/hid.h>
25#include <linux/module.h>
26
27#include "hid-ids.h"
28
29static __u8 ps3remote_rdesc[] = {
30 0x05, 0x01,
31 0x09, 0x05,
32 0xA1, 0x01,
33
34
35 0xA1, 0x02,
36
37
38
39 0x75, 0x08,
40 0x95, 0x01,
41 0x81, 0x01,
42
43
44
45 0x05, 0x09,
46 0x19, 0x01,
47 0x29, 0x18,
48 0x14,
49 0x25, 0x01,
50 0x75, 0x01,
51 0x95, 0x18,
52 0x81, 0x02,
53
54 0xC0,
55
56
57 0xA1, 0x02,
58
59
60 0x05, 0x09,
61 0x18,
62 0x29, 0xFE,
63 0x14,
64 0x26, 0xFE, 0x00,
65 0x75, 0x08,
66 0x95, 0x01,
67 0x80,
68
69
70
71 0x75, 0x08,
72 0x95, 0x06,
73 0x81, 0x01,
74
75
76 0x05, 0x06,
77 0x09, 0x20,
78 0x14,
79 0x25, 0x05,
80 0x75, 0x08,
81 0x95, 0x01,
82 0x81, 0x02,
83
84 0xC0,
85
86 0xC0
87};
88
89static const unsigned int ps3remote_keymap_joypad_buttons[] = {
90 [0x01] = KEY_SELECT,
91 [0x02] = BTN_THUMBL,
92 [0x03] = BTN_THUMBR,
93 [0x04] = BTN_START,
94 [0x05] = KEY_UP,
95 [0x06] = KEY_RIGHT,
96 [0x07] = KEY_DOWN,
97 [0x08] = KEY_LEFT,
98 [0x09] = BTN_TL2,
99 [0x0a] = BTN_TR2,
100 [0x0b] = BTN_TL,
101 [0x0c] = BTN_TR,
102 [0x0d] = KEY_OPTION,
103 [0x0e] = KEY_BACK,
104 [0x0f] = BTN_0,
105 [0x10] = KEY_SCREEN,
106 [0x11] = KEY_HOMEPAGE,
107 [0x14] = KEY_ENTER,
108};
109static const unsigned int ps3remote_keymap_remote_buttons[] = {
110 [0x00] = KEY_1,
111 [0x01] = KEY_2,
112 [0x02] = KEY_3,
113 [0x03] = KEY_4,
114 [0x04] = KEY_5,
115 [0x05] = KEY_6,
116 [0x06] = KEY_7,
117 [0x07] = KEY_8,
118 [0x08] = KEY_9,
119 [0x09] = KEY_0,
120 [0x0e] = KEY_ESC,
121 [0x0f] = KEY_CLEAR,
122 [0x16] = KEY_EJECTCD,
123 [0x1a] = KEY_MENU,
124 [0x28] = KEY_TIME,
125 [0x30] = KEY_PREVIOUS,
126 [0x31] = KEY_NEXT,
127 [0x32] = KEY_PLAY,
128 [0x33] = KEY_REWIND,
129 [0x34] = KEY_FORWARD,
130 [0x38] = KEY_STOP,
131 [0x39] = KEY_PAUSE,
132 [0x40] = KEY_CONTEXT_MENU,
133 [0x60] = KEY_FRAMEBACK,
134 [0x61] = KEY_FRAMEFORWARD,
135 [0x63] = KEY_SUBTITLE,
136 [0x64] = KEY_AUDIO,
137 [0x65] = KEY_ANGLE,
138 [0x70] = KEY_INFO,
139 [0x80] = KEY_BLUE,
140 [0x81] = KEY_RED,
141 [0x82] = KEY_GREEN,
142 [0x83] = KEY_YELLOW,
143};
144
145static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
146 unsigned int *rsize)
147{
148 *rsize = sizeof(ps3remote_rdesc);
149 return ps3remote_rdesc;
150}
151
152static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
153 struct hid_field *field, struct hid_usage *usage,
154 unsigned long **bit, int *max)
155{
156 unsigned int key = usage->hid & HID_USAGE;
157
158 if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
159 return -1;
160
161 switch (usage->collection_index) {
162 case 1:
163 if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons))
164 return -1;
165
166 key = ps3remote_keymap_joypad_buttons[key];
167 if (!key)
168 return -1;
169 break;
170 case 2:
171 if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons))
172 return -1;
173
174 key = ps3remote_keymap_remote_buttons[key];
175 if (!key)
176 return -1;
177 break;
178 default:
179 return -1;
180 }
181
182 hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
183 return 1;
184}
185
186static const struct hid_device_id ps3remote_devices[] = {
187
188 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) },
189
190 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
191 { }
192};
193MODULE_DEVICE_TABLE(hid, ps3remote_devices);
194
195static struct hid_driver ps3remote_driver = {
196 .name = "ps3_remote",
197 .id_table = ps3remote_devices,
198 .report_fixup = ps3remote_fixup,
199 .input_mapping = ps3remote_mapping,
200};
201module_hid_driver(ps3remote_driver);
202
203MODULE_LICENSE("GPL");
204MODULE_AUTHOR("David Dillow <dave@thedillows.org>, Antonio Ospite <ospite@studenti.unina.it>");
205