usb2-键盘里的hid

时间:2021-01-22 17:56:36
键盘设备和主机的hid规范
      /*键盘发送给PC的数据每次8个字节
      data0 data1 data2 data3 data4 data5 data6 data7 
      定义分别是:
      data0 --
      |--bit0: Left Control是否按下,按下为1
      |--bit1: Left Shift 是否按下,按下为1
      |--bit2: Left Alt 是否按下,按下为1
      |--bit3: Left GUI 是否按下,按下为1
      |--bit4: Right Control是否按下,按下为1
      |--bit5: Right Shift 是否按下,按下为1
      |--bit6: Right Alt 是否按下,按下为1
      |--bit7: Right GUI 是否按下,按下为1
      data1 -- 保留
      data2--data7 -- 普通按键
refer to hid spec 8.3*/
看一下hid规范的键盘码-refer to hid usage table section 10
Table 12: Keyboard/Keypad Page      
Usage ID (Dec) Usage ID (Hex)     Usage Name Ref: Typical AT-101 Position PC-AT Mac UNI X Boot      
0     00     Reserved (no event indicated)9     N/A     √     √     √ 4/101/104      
1     01     Keyboard ErrorRollOver9     N/A     √     √     √ 4/101/104      
2     02     Keyboard POSTFail9     N/A     √     √     √ 4/101/104      
3     03     Keyboard ErrorUndefined9     N/A     √     √     √ 4/101/104      
4     04     Keyboard a and A4     31     √     √     √ 4/101/104      
5     05     Keyboard b and B     50     √     √     √ 4/101/104      
6     06     Keyboard c and C4     48     √     √     √ 4/101/104      
7     07     Keyboard d and D     33     √     √     √ 4/101/104      
8     08     Keyboard e and E     19     √     √     √ 4/101/104      
9     09     Keyboard f and F     34     √     √     √ 4/101/104      
10     0A     Keyboard g and G     35     √     √     √ 4/101/104      
11     0B     Keyboard h and H     36     √     √     √ 4/101/104      
12     0C     Keyboard i and I     24     √     √     √ 4/101/104      
13     0D     Keyboard j and J     37     √     √     √ 4/101/104      
14     0E     Keyboard k and K     38     √     √     √ 4/101/104      
15     0F     Keyboard l and L     39     √     √     √ 4/101/104      
16     10     Keyboard m and M4     52     √     √     √ 4/101/104      
17     11     Keyboard n and N     51     √     √     √ 4/101/104      
18     12     Keyboard o and O4     25     √     √     √ 4/101/104      
19     13     Keyboard p and P4     26     √     √     √ 4/101/104      
20     14     Keyboard q and Q4     17     √     √     √ 4/101/104      

21     15     Keyboard r and R     20     √     √     √ 4/101/104      
22     16     Keyboard s and S4     32     √     √     √ 4/101/104      
23     17     Keyboard t and T     21     √     √     √ 4/101/104      
24     18     Keyboard u and U     23     √     √     √ 4/101/104      
25     19     Keyboard v and V     49     √     √     √ 4/101/104      
26     1A     Keyboard w and W4     18     √     √     √ 4/101/104      
27     1B     Keyboard x and X4     47     √     √     √ 4/101/104      
28     1C     Keyboard y and Y4     22     √     √     √ 4/101/104      
29     1D     Keyboard z and Z4     46     √     √     √ 4/101/104      
30     1E     Keyboard 1 and !4     2     √     √     √ 4/101/104      
31     1F     Keyboard 2 and @4     3     √     √     √ 4/101/104      
32     20     Keyboard 3 and #4     4     √     √     √ 4/101/104      
33     21     Keyboard 4 and $4     5     √     √     √ 4/101/104      
34     22     Keyboard 5 and %4     6     √     √     √ 4/101/104      
35     23     Keyboard 6 and ^4     7     √     √     √ 4/101/104      
36     24     Keyboard 7 and &4     8     √     √     √ 4/101/104      
37     25     Keyboard 8 and *4     9     √     √     √ 4/101/104      
38     26     Keyboard 9 and (4     10     √     √     √ 4/101/104      
39     27     Keyboard 0 and )4     11     √     √     √ 4/101/104      
40     28     Keyboard Return (ENTER)5     43     √     √     √ 4/101/104      
41     29     Keyboard ESCAPE     110     √     √     √ 4/101/104      
42     2A     Keyboard DELETE (Backspace)13     15     √     √     √ 4/101/104      
43     2B     Keyboard Tab     16     √     √     √ 4/101/104      
44     2C     Keyboard Spacebar     61     √     √     √ 4/101/104      
45     2D     Keyboard - and (underscore)4     12     √     √     √ 4/101/104      
46     2E     Keyboard = and +4     13     √     √     √ 4/101/104      
47     2F     Keyboard [ and {4     27     √     √     √ 4/101/104      
48     30     Keyboard ] and }4     28     √     √     √ 4/101/104      
49     31     Keyboard \ and |     29     √     √     √ 4/101/104      
50     32     Keyboard Non-US # and ~2     42     √     √     √ 4/101/104      
51     33     Keyboard ; and :4     40     √     √     √ 4/101/104      
52     34     Keyboard ‘ and “4     41     √     √     √ 4/101/104      
53     35     Keyboard Grave Accent and Tilde4     1     √     √     √ 4/101/104      
54     36     Keyboard, and <4     53     √     √     √ 4/101/104      
55     37     Keyboard . and >4     54     √     √     √ 4/101/104      
56     38     Keyboard / and ?4     55     √     √     √ 4/101/104      
57     39     Keyboard Caps Lock11     30     √     √     √ 4/101/104      
58     3A     Keyboard F1     112     √     √     √ 4/101/104      

59     3B     Keyboard F2     113     √     √     √ 4/101/104      
60     3C     Keyboard F3     114     √     √     √ 4/101/104      
61     3D     Keyboard F4     115     √     √     √ 4/101/104      
62     3E     Keyboard F5     116     √     √     √ 4/101/104      
63     3F     Keyboard F6     117     √     √     √ 4/101/104      
64     40     Keyboard F7     118     √     √     √ 4/101/104      
65     41     Keyboard F8     119     √     √     √ 4/101/104      
66     42     Keyboard F9     120     √     √     √ 4/101/104      
67     43     Keyboard F10     121     √     √     √ 4/101/104      
68     44     Keyboard F11     122     √     √     √ 101/104      
69     45     Keyboard F12     123     √     √     √ 101/104      
70     46     Keyboard PrintScreen1     124     √     √     √ 101/104      
71     47     Keyboard Scroll Lock11     125     √     √     √ 4/101/104      
72     48     Keyboard Pause1     126     √     √     √ 101/104      
73     49     Keyboard Insert1     75     √     √     √ 101/104      
74     4A     Keyboard Home1     80     √     √     √ 101/104      
75     4B     Keyboard PageUp1     85     √     √     √ 101/104      
76     4C     Keyboard Delete Forward1;14     76     √     √     √ 101/104      
77     4D     Keyboard End1     81     √     √     √ 101/104      
78     4E     Keyboard PageDown1     86     √     √     √ 101/104      
79     4F     Keyboard RightArrow1     89     √     √     √ 101/104      
80     50     Keyboard LeftArrow1     79     √     √     √ 101/104      
81     51     Keyboard DownArrow1     84     √     √     √ 101/104      
82     52     Keyboard UpArrow1     83     √     √     √ 101/104      
83     53     Keypad Num Lock and Clear11     90     √     √     √ 101/104      
84     54     Keypad /1     95     √     √     √ 101/104      
85     55     Keypad *     100     √     √     √ 4/101/104      
86     56     Keypad -     105     √     √     √ 4/101/104      
87     57     Keypad +     106     √     √     √ 4/101/104      
88     58     Keypad ENTER5     108     √     √     √ 101/104      
89     59     Keypad 1 and End     93     √     √     √ 4/101/104      
90     5A     Keypad 2 and Down Arrow     98     √     √     √ 4/101/104      
91     5B     Keypad 3 and PageDn     103     √     √     √ 4/101/104      
92     5C     Keypad 4 and Left Arrow     92     √     √     √ 4/101/104      
93     5D     Keypad 5     97     √     √     √ 4/101/104      
94     5E     Keypad 6 and Right Arrow     102     √     √     √ 4/101/104      
95     5F     Keypad 7 and Home     91     √     √     √ 4/101/104      
96     60     Keypad 8 and Up Arrow     96     √     √     √ 4/101/104      

97     61     Keypad 9 and PageUp     101     √     √     √ 4/101/104      
98     62     Keypad 0 and Insert     99     √     √     √ 4/101/104      
99     63     Keypad . and Delete     104     √     √     √ 4/101/104      
100     64     Keyboard Non-US \ and |3;6     45     √     √     √ 4/101/104      
101     65     Keyboard Application10     129     √         √ 104      
102     66     Keyboard Power9             √     √      
103     67     Keypad =             √          
104     68     Keyboard F13             √          
105     69     Keyboard F14             √          
106     6A     Keyboard F15             √          
107     6B     Keyboard F16                      
108     6C     Keyboard F17                      
109     6D     Keyboard F18                      
110     6E     Keyboard F19                      
111     6F     Keyboard F20                      
112     70     Keyboard F21                      
113     71     Keyboard F22                      
114     72     Keyboard F23                      
115     73     Keyboard F24                      
116     74     Keyboard Execute                 √      
117     75     Keyboard Help                 √      
118     76     Keyboard Menu                 √      
119     77     Keyboard Select                 √      
120     78     Keyboard Stop                 √      
121     79     Keyboard Again                 √      
122     7A     Keyboard Undo                 √      
123     7B     Keyboard Cut                 √      
124     7C     Keyboard Copy                 √      
125     7D     Keyboard Paste                 √      
126     7E     Keyboard Find                 √      
127     7F     Keyboard Mute                 √      
128     80     Keyboard Volume Up                 √      
129     81     Keyboard Volume Down                 √      
130     82     Keyboard Locking Caps Lock12                 √      
131     83     Keyboard Locking Num Lock12                 √      
132     84     Keyboard Locking Scroll Lock12                 √      
133     85     Keypad Comma27     107                  
134     86     Keypad Equal Sign29                      

135     87     Keyboard International115,28     56      
136     88     Keyboard International216          
137     89     Keyboard International317          
138     8A     Keyboard International418          
139     8B     Keyboard International519          
140     8C     Keyboard International620          
141     8D     Keyboard International721          
142     8E     Keyboard International822          
143     8F     Keyboard International922          
144     90     Keyboard LANG125          
145     91     Keyboard LANG226          
146     92     Keyboard LANG330          
147     93     Keyboard LANG431          
148     94     Keyboard LANG532          
149     95     Keyboard LANG68          
150     96     Keyboard LANG78          
151     97     Keyboard LANG88          
152     98     Keyboard LANG98          
153     99     Keyboard Alternate Erase7          
154     9A     Keyboard SysReq/Attention1          
155     9B     Keyboard Cancel          
156     9C     Keyboard Clear          
157     9D     Keyboard Prior          
158     9E     Keyboard Return          
159     9F     Keyboard Separator          
160     A0     Keyboard Out          
161     A1     Keyboard Oper          
162     A2     Keyboard Clear/Again          
163     A3     Keyboard CrSel/Props          
164     A4     Keyboard ExSel          
165-175     A5-CF     Reserved          
176     B0     Keypad 00          
177     B1     Keypad 000          
178     B2     Thousands Separator 33          
179     B3     Decimal Separator 33          
180     B4     Currency Unit 34          
181     B5     Currency Sub-unit 34          
182     B6     Keypad (          

183     B7     Keypad )      
184     B8     Keypad {      
185     B9     Keypad }      
186     BA     Keypad Tab      
187     BB     Keypad Backspace      
188     BC     Keypad A      
189     BD     Keypad B      
190     BE     Keypad C      
191     BF     Keypad D      
192     C0     Keypad E      
193     C1     Keypad F      
194     C2     Keypad XOR      
195     C3     Keypad ^      
196     C4     Keypad %      
197     C5     Keypad <      
198     C6     Keypad >      
199     C7     Keypad &      
200     C8     Keypad &&      
201     C9     Keypad |      
202     CA     Keypad ||      
203     CB     Keypad :      
204     CC     Keypad #      
205     CD     Keypad Space      
206     CE     Keypad @      
207     CF     Keypad !      
208     D0     Keypad Memory Store      
209     D1     Keypad Memory Recall      
210     D2     Keypad Memory Clear      
211     D3     Keypad Memory Add      
212     D4     Keypad Memory Subtract      
213     D5     Keypad Memory Multiply      
214     D6     Keypad Memory Divide      
215     D7     Keypad +/-      
216     D8     Keypad Clear      
217     D9     Keypad Clear Entry      
218     DA     Keypad Binary      
219     DB     Keypad Octal      
220     DC     Keypad Decimal      

