3      Copyright (C) Dean Camera, 2011. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2011  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 #define  __INCLUDE_FROM_USB_DRIVER 
  32 #include "../../Core/USBMode.h" 
  34 #if defined(USB_CAN_BE_HOST) 
  36 #define  __INCLUDE_FROM_SI_DRIVER 
  37 #define  __INCLUDE_FROM_STILLIMAGE_HOST_C 
  38 #include "StillImage.h" 
  40 uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
  41                                uint16_t ConfigDescriptorSize
, 
  42                                void* ConfigDescriptorData
) 
  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
; 
  49         memset(&SIInterfaceInfo
->State
, 0x00, sizeof(SIInterfaceInfo
->State
)); 
  51         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  52           return SI_ENUMERROR_InvalidConfigDescriptor
; 
  54         while (!(DataINEndpoint
) || !(DataOUTEndpoint
) || !(EventsEndpoint
)) 
  56                 if (!(StillImageInterface
) || 
  57                     USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  58                                               DCOMP_SI_Host_NextSIInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  60                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  61                                                       DCOMP_SI_Host_NextSIInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  63                                 return SI_ENUMERROR_NoCompatibleInterfaceFound
; 
  66                         StillImageInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  68                         DataINEndpoint  
= NULL
; 
  69                         DataOUTEndpoint 
= NULL
; 
  70                         EventsEndpoint  
= NULL
; 
  75                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  77                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  79                         if ((EndpointData
->Attributes 
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
) 
  80                           EventsEndpoint 
= EndpointData
; 
  82                           DataINEndpoint 
= EndpointData
; 
  86                         DataOUTEndpoint 
= EndpointData
; 
  90         for (uint8_t PipeNum 
= 1; PipeNum 
< PIPE_TOTAL_PIPES
; PipeNum
++) 
  95                 uint8_t  EndpointAddress
; 
  96                 uint8_t  InterruptPeriod
; 
  99                 if (PipeNum 
== SIInterfaceInfo
->Config
.DataINPipeNumber
) 
 101                         Size            
= DataINEndpoint
->EndpointSize
; 
 102                         EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
 103                         Token           
= PIPE_TOKEN_IN
; 
 105                         DoubleBanked    
= SIInterfaceInfo
->Config
.DataINPipeDoubleBank
; 
 108                         SIInterfaceInfo
->State
.DataINPipeSize 
= DataINEndpoint
->EndpointSize
; 
 110                 else if (PipeNum 
== SIInterfaceInfo
->Config
.DataOUTPipeNumber
) 
 112                         Size            
= DataOUTEndpoint
->EndpointSize
; 
 113                         EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 114                         Token           
= PIPE_TOKEN_OUT
; 
 116                         DoubleBanked    
= SIInterfaceInfo
->Config
.DataOUTPipeDoubleBank
; 
 119                         SIInterfaceInfo
->State
.DataOUTPipeSize 
= DataOUTEndpoint
->EndpointSize
; 
 121                 else if (PipeNum 
== SIInterfaceInfo
->Config
.EventsPipeNumber
) 
 123                         Size            
= EventsEndpoint
->EndpointSize
; 
 124                         EndpointAddress 
= EventsEndpoint
->EndpointAddress
; 
 125                         Token           
= PIPE_TOKEN_IN
; 
 126                         Type            
= EP_TYPE_INTERRUPT
; 
 127                         DoubleBanked    
= SIInterfaceInfo
->Config
.EventsPipeDoubleBank
; 
 128                         InterruptPeriod 
= EventsEndpoint
->PollingIntervalMS
; 
 130                         SIInterfaceInfo
->State
.EventsPipeSize 
= EventsEndpoint
->EndpointSize
; 
 137                 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
, 
 138                                          DoubleBanked ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
))) 
 140                         return SI_ENUMERROR_PipeConfigurationFailed
; 
 144                   Pipe_SetInterruptPeriod(InterruptPeriod
); 
 147         SIInterfaceInfo
->State
.InterfaceNumber 
= StillImageInterface
->InterfaceNumber
; 
 148         SIInterfaceInfo
->State
.IsActive 
= true; 
 150         return SI_ENUMERROR_NoError
