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

📄 fakehid.c

📁 实现bluez蓝牙profile需要的库
💻 C
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2003-2007  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#define _GNU_SOURCE#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <sys/poll.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/rfcomm.h>#include <bluetooth/hidp.h>#include "hidd.h"#include "uinput.h"#include <math.h>#ifdef NEED_PPOLL#include "ppoll.h"#endifstatic volatile sig_atomic_t __io_canceled = 0;static void sig_hup(int sig){}static void sig_term(int sig){	__io_canceled = 1;}static void send_event(int fd, uint16_t type, uint16_t code, int32_t value){	struct uinput_event event;	int len;	if (fd <= fileno(stderr))		return;	memset(&event, 0, sizeof(event));	event.type = type;	event.code = code;	event.value = value;	len = write(fd, &event, sizeof(event));}static int uinput_create(char *name, int keyboard, int mouse){	struct uinput_dev dev;	int fd, aux;	fd = open("/dev/uinput", O_RDWR);	if (fd < 0) {		fd = open("/dev/input/uinput", O_RDWR);		if (fd < 0) {			fd = open("/dev/misc/uinput", O_RDWR);			if (fd < 0) {				fprintf(stderr, "Can't open input device: %s (%d)\n",							strerror(errno), errno);				return -1;			}		}	}	memset(&dev, 0, sizeof(dev));	if (name)		strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);	dev.id.bustype = BUS_BLUETOOTH;	dev.id.vendor  = 0x0000;	dev.id.product = 0x0000;	dev.id.version = 0x0000;	if (write(fd, &dev, sizeof(dev)) < 0) {		fprintf(stderr, "Can't write device information: %s (%d)\n",							strerror(errno), errno);		close(fd);		return -1;	}	if (mouse) {		ioctl(fd, UI_SET_EVBIT, EV_REL);		for (aux = REL_X; aux <= REL_MISC; aux++)			ioctl(fd, UI_SET_RELBIT, aux);	}	if (keyboard) {		ioctl(fd, UI_SET_EVBIT, EV_KEY);		ioctl(fd, UI_SET_EVBIT, EV_LED);		ioctl(fd, UI_SET_EVBIT, EV_REP);		for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++)			ioctl(fd, UI_SET_KEYBIT, aux);		//for (aux = LED_NUML; aux <= LED_MISC; aux++)		//	ioctl(fd, UI_SET_LEDBIT, aux);	}	if (mouse) {		ioctl(fd, UI_SET_EVBIT, EV_KEY);		for (aux = BTN_LEFT; aux <= BTN_BACK; aux++)			ioctl(fd, UI_SET_KEYBIT, aux);	}	ioctl(fd, UI_DEV_CREATE);	return fd;}static int rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel){	struct sockaddr_rc addr;	int sk;	sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);	if (sk < 0) {		fprintf(stderr, "Can't create socket: %s (%d)\n",							strerror(errno), errno);		return -1;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, src);	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		fprintf(stderr, "Can't bind socket: %s (%d)\n",							strerror(errno), errno);		close(sk);		return -1;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, dst);	addr.rc_channel = channel;	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		fprintf(stderr, "Can't connect: %s (%d)\n",							strerror(errno), errno);		close(sk);		return -1;	}	return sk;}static void func(int fd){}static void back(int fd){}static void next(int fd){}static void button(int fd, unsigned int button, int is_press){	switch (button) {	case 1:		send_event(fd, EV_KEY, BTN_LEFT, is_press);		break;	case 3:		send_event(fd, EV_KEY, BTN_RIGHT, is_press);		break;	}	send_event(fd, EV_SYN, SYN_REPORT, 0);}static void move(int fd, unsigned int direction){	double angle;	int32_t x, y;	angle = (direction * 22.5) * 3.1415926 / 180;	x = (int) (sin(angle) * 8);	y = (int) (cos(angle) * -8);	send_event(fd, EV_REL, REL_X, x);	send_event(fd, EV_REL, REL_Y, y);	send_event(fd, EV_SYN, SYN_REPORT, 0);}static inline void epox_decode(int fd, unsigned char event){	switch (event) {	case 48:		func(fd); break;	case 55:		back(fd); break;	case 56:		next(fd); break;	case 53:		button(fd, 1, 1); break;	case 121:		button(fd, 1, 0); break;	case 113:		break;	case 54:		button(fd, 3, 1); break;	case 120:		button(fd, 3, 0); break;	case 112:		break;	case 51:		move(fd, 0); break;	case 97:		move(fd, 1); break;	case 65:		move(fd, 2); break;	case 98:		move(fd, 3); break;	case 50:		move(fd, 4); break;	case 99:		move(fd, 5); break;	case 67:		move(fd, 6); break;	case 101:		move(fd, 7); break;	case 52:		move(fd, 8); break;	case 100:		move(fd, 9); break;	case 66:		move(fd, 10); break;	case 102:		move(fd, 11); break;	case 49:		move(fd, 12); break;	case 103:		move(fd, 13); break;	case 57:		move(fd, 14); break;	case 104:		move(fd, 15); break;	case 69:		break;	default:		printf("Unknown event code %d\n", event);		break;	}}int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel){	unsigned char buf[16];	struct sigaction sa;	struct pollfd p;	sigset_t sigs;	char addr[18];	int i, fd, sk, len;	sk = rfcomm_connect(src, dst, channel);	if (sk < 0)		return -1;	fd = uinput_create("Bluetooth Presenter", 0, 1);	if (fd < 0) {		close(sk);		return -1;	}	ba2str(dst, addr);	printf("Connected to %s on channel %d\n", addr, channel);	printf("Press CTRL-C for hangup\n");	memset(&sa, 0, sizeof(sa));	sa.sa_flags   = SA_NOCLDSTOP;	sa.sa_handler = SIG_IGN;	sigaction(SIGCHLD, &sa, NULL);	sigaction(SIGPIPE, &sa, NULL);	sa.sa_handler = sig_term;	sigaction(SIGTERM, &sa, NULL);	sigaction(SIGINT,  &sa, NULL);	sa.sa_handler = sig_hup;	sigaction(SIGHUP, &sa, NULL);	sigfillset(&sigs);	sigdelset(&sigs, SIGCHLD);	sigdelset(&sigs, SIGPIPE);	sigdelset(&sigs, SIGTERM);	sigdelset(&sigs, SIGINT);	sigdelset(&sigs, SIGHUP);	p.fd = sk;	p.events = POLLIN | POLLERR | POLLHUP;	while (!__io_canceled) {		p.revents = 0;		if (ppoll(&p, 1, NULL, &sigs) < 1)			continue;		len = read(sk, buf, sizeof(buf));		if (len < 0)			break;		for (i = 0; i < len; i++)			epox_decode(fd, buf[i]);	}	printf("Disconnected\n");	ioctl(fd, UI_DEV_DESTROY);	close(fd);	close(sk);	return 0;}int headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel){	printf("Not implemented\n");	return -1;}/* The strange meta key close to Ctrl has been assigned to Esc,   Fn key to CtrlR and the left space to Alt*/static unsigned char jthree_keycodes[63] = {	KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,	KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T,	KEY_A, KEY_S, KEY_D, KEY_F, KEY_G,	KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B,	KEY_LEFTALT, KEY_TAB, KEY_CAPSLOCK, KEY_ESC,	KEY_7, KEY_8, KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE,	KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,	KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER,	KEY_N, KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_UP,	KEY_SPACE, KEY_COMPOSE, KEY_LEFT, KEY_DOWN, KEY_RIGHT,	KEY_LEFTCTRL, KEY_RIGHTSHIFT, KEY_LEFTSHIFT, KEY_DELETE, KEY_RIGHTCTRL, KEY_RIGHTALT,};static inline void jthree_decode(int fd, unsigned char event){	if (event > 63)		send_event(fd, EV_KEY, jthree_keycodes[event & 0x3f], 0);	else		send_event(fd, EV_KEY, jthree_keycodes[event - 1], 1);}int jthree_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel){	unsigned char buf[16];	struct sigaction sa;	struct pollfd p;	sigset_t sigs;	char addr[18];	int i, fd, sk, len;	sk = rfcomm_connect(src, dst, channel);	if (sk < 0)		return -1;	fd = uinput_create("J-Three Keyboard", 1, 0);	if (fd < 0) {		close(sk);		return -1;	}	ba2str(dst, addr);	printf("Connected to %s on channel %d\n", addr, channel);	printf("Press CTRL-C for hangup\n");	memset(&sa, 0, sizeof(sa));	sa.sa_flags   = SA_NOCLDSTOP;	sa.sa_handler = SIG_IGN;	sigaction(SIGCHLD, &sa, NULL);	sigaction(SIGPIPE, &sa, NULL);	sa.sa_handler = sig_term;	sigaction(SIGTERM, &sa, NULL);	sigaction(SIGINT,  &sa, NULL);	sa.sa_handler = sig_hup;	sigaction(SIGHUP, &sa, NULL);	sigfillset(&sigs);	sigdelset(&sigs, SIGCHLD);	sigdelset(&sigs, SIGPIPE);	sigdelset(&sigs, SIGTERM);	sigdelset(&sigs, SIGINT);	sigdelset(&sigs, SIGHUP);	p.fd = sk;	p.events = POLLIN | POLLERR | POLLHUP;	while (!__io_canceled) {		p.revents = 0;		if (ppoll(&p, 1, NULL, &sigs) < 1)			continue;		len = read(sk, buf, sizeof(buf));		if (len < 0)			break;		for (i = 0; i < len; i++)			jthree_decode(fd, buf[i]);	}	printf("Disconnected\n");	ioctl(fd, UI_DEV_DESTROY);	close(fd);	close(sk);	return 0;}static const int celluon_xlate_num[10] = {	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9};static const int celluon_xlate_char[26] = {	KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,	KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,	KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z};static int celluon_xlate(int c){	if (c >= '0' && c <= '9')		return celluon_xlate_num[c - '0'];	if (c >= 'A' && c <= 'Z')		return celluon_xlate_char[c - 'A'];	switch (c) {	case 0x08:		return KEY_BACKSPACE;	case 0x09:		return KEY_TAB;	case 0x0d:		return KEY_ENTER;	case 0x11:		return KEY_LEFTCTRL;	case 0x14:		return KEY_CAPSLOCK;	case 0x20:		return KEY_SPACE;	case 0x25:		return KEY_LEFT;	case 0x26:		return KEY_UP;	case 0x27:		return KEY_RIGHT;	case 0x28:		return KEY_DOWN;	case 0x2e:		return KEY_DELETE;	case 0x5b:		return KEY_MENU;	case 0xa1:		return KEY_RIGHTSHIFT;	case 0xa0:		return KEY_LEFTSHIFT;	case 0xba:		return KEY_SEMICOLON;	case 0xbd:		return KEY_MINUS;	case 0xbc:		return KEY_COMMA;	case 0xbb:		return KEY_EQUAL;	case 0xbe:		return KEY_DOT;	case 0xbf:		return KEY_SLASH;	case 0xc0:		return KEY_GRAVE;	case 0xdb:		return KEY_LEFTBRACE;	case 0xdc:		return KEY_BACKSLASH;	case 0xdd:		return KEY_RIGHTBRACE;	case 0xde:		return KEY_APOSTROPHE;	case 0xff03:		return KEY_HOMEPAGE;	case 0xff04:		return KEY_TIME;	case 0xff06:		return KEY_OPEN;	case 0xff07:		return KEY_LIST;	case 0xff08:		return KEY_MAIL;	case 0xff30:		return KEY_CALC;	case 0xff1a: /* Map FN to ALT */		return KEY_LEFTALT;	case 0xff2f:		return KEY_INFO;	default:		printf("Unknown key %x\n", c);		return c;	}}struct celluon_state {	int len;	/* Expected length of current packet */	int count;	/* Number of bytes received */	int action;	int key;};static void celluon_decode(int fd, struct celluon_state *s, uint8_t c){	if (s->count < 2 && c != 0xa5) {		/* Lost Sync */		s->count = 0;		return;	}	switch (s->count) {	case 0:		/* New packet - Reset state */		s->len = 30;		s->key = 0;		break;	case 1:		break;	case 6:		s->action = c;		break;	case 28:		s->key = c;		if (c == 0xff)			s->len = 31;		break;	case 29:	case 30:		if (s->count == s->len - 1) {			/* TODO: Verify checksum */			if (s->action < 2) {				send_event(fd, EV_KEY, celluon_xlate(s->key),								s->action);			}			s->count = -1;		} else {			s->key = (s->key << 8) | c;		}		break;	}	s->count++;	return;}int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel){	unsigned char buf[16];	struct sigaction sa;	struct pollfd p;	sigset_t sigs;	char addr[18];	int i, fd, sk, len;	struct celluon_state s;	sk = rfcomm_connect(src, dst, channel);	if (sk < 0)		return -1;	fd = uinput_create("Celluon Keyboard", 1, 0);	if (fd < 0) {		close(sk);		return -1;	}	ba2str(dst, addr);	printf("Connected to %s on channel %d\n", addr, channel);	printf("Press CTRL-C for hangup\n");	memset(&sa, 0, sizeof(sa));	sa.sa_flags   = SA_NOCLDSTOP;	sa.sa_handler = SIG_IGN;	sigaction(SIGCHLD, &sa, NULL);	sigaction(SIGPIPE, &sa, NULL);	sa.sa_handler = sig_term;	sigaction(SIGTERM, &sa, NULL);	sigaction(SIGINT,  &sa, NULL);	sa.sa_handler = sig_hup;	sigaction(SIGHUP, &sa, NULL);	sigfillset(&sigs);	sigdelset(&sigs, SIGCHLD);	sigdelset(&sigs, SIGPIPE);	sigdelset(&sigs, SIGTERM);	sigdelset(&sigs, SIGINT);	sigdelset(&sigs, SIGHUP);	p.fd = sk;	p.events = POLLIN | POLLERR | POLLHUP;	memset(&s, 0, sizeof(s));	while (!__io_canceled) {		p.revents = 0;		if (ppoll(&p, 1, NULL, &sigs) < 1)			continue;		len = read(sk, buf, sizeof(buf));		if (len < 0)			break;		for (i = 0; i < len; i++)			celluon_decode(fd, &s, buf[i]);	}	printf("Disconnected\n");	ioctl(fd, UI_DEV_DESTROY);	close(fd);	close(sk);	return 0;}

⌨️ 快捷键说明

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