Add const qualifiers to Host mode Class drivers.
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / StillImage.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 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 SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize,
38 uint8_t* 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 PIPE_BANK_DOUBLE);
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 PIPE_BANK_DOUBLE);
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 PIPE_BANK_DOUBLE);
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* 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* 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 void SI_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
146 {
147
148 }
149
150 static uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
151 {
152 uint8_t ErrorCode;
153
154 PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;
155
156 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
157 Pipe_Unfreeze();
158
159 if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
160 return ErrorCode;
161
162 uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
163
164 if (ParamBytes)
165 {
166 if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
167 return ErrorCode;
168 }
169
170 Pipe_ClearOUT();
171 Pipe_Freeze();
172
173 return PIPE_RWSTREAM_NoError;
174 }
175
176 static uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
177 {
178 uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
179
180 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
181 Pipe_Unfreeze();
182
183 while (!(Pipe_IsReadWriteAllowed()))
184 {
185 if (USB_INT_HasOccurred(USB_INT_HSOFI))
186 {
187 USB_INT_Clear(USB_INT_HSOFI);
188 TimeoutMSRem--;
189
190 if (!(TimeoutMSRem))
191 {
192 return PIPE_RWSTREAM_Timeout;
193 }
194 }
195
196 Pipe_Freeze();
197 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
198 Pipe_Unfreeze();
199
200 if (Pipe_IsStalled())
201 {
202 USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber);
203 return PIPE_RWSTREAM_PipeStalled;
204 }
205
206 Pipe_Freeze();
207 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
208 Pipe_Unfreeze();
209
210 if (Pipe_IsStalled())
211 {
212 USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber);
213 return PIPE_RWSTREAM_PipeStalled;
214 }
215
216 if (USB_HostState == HOST_STATE_Unattached)
217 return PIPE_RWSTREAM_DeviceDisconnected;
218 }
219
220 Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK);
221
222 if (PIMAHeader->Type == CType_ResponseBlock)
223 {
224 uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
225
226 if (ParamBytes)
227 Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);
228
229 Pipe_ClearIN();
230
231 PIMAHeader->Code &= 0x0000000F;
232 }
233
234 Pipe_Freeze();
235
236 return PIPE_RWSTREAM_NoError;
237 }
238
239 uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
240 {
241 uint8_t ErrorCode;
242
243 Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
244 Pipe_Unfreeze();
245
246 ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
247
248 Pipe_ClearOUT();
249 Pipe_Freeze();
250
251 return ErrorCode;
252 }
253
254 uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
255 {
256 uint8_t ErrorCode;
257
258 Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
259 Pipe_Unfreeze();
260
261 ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
262
263 Pipe_Freeze();
264
265 return ErrorCode;
266 }
267
268 bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* SIInterfaceInfo)
269 {
270 bool IsEventReceived = false;
271
272 Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
273 Pipe_Unfreeze();
274
275 if (Pipe_BytesInPipe())
276 IsEventReceived = true;
277
278 Pipe_Freeze();
279
280 return IsEventReceived;
281 }
282
283 uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
284 {
285 uint8_t ErrorCode;
286
287 Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
288 Pipe_Unfreeze();
289
290 ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(SI_PIMA_Container_t), NO_STREAM_CALLBACK);
291
292 Pipe_ClearIN();
293 Pipe_Freeze();
294
295 return ErrorCode;
296 }
297
298 uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
299 {
300 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
301 return HOST_SENDCONTROL_DeviceDisconnect;
302
303 uint8_t ErrorCode;
304
305 SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
306 {
307 .DataLength = PIMA_COMMAND_SIZE(0),
308 .Type = CType_CommandBlock,
309 .Code = 0x1002,
310 .Params = {},
311 };
312
313 if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
314 return ErrorCode;
315
316 if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
317 return ErrorCode;
318
319 if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
320 return SI_ERROR_LOGICAL_CMD_FAILED;
321
322 SIInterfaceInfo->State.TransactionID = 0;
323 SIInterfaceInfo->State.IsSessionOpen = true;
324
325 return PIPE_RWSTREAM_NoError;
326 }
327
328 uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
329 {
330 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
331 return HOST_SENDCONTROL_DeviceDisconnect;
332
333 uint8_t ErrorCode;
334
335 SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
336 {
337 .DataLength = PIMA_COMMAND_SIZE(0),
338 .Type = CType_CommandBlock,
339 .Code = 0x1003,
340 .Params = {},
341 };
342
343 if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
344 return ErrorCode;
345
346 if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
347 return ErrorCode;
348
349 SIInterfaceInfo->State.IsSessionOpen = false;
350
351 if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
352 return SI_ERROR_LOGICAL_CMD_FAILED;
353
354 return PIPE_RWSTREAM_NoError;
355 }
356
357 uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation,
358 const uint8_t TotalParams, uint32_t* Params)
359 {
360 if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
361 return HOST_SENDCONTROL_DeviceDisconnect;
362
363 uint8_t ErrorCode;
364
365 SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
366 {
367 .DataLength = PIMA_COMMAND_SIZE(TotalParams),
368 .Type = CType_CommandBlock,
369 .Code = Operation,
370 };
371
372 memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
373
374 if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
375 return ErrorCode;
376
377 return PIPE_RWSTREAM_NoError;
378 }
379
380 uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
381 {
382 uint8_t ErrorCode;
383 SI_PIMA_Container_t PIMABlock;
384
385 if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
386 return ErrorCode;
387
388 if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
389 return SI_ERROR_LOGICAL_CMD_FAILED;
390
391 return PIPE_RWSTREAM_NoError;
392 }
393
394 #endif