• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34 
35 #include <bluetooth/bluetooth.h>
36 #include <bluetooth/hidp.h>
37 #include <bluetooth/sdp.h>
38 
39 #include <glib.h>
40 #include <dbus/dbus.h>
41 
42 #include "../src/adapter.h"
43 #include "../src/device.h"
44 
45 #include "log.h"
46 #include "device.h"
47 #include "fakehid.h"
48 #include "uinput.h"
49 
50 #define PS3_FLAGS_MASK 0xFFFFFF00
51 
52 enum ps3remote_special_keys {
53 	PS3R_BIT_PS = 0,
54 	PS3R_BIT_ENTER = 3,
55 	PS3R_BIT_L2 = 8,
56 	PS3R_BIT_R2 = 9,
57 	PS3R_BIT_L1 = 10,
58 	PS3R_BIT_R1 = 11,
59 	PS3R_BIT_TRIANGLE = 12,
60 	PS3R_BIT_CIRCLE = 13,
61 	PS3R_BIT_CROSS = 14,
62 	PS3R_BIT_SQUARE = 15,
63 	PS3R_BIT_SELECT = 16,
64 	PS3R_BIT_L3 = 17,
65 	PS3R_BIT_R3 = 18,
66 	PS3R_BIT_START = 19,
67 	PS3R_BIT_UP = 20,
68 	PS3R_BIT_RIGHT = 21,
69 	PS3R_BIT_DOWN = 22,
70 	PS3R_BIT_LEFT = 23,
71 };
72 
73 static unsigned int ps3remote_bits[] = {
74 	[PS3R_BIT_ENTER] = 0x0b,
75 	[PS3R_BIT_PS] = 0x43,
76 	[PS3R_BIT_SQUARE] = 0x5f,
77 	[PS3R_BIT_CROSS] = 0x5e,
78 	[PS3R_BIT_CIRCLE] = 0x5d,
79 	[PS3R_BIT_TRIANGLE] = 0x5c,
80 	[PS3R_BIT_R1] = 0x5b,
81 	[PS3R_BIT_L1] = 0x5a,
82 	[PS3R_BIT_R2] = 0x59,
83 	[PS3R_BIT_L2] = 0x58,
84 	[PS3R_BIT_LEFT] = 0x57,
85 	[PS3R_BIT_DOWN] = 0x56,
86 	[PS3R_BIT_RIGHT] = 0x55,
87 	[PS3R_BIT_UP] = 0x54,
88 	[PS3R_BIT_START] = 0x53,
89 	[PS3R_BIT_R3] = 0x52,
90 	[PS3R_BIT_L3] = 0x51,
91 	[PS3R_BIT_SELECT] = 0x50,
92 };
93 
94 static unsigned int ps3remote_keymap[] = {
95 	[0x16] = KEY_EJECTCD,
96 	[0x64] = KEY_AUDIO,
97 	[0x65] = KEY_ANGLE,
98 	[0x63] = KEY_SUBTITLE,
99 	[0x0f] = KEY_CLEAR,
100 	[0x28] = KEY_TIME,
101 	[0x00] = KEY_1,
102 	[0x01] = KEY_2,
103 	[0x02] = KEY_3,
104 	[0x03] = KEY_4,
105 	[0x04] = KEY_5,
106 	[0x05] = KEY_6,
107 	[0x06] = KEY_7,
108 	[0x07] = KEY_8,
109 	[0x08] = KEY_9,
110 	[0x09] = KEY_0,
111 	[0x81] = KEY_RED,
112 	[0x82] = KEY_GREEN,
113 	[0x80] = KEY_BLUE,
114 	[0x83] = KEY_YELLOW,
115 	[0x70] = KEY_INFO,		/* display */
116 	[0x1a] = KEY_MENU,		/* top menu */
117 	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */
118 	[0x0e] = KEY_ESC,		/* return */
119 	[0x5c] = KEY_OPTION,		/* options/triangle */
120 	[0x5d] = KEY_BACK,		/* back/circle */
121 	[0x5f] = KEY_SCREEN,		/* view/square */
122 	[0x5e] = BTN_0,			/* cross */
123 	[0x54] = KEY_UP,
124 	[0x56] = KEY_DOWN,
125 	[0x57] = KEY_LEFT,
126 	[0x55] = KEY_RIGHT,
127 	[0x0b] = KEY_ENTER,
128 	[0x5a] = BTN_TL,		/* L1 */
129 	[0x58] = BTN_TL2,		/* L2 */
130 	[0x51] = BTN_THUMBL,		/* L3 */
131 	[0x5b] = BTN_TR,		/* R1 */
132 	[0x59] = BTN_TR2,		/* R2 */
133 	[0x52] = BTN_THUMBR,		/* R3 */
134 	[0x43] = KEY_HOMEPAGE,		/* PS button */
135 	[0x50] = KEY_SELECT,
136 	[0x53] = BTN_START,
137 	[0x33] = KEY_REWIND,		/* scan back */
138 	[0x32] = KEY_PLAY,
139 	[0x34] = KEY_FORWARD,		/* scan forward */
140 	[0x30] = KEY_PREVIOUS,
141 	[0x38] = KEY_STOP,
142 	[0x31] = KEY_NEXT,
143 	[0x60] = KEY_FRAMEBACK,		/* slow/step back */
144 	[0x39] = KEY_PAUSE,
145 	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */
146 	[0xff] = KEY_MAX,
147 };
148 
ps3remote_decode(char * buff,int size,unsigned int * value)149 static int ps3remote_decode(char *buff, int size, unsigned int *value)
150 {
151 	static unsigned int lastkey = 0;
152 	static unsigned int lastmask = 0;
153 	unsigned int i, mask;
154 	int retval;
155 	guint8 key;
156 
157 	if (size < 12) {
158 		error("Got a shorter packet! (size %i)\n", size);
159 		return KEY_RESERVED;
160 	}
161 
162 	mask = (buff[2] << 16) + (buff[3] << 8) + buff[4];
163 	key = buff[5];
164 
165 	/* first, check flags */
166 	for (i = 0; i < 24; i++) {
167 		if ((lastmask & (1 << i)) == (mask & (1 << i)))
168 			continue;
169 		if (ps3remote_bits[i] == 0)
170 			goto error;
171 		retval = ps3remote_keymap[ps3remote_bits[i]];
172 		if (mask & (1 << i))
173 			/* key pressed */
174 			*value = 1;
175 		else
176 			/* key released */
177 			*value = 0;
178 
179 		goto out;
180 	}
181 
182 	*value = buff[11];
183 	if (buff[11] == 1) {
184 		retval = ps3remote_keymap[key];
185 	} else
186 		retval = lastkey;
187 
188 	if (retval == KEY_RESERVED)
189 		goto error;
190 	if (retval == KEY_MAX)
191 		return retval;
192 
193 	lastkey = retval;
194 
195 out:
196 	fflush(stdout);
197 
198 	lastmask = mask;
199 
200 	return retval;
201 
202 error:
203 	error("ps3remote: unrecognized sequence [%#x][%#x][%#x][%#x] [%#x],"
204 			"last: [%#x][%#x][%#x][%#x]",
205 			buff[2], buff[3], buff[4], buff[5], buff[11],
206 				lastmask >> 16, lastmask >> 8 & 0xff,
207 						lastmask & 0xff, lastkey);
208 	return -1;
209 }
210 
ps3remote_event(GIOChannel * chan,GIOCondition cond,gpointer data)211 static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond,
212 				gpointer data)
213 {
214 	struct fake_input *fake = data;
215 	struct uinput_event event;
216 	unsigned int key, value = 0;
217 	ssize_t size;
218 	char buff[50];
219 	int fd;
220 
221 	if (cond & G_IO_NVAL)
222 		return FALSE;
223 
224 	if (cond & (G_IO_HUP | G_IO_ERR)) {
225 		error("Hangup or error on rfcomm server socket");
226 		goto failed;
227 	}
228 
229 	fd = g_io_channel_unix_get_fd(chan);
230 
231 	memset(buff, 0, sizeof(buff));
232 	size = read(fd, buff, sizeof(buff));
233 	if (size < 0) {
234 		error("IO Channel read error");
235 		goto failed;
236 	}
237 
238 	key = ps3remote_decode(buff, size, &value);
239 	if (key == KEY_RESERVED) {
240 		error("Got invalid key from decode");
241 		goto failed;
242 	} else if (key == KEY_MAX)
243 		return TRUE;
244 
245 	memset(&event, 0, sizeof(event));
246 	gettimeofday(&event.time, NULL);
247 	event.type = EV_KEY;
248 	event.code = key;
249 	event.value = value;
250 	if (write(fake->uinput, &event, sizeof(event)) != sizeof(event)) {
251 		error("Error writing to uinput device");
252 		goto failed;
253 	}
254 
255 	memset(&event, 0, sizeof(event));
256 	gettimeofday(&event.time, NULL);
257 	event.type = EV_SYN;
258 	event.code = SYN_REPORT;
259 	if (write(fake->uinput, &event, sizeof(event)) != sizeof(event)) {
260 		error("Error writing to uinput device");
261 		goto failed;
262 	}
263 
264 	return TRUE;
265 
266 failed:
267 	ioctl(fake->uinput, UI_DEV_DESTROY);
268 	close(fake->uinput);
269 	fake->uinput = -1;
270 	g_io_channel_unref(fake->io);
271 
272 	return FALSE;
273 }
274 
ps3remote_setup_uinput(struct fake_input * fake,struct fake_hid * fake_hid)275 static int ps3remote_setup_uinput(struct fake_input *fake,
276 						struct fake_hid *fake_hid)
277 {
278 	struct uinput_dev dev;
279 	int i;
280 
281 	fake->uinput = open("/dev/input/uinput", O_RDWR);
282 	if (fake->uinput < 0) {
283 		fake->uinput = open("/dev/uinput", O_RDWR);
284 		if (fake->uinput < 0) {
285 			fake->uinput = open("/dev/misc/uinput", O_RDWR);
286 			if (fake->uinput < 0) {
287 				error("Error opening uinput device file");
288 				return 1;
289 			}
290 		}
291 	}
292 
293 	memset(&dev, 0, sizeof(dev));
294 	snprintf(dev.name, sizeof(dev.name), "%s", "PS3 Remote Controller");
295 	dev.id.bustype = BUS_BLUETOOTH;
296 	dev.id.vendor = fake_hid->vendor;
297 	dev.id.product = fake_hid->product;
298 
299 	if (write(fake->uinput, &dev, sizeof(dev)) != sizeof(dev)) {
300 		error("Error creating uinput device");
301 		goto err;
302 	}
303 
304 	/* enabling key events */
305 	if (ioctl(fake->uinput, UI_SET_EVBIT, EV_KEY) < 0) {
306 		error("Error enabling uinput device key events");
307 		goto err;
308 	}
309 
310 	/* enabling keys */
311 	for (i = 0; i < 256; i++)
312 		if (ps3remote_keymap[i] != KEY_RESERVED)
313 			if (ioctl(fake->uinput, UI_SET_KEYBIT,
314 						ps3remote_keymap[i]) < 0) {
315 				error("Error enabling uinput key %i",
316 							ps3remote_keymap[i]);
317 				goto err;
318 			}
319 
320 	/* creating the device */
321 	if (ioctl(fake->uinput, UI_DEV_CREATE) < 0) {
322 		error("Error creating uinput device");
323 		goto err;
324 	}
325 
326 	return 0;
327 
328 err:
329 	close(fake->uinput);
330 	return 1;
331 }
332 
fake_hid_common_connect(struct fake_input * fake,GError ** err)333 static gboolean fake_hid_common_connect(struct fake_input *fake, GError **err)
334 {
335 	return TRUE;
336 }
337 
fake_hid_common_disconnect(struct fake_input * fake)338 static int fake_hid_common_disconnect(struct fake_input *fake)
339 {
340 	return 0;
341 }
342 
343 static struct fake_hid fake_hid_table[] = {
344 	/* Sony PS3 remote device */
345 	{
346 		.vendor		= 0x054c,
347 		.product	= 0x0306,
348 		.connect	= fake_hid_common_connect,
349 		.disconnect	= fake_hid_common_disconnect,
350 		.event		= ps3remote_event,
351 		.setup_uinput	= ps3remote_setup_uinput,
352 		.devices	= NULL,
353 	},
354 
355 	{ },
356 };
357 
fake_hid_match_device(uint16_t vendor,uint16_t product,struct fake_hid * fhid)358 static inline int fake_hid_match_device(uint16_t vendor, uint16_t product,
359 							struct fake_hid *fhid)
360 {
361 	return vendor == fhid->vendor && product == fhid->product;
362 }
363 
get_fake_hid(uint16_t vendor,uint16_t product)364 struct fake_hid *get_fake_hid(uint16_t vendor, uint16_t product)
365 {
366 	int i;
367 
368 	for (i = 0; fake_hid_table[i].vendor != 0; i++)
369 		if (fake_hid_match_device(vendor, product, &fake_hid_table[i]))
370 			return &fake_hid_table[i];
371 
372 	return NULL;
373 }
374 
fake_hid_connadd(struct fake_input * fake,GIOChannel * intr_io,struct fake_hid * fake_hid)375 struct fake_input *fake_hid_connadd(struct fake_input *fake,
376 						GIOChannel *intr_io,
377 						struct fake_hid *fake_hid)
378 {
379 	GList *l;
380 	struct fake_input *old = NULL;
381 
382 	/* Look for an already setup device */
383 	for (l = fake_hid->devices; l != NULL; l = l->next) {
384 		old = l->data;
385 		if (old->idev == fake->idev) {
386 			g_free(fake);
387 			fake = old;
388 			fake_hid->connect(fake, NULL);
389 			break;
390 		}
391 		old = NULL;
392 	}
393 
394 	/* New device? Add it to the list of known devices,
395 	 * and create the uinput necessary */
396 	if (old == NULL) {
397 		if (fake_hid->setup_uinput(fake, fake_hid)) {
398 			error("Error setting up uinput");
399 			g_free(fake);
400 			return NULL;
401 		}
402 		fake_hid->devices = g_list_append(fake_hid->devices, fake);
403 	}
404 
405 	fake->io = g_io_channel_ref(intr_io);
406 	g_io_channel_set_close_on_unref(fake->io, TRUE);
407 	g_io_add_watch(fake->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
408 					(GIOFunc) fake_hid->event, fake);
409 
410 	return fake;
411 }
412