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