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_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 if (DeviceDescriptor
->Header
.Type
!= DTYPE_Device
)
47 if (DeviceDescriptor
->VendorID
!= ANDROID_VENDOR_ID
)
50 *NeedModeSwitch
= ((DeviceDescriptor
->ProductID
!= ANDROID_ACCESSORY_PRODUCT_ID
) &&
51 (DeviceDescriptor
->ProductID
!= ANDROID_ACCESSORY_ADB_PRODUCT_ID
));
56 uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
57 uint16_t ConfigDescriptorSize
,
58 void* ConfigDescriptorData
)
60 USB_Descriptor_Endpoint_t
* DataINEndpoint
= NULL
;
61 USB_Descriptor_Endpoint_t
* DataOUTEndpoint
= NULL
;
62 USB_Descriptor_Interface_t
* AOAInterface
= NULL
;
64 memset(&AOAInterfaceInfo
->State
, 0x00, sizeof(AOAInterfaceInfo
->State
));
66 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
67 return AOA_ENUMERROR_InvalidConfigDescriptor
;
69 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
70 DCOMP_AOA_Host_NextAndroidAccessoryInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
72 return AOA_ENUMERROR_NoCompatibleInterfaceFound
;
75 AOAInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
77 while (!(DataINEndpoint
) || !(DataOUTEndpoint
))
79 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
80 DCOMP_AOA_Host_NextInterfaceBulkEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
82 return AOA_ENUMERROR_NoCompatibleInterfaceFound
;
85 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
87 if ((EndpointData
->EndpointAddress
& ENDPOINT_DIR_MASK
) == ENDPOINT_DIR_IN
)
88 DataINEndpoint
= EndpointData
;
90 DataOUTEndpoint
= EndpointData
;
93 for (uint8_t PipeNum
= 1; PipeNum
< PIPE_TOTAL_PIPES
; PipeNum
++)
98 uint8_t EndpointAddress
;
101 if (PipeNum
== AOAInterfaceInfo
->Config
.DataINPipeNumber
)
103 Size
= le16_to_cpu(DataINEndpoint
->EndpointSize
);
104 EndpointAddress
= DataINEndpoint
->EndpointAddress
;
105 Token
= PIPE_TOKEN_IN
;
107 DoubleBanked
= AOAInterfaceInfo
->Config
.DataINPipeDoubleBank
;
109 AOAInterfaceInfo
->State
.DataINPipeSize
= DataINEndpoint
->EndpointSize
;
111 else if (PipeNum
== AOAInterfaceInfo
->Config
.DataOUTPipeNumber
)
113 Size
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
);
114 EndpointAddress
= DataOUTEndpoint
->EndpointAddress
;
115 Token
= PIPE_TOKEN_OUT
;
117 DoubleBanked
= AOAInterfaceInfo
->Config
.DataOUTPipeDoubleBank
;
119 AOAInterfaceInfo
->State
.DataOUTPipeSize
= DataOUTEndpoint
->EndpointSize
;
126 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
,
127 DoubleBanked ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
)))
129 return AOA_ENUMERROR_PipeConfigurationFailed
;
133 AOAInterfaceInfo
->State
.IsActive
= true;
134 AOAInterfaceInfo
->State
.InterfaceNumber
= AOAInterface
->InterfaceNumber
;
136 return AOA_ENUMERROR_NoError
;
139 static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor
)
141 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
143 if (Header
->Type
== DTYPE_Interface
)
145 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
147 if ((Interface
->Class
== AOA_CSCP_AOADataClass
) &&
148 (Interface
->SubClass
== AOA_CSCP_AOADataSubclass
) &&
149 (Interface
->Protocol
== AOA_CSCP_AOADataProtocol
))
151 return DESCRIPTOR_SEARCH_Found
;
155 return DESCRIPTOR_SEARCH_NotFound
;
158 static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor
)
160 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
162 if (Header
->Type
== DTYPE_Endpoint
)
164 USB_Descriptor_Endpoint_t
* Endpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
);
166 uint8_t EndpointType
= (Endpoint
->Attributes
& EP_TYPE_MASK
);
168 if ((EndpointType
== EP_TYPE_BULK
) && (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))))
169 return DESCRIPTOR_SEARCH_Found
;
171 else if (Header
->Type
== DTYPE_Interface
)
173 return DESCRIPTOR_SEARCH_Fail
;
176 return DESCRIPTOR_SEARCH_NotFound
;
179 void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
)
181 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
184 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
185 AOA_Host_Flush(AOAInterfaceInfo
);
189 uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
)
193 uint16_t AccessoryProtocol
;
194 if ((ErrorCode
= AOA_Host_GetAccessoryProtocol(&AccessoryProtocol
)) != HOST_WAITERROR_Successful
)
197 if (AccessoryProtocol
!= CPU_TO_LE16(AOA_PROTOCOL_AccessoryV1
))
198 return AOA_ERROR_LOGICAL_CMD_FAILED
;
200 for (uint8_t PropertyIndex
= 0; PropertyIndex
< AOA_STRING_TOTAL_STRINGS
; PropertyIndex
++)
202 if ((ErrorCode
= AOA_Host_SendPropertyString(AOAInterfaceInfo
, PropertyIndex
)) != HOST_WAITERROR_Successful
)
206 USB_ControlRequest
= (USB_Request_Header_t
)
208 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_VENDOR
| REQREC_DEVICE
),
209 .bRequest
= AOA_REQ_StartAccessoryMode
,
215 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
216 return USB_Host_SendControlRequest(NULL
);
219 static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol
)
221 USB_ControlRequest
= (USB_Request_Header_t
)
223 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_VENDOR
| REQREC_DEVICE
),
224 .bRequest
= AOA_REQ_GetAccessoryProtocol
,
227 .wLength
= sizeof(uint16_t),
230 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
231 return USB_Host_SendControlRequest(Protocol
);
234 static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
235 const uint8_t StringIndex
)
237 const char* String
= ((char**)&AOAInterfaceInfo
->Config
.PropertyStrings
)[StringIndex
];
242 USB_ControlRequest
= (USB_Request_Header_t
)
244 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_VENDOR
| REQREC_DEVICE
),
245 .bRequest
= AOA_REQ_SendString
,
247 .wIndex
= StringIndex
,
248 .wLength
= (strlen(String
) + 1),
251 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
252 return USB_Host_SendControlRequest((char*)String
);
255 uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
256 const uint8_t* const Buffer
,
257 const uint16_t Length
)
259 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
260 return PIPE_READYWAIT_DeviceDisconnected
;
264 Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipeNumber
);
267 ErrorCode
= Pipe_Write_Stream_LE(Buffer
, Length
, NULL
);
273 uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
274 const char* const String
)
276 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
277 return PIPE_READYWAIT_DeviceDisconnected
;
281 Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipeNumber
);
284 ErrorCode
= Pipe_Write_Stream_LE(String
, strlen(String
), NULL
);
290 uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
293 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
294 return PIPE_READYWAIT_DeviceDisconnected
;
298 Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipeNumber
);
301 if (!(Pipe_IsReadWriteAllowed()))
305 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
312 return PIPE_READYWAIT_NoError
;
315 uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
)
317 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
320 Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataINPipeNumber
);
323 if (Pipe_IsINReceived())
325 if (!(Pipe_BytesInPipe()))
334 return Pipe_BytesInPipe();
345 int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
)
347 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
350 int16_t ReceivedByte
= -1;
352 Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataINPipeNumber
);
355 if (Pipe_IsINReceived())
357 if (Pipe_BytesInPipe())
358 ReceivedByte
= Pipe_Read_8();
360 if (!(Pipe_BytesInPipe()))
369 uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
)
371 if ((USB_HostState
!= HOST_STATE_Configured
) || !(AOAInterfaceInfo
->State
.IsActive
))
372 return PIPE_READYWAIT_DeviceDisconnected
;
376 Pipe_SelectPipe(AOAInterfaceInfo
->Config
.DataOUTPipeNumber
);
379 if (!(Pipe_BytesInPipe()))
380 return PIPE_READYWAIT_NoError
;
382 bool BankFull
= !(Pipe_IsReadWriteAllowed());
388 if ((ErrorCode
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
)
396 return PIPE_READYWAIT_NoError
;
399 #if defined(FDEV_SETUP_STREAM)
400 void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
403 *Stream
= (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar
, AOA_Host_getchar
, _FDEV_SETUP_RW
);
404 fdev_set_udata(Stream
, AOAInterfaceInfo
);
407 void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t
* const AOAInterfaceInfo
,
410 *Stream
= (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar
, AOA_Host_getchar_Blocking
, _FDEV_SETUP_RW
);
411 fdev_set_udata(Stream
, AOAInterfaceInfo
);
414 static int AOA_Host_putchar(char c
,
417 return AOA_Host_SendByte((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
), c
) ? _FDEV_ERR
: 0;
420 static int AOA_Host_getchar(FILE* Stream
)
422 int16_t ReceivedByte
= AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
));
424 if (ReceivedByte
< 0)
430 static int AOA_Host_getchar_Blocking(FILE* Stream
)
432 int16_t ReceivedByte
;
434 while ((ReceivedByte
= AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
))) < 0)
436 if (USB_HostState
== HOST_STATE_Unattached
)
439 AOA_Host_USBTask((USB_ClassInfo_AOA_Host_t
*)fdev_get_udata(Stream
));