diff --git a/include/at91_udp.h b/include/at91_udp.h index e667f91..235da43 100644 --- a/include/at91_udp.h +++ b/include/at91_udp.h @@ -1,6 +1,20 @@ #ifndef AT91_UDP_H_ #define AT91_UDP_H_ +#include + +void ep_transfer_send(uint32_t ep, + char *data, + uint32_t length, + void (*complete_cb)(void)); + +void ep_transfer_receive(uint32_t ep, + char *data, + uint32_t length, + void (*complete_cb)(void)); + +void ep_send_stall(uint32_t ep); + void at91_udp_init(void); #endif /*AT91_UDP_H_*/ diff --git a/src/at91_udp.c b/src/at91_udp.c index 81a7e80..656b4b3 100644 --- a/src/at91_udp.c +++ b/src/at91_udp.c @@ -185,7 +185,16 @@ static const struct my_config cfg_descriptor = { }, }; -static const struct dfu_status dfu_status = { +/* not const! */ +static struct usb_cdc_line_coding cdc_line_coding = { + .dwDTERate = 9600, + .bCharFormat = USB_CDC_1_STOP_BITS, + .bParityType = USB_CDC_NO_PARITY, + .bDataBits = 8, +}; + +/* not const! */ +static struct dfu_status dfu_status = { .bStatus = DFU_STATUS_OK, .bState = DFU_STATE_appIDLE, }; @@ -389,6 +398,7 @@ static void ep_handle_ctrlrequest(struct usb_ctrlrequest *req) // TODO: follow current_interface switch (req->bRequest) { case USB_REQ_DFU_DETACH: /* 0x00 */ + dfu_status.bStatus = DFU_STATE_appDETACH; ep_transfer_send(0, NULL, 0, NULL); break; @@ -397,7 +407,11 @@ static void ep_handle_ctrlrequest(struct usb_ctrlrequest *req) break; case USB_CDC_REQ_SET_LINE_CODING: /* 0x20 */ - /* TODO: read 7 bytes to dummy buffer */ + ep_transfer_receive(0, (char *)&cdc_line_coding, sizeof(cdc_line_coding), NULL); + break; + + case USB_CDC_REQ_GET_LINE_CODING: /* 0x21 */ + ep_transfer_send(0, (char *)&cdc_line_coding, sizeof(cdc_line_coding), NULL); break; case USB_CDC_REQ_SET_CONTROL_LINE_STATE: /* 0x22 */ @@ -511,9 +525,7 @@ static void udp_handle_ep(uint32_t ep) /* test again */ if (transfer->length == transfer->curpos) { ctx->flags &= ~CTX_OUT; - - if (transfer->complete_cb) - transfer->complete_cb(); + transfer_cb = transfer->complete_cb; } } @@ -564,6 +576,12 @@ static void udp_isr(void) udp->UDP_IDR = AT91C_UDP_EPINT1 | AT91C_UDP_EPINT2 | AT91C_UDP_EPINT3 | AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | AT91C_UDP_SOFINT | AT91C_UDP_WAKEUP; + + if (dfu_status.bStatus == DFU_STATE_appDETACH) { + void (* bootloader)(void) = (void *)0x13c000; + bootloader(); + while (1); + } } /* Handle Endpoint Interrupts */