different device in linux

//gcc -o key_source_detect key_source_detect.c `pkg-config --cflags --libs elementary x11 xextproto xext xi` -lecore_x
/*

In the sample, we do the following:
   -Declare a static structure to hold device id's of following devices:
    1. VCK (Virtual Core Keyboard)
    2. HWKeys   (Proxy device representing floating devices like REMOCON,PANEL_KEYS etc.)
    3. Remocon device (wt61p807 rc device)
    4. Panel Key device (wt61p807 panel key device)
   
   -Declare a static enum event_source to hold the current source of input.
    typedef enum
    {
        REMOCON,   //Floating slave represented by HWKeys device
        PANEL_KEY, //Floating slave represented by HWKeys device
        OTHER      //Any attached slave Keyboards and any other floating devices represented by HWKeys device
    }_event_source;
   
   -Implement a routine init_x_input_extension() to
    1. Check & Initialize XInput2 related things (one time)
    2. Setup the device id' in the global structure (using function get_id_for_known_devices())
    3. Initialize the event_source enum.
    4. Setup XInput2 masks for enabling the application to get XInput events

   -Implement a generic event handler to handle XInput events
    1. Filter unknown & unwanted events
    2. Check if the event is of type DeviceChange
    3. Check if the changed device is the VCK
    4. Get the new source of input for the VCK
    5. Update the global event_source enum according to the new input source

   -Implement a key handler
    1. Get the global event_source value to print the source of input
    2. Print the key value

   -Implement the main function
    1. Install a generic event handler with the above function as the callback routine
    2. Invoke init_x_input_extension function described above to do init and register for XInput events
    3. Routine application code
    4. Install a key handler


*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
#include <Elementary.h>
#include <Ecore_X.h>

//device names
#define REMOCON_DEV_NAME "wt61p807 rc device"
#define PANEL_KEY_DEV_NAME "wt61p807 panel key device"

//we define a structure to keep some
//variables that will be required in different functions
typedef struct
{
    int xi2_opcode; //XExtension opcode required in some XI2 API's
    Display *disp;  //X-Server Display required in some XI2 API's
    Window rootWin;//The root window pointer also required in some XI2 API's
    XIEventMask eventmask; //Event mask , required to select slave-siwtch event
    int vck_id;       //device id of the Virtual Core Keyboard device
    int hwkeys_dev_id; //device id of the HWKeys device
    int remocon_dev_id; //device id of remocon device
    int panel_key_dev_id; //device id of panel key device
}_input_device_info;

static _input_device_info input_device_info;

//event sources
typedef enum
{
    REMOCON,   /*Floating slave represented by HWKeys device*/
    PANEL_KEY, /*Floating slave represented by HWKeys device*/
    OTHER      /*Any attached slave Keyboards and any other floating devices represented by HWKeys device*/
}_event_source;
static _event_source event_source;

//function prototypes
static void _enable_xi2_events(void);
static void _disable_xi2_events(void);
void get_id_for_known_devices(void);
static int get_current_input_source_for_device(int device_id);


//function to check XI2 availability and do some initializations
//First we check for the XI2 input extension and initialize some parameters required in XI2 API.
//In here, we will also set some global parameters like device id of the VCK, HWKeys, and XTEST devices.
//Apart from device id's, we also try to get the names of these devices and save them.
//After this, we set required XI2 masks to enable our application to receive XI2 events.
int
init_x_input_extension()
{
    int event,error;
    int major = 2, minor = 0;

    //set the VCK device id..
    //device id of the VCK is always fixed in the X-Server = 3
    input_device_info.vck_id = 3;

    //Now get the Display & root window..
    input_device_info.disp = ecore_x_display_get();
    input_device_info.rootWin = DefaultRootWindow(input_device_info.disp);

    //now check for XI2 extension and version..
    //This is a one time thing that needs to be done only once
    //in the beginning of the program
    if( !XQueryExtension(input_device_info.disp, "XInputExtension",
                         &input_device_info.xi2_opcode, &event, &error) )
    {
        fprintf(stderr, "XInput Extension isn't supported.\n");
        input_device_info.xi2_opcode = -1;
        return 0;
    }

    if( XIQueryVersion(input_device_info.disp, &major, &minor) == BadRequest )
    {
        fprintf(stderr,"Failed to query XI version.\n");
        input_device_info.xi2_opcode = -1;
        return 0;
    }
    //now we know the extension is available..
    //now we will get and store the id of HWKeys device
    //xtest extesion keyboard, remocon & panel key device
    get_id_for_known_devices();

    //now we will initialize the event_source..
    //first get the current source of input for the VCK..
    int active_slave_id = get_current_input_source_for_device(input_device_info.vck_id);

    //let's check if the current input source for VCK is HWKeys?
    if(active_slave_id == input_device_info.hwkeys_dev_id)
    {
        //Yes HWKeys is the current input source..
        //But as we know its a dummy device, we now find the actual floating device driving the
        //HWKeys device. We use the same function which we used for getting the source for VCK.
        //Simply pass the device id of HWKeys device..the logic is same
        int floating_dev_id = get_current_input_source_for_device(input_device_info.hwkeys_dev_id);

        //now let's check if the actual device is either remocon or panel keys..
        if(floating_dev_id == input_device_info.remocon_dev_id)
        {
            event_source = REMOCON;
        }
        else if(floating_dev_id == input_device_info.panel_key_dev_id)
        {
            event_source = PANEL_KEY;
        }
        else
        {
            event_source = OTHER;
        }
    }
    else
    {
        event_source = OTHER;
    }


    //we now setup an event mask to listen to
    //slave-switch events on root window
    memset(&input_device_info.eventmask, 0L, sizeof(XIEventMask));
    input_device_info.eventmask.deviceid = XIAllDevices;
    input_device_info.eventmask.mask_len = XIMaskLen(XI_RawMotion);
    input_device_info.eventmask.mask = calloc(input_device_info.eventmask.mask_len, sizeof(char));

    /* Events we want to listen for all */
    XISetMask(input_device_info.eventmask.mask, XI_DeviceChanged);
    XISelectEvents(input_device_info.disp, input_device_info.rootWin,
                    &input_device_info.eventmask, 1);
    return 1;
}

