1
0
mirror of https://github.com/gdsports/USBHost_t36 synced 2024-11-21 08:35:03 -05:00

Begin work in hub port state machine & debounce wait

This commit is contained in:
PaulStoffregen 2017-02-28 11:39:59 -08:00
parent d0ee653192
commit 81f30ecd5f
2 changed files with 99 additions and 28 deletions

View File

@ -307,6 +307,18 @@ class USBHub : public USBDriver {
public:
USBHub();
enum { MAXPORTS = 7 };
enum {
PORT_OFF = 0,
PORT_DISCONNECT = 1,
PORT_DEBOUNCE1 = 2,
PORT_DEBOUNCE2 = 3,
PORT_DEBOUNCE3 = 4,
PORT_DEBOUNCE4 = 5,
PORT_DEBOUNCE5 = 6,
PORT_RESET = 7,
PORT_RECOVERY = 8,
PORT_ACTIVE = 9
};
protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
virtual void control(const Transfer_t *transfer);
@ -315,15 +327,19 @@ protected:
void send_poweron(uint32_t port);
void send_getstatus(uint32_t port);
void send_clearstatus(uint32_t port);
void send_reset(uint32_t port);
void send_setreset(uint32_t port);
static void callback(const Transfer_t *transfer);
void status_change(const Transfer_t *transfer);
void new_port_status(uint32_t port, uint32_t status);
void start_debounce_timer(uint32_t port);
void stop_debounce_timer(uint32_t port);
USBDriverTimer debouncetimer;
USBDriverTimer mytimer;
USBDriverTimer othertimer;
USBDriverTimer mytimers[MAXPORTS];
uint32_t debounce_in_use;
setup_t setup[MAXPORTS+1];
uint32_t statusbits[MAXPORTS+1];
uint8_t hub_desc[16];
uint8_t endpoint;
uint8_t interval;
@ -332,8 +348,6 @@ protected:
uint8_t powertime;
Pipe_t *changepipe;
uint32_t changebits;
uint32_t statusbits[MAXPORTS+1];
uint16_t portstatus[MAXPORTS];
uint8_t portstate[MAXPORTS];
};

105
hub.cpp
View File

@ -24,7 +24,7 @@
#include <Arduino.h>
#include "USBHost.h"
USBHub::USBHub() : /* mytimer(this), */ othertimer(this)
USBHub::USBHub() : debouncetimer(this), /* mytimer(this), */ othertimer(this)
{
// TODO: free Device_t, Pipe_t & Transfer_t we will need
driver_ready_for_device(this);
@ -44,6 +44,7 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t
//mytimer.start(99129);
othertimer.pointer = (void *)"Hello, I'm othertimer";
//othertimer.start(12345);
debouncetimer.pointer = (void *)"Debounce Timer";
for (int i=0; i < 7; i++) {
mytimers[i].init(this);
//mytimers[i].start((i + 1) * 10000);
@ -83,7 +84,6 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t
numports = 0; // unknown until hub descriptor is read
changepipe = NULL;
changebits = 0;
memset(portstatus, 0, sizeof(portstatus));
memset(portstate, 0, sizeof(portstate));
mk_setup(setup[0], 0xA0, 6, 0x2900, 0, sizeof(hub_desc));
@ -92,18 +92,6 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t
return true;
}
void USBHub::timer_event(USBDriverTimer *timer)
{
uint32_t us = micros() - timer->started_micros;
print("timer event (");
print(us);
print(" us): ");
print((char *)timer->pointer);
print(", this = ");
print((uint32_t)this, HEX);
println(", timer = ", (uint32_t)timer, HEX);
}
void USBHub::send_poweron(uint32_t port)
{
@ -127,9 +115,10 @@ void USBHub::send_clearstatus(uint32_t port)
queue_Control_Transfer(device, &setup[port], NULL, this);
}
void USBHub::send_reset(uint32_t port)
void USBHub::send_setreset(uint32_t port)
{
if (port == 0 || port > numports) return;
println("send_setreset");
mk_setup(setup[port], 0x23, 3, 4, port, 0); // set feature PORT_RESET
queue_Control_Transfer(device, &setup[port], NULL, this);
}
@ -177,7 +166,10 @@ void USBHub::control(const Transfer_t *transfer)
if (status != statusbits[port]) println("ERROR: status not same");
new_port_status(port, status);
}
send_clearstatus(port);
//if (changebits & (1 << port)) {
//changebits &= ~(1 << port);
send_clearstatus(port);
//}
break;
case 0x00100120: // clear hub status
println("Hub Status Cleared");
@ -211,14 +203,11 @@ void USBHub::status_change(const Transfer_t *transfer)
void USBHub::new_port_status(uint32_t port, uint32_t status)
{
if (port == 0 || port > numports) return;
uint32_t priorstatus = portstatus[port - 1];
portstatus[port] = status;
print(" Status: port=");
print(port);
print(", status=");
println(status, HEX);
#if 1
print(" status=");
print(status, HEX);
println(" port=", port);
println(" state=", portstate[port-1]);
// status bits, USB 2.0: 11.24.2.7.1 page 427
if (status & 0x0001) println(" Device is present: ");
if (status & 0x0002) {
@ -240,7 +229,41 @@ void USBHub::new_port_status(uint32_t port, uint32_t status)
if (status & 0x0100) println(" Has Power");
if (status & 0x0800) println(" Test Mode");
if (status & 0x1000) println(" Software Controls LEDs");
#endif
uint8_t &state = portstate[port-1];
switch (state) {
case PORT_OFF:
case PORT_DISCONNECT:
if (status & 0x0001) { // connected
state = PORT_DEBOUNCE1;
start_debounce_timer(port);
}
break;
case PORT_DEBOUNCE1:
case PORT_DEBOUNCE2:
case PORT_DEBOUNCE3:
case PORT_DEBOUNCE4:
case PORT_DEBOUNCE5:
if (status & 0x0001) {
if (++state > PORT_DEBOUNCE5) {
// TODO: check for exclusive access to
// enumeration process... stay in debounce
// and add to wait list if enumeration busy
stop_debounce_timer(port);
println("sending reset");
send_setreset(port);
}
} else {
state = PORT_DISCONNECT;
}
break;
case PORT_RESET:
case PORT_RECOVERY:
case PORT_ACTIVE:
break;
}
/*
if ((status & 0x0001) && !(priorstatus & 0x0001)) {
println(" connect");
// 100 ms debounce (USB 2.0: TATTDB, page 150 & 188)
@ -253,10 +276,44 @@ void USBHub::new_port_status(uint32_t port, uint32_t status)
}
*/
}
void USBHub::timer_event(USBDriverTimer *timer)
{
uint32_t us = micros() - timer->started_micros;
print("timer event (");
print(us);
print(" us): ");
print((char *)timer->pointer);
print(", this = ");
print((uint32_t)this, HEX);
println(", timer = ", (uint32_t)timer, HEX);
if (timer == &debouncetimer) {
uint32_t in_use = debounce_in_use;
if (in_use != 0) {
for (uint32_t i=1; i < numports; i++) {
if (in_use & (1 << i)) send_getstatus(i);
}
debouncetimer.start(20000);
}
}
}
void USBHub::start_debounce_timer(uint32_t port)
{
if (debounce_in_use == 0) debouncetimer.start(20000);
debounce_in_use |= (1 << port);
}
void USBHub::stop_debounce_timer(uint32_t port)
{
debounce_in_use &= ~(1 << port);
}
void USBHub::disconnect()
{
// TODO: free resources