Browse Source

Add transfer callbacks

main
PaulStoffregen 7 years ago
parent
commit
600166af4c
2 changed files with 38 additions and 17 deletions
  1. +9
    -6
      host.h
  2. +29
    -11
      k66_usbhost.ino

+ 9
- 6
host.h View File

typedef struct Pipe_struct Pipe_t; typedef struct Pipe_struct Pipe_t;
typedef struct Transfer_struct Transfer_t; typedef struct Transfer_struct Transfer_t;



typedef union { typedef union {
struct { struct {
union { union {
} qh; } qh;
Device_t *device; Device_t *device;
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
uint8_t direction; // 0=out, 1=in
//uint8_t data01; // next packet DATA0 or DATA1
uint8_t direction; // 0=out, 1=in (changes for control, others fixed)
uint8_t unusedbyte[2]; uint8_t unusedbyte[2];
uint32_t unused[2];
void *callback_object; // TODO: C++ callbacks??
void (*callback_function)(const Transfer_t *);
}; };




volatile uint32_t token; volatile uint32_t token;
volatile uint32_t buffer[5]; volatile uint32_t buffer[5];
} qtd; } qtd;
Pipe_t *pipe;
void *callback;
void *callback_arg;
// linked list of queued, not-yet-completed transfers
Transfer_t *next_followup; Transfer_t *next_followup;
// data to be used by callback function
Pipe_t *pipe;
void *buffer;
uint32_t length;
uint32_t unused[4]; uint32_t unused[4];
}; };



+ 29
- 11
k66_usbhost.ino View File



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

Loading…
Cancel
Save