//this function enables the reception of slave-switch events
static void
_enable_xi2_events()
{
    /* Events we want to listen */
    XISetMask(input_device_info.eventmask.mask, XI_DeviceChanged);
    XISelectEvents(input_device_info.disp, input_device_info.rootWin,
                    &input_device_info.eventmask, 1);
}

//this function disables the reception of slave-switch events
static void
_disable_xi2_events()
{
    /* Events we do not want to listen*/
    XIClearMask(input_device_info.eventmask.mask, XI_DeviceChanged);
    XISelectEvents(input_device_info.disp, input_device_info.rootWin,
                    &input_device_info.eventmask, 1);
}

//this function gets the device id of the HWKeys Device,
//XTEST extension keyboard device, remocon device & panel key device
void
get_id_for_known_devices()
{
    int i, ndevices, result;
    XIDeviceInfo *dev, *info = NULL;
    //XIQueryDevice API returns the info about querried device
    //If we pass XIAllDevices, it returns a list of all the devices
    //ndevices will have the number of devices and info will be
    //pointed to a list of XIDeviceInfo structures
    info = XIQueryDevice(input_device_info.disp, XIAllDevices, &ndevices);
    if( !info )    {
        fprintf(stderr,"There is no queried XI device.\n");
        return;
    }
    //now we iterate over the list of all devices to populate our device list
    for( i = 0; i < ndevices ; i++ ) {
        dev = &info[i];
        switch(dev->use) {
            case XISlaveKeyboard:
                //a slave keyboard device..
                //apply filter to get HWKeys device
                if( strcasestr(dev->name, "HWKeys" )) {
                    fprintf(stderr,"XISlaveKeyboard : HWKeys slave device found.. saving device id : %d..\n",dev->deviceid);
                    input_device_info.hwkeys_dev_id = dev->deviceid;
                    continue;
                }
                break;

            case XIMasterPointer:
            case XISlavePointer:
            case XIMasterKeyboard:
            case XIFloatingSlave:
                //a floating slave device..
                //remocon & panel keys fall in this class.. so we check the device names..
                if( strcasestr(dev->name, REMOCON_DEV_NAME )) {
                    fprintf(stderr,"XIFloatingSlave : Remocon device found.. saving device id : %d..\n",dev->deviceid);
                    input_device_info.remocon_dev_id = dev->deviceid;
                    continue;
                }
                if( strcasestr(dev->name, PANEL_KEY_DEV_NAME )) {
                    fprintf(stderr,"XIFloatingSlave : PANEL_KEY device found.. saving device id : %d..\n",dev->deviceid);
                    input_device_info.panel_key_dev_id = dev->deviceid;
                    continue;
                }
                break;
            default:
                break;
        }
    }
    //we must free the device info list received from XIQueryDevice else it will leak
    XIFreeDeviceInfo(info);
}

