亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1666 | 回復(fù): 0
打印 上一主題 下一主題

LINUX設(shè)備驅(qū)動之輸入子系統(tǒng)(一) [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-02-03 10:35 |只看該作者 |倒序瀏覽
Eric Fang  2010-02-03
--------------------------------------------------------------
本站分析linux內(nèi)核源碼,版本號為2.6.32.3
轉(zhuǎn)載請注明出處:
http://ericfang.cublog.cn/
--------------------------------------------------------------
在前面鍵盤驅(qū)動的分析中已經(jīng)接觸到了輸入子系統(tǒng),本文將結(jié)合鍵盤驅(qū)動,系統(tǒng)分析輸入子系統(tǒng)。

回想一下,在設(shè)備驅(qū)動匹配成功時,創(chuàng)建了一個input_dev并注冊到輸入子系統(tǒng);在鍵盤中斷處理例程中向輸入子系統(tǒng)上報事件。

輸入子系統(tǒng)是所有I/O設(shè)備驅(qū)動的中間層,如何為下層眾多各式各樣的輸入設(shè)備提供接口以及為上層提供了一個統(tǒng)一的界面?

根據(jù)內(nèi)核代碼,輸入子系統(tǒng)中存在兩個鏈表:input_dev_list、input_handler_list,當注冊一個input_dev時就會把它掛到input_dev_list上,然后去匹配input_handler_list上的input_handler,相反,當注冊一個input_handler時就會把它掛到input_handler_list上,然后去匹配input_dev_list上的input_dev,匹配成功時就會調(diào)用該handler的connect函數(shù),該函數(shù)一般會創(chuàng)建和注冊一個input_handle,這個input_handle中包含了input_dev和input_handler相關(guān)的信息,這樣當下層向輸入子系統(tǒng)上報事件時就可以通過input_handle找到相應(yīng)的input_handler并調(diào)用相關(guān)函數(shù),進一步為上次提供服務(wù)。

下面將一步一步詳細的分析這個過程。

一.Input設(shè)備的注冊
Input設(shè)備注冊的接口函數(shù)為:input_register_device,不過在注冊Input設(shè)備,前必須先創(chuàng)建一個Input設(shè)備,可以靜態(tài)定義一個Input設(shè)備然后自行初始化它,也可以調(diào)用input_allocate_device來創(chuàng)建一個Input設(shè)備(回想一下,在鍵盤驅(qū)動分析的代碼中就是調(diào)用這個函數(shù)的),看一下這個函數(shù):
1389       struct input_dev *input_allocate_device(void)
1390       {
1391              struct input_dev *dev;
1392      
1393              dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
1394              if (dev) {
1395                     dev->dev.type = &input_dev_type;
1396                     dev->dev.class = &input_class;
1397                     device_initialize(&dev->dev);
1398                     mutex_init(&dev->mutex);
1399                     spin_lock_init(&dev->event_lock);
1400                     INIT_LIST_HEAD(&dev->h_list);
1401                     INIT_LIST_HEAD(&dev->node);
1402      
1403                     __module_get(THIS_MODULE);
1404              }
1405      
1406              return dev;
1407       }
input_dev結(jié)構(gòu)如下:
1072       struct input_dev {
1073              const char *name;
1074              const char *phys;
1075              const char *uniq;
1076              struct input_id id;
1077      
1078              unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
1079              unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
1080              unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
1081              unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
1082              unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
1083              unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
1084              unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
1085              unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
1086              unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
1087      
1088              unsigned int keycodemax;
1089              unsigned int keycodesize;
1090              void *keycode;
1091              int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
1092              int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
1093      
1094              struct ff_device *ff;
1095      
1096              unsigned int repeat_key;
1097              struct timer_list timer;
1098      
1099              int sync;
1100      
1101              int abs[ABS_MAX + 1];
1102              int rep[REP_MAX + 1];
1103      
1104              unsigned long key[BITS_TO_LONGS(KEY_CNT)];
1105              unsigned long led[BITS_TO_LONGS(LED_CNT)];
1106              unsigned long snd[BITS_TO_LONGS(SND_CNT)];
1107              unsigned long sw[BITS_TO_LONGS(SW_CNT)];
1108      
1109              int absmax[ABS_MAX + 1];
1110        int absmin[ABS_MAX + 1];
1111        int absfuzz[ABS_MAX + 1];
1112        int absflat[ABS_MAX + 1];
1113        int absres[ABS_MAX + 1];
1114
1115        int (*open)(struct input_dev *dev);
1116        void (*close)(struct input_dev *dev);
1117        int (*flush)(struct input_dev *dev, struct file *file);
1118        int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
1119
1120              struct input_handle *grab;
1121      
1122              spinlock_t event_lock;
1123              struct mutex mutex;
1124      
1125              unsigned int users;
1126              bool going_away;
1127      
1128              struct device dev;
1129      
1130              struct list_head       h_list;
1131              struct list_head       node;
1132              };
和前面分析的其他設(shè)備的創(chuàng)建一樣,input_allocate_device函數(shù)為input_dev分配內(nèi)存空間,出始化其內(nèi)嵌的device,這里還初始化了input_dev結(jié)構(gòu)中的h_list和node鏈表頭,node是用于將該input_dev掛到input_dev_list上,而h_list指向的量表用于存放input_handle,在后面分析將會看到這點。
input_dev結(jié)構(gòu)里邊眾多的其他字段先不理會,等用到時再做分析。

創(chuàng)建了input_dev后,根據(jù)具體的驅(qū)動程序情況對input_dev進行相應(yīng)的設(shè)置(如在鍵盤驅(qū)動的分析中,調(diào)用了atkbd_set_device_attrs函數(shù)等)后,就可以調(diào)用input_register_device函數(shù)向輸入子系統(tǒng)注冊input_dev了,函數(shù)如下:
1503       int input_register_device(struct input_dev *dev)
1504       {
1505              static atomic_t input_no = ATOMIC_INIT(0);
1506              struct input_handler *handler;
1507              const char *path;
1508              int error;
1509      
1510              __set_bit(EV_SYN, dev->evbit);
1511      
1512              /*
1513              * If delay and period are pre-set by the driver, then autorepeating
1514              * is handled by the driver itself and we don't do it in input.c.
1515              */
1516      
1517              init_timer(&dev->timer);
1518              if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
1519                     dev->timer.data = (long) dev;
1520                     dev->timer.function = input_repeat_key;
1521                     dev->rep[REP_DELAY] = 250;
1522                     dev->rep[REP_PERIOD] = 33;
1523              }
1524      
1525              if (!dev->getkeycode)
1526                     dev->getkeycode = input_default_getkeycode;
1527      
1528              if (!dev->setkeycode)
1529                     dev->setkeycode = input_default_setkeycode;
1530      
1531              dev_set_name(&dev->dev, "input%ld",
1532                          (unsigned long) atomic_inc_return(&input_no) - 1);
1533      
1534              error = device_add(&dev->dev);
1535              if (error)
1536                     return error;
1537      
1538              path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
1539              printk(KERN_INFO "input: %s as %s\n",
1540                     dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
1541              kfree(path);
1542      
1543              error = mutex_lock_interruptible(&input_mutex);
1544              if (error) {
1545                     device_del(&dev->dev);
1546                     return error;
1547              }
1548      
1549              list_add_tail(&dev->node, &input_dev_list);
1550      
1551              list_for_each_entry(handler, &input_handler_list, node)
1552                     input_attach_handler(dev, handler);
1553      
1554              input_wakeup_procfs_readers();
1555      
1556              mutex_unlock(&input_mutex);
1557      
1558              return 0;
1559       }
1525~1529行,如果調(diào)用input_register_device前沒有為input_dev的getkeycode和setkeycode函數(shù)指針設(shè)值,則用input_default_getkeycode和input_default_setkeycode賦給他們,getkeycode和setkeycode是在上報事件的處理中用于獲得和設(shè)置相應(yīng)的鍵值,看下這兩個函數(shù):
0560       static int input_default_getkeycode(struct input_dev *dev,
0561                                       int scancode, int *keycode)
0562       {
0563              if (!dev->keycodesize)
0564                     return -EINVAL;
0565      
0566              if (scancode >= dev->keycodemax)
0567                     return -EINVAL;
0568      
0569              *keycode = input_fetch_keycode(dev, scancode);
0570      
0571              return 0;
0572       }

0546       static int input_fetch_keycode(struct input_dev *dev, int scancode)
0547       {
0548              switch (dev->keycodesize) {
0549                     case 1:
0550                            return ((u8 *)dev->keycode)[scancode];
0551      
0552                     case 2:
0553                            return ((u16 *)dev->keycode)[scancode];
0554      
0555                     default:
0556                            return ((u32 *)dev->keycode)[scancode];
0557              }
0558       }

0574       static int input_default_setkeycode(struct input_dev *dev,
0575                                       int scancode, int keycode)
0576       {
0577              int old_keycode;
0578              int i;
0579      
0580              if (scancode >= dev->keycodemax)
0581                     return -EINVAL;
0582      
0583              if (!dev->keycodesize)
0584                     return -EINVAL;
0585      
0586              if (dev->keycodesize > (dev->keycodesize * 8)))
0587                     return -EINVAL;
0588      
0589              switch (dev->keycodesize) {
0590                     case 1: {
0591                            u8 *k = (u8 *)dev->keycode;
0592                            old_keycode = k[scancode];
0593                            k[scancode] = keycode;
0594                            break;
0595                     }
0596                     case 2: {
0597                            u16 *k = (u16 *)dev->keycode;
0598                            old_keycode = k[scancode];
0599                            k[scancode] = keycode;
0600                            break;
0601                     }
0602                     default: {
0603                            u32 *k = (u32 *)dev->keycode;
0604                            old_keycode = k[scancode];
0605                            k[scancode] = keycode;
0606                            break;
0607                     }
0608              }
0609      
0610              clear_bit(old_keycode, dev->keybit);
0611              set_bit(keycode, dev->keybit);
0612      
0613              for (i = 0; i keycodemax; i++) {
0614                     if (input_fetch_keycode(dev, i) == old_keycode) {
0615                            set_bit(old_keycode, dev->keybit);
0616                            break; /* Setting the bit twice is useless, so break */
0617                     }
0618              }
0619      
0620              return 0;
0621       }
不難看出,如上面分析一樣input_default_getkeycode通過scancode索引在鍵值表中查到相應(yīng)的值并賦給*keycode;input_default_setkeycode函數(shù)則重新設(shè)置輸入索引的鍵值表的值。
接著看input_register_device函數(shù),第1534行調(diào)用device_add函數(shù)注冊input_dev內(nèi)嵌的device,獲得互斥鎖后,1549行調(diào)用list_add_tail(&dev->node, &input_dev_list)將該input_dev掛到input_dev_list鏈表上。
接著1551~1552行掃面input_handler_list上的每個handler,用input_attach_handler函數(shù)進行dev和handler的匹配,這里input_handler_list上的handler是什么時候掛上去的,我們在后面再分析,繼續(xù)分析input_attach_handler函數(shù):
0739       static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
0740       {
0741              const struct input_device_id *id;
0742              int error;
0743      
0744              if (handler->blacklist && input_match_device(handler->blacklist, dev))
0745                     return -ENODEV;
0746      
0747              id = input_match_device(handler->id_table, dev);
0748              if (!id)
0749                     return -ENODEV;
0750      
0751              error = handler->connect(handler, dev, id);
0752              if (error && error != -ENODEV)
0753                     printk(KERN_ERR
0754                            "input: failed to attach handler %s to device %s, "
0755                            "error: %d\n",
0756                            handler->name, kobject_name(&dev->dev.kobj), error);
0757      
0758              return error;
0759       }
第0744行先匹配blacklist和dev,如果匹配成功則返回-ENODEV,這里明顯屏蔽掉了blacklist列表上的設(shè)備,即使其在handler->id_table中能匹配成功。
第0747行匹配handler->id_table 和dev,如果匹配成功則調(diào)用handler的connect函數(shù)。
input_device_id結(jié)構(gòu)定義如下:
0312       struct input_device_id {
0313      
0314              kernel_ulong_t flags;
0315      
0316              __u16 bustype;
0317              __u16 vendor;
0318              __u16 product;
0319              __u16 version;
0320      
0321              kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
0322              kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
0323              kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
0324              kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
0325              kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
0326              kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
0327              kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
0328              kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
0329              kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
0330      
0331              kernel_ulong_t driver_info;
0332       };
接著看這個匹配過程:
0700       static const struct input_device_id *input_match_device(const struct input_device_id *id,
0701                                                        struct input_dev *dev)
0702       {
0703              int i;
0704      
0705              for (; id->flags || id->driver_info; id++) {
0706      
0707                     if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
0708                            if (id->bustype != dev->id.bustype)
0709                                   continue;
0710      
0711                     if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
0712                            if (id->vendor != dev->id.vendor)
0713                                   continue;
0714      
0715                     if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
0716                            if (id->product != dev->id.product)
0717                                   continue;
0718      
0719                     if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
0720                            if (id->version != dev->id.version)
0721                                   continue;
0722      
0723                     MATCH_BIT(evbit,  EV_MAX);
0724                     MATCH_BIT(keybit, KEY_MAX);
0725                     MATCH_BIT(relbit, REL_MAX);
0726                     MATCH_BIT(absbit, ABS_MAX);
0727                     MATCH_BIT(mscbit, MSC_MAX);
0728                     MATCH_BIT(ledbit, LED_MAX);
0729                     MATCH_BIT(sndbit, SND_MAX);
0730                     MATCH_BIT(ffbit,  FF_MAX);
0731                     MATCH_BIT(swbit,  SW_MAX);
0732      
0733                     return id;
0734              }
0735      
0736              return NULL;
0737       }
只要設(shè)置了id->driver_info ,for循環(huán)就會執(zhí)行,id->flags標示按需要匹配的字段,0723~0731行MATCH_BIT部分是必須匹配部分,看看這個宏定義:
0693       #define MATCH_BIT(bit, max) \
0694                     for (i = 0; i
0695                            if ((id->bit & dev->bit) != id->bit) \
0696                                   break; \
0697                     if (i != BITS_TO_LONGS(max)) \
0698                            continue;
可以看出如果id->bit有設(shè)值,要匹配成功dev->bit也必須設(shè)置相應(yīng)的值;如果id->bit沒設(shè)值,則該項不需要匹配。
接著input_register_device 函數(shù)第1554行input_wakeup_procfs_readers()函數(shù):
0768       static inline void input_wakeup_procfs_readers(void)
0769       {
0770              input_devices_state++;
0771              wake_up(&input_devices_poll_wait);
0772       }
自增input_devices_state并喚醒在文件操作poll上阻塞的進程,input_devices_state是用于更新相應(yīng)文件file的f_version。
input_register_device 函數(shù)接著釋放信號后返回。
Input設(shè)備的注冊就分析到這里。

接下一篇文章。


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u3/92745/showart_2169770.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP