]> git.gir.st - tmk_keyboard.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c
Squashed 'tmk_core/' changes from b9e0ea0..caca2c0
[tmk_keyboard.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Host / StillImageClassHost.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2012.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2012 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 disclaim 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 false;
104
105 if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1)))
106 return false;
107
108 if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1)))
109 return false;
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 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_BytesInPipe())
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
Imprint / Impressum