Sfoglia il codice sorgente

Merge branch 'master' into WIP2-Bluetooth

main
Paul Stoffregen 5 anni fa
parent
commit
4bcb12fa60
Nessun account collegato all'indirizzo email del committer
4 ha cambiato i file con 106 aggiunte e 47 eliminazioni
  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 Vedi File



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


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


ActiveSensing = 0xFE, // System Real Time - Active Sensing ActiveSensing = 0xFE, // System Real Time - Active Sensing
SystemReset = 0xFF, // System Real Time - System Reset 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) { void sendNoteOff(uint8_t note, uint8_t velocity, uint8_t channel, uint8_t cable=0) {
send(0x80, note, velocity, channel, cable); send(0x80, note, velocity, channel, cable);
} }
private: private:
Pipe_t *rxpipe; Pipe_t *rxpipe;
Pipe_t *txpipe; 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 rx_size;
uint16_t tx_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; bool rx_packet_queued;
const uint16_t max_packet_size;
const uint16_t rx_queue_size;
uint16_t rx_head; uint16_t rx_head;
uint16_t rx_tail; uint16_t rx_tail;
volatile uint8_t tx1_count; volatile uint8_t tx1_count;
strbuf_t mystring_bufs[1]; 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 { class USBSerial: public USBDriver, public Stream {

+ 14
- 16
ehci.cpp Vedi File

transfer = allocate_Transfer(); transfer = allocate_Transfer();
if (!transfer) return false; if (!transfer) return false;
data = transfer; 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 // last qTD needs info for followup
data->qtd.next = 1; data->qtd.next = 1;
data->pipe = pipe; data->pipe = pipe;

+ 1
- 0
keywords.txt Vedi File

MouseController KEYWORD1 MouseController KEYWORD1
DigitizerController KEYWORD1 DigitizerController KEYWORD1
MIDIDevice KEYWORD1 MIDIDevice KEYWORD1
MIDIDevice_BigBuffer KEYWORD1
USBSerial KEYWORD1 USBSerial KEYWORD1
AntPlus KEYWORD1 AntPlus KEYWORD1
JoystickController KEYWORD1 JoystickController KEYWORD1

+ 43
- 21
midi.cpp Vedi File

#define print USBHost::print_ #define print USBHost::print_
#define println USBHost::println_ #define println USBHost::println_


void MIDIDevice::init()
void MIDIDeviceBase::init()
{ {
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t));
// EP_CONTROL_UNDEFINED 0x00 // EP_CONTROL_UNDEFINED 0x00
// ASSOCIATION_CONTROL 0x01 // 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 // only claim at interface level
if (type != 1) return false; if (type != 1) return false;
if (p[0] != 9 || p[1] != 4) return false; // interface descriptor if (p[0] != 9 || p[1] != 4) return false; // interface descriptor
//println(" bInterfaceClass=", p[5]); //println(" bInterfaceClass=", p[5]);
//println(" bInterfaceSubClass=", p[6]); //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; p += 9;
println(" Interface is MIDI");
rx_ep = 0; rx_ep = 0;
tx_ep = 0; tx_ep = 0;


if (subtype == 1) { if (subtype == 1) {
// Interface Header, midi 1.0, page 21 // Interface Header, midi 1.0, page 21
println(" MIDI Header (ignored)"); println(" MIDI Header (ignored)");
ismidi = true;
} else if (subtype == 2) { } else if (subtype == 2) {
// MIDI IN Jack, midi 1.0, page 22 // MIDI IN Jack, midi 1.0, page 22
println(" MIDI IN Jack (ignored)"); println(" MIDI IN Jack (ignored)");
ismidi = true;
} else if (subtype == 3) { } else if (subtype == 3) {
// MIDI OUT Jack, midi 1.0, page 22 // MIDI OUT Jack, midi 1.0, page 22
println(" MIDI OUT Jack (ignored)"); println(" MIDI OUT Jack (ignored)");
ismidi = true;
} else if (subtype == 4) { } else if (subtype == 4) {
// Element Descriptor, midi 1.0, page 23-24 // Element Descriptor, midi 1.0, page 23-24
println(" MIDI Element (ignored)"); 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 { } else {
println(" Unknown MIDI CS_INTERFACE descriptor!");
return false; // unknown return false; // unknown
} }
} else if (type == 5) { } else if (type == 5) {
// MIDI endpoint info, midi 1.0: 6.2.2, page 26 // MIDI endpoint info, midi 1.0: 6.2.2, page 26
println(" MIDI Endpoint Jack Association (ignored)"); println(" MIDI Endpoint Jack Association (ignored)");
} else { } else {
println(" Unknown descriptor, type=", type);
return false; // unknown return false; // unknown
} }
p += len; p += len;
} }
if (!ismidi) {
println("This interface is not MIDI");
return false;
}
// if an IN endpoint was found, create its pipe // 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); rxpipe = new_Pipe(dev, rx_ep_type, rx_ep, 1, rx_size);
if (rxpipe) { if (rxpipe) {
rxpipe->callback_function = rx_callback; rxpipe->callback_function = rx_callback;
rxpipe = NULL; rxpipe = NULL;
} }
// if an OUT endpoint was found, create its pipe // 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); txpipe = new_Pipe(dev, tx_ep_type, tx_ep, 0, tx_size);
if (txpipe) { if (txpipe) {
txpipe->callback_function = tx_callback; txpipe->callback_function = tx_callback;
return (rxpipe || txpipe); return (rxpipe || txpipe);
} }


