From ffdef05619519acb8f0c53a275898586ab73990f Mon Sep 17 00:00:00 2001 From: Cristian Maglie <c.maglie@arduino.cc> Date: Sat, 16 Aug 2014 08:55:56 +0200 Subject: [PATCH] Correct implementation of USBD_RecvControl --- cores/arduino/USB/HID.cpp | 2 +- cores/arduino/USB/USBCore.cpp | 17 ++++++++++++---- cores/arduino/USB/USB_device.h | 6 +++++- cores/arduino/USB/samd21_device.c | 34 ++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/cores/arduino/USB/HID.cpp b/cores/arduino/USB/HID.cpp index f5d561e0..6f7f5f5c 100644 --- a/cores/arduino/USB/HID.cpp +++ b/cores/arduino/USB/HID.cpp @@ -198,7 +198,7 @@ bool WEAK HID_Setup(Setup& setup) if (HID_GET_IDLE == r) { UDD_Send(0, &_hid_idle, 1); - UDD_ClearIN(); + UDD_ReleaseIN(); return true; } } diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp index 38f7404f..abd40bbd 100644 --- a/cores/arduino/USB/USBCore.cpp +++ b/cores/arduino/USB/USBCore.cpp @@ -205,9 +205,18 @@ static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) uint32_t USBD_RecvControl(void* d, uint32_t len) { - udd_ack_out_received(0); - - return len; + uint8_t *buffer; + uint8_t *data = (uint8_t *)d; + uint32_t read = UDD_Recv_data(EP0, len); + if (read > len) + read = len; + UDD_Recv(EP0, &buffer); + UDD_WaitOUT(); + for (int i=0; i<read; i++) { + data[i] = buffer[i]; + } + UDD_ReleaseOUT(); + return read; } // Handle CLASS_INTERFACE requests @@ -631,7 +640,7 @@ void USB_Handler(void) if (ok) { TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");) - UDD_ClearIN(); + UDD_ReleaseIN(); } else { diff --git a/cores/arduino/USB/USB_device.h b/cores/arduino/USB/USB_device.h index dddda66e..f7338fb7 100644 --- a/cores/arduino/USB/USB_device.h +++ b/cores/arduino/USB/USB_device.h @@ -39,13 +39,17 @@ extern "C" { #define USB_ENDPOINT_TYPE_INTERRUPT 0x03 -extern void UDD_ClearIN(void); +extern void UDD_ReleaseIN(void); +extern void UDD_ReleaseOUT(void); +extern void UDD_WaitIN(void); +extern void UDD_WaitOUT(void); extern uint32_t UDD_FifoByteCount(uint32_t ep); extern void UDD_ReleaseRX(uint32_t ep); extern void UDD_ReleaseTX(uint32_t ep); extern uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len); extern uint8_t UDD_Recv8(uint32_t ep); extern void UDD_Recv(uint32_t ep, uint8_t** data); +extern uint8_t UDD_Recv_data(uint32_t ep, uint32_t len); extern void UDD_Init(void); extern void UDD_InitEP( uint32_t ul_ep, uint32_t ul_ep_cfg ); extern void send_zlp (void); diff --git a/cores/arduino/USB/samd21_device.c b/cores/arduino/USB/samd21_device.c index 6e750b06..e99e172d 100644 --- a/cores/arduino/USB/samd21_device.c +++ b/cores/arduino/USB/samd21_device.c @@ -238,11 +238,25 @@ void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg ) // Send packet. -void UDD_ClearIN(void) +void UDD_ReleaseIN(void) { USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY; } +void UDD_ReleaseOUT(void) +{ + USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY; +} + +void UDD_WaitIN() +{ + while (!( USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY )) {} +} + +void UDD_WaitOUT() +{ + while (!( USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK0RDY )) {} +} uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len) @@ -275,6 +289,24 @@ uint8_t UDD_Recv8(uint32_t ep) return udd_ep_out_cache_buffer[ep][0]; } +uint8_t UDD_Recv_data(uint32_t ep, uint32_t len) +{ + TRACE_DEVICE(printf("=> UDD_Recvdata : ep=%d\r\n", (char)ep);) + + usb_endpoint_table[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ep]; + usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = len; + usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY; + TRACE_DEVICE(printf("=> UDD_Recv8 : data=%lu\r\n", (unsigned long)data);) + + /* Wait for transfer to complete */ + while (!( USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0 )); + /* Clear Transfer complete 0 flag */ + //USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0 = 1; + + return udd_ep_out_cache_buffer[ep][0]; +} + void UDD_Recv(uint32_t ep, uint8_t** ppData) { *ppData = udd_ep_out_cache_buffer[ep]; -- GitLab