3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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 #warning The Still Image Host mode Class driver is currently incomplete and is for preview purposes only.
39 uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
, uint16_t ConfigDescriptorLength
,
40 uint8_t* DeviceConfigDescriptor
)
42 uint8_t FoundEndpoints
= 0;
44 memset(&SIInterfaceInfo
->State
, 0x00, sizeof(SIInterfaceInfo
->State
));
46 if (DESCRIPTOR_TYPE(DeviceConfigDescriptor
) != DTYPE_Configuration
)
47 return SI_ENUMERROR_InvalidConfigDescriptor
;
49 if (USB_GetNextDescriptorComp(&ConfigDescriptorLength
, &DeviceConfigDescriptor
,
50 DComp_SI_Host_NextSIInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
52 return SI_ENUMERROR_NoSIInterfaceFound
;
55 while (FoundEndpoints
!= (SI_FOUND_EVENTS_IN
| SI_FOUND_DATAPIPE_IN
| SI_FOUND_DATAPIPE_OUT
))
57 if (USB_GetNextDescriptorComp(&ConfigDescriptorLength
, &DeviceConfigDescriptor
,
58 DComp_SI_Host_NextSIInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
60 return SI_ENUMERROR_EndpointsNotFound
;
63 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(DeviceConfigDescriptor
, USB_Descriptor_Endpoint_t
);
65 if ((EndpointData
->Attributes
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
)
67 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
69 Pipe_ConfigurePipe(SIInterfaceInfo
->Config
.EventsPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
,
70 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
72 SIInterfaceInfo
->State
.EventsPipeSize
= EndpointData
->EndpointSize
;
74 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
);
76 FoundEndpoints
|= SI_FOUND_EVENTS_IN
;
81 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
83 Pipe_ConfigurePipe(SIInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
,
84 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
86 SIInterfaceInfo
->State
.DataINPipeSize
= EndpointData
->EndpointSize
;
88 FoundEndpoints
|= SI_FOUND_DATAPIPE_IN
;
92 Pipe_ConfigurePipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
,
93 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
95 SIInterfaceInfo
->State
.DataOUTPipeSize
= EndpointData
->EndpointSize
;
97 FoundEndpoints
|= SI_FOUND_DATAPIPE_OUT
;
102 SIInterfaceInfo
->State
.IsActive
= true;
103 return SI_ENUMERROR_NoError
;
106 uint8_t DComp_SI_Host_NextSIInterface(void* CurrentDescriptor
)
108 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
110 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
111 USB_Descriptor_Interface_t
);
113 if ((CurrentInterface
->Class
== STILL_IMAGE_CLASS
) &&
114 (CurrentInterface
->SubClass
== STILL_IMAGE_SUBCLASS
) &&
115 (CurrentInterface
->Protocol
== STILL_IMAGE_PROTOCOL
))
117 return DESCRIPTOR_SEARCH_Found
;
121 return DESCRIPTOR_SEARCH_NotFound
;
124 uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* CurrentDescriptor
)
126 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
128 USB_Descriptor_Endpoint_t
* CurrentEndpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
,
129 USB_Descriptor_Endpoint_t
);
131 uint8_t EndpointType
= (CurrentEndpoint
->Attributes
& EP_TYPE_MASK
);
133 if (((EndpointType
== EP_TYPE_BULK
) || (EndpointType
== EP_TYPE_INTERRUPT
)) &&
134 (!(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))))
136 return DESCRIPTOR_SEARCH_Found
;
139 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
141 return DESCRIPTOR_SEARCH_Fail
;
144 return DESCRIPTOR_SEARCH_NotFound
;
147 void SI_Host_USBTask(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
)
152 static uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
, SI_PIMA_Container_t
* PIMAHeader
)
156 if (SIInterfaceInfo
->State
.IsSessionOpen
)
157 PIMAHeader
->TransactionID
= SIInterfaceInfo
->State
.TransactionID
++;
159 PIMAHeader
->TransactionID
= 0;
161 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
164 if ((ErrorCode
= Pipe_Write_Stream_LE(PIMAHeader
, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
167 if (PIMAHeader
->Type
== CType_CommandBlock
)
169 uint8_t ParamBytes
= (PIMAHeader
->DataLength
- PIMA_COMMAND_SIZE(0));
173 if ((ErrorCode
= Pipe_Write_Stream_LE(&PIMAHeader
->Params
, ParamBytes
, NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
181 return PIPE_RWSTREAM_NoError
;
184 static uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
, SI_PIMA_Container_t
* PIMAHeader
)
186 uint16_t TimeoutMSRem
= COMMAND_DATA_TIMEOUT_MS
;
188 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
);
191 while (!(Pipe_IsReadWriteAllowed()))
193 if (USB_INT_HasOccurred(USB_INT_HSOFI
))
195 USB_INT_Clear(USB_INT_HSOFI
);
200 return PIPE_RWSTREAM_Timeout
;
205 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
208 if (Pipe_IsStalled())
210 USB_Host_ClearPipeStall(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
211 return PIPE_RWSTREAM_PipeStalled
;
215 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
);
218 if (Pipe_IsStalled())
220 USB_Host_ClearPipeStall(SIInterfaceInfo
->Config
.DataINPipeNumber
);
221 return PIPE_RWSTREAM_PipeStalled
;
224 if (USB_HostState
== HOST_STATE_Unattached
)
225 return PIPE_RWSTREAM_DeviceDisconnected
;
228 Pipe_Read_Stream_LE(PIMAHeader
, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK
);
230 if (PIMAHeader
->Type
== CType_ResponseBlock
)
232 uint8_t ParamBytes
= (PIMAHeader
->DataLength
- PIMA_COMMAND_SIZE(0));
235 Pipe_Read_Stream_LE(&PIMAHeader
->Params
, ParamBytes
, NO_STREAM_CALLBACK
);
239 PIMAHeader
->Code
&= 0x0000000F;
244 return PIPE_RWSTREAM_NoError
;
247 static uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
, void* Buffer
, uint16_t Bytes
)
251 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
);
254 ErrorCode
= Pipe_Write_Stream_LE(Buffer
, Bytes
, NO_STREAM_CALLBACK
);
262 static uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
, void* Buffer
, uint16_t Bytes
)
266 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
);
269 ErrorCode
= Pipe_Read_Stream_LE(Buffer
, Bytes
, NO_STREAM_CALLBACK
);
276 static bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
)
278 bool IsEventReceived
= false;
280 Pipe_SelectPipe(SIInterfaceInfo
->Config
.EventsPipeNumber
);
283 if (Pipe_BytesInPipe())
284 IsEventReceived
= true;
288 return IsEventReceived
;
291 static uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
, SI_PIMA_Container_t
* PIMAHeader
)
295 Pipe_SelectPipe(SIInterfaceInfo
->Config
.EventsPipeNumber
);
298 ErrorCode
= Pipe_Read_Stream_LE(PIMAHeader
, sizeof(SI_PIMA_Container_t
), NO_STREAM_CALLBACK
);
306 uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
)
308 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
309 return HOST_SENDCONTROL_DeviceDisconnect
;
313 SI_PIMA_Container_t PIMABlock
= (SI_PIMA_Container_t
)
315 .DataLength
= PIMA_COMMAND_SIZE(0),
316 .Type
= CType_CommandBlock
,
321 SIInterfaceInfo
->State
.TransactionID
= 1;
323 if ((ErrorCode
= SImage_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
326 if ((ErrorCode
= SImage_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
329 SIInterfaceInfo
->State
.IsSessionOpen
= true;
331 return PIPE_RWSTREAM_NoError
;
334 uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t
* SIInterfaceInfo
)
336 if ((USB_HostState
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
))
337 return HOST_SENDCONTROL_DeviceDisconnect
;
341 SI_PIMA_Container_t PIMABlock
= (SI_PIMA_Container_t
)
343 .DataLength
= PIMA_COMMAND_SIZE(0),
344 .Type
= CType_CommandBlock
,
349 if ((ErrorCode
= SImage_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
352 if ((ErrorCode
= SImage_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
)
355 SIInterfaceInfo
->State
.IsSessionOpen
= false;
357 return PIPE_RWSTREAM_NoError
;