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