input subsystem

    这几天在android上移植了sensor(compass+gsensor),虽然以前TP也是input系统,但只在driver处理,而sensor除了在driver处理还要在HAL处理,HAL处于input subsystem的上层,通过看HAL,对input子系统有了更全面的认识。sensor的数据流是sensor ic ---》driver---》input system----》HAL,其中,input system是由linux系统提供的,我们要完成driver和HAL。这里主要说一下input device在用户空间的接口,主要有三个位置分别如下

1.设备结点

/dev/input

crw-rw---- root input 13, 682012-03-28 16:16 event4

crw-rw---- root input 13, 702012-03-28 16:16 event6

crw-rw---- root input 13, 692012-03-28 16:16 event5

crw-rw---- root input 13, 672012-03-28 16:16 event3

crw-rw---- root input 13, 662012-03-28 16:16 event2

crw-rw---- root input 13, 652012-03-28 16:16 event1

crw-rw---- root input 13, 642012-03-28 16:16 event0

这些全是字符设备,通过这些字符设备节点可以在用户空间导出了原生event,转化成input_event,允许用户程序操作任何event,不会遗失任何信息。要读取相应inputdevice的数据,首先你必须获得input设备的文件描述符。获取方法如下

//这里的inputName必须与driver中注册input设备时制定的name一致,通过这个name就可以找到fd

//从而读取数据

//注册时定义data->input_dev_compass->name= "ami30x_compass";

int SensorBase::openInput(const char*inputName) {

int fd = -1;

const char *dirname = "/dev/input";

char devname[PATH_MAX];

char *filename;

DIR *dir;

struct dirent *de;

dir = opendir(dirname);

if(dir == NULL)

return -1;

strcpy(devname, dirname);

filename = devname +strlen(devname);

*filename++ = '/';

while((de = readdir(dir))) {

if(de->d_name[0] == '.' &&

(de->d_name[1] =='\0' ||

(de->d_name[1]== '.' && de->d_name[2] == '\0')))

continue;

strcpy(filename, de->d_name);

fd = open(devname, O_RDONLY);

if (fd>=0) {

char name[80];

//通过给设别结点发送ioctrl来获取相应的name,如果匹配则查找到

if (ioctl(fd,EVIOCGNAME(sizeof(name) - 1), &name) < 1) {

name[0] = '\0';

}

if (!strcmp(name,inputName)) {

strcpy(input_name,filename);

break;

} else {

close(fd);

fd = -1;

}

}

}

closedir(dir);

LOGE_IF(fd<0, "couldn'tfind '%s' input device", inputName);

return fd;

}

只要得到了这个fd,就可以与设备交互了,一般有3个接口可以使用

1IOCTRL

系统提供的IOCTRL如下

include/linux/input.h

#define EVIOCGVERSION _IOR('E',0x01, int) /* get driver version */

#define EVIOCGID _IOR('E', 0x02,struct input_id) /* get device ID */

#define EVIOCGREP _IOR('E',0x03, int[2]) /* get repeat settings */

#define EVIOCSREP _IOW('E',0x03, int[2]) /* set repeat settings */

#define EVIOCGKEYCODE _IOR('E',0x04, int[2]) /* get keycode */

#define EVIOCSKEYCODE _IOW('E',0x04, int[2]) /* set keycode */

#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */

#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */

#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */

#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global keystate */

#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */

#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */

#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */

#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */

#define EVIOCGABS(abs) _IOR('E',0x40 + abs, struct input_absinfo) /* get abs value/limits */

#define EVIOCSABS(abs) _IOW('E',0xc0 + abs, struct input_absinfo) /* set abs value/limits */

#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send aforce effect to a force feedback device */

#define EVIOCRMFF _IOW('E',0x81, int) /* Erase a force effect */

#define EVIOCGEFFECTS _IOR('E', 0x84,int) /*Report number of effects playable at the sametime*/

#define EVIOCGRAB _IOW('E',0x90, int) /* Grab/Release device */

值得一提的是EVIOCGNAME,通过ioctl命令EVIOCGNAME,能获取dev/input/event*对应的DeviceName,如ioctl(fd,EVIOCGNAME(sizeof(name)), name)

注意这个一般只是从系统中获取inputdevice的注册信息,不会与硬件通信。

2)获取设备的event通过char设备的read function

rb=read(fd,ev,sizeof(structinput_event)*64)

3)给设备发送信息通过write(如点亮键盘的numlock led

 write(fd, &ev, sizeof(struct input_event));

这些ioctrlreadwirte系统都已经实现,我们只要注册后,通过fd就可以使用,不需要在driver再实现fops

2.查看input class 信息

 /sys/devices/virtual/input/input*

自己进去看看好了

3.查看设备信息

/proc/bus/input/

# cat /proc/bus/input/devices

I: Bus=0018 Vendor=0000 Product=0000Version=0000

N: Name="ft5xxx"

P: Phys=

S:Sysfs=/devices/i2c-0/0-0038/input/input4

U: Uniq=

H: Handlers=event4 cpufreq

B: EV=b

B: KEY=400 0 4 0 0 0 0 0 0 0 0

B: ABS=2650000 3

I: Bus=0000 Vendor=0000 Product=0000Version=0000

N: Name="msm7627_sku2_keypad"

P: Phys=

S: Sysfs=/devices/virtual/input/input5

U: Uniq=

H: Handlers=kbd event5 cpufreq

B: EV=3

B: KEY=c0000 0 0 0

参考:

Input event驱动

Linux input 子系统 (1)(翻译国外的一篇文章,讲的很好)

linux内核input子系统解析

闲聊linux中的input设备(1)Linux中的设备大家族

(这是一个系列的文章,以akm的comapss 为例,正好我是在看android的sensor这块,风格有点像linnux那些事)

强烈建议看一看,看完以上三篇文章,基本对input subsystem会有比较全面的认识,包括driver层如何注册,input core如何处理及APP层如何处理接受到的event。




你可能感兴趣的:(linux,android,struct,IOC,input,linux内核)