; 
 153 uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor
) 
 155         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 157         if (Header
->Type 
== DTYPE_Interface
) 
 159                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 161                 if ((Interface
->Class    
== SI_CSCP_StillImageClass
)    && 
 162                     (Interface
->SubClass 
== SI_CSCP_StillImageSubclass
) && 
 163                     (Interface
->Protocol 
== SI_CSCP_BulkOnlyProtocol
)) 
 165                         return DESCRIPTOR_SEARCH_Found
; 
 169         return DESCRIPTOR_SEARCH_NotFound
; 
 172 uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor
) 
 174         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 176         if (Header
->Type 
== DTYPE_Endpoint
) 
 178                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 180                 uint8_t EndpointType 
= (Endpoint
->Attributes 
& EP_TYPE_MASK
); 
 182                 if (((EndpointType 
== EP_TYPE_BULK
) || (EndpointType 
== EP_TYPE_INTERRUPT
)) && 
 183                     (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
)))) 
 185                         return DESCRIPTOR_SEARCH_Found
; 
 188         else if (Header
->Type 
== DTYPE_Interface
) 
 190                 return DESCRIPTOR_SEARCH_Fail
; 
 193         return DESCRIPTOR_SEARCH_NotFound
; 
 196 uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
 197                                 PIMA_Container_t
* const PIMAHeader
) 
 201         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 202           return PIPE_RWSTREAM_DeviceDisconnected
; 
 204         if (SIInterfaceInfo
->State
.IsSessionOpen
) 
 205           PIMAHeader
->TransactionID 
= SIInterfaceInfo
->State
.TransactionID
++; 
 207         Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 210         if ((ErrorCode 
= Pipe_Write_Stream_LE(PIMAHeader
, PIMA_COMMAND_SIZE(0), NULL
)) != PIPE_RWSTREAM_NoError
) 
 213         uint8_t ParamBytes 
= (PIMAHeader
->DataLength 
- PIMA_COMMAND_SIZE(0)); 
 217                 if ((ErrorCode 
= Pipe_Write_Stream_LE(&PIMAHeader
->Params
, ParamBytes
, NULL
)) != PIPE_RWSTREAM_NoError
) 
 224         return PIPE_RWSTREAM_NoError
; 
 227 uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
 228                                    PIMA_Container_t
* const PIMAHeader
) 
 230         uint16_t TimeoutMSRem        
= SI_COMMAND_DATA_TIMEOUT_MS
; 
 231         uint16_t PreviousFrameNumber 
= USB_Host_GetFrameNumber(); 
 233         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 234           return PIPE_RWSTREAM_DeviceDisconnected
; 
 236         Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
); 
 239         while (!(Pipe_IsINReceived())) 
 241                 uint16_t CurrentFrameNumber 
= USB_Host_GetFrameNumber(); 
 243                 if (CurrentFrameNumber 
!= PreviousFrameNumber
) 
 245                         PreviousFrameNumber 
= CurrentFrameNumber
; 
 247                         if (!(TimeoutMSRem
--)) 
 248                           return PIPE_RWSTREAM_Timeout
; 
 252                 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 255                 if (Pipe_IsStalled()) 
 257                         USB_Host_ClearPipeStall(SIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 258                         return PIPE_RWSTREAM_PipeStalled
; 
 262                 Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
); 
 265                 if (Pipe_IsStalled()) 
 267                         USB_Host_ClearPipeStall(SIInterfaceInfo
->Config
.DataINPipeNumber
); 
 268                         return PIPE_RWSTREAM_PipeStalled
; 
 271                 if (USB_HostState 
== HOST_STATE_Unattached
) 
 272                   return PIPE_RWSTREAM_DeviceDisconnected
; 
 275         Pipe_Read_Stream_LE(PIMAHeader
, PIMA_COMMAND_SIZE(0), NULL
); 
 277         if (PIMAHeader
->Type 
== PIMA_CONTAINER_ResponseBlock
) 
 279                 uint8_t ParamBytes 
= (PIMAHeader
->DataLength 
- PIMA_COMMAND_SIZE(0)); 
 282                   Pipe_Read_Stream_LE(&PIMAHeader
->Params
, ParamBytes
, NULL
); 
 289         return PIPE_RWSTREAM_NoError
; 
 292 uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
 294                          const uint16_t Bytes
) 
 298         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 299           return PIPE_RWSTREAM_DeviceDisconnected
; 
 301         Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 304         ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, Bytes
, NULL
); 
 312 uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
 314                          const uint16_t Bytes
) 
 318         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 319           return PIPE_RWSTREAM_DeviceDisconnected
