]>
Commit | Line | Data |
---|---|---|
09f72ae8 | 1 | /** @file\r |
67b8a9ce | 2 | Helper functions to parse HID report descriptor and items.\r |
09f72ae8 | 3 | \r |
cd5ebaa0 | 4 | Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r |
9d510e61 | 5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
09f72ae8 | 6 | \r |
09f72ae8 | 7 | **/\r |
8 | \r | |
67b8a9ce | 9 | #include "UsbMouseAbsolutePointer.h"\r |
09f72ae8 | 10 | \r |
09f72ae8 | 11 | \r |
12 | /**\r | |
67b8a9ce | 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 | |
09f72ae8 | 23 | \r |
67b8a9ce | 24 | @param StartPos Start position of the HID item to get.\r |
d2286747 | 25 | @param EndPos End position of the range to get the next HID item.\r |
67b8a9ce | 26 | @param HidItem Buffer for the HID Item to return.\r |
09f72ae8 | 27 | \r |
67b8a9ce | 28 | @return Pointer to end of the HID item returned.\r |
29 | NULL if no HID item retrieved.\r | |
09f72ae8 | 30 | \r |
31 | **/\r | |
09f72ae8 | 32 | UINT8 *\r |
67b8a9ce | 33 | GetNextHidItem (\r |
09f72ae8 | 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 | |
67b8a9ce | 41 | if (EndPos <= StartPos) {\r |
09f72ae8 | 42 | return NULL;\r |
43 | }\r | |
44 | \r | |
45 | Temp = *StartPos;\r | |
46 | StartPos++;\r | |
67b8a9ce | 47 | \r |
09f72ae8 | 48 | //\r |
67b8a9ce | 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 | |
09f72ae8 | 53 | //\r |
67b8a9ce | 54 | HidItem->Type = BitFieldRead8 (Temp, 2, 3);\r |
55 | HidItem->Tag = BitFieldRead8 (Temp, 4, 7);\r | |
09f72ae8 | 56 | \r |
57 | if (HidItem->Tag == HID_ITEM_TAG_LONG) {\r | |
58 | //\r | |
67b8a9ce | 59 | // Long Items are not supported, although we try to parse it.\r |
09f72ae8 | 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 | |
67b8a9ce | 75 | HidItem->Size = BitFieldRead8 (Temp, 0, 1);\r |
09f72ae8 | 76 | \r |
67b8a9ce | 77 | switch (HidItem->Size) {\r |
09f72ae8 | 78 | case 0:\r |
79 | //\r | |
80 | // No data\r | |
81 | //\r | |
82 | return StartPos;\r | |
83 | \r | |
84 | case 1:\r | |
85 | //\r | |
67b8a9ce | 86 | // 1-byte data\r |
09f72ae8 | 87 | //\r |
88 | if ((EndPos - StartPos) >= 1) {\r | |
4140a663 | 89 | HidItem->Data.Uint8 = *StartPos++;\r |
09f72ae8 | 90 | return StartPos;\r |
91 | }\r | |
92 | \r | |
93 | case 2:\r | |
94 | //\r | |
67b8a9ce | 95 | // 2-byte data\r |
09f72ae8 | 96 | //\r |
97 | if ((EndPos - StartPos) >= 2) {\r | |
4140a663 | 98 | CopyMem (&HidItem->Data.Uint16, StartPos, sizeof (UINT16));\r |
09f72ae8 | 99 | StartPos += 2;\r |
100 | return StartPos;\r | |
101 | }\r | |
102 | \r | |
103 | case 3:\r | |
104 | //\r | |
67b8a9ce | 105 | // 4-byte data, adjust size\r |
09f72ae8 | 106 | //\r |
67b8a9ce | 107 | HidItem->Size = 4;\r |
09f72ae8 | 108 | if ((EndPos - StartPos) >= 4) {\r |
4140a663 | 109 | CopyMem (&HidItem->Data.Uint32, StartPos, sizeof (UINT32));\r |
09f72ae8 | 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 | |
67b8a9ce | 121 | Get data from HID item.\r |
122 | \r | |
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 | |
09f72ae8 | 126 | \r |
67b8a9ce | 127 | @param HidItem Pointer to the HID item.\r |
09f72ae8 | 128 | \r |
67b8a9ce | 129 | @return The data of HID item.\r |
09f72ae8 | 130 | \r |
131 | **/\r | |
09f72ae8 | 132 | UINT32\r |
133 | GetItemData (\r | |
134 | IN HID_ITEM *HidItem\r | |
135 | )\r | |
136 | {\r | |
137 | //\r | |
67b8a9ce | 138 | // Get data from HID item.\r |
09f72ae8 | 139 | //\r |
140 | switch (HidItem->Size) {\r | |
09f72ae8 | 141 | case 1:\r |
4140a663 | 142 | return HidItem->Data.Uint8;\r |
09f72ae8 | 143 | case 2:\r |
4140a663 | 144 | return HidItem->Data.Uint16;\r |
09f72ae8 | 145 | case 4:\r |
4140a663 | 146 | return HidItem->Data.Uint32;\r |
09f72ae8 | 147 | }\r |
09f72ae8 | 148 | return 0;\r |
149 | }\r | |
150 | \r | |
09f72ae8 | 151 | /**\r |
67b8a9ce | 152 | Parse HID item from report descriptor.\r |
09f72ae8 | 153 | \r |
67b8a9ce | 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 | |
09f72ae8 | 157 | \r |
67b8a9ce | 158 | @param UsbMouse The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV\r |
159 | @param HidItem The HID item to parse\r | |
09f72ae8 | 160 | \r |
161 | **/\r | |
09f72ae8 | 162 | VOID\r |
67b8a9ce | 163 | ParseHidItem (\r |
164 | IN USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouse,\r | |
165 | IN HID_ITEM *HidItem\r | |
09f72ae8 | 166 | )\r |
167 | {\r | |
67b8a9ce | 168 | UINT8 Data;\r |
09f72ae8 | 169 | \r |
67b8a9ce | 170 | switch (HidItem->Type) {\r |
171 | \r | |
172 | case HID_ITEM_TYPE_MAIN:\r | |
09f72ae8 | 173 | //\r |
67b8a9ce | 174 | // we don't care any main items, just skip\r |
09f72ae8 | 175 | //\r |
176 | return ;\r | |
09f72ae8 | 177 | \r |
67b8a9ce | 178 | case HID_ITEM_TYPE_GLOBAL:\r |
179 | //\r | |
180 | // For global items, we only care Usage Page tag for Button Page here\r | |
181 | //\r | |
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 | |
09f72ae8 | 192 | \r |
67b8a9ce | 193 | case HID_ITEM_TYPE_LOCAL:\r |
194 | if (HidItem->Size == 0) {\r | |
09f72ae8 | 195 | //\r |
67b8a9ce | 196 | // No expected data for local item\r |
09f72ae8 | 197 | //\r |
198 | return ;\r | |
67b8a9ce | 199 | }\r |
09f72ae8 | 200 | \r |
67b8a9ce | 201 | Data = (UINT8) GetItemData (HidItem);\r |
09f72ae8 | 202 | \r |
67b8a9ce | 203 | switch (HidItem->Tag) {\r |
204 | case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:\r | |
205 | if (UsbMouse->PrivateData.ButtonDetected) {\r | |
206 | UsbMouse->PrivateData.ButtonMinIndex = Data;\r | |
09f72ae8 | 207 | }\r |
09f72ae8 | 208 | return ;\r |
209 | \r | |
67b8a9ce | 210 | case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:\r |
09f72ae8 | 211 | {\r |
67b8a9ce | 212 | if (UsbMouse->PrivateData.ButtonDetected) {\r |
213 | UsbMouse->PrivateData.ButtonMaxIndex = Data;\r | |
09f72ae8 | 214 | }\r |
09f72ae8 | 215 | return ;\r |
216 | }\r | |
09f72ae8 | 217 | \r |
67b8a9ce | 218 | default:\r |
09f72ae8 | 219 | return ;\r |
220 | }\r | |
09f72ae8 | 221 | }\r |
222 | }\r | |
223 | \r | |
224 | \r | |
09f72ae8 | 225 | /**\r |
67b8a9ce | 226 | Parse Mouse Report Descriptor.\r |
09f72ae8 | 227 | \r |
67b8a9ce | 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_ABSOLUTE_POINTER_DEV.\r | |
09f72ae8 | 232 | \r |
67b8a9ce | 233 | @param UsbMouseAbsolutePointer The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV\r |
234 | @param ReportDescriptor Report descriptor to parse\r | |
235 | @param ReportSize Report descriptor size\r | |
09f72ae8 | 236 | \r |
67b8a9ce | 237 | @retval EFI_SUCCESS Report descriptor successfully parsed.\r |
238 | @retval EFI_UNSUPPORTED Report descriptor contains long item.\r | |
09f72ae8 | 239 | \r |
240 | **/\r | |
241 | EFI_STATUS\r | |
242 | ParseMouseReportDescriptor (\r | |
67b8a9ce | 243 | OUT USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointer,\r |
244 | IN UINT8 *ReportDescriptor,\r | |
245 | IN UINTN ReportSize\r | |
09f72ae8 | 246 | )\r |
247 | {\r | |
248 | UINT8 *DescriptorEnd;\r | |
67b8a9ce | 249 | UINT8 *Ptr;\r |
09f72ae8 | 250 | HID_ITEM HidItem;\r |
251 | \r | |
252 | DescriptorEnd = ReportDescriptor + ReportSize;\r | |
253 | \r | |
67b8a9ce | 254 | Ptr = GetNextHidItem (ReportDescriptor, DescriptorEnd, &HidItem);\r |
255 | while (Ptr != NULL) {\r | |
09f72ae8 | 256 | if (HidItem.Format != HID_ITEM_FORMAT_SHORT) {\r |
257 | //\r | |
67b8a9ce | 258 | // Long Item is not supported at current HID revision\r |
09f72ae8 | 259 | //\r |
67b8a9ce | 260 | return EFI_UNSUPPORTED;\r |
09f72ae8 | 261 | }\r |
262 | \r | |
263 | ParseHidItem (UsbMouseAbsolutePointer, &HidItem);\r | |
264 | \r | |
67b8a9ce | 265 | Ptr = GetNextHidItem (Ptr, DescriptorEnd, &HidItem);\r |
09f72ae8 | 266 | }\r |
267 | \r | |
67b8a9ce | 268 | UsbMouseAbsolutePointer->NumberOfButtons = (UINT8) (UsbMouseAbsolutePointer->PrivateData.ButtonMaxIndex - UsbMouseAbsolutePointer->PrivateData.ButtonMinIndex + 1);\r |
269 | UsbMouseAbsolutePointer->XLogicMax = 1023;\r | |
270 | UsbMouseAbsolutePointer->YLogicMax = 1023;\r | |
271 | UsbMouseAbsolutePointer->XLogicMin = -1023;\r | |
272 | UsbMouseAbsolutePointer->YLogicMin = -1023;\r | |
09f72ae8 | 273 | \r |
274 | return EFI_SUCCESS;\r | |
275 | }\r |