]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c
Squashed 'tmk_core/' content from commit 05caacc
[qmk_firmware.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Host / StillImageClassHost.c
1 /*\r
2              LUFA Library\r
3      Copyright (C) Dean Camera, 2012.\r
4 \r
5   dean [at] fourwalledcubicle [dot] com\r
6            www.lufa-lib.org\r
7 */\r
8 \r
9 /*\r
10   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
11 \r
12   Permission to use, copy, modify, distribute, and sell this\r
13   software and its documentation for any purpose is hereby granted\r
14   without fee, provided that the above copyright notice appear in\r
15   all copies and that both that the copyright notice and this\r
16   permission notice and warranty disclaimer appear in supporting\r
17   documentation, and that the name of the author not be used in\r
18   advertising or publicity pertaining to distribution of the\r
19   software without specific, written prior permission.\r
20 \r
21   The author disclaim all warranties with regard to this\r
22   software, including all implied warranties of merchantability\r
23   and fitness.  In no event shall the author be liable for any\r
24   special, indirect or consequential damages or any damages\r
25   whatsoever resulting from loss of use, data or profits, whether\r
26   in an action of contract, negligence or other tortious action,\r
27   arising out of or in connection with the use or performance of\r
28   this software.\r
29 */\r
30 \r
31 #define  __INCLUDE_FROM_USB_DRIVER\r
32 #include "../../Core/USBMode.h"\r
33 \r
34 #if defined(USB_CAN_BE_HOST)\r
35 \r
36 #define  __INCLUDE_FROM_SI_DRIVER\r
37 #define  __INCLUDE_FROM_STILLIMAGE_HOST_C\r
38 #include "StillImageClassHost.h"\r
39 \r
40 uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
41                                uint16_t ConfigDescriptorSize,\r
42                                void* ConfigDescriptorData)\r
43 {\r
44         USB_Descriptor_Endpoint_t*  DataINEndpoint      = NULL;\r
45         USB_Descriptor_Endpoint_t*  DataOUTEndpoint     = NULL;\r
46         USB_Descriptor_Endpoint_t*  EventsEndpoint      = NULL;\r
47         USB_Descriptor_Interface_t* StillImageInterface = NULL;\r
48 \r
49         memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));\r
50 \r
51         if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)\r
52           return SI_ENUMERROR_InvalidConfigDescriptor;\r
53 \r
54         while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(EventsEndpoint))\r
55         {\r
56                 if (!(StillImageInterface) ||\r
57                     USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,\r
58                                               DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)\r
59                 {\r
60                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,\r
61                                                       DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)\r
62                         {\r
63                                 return SI_ENUMERROR_NoCompatibleInterfaceFound;\r
64                         }\r
65 \r
66                         StillImageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);\r
67 \r
68                         DataINEndpoint  = NULL;\r
69                         DataOUTEndpoint = NULL;\r
70                         EventsEndpoint  = NULL;\r
71 \r
72                         continue;\r
73                 }\r
74 \r
75                 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);\r
76 \r
77                 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)\r
78                 {\r
79                         if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)\r
80                           EventsEndpoint = EndpointData;\r
81                         else\r
82                           DataINEndpoint = EndpointData;\r
83                 }\r
84                 else\r
85                 {\r
86                         DataOUTEndpoint = EndpointData;\r
87                 }\r
88         }\r
89 \r
90         SIInterfaceInfo->Config.DataINPipe.Size  = le16_to_cpu(DataINEndpoint->EndpointSize);\r
91         SIInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;\r
92         SIInterfaceInfo->Config.DataINPipe.Type  = EP_TYPE_BULK;\r
93         \r
94         SIInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);\r
95         SIInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;\r
96         SIInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;\r
97         \r
98         SIInterfaceInfo->Config.EventsPipe.Size = le16_to_cpu(EventsEndpoint->EndpointSize);\r
99         SIInterfaceInfo->Config.EventsPipe.EndpointAddress = EventsEndpoint->EndpointAddress;\r
100         SIInterfaceInfo->Config.EventsPipe.Type = EP_TYPE_INTERRUPT;\r
101 \r
102         if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataINPipe, 1)))\r
103           return false;\r
104         \r
105         if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1)))\r
106           return false;\r
107 \r
108         if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1)))\r
109           return false;\r
110         \r
111         SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber;\r
112         SIInterfaceInfo->State.IsActive = true;\r
113 \r
114         return SI_ENUMERROR_NoError;\r
115 }\r
116 \r
117 uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor)\r
118 {\r
119         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);\r
120 \r
121         if (Header->Type == DTYPE_Interface)\r
122         {\r
123                 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);\r
124 \r
125                 if ((Interface->Class    == SI_CSCP_StillImageClass)    &&\r
126                     (Interface->SubClass == SI_CSCP_StillImageSubclass) &&\r
127                     (Interface->Protocol == SI_CSCP_BulkOnlyProtocol))\r
128                 {\r
129                         return DESCRIPTOR_SEARCH_Found;\r
130                 }\r
131         }\r
132 \r
133         return DESCRIPTOR_SEARCH_NotFound;\r
134 }\r
135 \r
136 uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)\r
137 {\r
138         USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);\r
139 \r
140         if (Header->Type == DTYPE_Endpoint)\r
141         {\r
142                 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);\r
143 \r
144                 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);\r
145 \r
146                 if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&\r
147                     (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))\r
148                 {\r
149                         return DESCRIPTOR_SEARCH_Found;\r
150                 }\r
151         }\r
152         else if (Header->Type == DTYPE_Interface)\r
153         {\r
154                 return DESCRIPTOR_SEARCH_Fail;\r
155         }\r
156 \r
157         return DESCRIPTOR_SEARCH_NotFound;\r
158 }\r
159 \r
160 uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
161                                 PIMA_Container_t* const PIMAHeader)\r
162 {\r
163         uint8_t ErrorCode;\r
164 \r
165         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
166           return PIPE_RWSTREAM_DeviceDisconnected;\r
167 \r
168         if (SIInterfaceInfo->State.IsSessionOpen)\r
169           PIMAHeader->TransactionID = cpu_to_le32(SIInterfaceInfo->State.TransactionID++);\r
170 \r
171         Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);\r
172         Pipe_Unfreeze();\r
173 \r
174         if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NULL)) != PIPE_RWSTREAM_NoError)\r
175           return ErrorCode;\r
176 \r
177         uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));\r
178 \r
179         if (ParamBytes)\r
180         {\r
181                 if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NULL)) != PIPE_RWSTREAM_NoError)\r
182                   return ErrorCode;\r
183         }\r
184 \r
185         Pipe_ClearOUT();\r
186         Pipe_Freeze();\r
187 \r
188         return PIPE_RWSTREAM_NoError;\r
189 }\r
190 \r
191 uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
192                                    PIMA_Container_t* const PIMAHeader)\r
193 {\r
194         uint16_t TimeoutMSRem        = SI_COMMAND_DATA_TIMEOUT_MS;\r
195         uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();\r
196 \r
197         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
198           return PIPE_RWSTREAM_DeviceDisconnected;\r
199 \r
200         Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);\r
201         Pipe_Unfreeze();\r
202 \r
203         while (!(Pipe_IsINReceived()))\r
204         {\r
205                 uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();\r
206 \r
207                 if (CurrentFrameNumber != PreviousFrameNumber)\r
208                 {\r
209                         PreviousFrameNumber = CurrentFrameNumber;\r
210 \r
211                         if (!(TimeoutMSRem--))\r
212                           return PIPE_RWSTREAM_Timeout;\r
213                 }\r
214 \r
215                 Pipe_Freeze();\r
216                 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);\r
217                 Pipe_Unfreeze();\r
218 \r
219                 if (Pipe_IsStalled())\r
220                 {\r
221                         USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());\r
222                         return PIPE_RWSTREAM_PipeStalled;\r
223                 }\r
224 \r
225                 Pipe_Freeze();\r
226                 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);\r
227                 Pipe_Unfreeze();\r
228 \r
229                 if (Pipe_IsStalled())\r
230                 {\r
231                         USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());\r
232                         return PIPE_RWSTREAM_PipeStalled;\r
233                 }\r
234 \r
235                 if (USB_HostState == HOST_STATE_Unattached)\r
236                   return PIPE_RWSTREAM_DeviceDisconnected;\r
237         }\r
238 \r
239         Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NULL);\r
240 \r
241         if (PIMAHeader->Type == CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock))\r
242         {\r
243                 uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));\r
244 \r
245                 if (ParamBytes)\r
246                   Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NULL);\r
247 \r
248                 Pipe_ClearIN();\r
249         }\r
250 \r
251         Pipe_Freeze();\r
252 \r
253         return PIPE_RWSTREAM_NoError;\r
254 }\r
255 \r
256 uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
257                          void* Buffer,\r
258                          const uint16_t Bytes)\r
259 {\r
260         uint8_t ErrorCode;\r
261 \r
262         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
263           return PIPE_RWSTREAM_DeviceDisconnected;\r
264 \r
265         Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);\r
266         Pipe_Unfreeze();\r
267 \r
268         ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NULL);\r
269 \r
270         Pipe_ClearOUT();\r
271         Pipe_Freeze();\r
272 \r
273         return ErrorCode;\r
274 }\r
275 \r
276 uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
277                          void* Buffer,\r
278                          const uint16_t Bytes)\r
279 {\r
280         uint8_t ErrorCode;\r
281 \r
282         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
283           return PIPE_RWSTREAM_DeviceDisconnected;\r
284 \r
285         Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);\r
286         Pipe_Unfreeze();\r
287 \r
288         ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NULL);\r
289 \r
290         Pipe_Freeze();\r
291 \r
292         return ErrorCode;\r
293 }\r
294 \r
295 bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)\r
296 {\r
297         bool IsEventReceived = false;\r
298 \r
299         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
300           return false;\r
301 \r
302         Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address);\r
303         Pipe_Unfreeze();\r
304 \r
305         if (Pipe_BytesInPipe())\r
306           IsEventReceived = true;\r
307 \r
308         Pipe_Freeze();\r
309 \r
310         return IsEventReceived;\r
311 }\r
312 \r
313 uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
314                                    PIMA_Container_t* const PIMAHeader)\r
315 {\r
316         uint8_t ErrorCode;\r
317 \r
318         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
319           return PIPE_RWSTREAM_DeviceDisconnected;\r
320 \r
321         Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address);\r
322         Pipe_Unfreeze();\r
323 \r
324         ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(PIMA_Container_t), NULL);\r
325 \r
326         Pipe_ClearIN();\r
327         Pipe_Freeze();\r
328 \r
329         return ErrorCode;\r
330 }\r
331 \r
332 uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)\r
333 {\r
334         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
335           return PIPE_RWSTREAM_DeviceDisconnected;\r
336 \r
337         uint8_t ErrorCode;\r
338 \r
339         SIInterfaceInfo->State.TransactionID = 0;\r
340         SIInterfaceInfo->State.IsSessionOpen = false;\r
341 \r
342         PIMA_Container_t PIMABlock = (PIMA_Container_t)\r
343                 {\r
344                         .DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),\r
345                         .Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),\r
346                         .Code          = CPU_TO_LE16(0x1002),\r
347                         .Params        = {CPU_TO_LE32(1)},\r
348                 };\r
349 \r
350         if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)\r
351           return ErrorCode;\r
352 \r
353         if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)\r
354           return ErrorCode;\r
355 \r
356         if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))\r
357           return SI_ERROR_LOGICAL_CMD_FAILED;\r
358 \r
359         SIInterfaceInfo->State.IsSessionOpen = true;\r
360 \r
361         return PIPE_RWSTREAM_NoError;\r
362 }\r
363 \r
364 uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)\r
365 {\r
366         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
367           return PIPE_RWSTREAM_DeviceDisconnected;\r
368 \r
369         uint8_t ErrorCode;\r
370 \r
371         PIMA_Container_t PIMABlock = (PIMA_Container_t)\r
372                 {\r
373                         .DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),\r
374                         .Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),\r
375                         .Code          = CPU_TO_LE16(0x1003),\r
376                         .Params        = {CPU_TO_LE32(1)},\r
377                 };\r
378 \r
379         if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)\r
380           return ErrorCode;\r
381 \r
382         if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)\r
383           return ErrorCode;\r
384 \r
385         SIInterfaceInfo->State.IsSessionOpen = false;\r
386 \r
387         if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))\r
388           return SI_ERROR_LOGICAL_CMD_FAILED;\r
389 \r
390         return PIPE_RWSTREAM_NoError;\r
391 }\r
392 \r
393 uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,\r
394                             const uint16_t Operation,\r
395                             const uint8_t TotalParams,\r
396                             uint32_t* const Params)\r
397 {\r
398         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
399           return PIPE_RWSTREAM_DeviceDisconnected;\r
400 \r
401         uint8_t ErrorCode;\r
402 \r
403         PIMA_Container_t PIMABlock = (PIMA_Container_t)\r
404                 {\r
405                         .DataLength    = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)),\r
406                         .Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),\r
407                         .Code          = cpu_to_le16(Operation),\r
408                 };\r
409 \r
410         memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);\r
411 \r
412         if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)\r
413           return ErrorCode;\r
414 \r
415         return PIPE_RWSTREAM_NoError;\r
416 }\r
417 \r
418 uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)\r
419 {\r
420         uint8_t ErrorCode;\r
421         PIMA_Container_t PIMABlock;\r
422 \r
423         if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))\r
424           return PIPE_RWSTREAM_DeviceDisconnected;\r
425 \r
426         if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)\r
427           return ErrorCode;\r
428 \r
429         if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))\r
430           return SI_ERROR_LOGICAL_CMD_FAILED;\r
431 \r
432         return PIPE_RWSTREAM_NoError;\r
433 }\r
434 \r
435 #endif\r
436 \r