关于directfb



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的触摸屏,,隔几天接着写吧




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值