A library to send and receive MIDI messages over USB using the default USB-MIDI drivers on Win/Mac

Dependents:   USBMIDI_HelloWorld USBMIDI_DrumExample USBMIDI_MonoSynth MIDI_Interface_ver_1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbdevice.c Source File

usbdevice.c

00001 /* @license The MIT License
00002  * Copyright (c) 2011 mux, simon
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *  
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *  
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022 
00023 #include "usbcore.h"
00024 #include "mbed.h"
00025 
00026 #define STANDARD_DEVICE_REQUEST     (0x00)
00027 #define STANDARD_INTERFACE_REQUEST  (0x01)
00028 #define STANDARD_ENDPOINT_REQUEST   (0x02)
00029 #define CLASS_DEVICE_REQUEST        (0x20)
00030 #define CLASS_INTERFACE_REQUEST     (0x21)
00031 #define CLASS_ENDPOINT_REQUEST      (0x22)
00032 #define VENDOR_DEVICE_REQUEST       (0x40)
00033 #define VENDOR_INTERFACE_REQUEST    (0x41)
00034 #define VENDOR_ENDPOINT_REQUEST     (0x42)
00035 #define GET_STATUS                  (0x00)
00036 #define CLEAR_FEATURE               (0x01)
00037 #define SET_FEATURE                 (0x03)
00038 #define SET_ADDRESS                 (0x05)
00039 #define GET_DESCRIPTOR              (0x06)
00040 #define SET_DESCRIPTOR              (0x07)
00041 #define GET_CONFIGURATION           (0x08)
00042 #define SET_CONFIGURATION           (0x09)
00043 #define DEVICE_DESCRIPTOR           (0x01)
00044 #define CONFIG_DESCRIPTOR           (0x02)
00045 #define STRING_DESCRIPTOR           (0x03)
00046 #define INTERFACE_DESCRIPTOR        (0x04)
00047 #define ENDPOINT_DESCRIPTOR         (0x05)
00048 #define QUALIFIER_DESCRIPTOR        (0x06)
00049 #define unpack(x) (x & 0xFF),((x >> 8) & 0xFF)
00050 
00051 // setup packet
00052 struct {
00053     uint8_t   bmRequestType;
00054     uint8_t   bRequest;
00055     uint16_t  wValue;
00056     uint16_t  wIndex;
00057     uint16_t  wLength;
00058 } __attribute__((packed)) setup = {0};
00059 
00060 // data packet
00061 struct { 
00062     uint8_t *data;
00063     uint8_t size;
00064     uint8_t sent;
00065 } transfer = {0};
00066 
00067 uint8_t device_descriptor[] = {
00068     0x12,                       // Descriptor size in bytes (12h)                  
00069     DEVICE_DESCRIPTOR,          // The constant DEVICE (01h)                       
00070     unpack(0x0200),             // US2B specification release number (BCD)         
00071     0x00,                       // Class code                                      
00072     0x00,                       // Subclass code                                   
00073     0x00,                       // Protocol Code                                   
00074     MAX_EP0_PSIZE,              // Maximum packet size for endpoint zero           
00075     unpack(0x0763),             // Vendor ID                                       
00076     unpack(0x0198),             // Product ID                                      
00077     unpack(0x0001),             // Device release number (BCD)                     
00078     0x00,                       // Index of string descriptor for the manufacturer 
00079     0x00,                       // Index of string descriptor for the product      
00080     0x00,                       // Index of string descriptor for the serial number
00081     0x01,                       // Number of possible configurations               
00082 };
00083 
00084 uint8_t config_descriptor[]={
00085     0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50, // configuration descriptor
00086     // The Audio Interface Collection
00087     0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, // Standard AC Interface Descriptor
00088     0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, // Class-specific AC Interface Descriptor
00089     0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, // MIDIStreaming Interface Descriptors
00090     0x07, 0x24, 0x01, 0x00, 0x01, 0x41, 0x00,             // Class-Specific MS Interface Header Descriptor
00091 
00092     // MIDI IN JACKS
00093     0x06, 0x24, 0x02, 0x01, 0x01, 0x00,
00094     0x06, 0x24, 0x02, 0x02, 0x02, 0x00,
00095 
00096     // MIDI OUT JACKS
00097     0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00,
00098     0x09, 0x24, 0x03, 0x02, 0x06, 0x01, 0x01, 0x01, 0x00,
00099 
00100     // OUT endpoint descriptor
00101     0x09, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
00102     0x05, 0x25, 0x01, 0x01, 0x01,
00103 
00104     // IN endpoint descriptor
00105     0x09, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
00106     0x05, 0x25, 0x01, 0x01, 0x03,
00107 };
00108 
00109 void ep0_in();
00110 
00111 void data_in_stage(uint8_t *desc, uint8_t length) {
00112     transfer.sent = 0;
00113     transfer.data = desc;
00114     transfer.size = length;
00115     ep0_in();
00116 }
00117 
00118 void status_in_stage() {
00119     ep_write(EP1, 0, 0); // ZLEP for status stage
00120 }
00121 
00122 void ep0_setup() {
00123     ep_read(EP0,(uint8_t*) &setup);
00124 
00125     switch (setup.bmRequestType & 0x7f) { // mask direction
00126         case STANDARD_DEVICE_REQUEST:
00127             switch (setup.bRequest) {
00128                 case GET_DESCRIPTOR:
00129                     switch ((setup.wValue>>8)) {
00130                         case DEVICE_DESCRIPTOR:     // device descriptor request
00131                         case QUALIFIER_DESCRIPTOR:  // device qualifier descriptor
00132                             data_in_stage(device_descriptor, sizeof(device_descriptor));
00133                             break;
00134                         case CONFIG_DESCRIPTOR:     // configuration descriptor
00135                             data_in_stage(config_descriptor, setup.wLength);
00136                             break;
00137                         case STRING_DESCRIPTOR:
00138                             break;
00139                         default:
00140                             break;
00141                     }
00142                     break;
00143                 case SET_ADDRESS:
00144                     usb_set_address((uint8_t) (setup.wValue & 0xFF));
00145                     status_in_stage();
00146                     break;
00147                 case SET_CONFIGURATION:
00148                     if (!setup.wValue) {
00149                         break;
00150                     }
00151                     ep_realize(EP4, MAX_EPn_PSIZE);
00152                     ep_realize(EP5, MAX_EPn_PSIZE);
00153                     status_in_stage();
00154                     usb_configure(1);
00155                     break;
00156                 default:
00157                     break;
00158             }
00159             break;
00160         default:
00161             break;
00162     }
00163 }
00164 
00165 void ep0_in() {
00166     if ((setup.bmRequestType & 0x80) && transfer.size) { // device to host
00167         if (transfer.size > MAX_EP0_PSIZE) {
00168             transfer.sent = MAX_EP0_PSIZE;
00169         } else {
00170             transfer.sent = transfer.size;
00171         }
00172         ep_write(EP1, transfer.data, transfer.sent);
00173         transfer.data += transfer.sent;
00174         transfer.size -= transfer.sent;
00175     }
00176 }
00177 
00178 void ep0_out() {
00179     uint8_t buf[64];
00180     ep_read(EP0, buf);
00181 }