3      Copyright (C) Dean Camera, 2013. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2013  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 disclaims 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_AOA_DRIVER 
  37 #define  __INCLUDE_FROM_ANDROIDACCESSORY_HOST_C 
  38 #include "AndroidAccessoryClassHost.h" 
  40 bool AOA_Host_ValidateAccessoryDevice(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
  41                                       const USB_Descriptor_Device_t
* const DeviceDescriptor
, 
  42                                       bool* const NeedModeSwitch
) 
  44         (void)AOAInterfaceInfo
; 
  46         if (DeviceDescriptor
->Header
.Type 
!= DTYPE_Device
) 
  49         *NeedModeSwitch 
= ((DeviceDescriptor
->ProductID 
!= ANDROID_ACCESSORY_PRODUCT_ID
) && 
  50                            (DeviceDescriptor
->ProductID 
!= ANDROID_ACCESSORY_ADB_PRODUCT_ID
)); 
  55 uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
  56                                 uint16_t ConfigDescriptorSize
, 
  57                                 void* ConfigDescriptorData
) 
  59         USB_Descriptor_Endpoint_t
*  DataINEndpoint  
= NULL
; 
  60         USB_Descriptor_Endpoint_t
*  DataOUTEndpoint 
= NULL
; 
  61         USB_Descriptor_Interface_t
* AOAInterface    
= NULL
; 
  63         memset(&AOAInterfaceInfo
->State
, 0x00, sizeof(AOAInterfaceInfo
->State
)); 
  65         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  66           return AOA_ENUMERROR_InvalidConfigDescriptor
; 
  68         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  69                                       DCOMP_AOA_Host_NextAndroidAccessoryInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  71                 return AOA_ENUMERROR_NoCompatibleInterfaceFound
; 
  74         AOAInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  76         while (!(DataINEndpoint
) || !(DataOUTEndpoint
)) 
  78                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  79                                               DCOMP_AOA_Host_NextInterfaceBulkEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  81                         return AOA_ENUMERROR_NoCompatibleInterfaceFound
; 
  84                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  86                 if ((EndpointData
->EndpointAddress 
& ENDPOINT_DIR_MASK
) == ENDPOINT_DIR_IN
) 
  87                   DataINEndpoint  
= EndpointData
; 
  89                   DataOUTEndpoint 
= EndpointData
; 
  92         AOAInterfaceInfo
->Config
.DataINPipe
.Size  
= le16_to_cpu(DataINEndpoint
->EndpointSize
); 
  93         AOAInterfaceInfo
->Config
.DataINPipe
.EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
  94         AOAInterfaceInfo
->Config
.DataINPipe
.Type  
= EP_TYPE_BULK
; 
  96         AOAInterfaceInfo
->Config
.DataOUTPipe
.Size 
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
); 
  97         AOAInterfaceInfo
->Config
.DataOUTPipe
.EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
  98         AOAInterfaceInfo
->Config
.DataOUTPipe
.Type 
= EP_TYPE_BULK
; 
 100         if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo
->Config
.DataINPipe
, 1))) 
 103         if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo
->Config
.DataOUTPipe
, 1))) 
 106         AOAInterfaceInfo
->State
.IsActive        
= true; 
 107         AOAInterfaceInfo
->State
.InterfaceNumber 
= AOAInterface
->InterfaceNumber
; 
 109         return AOA_ENUMERROR_NoError
; 
 112 static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor
) 
 114         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 116         if (Header
->Type 
== DTYPE_Interface
) 
 118                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 120                 if ((Interface
->Class    
== AOA_CSCP_AOADataClass
)    && 
 121                     (Interface
->SubClass 
== AOA_CSCP_AOADataSubclass
) && 
 122                     (Interface
->Protocol 
== AOA_CSCP_AOADataProtocol
)) 
 124                         return DESCRIPTOR_SEARCH_Found
; 
 128         return DESCRIPTOR_SEARCH_NotFound
; 
 131 static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor
) 
 133         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 135         if (Header
->Type 
== DTYPE_Endpoint
) 
 137                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 139                 uint8_t EndpointType 
= (Endpoint
->Attributes 
& EP_TYPE_MASK
); 
 141                 if ((EndpointType 
== EP_TYPE_BULK
) && (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
)))) 
 142                   return DESCRIPTOR_SEARCH_Found
; 
 144         else if (Header
->Type 
== DTYPE_Interface
) 
 146                 return DESCRIPTOR_SEARCH_Fail
; 
 149         return DESCRIPTOR_SEARCH_NotFound
; 
 152 void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
) 
 154         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 157         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) 
 158         AOA_Host_Flush(AOAInterfaceInfo
); 
 162 uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
) 
 166         uint16_t AccessoryProtocol
; 
 167         if ((ErrorCode 
= AOA_Host_GetAccessoryProtocol(&AccessoryProtocol
)) != HOST_WAITERROR_Successful
) 
 170         if ((AccessoryProtocol 
!= CPU_TO_LE16(AOA_PROTOCOL_AccessoryV1
)) && (AccessoryProtocol 
!= CPU_TO_LE16(AOA_PROTOCOL_AccessoryV2
))) 
 171           return AOA_ERROR_LOGICAL_CMD_FAILED
