Statistics
| Branch: | Tag: | Revision:

root / LUFA / Drivers / USB / Class / Host / MIDI.c @ 978b99e5

History | View | Annotate | Download (7.5 KB)

1
/*
2
             LUFA Library
3
     Copyright (C) Dean Camera, 2011.
4

5
  dean [at] fourwalledcubicle [dot] com
6
           www.lufa-lib.org
7
*/
8

    
9
/*
10
  Copyright 2011  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 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
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_MIDI_DRIVER
37
#define  __INCLUDE_FROM_MIDI_HOST_C
38
#include "MIDI.h"
39

    
40
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
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* MIDIInterface   = NULL;
47

    
48
        memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
49

    
50
        if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
51
          return MIDI_ENUMERROR_InvalidConfigDescriptor;
52

    
53
        while (!(DataINEndpoint) || !(DataOUTEndpoint))
54
        {
55
                if (!(MIDIInterface) ||
56
                    USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
57
                                              DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
58
                {
59
                        if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
60
                                                      DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
61
                        {
62
                                return MIDI_ENUMERROR_NoCompatibleInterfaceFound;
63
                        }
64

    
65
                        MIDIInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
66

    
67
                        DataINEndpoint  = NULL;
68
                        DataOUTEndpoint = NULL;
69

    
70
                        continue;
71
                }
72

    
73
                USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
74

    
75
                if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
76
                  DataINEndpoint  = EndpointData;
77
                else
78
                  DataOUTEndpoint = EndpointData;
79
        }
80

    
81
        for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
82
        {
83
                uint16_t Size;
84
                uint8_t  Type;
85
                uint8_t  Token;
86
                uint8_t  EndpointAddress;
87
                bool     DoubleBanked;
88

    
89
                if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber)
90
                {
91
                        Size            = le16_to_cpu(DataINEndpoint->EndpointSize);
92
                        EndpointAddress = DataINEndpoint->EndpointAddress;
93
                        Token           = PIPE_TOKEN_IN;
94
                        Type            = EP_TYPE_BULK;
95
                        DoubleBanked    = MIDIInterfaceInfo->Config.DataINPipeDoubleBank;
96

    
97
                        MIDIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
98
                }
99
                else if (PipeNum == MIDIInterfaceInfo->Config.DataOUTPipeNumber)
100
                {
101
                        Size            = le16_to_cpu(DataOUTEndpoint->EndpointSize);
102
                        EndpointAddress = DataOUTEndpoint->EndpointAddress;
103
                        Token           = PIPE_TOKEN_OUT;
104
                        Type            = EP_TYPE_BULK;
105
                        DoubleBanked    = MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank;
106

    
107
                        MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
108
                }
109
                else
110
                {
111
                        continue;
112
                }
113

    
114
                if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
115
                                         DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
116
                {
117
                        return MIDI_ENUMERROR_PipeConfigurationFailed;
118
                }
119
        }
120

    
121
        MIDIInterfaceInfo->State.InterfaceNumber = MIDIInterface->InterfaceNumber;
122
        MIDIInterfaceInfo->State.IsActive = true;
123

    
124
        return MIDI_ENUMERROR_NoError;
125
}
126

    
127
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
128
{
129
        USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
130

    
131
        if (Header->Type == DTYPE_Interface)
132
        {
133
                USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
134

    
135
                if ((Interface->Class    == AUDIO_CSCP_AudioClass)            &&
136
                    (Interface->SubClass == AUDIO_CSCP_MIDIStreamingSubclass) &&
137
                    (Interface->Protocol == AUDIO_CSCP_StreamingProtocol))
138
                {
139
                        return DESCRIPTOR_SEARCH_Found;
140
                }
141
        }
142

    
143
        return DESCRIPTOR_SEARCH_NotFound;
144
}
145

    
146
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
147
{
148
        USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
149

    
150
        if (Header->Type == DTYPE_Endpoint)
151
        {
152
                USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
153

    
154
                uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
155

    
156
                if ((EndpointType == EP_TYPE_BULK) && !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
157
                  return DESCRIPTOR_SEARCH_Found;
158
        }
159
        else if (Header->Type == DTYPE_Interface)
160
        {
161
                return DESCRIPTOR_SEARCH_Fail;
162
        }
163

    
164
        return DESCRIPTOR_SEARCH_NotFound;
165
}
166

    
167
void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
168
{
169
        if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
170
          return;
171

    
172
        #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
173
        MIDI_Host_Flush(MIDIInterfaceInfo);
174
        #endif        
175
}
176

    
177
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
178
{
179
        if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
180
          return PIPE_RWSTREAM_DeviceDisconnected;
181

    
182
        uint8_t ErrorCode;
183

    
184
        Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
185

    
186
        if (Pipe_BytesInPipe())
187
        {
188
                Pipe_ClearOUT();
189

    
190
                if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
191
                  return ErrorCode;
192
        }
193

    
194
        return PIPE_READYWAIT_NoError;
195
}
196

    
197
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
198
                                  MIDI_EventPacket_t* const Event)
199
{
200
        if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
201
          return HOST_SENDCONTROL_DeviceDisconnected;
202

    
203
        uint8_t ErrorCode;
204

    
205
        Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
206

    
207
        if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != PIPE_RWSTREAM_NoError)
208
          return ErrorCode;
209

    
210
        if (!(Pipe_IsReadWriteAllowed()))
211
          Pipe_ClearOUT();
212

    
213
        return PIPE_RWSTREAM_NoError;
214
}
215

    
216
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
217
                                  MIDI_EventPacket_t* const Event)
218
{
219
        if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
220
          return HOST_SENDCONTROL_DeviceDisconnected;
221

    
222
        Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipeNumber);
223

    
224
        if (!(Pipe_IsReadWriteAllowed()))
225
          return false;
226

    
227
        Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL);
228

    
229
        if (!(Pipe_IsReadWriteAllowed()))
230
          Pipe_ClearIN();
231

    
232
        return true;
233
}
234

    
235
#endif
236