gdsports / usb_host_library_samd Goto Github PK
View Code? Open in Web Editor NEWUSB host library 2.0 for Zero/M0/SAMD
USB host library 2.0 for Zero/M0/SAMD
I can make USB_STATE_RUNNING with my Zoom G3 without de USBH_MIDI library.
But when I add the:
USBH_MIDI midiUsb(&usb);
I get problems.
Stuck a while with USB_STATE_CONFIGURING and then USB_STATE_ERROR.
Any Idea of what is happening or what I need to look for?
I just need to send data. Another library that I can use to send data?
outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes_send, dataptr);
How I get the "bAdress" and "epInfo[epDataOutIndex].epAddr" without USBH_MIDI library?
The directional keys are not captured in the ASCII codes and are not returned by the Arduino KeyboardController getKey()
function. However, for the KeyboardController library there is a function getOemKey()
that can be used to capture presses of the directional arrow keys (up down left right). This function returns 79-81 for the arrow keys and then can be translated into the appropriate escape codes in a printKey()
function as below.
I simplified the KeyboardController.ino sample file by deleting all the extra serial write outputs and left only the output for the printKey()
statement as below.
Hardware setup: I ran this on an Adafruit ItsyBitsy M4 with serial output via UART. The UART was setup using #define SerialDebug Serial1
Below is the printkey()
function that translates the getOemKey()
codes into arrow key escape codes for my application.
void printKey() {
switch (keyboard.getOemKey()) { // Trial on 5/4/2020 to see if it will fix arrow keys
case 80:
SerialDebug.write(27); // left
SerialDebug.write(91);
SerialDebug.write(68);
break;
case 79:
SerialDebug.write(27); // Right
SerialDebug.write(91);
SerialDebug.write(67);
break;
case 81:
SerialDebug.write(27); // down
SerialDebug.write(91);
SerialDebug.write(66);
break;
case 82:
SerialDebug.write(27); // up
SerialDebug.write(91);
SerialDebug.write(65);
break;
default:
SerialDebug.write(keyboard.getKey());
break;
}
}
I'm curious whether this works with USBC boards. In theory the CC lines need to have a different configuration for host vs. device. Does that mean some hardware modifications would be necessary?
Can anyone think of a reason why introducing
#include <usbh_midi.h>
#include <usbhub.h>
in a sketch with an OLED display produces garbled images on the display?
the oled runs on I2C on the standard XIAO/QT Py pins of the SAMD21.
Hi folks,
I made an adapter PCB that puts two Adafruit QTPy boards back-to back and connects the UART, SPI and I2C lines (plus power and ground). Happy to share the Eagle files when it's working (or before privately).
However, when I run the MouseController example it only gets "Detached, waiting for Device" and never enumerates. The USB_desc example also just waits with no state changes.
Because the QTPy has only a USB-C connector, I am using a USB-C OTG connector (this one: https://tinyurl.com/y6rd252y )
Is there any chance that the USBHost code won't work w/a USB-C or a USB 3.0 connection?
This same code worked with the Trinket M0, so I'm a bit lost.
Thanks
I'm working on USB MIDI Host support with a USB hub and I cannot get the device to enumerate properly. I have ported changes from the USB Host Shield Library 2.0.
Here are my changes:
https://github.com/DatanoiseTV/USB_Host_Library_SAMD
Any hints?
Hello, I am trying to connect a USB keyboard -> SAMD21 (Itsy Bitsy M0 Express) -> OLED.
I want to send ASCII from the USB keyboard to the M0 so I can output characters on the OLED.
I'm not sure how to use this library. I have installed it into Arduino IDE, used your KeyboardController.ino example code but I'm not sure how to read the serial output to test it.
I've connected a Prolific USB-to-Serial cable to the M0 (tx/Rx) and my computer (shows up as COM14) and opened the port via PuTTY to read the output and this is what I get in the console upon booting up the M0: " ▒▒▒▒▒▒ "
I am new to programming and working with microcontrollers, so if you could offer any help as to how to use this library that would be greatly appreciated!
(P.S. I found your Trinket M0 firmware UF2 stuff and tried that but I also couldn't get it to work on my Itsy Bitsy M0)
I am trying to use this library to implement a simple PTP (picture transfer protocol) to be able to control my DLSR using Trinket M0.
But no matter what, I never get any data from the camera when using the actual PTP.
I can get all the descriptors just fine, as that's done by the library itself. Using them I set up the device to use correct endpoints and config. But then, no matter what, when I tried to get "GetDeviceInfo" from the camera, both outTransfer and inTransfer return 0, but there are never any data coming from inTransfer.
Here is the function that I call when I press a button connected to pin 1 on my trinket.
void camPoll() {
int rcode;
uint16_t length = (sizeof(uint16_t)*2 + sizeof(uint32_t)*2); //dont care about the rest of the container
uint8_t data[length];
memset(data, 0, length);
//little endian
data[0] = 0x0C; //len 0
data[4] = 0x01; //type 0
data[6] = 0x01; //code 1
data[7] = 0x10; //code 0
//send command container
rcode = UsbH.outTransfer(1, ep_info[BULK_OUT].epAddr, length, data);
u8x8log.printf("RC: %d\n", rcode);
uint16_t read = 64;
uint8_t in_data[64];
memset(in_data, 0, 64);
//receive data
rcode = UsbH.inTransfer(1, ep_info[BULK_IN].epAddr, &read, in_data);
u8x8log.printf("RC: %d\n", rcode);
//print data
for (int i = 0; i < 64; i++) {
u8x8log.printf("%02x", in_data[i]);
if ((i + 1) % 8 == 0) u8x8log.printf("\n");
}
}
And every time, I get return code 0, but no data in "in_data".
Also, after 2 tries, I start to get return code 2 on outTransfer.
I have tried literally everything I could think of (different packet sizes, endians, endpoints), but nothing works.
Does anyone have any idea how to actually use this for PTP?
P.S.: I looked into some PTP libraries (libgphoto2, PTP2.0). I followed them as close as I could, but I never get anything from the camera.
I am running some tests here with a FTDI device and I just can't send more than 64 bytes.
Checking the Ftdi.SndData, I saw it calls the OutTransfer which is suppose to deal with the maxpktsize (64 byte) limit.
I didn't test a solution yet, but looks like this is wrong:
uint8_t buf[64];
for( i=0; i<nbytes; i++) {
buf[i] = data[i];
}
nbytes is the number of bytes (total) to be sent, a uint32. But this implementation takes only the fist 64bytes, since buf is 64 bytes long.
This for loop, copying the data to the buffer that will be writen should be done insisde the while (bytes_left)
loop. This while loop seems to be OK, treating the message in chunks of 64 bytes and updating bytes_left every iteration.
I will test the solution tomorrow.
I was using a Trinket M0. That worked so I moved to a Nano 33 iOT and that worked... but going to the RP2040 Connect with Cortex M0+, I am getting errors mentioning the variant. Is there something I can change to allow it to work with the M0+ (133Mhz) or is it a whole different animal?
using on Arduino Nano IOT board
libraries/USB_Host_Library_SAMD-master/src/usbhub.cpp:18:10: fatal error: delay.h: No such file or directory
#include "delay.h"
include from sketch
#include <cdcacm.h>
#include <usbhub.h>
or just
#include <usbhub.h>
if I comment it out , no errors
I'm using the SAMD51 MicroMod with the ATP Carrier board. When the default MouseController example sketch is uploaded, the board is no longer detected by my PC. Is there a way to get it show on the COM port so I can upload new sketches??
USBH_MIDI : Failing to get device descriptor with some devices.
The problem is at line 163 from USBH_MIDI.cpp: (Init)
rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf );
With some devices work fine, and with others doesn't.
(return 0 when successful ; 8 when error )
Looking deep, the problem come from:
Line 206 from USB.cpp
rcode = dispatchPkt(tokSETUP, ep, nak_limit); // Dispatch packet
Any tips?
I can get device descriptor of any devices without using USBH_MIDI (without creating USBH_MIDI class)
I can get device descriptor from my PenDrive, and return that isn't a MIDI Device.
I can't get device descriptor from my Mouse by example, returning the RCODE equal 8.
My Zoom G3 works fine. My Nux MG300 doesn't.
First off, thanks for making the port! I'm trying to connect my PS3 nav controller to an MKR 1010 but I'm having some trouble. To pair the controller do we still have to find a way to plug it into the MKR board?
Also is there any way to access the serial port once it's programmed?
Thanks!
cannot compile this library anymore on MKRzero, stops at "Arduino/Sketches/libraries/USB_Host_Library_SAMD/src/usbhub.cpp:18:10: fatal error: delay.h: No such file or directory".
Hi,
This library is perfect for my needs, but I'm finding it is losing MIDI messages. Has anyone else seen this?
To demonstrate the issue, I've create a lightly modified version of the USBH_MIDI_dump.ino
file at:
https://gist.github.com/todbot/7f05268ed3c5201c163a3e269d2c2d64
It parses out the received buffer into a collection of 4-byte USB-MIDI messages and logs the number of Note-On vs Note-Off messages.
If hooking up a USB MIDI keyboard (I've tried several) and mashing on the keys, you'll notice a mismatch between Note-On and Note-Off messages. You an also hear this if hooking up a serial MIDI synth to USB_MIDI_converter.ino
.
I have enabled DEBUG_USB_HOST
and can see the startup messages but no errors. I've tested this on a Trinket M0, ItsyBitsy M0 and ItsyBitsy M4, all with the same result.
I'd like to diagnose this issue. I have some experience with USB but not host stacks. Any tips on where to start?
Hello,
I am trying to figure out a way to disable USB host or be able to switch from USB host USB device mode. Does this library offer this functionality?
I connect MKR 1010 to a Lidar with a OTG cable .MKR 1010 is USBHost , it can send command to Lidar and receive data from Lidar.
But the problem I meet is the data I receive is loss some bytes. The bellow is my code.
`#include <cdcacm.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include <usbhub.h>
#include "pgmstrings.h"
// On SAMD boards where the native USB port is also the serial console, use
// Serial1 for the serial console. This applies to all SAMD boards except for
// Arduino Zero and M0 boards.
#if (USB_VID==0x2341 && defined(ARDUINO_SAMD_ZERO)) || (USB_VID==0x2a03 && defined(ARDUINO_SAM_ZERO))
#define SerialDebug SERIAL_PORT_MONITOR
#else
#define SerialDebug Serial1
#endif
class ACMAsyncOper : public CDCAsyncOper
{
public:
uint8_t OnInit(ACM *pacm);
};
uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
uint8_t rcode;
// Set DTR = 1 RTS=1
rcode = pacm->SetControlLineState(3);
if (rcode)
{
ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate = 115200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode = pacm->SetLineCoding(&lc);
if (rcode)
ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
return rcode;
}
uint8_t* hokuyo_data= (uint8_t*) malloc(128);
char ssid[] = "passssss";
char pass[] = "12345678";
int keIndex = 0;
int status = WL_IDLE_STATUS;
const IPAddress serverIP(192, 168, 137, 1);
uint16_t serverPort = 54768;
WiFiClient client;
USBHost UsbH;
USBHub Hub(&UsbH);
ACMAsyncOper AsyncOper;
ACM Acm(&UsbH, &AsyncOper);
void setup()
{
// SerialDebug.begin(19200);
// SerialDebug.println("Start");
if (UsbH.Init())
//SerialDebug.println("USB host failed to initialize");
delay( 200 );
//SerialDebug.println("USB Host init OK");
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
//Serial.print(".");
}
if (client.connect(serverIP, serverPort))
{
client.print("Hello world!");
}
else
{
client.stop();
}
//client.connect(serverIP, serverPort);
//client.print("Hello world!");
}
void loop()
{
UsbH.Task();
if (Acm.isReady()) {
uint8_t rcode;
if (client.available()) {
String line = client.readString();
//client.write(line.c_str());
/* sending to the phone */
rcode = Acm.SndData(line.length(), (uint8_t*) line.c_str());
if (rcode)
ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
} //if(Serial.available()...
//delay(50);
uint32_t epAddr = Acm.GetEpAddress();
static uint8_t buf[1024];
uint16_t rcvd = 1024;
rcode = Acm.RcvData(&rcvd, buf);
if (rcode && rcode != USB_ERRORFLOW)
ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
if (rcvd) { //more than zero bytes received
for (uint16_t i = 0; i < rcvd; i++) {
client.write((char) buf[i]); //printing on the screen
}
}
}
}`
hi sir, I use this librarry with my seeeduino xiao to controlling my MIDI device. I have tested on several MIDI Device and It's work og my BOSS ME 80, Zoom MS60B, Behringer BCF2000. but when I try on Korg PA300 still detected and sketch running normally but no MIDI messages sent to KORG PA300. how I can fix it? thanks
Question/test request
Could this work:
Hi the datasheet for the SAMD21 here https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/Atmel-42181-SAM-D21_Datasheet.pdf page 836, says that the ADDR value must be aligned with the two least significant bits zero.
So in USBH_MIDI_dump.ino the bufMidi declaration should be
uint8_t bufMidi[64] __attribute__ ((aligned (4)));
Similarly, looking at USB_MIDI_converter_multi.ino, this leads to the declaration in usbh_midi.h
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
This also needs to be aligned per the datasheet.
I am not sure the implications of this. I am doing a deep dive on this code to sort out the dropped MIDI message problem, and just stumbled on it.
I am using an Seeed Xiao SAMD21 controller as an USB Host.
The USB counter part I would like to read and write to is a custom Controller from a 3rd-party company that normally connects via USB-FTDI COM port to a computer.
I would like to directly connect this 3rd-party Controller to my Xiao SAMD21 USB-Host.
By the below code example1, I achieved to read from the 3rd-party controller !!
I used the existing example for a PL2303 from the given USB_Host_Library_SAMD library. And this PL2303 example seemed to work best to interact with my 3rd-party Controller.
However, there are still two problems:
As for the first problem: erroneous readings:
Some readings are cut-off parts of the receiving string. Most receiving-communication works. There is just about every 10th cmd from the 3rd-party controller that is only partially transmitted (i.e. partially received). I tried to change the delay in the receiving routine as can be seen in example1 below. But without success.
Do you have any idea what I could do in order to get 100% successful data readings ?
Example1: Receiving data from the 3rd-party Controller to a SAMD21 USB-Host:
#include <usbhub.h>
#include <cdcacm.h>
#include <cdcprolific.h>
class PLAsyncOper : public CDCAsyncOper {
public:
uint8_t OnInit(ACM *pacm);
};
uint8_t PLAsyncOper::OnInit(ACM *pacm) {
uint8_t rcode;
// Set DTR = 1
rcode = pacm->SetControlLineState(1);
if (rcode) {
ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate = 115200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode = pacm->SetLineCoding(&lc);
if (rcode) {
ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
}
return rcode;
}
USBHost UsbH;
PLAsyncOper AsyncOper;
PL2303 Pl(&UsbH, &AsyncOper);
void setup() {
Serial1.begin(115200); // receiving from 3rd-party controller and sending to Serial1
delay(2000);
if (UsbH.Init()) {
Serial1.println("USB host did not start");
}
delay( 200 );
}
void loop() {
UsbH.Task();
if( UsbH.getUsbTaskState() == USB_STATE_RUNNING ) {
uint8_t rcode;
uint8_t buf[32];
uint16_t rcvd = 32;
rcode = Pl.RcvData(&rcvd, buf);
if (rcvd) { // more than zero bytes received
String receivedStr = "";
for (uint16_t i=0; i < rcvd; i++ ) {
receivedStr += (char)buf[i];
delay(3);
// delay(5); // ...other delays did not have an effect, unfortunately
// delay(10); // ... but without any delay, every cmd is only received partailly. So I think there must be a delay even tough it makes the entire reading slower....
// delay(20);
// delay(100);
}
Serial1.write(receivedStr.c_str());
}
}
}
Also, I tried to write to the 3rd-party Controller - but this did not work at all. See code-example 2
Example2: Sending data to the 3rd-party Controller from a SAMD21 USB-Host:
#include <usbhub.h>
#include <cdcacm.h>
#include <cdcprolific.h>
class PLAsyncOper : public CDCAsyncOper {
public:
uint8_t OnInit(ACM *pacm);
};
uint8_t PLAsyncOper::OnInit(ACM *pacm) {
uint8_t rcode;
// Set DTR = 1
rcode = pacm->SetControlLineState(1);
if (rcode) {
ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate = 115200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode = pacm->SetLineCoding(&lc);
if (rcode) {
ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
}
return rcode;
}
USBHost UsbH;
PLAsyncOper AsyncOper;
PL2303 Pl(&UsbH, &AsyncOper);
void setup() {
Serial1.begin(115200); // receiving from 3rd-party controller and sending to Serial1
delay(2000);
if (UsbH.Init()) {
Serial1.println("USB host did not start");
}
delay( 200 );
}
void loop() {
UsbH.Task();
if( UsbH.getUsbTaskState() == USB_STATE_RUNNING ) {
uint8_t rcode;
// sending to the 3rd-party controller
if (Serial1.available()) {
uint8_t data= Serial1.read();
rcode = Pl.SndData(1, &data);
}
}
}
There was no data transmission at all. What could be improved ??
Questions:
Here is a complete printout of the 3rd-party USB chip that my 3rd-party Controller contains:
String Descriptors:
Manufacturer: Prolific Technology Inc.
Product: USB-Serial Controller D
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0110
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 40
Vendor ID: 067B
Product ID: 2303
Revision ID: 0400
Mfg.string index: 01
Prod.string index: 02
Serial number index: 00
Number of conf.: 01
Configuration descriptor:
Total length: 0027
Num.intf: 01
Conf.value: 01
Conf.string: 00
Attr.: 80
Max.pwr: 32
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 03
Intf. Class: FF
Intf. Subclass: 00
Intf. Protocol: 00
Intf.string: 00
Endpoint descriptor:
Atr:oint address03 81
axpktsie 00
olin iteva: 0
ndpin dsrito:
npontaddes:02
At.: 0
Polig ntrvl 000
Enpintdecrpor
Atr.t ddes: 0
Polig ntrvl:0 000
Adr1(.01)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.