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 "../../HighLevel/USBMode.h" 
  33 #if defined(USB_CAN_BE_HOST) 
  35 #define  __INCLUDE_FROM_MIDI_DRIVER 
  36 #define  __INCLUDE_FROM_MIDI_HOST_C 
  39 uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, 
  40                                  uint16_t ConfigDescriptorSize
, 
  41                                  void* ConfigDescriptorData
) 
  43         USB_Descriptor_Endpoint_t
*  DataINEndpoint  
= NULL
; 
  44         USB_Descriptor_Endpoint_t
*  DataOUTEndpoint 
= NULL
; 
  45         USB_Descriptor_Interface_t
* MIDIInterface   
= NULL
; 
  47         memset(&MIDIInterfaceInfo
->State
, 0x00, sizeof(MIDIInterfaceInfo
->State
)); 
  49         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  50           return MIDI_ENUMERROR_InvalidConfigDescriptor
; 
  52         while (!(DataINEndpoint
) || !(DataOUTEndpoint
)) 
  54                 if (!(MIDIInterface
) || 
  55                     USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  56                                               DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  58                         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  59                                                       DCOMP_MIDI_Host_NextMIDIStreamingInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  61                                 return MIDI_ENUMERROR_NoCompatibleInterfaceFound
; 
  64                         MIDIInterface 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
); 
  66                         DataINEndpoint  
= NULL
; 
  67                         DataOUTEndpoint 
= NULL
; 
  72                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  74                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  75                   DataINEndpoint  
= EndpointData
; 
  77                   DataOUTEndpoint 
= EndpointData
; 
  80         for (uint8_t PipeNum 
= 1; PipeNum 
< PIPE_TOTAL_PIPES
; PipeNum
++) 
  85                 uint8_t  EndpointAddress
; 
  88                 if (PipeNum 
== MIDIInterfaceInfo
->Config
.DataINPipeNumber
) 
  90                         Size            
= DataINEndpoint
->EndpointSize
; 
  91                         EndpointAddress 
= DataINEndpoint
->EndpointAddress
; 
  92                         Token           
= PIPE_TOKEN_IN
; 
  94                         DoubleBanked    
= MIDIInterfaceInfo
->Config
.DataINPipeDoubleBank
; 
  96                         MIDIInterfaceInfo
->State
.DataINPipeSize 
= DataINEndpoint
->EndpointSize
; 
  98                 else if (PipeNum 
== MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
) 
 100                         Size            
= DataOUTEndpoint
->EndpointSize
; 
 101                         EndpointAddress 
= DataOUTEndpoint
->EndpointAddress
; 
 102                         Token           
= PIPE_TOKEN_OUT
; 
 104                         DoubleBanked    
= MIDIInterfaceInfo
->Config
.DataOUTPipeDoubleBank
; 
 106                         MIDIInterfaceInfo
->State
.DataOUTPipeSize 
= DataOUTEndpoint
->EndpointSize
; 
 113                 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
, 
 114                                          DoubleBanked ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
))) 
 116                         return MIDI_ENUMERROR_PipeConfigurationFailed
; 
 120         MIDIInterfaceInfo
->State
.InterfaceNumber 
= MIDIInterface
->InterfaceNumber
; 
 121         MIDIInterfaceInfo
->State
.IsActive 
= true; 
 123         return MIDI_ENUMERROR_NoError
; 
 126 static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor
) 
 128         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 130         if (Header
->Type 
== DTYPE_Interface
) 
 132                 USB_Descriptor_Interface_t
* Interface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
); 
 134                 if ((Interface
->Class    
== AUDIO_CSCP_AudioClass
)            && 
 135                     (Interface
->SubClass 
== AUDIO_CSCP_MIDIStreamingSubclass
) && 
 136                     (Interface
->Protocol 
== AUDIO_CSCP_StreamingProtocol
)) 
 138                         return DESCRIPTOR_SEARCH_Found
; 
 142         return DESCRIPTOR_SEARCH_NotFound
; 
 145 static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor
) 
 147         USB_Descriptor_Header_t
* Header 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
); 
 149         if (Header
->Type 
== DTYPE_Endpoint
) 
 151                 USB_Descriptor_Endpoint_t
* Endpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
); 
 153                 uint8_t EndpointType 
= (Endpoint
->Attributes 
& EP_TYPE_MASK
); 
 155                 if ((EndpointType 
== EP_TYPE_BULK
) && !(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))) 
 156                   return DESCRIPTOR_SEARCH_Found
; 
 158         else if (Header
->Type 
== DTYPE_Interface
) 
 160                 return DESCRIPTOR_SEARCH_Fail
; 
 163         return DESCRIPTOR_SEARCH_NotFound
; 
 166 void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
) 
 168         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 171         #if !defined(NO_CLASS_DRIVER_AUTOFLUSH) 
 172         MIDI_Host_Flush(MIDIInterfaceInfo
); 
 176 uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
) 
 178         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 179           return PIPE_RWSTREAM_DeviceDisconnected
; 
 183         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 185         if (Pipe_BytesInPipe()) 
 189                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 193         return PIPE_READYWAIT_NoError
; 
 196 uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, 
 197                                   MIDI_EventPacket_t
* const Event
) 
 199         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 200           return HOST_SENDCONTROL_DeviceDisconnected
; 
 204         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 206         if ((ErrorCode 
= Pipe_Write_Stream_LE(Event
, sizeof(MIDI_EventPacket_t
), NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 209         if (!(Pipe_IsReadWriteAllowed())) 
 212         return PIPE_RWSTREAM_NoError
; 
 215 bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, 
 216                                   MIDI_EventPacket_t
* const Event
) 
 218         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 219           return HOST_SENDCONTROL_DeviceDisconnected
; 
 221         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataINPipeNumber
); 
 223         if (!(Pipe_IsReadWriteAllowed())) 
 226         Pipe_Read_Stream_LE(Event
, sizeof(MIDI_EventPacket_t
), NO_STREAM_CALLBACK
); 
 228         if (!(Pipe_IsReadWriteAllowed()))