Merge branch 'master' into ESP8266

* master:
  Update MIDI driver v0.3.2
  Fix missing unsigned comparison.
  Release version 1.3.0
  Added intel_arc32 to PlatformIO platforms
  Fixed type in waitingForConnection variable and set it to false when pairing
  Use descriptor length in order to advance the buffer when parsing the descriptors
This commit is contained in:
Kristian Sloth Lauszus 2017-05-11 00:12:30 +02:00
commit 14fec8dab8
15 changed files with 144 additions and 177 deletions

View file

@ -51,7 +51,7 @@ env:
- PLATFORMIO_CI_SRC=examples/PSBuzz - PLATFORMIO_CI_SRC=examples/PSBuzz
# - PLATFORMIO_CI_SRC=examples/testusbhostFAT # - PLATFORMIO_CI_SRC=examples/testusbhostFAT
- PLATFORMIO_CI_SRC=examples/USB_desc - PLATFORMIO_CI_SRC=examples/USB_desc
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidrectional_converter - PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidirectional_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/eVY1_sample - PLATFORMIO_CI_SRC=examples/USBH_MIDI/eVY1_sample
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter_multi - PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter_multi

View file

@ -254,7 +254,7 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
hci_counter = 0; hci_counter = 0;
hci_state = HCI_INIT_STATE; hci_state = HCI_INIT_STATE;
watingForConnection = false; waitingForConnection = false;
bPollEnable = true; bPollEnable = true;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
@ -802,14 +802,14 @@ void BTD::HCI_task() {
Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80); Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
#endif #endif
hci_write_scan_enable(); hci_write_scan_enable();
watingForConnection = true; waitingForConnection = true;
hci_state = HCI_CONNECT_IN_STATE; hci_state = HCI_CONNECT_IN_STATE;
} }
break; break;
case HCI_CONNECT_IN_STATE: case HCI_CONNECT_IN_STATE:
if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) { if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
watingForConnection = false; waitingForConnection = false;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nIncoming Connection Request"), 0x80); Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
#endif #endif

9
BTD.h
View file

@ -432,7 +432,7 @@ public:
/**@}*/ /**@}*/
/** Use this to see if it is waiting for a incoming connection. */ /** Use this to see if it is waiting for a incoming connection. */
bool watingForConnection; bool waitingForConnection;
/** This is used by the service to know when to store the device information. */ /** This is used by the service to know when to store the device information. */
bool l2capConnectionClaimed; bool l2capConnectionClaimed;
/** This is used by the SPP library to claim the current SDP incoming request. */ /** This is used by the SPP library to claim the current SDP incoming request. */
@ -476,14 +476,15 @@ public:
/** True if it's a Wii U Pro Controller. */ /** True if it's a Wii U Pro Controller. */
bool wiiUProController; bool wiiUProController;
/** Call this function to pair with a Wiimote */ /** Call this function to pair with a HID device */
void pairWithHID() { void pairWithHID() {
waitingForConnection = false;
pairWithHIDDevice = true; pairWithHIDDevice = true;
hci_state = HCI_CHECK_DEVICE_SERVICE; hci_state = HCI_CHECK_DEVICE_SERVICE;
}; };
/** Used to only send the ACL data to the Wiimote. */ /** Used to only send the ACL data to the HID device. */
bool connectToHIDDevice; bool connectToHIDDevice;
/** True if a Wiimote is connecting. */ /** True if a HID device is connecting. */
bool incomingHIDDevice; bool incomingHIDDevice;
/** True when it should pair with a device like a mouse or keyboard. */ /** True when it should pair with a device like a mouse or keyboard. */
bool pairWithHIDDevice; bool pairWithHIDDevice;

View file

@ -21,8 +21,9 @@
#include "hiduniversal.h" #include "hiduniversal.h"
#include "PS4Parser.h" #include "PS4Parser.h"
#define PS4_VID 0x054C // Sony Corporation #define PS4_VID 0x054C // Sony Corporation
#define PS4_PID 0x05C4 // PS4 Controller #define PS4_PID 0x05C4 // PS4 Controller
#define PS4_PID_SLIM 0x09CC // PS4 Slim Controller
/** /**
* This class implements support for the PS4 controller via USB. * This class implements support for the PS4 controller via USB.
@ -44,7 +45,7 @@ public:
* @return Returns true if it is connected. * @return Returns true if it is connected.
*/ */
bool connected() { bool connected() {
return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID; return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM);
}; };
/** /**
@ -65,7 +66,7 @@ protected:
* @param buf Pointer to the data buffer. * @param buf Pointer to the data buffer.
*/ */
virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM))
PS4Parser::Parse(len, buf); PS4Parser::Parse(len, buf);
}; };
@ -75,7 +76,7 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way. * This is useful for instance if you want to set the LEDs in a specific way.
*/ */
virtual uint8_t OnInitSuccessful() { virtual uint8_t OnInitSuccessful() {
if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) { if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM)) {
PS4Parser::Reset(); PS4Parser::Reset();
if (pFuncOnInit) if (pFuncOnInit)
pFuncOnInit(); // Call the user function pFuncOnInit(); // Call the user function
@ -120,7 +121,7 @@ protected:
* @return Returns true if the device's VID and PID matches this driver. * @return Returns true if the device's VID and PID matches this driver.
*/ */
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) { virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
return (vid == PS4_VID && pid == PS4_PID); return (vid == PS4_VID && (pid == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM));
}; };
/**@}*/ /**@}*/

