| 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
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)
56 return SI_ENUMERROR_InvalidConfigDescriptor;
57
58 while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(EventsEndpoint))
59 {
60 if (!(StillImageInterface) ||
61 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
62 DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
63 {
64 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
65 DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
66 {
67 return SI_ENUMERROR_NoCompatibleInterfaceFound;
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 {
144 return SI_ENUMERROR_PipeConfigurationFailed;
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 {
159 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
160
161 if (Header->Type == DTYPE_Interface)
162 {
163 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
164
165 if ((Interface->Class == SI_CSCP_StillImageClass) &&
166 (Interface->SubClass == SI_CSCP_StillImageSubclass) &&
167 (Interface->Protocol == SI_CSCP_BulkOnlyProtocol))
168 {
169 return DESCRIPTOR_SEARCH_Found;
170 }
171 }
172
173 return DESCRIPTOR_SEARCH_NotFound;
174 }
175
176 uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
177 {
178 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
179
180 if (Header->Type == DTYPE_Endpoint)
181 {
182 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
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 {
189 return DESCRIPTOR_SEARCH_Found;
190 }
191 }
192 else if (Header->Type == DTYPE_Interface)
193 {
194 return DESCRIPTOR_SEARCH_Fail;
195 }
196
197 return DESCRIPTOR_SEARCH_NotFound;
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))
207 return PIPE_RWSTREAM_DeviceDisconnected;
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
232 uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
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))
240 return PIPE_RWSTREAM_DeviceDisconnected;
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 {
263 USB_Host_ClearEndpointStall(portnum,Pipe_GetBoundEndpointAddress(portnum));
264 return PIPE_RWSTREAM_PipeStalled;
265 }
266
267 Pipe_Freeze();
268 Pipe_SelectPipe(portnum,SIInterfaceInfo->Config.DataINPipeNumber);
269 Pipe_Unfreeze();
270
271 if (Pipe_IsStalled(portnum))
272 {
273 USB_Host_ClearEndpointStall(portnum,Pipe_GetBoundEndpointAddress(portnum));
274 return PIPE_RWSTREAM_PipeStalled;
275 }
276
277 if (USB_HostState[portnum] == HOST_STATE_Unattached)
278 return PIPE_RWSTREAM_DeviceDisconnected;
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))
306 return PIPE_RWSTREAM_DeviceDisconnected;
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))
327 return PIPE_RWSTREAM_DeviceDisconnected;
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
339 bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
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
358 uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
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))
365 return PIPE_RWSTREAM_DeviceDisconnected;
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))
383 return PIPE_RWSTREAM_DeviceDisconnected;
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 {
392 .DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
393 .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
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)))
405 return SI_ERROR_LOGICAL_CMD_FAILED;
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))
417 return PIPE_RWSTREAM_DeviceDisconnected;
418
419 uint8_t ErrorCode;
420
421 PIMA_Container_t PIMABlock = (PIMA_Container_t)
422 {
423 .DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
424 .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
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)))
438 return SI_ERROR_LOGICAL_CMD_FAILED;
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))
451 return PIPE_RWSTREAM_DeviceDisconnected;
452
453 uint8_t ErrorCode;
454
455 PIMA_Container_t PIMABlock = (PIMA_Container_t)
456 {
457 .DataLength = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)),
458 .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
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))
477 return PIPE_RWSTREAM_DeviceDisconnected;
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)))
483 return SI_ERROR_LOGICAL_CMD_FAILED;
484
485 return PIPE_RWSTREAM_NoError;
486 }
487
488 #endif
489