void MIDIDevice::rx_callback(const Transfer_t *transfer)
void MIDIDeviceBase::rx_callback(const Transfer_t *transfer)
{ {
if (transfer->driver) { if (transfer->driver) {
((MIDIDevice *)(transfer->driver))->rx_data(transfer); ((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) { if (transfer->driver) {
((MIDIDevice *)(transfer->driver))->tx_data(transfer); ((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"); println("MIDIDevice Receive");
print(" MIDI Data: "); print(" MIDI Data: ");
for (uint32_t i=0; i < len; i++) { for (uint32_t i=0; i < len; i++) {
uint32_t msg = rx_buffer[i]; uint32_t msg = rx_buffer[i];
if (msg) { if (msg) {
if (++head >= RX_QUEUE_SIZE) head = 0;
if (++head >= rx_queue_size) head = 0;
rx_queue[head] = msg; rx_queue[head] = msg;
} }
} }
rx_head = head; rx_head = head;
rx_tail = tail; 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("rx_size = ", rx_size);
println("avail = ", avail); println("avail = ", avail);
if (avail >= (uint32_t)(rx_size>>2)) { if (avail >= (uint32_t)(rx_size>>2)) {
} }
} }


void MIDIDevice::tx_data(const Transfer_t *transfer)
void MIDIDeviceBase::tx_data(const Transfer_t *transfer)
{ {
println("MIDIDevice transmit complete"); println("MIDIDevice transmit complete");
print(" MIDI Data: "); print(" MIDI Data: ");
} }




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




void MIDIDevice::write_packed(uint32_t data)
void MIDIDeviceBase::write_packed(uint32_t data)
{ {
if (!txpipe) return; if (!txpipe) return;
uint32_t tx_max = tx_size / 4; uint32_t tx_max = tx_size / 4;
} }
} }


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; cable = (cable & 0x0F) << 4;
while (length > 3) { while (length > 3) {
} }
} }


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; cable = (cable & 0x0F) << 4;








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


head = rx_head; head = rx_head;
tail = rx_tail; tail = rx_tail;
if (head == tail) return false; if (head == tail) return false;
if (++tail >= RX_QUEUE_SIZE) tail = 0;
if (++tail >= rx_queue_size) tail = 0;
n = rx_queue[tail]; n = rx_queue[tail];
rx_tail = tail; rx_tail = tail;
if (!rx_packet_queued && rxpipe) { 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)) { if (avail >= (uint32_t)(rx_size>>2)) {
__disable_irq(); __disable_irq();
queue_Data_Transfer(rxpipe, rx_buffer, rx_size, this); queue_Data_Transfer(rxpipe, rx_buffer, rx_size, this);
return false; return false;
} }


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

Loading…
Annulla
Salva