]>
Commit | Line | Data |
---|---|---|
ed838d0c | 1 | /** @file\r |
29129ce4 | 2 | Helper functions to parse HID report descriptor and items.\r |
bb80e3b2 | 3 | \r |
d1102dba | 4 | Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r |
9d510e61 | 5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
ed838d0c | 6 | \r |
ed838d0c | 7 | **/\r |
8 | \r | |
29129ce4 | 9 | #include "UsbMouse.h"\r |
ed838d0c | 10 | \r |
11 | \r | |
ed838d0c | 12 | /**\r |
29129ce4 | 13 | Get next HID item from report descriptor.\r |
14 | \r | |
15 | This function retrieves next HID item from report descriptor, according to\r | |
16 | the start position.\r | |
17 | According to USB HID Specification, An item is piece of information\r | |
18 | about the device. All items have a one-byte prefix that contains\r | |
19 | the item tag, item type, and item size.\r | |
20 | There are two basic types of items: short items and long items.\r | |
21 | If the item is a short item, its optional data size may be 0, 1, 2, or 4 bytes.\r | |
22 | Only short item is supported here.\r | |
ed838d0c | 23 | \r |
29129ce4 | 24 | @param StartPos Start position of the HID item to get.\r |
25 | @param EndPos End position of the range to get the the next HID item.\r | |
26 | @param HidItem Buffer for the HID Item to return.\r | |
ed838d0c | 27 | \r |
29129ce4 | 28 | @return Pointer to end of the HID item returned.\r |
29 | NULL if no HID item retrieved.\r | |
ed838d0c | 30 | \r |
31 | **/\r | |
ed838d0c | 32 | UINT8 *\r |
29129ce4 | 33 | GetNextHidItem (\r |
ed838d0c | 34 | IN UINT8 *StartPos,\r |
35 | IN UINT8 *EndPos,\r | |
36 | OUT HID_ITEM *HidItem\r | |
37 | )\r | |
38 | {\r | |
39 | UINT8 Temp;\r | |
40 | \r | |
29129ce4 | 41 | if (EndPos <= StartPos) {\r |
ed838d0c | 42 | return NULL;\r |
43 | }\r | |
44 | \r | |
45 | Temp = *StartPos;\r | |
46 | StartPos++;\r | |
29129ce4 | 47 | \r |
ed838d0c | 48 | //\r |
29129ce4 | 49 | // Bit format of prefix byte:\r |
50 | // Bits 0-1: Size\r | |
51 | // Bits 2-3: Type\r | |
52 | // Bits 4-7: Tag\r | |
ed838d0c | 53 | //\r |
29129ce4 | 54 | HidItem->Type = BitFieldRead8 (Temp, 2, 3);\r |
55 | HidItem->Tag = BitFieldRead8 (Temp, 4, 7);\r | |
ed838d0c | 56 | \r |
57 | if (HidItem->Tag == HID_ITEM_TAG_LONG) {\r | |
58 | //\r | |
29129ce4 | 59 | // Long Items are not supported, although we try to parse it.\r |
ed838d0c | 60 | //\r |
61 | HidItem->Format = HID_ITEM_FORMAT_LONG;\r | |
62 | \r | |
63 | if ((EndPos - StartPos) >= 2) {\r | |
64 | HidItem->Size = *StartPos++;\r | |
65 | HidItem->Tag = *StartPos++;\r | |
66 | \r | |
67 | if ((EndPos - StartPos) >= HidItem->Size) {\r | |
68 | HidItem->Data.LongData = StartPos;\r | |
69 | StartPos += HidItem->Size;\r | |
70 | return StartPos;\r | |
71 | }\r | |
72 | }\r | |
73 | } else {\r | |
74 | HidItem->Format = HID_ITEM_FORMAT_SHORT;\r | |
29129ce4 | 75 | HidItem->Size = BitFieldRead8 (Temp, 0, 1);\r |
ed838d0c | 76 | \r |
29129ce4 | 77 | switch (HidItem->Size) {\r |
ed838d0c | 78 | case 0:\r |
79 | //\r | |
80 | // No data\r | |
81 | //\r | |
82 | return StartPos;\r | |
83 | \r | |
84 | case 1:\r | |
85 | //\r | |
29129ce4 | 86 | // 1-byte data\r |
ed838d0c | 87 | //\r |
88 | if ((EndPos - StartPos) >= 1) {\r | |
4140a663 | 89 | HidItem->Data.Uint8 = *StartPos++;\r |
ed838d0c | 90 | return StartPos;\r |
91 | }\r | |
92 | \r | |
93 | case 2:\r | |
94 | //\r | |
29129ce4 | 95 | // 2-byte data\r |
ed838d0c | 96 | //\r |
97 | if ((EndPos - StartPos) >= 2) {\r | |
4140a663 | 98 | CopyMem (&HidItem->Data.Uint16, StartPos, sizeof (UINT16));\r |
ed838d0c | 99 | StartPos += 2;\r |
100 | return StartPos;\r | |
101 | }\r | |
102 | \r | |
103 | case 3:\r | |
104 | //\r | |
29129ce4 | 105 | // 4-byte data, adjust size\r |
ed838d0c | 106 | //\r |
29129ce4 | 107 | HidItem->Size = 4;\r |
ed838d0c | 108 | if ((EndPos - StartPos) >= 4) {\r |
4140a663 | 109 | CopyMem (&HidItem->Data.Uint32, StartPos, sizeof (UINT32));\r |
ed838d0c | 110 | StartPos += 4;\r |
111 | return StartPos;\r | |
112 | }\r | |
113 | }\r | |
114 | }\r | |
115 | \r | |
116 | return NULL;\r | |
117 | }\r | |
118 | \r | |
119 | \r | |
120 | /**\r | |
29129ce4 | 121 | Get data from HID item.\r |
ed838d0c | 122 | \r |
29129ce4 | 123 | This function retrieves data from HID item.\r |
124 | It only supports short items, which has 4 types of data:\r | |
125 | 0, 1, 2, or 4 bytes.\r | |
ed838d0c | 126 | \r |
29129ce4 | 127 | @param HidItem Pointer to the HID item.\r |
128 | \r | |
129 | @return The data of HID item.\r | |
ed838d0c | 130 | \r |
131 | **/\r | |
ed838d0c | 132 | UINT32\r |
133 | GetItemData (\r | |
134 | IN HID_ITEM *HidItem\r | |
135 | )\r | |
136 | {\r | |
137 | //\r | |
29129ce4 | 138 | // Get data from HID item.\r |
ed838d0c | 139 | //\r |
140 | switch (HidItem->Size) {\r | |
ed838d0c | 141 | case 1:\r |
4140a663 | 142 | return HidItem->Data.Uint8;\r |
ed838d0c | 143 | case 2:\r |
4140a663 | 144 | return HidItem->Data.Uint16;\r |
ed838d0c | 145 | case 4:\r |
4140a663 | 146 | return HidItem->Data.Uint32;\r |
ed838d0c | 147 | }\r |
ed838d0c | 148 | return 0;\r |
149 | }\r | |
150 | \r | |
ed838d0c | 151 | /**\r |
29129ce4 | 152 | Parse HID item from report descriptor.\r |
ed838d0c | 153 | \r |
29129ce4 | 154 | There are three item types: Main, Global, and Local.\r |
155 | This function parses these types of HID items according\r | |
156 | to tag info.\r | |
d1102dba | 157 | \r |
bb80e3b2 | 158 | @param UsbMouse The instance of USB_MOUSE_DEV\r |
29129ce4 | 159 | @param HidItem The HID item to parse\r |
ed838d0c | 160 | \r |
161 | **/\r | |
ed838d0c | 162 | VOID\r |
29129ce4 | 163 | ParseHidItem (\r |
ed838d0c | 164 | IN USB_MOUSE_DEV *UsbMouse,\r |
29129ce4 | 165 | IN HID_ITEM *HidItem\r |
ed838d0c | 166 | )\r |
167 | {\r | |
29129ce4 | 168 | UINT8 Data;\r |
ed838d0c | 169 | \r |
29129ce4 | 170 | switch (HidItem->Type) {\r |
171 | \r | |
172 | case HID_ITEM_TYPE_MAIN:\r | |
ed838d0c | 173 | //\r |
29129ce4 | 174 | // we don't care any main items, just skip\r |
ed838d0c | 175 | //\r |
29129ce4 | 176 | return;\r |
ed838d0c | 177 | \r |
29129ce4 | 178 | case HID_ITEM_TYPE_GLOBAL:\r |
ed838d0c | 179 | //\r |
29129ce4 | 180 | // For global items, we only care Usage Page tag for Button Page here\r |
ed838d0c | 181 | //\r |
29129ce4 | 182 | if (HidItem->Tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE) {\r |
183 | Data = (UINT8) GetItemData (HidItem);\r | |
184 | if (Data == 0x09) {\r | |
185 | //\r | |
186 | // Button Page\r | |
187 | //\r | |
188 | UsbMouse->PrivateData.ButtonDetected = TRUE;\r | |
189 | }\r | |
190 | }\r | |
191 | return;\r | |
ed838d0c | 192 | \r |
29129ce4 | 193 | case HID_ITEM_TYPE_LOCAL:\r |
194 | if (HidItem->Size == 0) {\r | |
195 | //\r | |
196 | // No expected data for local item\r | |
197 | //\r | |
198 | return ;\r | |
ed838d0c | 199 | }\r |
200 | \r | |
29129ce4 | 201 | Data = (UINT8) GetItemData (HidItem);\r |
ed838d0c | 202 | \r |
29129ce4 | 203 | switch (HidItem->Tag) {\r |
204 | case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:\r | |
ed838d0c | 205 | if (UsbMouse->PrivateData.ButtonDetected) {\r |
29129ce4 | 206 | UsbMouse->PrivateData.ButtonMinIndex = Data;\r |
ed838d0c | 207 | }\r |
ed838d0c | 208 | return ;\r |
ed838d0c | 209 | \r |
29129ce4 | 210 | case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:\r |
ed838d0c | 211 | {\r |
29129ce4 | 212 | if (UsbMouse->PrivateData.ButtonDetected) {\r |
213 | UsbMouse->PrivateData.ButtonMaxIndex = Data;\r | |
ed838d0c | 214 | }\r |
29129ce4 | 215 | return ;\r |
ed838d0c | 216 | }\r |
217 | \r | |
29129ce4 | 218 | default:\r |
219 | return;\r | |
220 | }\r | |
ed838d0c | 221 | }\r |
222 | }\r | |
bb80e3b2 | 223 | \r |
ed838d0c | 224 | \r |
225 | /**\r | |
bb80e3b2 | 226 | Parse Mouse Report Descriptor.\r |
ed838d0c | 227 | \r |
29129ce4 | 228 | According to USB HID Specification, report descriptors are\r |
229 | composed of pieces of information. Each piece of information\r | |
230 | is called an Item. This function retrieves each item from\r | |
231 | the report descriptor and updates USB_MOUSE_DEV.\r | |
232 | \r | |
bb80e3b2 | 233 | @param UsbMouse The instance of USB_MOUSE_DEV\r |
ed838d0c | 234 | @param ReportDescriptor Report descriptor to parse\r |
235 | @param ReportSize Report descriptor size\r | |
236 | \r | |
29129ce4 | 237 | @retval EFI_SUCCESS Report descriptor successfully parsed.\r |
238 | @retval EFI_UNSUPPORTED Report descriptor contains long item.\r | |
ed838d0c | 239 | \r |
240 | **/\r | |
241 | EFI_STATUS\r | |
242 | ParseMouseReportDescriptor (\r | |
29129ce4 | 243 | OUT USB_MOUSE_DEV *UsbMouse,\r |
ed838d0c | 244 | IN UINT8 *ReportDescriptor,\r |
245 | IN UINTN ReportSize\r | |
246 | )\r | |
247 | {\r | |
248 | UINT8 *DescriptorEnd;\r | |
bb80e3b2 | 249 | UINT8 *Ptr;\r |
ed838d0c | 250 | HID_ITEM HidItem;\r |
251 | \r | |
252 | DescriptorEnd = ReportDescriptor + ReportSize;\r | |
253 | \r | |
29129ce4 | 254 | Ptr = GetNextHidItem (ReportDescriptor, DescriptorEnd, &HidItem);\r |
bb80e3b2 | 255 | while (Ptr != NULL) {\r |
ed838d0c | 256 | if (HidItem.Format != HID_ITEM_FORMAT_SHORT) {\r |
257 | //\r | |
29129ce4 | 258 | // Long Item is not supported at current HID revision\r |
ed838d0c | 259 | //\r |
29129ce4 | 260 | return EFI_UNSUPPORTED;\r |
ed838d0c | 261 | }\r |
262 | \r | |
263 | ParseHidItem (UsbMouse, &HidItem);\r | |
264 | \r | |
29129ce4 | 265 | Ptr = GetNextHidItem (Ptr, DescriptorEnd, &HidItem);\r |
ed838d0c | 266 | }\r |
267 | \r | |
29129ce4 | 268 | UsbMouse->NumberOfButtons = (UINT8) (UsbMouse->PrivateData.ButtonMaxIndex - UsbMouse->PrivateData.ButtonMinIndex + 1);\r |
269 | UsbMouse->XLogicMax = 127;\r | |
270 | UsbMouse->YLogicMax = 127;\r | |
271 | UsbMouse->XLogicMin = -127;\r | |
272 | UsbMouse->YLogicMin = -127;\r | |
ed838d0c | 273 | \r |
274 | return EFI_SUCCESS;\r | |
275 | }\r |