]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMouseDxe/MouseHid.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
ed838d0c 11/**\r
29129ce4 12 Get next HID item from report descriptor.\r
13\r
14 This function retrieves next HID item from report descriptor, according to\r
15 the start position.\r
16 According to USB HID Specification, An item is piece of information\r
17 about the device. All items have a one-byte prefix that contains\r
18 the item tag, item type, and item size.\r
19 There are two basic types of items: short items and long items.\r
20 If the item is a short item, its optional data size may be 0, 1, 2, or 4 bytes.\r
21 Only short item is supported here.\r
ed838d0c 22\r
29129ce4 23 @param StartPos Start position of the HID item to get.\r
d2286747 24 @param EndPos End position of the range to get the next HID item.\r
29129ce4 25 @param HidItem Buffer for the HID Item to return.\r
ed838d0c 26\r
29129ce4 27 @return Pointer to end of the HID item returned.\r
28 NULL if no HID item retrieved.\r
ed838d0c 29\r
30**/\r
ed838d0c 31UINT8 *\r
29129ce4 32GetNextHidItem (\r
1436aea4
MK
33 IN UINT8 *StartPos,\r
34 IN UINT8 *EndPos,\r
35 OUT HID_ITEM *HidItem\r
ed838d0c 36 )\r
37{\r
1436aea4 38 UINT8 Temp;\r
ed838d0c 39\r
29129ce4 40 if (EndPos <= StartPos) {\r
ed838d0c 41 return NULL;\r
42 }\r
43\r
44 Temp = *StartPos;\r
45 StartPos++;\r
29129ce4 46\r
ed838d0c 47 //\r
29129ce4 48 // Bit format of prefix byte:\r
49 // Bits 0-1: Size\r
50 // Bits 2-3: Type\r
51 // Bits 4-7: Tag\r
ed838d0c 52 //\r
29129ce4 53 HidItem->Type = BitFieldRead8 (Temp, 2, 3);\r
54 HidItem->Tag = BitFieldRead8 (Temp, 4, 7);\r
ed838d0c 55\r
56 if (HidItem->Tag == HID_ITEM_TAG_LONG) {\r
57 //\r
29129ce4 58 // Long Items are not supported, although we try to parse it.\r
ed838d0c 59 //\r
60 HidItem->Format = HID_ITEM_FORMAT_LONG;\r
61\r
62 if ((EndPos - StartPos) >= 2) {\r
63 HidItem->Size = *StartPos++;\r
64 HidItem->Tag = *StartPos++;\r
65\r
66 if ((EndPos - StartPos) >= HidItem->Size) {\r
67 HidItem->Data.LongData = StartPos;\r
1436aea4 68 StartPos += HidItem->Size;\r
ed838d0c 69 return StartPos;\r
70 }\r
71 }\r
72 } else {\r
73 HidItem->Format = HID_ITEM_FORMAT_SHORT;\r
29129ce4 74 HidItem->Size = BitFieldRead8 (Temp, 0, 1);\r
ed838d0c 75\r
29129ce4 76 switch (HidItem->Size) {\r
1436aea4
MK
77 case 0:\r
78 //\r
79 // No data\r
80 //\r
ed838d0c 81 return StartPos;\r
ed838d0c 82\r
1436aea4
MK
83 case 1:\r
84 //\r
85 // 1-byte data\r
86 //\r
87 if ((EndPos - StartPos) >= 1) {\r
88 HidItem->Data.Uint8 = *StartPos++;\r
89 return StartPos;\r
90 }\r
ed838d0c 91\r
1436aea4
MK
92 case 2:\r
93 //\r
94 // 2-byte data\r
95 //\r
96 if ((EndPos - StartPos) >= 2) {\r
97 CopyMem (&HidItem->Data.Uint16, StartPos, sizeof (UINT16));\r
98 StartPos += 2;\r
99 return StartPos;\r
100 }\r
101\r
102 case 3:\r
103 //\r
104 // 4-byte data, adjust size\r
105 //\r
106 HidItem->Size = 4;\r
107 if ((EndPos - StartPos) >= 4) {\r
108 CopyMem (&HidItem->Data.Uint32, StartPos, sizeof (UINT32));\r
109 StartPos += 4;\r
110 return StartPos;\r
111 }\r
ed838d0c 112 }\r
113 }\r
114\r
115 return NULL;\r
116}\r
117\r
ed838d0c 118/**\r
29129ce4 119 Get data from HID item.\r
ed838d0c 120\r
29129ce4 121 This function retrieves data from HID item.\r
122 It only supports short items, which has 4 types of data:\r
123 0, 1, 2, or 4 bytes.\r
ed838d0c 124\r
29129ce4 125 @param HidItem Pointer to the HID item.\r
126\r
127 @return The data of HID item.\r
ed838d0c 128\r
129**/\r
ed838d0c 130UINT32\r
131GetItemData (\r
1436aea4 132 IN HID_ITEM *HidItem\r
ed838d0c 133 )\r
134{\r
135 //\r
29129ce4 136 // Get data from HID item.\r
ed838d0c 137 //\r
138 switch (HidItem->Size) {\r
1436aea4
MK
139 case 1:\r
140 return HidItem->Data.Uint8;\r
141 case 2:\r
142 return HidItem->Data.Uint16;\r
143 case 4:\r
144 return HidItem->Data.Uint32;\r
ed838d0c 145 }\r
1436aea4 146\r
ed838d0c 147 return 0;\r
148}\r
149\r
ed838d0c 150/**\r
29129ce4 151 Parse HID item from report descriptor.\r
ed838d0c 152\r
29129ce4 153 There are three item types: Main, Global, and Local.\r
154 This function parses these types of HID items according\r
155 to tag info.\r
d1102dba 156\r
bb80e3b2 157 @param UsbMouse The instance of USB_MOUSE_DEV\r
29129ce4 158 @param HidItem The HID item to parse\r
ed838d0c 159\r
160**/\r
ed838d0c 161VOID\r
29129ce4 162ParseHidItem (\r
1436aea4
MK
163 IN USB_MOUSE_DEV *UsbMouse,\r
164 IN HID_ITEM *HidItem\r
ed838d0c 165 )\r
166{\r
29129ce4 167 UINT8 Data;\r
ed838d0c 168\r
29129ce4 169 switch (HidItem->Type) {\r
1436aea4
MK
170 case HID_ITEM_TYPE_MAIN:\r
171 //\r
172 // we don't care any main items, just skip\r
173 //\r
174 return;\r
29129ce4 175\r
1436aea4
MK
176 case HID_ITEM_TYPE_GLOBAL:\r
177 //\r
178 // For global items, we only care Usage Page tag for Button Page here\r
179 //\r
180 if (HidItem->Tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE) {\r
181 Data = (UINT8)GetItemData (HidItem);\r
182 if (Data == 0x09) {\r
183 //\r
184 // Button Page\r
185 //\r
186 UsbMouse->PrivateData.ButtonDetected = TRUE;\r
187 }\r
188 }\r
ed838d0c 189\r
1436aea4
MK
190 return;\r
191\r
192 case HID_ITEM_TYPE_LOCAL:\r
193 if (HidItem->Size == 0) {\r
29129ce4 194 //\r
1436aea4 195 // No expected data for local item\r
29129ce4 196 //\r
1436aea4 197 return;\r
29129ce4 198 }\r
ed838d0c 199\r
1436aea4 200 Data = (UINT8)GetItemData (HidItem);\r
ed838d0c 201\r
1436aea4
MK
202 switch (HidItem->Tag) {\r
203 case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:\r
204 if (UsbMouse->PrivateData.ButtonDetected) {\r
205 UsbMouse->PrivateData.ButtonMinIndex = Data;\r
206 }\r
ed838d0c 207\r
1436aea4 208 return;\r
ed838d0c 209\r
1436aea4
MK
210 case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:\r
211 {\r
212 if (UsbMouse->PrivateData.ButtonDetected) {\r
213 UsbMouse->PrivateData.ButtonMaxIndex = Data;\r
214 }\r
ed838d0c 215\r
1436aea4
MK
216 return;\r
217 }\r
218\r
219 default:\r
220 return;\r
221 }\r
ed838d0c 222 }\r
223}\r
bb80e3b2 224\r
ed838d0c 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
1436aea4
MK
243 OUT USB_MOUSE_DEV *UsbMouse,\r
244 IN UINT8 *ReportDescriptor,\r
245 IN UINTN ReportSize\r
ed838d0c 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
1436aea4
MK
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