/*
  function to get the device id of the device actually driving a given virtual device
  this happens in case of VCK & HWKeys device as both are virtual and need some
  physical device to drive them
  to find the driving slave,
  1. we query the virtual device to get deviceinfo
  2. get the keyclass from the deviceinfo
  3. get the source id from the key class
  4. the source id obtained in above step is the desired result.

               VCK(Virtual)
                |
    -------------------------------------
    ^           ^                       ^
    |           |                       |
   KBD1(Phy)   KBD2(Phy)       HWKeys(Virtual)
                                        ^
                                        |
                                -----------------
                                ^               ^
                                |               |
                        REMOCON(Phy)       PANEL_KEY(Phy)

*/
static int
get_current_input_source_for_device(int device_id)
{
    int i,ndevices,sourceid;
    XIDeviceInfo *dev;
    XIAnyClassInfo **classes = NULL;
    XIKeyClassInfo *keyClass = NULL;

    //get device info
    dev = XIQueryDevice(input_device_info.disp, device_id, &ndevices);
    //get the key class info to get the source id of the device actually generating input ..
    classes = dev->classes;
    for ( i=0; i < dev->num_classes; i++ )
      {
         switch (classes[i]->type)
           {
              case XIKeyClass:
                 keyClass = (XIKeyClassInfo *)classes[i];
                 return keyClass->sourceid;
                 break;  

              default:
                 break;
           }
      }
    XIFreeDeviceInfo(dev);
    return 0;
}


//event-handler to handle slave switch event
//This is the place to update the input device state in the application.
//The global state can be used in different parts of the application.
//In here, the application can set flags to change UI according to the input source etc.
static int
_cb_event_generic(void *data, int ev_type, void *event)
{
    Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic *)event;
    XIDeviceEvent *evData = (XIDeviceEvent *)(e->data);
    XIDeviceChangedEvent *devChangeEvent;

    //filters to drop unwanted events..
    if (e->extension != input_device_info.xi2_opcode){
        fprintf(stderr,"Invalid event !(extension:%d, evtype:%d)\n", e->extension, e->evtype);
        return 1;
    }

    if (!evData || evData->send_event){
       fprintf(stderr,"Generic event data is not available or the event was sent via XSendEvent (and will be ignored) !\n");
       return 1;
    }

    //switch to the event of interest..
    switch (e->evtype) {
        //The slave-switch event is a type of XI_DeviceChanged event
        case XI_DeviceChanged:
            devChangeEvent = (XIDeviceChangedEvent *)evData;
            if(input_device_info.vck_id == devChangeEvent->deviceid) {
                if(devChangeEvent->sourceid == input_device_info.hwkeys_dev_id) {
                    fprintf(stderr,"Input source changed ! New Source Of Input: HWKeys/XTEST (device id :%d)\n", devChangeEvent->sourceid);
                    //get the floating device that is currentlyactive..
                    int floating_dev_id = get_current_input_source_for_device(input_device_info.hwkeys_dev_id);
                    //now let's check if the actual device is either remocon or panel keys..
                    if(floating_dev_id == input_device_info.remocon_dev_id){
                        event_source = REMOCON;
                    } else if(floating_dev_id == input_device_info.panel_key_dev_id) {
                        event_source = PANEL_KEY;
                    } else {
                        event_source = OTHER;
                    }
                } else {
                    event_source = OTHER;
                }
            }
            break;

        default:
            break;
    }

    return 1;
}

//this function prints the keystrokes and the source of input
//from the global state variables in input_device_info structure..
static void _key_pressed(void *dt, Evas *e,
        Evas_Object *obj, void *ei)
{
    Evas_Event_Key_Down *ev = ei;

    switch (event_source) {
        case REMOCON:
            fprintf(stderr,"Input Source : Remocon\n");
            break;
        case PANEL_KEY:
            fprintf(stderr,"Input Source : Panel Key\n");
            break;
        case OTHER:
        default:
            fprintf(stderr,"Input Source : Other\n");
            break;
    }
    fprintf(stderr,"ev->keyname is %s\n", ev->keyname);
}


EAPI_MAIN int
elm_main(int argc, char *argv[])
{
    //add an event handler to handle slave-switch events..
    ecore_event_handler_add(ECORE_X_EVENT_GENERIC,
                             (Ecore_Event_Handler_Cb)_cb_event_generic,
                             NULL);

    //initialize x_input extension..
    init_x_input_extension();

    //create and show the application main window..
    Evas_Object *win, *bg;
    win = elm_win_add(NULL, "Device Detect example", ELM_WIN_UTILITY);
    elm_win_title_set(win, "Device Detect example");
    elm_win_borderless_set(win, EINA_TRUE);
    elm_win_alpha_set(win, EINA_TRUE);

    bg = elm_bg_add(win);
    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    elm_win_resize_object_add(win, bg);
    evas_object_color_set(bg,255,0,0,255);
    evas_object_show(bg);
    evas_object_resize(win, 1920, 500);
    evas_object_show(win);

    evas_object_event_callback_add(win, EVAS_CALLBACK_KEY_DOWN,
                    _key_pressed, NULL);


    elm_run();
    elm_shutdown();

    return 0;
}
ELM_MAIN()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值