http://www.doc88.com/p-116663997270.html
具体内容以后补上,上面是参考网址
分析一下directfb的输入驱动调用流程吧,
使用directfb时,系统会从目录寻找对应子系统的.so库,然后加载库到系统中,具体过程我也没细看,上面那个网址里的介绍非常详细,
以其中的linuxinput为例,看看过程,direcfb的linuxinput 驱动
加载了linuxinput模块后,
/*
* Return the number of available devices.
* Called once during initialization of DirectFB.
*/
static int
driver_get_available( void )
{
int i;
char *tsdev;
#ifdef LINUX_INPUT_USE_FBDEV
if (dfb_system_type() != CORE_FBDEV)
return 0;
#endif
/* Use the devices specified in the configuration. */
if (fusion_vector_has_elements( &dfb_config->linux_input_devices )) {
const char *device;
fusion_vector_foreach (device, i, dfb_config->linux_input_devices) {
if (num_devices >= MAX_LINUX_INPUT_DEVICES)
break;
if (check_device( device ))
device_names[num_devices++] = D_STRDUP( device );
}
return num_devices;
}
/* Check for tslib device being used. */
tsdev = getenv( "TSLIB_TSDEVICE" );
/* No devices specified. Try to guess some. */
for (i=0; i<MAX_LINUX_INPUT_DEVICES; i++) {
char buf[32];
snprintf( buf, 32, "/dev/input/event%d", i );
/* Let tslib driver handle its device. */
if (tsdev && !strcmp( tsdev, buf ))
continue;
if (check_device( buf ))
device_names[num_devices++] = D_STRDUP( buf );
}
return num_devices;
}
初始化时首先要调用driver_get_available( void )查找设备的数目,这里面主要用到了check_device()函数
static bool
check_device( const char *device )
{
int fd;
/* Check if we are able to open the device */
fd = open( device, O_RDWR );
if (fd < 0) {
return false;
}
else {
InputDeviceInfo info;
bool touchpad;
/* try to grab the device */
if (dfb_config->linux_input_grab) {
/* 2.4 kernels don't have EVIOCGRAB so ignore EINVAL */
if (ioctl( fd, EVIOCGRAB, 1 ) && errno != EINVAL) {
close( fd );
return false;
}
}
memset( &info, 0, sizeof(InputDeviceInfo) );
get_device_info( fd, &info, &touchpad );
if (dfb_config->linux_input_grab)
ioctl( fd, EVIOCGRAB, 0 );
close( fd );
if (!dfb_config->linux_input_ir_only ||
(info.desc.type & DIDTF_REMOTE))
return true;
}
return false;
}
检测完设备后,就执行driver_open_device()函数,这个函数的作用主要是打开设备,封装原来的设备信息,然后开启输入线程,当外部有输入时执行线程处理函数,,然后把输入信息上报到上层,从而实现时间响应,我也只是猜测,但是大体上应该就差不多这么个过程
/*
* Open the device, fill out information about it,
* allocate and fill private data, start input thread.
* Called during initialization, resuming or taking over mastership.
*/
static DFBResult
driver_open_device( CoreInputDevice *device,
unsigned int number,
InputDeviceInfo *info,
void **driver_data )
{
int fd, ret;
unsigned long ledbit[NBITS(LED_CNT)];
LinuxInputData *data;
#ifdef LINUX_INPUT_USE_FBDEV
FBDev *dfb_fbdev = dfb_system_data();
#endif
bool touchpad;
/* open device */
fd = open( device_names[number], O_RDWR );
if (fd < 0) {
D_PERROR( "DirectFB/linux_input: could not open device" );
return DFB_INIT;
}
/* grab device */
if (dfb_config->linux_input_grab) {
ret = ioctl( fd, EVIOCGRAB, 1 );
/* 2.4 kernels don't have EVIOCGRAB so ignore EINVAL */
if (ret && errno != EINVAL) {
D_PERROR( "Direc tFB/linux_input: could not grab device" );
close( fd );
return DFB_INIT;
}
}
/* fill device info structure */
get_device_info( fd, info, &touchpad );
/* allocate and fill private data */
data = D_CALLOC( 1, sizeof(LinuxInputData) );
if (!data) {
if (dfb_config->linux_input_grab)
ioctl( fd, EVIOCGRAB, 0 );
close( fd );
return D_OOM();
}
data->fd = fd;
data->device = device;
#ifdef LINUX_INPUT_USE_FBDEV
data->vt = dfb_fbdev->vt;
#endif
data->touchpad = touchpad;
/* check if the device has LEDs */
ret = ioctl( fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit );
if (ret < 0)
D_PERROR( "DirectFB/linux_input: could not get LED bits" );
else
data->has_leds = test_bit( LED_SCROLLL, ledbit ) ||
test_bit( LED_NUML, ledbit ) ||
test_bit( LED_CAPSL, ledbit );
if (data->has_leds) {
/* get LED state */
ret = ioctl( fd, EVIOCGLED(sizeof(data->led_state)), data->led_state );
if (ret < 0) {
D_PERROR( "DirectFB/linux_input: could not get LED state" );
if (dfb_config->linux_input_grab)
ioctl( fd, EVIOCGRAB, 0 );
close( fd );
D_FREE( data );
return DFB_INIT;
}
/* turn off LEDs */
set_led( data, LED_SCROLLL, 0 );
set_led( data, LED_NUML, 0 );
set_led( data, LED_CAPSL, 0 );
}
/* start input thread */
data->thread = direct_thread_create( DTT_INPUT, linux_input_EventThread, data, "Linux Input" );
/* set private data pointer */
*driver_data = data;
return DFB_OK;
}
然后在directfb输入驱动中很关键的一个函数是
/*
* Input thread reading from device.
* Generates events on incoming data.
*/
static void*
linux_input_EventThread( DirectThread *thread, void *driver_data )
{
LinuxInputData *data = (LinuxInputData*) driver_data;
int readlen, status;
unsigned int i;
struct input_event levt[64];
fd_set set;
struct touchpad_fsm_state fsm_state;
/* Query min/max coordinates. */
if (data->touchpad) {
struct input_absinfo absinfo;
touchpad_fsm_init( &fsm_state );
ioctl( data->fd, EVIOCGABS(ABS_X), &absinfo );
fsm_state.x.min = absinfo.minimum;
fsm_state.x.max = absinfo.maximum;
ioctl( data->fd, EVIOCGABS(ABS_Y), &absinfo );
fsm_state.y.min = absinfo.minimum;
fsm_state.y.max = absinfo.maximum;
}
while (1) {
DFBInputEvent devt = { .type = DIET_UNKNOWN };
FD_ZERO( &set );
FD_SET( data->fd, &set );
if (data->touchpad && timeout_is_set( &fsm_state.timeout )) {
struct timeval time;
gettimeofday( &time, NULL );
if (!timeout_passed( &fsm_state.timeout, &time )) {
struct timeval timeout = fsm_state.timeout;
timeout_sub( &timeout, &time );
status = select( data->fd + 1, &set, NULL, NULL, &timeout );
} else {
status = 0;
}
}
else {
status = select( data->fd + 1, &set, NULL, NULL, NULL );
}
if (status < 0 && errno != EINTR)
break;
direct_thread_testcancel( thread );
if (status < 0)
continue;
/* timeout? */
if (status == 0) {
if (data->touchpad && touchpad_fsm( &fsm_state, NULL, &devt ) > 0)
dfb_input_dispatch( data->device, &devt );
continue;
}
readlen = read( data->fd, levt, sizeof(levt) );
if (readlen < 0 && errno != EINTR)
break;
direct_thread_testcancel( thread );
if (readlen <= 0)
continue;
for (i=0; i<readlen / sizeof(levt[0]); i++) {
DFBInputEvent temp = { .type = DIET_UNKNOWN };
if (data->touchpad) {
status = touchpad_fsm( &fsm_state, &levt[i], &temp );
if (status < 0) {
/* Not handled. Try the direct approach. */
if (!translate_event( &levt[i], &temp ))
continue;
}
else if (status == 0) {
/* Handled but no further processing is necessary. */
continue;
}
}
else {
if (!translate_event( &levt[i], &temp ))
continue;
}
/* Flush previous event with DIEF_FOLLOW? */
if (devt.type != DIET_UNKNOWN) {
flush_xy( data, false );
/* Signal immediately following event. */
devt.flags |= DIEF_FOLLOW;
dfb_input_dispatch( data->device, &devt );
if (data->has_leds && (devt.locks != data->locks)) {
set_led( data, LED_SCROLLL, devt.locks & DILS_SCROLL );
set_led( data, LED_NUML, devt.locks & DILS_NUM );
set_led( data, LED_CAPSL, devt.locks & DILS_CAPS );
data->locks = devt.locks;
}
devt.type = DIET_UNKNOWN;
devt.flags = DIEF_NONE;
}
devt = temp;
if (D_FLAGS_IS_SET( devt.flags, DIEF_AXISREL ) && devt.type == DIET_AXISMOTION &&
dfb_config->mouse_motion_compression)
{
switch (devt.axis) {
case DIAI_X:
data->dx += devt.axisrel;
continue;
case DIAI_Y:
data->dy += devt.axisrel;
continue;
default:
break;
}
}
/* Event is dispatched in next round of loop. */
}
/* Flush last event without DIEF_FOLLOW. */
if (devt.type != DIET_UNKNOWN) {
flush_xy( data, false );
dfb_input_dispatch( data->device, &devt );
if (data->has_leds && (devt.locks != data->locks)) {
set_led( data, LED_SCROLLL, devt.locks & DILS_SCROLL );
set_led( data, LED_NUML, devt.locks & DILS_NUM );
set_led( data, LED_CAPSL, devt.locks & DILS_CAPS );
data->locks = devt.locks;
}
}
else
flush_xy( data, true );
}
if (status <= 0)
D_PERROR ("linux_input thread died\n");
return NULL;
}
这个函数对我们添加directfb输入时间支持很关键啊,这几天我在让directfb支持我的tiny210的触摸屏,,隔几天接着写吧