; 
 321         Pipe_SelectPipe(SIInterfaceInfo
->Config
.DataINPipeNumber
); 
 324         ErrorCode 
= Pipe_Read_Stream_LE(Buffer
, Bytes
, NULL
); 
 331 bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
) 
 333         bool IsEventReceived 
= false; 
 335         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 338         Pipe_SelectPipe(SIInterfaceInfo
->Config
.EventsPipeNumber
); 
 341         if (Pipe_BytesInPipe()) 
 342           IsEventReceived 
= true; 
 346         return IsEventReceived
; 
 349 uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
 350                                    PIMA_Container_t
* const PIMAHeader
) 
 354         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 355           return PIPE_RWSTREAM_DeviceDisconnected
; 
 357         Pipe_SelectPipe(SIInterfaceInfo
->Config
.EventsPipeNumber
); 
 360         ErrorCode 
= Pipe_Read_Stream_LE(PIMAHeader
, sizeof(PIMA_Container_t
), NULL
); 
 368 uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
) 
 370         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 371           return PIPE_RWSTREAM_DeviceDisconnected
; 
 375         SIInterfaceInfo
->State
.TransactionID 
= 0; 
 376         SIInterfaceInfo
->State
.IsSessionOpen 
= false; 
 378         PIMA_Container_t PIMABlock 
= (PIMA_Container_t
) 
 380                         .DataLength    
= PIMA_COMMAND_SIZE(1), 
 381                         .Type          
= PIMA_CONTAINER_CommandBlock
, 
 386         if ((ErrorCode 
= SI_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
) 
 389         if ((ErrorCode 
= SI_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
) 
 392         if ((PIMABlock
.Type 
!= PIMA_CONTAINER_ResponseBlock
) || (PIMABlock
.Code 
!= 0x2001)) 
 393           return SI_ERROR_LOGICAL_CMD_FAILED
; 
 395         SIInterfaceInfo
->State
.IsSessionOpen 
= true; 
 397         return PIPE_RWSTREAM_NoError
; 
 400 uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
) 
 402         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 403           return PIPE_RWSTREAM_DeviceDisconnected
; 
 407         PIMA_Container_t PIMABlock 
= (PIMA_Container_t
) 
 409                         .DataLength    
= PIMA_COMMAND_SIZE(1), 
 410                         .Type          
= PIMA_CONTAINER_CommandBlock
, 
 415         if ((ErrorCode 
= SI_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
) 
 418         if ((ErrorCode 
= SI_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
) 
 421         SIInterfaceInfo
->State
.IsSessionOpen 
= false; 
 423         if ((PIMABlock
.Type 
!= PIMA_CONTAINER_ResponseBlock
) || (PIMABlock
.Code 
!= 0x2001)) 
 424           return SI_ERROR_LOGICAL_CMD_FAILED
; 
 426         return PIPE_RWSTREAM_NoError
; 
 429 uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
, 
 430                             const uint16_t Operation
, 
 431                             const uint8_t TotalParams
, 
 432                             uint32_t* const Params
) 
 434         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 435           return PIPE_RWSTREAM_DeviceDisconnected
; 
 439         PIMA_Container_t PIMABlock 
= (PIMA_Container_t
) 
 441                         .DataLength    
= PIMA_COMMAND_SIZE(TotalParams
), 
 442                         .Type          
= PIMA_CONTAINER_CommandBlock
, 
 446         memcpy(&PIMABlock
.Params
, Params
, sizeof(uint32_t) * TotalParams
); 
 448         if ((ErrorCode 
= SI_Host_SendBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
) 
 451         return PIPE_RWSTREAM_NoError
; 
 454 uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t
* const SIInterfaceInfo
) 
 457         PIMA_Container_t PIMABlock
; 
 459         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(SIInterfaceInfo
->State
.IsActive
)) 
 460           return PIPE_RWSTREAM_DeviceDisconnected
; 
 462         if ((ErrorCode 
= SI_Host_ReceiveBlockHeader(SIInterfaceInfo
, &PIMABlock
)) != PIPE_RWSTREAM_NoError
) 
 465         if ((PIMABlock
.Type 
!= PIMA_CONTAINER_ResponseBlock
) || (PIMABlock
.Code 
!= 0x2001)) 
 466           return SI_ERROR_LOGICAL_CMD_FAILED
; 
 468         return PIPE_RWSTREAM_NoError
;