Added Class, ClassDevice, ClassHost and ClassCommon to the internal class driver...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / AudioClassHost.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../Core/USBMode.h"
33
34 #if defined(USB_CAN_BE_HOST)
35
36 #define __INCLUDE_FROM_AUDIO_DRIVER
37 #define __INCLUDE_FROM_AUDIO_HOST_C
38 #include "AudioClassHost.h"
39
40 uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
41 uint16_t ConfigDescriptorSize,
42 void* ConfigDescriptorData)
43 {
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;
48
49 memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
50
51 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
52 return AUDIO_ENUMERROR_InvalidConfigDescriptor;
53
54 while ((AudioInterfaceInfo->Config.DataINPipeNumber && !(DataINEndpoint)) ||
55 (AudioInterfaceInfo->Config.DataOUTPipeNumber && !(DataOUTEndpoint)))
56 {
57 if (!(AudioControlInterface) ||
58 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
59 DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
60 {
61 if (!(AudioControlInterface) ||
62 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
63 DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found)
64 {
65 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
66 DCOMP_Audio_Host_NextAudioControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
67 {
68 return AUDIO_ENUMERROR_NoCompatibleInterfaceFound;
69 }
70
71 AudioControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
72
73 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
74 DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found)
75 {
76 return AUDIO_ENUMERROR_NoCompatibleInterfaceFound;
77 }
78 }
79
80 AudioStreamingInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
81
82 DataINEndpoint = NULL;
83 DataOUTEndpoint = NULL;
84
85 continue;
86 }
87
88 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
89
90 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
91 DataINEndpoint = EndpointData;
92 else
93 DataOUTEndpoint = EndpointData;
94 }
95
96 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
97 {
98 uint16_t Size;
99 uint8_t Type;
100 uint8_t Token;
101 uint8_t EndpointAddress;
102 bool DoubleBanked;
103
104 if (PipeNum == AudioInterfaceInfo->Config.DataINPipeNumber)
105 {
106 Size = le16_to_cpu(DataINEndpoint->EndpointSize);
107 EndpointAddress = DataINEndpoint->EndpointAddress;
108 Token = PIPE_TOKEN_IN;
109 Type = EP_TYPE_ISOCHRONOUS;
110 DoubleBanked = true;
111
112 AudioInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
113 }
114 else if (PipeNum == AudioInterfaceInfo->Config.DataOUTPipeNumber)
115 {
116 Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
117 EndpointAddress = DataOUTEndpoint->EndpointAddress;
118 Token = PIPE_TOKEN_OUT;
119 Type = EP_TYPE_ISOCHRONOUS;
120 DoubleBanked = true;
121
122 AudioInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
123 }
124 else
125 {
126 continue;
127 }
128
129 if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
130 DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
131 {
132 return AUDIO_ENUMERROR_PipeConfigurationFailed;
133 }
134 }
135
136 AudioInterfaceInfo->State.ControlInterfaceNumber = AudioControlInterface->InterfaceNumber;
137 AudioInterfaceInfo->State.StreamingInterfaceNumber = AudioStreamingInterface->InterfaceNumber;
138 AudioInterfaceInfo->State.EnabledStreamingAltIndex = AudioStreamingInterface->AlternateSetting;
139 AudioInterfaceInfo->State.IsActive = true;
140
141 return AUDIO_ENUMERROR_NoError;
142 }
143
144 static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor)
145 {
146 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
147
148 if (Header->Type == DTYPE_Interface)
149 {
150 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
151
152 if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
153 (Interface->SubClass == AUDIO_CSCP_ControlSubclass) &&
154 (Interface->Protocol == AUDIO_CSCP_ControlProtocol))
155 {
156 return DESCRIPTOR_SEARCH_Found;
157 }
158 }
159
160 return DESCRIPTOR_SEARCH_NotFound;
161 }
162
163 static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor)
164 {
165 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
166
167 if (Header->Type == DTYPE_Interface)
168 {
169 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
170
171 if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
172 (Interface->SubClass == AUDIO_CSCP_AudioStreamingSubclass) &&
173 (Interface->Protocol == AUDIO_CSCP_StreamingProtocol))
174 {
175 return DESCRIPTOR_SEARCH_Found;
176 }
177 }
178
179 return DESCRIPTOR_SEARCH_NotFound;
180 }
181
182 static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor)
183 {
184 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
185
186 if (Header->Type == DTYPE_Endpoint)
187 {
188 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
189
190 if ((Endpoint->Attributes & EP_TYPE_MASK) == EP_TYPE_ISOCHRONOUS)
191 return DESCRIPTOR_SEARCH_Found;
192 }
193 else if (Header->Type == DTYPE_Interface)
194 {
195 return DESCRIPTOR_SEARCH_Fail;
196 }
197
198 return DESCRIPTOR_SEARCH_NotFound;
199 }
200
201 uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
202 const bool EnableStreaming)
203 {
204 if (!(AudioInterfaceInfo->State.IsActive))
205 return HOST_SENDCONTROL_DeviceDisconnected;
206
207 return USB_Host_SetInterfaceAltSetting(AudioInterfaceInfo->State.StreamingInterfaceNumber,
208 EnableStreaming ? AudioInterfaceInfo->State.EnabledStreamingAltIndex : 0);
209 }
210
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,
216 void* const Data)
217 {
218 if (!(AudioInterfaceInfo->State.IsActive))
219 return HOST_SENDCONTROL_DeviceDisconnected;
220
221 uint8_t RequestType;
222 uint8_t EndpointAddress;
223
224 if (EndpointProperty & 0x80)
225 RequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT);
226 else
227 RequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT);
228
229 Pipe_SelectPipe(DataPipeIndex);
230 EndpointAddress = Pipe_GetBoundEndpointAddress();
231
232 USB_ControlRequest = (USB_Request_Header_t)
233 {
234 .bmRequestType = RequestType,
235 .bRequest = EndpointProperty,
236 .wValue = ((uint16_t)EndpointControl << 8),
237 .wIndex = EndpointAddress,
238 .wLength = DataLength,
239 };
240
241 Pipe_SelectPipe(PIPE_CONTROLPIPE);
242
243 return USB_Host_SendControlRequest(Data);
244 }
245
246 #endif
247