3      Copyright (C) Dean Camera, 2010. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2010  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_CLASS_HOST_C 
  36 #define  __INCLUDE_FROM_MIDI_DRIVER 
  39 uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, uint16_t ConfigDescriptorSize
, 
  40                                  void* ConfigDescriptorData
) 
  42         uint8_t FoundEndpoints 
= 0; 
  44         memset(&MIDIInterfaceInfo
->State
, 0x00, sizeof(MIDIInterfaceInfo
->State
)); 
  46         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  47           return MIDI_ENUMERROR_InvalidConfigDescriptor
; 
  49         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  50                                       DComp_MIDI_Host_NextMIDIStreamingInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  52                 return MIDI_ENUMERROR_NoStreamingInterfaceFound
; 
  55         while (FoundEndpoints 
!= (MIDI_FOUND_DATAPIPE_IN 
| MIDI_FOUND_DATAPIPE_OUT
)) 
  57                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  58                                               DComp_MIDI_Host_NextMIDIStreamingDataEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  60                         return MIDI_ENUMERROR_EndpointsNotFound
; 
  63                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  65                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  67                         Pipe_ConfigurePipe(MIDIInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
, 
  68                                                            EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, 
  69                                                            MIDIInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
  70                         MIDIInterfaceInfo
->State
.DataINPipeSize 
= EndpointData
->EndpointSize
; 
  72                         FoundEndpoints 
|= MIDI_FOUND_DATAPIPE_IN
; 
  76                         Pipe_ConfigurePipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
, 
  77                                                            EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, 
  78                                                            MIDIInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
  79                         MIDIInterfaceInfo
->State
.DataOUTPipeSize 
= EndpointData
->EndpointSize
; 
  81                         FoundEndpoints 
|= MIDI_FOUND_DATAPIPE_OUT
; 
  85         MIDIInterfaceInfo
->State
.IsActive 
= true; 
  86         return MIDI_ENUMERROR_NoError
; 
  89 static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor
) 
  91         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
  93                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
  94                                                                                 USB_Descriptor_Interface_t
); 
  96                 if ((CurrentInterface
->Class    
== MIDI_STREAMING_CLASS
)    && 
  97                     (CurrentInterface
->SubClass 
== MIDI_STREAMING_SUBCLASS
) && 
  98                     (CurrentInterface
->Protocol 
== MIDI_STREAMING_PROTOCOL
)) 
 100                         return DESCRIPTOR_SEARCH_Found
; 
 104         return DESCRIPTOR_SEARCH_NotFound
; 
 107 static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor
) 
 109         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
) 
 111                 USB_Descriptor_Endpoint_t
* CurrentEndpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 112                                                                               USB_Descriptor_Endpoint_t
); 
 114                 uint8_t EndpointType 
= (CurrentEndpoint
->Attributes 
& EP_TYPE_MASK
); 
 116                 if ((EndpointType 
== EP_TYPE_BULK
) && !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))) 
 117                   return DESCRIPTOR_SEARCH_Found
; 
 119         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 121                 return DESCRIPTOR_SEARCH_Fail
; 
 124         return DESCRIPTOR_SEARCH_NotFound
; 
 127 uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
) 
 129         if (USB_HostState 
!= HOST_STATE_Configured
) 
 130           return PIPE_RWSTREAM_DeviceDisconnected
; 
 134         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 136         if (Pipe_BytesInPipe()) 
 140                 if ((ErrorCode 
= Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError
) 
 144         return PIPE_READYWAIT_NoError
; 
 147 uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, MIDI_EventPacket_t
* const Event
) 
 149         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 150           return HOST_SENDCONTROL_DeviceDisconnected
; 
 152         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 154         if (Pipe_IsReadWriteAllowed()) 
 158                 if ((ErrorCode 
= Pipe_Write_Stream_LE(Event
, sizeof(MIDI_EventPacket_t
), NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 161                 if (!(Pipe_IsReadWriteAllowed())) 
 165         return PIPE_RWSTREAM_NoError
; 
 168 bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, MIDI_EventPacket_t
* const Event
) 
 170         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 171           return HOST_SENDCONTROL_DeviceDisconnected
; 
 173         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataINPipeNumber
); 
 175         if (!(Pipe_IsReadWriteAllowed())) 
 178         Pipe_Read_Stream_LE(Event
, sizeof(MIDI_EventPacket_t
), NO_STREAM_CALLBACK
); 
 180         if (!(Pipe_IsReadWriteAllowed()))