3      Copyright (C) Dean Camera, 2009. 
   5   dean [at] fourwalledcubicle [dot] com 
   6       www.fourwalledcubicle.com 
  10   Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com) 
  12   Permission to use, copy, modify, and distribute this software 
  13   and its documentation for any purpose and without fee is hereby 
  14   granted, provided that the above copyright notice appear in all 
  15   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 #include "../../HighLevel/USBMode.h" 
  32 #if defined(USB_CAN_BE_HOST) 
  34 #define  INCLUDE_FROM_MIDI_CLASS_HOST_C 
  37 uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, uint16_t ConfigDescriptorSize
, 
  38                                  void* ConfigDescriptorData
) 
  40         uint8_t FoundEndpoints 
= 0; 
  42         memset(&MIDIInterfaceInfo
->State
, 0x00, sizeof(MIDIInterfaceInfo
->State
)); 
  44         if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
) 
  45           return MIDI_ENUMERROR_InvalidConfigDescriptor
; 
  47         if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  48                                       DComp_MIDI_Host_NextMIDIStreamingInterface
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  50                 return MIDI_ENUMERROR_NoStreamingInterfaceFound
; 
  53         while (FoundEndpoints 
!= (MIDI_FOUND_DATAPIPE_IN 
| MIDI_FOUND_DATAPIPE_OUT
)) 
  55                 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
, 
  56                                               DComp_MIDI_Host_NextMIDIStreamingDataEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
) 
  58                         return MIDI_ENUMERROR_EndpointsNotFound
; 
  61                 USB_Descriptor_Endpoint_t
* EndpointData 
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
); 
  63                 if (EndpointData
->EndpointAddress 
& ENDPOINT_DESCRIPTOR_DIR_IN
) 
  65                         Pipe_ConfigurePipe(MIDIInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
, 
  66                                                            EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, 
  67                                                            MIDIInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
  68                         MIDIInterfaceInfo
->State
.DataINPipeSize 
= EndpointData
->EndpointSize
; 
  70                         FoundEndpoints 
|= MIDI_FOUND_DATAPIPE_IN
; 
  74                         Pipe_ConfigurePipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
, 
  75                                                            EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
, 
  76                                                            MIDIInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE 
: PIPE_BANK_SINGLE
); 
  77                         MIDIInterfaceInfo
->State
.DataOUTPipeSize 
= EndpointData
->EndpointSize
; 
  79                         FoundEndpoints 
|= MIDI_FOUND_DATAPIPE_OUT
; 
  83         MIDIInterfaceInfo
->State
.IsActive 
= true; 
  84         return MIDI_ENUMERROR_NoError
; 
  87 static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor
) 
  89         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
  91                 USB_Descriptor_Interface_t
* CurrentInterface 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
  92                                                                                 USB_Descriptor_Interface_t
); 
  94                 if ((CurrentInterface
->Class    
== MIDI_STREAMING_CLASS
)    && 
  95                     (CurrentInterface
->SubClass 
== MIDI_STREAMING_SUBCLASS
) && 
  96                     (CurrentInterface
->Protocol 
== MIDI_STREAMING_PROTOCOL
)) 
  98                         return DESCRIPTOR_SEARCH_Found
; 
 102         return DESCRIPTOR_SEARCH_NotFound
; 
 105 static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor
) 
 107         if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
) 
 109                 USB_Descriptor_Endpoint_t
* CurrentEndpoint 
= DESCRIPTOR_PCAST(CurrentDescriptor
, 
 110                                                                               USB_Descriptor_Endpoint_t
); 
 112                 uint8_t EndpointType 
= (CurrentEndpoint
->Attributes 
& EP_TYPE_MASK
); 
 114                 if ((EndpointType 
== EP_TYPE_BULK
) && !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
))) 
 115                   return DESCRIPTOR_SEARCH_Found
; 
 117         else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
) 
 119                 return DESCRIPTOR_SEARCH_Fail
; 
 122         return DESCRIPTOR_SEARCH_NotFound
; 
 125 void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
) 
 130 uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, MIDI_EventPacket_t
* const Event
) 
 132         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 133           return HOST_SENDCONTROL_DeviceDisconnect
; 
 135         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataOUTPipeNumber
); 
 137         if (Pipe_IsReadWriteAllowed()); 
 141                 if ((ErrorCode 
= Pipe_Write_Stream_LE(Event
, sizeof(MIDI_EventPacket_t
), NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
) 
 147         return PIPE_RWSTREAM_NoError
; 
 150 bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t
* const MIDIInterfaceInfo
, MIDI_EventPacket_t
* const Event
) 
 152         if ((USB_HostState 
!= HOST_STATE_Configured
) || !(MIDIInterfaceInfo
->State
.IsActive
)) 
 153           return HOST_SENDCONTROL_DeviceDisconnect
; 
 155         Pipe_SelectPipe(MIDIInterfaceInfo
->Config
.DataINPipeNumber
); 
 157         if (!(Pipe_IsReadWriteAllowed())) 
 160         Pipe_Read_Stream_LE(Event
, sizeof(MIDI_EventPacket_t
), NO_STREAM_CALLBACK
);