221     DD     Keypad Hexadecimal                      
222-223     DE-DF     Reserved                      
224     E0     Keyboard LeftControl     58     √     √     √ 4/101/104      
225     E1     Keyboard LeftShift     44     √     √     √ 4/101/104      
226     E2     Keyboard LeftAlt     60     √     √     √ 4/101/104      
227     E3     Keyboard Left GUI10;23     127     √     √     √     104      
228     E4     Keyboard RightControl     64     √     √     √ 101/104      
229     E5     Keyboard RightShift     57     √     √     √ 4/101/104      
230     E6     Keyboard RightAlt     62     √     √     √ 101/104      
231     E7     Keyboard Right GUI10;24     128     √     √     √     104      
232-65535 E8-FFFF     Reserved      



①host side
drivers/hid/usbhid/usbkbd.c中定义了一张表
static const unsigned char usb_kbd_keycode[256] = {
	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,//0
	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,//16
	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,//32
	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,//48
	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,//64
	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,//80
	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,//96
	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,//112
	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,//128
	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//144
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//160
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//176
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//192
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//208
	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,//224
	150,158,159,128,136,177,178,176,142,152,173,140//240-251
};
看看是怎么检测和上报按下释放事件的,在函数static void usb_kbd_irq(struct urb *urb)
/****************************************检测修饰键*********************************************************/
/*每次中断传输都会执行以下检查*/
	for (i = 0; i < 8; i++)
		input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
/*
new是kbd的成员,在usb_kbd_alloc_mem函数中分配8字节内存:kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma),
并且在中断urb初始化函数中usb_fill_int_urb(kbd->irq, dev, pipe, kbd->new, (maxp > 8 ? 8 : maxp), usb_kbd_irq, kbd, endpoint->bInterval);
指定new为urb的缓冲区,即从单片机端点里取得的数据会放在new指向的内存里面,最大为8字节
根据hid规范,从单片机获取的数据的首字节即new[0],其8位分别表示
      new[0] --
      |--bit0: Left Control是否按下,按下为1
      |--bit1: Left Shift 是否按下,按下为1
      |--bit2: Left Alt 是否按下,按下为1
      |--bit3: Left GUI 是否按下,按下为1
      |--bit4: Right Control是否按下,按下为1
      |--bit5: Right Shift 是否按下,按下为1
      |--bit6: Right Alt 是否按下,按下为1
      |--bit7: Right GUI 是否按下,按下为1
(kbd->new[0] >> i) & 1 检测第i位是否为1,如果为1,则上报按键usb_kbd_keycode[i + 224]
例如,若Left Control键按下,则在首次循环中,(kbd->new[0] >> 0) & 1=1,所以上报usb_kbd_keycode[0 + 224],查上面usb_kbd_keycode数组可知,
usb_kbd_keycode[224]=29,即上报键值29
至于29到底是不是代表此键,可以查看输入子系统的键值定义,http://blog.csdn.net/songqqnew/article/details/6875502,发现有行 
 #define KEY_LEFTCTRL        29    
其他类似...

可见通过input_report_key函数关联了3个按键表,总结一下
1.hid规范的键盘码:本页可查到。是设备和主机间的约定,比如上面的例子,板子上有Left Control键按下,单片机就要按hid规范令new[0].0=1,
主机获取到new[0].0=1则就会知道Left control键按下。又如对于鼠标按键,板子中键按下,单片机要按hid规范令data[0]=0x04,主机获取到data[0]=0x04,便知道鼠标的左键按下。当然,鼠标hid和键盘hid的数据格式和含义不一样。
2.input.h里的键盘码:http://blog.csdn.net/songqqnew/article/details/6875502。是input子系统里规定的某个按键按下要上报哪个数值。应该是input子系统和应用程序间的一个约定。
3.usb_kbd_keycode[256]:本页可查到。此数组为了操作方便,用数组下标和对应成员值将hid规范码和input规范码统一起来,对于某个按键
有usb_kbd_keycode[hid规范码]=input规范码
比如按键a:usb_kbd_keycode[4]=30,按键1:usb_kbd_keycode[0x1e]=2
*/

