diff options
Diffstat (limited to 'lib/lufa/LUFA/Drivers/USB/Class/Host/AudioClassHost.c')
| -rw-r--r-- | lib/lufa/LUFA/Drivers/USB/Class/Host/AudioClassHost.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/lib/lufa/LUFA/Drivers/USB/Class/Host/AudioClassHost.c b/lib/lufa/LUFA/Drivers/USB/Class/Host/AudioClassHost.c new file mode 100644 index 000000000..9f1a6dc2c --- /dev/null +++ b/lib/lufa/LUFA/Drivers/USB/Class/Host/AudioClassHost.c | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* | ||
| 2 | LUFA Library | ||
| 3 | Copyright (C) Dean Camera, 2017. | ||
| 4 | |||
| 5 | dean [at] fourwalledcubicle [dot] com | ||
| 6 | www.lufa-lib.org | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | Copyright 2017 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 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 | ||
| 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.DataINPipe.Address && !(DataINEndpoint)) || | ||
| 55 | (AudioInterfaceInfo->Config.DataOUTPipe.Address && !(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 | AudioInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize); | ||
| 97 | AudioInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress; | ||
| 98 | AudioInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_ISOCHRONOUS; | ||
| 99 | AudioInterfaceInfo->Config.DataINPipe.Banks = 2; | ||
| 100 | |||
| 101 | AudioInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); | ||
| 102 | AudioInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress; | ||
| 103 | AudioInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_ISOCHRONOUS; | ||
| 104 | AudioInterfaceInfo->Config.DataOUTPipe.Banks = 2; | ||
| 105 | |||
| 106 | if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataINPipe, 1))) | ||
| 107 | return AUDIO_ENUMERROR_PipeConfigurationFailed; | ||
| 108 | |||
| 109 | if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataOUTPipe, 1))) | ||
| 110 | return AUDIO_ENUMERROR_PipeConfigurationFailed; | ||
| 111 | |||
| 112 | AudioInterfaceInfo->State.ControlInterfaceNumber = AudioControlInterface->InterfaceNumber; | ||
| 113 | AudioInterfaceInfo->State.StreamingInterfaceNumber = AudioStreamingInterface->InterfaceNumber; | ||
| 114 | AudioInterfaceInfo->State.EnabledStreamingAltIndex = AudioStreamingInterface->AlternateSetting; | ||
| 115 | AudioInterfaceInfo->State.IsActive = true; | ||
| 116 | |||
| 117 | return AUDIO_ENUMERROR_NoError; | ||
| 118 | } | ||
| 119 | |||
| 120 | static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor) | ||
| 121 | { | ||
| 122 | USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); | ||
| 123 | |||
| 124 | if (Header->Type == DTYPE_Interface) | ||
| 125 | { | ||
| 126 | USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t); | ||
| 127 | |||
| 128 | if ((Interface->Class == AUDIO_CSCP_AudioClass) && | ||
| 129 | (Interface->SubClass == AUDIO_CSCP_ControlSubclass) && | ||
| 130 | (Interface->Protocol == AUDIO_CSCP_ControlProtocol)) | ||
| 131 | { | ||
| 132 | return DESCRIPTOR_SEARCH_Found; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | return DESCRIPTOR_SEARCH_NotFound; | ||
| 137 | } | ||
| 138 | |||
| 139 | static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor) | ||
| 140 | { | ||
| 141 | USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); | ||
| 142 | |||
| 143 | if (Header->Type == DTYPE_Interface) | ||
| 144 | { | ||
| 145 | USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t); | ||
| 146 | |||
| 147 | if ((Interface->Class == AUDIO_CSCP_AudioClass) && | ||
| 148 | (Interface->SubClass == AUDIO_CSCP_AudioStreamingSubclass) && | ||
| 149 | (Interface->Protocol == AUDIO_CSCP_StreamingProtocol)) | ||
| 150 | { | ||
| 151 | return DESCRIPTOR_SEARCH_Found; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | return DESCRIPTOR_SEARCH_NotFound; | ||
| 156 | } | ||
| 157 | |||
| 158 | static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor) | ||
| 159 | { | ||
| 160 | USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); | ||
| 161 | |||
| 162 | if (Header->Type == DTYPE_Endpoint) | ||
| 163 | { | ||
| 164 | USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t); | ||
| 165 | |||
| 166 | if ((Endpoint->Attributes & EP_TYPE_MASK) == EP_TYPE_ISOCHRONOUS) | ||
| 167 | return DESCRIPTOR_SEARCH_Found; | ||
| 168 | } | ||
| 169 | else if (Header->Type == DTYPE_Interface) | ||
| 170 | { | ||
| 171 | return DESCRIPTOR_SEARCH_Fail; | ||
| 172 | } | ||
| 173 | |||
| 174 | return DESCRIPTOR_SEARCH_NotFound; | ||
| 175 | } | ||
| 176 | |||
| 177 | uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo, | ||
| 178 | const bool EnableStreaming) | ||
| 179 | { | ||
| 180 | if (!(AudioInterfaceInfo->State.IsActive)) | ||
| 181 | return HOST_SENDCONTROL_DeviceDisconnected; | ||
| 182 | |||
| 183 | return USB_Host_SetInterfaceAltSetting(AudioInterfaceInfo->State.StreamingInterfaceNumber, | ||
| 184 | EnableStreaming ? AudioInterfaceInfo->State.EnabledStreamingAltIndex : 0); | ||
| 185 | } | ||
| 186 | |||
| 187 | uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo, | ||
| 188 | const uint8_t DataPipeIndex, | ||
| 189 | const uint8_t EndpointProperty, | ||
| 190 | const uint8_t EndpointControl, | ||
| 191 | const uint16_t DataLength, | ||
| 192 | void* const Data) | ||
| 193 | { | ||
| 194 | if (!(AudioInterfaceInfo->State.IsActive)) | ||
| 195 | return HOST_SENDCONTROL_DeviceDisconnected; | ||
| 196 | |||
| 197 | uint8_t RequestType; | ||
| 198 | uint8_t EndpointAddress; | ||
| 199 | |||
| 200 | if (EndpointProperty & 0x80) | ||
| 201 | RequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT); | ||
| 202 | else | ||
| 203 | RequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT); | ||
| 204 | |||
| 205 | Pipe_SelectPipe(DataPipeIndex); | ||
| 206 | EndpointAddress = Pipe_GetBoundEndpointAddress(); | ||
| 207 | |||
| 208 | USB_ControlRequest = (USB_Request_Header_t) | ||
| 209 | { | ||
| 210 | .bmRequestType = RequestType, | ||
| 211 | .bRequest = EndpointProperty, | ||
| 212 | .wValue = ((uint16_t)EndpointControl << 8), | ||
| 213 | .wIndex = EndpointAddress, | ||
| 214 | .wLength = DataLength, | ||
| 215 | }; | ||
| 216 | |||
| 217 | Pipe_SelectPipe(PIPE_CONTROLPIPE); | ||
| 218 | |||
| 219 | return USB_Host_SendControlRequest(Data); | ||
| 220 | } | ||
| 221 | |||
| 222 | #endif | ||
| 223 | |||
