My Fork of F401RE-USBHost. Add USBHostMIDI functions (originaled by Kaoru Shoji http://mbed.org/users/kshoji/code/USBHostMIDI/)
Dependents: F401RE-USBHostMIDI_RecieveExample
Fork of F401RE-USBHost by
Diff: USBHostMIDI/USBHostMIDI.cpp
- Revision:
- 18:bac56d0365e1
- Child:
- 22:81d8c59d1070
diff -r 4a710e2ba162 -r bac56d0365e1 USBHostMIDI/USBHostMIDI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostMIDI/USBHostMIDI.cpp Wed Jun 25 20:48:01 2014 +0000 @@ -0,0 +1,258 @@ +/* USBHostMidi library + * Originaled by k.shoji + * porting by Takuya Urakawa + */ + +/* mbed USBHost Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "USBHostMIDI.h" + +#if USBHOST_MIDI + +#include "dbg.h" + +#define SET_LINE_CODING 0x20 + +USBHostMIDI::USBHostMIDI(): circ_buf() { + host = USBHost::getHostInst(); + size_bulk_in = 0; + size_bulk_out = 0; + init(); +} + +void USBHostMIDI::init() { + dev = NULL; + bulk_in = NULL; + bulk_out = NULL; + dev_connected = false; + midi_intf = -1; + midi_device_found = false; + circ_buf.flush(); +} + +bool USBHostMIDI::connected() +{ + return dev_connected; +} + +bool USBHostMIDI::connect() { + + if (dev_connected) { + return true; + } + for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { + if ((dev = host->getDevice(i)) != NULL) { + + USB_DBG("Trying to connect MIDI device\r\n"); + + if(host->enumerate(dev, this)) + break; + + if (midi_device_found) { + bulk_in = dev->getEndpoint(midi_intf, BULK_ENDPOINT, IN); + bulk_out = dev->getEndpoint(midi_intf, BULK_ENDPOINT, OUT); + + if (!bulk_in || !bulk_out) + break; + + USB_INFO("New MIDI device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, midi_intf); + dev->setName("MIDI", midi_intf); + host->registerDriver(dev, midi_intf, this, &USBHostMIDI::init); + + size_bulk_in = bulk_in->getSize(); + size_bulk_out = bulk_out->getSize(); + + bulk_in->attach(this, &USBHostMIDI::rxHandler); + + host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); + dev_connected = true; + return true; + } + } + } + init(); + return false; +} + +void USBHostMIDI::rxHandler() { + uint8_t pos = 0; + uint8_t midi[4]; + if (bulk_in) { + int len = bulk_in->getLengthTransferred(); + if (bulk_in->getState() == USB_TYPE_IDLE || bulk_in->getState() == USB_TYPE_FREE) { + for (int i = 0; i < len; i++) { + circ_buf.queue(buf[i]); + } + + // MIDI event handling + while (!circ_buf.isEmpty()) { + // read each four bytes + circ_buf.dequeue(&midi[pos++]); + if (pos == 4) { + pos = 0; + + // process MIDI message + // switch by code index number + switch (midi[0] & 0xf) { + case 8: + noteOff(midi[1] & 0xf, midi[2], midi[3]); + break; + case 9: + if (midi[3]) { + noteOn(midi[1] & 0xf, midi[2], midi[3]); + } else { + noteOff(midi[1] & 0xf, midi[2], midi[3]); + } + break; + case 11: + controlChange(midi[1] & 0xf, midi[2], midi[3]); + break; + case 12: + programChange(midi[1] & 0xf, midi[2]); + break; + case 14: + pitchBend(midi[1] & 0xf, midi[2] | (midi[3] << 7)); + break; + default: + break; + } + } + } + + host->bulkRead(dev, bulk_in, buf, size_bulk_in, false); + } + } +} + +int USBHostMIDI::sendNoteOn(unsigned char channel, unsigned char note, unsigned char velocity) { + uint8_t midi[4]; + + if (bulk_out) { + midi[0] = 9; + midi[1] = channel & 0xf; + midi[2] = note & 0x7f; + midi[3] = velocity & 0x7f; + if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { + return 1; + } + } + return -1; +} + +int USBHostMIDI::sendNoteOff(unsigned char channel, unsigned char note, unsigned char velocity) { + uint8_t midi[4]; + + if (bulk_out) { + midi[0] = 8; + midi[1] = channel & 0xf; + midi[2] = note & 0x7f; + midi[3] = velocity & 0x7f; + if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { + return 1; + } + } + return -1; +} + +int USBHostMIDI::sendControlChange(unsigned char channel, unsigned char key, unsigned char value) { + uint8_t midi[4]; + + if (bulk_out) { + midi[0] = 11; + midi[1] = channel & 0xf; + midi[2] = key & 0x7f; + midi[3] = value & 0x7f; + if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { + return 1; + } + } + return -1; +} + +int USBHostMIDI::sendProgramChange(unsigned char channel, unsigned char program) { + uint8_t midi[4]; + + if (bulk_out) { + midi[0] = 12; + midi[1] = channel & 0xf; + midi[2] = program & 0x7f; + midi[3] = 0; + if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { + return 1; + } + } + return -1; +} + +int USBHostMIDI::sendPitchBend(unsigned char channel, unsigned int value) { + uint8_t midi[4]; + + if (bulk_out) { + midi[0] = 14; + midi[1] = channel & 0xf; + midi[2] = value & 0x7f; + midi[3] = (value >> 7) & 0x7f; + if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) { + return 1; + } + } + return -1; +} + +void USBHostMIDI::poll() +{ + host->poll(); +} + +/*virtual*/ void USBHostMIDI::setVidPid(uint16_t vid, uint16_t pid) +{ + // we don't check VID/PID for this driver +} + +/*virtual*/ bool USBHostMIDI::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + // USB MIDI class/subclass + if ((midi_intf == -1) && + (intf_class == AUDIO_CLASS) && + (intf_subclass == 0x03)) { + midi_intf = intf_nb; + return true; + } + + // vendor specific device + if ((midi_intf == -1) && + (intf_class == 0xff) && + (intf_subclass == 0x03)) { + midi_intf = intf_nb; + return true; + } + + return false; +} + +/*virtual*/ bool USBHostMIDI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if (intf_nb == midi_intf) { + if (type == BULK_ENDPOINT) { + midi_device_found = true; + return true; + } + } + return false; +} + +#endif