Browse Source

Merge branch 'master' into WIP2-Bluetooth

main
Paul Stoffregen 5 years ago
parent
commit
4bcb12fa60
No account linked to committer's email address
4 changed files with 106 additions and 47 deletions
  1. +48
    -10
      USBHost_t36.h
  2. +14
    -16
      ehci.cpp
  3. +1
    -0
      keywords.txt
  4. +43
    -21
      midi.cpp

+ 48
- 10
USBHost_t36.h View File

@@ -1012,7 +1012,7 @@ private:

//--------------------------------------------------------------------------

class MIDIDevice : public USBDriver {
class MIDIDeviceBase : public USBDriver {
public:
enum { SYSEX_MAX_LEN = 290 };

@@ -1038,9 +1038,12 @@ public:
ActiveSensing = 0xFE, // System Real Time - Active Sensing
SystemReset = 0xFF, // System Real Time - System Reset
};
MIDIDevice(USBHost &host) { init(); }
MIDIDevice(USBHost *host) { init(); }

MIDIDeviceBase(USBHost &host, uint32_t *rx, uint32_t *tx1, uint32_t *tx2,
uint16_t bufsize, uint32_t *rqueue, uint16_t qsize) :
rx_buffer(rx), tx_buffer1(tx1), tx_buffer2(tx2),
rx_queue(rqueue), max_packet_size(bufsize), rx_queue_size(qsize) {
init();
}
void sendNoteOff(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) {
send(0x80, note, velocity, channel, cable);
}
@@ -1290,15 +1293,21 @@ protected:
private:
Pipe_t *rxpipe;
Pipe_t *txpipe;
enum { MAX_PACKET_SIZE = 64 };
enum { RX_QUEUE_SIZE = 80 }; // must be more than MAX_PACKET_SIZE/4
uint32_t rx_buffer[MAX_PACKET_SIZE/4];
uint32_t tx_buffer1[MAX_PACKET_SIZE/4];
uint32_t tx_buffer2[MAX_PACKET_SIZE/4];
//enum { MAX_PACKET_SIZE = 64 };
//enum { RX_QUEUE_SIZE = 80 }; // must be more than MAX_PACKET_SIZE/4
//uint32_t rx_buffer[MAX_PACKET_SIZE/4];
//uint32_t tx_buffer1[MAX_PACKET_SIZE/4];
//uint32_t tx_buffer2[MAX_PACKET_SIZE/4];
uint32_t * const rx_buffer;
uint32_t * const tx_buffer1;
uint32_t * const tx_buffer2;
uint16_t rx_size;
uint16_t tx_size;
uint32_t rx_queue[RX_QUEUE_SIZE];
//uint32_t rx_queue[RX_QUEUE_SIZE];
uint32_t * const rx_queue;
bool rx_packet_queued;
const uint16_t max_packet_size;
const uint16_t rx_queue_size;
uint16_t rx_head;
uint16_t rx_tail;
volatile uint8_t tx1_count;
@@ -1339,6 +1348,35 @@ private:
strbuf_t mystring_bufs[1];
};

class MIDIDevice : public MIDIDeviceBase {
public:
MIDIDevice(USBHost &host) :
MIDIDeviceBase(host, rx, tx1, tx2, MAX_PACKET_SIZE, queue, RX_QUEUE_SIZE) {};
// MIDIDevice(USBHost *host) : ....
private:
enum { MAX_PACKET_SIZE = 64 };
enum { RX_QUEUE_SIZE = 80 }; // must be more than MAX_PACKET_SIZE/4
uint32_t rx[MAX_PACKET_SIZE/4];
uint32_t tx1[MAX_PACKET_SIZE/4];
uint32_t tx2[MAX_PACKET_SIZE/4];
uint32_t queue[RX_QUEUE_SIZE];
};

class MIDIDevice_BigBuffer : public MIDIDeviceBase {
public:
MIDIDevice_BigBuffer(USBHost &host) :
MIDIDeviceBase(host, rx, tx1, tx2, MAX_PACKET_SIZE, queue, RX_QUEUE_SIZE) {};
// MIDIDevice(USBHost *host) : ....
private:
enum { MAX_PACKET_SIZE = 512 };
enum { RX_QUEUE_SIZE = 400 }; // must be more than MAX_PACKET_SIZE/4
uint32_t rx[MAX_PACKET_SIZE/4];
uint32_t tx1[MAX_PACKET_SIZE/4];
uint32_t tx2[MAX_PACKET_SIZE/4];
uint32_t queue[RX_QUEUE_SIZE];
};


//--------------------------------------------------------------------------

