我正在创build一个游戏库的Linux模块,让你热插拔多个游戏杆,它使用inotify来观看/dev/input 。
我正在testing3个游戏杆:
首先,我连接2个操纵杆。
然后我启动应用程序,操纵杆工作,我没有得到一个错误。
之后,我连接第三个游戏杆, perror给: /dev/input/js1: Permission denied 。
当我检查ls -l /proc/<pid-of-process>/fd它列出了/dev/input/js0和/dev/input/js2 。
当我以root身份运行游戏杆时,所有游戏杆都可以正常工作。
这是如何初始化的:
CoInitialize尚未被调用 – (从无DirectXTK的库中加载gamepad.h)
为什么SDL不能在Linux上检测我的iBuffalo游戏控制器(PocketCHIP)?
解释USB游戏杆轴
static void createGamepad(char *locName){ char dirName[30]; int fd; snprintf(dirName,30,"/dev/input/%s",locName); fd = open(dirName,O_RDONLY | O_NONBLOCK,0); if(fd < 0){ perror(dirName); } } struct dirent *dir; DIR *d; int i,notifyfd,watch; // Attach notifications to check if a device connects/disconnects notifyfd = inotify_init(); watch = inotify_add_watch(notifyfd,"/dev/input",IN_CREATE | IN_DELETE); d = opendir("/dev/input"); i = 0; while((dir = readdir(d)) != NULL){ if(*dir->d_name == 'j' && *(dir->d_name + 1) == 's'){ createGamepad(dir->d_name,i); i++; } } closedir(d);
之后,inotify在while(1)循环中像这样处理它:
static bool canReadINotify(){ fd_set set; struct timeval timeout; FD_ZERO(&set); FD_SET(notifyfd,&set); timeout.tv_sec = 0; timeout.tv_usec = 0; return select(notifyfd + 1,&set,NULL,&timeout) > 0 && FD_ISSET(notifyfd,&set); } // Inside the event loop struct inotify_event ne; while(canReadINotify()){ if(read(notifyfd,&ne,sizeof(struct inotify_event) + 16) >= 0){ if(*ne.name != 'j' || *(ne.name + 1) != 's'){ continue; } if(ne.mask & IN_CREATE){ createGamepad(ne.name); } } }
它甚至可能与inotify或者我应该使用udev? 如果有可能,我该如何解决这个问题?
这很可能是一个竞争条件。 你会发现,当设备节点被创建时(通过udev使用mknod()调用),你会得到inotify事件,但是访问权限是由udev使用一个单独的chown()调用设置的,稍后一点点。
请参阅systemd src/udev/udev-node.c , node_permissions_apply() 。 在这种情况下, /dev/input/jsX不是符号链接,而是实际的设备节点; 至少在systemd之后,设备节点访问模式会在实际节点创建后的某个时间被设置。
一个可靠的解决方案是修改你的createGamepad()函数,以便在fd == -1 && errno == EACCES完全失败,而不是在短时间后重试; 至少几次,比如说一两秒钟。
然而, ninjalj指出了一个更好的建议 :使用访问权限更改作为触发器来检查设备节点。 这是通过使用IN_CREATE | IN_DELETE | IN_ATTRIBUTE来实现的 IN_CREATE | IN_DELETE | IN_ATTRIBUTE inotify_add_watch()函数中的IN_CREATE | IN_DELETE | IN_ATTRIBUTE !
(你也可以忽略createGamepad() open()==-1,errno==EACCES错误,因为它们很有可能是由这个竞争条件引起的,下面的IN_ATTRIBUTE inotify事件将会产生对同一个设备的访问。 )
在ninjalj的评论之前,我本人曾经使用过一系列的输入设备,而另外一个是用于“可能的”输入设备,在短暂的暂停之后可能需要重试以决定它们是否可用,但是我认为他的建议好多了
需要/想要一个例子?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。