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