在 PHP 中处理 Linux 输入事件 (/dev/input/event*)

问题描述 投票:0回答:1

我正在尝试使用 php 在 GNU/Linux 上获取键盘事件,代码如下:

<?php
$fd = fopen("/dev/input/event0", "rb");
while (true) {
    $ev = fread($fd, 24);
    $event = unpack("Lsec/Lusec/Stype/Scode/Ivalue", $ev);
    var_dump($event);
}
fclose($fd);
?>

但结果与我在以下 C 程序中得到的事件不同:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
int main()
{
    struct input_event ev;
    int fd = open("/dev/input/event0", O_RDONLY);
    while(1)
    {
        read(fd, &ev, sizeof(ev));
        printf ("Event sec: %lu\n", ev.time.tv_sec);
        printf ("Event usec: %lu\n", ev.time.tv_usec);
        printf("Event type: %d\n", ev.type);
        printf("Event code: %d\n", ev.code);
        printf("Event value: %d\n", ev.value);
        printf("Event value: %s\n", "***************");
    }
    close(fd);
}

部分结果对比:

C:
Event sec: 1700377522
Event usec: 896483
Event type: 4
Event code: 4
Event value: 31
Event value: ***************
Event sec: 1700377522
Event usec: 896483
Event type: 1
Event code: 31
Event value: 1
Event value: ***************
Event sec: 1700377522
Event usec: 896483
Event type: 0
Event code: 0
Event value: 0
Event value: ***************

PHP:
array(5) {
  ["sec"]=>
  int(1700377522)
  ["usec"]=>
  int(0)
  ["type"]=>
  int(44515)
  ["code"]=>
  int(13)
  ["value"]=>
  int(0)
}
array(5) {
  ["sec"]=>
  int(1700377522)
  ["usec"]=>
  int(0)
  ["type"]=>
  int(44515)
  ["code"]=>
  int(13)
  ["value"]=>
  int(0)
}
array(5) {
  ["sec"]=>
  int(1700377522)
  ["usec"]=>
  int(0)
  ["type"]=>
  int(44515)
  ["code"]=>
  int(13)
  ["value"]=>
  int(0)
}

sec
参数似乎解码正常,另一方面,其他参数,我猜测问题是由解包格式引起的:
unpack("Lsec/Lusec/Stype/Scode/Ivalue", $ev);
,但我根据
/usr/include/linux/input.h

设置了所有内容
struct input_event {
        struct timeval time; = {long seconds, long microseconds}
        unsigned short type;
        unsigned short code;
        unsigned int value;
};

这有什么问题吗?

注: 我在“input.h”中看到一些填充字节:

#if defined(__sparc__) && defined(__arch64__)
    unsigned int __usec;
    unsigned int __pad;
#else

这可能是问题所在吗?我该如何解决它?

php linux events linux-kernel inputevent
1个回答
0
投票

在 64 位 Linux 上,C 整数类型具有以下宽度:

  • short
    :16 位
  • int
    :32 位
  • long
    :64 位

input_event
结构体大小为 8 + 8 + 2 + 2 + 4 = 24 字节。

PHP

pack()
函数的文档说:

L unsigned long(始终为 32 位,机器字节顺序)

这里存在不匹配:对于

long
字段,您读取的是 32 位而不是 64 位。你应该使用这个:

q 有符号 long long(始终为 64 位,机器字节顺序)

所以正确的拆包是:

$event = unpack("qsec/qusec/Stype/Scode/Lvalue", $ev);
© www.soinside.com 2019 - 2024. All rights reserved.