View file

@ -119,16 +119,13 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
switch(dscrType) { switch(dscrType) {
case USB_DESCRIPTOR_INTERFACE: case USB_DESCRIPTOR_INTERFACE:
isGoodInterface = false; isGoodInterface = false;
break;
case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_CONFIGURATION:
theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
break;
case USB_DESCRIPTOR_ENDPOINT: case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
break;
case HID_DESCRIPTOR_HID: case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2;
break; break;
} }
theBuffer.valueSize = dscrLen - 2;
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
stateParseDescr = 4; stateParseDescr = 4;
case 4: case 4:

View file

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* USB-MIDI dump utility * USB-MIDI dump utility
* Copyright (C) 2013-2016 Yuuichi Akagawa * Copyright (C) 2013-2017 Yuuichi Akagawa
* *
* for use with USB Host Shield 2.0 from Circuitsathome.com * for use with USB Host Shield 2.0 from Circuitsathome.com
* https://github.com/felis/USB_Host_Shield_2.0 * https://github.com/felis/USB_Host_Shield_2.0
@ -24,7 +24,7 @@ USB Usb;
USBH_MIDI Midi(&Usb); USBH_MIDI Midi(&Usb);
void MIDI_poll(); void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime); void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
boolean bFirst; boolean bFirst;
uint16_t pid, vid; uint16_t pid, vid;
@ -46,13 +46,13 @@ void loop()
//unsigned long t1; //unsigned long t1;
Usb.Task(); Usb.Task();
//t1 = micros(); //uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{ {
MIDI_poll(); MIDI_poll();
} }
//delay(1ms) //delay(1ms)
//doDelay(t1, micros(), 1000); //doDelay(t1, (uint32_t)micros(), 1000);
} }
// Poll USB MIDI Controler and send to serial MIDI // Poll USB MIDI Controler and send to serial MIDI
@ -69,11 +69,7 @@ void MIDI_poll()
pid = Midi.pid; pid = Midi.pid;
} }
if (Midi.RecvData( &rcvd, bufMidi) == 0 ) { if (Midi.RecvData( &rcvd, bufMidi) == 0 ) {
#ifdef __ARDUINO_ARC__ sprintf(buf, "%08lX: ", (uint32_t)millis());
sprintf(buf, "%016llX: ", millis()); // millis() is 64-bits on the Arduino/Genuino 101
#else
sprintf(buf, "%08lX: ", millis());
#endif
Serial.print(buf); Serial.print(buf);
Serial.print(rcvd); Serial.print(rcvd);
Serial.print(':'); Serial.print(':');
@ -86,9 +82,9 @@ void MIDI_poll()
} }
// Delay time (max 16383 us) // Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime) void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{ {
unsigned long t3; uint32_t t3;
if ( t1 > t2 ) { if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2); t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* USB-MIDI to Legacy Serial MIDI converter * USB-MIDI to Legacy Serial MIDI converter
* Copyright (C) 2012-2016 Yuuichi Akagawa * Copyright (C) 2012-2017 Yuuichi Akagawa
* *
* Idea from LPK25 USB-MIDI to Serial MIDI converter * Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com * by Collin Cunningham - makezine.com, narbotic.com
@ -35,7 +35,7 @@ USB Usb;
USBH_MIDI Midi(&Usb); USBH_MIDI Midi(&Usb);
void MIDI_poll(); void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime); void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
void setup() void setup()
{ {
@ -49,16 +49,14 @@ void setup()
void loop() void loop()
{ {
unsigned long t1;
Usb.Task(); Usb.Task();
t1 = micros(); uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{ {
MIDI_poll(); MIDI_poll();
} }
//delay(1ms) //delay(1ms)
doDelay(t1, micros(), 1000); doDelay(t1, (uint32_t)micros(), 1000);
} }
// Poll USB MIDI Controler and send to serial MIDI // Poll USB MIDI Controler and send to serial MIDI
@ -76,9 +74,9 @@ void MIDI_poll()
} }
// Delay time (max 16383 us) // Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime) void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{ {
unsigned long t3; uint32_t t3;
if ( t1 > t2 ) { if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2); t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* USB-MIDI to Legacy Serial MIDI converter * USB-MIDI to Legacy Serial MIDI converter
* Copyright (C) 2012-2016 Yuuichi Akagawa * Copyright (C) 2012-2017 Yuuichi Akagawa
* *
* Idea from LPK25 USB-MIDI to Serial MIDI converter * Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com * by Collin Cunningham - makezine.com, narbotic.com
@ -37,7 +37,7 @@ USBH_MIDI Midi1(&Usb);
USBH_MIDI Midi2(&Usb); USBH_MIDI Midi2(&Usb);
void MIDI_poll(); void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime); void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
void setup() void setup()
{ {
@ -51,16 +51,14 @@ void setup()
void loop() void loop()
{ {
unsigned long t1;
Usb.Task(); Usb.Task();
t1 = micros(); uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{ {
MIDI_poll(); MIDI_poll();
} }
//delay(1ms) //delay(1ms)
doDelay(t1, micros(), 1000); doDelay(t1, (uint32_t)micros(), 1000);
} }
// Poll USB MIDI Controler and send to serial MIDI // Poll USB MIDI Controler and send to serial MIDI
@ -84,9 +82,9 @@ void MIDI_poll()
} }
// Delay time (max 16383 us) // Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime) void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{ {
unsigned long t3; uint32_t t3;
if ( t1 > t2 ) { if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2); t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* Legacy Serial MIDI and USB Host bidirectional converter * Legacy Serial MIDI and USB Host bidirectional converter
* Copyright (C) 2013-2016 Yuuichi Akagawa * Copyright (C) 2013-2017 Yuuichi Akagawa
* *
* for use with Arduino MIDI library * for use with Arduino MIDI library
* https://github.com/FortySevenEffects/arduino_midi_library/ * https://github.com/FortySevenEffects/arduino_midi_library/
@ -43,13 +43,12 @@ USB Usb;
USBH_MIDI Midi(&Usb); USBH_MIDI Midi(&Usb);
void MIDI_poll(); void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime); void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
//If you want handle System Exclusive message, enable this #define otherwise comment out it. //If you want handle System Exclusive message, enable this #define otherwise comment out it.
#define USBH_MIDI_SYSEX_ENABLE #define USBH_MIDI_SYSEX_ENABLE
#ifdef USBH_MIDI_SYSEX_ENABLE #ifdef USBH_MIDI_SYSEX_ENABLE
MidiSysEx sysExData;
//SysEx: //SysEx:
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) { void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
Midi.SendSysEx(sysexmsg, sizeofsysex); Midi.SendSysEx(sysexmsg, sizeofsysex);
@ -70,7 +69,7 @@ void setup()
void loop() void loop()
{ {
unsigned long t1; uint32_t t1;
uint8_t msg[4]; uint8_t msg[4];
Usb.Task(); Usb.Task();
@ -95,7 +94,7 @@ void loop()
} }
} }
//delay(1ms) //delay(1ms)
doDelay(t1, micros(), 1000); doDelay(t1, (uint32_t)micros(), 1000);
} }
// Poll USB MIDI Controler and send to serial MIDI // Poll USB MIDI Controler and send to serial MIDI
@ -119,28 +118,22 @@ void MIDI_poll()
uint8_t *p = recvBuf; uint8_t *p = recvBuf;
while (readPtr < MIDI_EVENT_PACKET_SIZE) { while (readPtr < MIDI_EVENT_PACKET_SIZE) {
if (*p == 0 && *(p + 1) == 0) break; //data end if (*p == 0 && *(p + 1) == 0) break; //data end
MidiSysEx::Status rc = sysExData.set(p);
switch (rc) { uint8_t outbuf[3];
case MidiSysEx::nonsysex : //No SysEx message send data to Serial MIDI uint8_t rc = Midi.extractSysExData(p, outbuf);
p++; if ( rc == 0 ) {
size = Midi.lookupMsgSize(*p); p++;
_MIDI_SERIAL_PORT.write(p, size); size = Midi.lookupMsgSize(*p);
p += 3; _MIDI_SERIAL_PORT.write(p, size);
break; p += 3;
case MidiSysEx::done : //SysEx end. send data to Serial MIDI } else {
_MIDI_SERIAL_PORT.write(sysExData.get(), sysExData.getSize()); _MIDI_SERIAL_PORT.write(outbuf, rc);
/* FALLTHROUGH */ p += 4;
case MidiSysEx::overflow : //SysEx buffer over. ignore and flush buffer.
sysExData.clear();
/* FALLTHROUGH */
default:
p += 4;
break;
} }
readPtr += 4; readPtr += 4;
} }
#else #else
uint8_t outBuf[ 3 ]; uint8_t outBuf[3];
do { do {
if ( (size = Midi.RecvData(outBuf)) > 0 ) { if ( (size = Midi.RecvData(outBuf)) > 0 ) {
//MIDI Output //MIDI Output
@ -151,9 +144,9 @@ void MIDI_poll()
} }
// Delay time (max 16383 us) // Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime) void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{ {
unsigned long t3; uint32_t t3;
if ( t1 > t2 ) { if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2); t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -96,7 +96,7 @@ void loop()
Usb.Task(); Usb.Task();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {
if ((millis() - next_time) >= 0L) { if ((long)(millis() - next_time) >= 0L) {
Usb.ForEachUsbDevice(&PrintAllDescriptors); Usb.ForEachUsbDevice(&PrintAllDescriptors);
Usb.ForEachUsbDevice(&PrintAllAddresses); Usb.ForEachUsbDevice(&PrintAllAddresses);

View file

@ -75,7 +75,7 @@ PS3MoveConnected KEYWORD2
PS3NavigationConnected KEYWORD2 PS3NavigationConnected KEYWORD2
isReady KEYWORD2 isReady KEYWORD2
watingForConnection KEYWORD2 waitingForConnection KEYWORD2
isTouching KEYWORD2 isTouching KEYWORD2
getX KEYWORD2 getX KEYWORD2

View file

@ -31,7 +31,7 @@
"type": "git", "type": "git",
"url": "https://github.com/felis/USB_Host_Shield_2.0.git" "url": "https://github.com/felis/USB_Host_Shield_2.0.git"
}, },
"version": "1.2.1", "version": "1.3.0",
"license": "GPL-2.0", "license": "GPL-2.0",
"examples": "examples":
[ [
@ -46,6 +46,7 @@
"platforms": "platforms":
[ [
"atmelavr", "atmelavr",
"intel_arc32",
"teensy", "teensy",
"atmelsam", "atmelsam",
"nordicnrf51", "nordicnrf51",

View file

@ -1,9 +1,9 @@
name=USB Host Shield Library 2.0 name=USB Host Shield Library 2.0
version=1.2.1 version=1.3.0
author=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>, Alexei Glushchenko (Circuits@Home) <alex-gl@mail.ru> author=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>, Alexei Glushchenko (Circuits@Home) <alex-gl@mail.ru>
maintainer=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com> maintainer=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>
sentence=Revision 2.0 of MAX3421E-based USB Host Shield Library. sentence=Revision 2.0 of MAX3421E-based USB Host Shield Library.
paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS Buzz, Wii and Xbox controllers. paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS Buzz, Wii and Xbox controllers.
category=Other category=Other
url=https://github.com/felis/USB_Host_Shield_2.0 url=https://github.com/felis/USB_Host_Shield_2.0
architectures=* architectures=*

View file

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* USB-MIDI class driver for USB Host Shield 2.0 Library * USB-MIDI class driver for USB Host Shield 2.0 Library
* Copyright (c) 2012-2016 Yuuichi Akagawa * Copyright (c) 2012-2017 Yuuichi Akagawa
* *
* Idea from LPK25 USB-MIDI to Serial MIDI converter * Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com * by Collin Cunningham - makezine.com, narbotic.com
@ -93,11 +93,9 @@ isMidiFound(false),
readPtr(0) { readPtr(0) {
// initialize endpoint data structures // initialize endpoint data structures
for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) { for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
// epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : 4;
} }
// register in USB subsystem // register in USB subsystem
@ -109,7 +107,7 @@ readPtr(0) {
/* Connection initialization of an MIDI Device */ /* Connection initialization of an MIDI Device */
uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed) uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
{ {
uint8_t buf[DESC_BUFF_SIZE]; uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
uint8_t rcode; uint8_t rcode;
UsbDevice *p = NULL; UsbDevice *p = NULL;
@ -117,6 +115,15 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
uint8_t num_of_conf; // number of configurations uint8_t num_of_conf; // number of configurations
USBTRACE("\rMIDI Init\r\n"); USBTRACE("\rMIDI Init\r\n");
//for reconnect
for(uint8_t i=epDataInIndex; i<=epDataOutIndex; i++) {
epInfo[i].epAddr = (i==epDataInIndex) ? 0x81 : 0x01;
epInfo[i].maxPktSize = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
}
// get memory address of USB device address pool // get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
@ -192,15 +199,18 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
USBTRACE(" PID:"), D_PrintHex(pid, 0x80); USBTRACE(" PID:"), D_PrintHex(pid, 0x80);
USBTRACE2(" #Conf:", num_of_conf); USBTRACE2(" #Conf:", num_of_conf);
isMidiFound = false;
for (uint8_t i=0; i<num_of_conf; i++) { for (uint8_t i=0; i<num_of_conf; i++) {
parseConfigDescr(bAddress, i); rcode = parseConfigDescr(bAddress, i);
if( rcode )
goto FailGetConfDescr;
if (bNumEP > 1) if (bNumEP > 1)
break; break;
} // for } // for
USBTRACE2("\r\nNumEP:", bNumEP); USBTRACE2("\r\nNumEP:", bNumEP);
if( bNumEP < 3 ){ //Device not found. if( bNumEP < 2 ){ //Device not found.
rcode = 0xff; rcode = 0xff;
goto FailGetConfDescr; goto FailGetConfDescr;
} }
@ -214,7 +224,7 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
} }
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
USBTRACE2("Conf:", bConfNum); USBTRACE2("Conf:", bConfNum);
USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80)); USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr); USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
@ -236,7 +246,7 @@ FailSetConfDescr:
} }
/* get and parse config descriptor */ /* get and parse config descriptor */
void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf ) uint8_t USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
{ {
uint8_t buf[ DESC_BUFF_SIZE ]; uint8_t buf[ DESC_BUFF_SIZE ];
uint8_t* buf_ptr = buf; uint8_t* buf_ptr = buf;
@ -245,12 +255,12 @@ void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
uint8_t descr_type; uint8_t descr_type;
unsigned int total_length; unsigned int total_length;
USB_ENDPOINT_DESCRIPTOR *epDesc; USB_ENDPOINT_DESCRIPTOR *epDesc;
boolean isMidi = false; bool isMidi = false;
// get configuration descriptor (get descriptor size only) // get configuration descriptor (get descriptor size only)
rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf ); rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf );
if( rcode ){ if( rcode ){
return; return rcode;
} }
total_length = buf[2] | ((int)buf[3] << 8); total_length = buf[2] | ((int)buf[3] << 8);
if( total_length > DESC_BUFF_SIZE ) { //check if total length is larger than buffer if( total_length > DESC_BUFF_SIZE ) { //check if total length is larger than buffer
@ -260,7 +270,7 @@ void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
// get configuration descriptor (all) // get configuration descriptor (all)
rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
if( rcode ){ if( rcode ){
return; return rcode;
} }
//parsing descriptors //parsing descriptors
@ -313,6 +323,7 @@ void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
}//switch( descr_type }//switch( descr_type
buf_ptr += descr_length; //advance buffer pointer buf_ptr += descr_length; //advance buffer pointer
}//while( buf_ptr <=... }//while( buf_ptr <=...
return 0;
} }
/* Performs a cleanup after failed Init() attempt */ /* Performs a cleanup after failed Init() attempt */
@ -340,12 +351,12 @@ uint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
} }
/* Receive data from MIDI device */ /* Receive data from MIDI device */
uint8_t USBH_MIDI::RecvData(uint8_t *outBuf) uint8_t USBH_MIDI::RecvData(uint8_t *outBuf, bool isRaw)
{ {
uint8_t rcode = 0; //return code uint8_t rcode = 0; //return code
uint16_t rcvd; uint16_t rcvd;
if( bPollEnable == false ) return false; if( bPollEnable == false ) return 0;
//Checking unprocessed message in buffer. //Checking unprocessed message in buffer.
if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){ if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){
@ -368,14 +379,22 @@ uint8_t USBH_MIDI::RecvData(uint8_t *outBuf)
} }
RecvData_return_from_buffer: RecvData_return_from_buffer:
uint8_t m;
uint8_t cin = recvBuf[readPtr];
if( isRaw == true ) {
*(outBuf++) = cin;
}
readPtr++; readPtr++;
outBuf[0] = recvBuf[readPtr]; *(outBuf++) = m = recvBuf[readPtr++];
readPtr++; *(outBuf++) = recvBuf[readPtr++];
outBuf[1] = recvBuf[readPtr]; *(outBuf++) = recvBuf[readPtr++];
readPtr++; return lookupMsgSize(m, cin);
outBuf[2] = recvBuf[readPtr]; }
readPtr++;
return lookupMsgSize(outBuf[0]); /* Receive raw data from MIDI device */
uint8_t USBH_MIDI::RecvRawData(uint8_t *outBuf)
{
return RecvData(outBuf, true);
} }
/* Send data to MIDI device */ /* Send data to MIDI device */
@ -443,10 +462,18 @@ void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
/*Return */ /*Return */
/* 0 : undefined message */ /* 0 : undefined message */
/* 0<: Vaild message size(1-3) */ /* 0<: Vaild message size(1-3) */
uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg) uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)
{ {
uint8_t msgSize = 0; uint8_t msgSize = 0;
//SysEx message?
cin = cin & 0x0f;
if( (cin & 0xc) == 4 ) {
if( cin == 4 || cin == 7 ) return 3;
if( cin == 6 ) return 2;
if( cin == 5 ) return 1;
}
if( midiMsg < 0xf0 ) midiMsg &= 0xf0; if( midiMsg < 0xf0 ) midiMsg &= 0xf0;
switch(midiMsg) { switch(midiMsg) {
//3 bytes messages //3 bytes messages
@ -486,7 +513,7 @@ uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg)
} }
/* SysEx data size counter */ /* SysEx data size counter */
unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr) uint16_t USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
{ {
unsigned int c = 1; unsigned int c = 1;
@ -500,8 +527,8 @@ unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
dataptr++; dataptr++;
c++; c++;
//Limiter (upto 256 bytes) //Limiter (default: 256 bytes)
if(c > 256){ if(c > MIDI_MAX_SYSEX_SIZE){
c = 0; c = 0;
break; break;
} }
@ -510,15 +537,17 @@ unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
} }
/* Send SysEx message to MIDI device */ /* Send SysEx message to MIDI device */
uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, unsigned int datasize, uint8_t nCable) uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable)
{ {
uint8_t buf[64]; uint8_t buf[MIDI_EVENT_PACKET_SIZE];
uint8_t rc; uint8_t rc = 0;
unsigned int n = datasize; uint16_t n = datasize;
unsigned int pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size uint16_t pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size
uint8_t wptr = 0; uint8_t wptr = 0;
uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize; uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;
if( maxpkt > MIDI_EVENT_PACKET_SIZE ) maxpkt = MIDI_EVENT_PACKET_SIZE;
USBTRACE("SendSysEx:\r\t"); USBTRACE("SendSysEx:\r\t");
USBTRACE2(" Length:\t", datasize); USBTRACE2(" Length:\t", datasize);
USBTRACE2(" Total pktSize:\t", pktSize); USBTRACE2(" Total pktSize:\t", pktSize);
@ -571,60 +600,33 @@ uint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)
} }
// uint8_t USBH_MIDI::extractSysExData(uint8_t *p, uint8_t *buf)
// System Exclusive packet data management class
//
MidiSysEx::MidiSysEx()
{ {
clear(); uint8_t rc = 0;
}
void MidiSysEx::clear()
{
pos = 0;
buf[0] = 0;
}
MidiSysEx::Status MidiSysEx::set(uint8_t *p)
{
MidiSysEx::Status rc = MidiSysEx::ok;
uint8_t cin = *(p) & 0x0f; uint8_t cin = *(p) & 0x0f;
//SysEx message? //SysEx message?
if( (cin & 0xc) != 4 ) return MidiSysEx::nonsysex; if( (cin & 0xc) != 4 ) return rc;
switch(cin) { switch(cin) {
case 4: case 4:
case 7: case 7:
if( pos+2 < MIDI_EVENT_PACKET_SIZE ) { *buf++ = *(p+1);
buf[pos++] = *(p+1); *buf++ = *(p+2);
buf[pos++] = *(p+2); *buf++ = *(p+3);
buf[pos++] = *(p+3); rc = 3;
}else{
rc = MidiSysEx::overflow;
}
break;
case 5:
if( pos+1 < MIDI_EVENT_PACKET_SIZE ) {
buf[pos++] = *(p+1);
buf[pos++] = *(p+2);
}else{
rc = MidiSysEx::overflow;
}
break; break;
case 6: case 6:
if( pos < MIDI_EVENT_PACKET_SIZE ) { *buf++ = *(p+1);
buf[pos++] = *(p+1); *buf++ = *(p+2);
}else{ rc = 2;
rc = MidiSysEx::overflow; break;
} case 5:
*buf++ = *(p+1);
rc = 1;
break; break;
default: default:
break; break;
} }
//SysEx end?
if((cin & 0x3) != 0) {
rc = MidiSysEx::done;
}
return(rc); return(rc);
} }

