我有hardware device并且提供它的供应商提供了一些C代码来监听使用ioctl
的按钮按下。该设备具有SSD1289控制器。
按钮不需要额外的引脚,可以通过SPI读取它们的状态。
这就是我想要的,阅读按下了哪个按钮。
我试图在Python中为我自己的应用程序复制这个脚本,但_IOR和ioctl要求让我失望。
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#define SSD1289_GET_KEYS _IOR('keys', 1, unsigned char *)
void get_keys(int fd)
{
unsigned char keys;
if (ioctl(fd, SSD1289_GET_KEYS, &keys) == -1)
{
perror("_apps ioctl get");
}
else
{
printf("Keys : %2x\n", keys);
}
}
int main(int argc, char *argv[])
{
char *file_name = "/dev/fb1";
int fd;
fd = open(file_name, O_RDWR);
if (fd == -1)
{
perror("_apps open");
return 2;
}
while(1)
get_keys(fd);
printf("Ioctl Number: (int)%d (hex)%x\n", SSD1289_GET_KEYS, SSD1289_GET_KEYS);
close (fd);
return 0;
}
现在我知道Python有一个ioctl模块,在某些时候我应该调用
file = open("/dev/fb1")
buf = array.array('h', [0])
fcntl.ioctl(file, ????, buf, 1)
我无法弄清SSD1289_GET_KEYS
应该是什么。我如何得到这个以及_IOR
是什么?
此外,如果这是错误的方法,知道这也是一个帮助。有spidev这样的库可以用于SPI,但我不知道用它来读什么。
@alexis在下面提供了一些有用的步骤,这让我想到了这一点:
import fcntl
import array
file = open("/dev/fb1")
buf = array.array('h', [0])
fcntl.ioctl(file, -444763391, buf, 1)
现在,如果我将上述内容保持在循环中,按下按钮会更改buf的值。
答案 0 :(得分:4)
你走在正确的轨道上,你只需要弄清楚要使用的常数。您的供应商程序实际上会以十进制和十六进制打印出来 - 如果您只想编辑main()
并将printf
行移到无尽的while
循环之上:
printf("Ioctl Number: (int)%d (hex)%x\n", SSD1289_GET_KEYS, SSD1289_GET_KEYS);
while(1)
get_keys(fd);
说明:
_IOR
是sys/ioctl.h
中定义的宏。其定义如下:
#define _IOC(inout,group,num,len) \
(inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0)
#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
我已经包含了相关的上下文行。你可以看到这个宏构造了一个位掩码(我们可以从名称中看出)处理读操作。但是你的目标是弄清楚你需要的位掩码,你可以毫不费力地做:通过cc -E
运行你的供应商的C程序,你会看到应用预处理器命令后的源代码。追踪get_keys
的定义(首先会有大量的头文件,所以它将在输出的最后),并拉出第二个参数。
结果可能与系统有关,所以你应该自己尝试一下。在我的盒子上,它出现了
((__uint32_t)0x40000000 | ((sizeof(unsigned char *) & 0x1fff) << 16) | ((('keys')) << 8) | ((1)))
不急于将其翻译成python,我在main()
的最开头添加了以下几行:
printf("%d", ((__uint32_t)0x40000000 | ((sizeof(unsigned char *) & 0x1fff) << 16) |
((('keys')) << 8) | ((1))));
exit(0);
我运行了程序,它给了我输出1702458113
,可能是你需要的值。它应该与已经存在的printf
命令的十进制输出相同(但隐藏在无尽的while
循环下面)。但是你自己检查一下,如果你把你的硬件或其他东西吹掉,不要怪我!