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