LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 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)
57 
58  while (!(DataINEndpoint) || !(DataOUTEndpoint))
59  {
60  if (!(HIDInterface) ||
61  USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
63  {
64  if (DataINEndpoint || DataOUTEndpoint)
65  break;
66 
67  do
68  {
69  if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
71  {
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,
81  {
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  {
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 {
163 
164  if (Header->Type == DTYPE_Interface)
165  {
167 
168  if (Interface->Class == HID_CSCP_HIDClass)
170  }
171 
173 }
174 
175 static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
176 {
178 
179  if (Header->Type == HID_DTYPE_HID)
181  else if (Header->Type == DTYPE_Interface)
182  return DESCRIPTOR_SEARCH_Fail;
183  else
185 }
186 
187 static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
188 {
190 
191  if (Header->Type == DTYPE_Endpoint)
192  {
194 
195  if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
197  }
198  else if (Header->Type == DTYPE_Interface)
199  {
200  return DESCRIPTOR_SEARCH_Fail;
201  }
202 
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 {
212  {
213  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
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 
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))
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  {
304  {
305  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
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 
317 
318  return USB_Host_SendControlRequest(portnum,Buffer);
319  }
320 }
321 
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 
349  {
350  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
352  .wValue = 0,
353  .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
354  .wLength = 0,
355  };
356 
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 
366 }
367 
368 uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
369  const uint16_t MS)
370 {
372  {
373  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
375  .wValue = ((MS << 6) & 0xFF00),
376  .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
377  .wLength = 0,
378  };
379  uint8_t portnum = HIDInterfaceInfo->Config.PortNumber;
380 
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 
394  {
397  .wValue = (HID_DTYPE_Report << 8),
398  .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
399  .wLength = HIDInterfaceInfo->State.HIDReportSize,
400  };
401 
403 
404  if ((ErrorCode = USB_Host_SendControlRequest(portnum,HIDReportData)) != HOST_SENDCONTROL_Successful)
405  return ErrorCode;
406 
407  if (HIDInterfaceInfo->State.UsingBootProtocol)
408  {
410  {
411  .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
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