/****************************************检测普通键*********************************************************/
/*每次中断传输都会执行以下检查*/
	for (i = 2; i < 8; i++) {
/*根据hid规范普通按键值处于data[2]-data[7],所以检查new[2]-new[7]获取按键值。在单片机侧是直接在相应字节填入hid规范码,如填入new[5]=0x1e.*/


		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
/*这种情况发生在原来按下的键释放时。
至于>3,可以看hid规范码:有意义的hid规范码从4(字符a)开始。
数组old[]是new[]的一个拷贝,size 8,见最后一行。
*/
/*memscan源码如下
memscan --    Find a character in an area of memory. 
void *memscan(void *addr, int c, size_t size)
{
    unsigned char *p = addr
    while (size) {
        if (*p == c)
            return (void *)p;
        p++;
        size--;
    }
      return (void *)p;
} */   
/*比如单片机发过来数据new[5]=0x1e(按键1),则在i=5时,
在new[2]至new[7]中寻找和old[5]相等的字符,如果相等返回new中相等字符的地址;否则返回new的最后一个元素的下一个地址,实际就是new+8。所以若没找到,
则memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8成立
*/
/*总之,此if做了:检查old[i]值的hid规范合法性,并和新出现的按键值即new[2]--new[7]一一比较,如果新出现的按键值没有old[i],说明old[i]已经被释放了,所以执行以下操作
如果不是新的释放事件,而是原来的键一直处于释放状态,则不会执行下面的操作,说明只会在按键释放瞬间发生按键释放上报事件,而在未按期间不会上报释放事件。*/
			if (usb_kbd_keycode[kbd->old[i]])//old[i]对应的input码有意义,执行以下
				input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);//上报按键释放事件
			else
				dev_info(&urb->dev->dev,
						"Unknown key (scancode %#x) released.\n", kbd->old[i]);
		}


		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
/*这种情况发生在原来释放的键按下时。
此if非彼if,它做了:检查new[i]值的hid规范合法性,并和old[2]--old[7]比较,如果没有一个值和new[i]相等,说明new[i]是新按下的按键,所以执行下面的操作
如果不是新键按下,而是原来的按键一直没有释放,则不会执行下面的操作,说明只会在按键按下时上报按键事件,而按着过程中,不会上报按键事件。
*/			if (usb_kbd_keycode[kbd->new[i]])
				input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);//上报新键按下事件
			else
				dev_info(&urb->dev->dev,
						"Unknown key (scancode %#x) released.\n", kbd->new[i]);
		}
	}


	input_sync(kbd->dev);
	memcpy(kbd->old, kbd->new, 8);//拷贝new到old
/*总之实现了,在按键释放时报告一次释放事件,释放之后不会再报告;在按键按下时会报告一次按下事件,按下之后不会再报告。还算巧妙*/

②device side
单片机装备5个按键k1,k2,k3,k4,k5用来模拟键盘的1, 2, 3, 4, 5键
比如单片机检测到k1按下,会令keyboardvalue[5]=0x1e,代码如下
static INT8U keyboardvalue[8] = {0,0,0,0,0,0,0,0};//和hid规范相应的8个字节,用于发送给主机
int main( void )
{
    INT8U btmp;
	Clock_Init( );
	USB_Init( USB_ENABLE );
	EA = 1;
	while( 1 )
	{
//		keyboardvalue[5] = 0x3D;
//		HID_SendData( keyboardvalue, 8 ); 
        for( btmp = 0; btmp < 8; btmp ++ )
        {   
            keyboardvalue[btmp] = 0;            
        }
        btmp = 1;
        switch( KeyScan( )
        {
            case    K1_PRESS:
                keyboardvalue[5] = 0x1e;//即数字1,参照hid规范码,当然也可使用其他字节,比如 keyboardvalue[2]=0x1e, keyboardvalue[7]=0x1e等
                break;
            case    K2_PRESS:
                keyboardvalue[5] = 0x1f;//数字2
                break;
            case    K3_PRESS:
                keyboardvalue[5] = 0x20;//数字3
                break;
            case    K4_PRESS:
                keyboardvalue[5] = 0x21;//数字4
                break;   
            case    K5_PRESS:
                keyboardvalue[5] = 0x22;//数字5
                break;
            case    K1_RELEASE:
            case    K2_RELEASE:
            case    K3_RELEASE:
            case    K4_RELEASE:
            case    K5_RELEASE:				
                break;
            default:
                btmp = 0;
                break;   
        }						 
        if( btmp )
        {
            HID_SendData( keyboardvalue, 8 );  //发送使能
        }
		IdleMode( );
	}
	return 0;
}