Home | History | Annotate | Download | only in input
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel (at) 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 
    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 
    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 
    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 
    333 static gboolean fake_hid_common_connect(struct fake_input *fake, GError **err)
    334 {
    335 	return TRUE;
    336 }
    337 
    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 
    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 
    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 
    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