View file

@ -1,7 +1,7 @@
/* /*
******************************************************************************* *******************************************************************************
* USB-MIDI class driver for USB Host Shield 2.0 Library * USB-MIDI class driver for USB Host Shield 2.0 Library
* Copyright (c) 2012-2016 Yuuichi Akagawa * Copyright (c) 2012-2017 Yuuichi Akagawa
* *
* Idea from LPK25 USB-MIDI to Serial MIDI converter * Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com * by Collin Cunningham - makezine.com, narbotic.com
@ -33,6 +33,7 @@
#define USB_SUBCLASS_MIDISTREAMING 3 #define USB_SUBCLASS_MIDISTREAMING 3
#define DESC_BUFF_SIZE 256 #define DESC_BUFF_SIZE 256
#define MIDI_EVENT_PACKET_SIZE 64 #define MIDI_EVENT_PACKET_SIZE 64
#define MIDI_MAX_SYSEX_SIZE 256
class USBH_MIDI; class USBH_MIDI;
class USBH_MIDI : public USBDeviceConfig class USBH_MIDI : public USBDeviceConfig
@ -57,8 +58,8 @@ protected:
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE]; uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
uint8_t readPtr; uint8_t readPtr;
void parseConfigDescr(uint8_t addr, uint8_t conf); uint8_t parseConfigDescr(uint8_t addr, uint8_t conf);
unsigned int countSysExDataSize(uint8_t *dataptr); uint16_t countSysExDataSize(uint8_t *dataptr);
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
void PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ); void PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr );
#endif #endif
@ -67,10 +68,12 @@ public:
USBH_MIDI(USB *p); USBH_MIDI(USB *p);
// Methods for recieving and sending data // Methods for recieving and sending data
uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr); uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr);
uint8_t RecvData(uint8_t *outBuf); uint8_t RecvData(uint8_t *outBuf, bool isRaw=false);
uint8_t RecvRawData(uint8_t *outBuf);
uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0); uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0);
uint8_t lookupMsgSize(uint8_t midiMsg); uint8_t lookupMsgSize(uint8_t midiMsg, uint8_t cin=0);
uint8_t SendSysEx(uint8_t *dataptr, unsigned int datasize, uint8_t nCable=0); uint8_t SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable=0);
uint8_t extractSysExData(uint8_t *p, uint8_t *buf);
uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr); uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr);
// backward compatibility functions // backward compatibility functions
inline uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr){ return RecvData(bytes_rcvd, dataptr); }; inline uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr){ return RecvData(bytes_rcvd, dataptr); };
@ -81,27 +84,4 @@ public:
virtual uint8_t Release(); virtual uint8_t Release();
virtual uint8_t GetAddress() { return bAddress; }; virtual uint8_t GetAddress() { return bAddress; };
}; };
//
// System Exclusive packet data management class
//
class MidiSysEx {
private:
uint8_t pos;
uint8_t buf[MIDI_EVENT_PACKET_SIZE];
public:
typedef enum {
nonsysex = 0,
ok = 1,
done = 0xfe,
overflow = 0xff
} Status;
MidiSysEx();
void clear();
MidiSysEx::Status set(uint8_t *p);
inline uint8_t *get(){return buf;};
inline uint8_t getSize(){return pos;};
};
#endif //_USBH_MIDI_H_ #endif //_USBH_MIDI_H_