3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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
31 #include "../../HighLevel/USBMode.h"
32 #if defined(USB_CAN_BE_HOST)
34 #define INCLUDE_FROM_SI_CLASS_HOST_C
35 #include "StillImage.h"
37 uint8_t SImage_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, uint16_t ConfigDescriptorSize
,
38 void* DeviceConfigDescriptor
)
40 uint8_t FoundEndpoints
= 0;
42 memset(&SIInterfaceInfo
->State
, 0x00, sizeof(SIInterfaceInfo
->State
));
44 if (DESCRIPTOR_TYPE(DeviceConfigDescriptor
) != DTYPE_Configuration
)
45 return SI_ENUMERROR_InvalidConfigDescriptor
;
47 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &DeviceConfigDescriptor
,
48 DComp_SI_Host_NextSIInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
50 return SI_ENUMERROR_NoSIInterfaceFound
;
53 while (FoundEndpoints
!= (SI_FOUND_EVENTS_IN
| SI_FOUND_DATAPIPE_IN
| SI_FOUND_DATAPIPE_OUT
))
55 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &DeviceConfigDescriptor
,
56 DComp_SI_Host_NextSIInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
58 return SI_ENUMERROR_EndpointsNotFound
;
61 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(DeviceConfigDescriptor
, USB_Descriptor_Endpoint_t
);
63 if ((EndpointData
->Attributes
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
)
65 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
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
;
72 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
);
74 FoundEndpoints
|= SI_FOUND_EVENTS_IN
;
79 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
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
;
86 FoundEndpoints
|= SI_FOUND_DATAPIPE_IN
;
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
;
95 FoundEndpoints
|= SI_FOUND_DATAPIPE_OUT
;
100 SIInterfaceInfo
->State
.IsActive
= true;
101 return SI_ENUMERROR_NoError
;
104 uint8_t DComp_SI_Host_NextSIInterface(void* const CurrentDescriptor
)
106 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
108 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
109 USB_Descriptor_Interface_t
);
111 if ((CurrentInterface
->Class
== STILL_IMAGE_CLASS
) &&
112 (CurrentInterface
->SubClass
== STILL_IMAGE_SUBCLASS
) &&
113 (CurrentInterface
->Protocol
== STILL_IMAGE_PROTOCOL
))
115 return DESCRIPTOR_SEARCH_Found
;
119 return DESCRIPTOR_SEARCH_NotFound
;
122 uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor
)
124 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
126 USB_Descriptor_Endpoint_t
* CurrentEndpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
,
127 USB_Descriptor_Endpoint_t
);
129 uint8_t EndpointType
= (CurrentEndpoint
->Attributes
& EP_TYPE_MASK
);
131 if (((EndpointType
== EP_TYPE_BULK
) || (EndpointType
== EP_TYPE_INTERRUPT
)) &&
132 (!(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))))
134 return DESCRIPTOR_SEARCH_Found
;
137 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
139 return DESCRIPTOR_SEARCH_Fail
;
142 return DESCRIPTOR_SEARCH_NotFound
;
145 uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, SI_PIMA_Container_t
* const PIMAHeader
)
149 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
150 return PIPE_RWSTREAM_DeviceDisconnected
;
152 PIMAHeader
->TransactionID
= SIInterfaceInfo
->State
.TransactionID
++;
154 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
157 if ((ErrorCode
= Pipe_Write_Stream_LE(PIMAHeader
, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
160 uint8_t ParamBytes
= (PIMAHeader
->DataLength
- PIMA_COMMAND_SIZE(0));
164 if ((ErrorCode
= Pipe_Write_Stream_LE(&PIMAHeader
->Params
, ParamBytes
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
171 return PIPE_RWSTREAM_NoError
;
174 uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, SI_PIMA_Container_t
* const PIMAHeader
)
176 uint16_t TimeoutMSRem
= COMMAND_DATA_TIMEOUT_MS
;
178 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
179 return PIPE_RWSTREAM_DeviceDisconnected
;
181 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
);
184 while (!(Pipe_IsReadWriteAllowed()))
186 if (USB_INT_HasOccurred(USB_INT_HSOFI
))
188 USB_INT_Clear(USB_INT_HSOFI
);
193 return PIPE_RWSTREAM_Timeout
;
198 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
201 if (Pipe_IsStalled())
203 USB_Host_ClearPipeStall(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
204 return PIPE_RWSTREAM_PipeStalled
;
208 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
);
211 if (Pipe_IsStalled())
213 USB_Host_ClearPipeStall(SIInterfaceInfo
->Config
.DataINPipeNumber
);
214 return PIPE_RWSTREAM_PipeStalled
;
217 if (USB_HostState
== HOST_STATE_Unattached
)
218 return PIPE_RWSTREAM_DeviceDisconnected
;
221 Pipe_Read_Stream_LE(PIMAHeader
, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK
);
223 if (PIMAHeader
->Type
== CType_ResponseBlock
)
225 uint8_t ParamBytes
= (PIMAHeader
->DataLength
- PIMA_COMMAND_SIZE(0));
228 Pipe_Read_Stream_LE(&PIMAHeader
->Params
, ParamBytes
, NO_STREAM_CALLBACK
);
235 return PIPE_RWSTREAM_NoError
;
238 uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, void* Buffer
, const uint16_t Bytes
)
242 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
243 return PIPE_RWSTREAM_DeviceDisconnected
;
245 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
248 ErrorCode
= Pipe_Write_Stream_LE(Buffer
, Bytes
, NO_STREAM_CALLBACK
);
256 uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, void* Buffer
, const uint16_t Bytes
)
260 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
261 return PIPE_RWSTREAM_DeviceDisconnected
;
263 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
);
266 ErrorCode
= Pipe_Read_Stream_LE(Buffer
, Bytes
, NO_STREAM_CALLBACK
);
273 bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
)
275 bool IsEventReceived
= false;
277 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
280 Pipe_SelectPipe(SIInterfaceInfo
->Config
.EventsPipeNumber
);
283 if (Pipe_BytesInPipe())
284 IsEventReceived
= true;
288 return IsEventReceived
;
291 uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, SI_PIMA_Container_t
* const PIMAHeader
)
295 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
296 return PIPE_RWSTREAM_DeviceDisconnected
;
298 Pipe_SelectPipe(SIInterfaceInfo
->Config
.EventsPipeNumber
);
301 ErrorCode
= Pipe_Read_Stream_LE(PIMAHeader
, sizeof(SI_PIMA_Container_t
), NO_STREAM_CALLBACK
);
309 uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
)
311 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
312 return HOST_SENDCONTROL_DeviceDisconnected
;
316 SI_PIMA_Container_t PIMABlock
= (SI_PIMA_Container_t
)
318 .DataLength
= PIMA_COMMAND_SIZE(0),
319 .Type
= CType_CommandBlock
,
324 if ((ErrorCode
= SImage_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
327 if ((ErrorCode
= SImage_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
330 if ((PIMABlock
.Type
!= CType_ResponseBlock
) || (PIMABlock
.Code
!= 0x2001))
331 return SI_ERROR_LOGICAL_CMD_FAILED
;
333 SIInterfaceInfo
->State
.TransactionID
= 0;
334 SIInterfaceInfo
->State
.IsSessionOpen
= true;
336 return PIPE_RWSTREAM_NoError
;
339 uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
)
341 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
342 return HOST_SENDCONTROL_DeviceDisconnected
;
346 SI_PIMA_Container_t PIMABlock
= (SI_PIMA_Container_t
)
348 .DataLength
= PIMA_COMMAND_SIZE(0),
349 .Type
= CType_CommandBlock
,
354 if ((ErrorCode
= SImage_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
357 if ((ErrorCode
= SImage_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
360 SIInterfaceInfo
->State
.IsSessionOpen
= false;
362 if ((PIMABlock
.Type
!= CType_ResponseBlock
) || (PIMABlock
.Code
!= 0x2001))
363 return SI_ERROR_LOGICAL_CMD_FAILED
;
365 return PIPE_RWSTREAM_NoError
;
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
)
371 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
372 return HOST_SENDCONTROL_DeviceDisconnected
;
376 SI_PIMA_Container_t PIMABlock
= (SI_PIMA_Container_t
)
378 .DataLength
= PIMA_COMMAND_SIZE(TotalParams
),
379 .Type
= CType_CommandBlock
,
383 memcpy(&PIMABlock
.Params
, Params
, sizeof(uint32_t) * TotalParams
);
385 if ((ErrorCode
= SImage_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
388 return PIPE_RWSTREAM_NoError
;
391 uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
)
394 SI_PIMA_Container_t PIMABlock
;
396 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
397 return HOST_SENDCONTROL_DeviceDisconnected
;
399 if ((ErrorCode
= SImage_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
402 if ((PIMABlock
.Type
!= CType_ResponseBlock
) || (PIMABlock
.Code
!= 0x2001))
403 return SI_ERROR_LOGICAL_CMD_FAILED
;
405 return PIPE_RWSTREAM_NoError
;