| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
HIDClassHost.c
Go to the documentation of this file.
1 /*
2 * @brief Host mode driver for the library USB HID Class driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * Copyright(C) Dean Camera, 2011, 2012
7 * All rights reserved.
8 *
9 * @par
10 * Software that is described herein is for illustrative purposes only
11 * which provides customers with programming information regarding the
12 * LPC products. This software is supplied "AS IS" without any warranties of
13 * any kind, and NXP Semiconductors and its licensor disclaim any and
14 * all warranties, express or implied, including all implied warranties of
15 * merchantability, fitness for a particular purpose and non-infringement of
16 * intellectual property rights. NXP Semiconductors assumes no responsibility
17 * or liability for the use of the software, conveys no license or rights under any
18 * patent, copyright, mask work right, or any other intellectual property rights in
19 * or to any products. NXP Semiconductors reserves the right to make changes
20 * in the software without notification. NXP Semiconductors also makes no
21 * representation or warranty that such application will be suitable for the
22 * specified use without further testing or modification.
23 *
24 * @par
25 * Permission to use, copy, modify, and distribute this software and its
26 * documentation is hereby granted, under NXP Semiconductors' and its
27 * licensor's relevant copyrights in the software, without fee, provided that it
28 * is used in conjunction with NXP Semiconductors microcontrollers. This
29 * copyright, permission, and disclaimer notice must appear in all copies of
30 * this code.
31 */
32
33
34 #define __INCLUDE_FROM_USB_DRIVER
35 #include "../../Core/USBMode.h"
36
37 #if defined(USB_CAN_BE_HOST)
38
39 #define __INCLUDE_FROM_HID_DRIVER
40 #define __INCLUDE_FROM_HID_HOST_C
41 #include "HIDClassHost.h"
42
43 uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
44 uint16_t ConfigDescriptorSize,
45 void* ConfigDescriptorData)
46 {
47 USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
48 USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
49 USB_Descriptor_Interface_t* HIDInterface = NULL;
50 USB_HID_Descriptor_HID_t* HIDDescriptor = NULL;
51 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
52
53 memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
54
55 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
56 return HID_ENUMERROR_InvalidConfigDescriptor;
57
58 while (!(DataINEndpoint) || !(DataOUTEndpoint))
59 {
60 if (!(HIDInterface) ||
61 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
62 DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
63 {
64 if (DataINEndpoint || DataOUTEndpoint)
65 break;
66
67 do
68 {
69 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
70 DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
71 {
72 return HID_ENUMERROR_NoCompatibleInterfaceFound;
73 }
74
75 HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
76 } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
77 (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
78
79 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
80 DCOMP_HID_Host_NextHIDDescriptor) != DESCRIPTOR_SEARCH_COMP_Found)
81 {
82 return HID_ENUMERROR_NoCompatibleInterfaceFound;
83 }
84
85 HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t);
86
87 DataINEndpoint = NULL;
88 DataOUTEndpoint = NULL;
89
90 continue;
91 }
92
93 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
94
95 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
96 DataINEndpoint = EndpointData;
97 else
98 DataOUTEndpoint = EndpointData;
99 }
100
101 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
102 {
103 uint16_t Size;
104 uint8_t Type;
105 uint8_t Token;
106 uint8_t EndpointAddress;
107 uint8_t InterruptPeriod;
108 bool DoubleBanked;
109
110 if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber)
111 {
112 Size = le16_to_cpu(DataINEndpoint->EndpointSize);
113 EndpointAddress = DataINEndpoint->EndpointAddress;
114 Token = PIPE_TOKEN_IN;
115 Type = EP_TYPE_INTERRUPT;
116 DoubleBanked = HIDInterfaceInfo->Config.DataINPipeDoubleBank;
117 InterruptPeriod = DataINEndpoint->PollingIntervalMS;
118
119 HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
120 }
121 else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber)
122 {
123 if (DataOUTEndpoint == NULL)
124 continue;
125
126 Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
127 EndpointAddress = DataOUTEndpoint->EndpointAddress;
128 Token = PIPE_TOKEN_OUT;
129 Type = EP_TYPE_INTERRUPT;
130 DoubleBanked = HIDInterfaceInfo->Config.DataOUTPipeDoubleBank;
131 InterruptPeriod = DataOUTEndpoint->PollingIntervalMS;
132
133 HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
134 HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
135 }
136 else
137 {
138 continue;
139 }
140
141 if (!(Pipe_ConfigurePipe(portnum,PipeNum, Type, Token, EndpointAddress, Size,
142 DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
143 {
144 return HID_ENUMERROR_PipeConfigurationFailed;
145 }
146
147 if (InterruptPeriod)
148 Pipe_SetInterruptPeriod(InterruptPeriod);
149 }
150
151 HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber;
152 HIDInterfaceInfo->State.HIDReportSize = LE16_TO_CPU(HIDDescriptor->HIDReportLength);
153 HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol);
154 HIDInterfaceInfo->State.LargestReportSize = 8;
155 HIDInterfaceInfo->State.IsActive = true;
156
157 return HID_ENUMERROR_NoError;
158 }
159
160 static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
161 {
162 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
163
164 if (Header->Type == DTYPE_Interface)
165 {
166 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
167
168 if (Interface->Class == HID_CSCP_HIDClass)
169 return DESCRIPTOR_SEARCH_Found;
170 }
171
172 return DESCRIPTOR_SEARCH_NotFound;
173 }
174
175 static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
176 {
177 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
178
179 if (Header->Type == HID_DTYPE_HID)
180 return DESCRIPTOR_SEARCH_Found;
181 else if (Header->Type == DTYPE_Interface)
182 return DESCRIPTOR_SEARCH_Fail;
183 else
184 return DESCRIPTOR_SEARCH_NotFound;
185 }
186
187 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
188 {
189 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
190
191 if (Header->Type == DTYPE_Endpoint)
192 {
193 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
194
195 if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
196 return DESCRIPTOR_SEARCH_Found;
197 }
198 else if (Header->Type == DTYPE_Interface)
199 {
200 return DESCRIPTOR_SEARCH_Fail;
201 }
202
203 return DESCRIPTOR_SEARCH_NotFound;
204 }
205
206 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
207 uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
208 const uint8_t ReportID,
209 void* Buffer)
210 {
211 USB_ControlRequest = (USB_Request_Header_t)
212 {
213 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
214 .bRequest = HID_REQ_SetReport,
215 .wValue = ((HID_REPORT_ITEM_In + 1) << 8) | ReportID,
216 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
217 .wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In),
218 };
219 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
220
221 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
222
223 return USB_Host_SendControlRequest(portnum,Buffer);
224 }
225 #endif
226
227 uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
228 void* Buffer)
229 {
230 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
231 uint8_t ErrorCode;
232 if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
233 return PIPE_READYWAIT_DeviceDisconnected;
234
235 Pipe_SelectPipe(portnum,HIDInterfaceInfo->Config.DataINPipeNumber);
236 Pipe_Unfreeze();
237
238 uint16_t ReportSize;
239 uint8_t* BufferPos = Buffer;
240
241 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
242 if (!(HIDInterfaceInfo->State.UsingBootProtocol))
243 {
244 uint8_t ReportID = 0;
245
246 if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
247 {
248 ReportID = Pipe_Read_8(portnum);
249 *(BufferPos++) = ReportID;
250 }
251
252 ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
253 }
254 else
255 #endif
256 {
257 ReportSize = Pipe_BytesInPipe(portnum);
258 }
259
260 if ((ErrorCode = Pipe_Read_Stream_LE(portnum,BufferPos, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
261 return ErrorCode;
262
263 Pipe_ClearIN(portnum);
264 Pipe_Freeze();
265
266 return PIPE_RWSTREAM_NoError;
267 }
268
269 uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
270 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
271 const uint8_t ReportID,
272 #endif
273 const uint8_t ReportType,
274 void* Buffer,
275 const uint16_t ReportSize)
276 {
277 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
278 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
279 if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
280 return false;
281
282 if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
283 {
284 uint8_t ErrorCode;
285
286 Pipe_SelectPipe(portnum,HIDInterfaceInfo->Config.DataOUTPipeNumber);
287 Pipe_Unfreeze();
288
289 if (ReportID)
290 Pipe_Write_Stream_LE(portnum,&ReportID, sizeof(ReportID), NULL);
291
292 if ((ErrorCode = Pipe_Write_Stream_LE(portnum,Buffer, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
293 return ErrorCode;
294
295 Pipe_ClearOUT(portnum);
296 Pipe_Freeze();
297
298 return PIPE_RWSTREAM_NoError;
299 }
300 else
301 #endif
302 {
303 USB_ControlRequest = (USB_Request_Header_t)
304 {
305 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
306 .bRequest = HID_REQ_SetReport,
307 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
308 .wValue = ((ReportType + 1) << 8) | ReportID,
309 #else
310 .wValue = ((ReportType + 1) << 8),
311 #endif
312 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
313 .wLength = ReportSize,
314 };
315
316 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
317
318 return USB_Host_SendControlRequest(portnum,Buffer);
319 }
320 }
321
322 bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
323 {
324 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
325 bool ReportReceived;
326
327 if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
328 return false;
329
330 Pipe_SelectPipe(portnum,HIDInterfaceInfo->Config.DataINPipeNumber);
331 Pipe_Unfreeze();
332
333 ReportReceived = Pipe_IsINReceived(portnum);
334
335 Pipe_Freeze();
336
337 return ReportReceived;
338 }
339
340 uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
341 {
342 uint8_t ErrorCode;
343 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
344
345 if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
346 return HID_ERROR_LOGICAL;
347
348 USB_ControlRequest = (USB_Request_Header_t)
349 {
350 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
351 .bRequest = HID_REQ_SetProtocol,
352 .wValue = 0,
353 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
354 .wLength = 0,
355 };
356
357 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
358
359 if ((ErrorCode = USB_Host_SendControlRequest(portnum,NULL)) != HOST_SENDCONTROL_Successful)
360 return ErrorCode;
361
362 HIDInterfaceInfo->State.LargestReportSize = 8;
363 HIDInterfaceInfo->State.UsingBootProtocol = true;
364
365 return HOST_SENDCONTROL_Successful;
366 }
367
368 uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
369 const uint16_t MS)
370 {
371 USB_ControlRequest = (USB_Request_Header_t)
372 {
373 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
374 .bRequest = HID_REQ_SetIdle,
375 .wValue = ((MS << 6) & 0xFF00),
376 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
377 .wLength = 0,
378 };
379 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
380
381 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
382
383 return USB_Host_SendControlRequest(portnum,NULL);
384 }
385
386 #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
387 uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
388 {
389 uint8_t ErrorCode;
390 uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
391 uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
392
393 USB_ControlRequest = (USB_Request_Header_t)
394 {
395 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
396 .bRequest = REQ_GetDescriptor,
397 .wValue = (HID_DTYPE_Report << 8),
398 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
399 .wLength = HIDInterfaceInfo->State.HIDReportSize,
400 };
401
402 Pipe_SelectPipe(portnum,PIPE_CONTROLPIPE);
403
404 if ((ErrorCode = USB_Host_SendControlRequest(portnum,HIDReportData)) != HOST_SENDCONTROL_Successful)
405 return ErrorCode;
406
407 if (HIDInterfaceInfo->State.UsingBootProtocol)
408 {
409 USB_ControlRequest = (USB_Request_Header_t)
410 {
411 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
412 .bRequest = HID_REQ_SetProtocol,
413 .wValue = 1,
414 .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
415 .wLength = 0,
416 };
417
418 if ((ErrorCode = USB_Host_SendControlRequest(portnum,NULL)) != HOST_SENDCONTROL_Successful)
419 return ErrorCode;
420
421 HIDInterfaceInfo->State.UsingBootProtocol = false;
422 }
423
424 if (HIDInterfaceInfo->Config.HIDParserData == NULL)
425 return HID_ERROR_LOGICAL;
426
427 if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
428 HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
429 {
430 return HID_ERROR_LOGICAL | ErrorCode;
431 }
432
433 uint8_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
434 HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
435
436 return 0;
437 }
438 #endif
439
440 #endif
441