尝试使用/ dev / uinput打开内置网络摄像头

时间:2013-04-01 19:10:46

标签: linux webcam inject keystroke

基本上,我想从shell或shell脚本中打开我的笔记本电脑的内置网络摄像头,而不必在每次打开时都按Fn+ESC

我一直试图在我的远程yeeloong 8089B notebook中激活集成网络摄像头,使用/ dev / uinput,在debian squeeze下,使用内核2.6.32-loongson-2f#1 PREEMPT来自{{3} }。我已经通过使用uinput实现了激活WLAN,但我无法使用uinput打开相机。通常情况下,我会按Fn+ESC打开相机,但是使用uinpuit它似乎不起作用。相机可以工作,可以通过以下方式进行测试:

mplayer tv:// -really-quiet -tv driver=v4l2:device=/dev/video0 </dev/null

我使用以下程序(基于Gregory Thiemonge和Mehul Patel的HOWTO)尝试使用uinput激活我的网络摄像头(对不起,如果代码有点难看,我有点匆匆写了):

cam_wlan.c:

#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define end(arg) do { \
    perror(arg); \
    exit(EXIT_FAILURE); \
} while (0)

static int fd = -1;
struct uinput_user_dev uidev;
struct input_event ev;

int setup_uinput_dev();
void cam();
void wifi();
int destroy_close();

int main(void) {
    setup_uinput_dev();
    cam();
    wifi();
    destroy_close();
    return 0;
}

int setup_uinput_dev() {
    fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
    if(fd < 0)
        end("Unable to open /dev/uinput\n");
    memset(&uidev,0,sizeof(uidev));
    strncpy(uidev.name, "uinput-sample", UINPUT_MAX_NAME_SIZE);
    uidev.id.version = 1;
    uidev.id.bustype = BUS_USB;
    if(ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
        end("Unable to setup UINPUT device.\n");
    if(ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA) < 0)
        end("Unable to setup UINPUT device.\n");
    if(ioctl(fd, UI_SET_KEYBIT, KEY_WLAN) < 0)
        end("Unable to setup UINPUT device.\n");
    if(write(fd, &uidev, sizeof(uidev)) < 0)
        end("Unable to write to UINPUT device.\n");
    if(ioctl(fd, UI_DEV_CREATE) < 0)
        end("Unable to create UINPUT device.\n");
    return 0;
}

void cam() {
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = KEY_CAMERA;
    ev.value = 1;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = KEY_CAMERA;
    ev.value = 0;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
}

void wifi() {
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = KEY_WLAN;
    ev.value = 1;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
    memset(&ev, 0, sizeof(ev));
    ev.type = EV_KEY;
    ev.code = KEY_WLAN;
    ev.value = 0;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
    ev.type = EV_SYN;
    ev.code = SYN_REPORT;
    ev.value = 0;
    if(write(fd, &ev, sizeof(struct input_event)) < 0)
        end("Unable to write to UINPUT device.\n");
}

int destroy_close() {
    if(ioctl(fd, UI_DEV_DESTROY) < 0)
        end("Unable to destroy UINPUT device.\n");
    close(fd);
    return 0;
}

我用

编译
gcc -o cam_wlan cam_wlan.c

在运行cam_wlan之前,必须以root身份:

modprobe uinput
lsmod | grep uinput
ls /dev/uinput

确认输入设备已被激活。

我遇到的问题是,当我运行cam_wlan时,WLAN LED会切换,但网络摄像头却没有。通常,当我按Fn+ESC切换内置网络摄像头时,dmesg会显示:

[45254.379000] usb 1-1: new high speed USB device using ehci_hcd and address 15
[45254.536000] usb 1-1: New USB device found, idVendor=064e, idProduct=a114
[45254.536000] usb 1-1: New USB device strings: Mfr=2, Product=1, SerialNumber=3
[45254.536000] usb 1-1: Product: USB 2.0 Camera
[45254.539000] usb 1-1: Manufacturer: SuYin
[45254.539000] usb 1-1: SerialNumber: CN0317-S30C-MC03-VS-B20081113
[45254.546000] usb 1-1: configuration #1 chosen from 1 choice
[45254.550000] uvcvideo: Found UVC 1.00 device USB 2.0 Camera (064e:a114)
[45254.567000] input: USB 2.0 Camera as /devices/pci0000:00/0000:00:09.1/usb1/1-1/1-1:1.0/input/input896

lsusb会显示:

Bus 001 Device 015: ID 064e:a114 Suyin Corp.

以root身份运行evtest /dev/input/event2会显示:

Input driver version is 1.0.0
Input device ID: bus 0x19 vendor 0x0 product 0x0 version 0x0
Input device name: "HotKeys"
Supported events:
  Event type 0 (Sync)
  Event type 1 (Key)
    Event code 113 (Mute)
    Event code 114 (VolumeDown)
    Event code 115 (VolumeUp)
    Event code 142 (Sleep)
    Event code 212 (Camera)
    Event code 224 (Brightness down)
    Event code 225 (Brightness up)
    Event code 227 (?)
    Event code 238 (?)
  Event type 5 (?)
    Event code 0 (?)
Testing ... (interrupt to exit)
Event: time 1364796475.137014, type 1 (Key), code 212 (Camera), value 1
Event: time 1364796475.138119, -------------- Report Sync ------------
Event: time 1364796475.138145, type 1 (Key), code 212 (Camera), value 0
Event: time 1364796475.138159, -------------- Report Sync ------------

当我运行cam_wlan时,这些都不会发生。我应该提一下,在运行cam_wlan时,WLAN切换不会发生事件报告,尽管WLAN LED会切换(并且通过运行cam_wlan确实激活和停用WLAN),而网络摄像头则没有切换。

我也尝试用原来的cam_wlan.c代替行

...
    if(ioctl(fd, UI_SET_KEYBIT, KEY_WLAN) < 0)
...
    ev.code = KEY_WLAN;
...

...
    if(ioctl(fd, UI_SET_KEYBIT, KEY_FN_ESC) < 0)
...
    ev.code = KEY_FN_ESC;
...

但这也不起作用。

所以,我愿意接受建议。我还可以尝试从shell激活集成网络摄像头? (即,不必在键盘上按Fn+ESC这样做)

0 个答案:

没有答案