3      Copyright (C) Dean Camera, 2012. 
   5   dean [at] fourwalledcubicle [dot] com 
  10   Copyright 2012  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
);