輸入服務子系統實例分析(韋東山的視頻總結及針對linux-2.6.30.4)


根據韋東山視頻講解,和自己理解總結的:

1.分配一個input_dev結構體,

2.設置input_dev。

3.註冊input_dev結構體。

4.硬件相關的操作。

/*參考/keyboard/corgikbd.c*/

static int __init corgikbd_init(void)
{

    return platform_driver_register(&corgikbd_driver);
}

static struct platform_driver corgikbd_driver = {
    .probe   = corgikbd_probe,
    .remove  = __devexit_p(corgikbd_remove),
    .suspend = corgikbd_suspend,
    .resume  = corgikbd_resume,
    .driver  = {
             .name  = "corgi-keyboard",
             .owner = THIS_MODULE,
    },
};


static int __devinit corgikbd_probe(struct platform_device *pdev)
{
     struct corgikbd *corgikbd;
     struct input_dev *input_dev;
     int i, err = -ENOMEM;

     corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);

     /*1.分配一個input_dev結構*/
     input_dev = input_allocate_device();
     if (!corgikbd || !input_dev)
           goto fail;

     platform_set_drvdata(pdev, corgikbd);

     corgikbd->input = input_dev;
     spin_lock_init(&corgikbd->lock);

     /* Init Keyboard rescan timer */
     init_timer(&corgikbd->timer);
     corgikbd->timer.function = corgikbd_timer_callback;
     corgikbd->timer.data = (unsigned long) corgikbd;


     /* Init Hinge Timer */
     init_timer(&corgikbd->htimer);
     corgikbd->htimer.function = corgikbd_hinge_timer;
     corgikbd->htimer.data = (unsigned long) corgikbd;

     corgikbd->suspend_jiffies=jiffies;

     (corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));



     input_dev->name = "Corgi Keyboard";
     input_dev->phys = "corgikbd/input0";
     input_dev->id.bustype = BUS_HOST;
     input_dev->id.vendor = 0x0001;
     input_dev->id.product = 0x0001;
     input_dev->id.version = 0x0100;
     input_dev->dev.parent = &pdev->dev;
     /*2.設置input_dev*/

/*2.1設置能產生哪些事件 Event types   

         *EV_KEY 定義爲#define  EV_KEY   0x01  

         *能產生按鍵類事件

         *EV_REP 重複,當按下,不松時能產生多個值

         */
     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
                        BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
     input_dev->keycode = corgikbd->keycode;
     input_dev->keycodesize = sizeof(unsigned char);
     input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
       /*2.2設置能產生這類事件的哪些事件*/
     for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
          set_bit(corgikbd->keycode[i], input_dev->keybit);
     clear_bit(0, input_dev->keybit);
     set_bit(SW_LID, input_dev->swbit);
     set_bit(SW_TABLET_MODE, input_dev->swbit);
     set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);

     /*3.註冊 input_dev */
     err = input_register_device(corgikbd->input);
     if (err)
         goto fail;

     mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
      /*4.硬件相關的操作*/
     /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
     for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
          pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);

      /*註冊中斷*/

              if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i),corgikbd_interrupt,
                 IRQF_DISABLED | IRQF_TRIGGER_RISING,"corgikbd",corgikbd)
)
                     printk(KERN_WARNING "corgikbd:Can't get IRQ:%d!\n",i);
      }


      /* Set Strobe lines as outputs - set high */
      for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
         pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i)|GPIO_OUT|GPIO_DFLT_HIGH);

      /* Setup the headphone jack as an input */
      pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);

      return 0;

fail:   input_free_device(input_dev);
        kfree(corgikbd);
        return err;
}

下面我們自己下符合輸入子服務系統的程序

/*引腳描述結構體*/

struct pin_dec{
int irq;
char *name;
unsigned int pin;
unsigned int key_val;
};

/*定義的按鍵的四個引腳描述結構體數組*/
struct pin_dec pins_desc[4] = {
   {IRQ_EINT1,"s1",S3C2410_GPF1, KEY_L},
   {IRQ_EINT4,"s2",S3C2410_GPF4, KEY_S},
   {IRQ_EINT2,"s3",S3C2410_GPF2, KEY_ENTER},
   {IRQ_EINT0,"s4",S3C2410_GPF0, KEY_LEFTSHIFT},
};

/*定義一個定時器*/

static struct timer_list buttons_timer;

     /*入口函數*/

static int buttons_init(void)
{
    int i;
    /*1.分配一個input_dev結構體*/
    buttons_dev = input_allocate_device();
    /*2.設置*/
        /*2.1能產生的哪類事件*/
    buttons_dev->evbit = BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);
       /*2.2能產生這類操作裏的哪些事件*/
    __set_bit(KEY_L,buttons_dev->keybit);
    __set_bit(KEY_S,buttons_dev->keybit);
    __set_bit(KEY_ENTER,buttons_dev->keybit);
    __set_bit(KEY_LEFTSHIFT,buttons_dev->keybit);
    /*3.註冊*/
    input_register_device(buttons_dev);
    /*4.硬件相關的操作*/
     init_timer(&buttons_timer); /*初始化定時器*/

     /*指定定時器中斷的處理函數*/
     buttons_timer.function = buttons_timer_function; 

     /*增加一個定時器*/
     add_timer(&buttons_timer); 
     for(i=0;i<4;i++){

                 /*註冊中斷*/
        request_irq(pins_desc[i].irq,buttons_irq,
IRQ_TYPE_EDGE_BOTH,pins_desc[i].name,

                    &pins_desc[i]);

     }
     return 0;
}


static irqreturn_t buttons_irq(int irq, void *dev_id){
     /*10ms後啓動定時器,消抖*/
     irq_pd = (struct pin_dec*)dev_id;

     /*修改定時器*/
     mod_timer(&buttons_timer,jiffies+HZ/100);
     return IRQ_RETVAL(IRQ_HANDLED);
}


/*定時器的處理函數*/

static void buttons_timer_function(unsigned long data)
{
     struct pin_dec*pindesc = irq_pd;
     unsigned int pinval;
     pinval = s3c2410_gpio_getpin(pindesc->pin);
     if(pinval){

                /*上報事件*/

     /*也可以用input_report_key(buttons_dev,pindesc->key_val,0)*/

        /*鬆開時*/

        input_event(buttons_dev,EV_KEY,pindesc->key_val,0);
        input_sync(buttons_dev);
     }
     else
     {

           /*按下時*/

          /*也可以用input_report_key(buttons_dev,pindesc->key_val,1)*/
          input_event(buttons_dev,EV_KEY,pindesc->key_val,1);
          input_sync(buttons_dev);
     }
}


/*出口函數*/

static void buttons_exit(void)
{
    int i;
    for(i=0;i<4;i++){

        /*釋放中斷*/
       free_irq(pins_desc[i].irq,&pins_desc[i]);
    }

        /*吊銷定時器*/
   del_timer(&buttons_timer);

        /*註銷註冊的buttons_dev*/
   input_unregister_device(buttons_dev);

   /*釋放掉buttons_dev佔用的內存*/
   input_free_device(buttons_dev);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章