class USBSerial: public USBDriver, public Stream {

+ 14
- 16
ehci.cpp View File

@@ -745,23 +745,21 @@ bool USBHost::queue_Data_Transfer(Pipe_t *pipe, void *buffer, uint32_t len, USBD
transfer = allocate_Transfer();
if (!transfer) return false;
data = transfer;
if (len) {
for (count=((len-1) >> 14); count; count--) {
next = allocate_Transfer();
if (!next) {
// free already-allocated qTDs
while (1) {
next = (Transfer_t *)transfer->qtd.next;
free_Transfer(transfer);
if (transfer == data) break;
transfer = next;
}
return false;
for (count=((len-1) >> 14); count; count--) {
next = allocate_Transfer();
if (!next) {
// free already-allocated qTDs
while (1) {
next = (Transfer_t *)transfer->qtd.next;
free_Transfer(transfer);
if (transfer == data) break;
transfer = next;
}
data->qtd.next = (uint32_t)next;
data = next;
}
}
return false;
}
data->qtd.next = (uint32_t)next;
data = next;
}
// last qTD needs info for followup
data->qtd.next = 1;
data->pipe = pipe;

+ 1
- 0
keywords.txt View File

@@ -6,6 +6,7 @@ KeyboardController KEYWORD1
MouseController KEYWORD1
DigitizerController KEYWORD1
MIDIDevice KEYWORD1
MIDIDevice_BigBuffer KEYWORD1
USBSerial KEYWORD1
AntPlus KEYWORD1
JoystickController KEYWORD1

+ 43
- 21
midi.cpp View File

@@ -27,7 +27,7 @@
#define print USBHost::print_
#define println USBHost::println_

void MIDIDevice::init()
void MIDIDeviceBase::init()
{
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t));
@@ -83,7 +83,7 @@ void MIDIDevice::init()
// EP_CONTROL_UNDEFINED 0x00
// ASSOCIATION_CONTROL 0x01

bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
bool MIDIDeviceBase::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
{
// only claim at interface level
if (type != 1) return false;
@@ -96,10 +96,18 @@ bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint
if (p[0] != 9 || p[1] != 4) return false; // interface descriptor
//println(" bInterfaceClass=", p[5]);
//println(" bInterfaceSubClass=", p[6]);
if (p[5] != 1) return false; // bInterfaceClass: 1 = Audio class
if (p[6] != 3) return false; // bInterfaceSubClass: 3 = MIDI
bool ismidi = false;
if (p[5] == 1 && p[6] == 3) {
println(" Interface is MIDI"); // p[5] is bInterfaceClass: 1 = Audio class
ismidi = true; // p[6] is bInterfaceSubClass: 3 = MIDI
} else {
if (p[5] >= 2 && p[5] <= 18) return false; // definitely not MIDI
// Yamaha uses vendor specific class, but can be
// identified as MIDI from CS_INTERFACE descriptors.
// https://forum.pjrc.com/threads/55142?p=199162&viewfull=1#post199162
println(" Interface is unknown (might be Yahama)");
}
p += 9;
println(" Interface is MIDI");
rx_ep = 0;
tx_ep = 0;

@@ -117,16 +125,25 @@ bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint
if (subtype == 1) {
// Interface Header, midi 1.0, page 21
println(" MIDI Header (ignored)");
ismidi = true;
} else if (subtype == 2) {
// MIDI IN Jack, midi 1.0, page 22
println(" MIDI IN Jack (ignored)");
ismidi = true;
} else if (subtype == 3) {
// MIDI OUT Jack, midi 1.0, page 22
println(" MIDI OUT Jack (ignored)");
ismidi = true;
} else if (subtype == 4) {
// Element Descriptor, midi 1.0, page 23-24
println(" MIDI Element (ignored)");
ismidi = true;
} else if (subtype == 0xF1 && p[3] == 2) {
// see Linux sound/usb/quirks.c create_roland_midi_quirk()
println(" Roland vendor-specific (ignored)");
ismidi = true;
} else {
println(" Unknown MIDI CS_INTERFACE descriptor!");
return false; // unknown
}
} else if (type == 5) {
@@ -160,12 +177,17 @@ bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint
// MIDI endpoint info, midi 1.0: 6.2.2, page 26
println(" MIDI Endpoint Jack Association (ignored)");
} else {
println(" Unknown descriptor, type=", type);
return false; // unknown
}
p += len;
}
if (!ismidi) {
println("This interface is not MIDI");
return false;
}
// if an IN endpoint was found, create its pipe
if (rx_ep && rx_size <= MAX_PACKET_SIZE) {
if (rx_ep && rx_size <= max_packet_size) {
rxpipe = new_Pipe(dev, rx_ep_type, rx_ep, 1, rx_size);
if (rxpipe) {
rxpipe->callback_function = rx_callback;
@@ -176,7 +198,7 @@ bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint
rxpipe = NULL;
}
// if an OUT endpoint was found, create its pipe
if (tx_ep && tx_size <= MAX_PACKET_SIZE) {
if (tx_ep && tx_size <= max_packet_size) {
txpipe = new_Pipe(dev, tx_ep_type, tx_ep, 0, tx_size);
if (txpipe) {
txpipe->callback_function = tx_callback;
@@ -197,21 +219,21 @@ bool MIDIDevice::claim(Device_t *dev, int type, const uint8_t *descriptors, uint
return (rxpipe || txpipe);
}

void MIDIDevice::rx_callback(const Transfer_t *transfer)
void MIDIDeviceBase::rx_callback(const Transfer_t *transfer)
{
if (transfer->driver) {
((MIDIDevice *)(transfer->driver))->rx_data(transfer);
}
}

void MIDIDevice::tx_callback(const Transfer_t *transfer)
void MIDIDeviceBase::tx_callback(const Transfer_t *transfer)
{
if (transfer->driver) {
((MIDIDevice *)(transfer->driver))->tx_data(transfer);
}
}

void MIDIDevice::rx_data(const Transfer_t *transfer)
void MIDIDeviceBase::rx_data(const Transfer_t *transfer)
{
println("MIDIDevice Receive");
print(" MIDI Data: ");
@@ -222,13 +244,13 @@ void MIDIDevice::rx_data(const Transfer_t *transfer)
for (uint32_t i=0; i < len; i++) {
uint32_t msg = rx_buffer[i];
if (msg) {
if (++head >= RX_QUEUE_SIZE) head = 0;
if (++head >= rx_queue_size) head = 0;
rx_queue[head] = msg;
}
}
rx_head = head;
rx_tail = tail;
uint32_t avail = (head < tail) ? tail - head - 1 : RX_QUEUE_SIZE - 1 - head + tail;
uint32_t avail = (head < tail) ? tail - head - 1 : rx_queue_size - 1 - head + tail;
//println("rx_size = ", rx_size);
println("avail = ", avail);
if (avail >= (uint32_t)(rx_size>>2)) {
@@ -244,7 +266,7 @@ void MIDIDevice::rx_data(const Transfer_t *transfer)
}
}

void MIDIDevice::tx_data(const Transfer_t *transfer)
void MIDIDeviceBase::tx_data(const Transfer_t *transfer)
{
println("MIDIDevice transmit complete");
print(" MIDI Data: ");
@@ -257,7 +279,7 @@ void MIDIDevice::tx_data(const Transfer_t *transfer)
}


void MIDIDevice::disconnect()
void MIDIDeviceBase::disconnect()
{
// should rx_queue be cleared?
// as-is, the user can still read MIDI messages
@@ -267,7 +289,7 @@ void MIDIDevice::disconnect()
}


void MIDIDevice::write_packed(uint32_t data)
void MIDIDeviceBase::write_packed(uint32_t data)
{
if (!txpipe) return;
uint32_t tx_max = tx_size / 4;
@@ -305,7 +327,7 @@ void MIDIDevice::write_packed(uint32_t data)
}
}

void MIDIDevice::send_sysex_buffer_has_term(const uint8_t *data, uint32_t length, uint8_t cable)
void MIDIDeviceBase::send_sysex_buffer_has_term(const uint8_t *data, uint32_t length, uint8_t cable)
{
cable = (cable & 0x0F) << 4;
while (length > 3) {
@@ -322,7 +344,7 @@ void MIDIDevice::send_sysex_buffer_has_term(const uint8_t *data, uint32_t length
}
}

void MIDIDevice::send_sysex_add_term_bytes(const uint8_t *data, uint32_t length, uint8_t cable)
void MIDIDeviceBase::send_sysex_add_term_bytes(const uint8_t *data, uint32_t length, uint8_t cable)
{
cable = (cable & 0x0F) << 4;

@@ -354,18 +376,18 @@ void MIDIDevice::send_sysex_add_term_bytes(const uint8_t *data, uint32_t length,



bool MIDIDevice::read(uint8_t channel)
bool MIDIDeviceBase::read(uint8_t channel)
{
uint32_t n, head, tail, avail, ch, type1, type2, b1;

head = rx_head;
tail = rx_tail;
if (head == tail) return false;
if (++tail >= RX_QUEUE_SIZE) tail = 0;
if (++tail >= rx_queue_size) tail = 0;
n = rx_queue[tail];
rx_tail = tail;
if (!rx_packet_queued && rxpipe) {
avail = (head < tail) ? tail - head - 1 : RX_QUEUE_SIZE - 1 - head + tail;
avail = (head < tail) ? tail - head - 1 : rx_queue_size - 1 - head + tail;
if (avail >= (uint32_t)(rx_size>>2)) {
__disable_irq();
queue_Data_Transfer(rxpipe, rx_buffer, rx_size, this);
@@ -552,7 +574,7 @@ bool MIDIDevice::read(uint8_t channel)
return false;
}

void MIDIDevice::sysex_byte(uint8_t b)
void MIDIDeviceBase::sysex_byte(uint8_t b)
{
if (handleSysExPartial && msg_sysex_len >= SYSEX_MAX_LEN) {
// when buffer is full, send another chunk to partial handler.

Loading…
Cancel
Save