LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
StillImageClassHost.c
Go to the documentation of this file.
1 /*
2  * @brief Host mode driver for the library USB Still Image 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_SI_DRIVER
40 #define __INCLUDE_FROM_STILLIMAGE_HOST_C
41 #include "StillImageClassHost.h"
42 
43 uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
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_Endpoint_t* EventsEndpoint = NULL;
50  USB_Descriptor_Interface_t* StillImageInterface = NULL;
51  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
52 
53  memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
54 
55  if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
57 
58  while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(EventsEndpoint))
59  {
60  if (!(StillImageInterface) ||
61  USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
63  {
64  if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
66  {
68  }
69 
70  StillImageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
71 
72  DataINEndpoint = NULL;
73  DataOUTEndpoint = NULL;
74  EventsEndpoint = NULL;
75 
76  continue;
77  }
78 
79  USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
80 
81  if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
82  {
83  if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
84  EventsEndpoint = EndpointData;
85  else
86  DataINEndpoint = EndpointData;
87  }
88  else
89  {
90  DataOUTEndpoint = EndpointData;
91  }
92  }
93 
94  for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
95  {
96  uint16_t Size;
97  uint8_t Type;
98  uint8_t Token;
99  uint8_t EndpointAddress;
100  uint8_t InterruptPeriod;
101  bool DoubleBanked;
102 
103  if (PipeNum == SIInterfaceInfo->Config.DataINPipeNumber)
104  {
105  Size = DataINEndpoint->EndpointSize;
106  EndpointAddress = DataINEndpoint->EndpointAddress;
107  Token = PIPE_TOKEN_IN;
108  Type = EP_TYPE_BULK;
109  DoubleBanked = SIInterfaceInfo->Config.DataINPipeDoubleBank;
110  InterruptPeriod = 0;
111 
112  SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
113  }
114  else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber)
115  {
116  Size = DataOUTEndpoint->EndpointSize;
117  EndpointAddress = DataOUTEndpoint->EndpointAddress;
118  Token = PIPE_TOKEN_OUT;
119  Type = EP_TYPE_BULK;
120  DoubleBanked = SIInterfaceInfo->Config.DataOUTPipeDoubleBank;
121  InterruptPeriod = 0;
122 
123  SIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
124  }
125  else if (PipeNum == SIInterfaceInfo->Config.EventsPipeNumber)
126  {
127  Size = EventsEndpoint->EndpointSize;
128  EndpointAddress = EventsEndpoint->EndpointAddress;
129  Token = PIPE_TOKEN_IN;
130  Type = EP_TYPE_INTERRUPT;
131  DoubleBanked = SIInterfaceInfo->Config.EventsPipeDoubleBank;
132  InterruptPeriod = EventsEndpoint->PollingIntervalMS;
133 
134  SIInterfaceInfo->State.EventsPipeSize = EventsEndpoint->EndpointSize;
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  SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber;
152  SIInterfaceInfo->State.IsActive = true;
153 
154  return SI_ENUMERROR_NoError;
155 }
156 
157 uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor)
158 {
160 
161  if (Header->Type == DTYPE_Interface)
162  {
164 
165  if ((Interface->Class == SI_CSCP_StillImageClass) &&
166  (Interface->SubClass == SI_CSCP_StillImageSubclass) &&
167  (Interface->Protocol == SI_CSCP_BulkOnlyProtocol))
168  {
170  }
171  }
172 
174 }
175 
176 uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
177 {
179 
180  if (Header->Type == DTYPE_Endpoint)
181  {
183 
184  uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
185 
186  if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
187  (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
188  {
190  }
191  }
192  else if (Header->Type == DTYPE_Interface)
193  {
194  return DESCRIPTOR_SEARCH_Fail;
195  }
196 
198 }
199 
200 uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
201  PIMA_Container_t* const PIMAHeader)
202 {
203  uint8_t ErrorCode;
204  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
205 
206  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
208 
209  if (SIInterfaceInfo->State.IsSessionOpen)
210  PIMAHeader->TransactionID = cpu_to_le32(SIInterfaceInfo->State.TransactionID++);
211 
212  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataOUTPipeNumber);
213  Pipe_Unfreeze();
214 
215  if ((ErrorCode = Pipe_Write_Stream_LE(portnum,PIMAHeader, PIMA_COMMAND_SIZE(0), NULL)) != PIPE_RWSTREAM_NoError)
216  return ErrorCode;
217 
218  uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
219 
220  if (ParamBytes)
221  {
222  if ((ErrorCode = Pipe_Write_Stream_LE(portnum,&PIMAHeader->Params, ParamBytes, NULL)) != PIPE_RWSTREAM_NoError)
223  return ErrorCode;
224  }
225 
226  Pipe_ClearOUT(portnum);
227  Pipe_Freeze();
228 
229  return PIPE_RWSTREAM_NoError;
230 }
231 
233  PIMA_Container_t* const PIMAHeader)
234 {
235  uint16_t TimeoutMSRem = SI_COMMAND_DATA_TIMEOUT_MS;
236  uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
237  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
238 
239  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
241 
242  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataINPipeNumber);
243  Pipe_Unfreeze();
244 
245  while (!(Pipe_IsINReceived(portnum)))
246  {
247  uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
248 
249  if (CurrentFrameNumber != PreviousFrameNumber)
250  {
251  PreviousFrameNumber = CurrentFrameNumber;
252 
253  if (!(TimeoutMSRem--))
254  return PIPE_RWSTREAM_Timeout;
255  }
256 
257  Pipe_Freeze();
258  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataOUTPipeNumber);
259  Pipe_Unfreeze();
260 
261  if (Pipe_IsStalled(portnum))
262  {
265  }
266 
267  Pipe_Freeze();
268  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataINPipeNumber);
269  Pipe_Unfreeze();
270 
271  if (Pipe_IsStalled(portnum))
272  {
275  }
276 
277  if (USB_HostState[portnum] == HOST_STATE_Unattached)
279  }
280 
281  Pipe_Read_Stream_LE(portnum,PIMAHeader, PIMA_COMMAND_SIZE(0), NULL);
282 
283  if (PIMAHeader->Type == CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock))
284  {
285  uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
286 
287  if (ParamBytes)
288  Pipe_Read_Stream_LE(portnum,&PIMAHeader->Params, ParamBytes, NULL);
289 
290  Pipe_ClearIN(portnum);
291  }
292 
293  Pipe_Freeze();
294 
295  return PIPE_RWSTREAM_NoError;
296 }
297 
298 uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
299  void* Buffer,
300  const uint16_t Bytes)
301 {
302  uint8_t ErrorCode;
303  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
304 
305  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
307 
308  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataOUTPipeNumber);
309  Pipe_Unfreeze();
310 
311  ErrorCode = Pipe_Write_Stream_LE(portnum,Buffer, Bytes, NULL);
312 
313  Pipe_ClearOUT(portnum);
314  Pipe_Freeze();
315 
316  return ErrorCode;
317 }
318 
319 uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
320  void* Buffer,
321  const uint16_t Bytes)
322 {
323  uint8_t ErrorCode;
324  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
325 
326  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
328 
329  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataINPipeNumber);
330  Pipe_Unfreeze();
331 
332  ErrorCode = Pipe_Read_Stream_LE(portnum,Buffer, Bytes, NULL);
333 
334  Pipe_Freeze();
335 
336  return ErrorCode;
337 }
338 
340 {
341  bool IsEventReceived = false;
342  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
343 
344  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
345  return false;
346 
347  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.EventsPipeNumber);
348  Pipe_Unfreeze();
349 
350  if (Pipe_BytesInPipe(portnum))
351  IsEventReceived = true;
352 
353  Pipe_Freeze();
354 
355  return IsEventReceived;
356 }
357 
359  PIMA_Container_t* const PIMAHeader)
360 {
361  uint8_t ErrorCode;
362  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
363 
364  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
366 
367  Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.EventsPipeNumber);
368  Pipe_Unfreeze();
369 
370  ErrorCode = Pipe_Read_Stream_LE(portnum,PIMAHeader, sizeof(PIMA_Container_t), NULL);
371 
372  Pipe_ClearIN(portnum);
373  Pipe_Freeze();
374 
375  return ErrorCode;
376 }
377 
378 uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
379 {
380  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
381 
382  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
384 
385  uint8_t ErrorCode;
386 
387  SIInterfaceInfo->State.TransactionID = 0;
388  SIInterfaceInfo->State.IsSessionOpen = false;
389 
390  PIMA_Container_t PIMABlock = (PIMA_Container_t)
391  {
394  .Code = CPU_TO_LE16(0x1002),
395  .Params = {CPU_TO_LE32(1)},
396  };
397 
398  if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
399  return ErrorCode;
400 
401  if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
402  return ErrorCode;
403 
404  if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
406 
407  SIInterfaceInfo->State.IsSessionOpen = true;
408 
409  return PIPE_RWSTREAM_NoError;
410 }
411 
412 uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
413 {
414  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
415 
416  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
418 
419  uint8_t ErrorCode;
420 
421  PIMA_Container_t PIMABlock = (PIMA_Container_t)
422  {
425  .Code = CPU_TO_LE16(0x1003),
426  .Params = {CPU_TO_LE32(1)},
427  };
428 
429  if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
430  return ErrorCode;
431 
432  if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
433  return ErrorCode;
434 
435  SIInterfaceInfo->State.IsSessionOpen = false;
436 
437  if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
439 
440  return PIPE_RWSTREAM_NoError;
441 }
442 
443 uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
444  const uint16_t Operation,
445  const uint8_t TotalParams,
446  uint32_t* const Params)
447 {
448  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
449 
450  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
452 
453  uint8_t ErrorCode;
454 
455  PIMA_Container_t PIMABlock = (PIMA_Container_t)
456  {
457  .DataLength = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)),
459  .Code = cpu_to_le16(Operation),
460  };
461 
462  memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
463 
464  if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
465  return ErrorCode;
466 
467  return PIPE_RWSTREAM_NoError;
468 }
469 
470 uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
471 {
472  uint8_t ErrorCode;
473  PIMA_Container_t PIMABlock;
474  uint8_t portnum = SIInterfaceInfo->Config.PortNumber;
475 
476  if ((USB_HostState[portnum] != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
478 
479  if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
480  return ErrorCode;
481 
482  if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
484 
485  return PIPE_RWSTREAM_NoError;
486 }
487 
488 #endif
489