⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fakehid.c

📁 BlueZ源码
💻 C
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <bluetooth/bluetooth.h>#include <bluetooth/l2cap.h>#include <bluetooth/hidp.h>#include <glib.h>#include <dbus/dbus.h>#include "logging.h"#include "device.h"#include "fakehid.h"#include "uinput.h"#define PS3_FLAGS_MASK 0xFFFFFF00enum ps3remote_special_keys {	PS3R_BIT_PS = 0,	PS3R_BIT_ENTER = 3,	PS3R_BIT_L2 = 8,	PS3R_BIT_R2 = 9,	PS3R_BIT_L1 = 10,	PS3R_BIT_R1 = 11,	PS3R_BIT_TRIANGLE = 12,	PS3R_BIT_CIRCLE = 13,	PS3R_BIT_CROSS = 14,	PS3R_BIT_SQUARE = 15,	PS3R_BIT_SELECT = 16,	PS3R_BIT_L3 = 17,	PS3R_BIT_R3 = 18,	PS3R_BIT_START = 19,	PS3R_BIT_UP = 20,	PS3R_BIT_RIGHT = 21,	PS3R_BIT_DOWN = 22,	PS3R_BIT_LEFT = 23,};static unsigned int ps3remote_bits[] = {	[PS3R_BIT_ENTER] = 0x0b,	[PS3R_BIT_PS] = 0x43,	[PS3R_BIT_SQUARE] = 0x5f,	[PS3R_BIT_CROSS] = 0x5e,	[PS3R_BIT_CIRCLE] = 0x5d,	[PS3R_BIT_TRIANGLE] = 0x5c,	[PS3R_BIT_R1] = 0x5b,	[PS3R_BIT_L1] = 0x5a,	[PS3R_BIT_R2] = 0x59,	[PS3R_BIT_L2] = 0x58,	[PS3R_BIT_LEFT] = 0x57,	[PS3R_BIT_DOWN] = 0x56,	[PS3R_BIT_RIGHT] = 0x55,	[PS3R_BIT_UP] = 0x54,	[PS3R_BIT_START] = 0x53,	[PS3R_BIT_R3] = 0x52,	[PS3R_BIT_L3] = 0x51,	[PS3R_BIT_SELECT] = 0x50,};static unsigned int ps3remote_keymap[] = {	[0x16] = KEY_EJECTCD,	[0x64] = KEY_AUDIO,	[0x65] = KEY_ANGLE,	[0x63] = KEY_SUBTITLE,	[0x0f] = KEY_CLEAR,	[0x28] = KEY_TIME,	[0x00] = KEY_1,	[0x01] = KEY_2,	[0x02] = KEY_3,	[0x03] = KEY_4,	[0x04] = KEY_5,	[0x05] = KEY_6,	[0x06] = KEY_7,	[0x07] = KEY_8,	[0x08] = KEY_9,	[0x09] = KEY_0,	[0x81] = KEY_RED,	[0x82] = KEY_GREEN,	[0x80] = KEY_BLUE,	[0x83] = KEY_YELLOW,	[0x70] = KEY_INFO,		/* display */	[0x1a] = KEY_MENU,		/* top menu */	[0x40] = KEY_CONTEXT_MENU,	/* pop up/menu */	[0x0e] = KEY_ESC,		/* return */	[0x5c] = KEY_OPTION,		/* options/triangle */	[0x5d] = KEY_BACK,		/* back/circle */	[0x5f] = KEY_SCREEN,		/* view/square */	[0x5e] = BTN_0,			/* cross */	[0x54] = KEY_UP,	[0x56] = KEY_DOWN,	[0x57] = KEY_LEFT,	[0x55] = KEY_RIGHT,	[0x0b] = KEY_ENTER,	[0x5a] = BTN_TL,		/* L1 */	[0x58] = BTN_TL2,		/* L2 */	[0x51] = BTN_THUMBL,		/* L3 */	[0x5b] = BTN_TR,		/* R1 */	[0x59] = BTN_TR2,		/* R2 */	[0x52] = BTN_THUMBR,		/* R3 */	[0x43] = KEY_HOMEPAGE,		/* PS button */	[0x50] = KEY_SELECT,	[0x53] = BTN_START,	[0x33] = KEY_REWIND,		/* scan back */	[0x32] = KEY_PLAY,	[0x34] = KEY_FORWARD,		/* scan forward */	[0x30] = KEY_PREVIOUS,	[0x38] = KEY_STOP,	[0x31] = KEY_NEXT,	[0x60] = KEY_FRAMEBACK,		/* slow/step back */	[0x39] = KEY_PAUSE,	[0x61] = KEY_FRAMEFORWARD,	/* slow/step forward */	[0xff] = KEY_MAX,};static int ps3remote_decode(char *buff, int size, unsigned int *value){	static unsigned int lastkey = 0;	static unsigned int lastmask = 0;	int retval, mask, i;	guint8 key;	if (size < 12) {		error("Got a shorter packet! (size %i)\n", size);		return KEY_RESERVED;	}	mask = (buff[2] << 16) + (buff[3] << 8) + buff[4];	key = buff[5];	/* first, check flags */	for (i = 0; i < 24; i++) {		if ((lastmask & (1 << i)) == (mask & (1 << i)))			continue;		if (ps3remote_bits[i] == 0)			goto error;		retval = ps3remote_keymap[ps3remote_bits[i]];		if (mask & (1 << i))			/* key pressed */			*value = 1;		else			/* key released */			*value = 0;		goto out;	}	*value = buff[11];	if (buff[11] == 1) {		retval = ps3remote_keymap[key];	} else		retval = lastkey;	if (retval == KEY_RESERVED)		goto error;	if (retval == KEY_MAX)		return retval;	lastkey = retval;out:	fflush(stdout);	lastmask = mask;	return retval;error:	error("ps3remote: unrecognized sequence [%#x][%#x][%#x][%#x] [%#x],"			"last: [%#x][%#x][%#x][%#x]",			buff[2], buff[3], buff[4], buff[5], buff[11],				lastmask >> 16, lastmask >> 8 & 0xff,						lastmask & 0xff, lastkey);	return -1;}static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond,				gpointer data){	struct fake_input *fake = data;	struct uinput_event event;	unsigned int key, value = 0;	gsize size;	char buff[50];	if (cond & G_IO_NVAL)		return FALSE;	if (cond & (G_IO_HUP | G_IO_ERR)) {		error("Hangup or error on rfcomm server socket");		goto failed;	}	memset(buff, 0, sizeof(buff));	if (g_io_channel_read(chan, buff, sizeof(buff), &size) !=							G_IO_ERROR_NONE) {		error("IO Channel read error");		goto failed;	}	key = ps3remote_decode(buff, size, &value);	if (key == KEY_RESERVED) {		error("Got invalid key from decode");		goto failed;	} else if (key == KEY_MAX)		return TRUE;	memset(&event, 0, sizeof(event));	gettimeofday(&event.time, NULL);	event.type = EV_KEY;	event.code = key;	event.value = value;	if (write(fake->uinput, &event, sizeof(event)) != sizeof(event)) {		error("Error writing to uinput device");		goto failed;	}	memset(&event, 0, sizeof(event));	gettimeofday(&event.time, NULL);	event.type = EV_SYN;	event.code = SYN_REPORT;	if (write(fake->uinput, &event, sizeof(event)) != sizeof(event)) {		error("Error writing to uinput device");		goto failed;	}	return TRUE;failed:	ioctl(fake->uinput, UI_DEV_DESTROY);	close(fake->uinput);	fake->uinput = -1;	g_io_channel_unref(fake->io);	return FALSE;}static int ps3remote_setup_uinput(struct fake_input *fake,				  struct fake_hid *fake_hid){	struct uinput_dev dev;	int i;	fake->uinput = open("/dev/input/uinput", O_RDWR);	if (fake->uinput < 0) {		fake->uinput = open("/dev/uinput", O_RDWR);		if (fake->uinput < 0) {			fake->uinput = open("/dev/misc/uinput", O_RDWR);			if (fake->uinput < 0) {				error("Error opening uinput device file");				return 1;			}		}	}	memset(&dev, 0, sizeof(dev));	snprintf(dev.name, sizeof(dev.name), "%s", "PS3 Remote Controller");	dev.id.bustype = BUS_BLUETOOTH;	dev.id.vendor = fake_hid->vendor;	dev.id.product = fake_hid->product;	if (write(fake->uinput, &dev, sizeof(dev)) != sizeof(dev)) {		error("Error creating uinput device");		goto err;	}	/* enabling key events */	if (ioctl(fake->uinput, UI_SET_EVBIT, EV_KEY) < 0) {		error("Error enabling uinput device key events");		goto err;	}	/* enabling keys */	for (i = 0; i < 256; i++)		if (ps3remote_keymap[i] != KEY_RESERVED)			if (ioctl(fake->uinput, UI_SET_KEYBIT,						ps3remote_keymap[i]) < 0) {				error("Error enabling uinput key %i",							ps3remote_keymap[i]);				goto err;			}	/* creating the device */	if (ioctl(fake->uinput, UI_DEV_CREATE) < 0) {		error("Error creating uinput device");		goto err;	}	return 0;err:	close(fake->uinput);	return 1;}static gboolean fake_hid_common_connect(struct fake_input *fake){	return TRUE;}static int fake_hid_common_disconnect(struct fake_input *fake){	return 0;}static struct fake_hid fake_hid_table[] = {	/* Sony PS3 remote device */	{		.vendor		= 0x054c,		.product	= 0x0306,		.connect	= fake_hid_common_connect,		.disconnect	= fake_hid_common_disconnect,		.event		= ps3remote_event,		.setup_uinput	= ps3remote_setup_uinput,	},	{ },};static inline int fake_hid_match_device(uint16_t vendor, uint16_t product,							struct fake_hid *fhid){	return vendor == fhid->vendor && product == fhid->product;}struct fake_hid *get_fake_hid(uint16_t vendor, uint16_t product){	int i;	for (i = 0; fake_hid_table[i].vendor != 0; i++)		if (fake_hid_match_device(vendor, product, &fake_hid_table[i]))			return &fake_hid_table[i];	return NULL;}int fake_hid_connadd(struct fake_input *fake, int intr_sk,						struct fake_hid *fake_hid){	if (fake_hid->setup_uinput(fake, fake_hid)) {		error("Error setting up uinput");		return ENOMEM;	}	fake->io = g_io_channel_unix_new(intr_sk);	g_io_channel_set_close_on_unref(fake->io, TRUE);	g_io_add_watch(fake->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,					(GIOFunc) fake_hid->event, fake);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -