Added explicit ADC channel masks for the standard set of ADC channels, as the single...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / StillImage.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2010 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 #include "../../HighLevel/USBMode.h"
32 #if defined(USB_CAN_BE_HOST)
33
34 #define INCLUDE_FROM_SI_CLASS_HOST_C
35 #include "StillImage.h"
36
37 uint8_t SImage_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize,
38 void* DeviceConfigDescriptor)
39 {
40 uint8_t FoundEndpoints = 0;
41
42 memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
43
44 if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
45 return SI_ENUMERROR_InvalidConfigDescriptor;
46
47 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
48 DComp_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
49 {
50 return SI_ENUMERROR_NoSIInterfaceFound;
51 }
52
53 while (FoundEndpoints != (SI_FOUND_EVENTS_IN | SI_FOUND_DATAPIPE_IN | SI_FOUND_DATAPIPE_OUT))
54 {
55 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
56 DComp_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
57 {
58 return SI_ENUMERROR_EndpointsNotFound;
59 }
60
61 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
62
63 if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
64 {
65 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
66 {
67 Pipe_ConfigurePipe(SIInterfaceInfo->Config.EventsPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
68 EndpointData->EndpointAddress, EndpointData->EndpointSize,
69 SIInterfaceInfo->Config.EventsPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
70 SIInterfaceInfo->State.EventsPipeSize = EndpointData->EndpointSize;
71
72 Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
73
74 FoundEndpoints |= SI_FOUND_EVENTS_IN;
75 }
76 }
77 else
78 {
79 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
80 {
81 Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
82 EndpointData->EndpointAddress, EndpointData->EndpointSize,
83 SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
84 SIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
85
86 FoundEndpoints |= SI_FOUND_DATAPIPE_IN;
87 }
88 else
89 {
90 Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
91 EndpointData->EndpointAddress, EndpointData->EndpointSize,
92 SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
93 SIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
94
95 FoundEndpoints |= SI_FOUND_DATAPIPE_OUT;
96 }
97 }
98 }
99
100 SIInterfaceInfo->State.IsActive = true;
101 return SI_ENUMERROR_NoError;
102 }
103
104 uint8_t DComp_SI_Host_NextSIInterface(void* const CurrentDescriptor)
105 {
106 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
107 {
108 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
109 USB_Descriptor_Interface_t);
110
111 if ((CurrentInterface->Class == STILL_IMAGE_CLASS) &&
112 (CurrentInterface->SubClass == STILL_IMAGE_SUBCLASS) &&
113 (CurrentInterface->Protocol == STILL_IMAGE_PROTOCOL))
114 {
115 return DESCRIPTOR_SEARCH_Found;
116 }
117 }
118
119 return DESCRIPTOR_SEARCH_NotFound;
120 }
121
122 uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
123 {
124 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
125 {
126 USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
127 USB_Descriptor_Endpoint_t);
128
129 uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
130
131 if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
132 (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))))
133 {
134 return DESCRIPTOR_SEARCH_Found;
135 }
136 }
137 else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
138 {
139 return DESCRIPTOR_SEARCH_Fail;
140 }
141
142 return DESCRIPTOR_SEARCH_NotFound;
143 }
144
145 uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
146 {
147 uint8_t ErrorCode;
148
149 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
150 return PIPE_RWSTREAM_DeviceDisconnected;
151
152 PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;
153
154 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
155 Pipe_Unfreeze();
156
157 if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
158 return ErrorCode;
159
160 uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
161
162 if (ParamBytes)
163 {
164 if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
165 return ErrorCode;
166 }
167
168 Pipe_ClearOUT();
169 Pipe_Freeze();
170
171 return PIPE_RWSTREAM_NoError;
172 }
173
174 uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
175 {
176 uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
177
178 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
179 return PIPE_RWSTREAM_DeviceDisconnected;
180
181 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
182 Pipe_Unfreeze();
183
184 while (!(Pipe_IsReadWriteAllowed()))
185 {
186 if (USB_INT_HasOccurred(USB_INT_HSOFI))
187 {
188 USB_INT_Clear(USB_INT_HSOFI);
189 TimeoutMSRem--;
190
191 if (!(TimeoutMSRem))
192 {
193 return PIPE_RWSTREAM_Timeout;
194 }
195 }
196
197 Pipe_Freeze();
198 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
199 Pipe_Unfreeze();
200
201 if (Pipe_IsStalled())
202 {
203 USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber);
204 return PIPE_RWSTREAM_PipeStalled;
205 }
206
207 Pipe_Freeze();
208 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
209 Pipe_Unfreeze();
210
211 if (Pipe_IsStalled())
212 {
213 USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber);
214 return PIPE_RWSTREAM_PipeStalled;
215 }
216
217 if (USB_HostState == HOST_STATE_Unattached)
218 return PIPE_RWSTREAM_DeviceDisconnected;
219 }
220
221 Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK);
222
223 if (PIMAHeader->Type == CType_ResponseBlock)
224 {
225 uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
226
227 if (ParamBytes)
228 Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);
229
230 Pipe_ClearIN();
231 }
232
233 Pipe_Freeze();
234
235 return PIPE_RWSTREAM_NoError;
236 }
237
238 uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
239 {
240 uint8_t ErrorCode;
241
242 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
243 return PIPE_RWSTREAM_DeviceDisconnected;
244
245 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
246 Pipe_Unfreeze();
247
248 ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
249
250 Pipe_ClearOUT();
251 Pipe_Freeze();
252
253 return ErrorCode;
254 }
255
256 uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
257 {
258 uint8_t ErrorCode;
259
260 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
261 return PIPE_RWSTREAM_DeviceDisconnected;
262
263 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
264 Pipe_Unfreeze();
265
266 ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
267
268 Pipe_Freeze();
269
270 return ErrorCode;
271 }
272
273 bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* SIInterfaceInfo)
274 {
275 bool IsEventReceived = false;
276
277 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
278 return false;
279
280 Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
281 Pipe_Unfreeze();
282
283 if (Pipe_BytesInPipe())
284 IsEventReceived = true;
285
286 Pipe_Freeze();
287
288 return IsEventReceived;
289 }
290
291 uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
292 {
293 uint8_t ErrorCode;
294
295 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
296 return PIPE_RWSTREAM_DeviceDisconnected;
297
298 Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
299 Pipe_Unfreeze();
300
301 ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(SI_PIMA_Container_t), NO_STREAM_CALLBACK);
302
303 Pipe_ClearIN();
304 Pipe_Freeze();
305
306 return ErrorCode;
307 }
308
309 uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
310 {
311 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
312 return HOST_SENDCONTROL_DeviceDisconnected;
313
314 uint8_t ErrorCode;
315
316 SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
317 {
318 .DataLength = PIMA_COMMAND_SIZE(0),
319 .Type = CType_CommandBlock,
320 .Code = 0x1002,
321 .Params = {},
322 };
323
324 if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
325 return ErrorCode;
326
327 if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
328 return ErrorCode;
329
330 if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
331 return SI_ERROR_LOGICAL_CMD_FAILED;
332
333 SIInterfaceInfo->State.TransactionID = 0;
334 SIInterfaceInfo->State.IsSessionOpen = true;
335
336 return PIPE_RWSTREAM_NoError;
337 }
338
339 uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
340 {
341 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
342 return HOST_SENDCONTROL_DeviceDisconnected;
343
344 uint8_t ErrorCode;
345
346 SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
347 {
348 .DataLength = PIMA_COMMAND_SIZE(0),
349 .Type = CType_CommandBlock,
350 .Code = 0x1003,
351 .Params = {},
352 };
353
354 if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
355 return ErrorCode;
356
357 if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
358 return ErrorCode;
359
360 SIInterfaceInfo->State.IsSessionOpen = false;
361
362 if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
363 return SI_ERROR_LOGICAL_CMD_FAILED;
364
365 return PIPE_RWSTREAM_NoError;
366 }
367
368 uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation,
369 const uint8_t TotalParams, uint32_t* Params)
370 {
371 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
372 return HOST_SENDCONTROL_DeviceDisconnected;
373
374 uint8_t ErrorCode;
375
376 SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
377 {
378 .DataLength = PIMA_COMMAND_SIZE(TotalParams),
379 .Type = CType_CommandBlock,
380 .Code = Operation,
381 };
382
383 memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
384
385 if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
386 return ErrorCode;
387
388 return PIPE_RWSTREAM_NoError;
389 }
390
391 uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
392 {
393 uint8_t ErrorCode;
394 SI_PIMA_Container_t PIMABlock;
395
396 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
397 return HOST_SENDCONTROL_DeviceDisconnected;
398
399 if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
400 return ErrorCode;
401
402 if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
403 return SI_ERROR_LOGICAL_CMD_FAILED;
404
405 return PIPE_RWSTREAM_NoError;
406 }
407
408 #endif