Browse Source

Begin work in hub port state machine & debounce wait

main
PaulStoffregen 7 years ago
parent
commit
81f30ecd5f
2 changed files with 99 additions and 28 deletions
  1. +18
    -4
      USBHost.h
  2. +81
    -24
      hub.cpp

+ 18
- 4
USBHost.h View File

public: public:
USBHub(); USBHub();
enum { MAXPORTS = 7 }; 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: protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
virtual void control(const Transfer_t *transfer); virtual void control(const Transfer_t *transfer);
void send_poweron(uint32_t port); void send_poweron(uint32_t port);
void send_getstatus(uint32_t port); void send_getstatus(uint32_t port);
void send_clearstatus(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); static void callback(const Transfer_t *transfer);
void status_change(const Transfer_t *transfer); void status_change(const Transfer_t *transfer);
void new_port_status(uint32_t port, uint32_t status); 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 mytimer;
USBDriverTimer othertimer; USBDriverTimer othertimer;
USBDriverTimer mytimers[MAXPORTS]; USBDriverTimer mytimers[MAXPORTS];
uint32_t debounce_in_use;
setup_t setup[MAXPORTS+1]; setup_t setup[MAXPORTS+1];
uint32_t statusbits[MAXPORTS+1];
uint8_t hub_desc[16]; uint8_t hub_desc[16];
uint8_t endpoint; uint8_t endpoint;
uint8_t interval; uint8_t interval;
uint8_t powertime; uint8_t powertime;
Pipe_t *changepipe; Pipe_t *changepipe;
uint32_t changebits; uint32_t changebits;
uint32_t statusbits[MAXPORTS+1];
uint16_t portstatus[MAXPORTS];
uint8_t portstate[MAXPORTS]; uint8_t portstate[MAXPORTS];
}; };



+ 81
- 24
hub.cpp View File

#include <Arduino.h> #include <Arduino.h>
#include "USBHost.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 // TODO: free Device_t, Pipe_t & Transfer_t we will need
driver_ready_for_device(this); driver_ready_for_device(this);
//mytimer.start(99129); //mytimer.start(99129);
othertimer.pointer = (void *)"Hello, I'm othertimer"; othertimer.pointer = (void *)"Hello, I'm othertimer";
//othertimer.start(12345); //othertimer.start(12345);
debouncetimer.pointer = (void *)"Debounce Timer";
for (int i=0; i < 7; i++) { for (int i=0; i < 7; i++) {
mytimers[i].init(this); mytimers[i].init(this);
//mytimers[i].start((i + 1) * 10000); //mytimers[i].start((i + 1) * 10000);
numports = 0; // unknown until hub descriptor is read numports = 0; // unknown until hub descriptor is read
changepipe = NULL; changepipe = NULL;
changebits = 0; changebits = 0;
memset(portstatus, 0, sizeof(portstatus));
memset(portstate, 0, sizeof(portstate)); memset(portstate, 0, sizeof(portstate));


mk_setup(setup[0], 0xA0, 6, 0x2900, 0, sizeof(hub_desc)); mk_setup(setup[0], 0xA0, 6, 0x2900, 0, sizeof(hub_desc));
return true; 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) void USBHub::send_poweron(uint32_t port)
{ {
queue_Control_Transfer(device, &setup[port], NULL, this); 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; if (port == 0 || port > numports) return;
println("send_setreset");
mk_setup(setup[port], 0x23, 3, 4, port, 0); // set feature PORT_RESET mk_setup(setup[port], 0x23, 3, 4, port, 0); // set feature PORT_RESET
queue_Control_Transfer(device, &setup[port], NULL, this); queue_Control_Transfer(device, &setup[port], NULL, this);
} }
if (status != statusbits[port]) println("ERROR: status not same"); if (status != statusbits[port]) println("ERROR: status not same");
new_port_status(port, status); new_port_status(port, status);
} }
send_clearstatus(port);
//if (changebits & (1 << port)) {
//changebits &= ~(1 << port);
send_clearstatus(port);
//}
break; break;
case 0x00100120: // clear hub status case 0x00100120: // clear hub status
println("Hub Status Cleared"); println("Hub Status Cleared");
void USBHub::new_port_status(uint32_t port, uint32_t status) void USBHub::new_port_status(uint32_t port, uint32_t status)
{ {
if (port == 0 || port > numports) return; 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 // status bits, USB 2.0: 11.24.2.7.1 page 427
if (status & 0x0001) println(" Device is present: "); if (status & 0x0001) println(" Device is present: ");
if (status & 0x0002) { if (status & 0x0002) {
if (status & 0x0100) println(" Has Power"); if (status & 0x0100) println(" Has Power");
if (status & 0x0800) println(" Test Mode"); if (status & 0x0800) println(" Test Mode");
if (status & 0x1000) println(" Software Controls LEDs"); 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)) { if ((status & 0x0001) && !(priorstatus & 0x0001)) {
println(" connect"); println(" connect");
// 100 ms debounce (USB 2.0: TATTDB, page 150 & 188) // 100 ms debounce (USB 2.0: TATTDB, page 150 & 188)




} }
*/

}



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);
} }





Loading…
Cancel
Save