小萌新想把蓝牙键盘的键盘信号通过手机SOCKET通讯传给电脑,用的是写入 /dev/input/event 的方法
碰到的第一个坑,是权限问题,open函数写入的权限代码不管用,最后是生成文件后,用SUDO权限跑起来的
open("/dev/input/event4",O_RDWR,0777);//除了0777,也试过好几个其他的组合,全都perror显示权限不足
碰到的第二个坑,是一开始直接抄别人的代码,用的event0,结果跑起来按键基本没反应,原本以为是完全失败了,意外按下F2和F5的时候,弹出关机…
然后去查了查,学到了用 cat /proc/bus/input/devices 来查看对应的event和设备,原来我的event0和1都是POWER BUTTON……
而且键盘显示也是两个:
I: Bus=0003 Vendor=046d Product=c31c Version=0110
N: Name="Logitech USB Keyboard"
P: Phys=usb-0000:00:14.0-12/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb3/3-12/3-12:1.0/0003:046D:C31C.0002/input/input4
U: Uniq=
H: Handlers=sysrq kbd event4 leds
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=1f
I: Bus=0003 Vendor=046d Product=c31c Version=0110
N: Name="Logitech USB Keyboard"
P: Phys=usb-0000:00:14.0-12/input1
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb3/3-12/3-12:1.1/0003:046D:C31C.0003/input/input5
U: Uniq=
H: Handlers=kbd event5
B: PROP=0
B: EV=1b
B: KEY=2010000 397ad801d001 1e000000000000 0
B: ABS=100000000
B: MSC=10
一开始看到LEDS…我以为event5才是输入,结果试了之后,发现event4才是…
找到了键盘的event,发现还是不行,按键奇奇怪怪的,显然是键码问题,于是听了一遍实际键盘的键码,把蓝牙的键码全部switch一遍
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 12341
void sendkbmsg(int value,int kcode)
{
int fd_kb = open("/dev/input/event4",O_RDWR,0777);
if(fd_kb<0)
perror("open /dev/input/event4 failed\n");
struct input_event event;
event.code = kcode;
event.type = EV_KEY;
event.value = value;
gettimeofday(&event.time,0);
if(write(fd_kb,&event,sizeof(event))!=sizeof(event))
perror("write /dev/input/event4 failed/n");
close(fd_kb);
}
int trascode(int rgkecode)
{
int result = rgkecode;
switch (rgkecode) {
case 16777216: result = 59; break;
case 16777376: result = 60; break;
case 16777469: result = 62; break;
case 16777362: result = 63; break;
case 16777346: result = 65; break;
case 16777344: result = 66; break;
case 16777347: result = 67; break;
case 16777329: result = 68; break;
case 96: result = 41; break;
case 49: result = 2; break;
case 50: result = 3; break;
case 51: result = 4; break;
case 52: result = 5; break;
case 53: result = 6; break;
case 54: result = 7; break;
case 55: result = 8; break;
case 56: result = 9; break;
case 57: result = 10; break;
case 48: result = 11; break;
case 45: result = 12; break;
case 61: result = 13; break;
case 16777219: result = 14; break;
case 16777217: result = 15; break;
case 16777252: result = 58; break;
case 16777248: result = 42; break;
case 16777249: result = 29; break;
case 16777251: result = 56; break;
case 32: result = 57; break;
case 16777220: result = 28; break;
case 16777235: result = 103; break;
case 16777237: result = 108; break;
case 16777234: result = 105; break;
case 16777236: result = 106; break;
case 81: result = 16; break;
case 87: result = 17; break;
case 69: result = 18; break;
case 82: result = 19; break;
case 84: result = 20; break;
case 89: result = 21; break;
case 85: result = 22; break;
case 73: result = 23; break;
case 79: result = 24; break;
case 80: result = 25; break;
case 91: result = 26; break;
case 93: result = 27; break;
case 92: result = 43; break;
case 65: result = 30; break;
case 83: result = 31; break;
case 68: result = 32; break;
case 70: result = 33; break;
case 71: result = 34; break;
case 72: result = 35; break;
case 74: result = 36; break;
case 75: result = 37; break;
case 76: result = 38; break;
case 59: result = 39; break;
case 39: result = 40; break;
case 90: result = 44; break;
case 88: result = 45; break;
case 67: result = 46; break;
case 86: result = 47; break;
case 66: result = 48; break;
case 78: result = 49; break;
case 77: result = 50; break;
case 44: result = 51; break;
case 46: result = 52; break;
case 47: result = 53; break;
default:
break;
}
return result;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
printf("starting....\n");
//建立SOCKET服务端,听取手机传来的消息
int serverSocket;
struct sockaddr_in server_addr;
struct sockaddr_in clientAddr;
int addr_len = sizeof(clientAddr);
int client;
char buffer[200];
int iDataNum;
if((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
return 1;
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(serverSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("connect");
return 1;
}
if(listen(serverSocket, 5) < 0)
{
perror("listen");
return 1;
}
while(1)
{
printf("监听端口: %d\n", SERVER_PORT);
client = accept(serverSocket, (struct sockaddr*)&clientAddr, (socklen_t*)&addr_len);
if(client < 0)
{
perror("accept");
continue;
}
printf("等待消息...\n");
printf("IP is %s\n", inet_ntoa(clientAddr.sin_addr));
printf("Port is %d\n", htons(clientAddr.sin_port));
buffer[0] = '\0';
iDataNum = recv(client, buffer, 200, 0);
if(iDataNum < 0)
{
perror("recv null");
continue;
}
//听取消息完成,下面开始处理...
buffer[iDataNum] = '\0';
char kvalue[5]={0};
int kcode;
sscanf(buffer,"%[^' '] %d",kvalue,&kcode);
int kivalue = strlen(kvalue)>=4?1:0;
sendkbmsg(kivalue,trascode(kcode));
printf("%s,%d",kvalue,kcode);
}
return a.exec();
}
本以为成了,然而还是有BUG……
键码确实写入到event了,但是,出现了一个非常奇怪的BUG——
必须按到第四个键,前面的按键消息才会一起被处理出来,不然连显示都不会显示
或者按下实际插在电脑上的键盘任意一个按键,才会一起被处理显示出来
而且还发生了一次不断输入(实际上蓝牙键盘上并没有按着)数字“2”的情况,直到按下电脑键盘的按键才停下…
…………
最新进度,找到一部分解决方法了,关于延迟的那部分:
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd_kb, &event, sizeof(event));
在写入按键事件后,还得向系统发送报告,才会立刻被处理,从这篇
学习到的,萌新果然需要多多搜索,多多学习,搜索方法也得精练呐
不过那个重复输入的问题,好像还是存在,但是触发的非常偶然,目前还没找到关键的触发条件,连问题都找不着,没法解决。。。
PS:现在就是用的工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工工aaaa……
好吧,打到这里的时候,BUG又再次触发了,而且用USB键盘打断了连续输入后,就再起不能了…
看了一次,似乎和连接反复断开重接有关…
“too many open file”……