]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/MouseHid.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMouseAbsolutePointerDxe / MouseHid.c
CommitLineData
09f72ae8 1/** @file\r
67b8a9ce 2 Helper functions to parse HID report descriptor and items.\r
09f72ae8 3\r
cd5ebaa0 4Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-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
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
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 32UINT8 *\r
67b8a9ce 33GetNextHidItem (\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 132UINT32\r
133GetItemData (\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 162VOID\r
67b8a9ce 163ParseHidItem (\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
241EFI_STATUS\r
242ParseMouseReportDescriptor (\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