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_AUDIO_DRIVER
37 #define __INCLUDE_FROM_AUDIO_HOST_C
38 #include "AudioClassHost.h"
40 uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t
* const AudioInterfaceInfo
,
41 uint16_t ConfigDescriptorSize
,
42 void* ConfigDescriptorData
)
44 USB_Descriptor_Endpoint_t
* DataINEndpoint
= NULL
;
45 USB_Descriptor_Endpoint_t
* DataOUTEndpoint
= NULL
;
46 USB_Descriptor_Interface_t
* AudioControlInterface
= NULL
;
47 USB_Descriptor_Interface_t
* AudioStreamingInterface
= NULL
;
49 memset(&AudioInterfaceInfo
->State
, 0x00, sizeof(AudioInterfaceInfo
->State
));
51 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
52 return AUDIO_ENUMERROR_InvalidConfigDescriptor
;
54 while ((AudioInterfaceInfo
->Config
.DataINPipeNumber
&& !(DataINEndpoint
)) ||
55 (AudioInterfaceInfo
->Config
.DataOUTPipeNumber
&& !(DataOUTEndpoint
)))
57 if (!(AudioControlInterface
) ||
58 USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
59 DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
61 if (!(AudioControlInterface
) ||
62 USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
63 DCOMP_Audio_Host_NextAudioStreamInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
65 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
66 DCOMP_Audio_Host_NextAudioControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
68 return AUDIO_ENUMERROR_NoCompatibleInterfaceFound
;
71 AudioControlInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
73 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
74 DCOMP_Audio_Host_NextAudioStreamInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
76 return AUDIO_ENUMERROR_NoCompatibleInterfaceFound
;
80 AudioStreamingInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
82 DataINEndpoint
= NULL
;
83 DataOUTEndpoint
= NULL
;
88 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
90 if ((EndpointData
->EndpointAddress
& ENDPOINT_DIR_MASK
) == ENDPOINT_DIR_IN
)
91 DataINEndpoint
= EndpointData
;
93 DataOUTEndpoint
= EndpointData
;
96 for (uint8_t PipeNum
= 1; PipeNum
< PIPE_TOTAL_PIPES
; PipeNum
++)
101 uint8_t EndpointAddress
;
104 if (PipeNum
== AudioInterfaceInfo
->Config
.DataINPipeNumber
)
106 Size
= le16_to_cpu(DataINEndpoint
->EndpointSize
);
107 EndpointAddress
= DataINEndpoint
->EndpointAddress
;
108 Token
= PIPE_TOKEN_IN
;
109 Type
= EP_TYPE_ISOCHRONOUS
;
112 AudioInterfaceInfo
->State
.DataINPipeSize
= DataINEndpoint
->EndpointSize
;
114 else if (PipeNum
== AudioInterfaceInfo
->Config
.DataOUTPipeNumber
)
116 Size
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
);
117 EndpointAddress
= DataOUTEndpoint
->EndpointAddress
;
118 Token
= PIPE_TOKEN_OUT
;
119 Type
= EP_TYPE_ISOCHRONOUS
;
122 AudioInterfaceInfo
->State
.DataOUTPipeSize
= DataOUTEndpoint
->EndpointSize
;
129 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
,
130 DoubleBanked ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
)))
132 return AUDIO_ENUMERROR_PipeConfigurationFailed
;
136 AudioInterfaceInfo
->State
.ControlInterfaceNumber
= AudioControlInterface
->InterfaceNumber
;
137 AudioInterfaceInfo
->State
.StreamingInterfaceNumber
= AudioStreamingInterface
->InterfaceNumber
;
138 AudioInterfaceInfo
->State
.EnabledStreamingAltIndex
= AudioStreamingInterface
->AlternateSetting
;
139 AudioInterfaceInfo
->State
.IsActive
= true;
141 return AUDIO_ENUMERROR_NoError
;
144 static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor
)
146 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
148 if (Header
->Type
== DTYPE_Interface
)
150 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
152 if ((Interface
->Class
== AUDIO_CSCP_AudioClass
) &&
153 (Interface
->SubClass
== AUDIO_CSCP_ControlSubclass
) &&
154 (Interface
->Protocol
== AUDIO_CSCP_ControlProtocol
))
156 return DESCRIPTOR_SEARCH_Found
;
160 return DESCRIPTOR_SEARCH_NotFound
;
163 static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor
)
165 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
167 if (Header
->Type
== DTYPE_Interface
)
169 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
171 if ((Interface
->Class
== AUDIO_CSCP_AudioClass
) &&
172 (Interface
->SubClass
== AUDIO_CSCP_AudioStreamingSubclass
) &&
173 (Interface
->Protocol
== AUDIO_CSCP_StreamingProtocol
))
175 return DESCRIPTOR_SEARCH_Found
;
179 return DESCRIPTOR_SEARCH_NotFound
;
182 static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor
)
184 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
186 if (Header
->Type
== DTYPE_Endpoint
)
188 USB_Descriptor_Endpoint_t
* Endpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
);
190 if ((Endpoint
->Attributes
& EP_TYPE_MASK
) == EP_TYPE_ISOCHRONOUS
)
191 return DESCRIPTOR_SEARCH_Found
;
193 else if (Header
->Type
== DTYPE_Interface
)
195 return DESCRIPTOR_SEARCH_Fail
;
198 return DESCRIPTOR_SEARCH_NotFound
;
201 uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t
* const AudioInterfaceInfo
,
202 const bool EnableStreaming
)
204 if (!(AudioInterfaceInfo
->State
.IsActive
))
205 return HOST_SENDCONTROL_DeviceDisconnected
;
207 return USB_Host_SetInterfaceAltSetting(AudioInterfaceInfo
->State
.StreamingInterfaceNumber
,
208 EnableStreaming ? AudioInterfaceInfo
->State
.EnabledStreamingAltIndex
: 0);
211 uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t
* const AudioInterfaceInfo
,
212 const uint8_t DataPipeIndex
,
213 const uint8_t EndpointProperty
,
214 const uint8_t EndpointControl
,
215 const uint16_t DataLength
,
218 if (!(AudioInterfaceInfo
->State
.IsActive
))
219 return HOST_SENDCONTROL_DeviceDisconnected
;
222 uint8_t EndpointAddress
;
224 if (EndpointProperty
& 0x80)
225 RequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_ENDPOINT
);
227 RequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_ENDPOINT
);
229 Pipe_SelectPipe(DataPipeIndex
);
230 EndpointAddress
= Pipe_GetBoundEndpointAddress();
232 USB_ControlRequest
= (USB_Request_Header_t
)
234 .bmRequestType
= RequestType
,
235 .bRequest
= EndpointProperty
,
236 .wValue
= ((uint16_t)EndpointControl
<< 8),
237 .wIndex
= EndpointAddress
,
238 .wLength
= DataLength
,
241 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
243 return USB_Host_SendControlRequest(Data
);