; 
 173         for (uint8_t PropertyIndex 
= 0; PropertyIndex 
< AOA_STRING_TOTAL_STRINGS
; PropertyIndex
++) 
 175                 if ((ErrorCode 
= AOA_Host_SendPropertyString(AOAInterfaceInfo
, PropertyIndex
)) != HOST_WAITERROR_Successful
) 
 179         USB_ControlRequest 
= (USB_Request_Header_t
) 
 181                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_VENDOR 
| REQREC_DEVICE
), 
 182                 .bRequest      
= AOA_REQ_StartAccessoryMode
, 
 188         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 189         return USB_Host_SendControlRequest(NULL
); 
 192 static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol
) 
 194         USB_ControlRequest 
= (USB_Request_Header_t
) 
 196                 .bmRequestType 
= (REQDIR_DEVICETOHOST 
| REQTYPE_VENDOR 
| REQREC_DEVICE
), 
 197                 .bRequest      
= AOA_REQ_GetAccessoryProtocol
, 
 200                 .wLength       
= sizeof(uint16_t), 
 203         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 204         return USB_Host_SendControlRequest(Protocol
); 
 207 static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
 208                                            const uint8_t StringIndex
) 
 210         const char* String 
= AOAInterfaceInfo
->Config
.PropertyStrings
[StringIndex
]; 
 215         USB_ControlRequest 
= (USB_Request_Header_t
) 
 217                 .bmRequestType 
= (REQDIR_HOSTTODEVICE 
| REQTYPE_VENDOR 
| REQREC_DEVICE
), 
 218                 .bRequest      
= AOA_REQ_SendString
, 
 220                 .wIndex        
= StringIndex
, 
 221                 .wLength       
= (strlen(String
) + 1), 
 224         Pipe_SelectPipe(PIPE_CONTROLPIPE
); 
 225         return USB_Host_SendControlRequest((char*)String
); 
 228 uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
 229                           const void* const Buffer
, 
 230                           const uint16_t Length
) 
 232         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 233           return PIPE_READYWAIT_DeviceDisconnected
; 
 237         Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipe
.Address
); 
 240         ErrorCode 
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
); 
 246 uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
 247                             const char* const String
) 
 249         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 250           return PIPE_READYWAIT_DeviceDisconnected
; 
 254         Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipe
.Address
); 
 257         ErrorCode 
= Pipe_Write_Stream_LE(String
, strlen(String
), NULL
); 
 263 uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
 266         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 267           return PIPE_READYWAIT_DeviceDisconnected
; 
 271         Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipe
.Address
); 
 274         if (!(Pipe_IsReadWriteAllowed())) 
 278                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 285         return PIPE_READYWAIT_NoError
; 
 288 uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
) 
 290         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 293         Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataINPipe
.Address
); 
 296         if (Pipe_IsINReceived()) 
 298                 if (!(Pipe_BytesInPipe())) 
 307                         return Pipe_BytesInPipe(); 
 318 int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
) 
 320         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 323         int16_t ReceivedByte 
= -1; 
 325         Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataINPipe
.Address
); 
 328         if (Pipe_IsINReceived()) 
 330                 if (Pipe_BytesInPipe()) 
 331                   ReceivedByte 
= Pipe_Read_8(); 
 333                 if (!(Pipe_BytesInPipe())) 
 342 uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
) 
 344         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
)) 
 345           return PIPE_READYWAIT_DeviceDisconnected
; 
 349         Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipe
.Address
); 
 352         if (!(Pipe_BytesInPipe())) 
 353           return PIPE_READYWAIT_NoError
; 
 355         bool BankFull 
= !(Pipe_IsReadWriteAllowed()); 
 361                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 369         return PIPE_READYWAIT_NoError
; 
 372 #if defined(FDEV_SETUP_STREAM) 
 373 void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
 376         *Stream 
= (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar
, AOA_Host_getchar
, _FDEV_SETUP_RW
); 
 377         fdev_set_udata(Stream
, AOAInterfaceInfo
); 
 380 void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
, 
 383         *Stream 
= (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar
, AOA_Host_getchar_Blocking
, _FDEV_SETUP_RW
); 
 384         fdev_set_udata(Stream
, AOAInterfaceInfo
); 
 387 static int AOA_Host_putchar(char c
, 
 390         return AOA_Host_SendByte((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR 
: 0; 
 393 static int AOA_Host_getchar(FILE* Stream
) 
 395         int16_t ReceivedByte 
= AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
)); 
 397         if (ReceivedByte 
< 0) 
 403 static int AOA_Host_getchar_Blocking(FILE* Stream
) 
 405         int16_t ReceivedByte
; 
 407         while ((ReceivedByte 
= AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
))) < 0) 
 409                 if (USB_HostState 
== HOST_STATE_Unattached
) 
 412                 AOA_Host_USBTask((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
));