|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (stat & USBHS_USBSTS_UAI) { // completed qTD(s) from the async schedule |
|
|
if (stat & USBHS_USBSTS_UAI) { // completed qTD(s) from the async schedule |
|
|
Serial.println("Async Followup"); |
|
|
Serial.println("Async Followup"); |
|
|
|
|
|
|
|
|
Transfer_t *p, *prev=NULL, *next; |
|
|
|
|
|
|
|
|
|
|
|
p = async_followup_first; |
|
|
|
|
|
|
|
|
Transfer_t *prev=NULL; |
|
|
|
|
|
Transfer_t *p = async_followup_first; |
|
|
while (p) { |
|
|
while (p) { |
|
|
|
|
|
|
|
|
next = p->next_followup; |
|
|
|
|
|
|
|
|
Transfer_t *next = p->next_followup; |
|
|
if (followup_Transfer(p)) { |
|
|
if (followup_Transfer(p)) { |
|
|
// transfer completed |
|
|
// transfer completed |
|
|
if (prev) { |
|
|
if (prev) { |
|
|
|
|
|
|
|
|
p = next; |
|
|
p = next; |
|
|
} |
|
|
} |
|
|
async_followup_last = prev; |
|
|
async_followup_last = prev; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
if (stat & USBHS_USBSTS_UPI) { // completed qTD(s) from the periodic schedule |
|
|
if (stat & USBHS_USBSTS_UPI) { // completed qTD(s) from the periodic schedule |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void enumeration(const Transfer_t *transfer) |
|
|
|
|
|
{ |
|
|
|
|
|
Serial.print(" CALLBACK: "); |
|
|
|
|
|
uint8_t *p = (uint8_t *)transfer->buffer; |
|
|
|
|
|
for (uint32_t i=0; i < transfer->length; i++) { |
|
|
|
|
|
Serial.print(*p++, HEX); |
|
|
|
|
|
Serial.print(' '); |
|
|
|
|
|
} |
|
|
|
|
|
Serial.println(); |
|
|
|
|
|
print(transfer); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Create a new device and begin the enumeration process |
|
|
// Create a new device and begin the enumeration process |
|
|
// |
|
|
// |
|
|
Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port) |
|
|
Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port) |
|
|
|
|
|
|
|
|
free_Device(dev); |
|
|
free_Device(dev); |
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
dev->control_pipe->callback_function = &enumeration; |
|
|
|
|
|
|
|
|
static uint8_t buffer[8]; |
|
|
static uint8_t buffer[8]; |
|
|
dev->control_pipe->direction = 1; // 1=IN |
|
|
dev->control_pipe->direction = 1; // 1=IN |
|
|
|
|
|
|
|
|
Serial.println("new_Transfer"); |
|
|
Serial.println("new_Transfer"); |
|
|
Transfer_t *transfer = allocate_Transfer(); |
|
|
Transfer_t *transfer = allocate_Transfer(); |
|
|
if (!transfer) return false; |
|
|
if (!transfer) return false; |
|
|
transfer->pipe = pipe; |
|
|
|
|
|
if (pipe->type == 0) { |
|
|
if (pipe->type == 0) { |
|
|
// control transfer |
|
|
// control transfer |
|
|
Transfer_t *data, *status; |
|
|
Transfer_t *data, *status; |
|
|
uint32_t status_direction; |
|
|
uint32_t status_direction; |
|
|
if (len > 16384) { |
|
|
if (len > 16384) { |
|
|
|
|
|
// hopefully we never need more |
|
|
|
|
|
// than 16K in a control transfer |
|
|
free_Transfer(transfer); |
|
|
free_Transfer(transfer); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
init_qTD(data, buffer, len, pipe->direction, 1, false); |
|
|
init_qTD(data, buffer, len, pipe->direction, 1, false); |
|
|
transfer->qtd.next = (uint32_t)data; |
|
|
transfer->qtd.next = (uint32_t)data; |
|
|
data->qtd.next = (uint32_t)status; |
|
|
data->qtd.next = (uint32_t)status; |
|
|
data->pipe = pipe; |
|
|
|
|
|
status_direction = pipe->direction ^ 1; |
|
|
status_direction = pipe->direction ^ 1; |
|
|
} else { |
|
|
} else { |
|
|
transfer->qtd.next = (uint32_t)status; |
|
|
transfer->qtd.next = (uint32_t)status; |
|
|
|
|
|
|
|
|
init_qTD(transfer, &pipe->device->setup, 8, 2, 0, false); |
|
|
init_qTD(transfer, &pipe->device->setup, 8, 2, 0, false); |
|
|
init_qTD(status, NULL, 0, status_direction, 1, true); |
|
|
init_qTD(status, NULL, 0, status_direction, 1, true); |
|
|
status->pipe = pipe; |
|
|
status->pipe = pipe; |
|
|
|
|
|
status->buffer = buffer; |
|
|
|
|
|
status->length = len; |
|
|
status->qtd.next = 1; |
|
|
status->qtd.next = 1; |
|
|
} else { |
|
|
} else { |
|
|
// bulk, interrupt or isochronous transfer |
|
|
// bulk, interrupt or isochronous transfer |
|
|
|
|
|
|
|
|
// copy transfer non-token fields to halt |
|
|
// copy transfer non-token fields to halt |
|
|
halt->qtd.next = transfer->qtd.next; |
|
|
halt->qtd.next = transfer->qtd.next; |
|
|
halt->qtd.alt_next = transfer->qtd.alt_next; |
|
|
halt->qtd.alt_next = transfer->qtd.alt_next; |
|
|
halt->qtd.buffer[0] = transfer->qtd.buffer[0]; |
|
|
|
|
|
|
|
|
halt->qtd.buffer[0] = transfer->qtd.buffer[0]; // TODO: optimize... |
|
|
halt->qtd.buffer[1] = transfer->qtd.buffer[1]; |
|
|
halt->qtd.buffer[1] = transfer->qtd.buffer[1]; |
|
|
halt->qtd.buffer[2] = transfer->qtd.buffer[2]; |
|
|
halt->qtd.buffer[2] = transfer->qtd.buffer[2]; |
|
|
halt->qtd.buffer[3] = transfer->qtd.buffer[3]; |
|
|
halt->qtd.buffer[3] = transfer->qtd.buffer[3]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!(transfer->qtd.token & 0x80)) { |
|
|
if (!(transfer->qtd.token & 0x80)) { |
|
|
// TODO: check error status |
|
|
// TODO: check error status |
|
|
|
|
|
if (transfer->qtd.token & 0x8000) { |
|
|
|
|
|
// this transfer caused an interrupt |
|
|
|
|
|
if (transfer->pipe->callback_function) { |
|
|
|
|
|
// do the callback |
|
|
|
|
|
(*(transfer->pipe->callback_function))(transfer); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
// do callback function... |
|
|
// do callback function... |
|
|
Serial.println(" completed"); |
|
|
Serial.println(" completed"); |
|
|
free_Transfer(transfer); |
|
|
free_Transfer(transfer); |
|
|
return true; |
|
|
return true; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |