diff --git a/demos/device/device_os_none/mscd_app_ramdisk.c b/demos/device/device_os_none/mscd_app_ramdisk.c index 7a43d6f5..5e97669d 100644 --- a/demos/device/device_os_none/mscd_app_ramdisk.c +++ b/demos/device/device_os_none/mscd_app_ramdisk.c @@ -89,21 +89,17 @@ uint8_t mscd_app_ramdisk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] TUSB_CFG_ATTR_USBRAM = //--------------------------------------------------------------------+ // IMPLEMENTATION //--------------------------------------------------------------------+ -uint16_t read10(uint8_t coreid, uint8_t lun, scsi_read10_t* p_read10, void** pp_buffer) +uint16_t tusbd_msc_read10_cb (uint8_t coreid, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) { - uint8_t block_count = __be2h_16(p_read10->block_count); + (*pp_buffer) = mscd_app_ramdisk[lba]; - (*pp_buffer) = mscd_app_ramdisk[ __be2le(p_read10->lba)]; - - return block_count*DISK_BLOCK_SIZE; + return min16_of(block_count, DISK_BLOCK_NUM); } - -uint16_t write10(uint8_t coreid, uint8_t lun, scsi_read10_t* p_read10, void** pp_buffer) +uint16_t tusbh_msc_write10_cb(uint8_t coreid, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) { - uint8_t block_count = __be2h_16(p_read10->block_count); - (*pp_buffer) = mscd_app_ramdisk[ __be2le(p_read10->lba)]; + (*pp_buffer) = mscd_app_ramdisk[lba]; - return block_count*DISK_BLOCK_SIZE; + return min16_of(block_count, DISK_BLOCK_NUM); } //--------------------------------------------------------------------+ diff --git a/demos/device/device_os_none/mscd_app_romdisk.c b/demos/device/device_os_none/mscd_app_romdisk.c index 0388af2f..16118df2 100644 --- a/demos/device/device_os_none/mscd_app_romdisk.c +++ b/demos/device/device_os_none/mscd_app_romdisk.c @@ -95,22 +95,18 @@ static uint8_t ramdisk_buffer[DISK_BLOCK_SIZE] TUSB_CFG_ATTR_USBRAM; //--------------------------------------------------------------------+ // IMPLEMENTATION //--------------------------------------------------------------------+ -uint16_t read10(uint8_t coreid, uint8_t lun, scsi_read10_t* p_read10, void** pp_buffer) +uint16_t tusbd_msc_read10_cb (uint8_t coreid, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) { - uint8_t block_count = __be2h_16(p_read10->block_count); - - memcpy(ramdisk_buffer, mscd_app_rommdisk[ __be2le(p_read10->lba)], DISK_BLOCK_SIZE); - + memcpy(ramdisk_buffer, mscd_app_rommdisk[lba], DISK_BLOCK_SIZE); (*pp_buffer) = ramdisk_buffer; - return block_count*DISK_BLOCK_SIZE; + return 1; } // Stall write10 as this is readonly disk -uint16_t write10(uint8_t coreid, uint8_t lun, scsi_read10_t* p_read10, void** pp_buffer) +uint16_t tusbh_msc_write10_cb(uint8_t coreid, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) { (*pp_buffer) = NULL; - return 0; } diff --git a/tinyusb/class/msc_device.c b/tinyusb/class/msc_device.c index 1ed33a3c..94545d80 100644 --- a/tinyusb/class/msc_device.c +++ b/tinyusb/class/msc_device.c @@ -139,7 +139,9 @@ tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * void mscd_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes) { // TODO failed --> STALL pipe, on clear STALL --> queue endpoint OUT - mscd_interface_t * p_msc = &mscd_data; + mscd_interface_t * const p_msc = &mscd_data; + msc_cmd_block_wrapper_t * const p_cbw = &p_msc->cbw; + msc_cmd_status_wrapper_t * const p_csw = &p_msc->csw; if ( endpointhandle_is_equal(p_msc->edpt_in, edpt_hdl) ) { @@ -149,37 +151,75 @@ void mscd_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_b ASSERT( endpointhandle_is_equal(p_msc->edpt_out, edpt_hdl) && xferred_bytes == sizeof(msc_cmd_block_wrapper_t) && event == TUSB_EVENT_XFER_COMPLETE && - p_msc->cbw.signature == MSC_CBW_SIGNATURE, VOID_RETURN ); + p_cbw->signature == MSC_CBW_SIGNATURE, VOID_RETURN ); void *p_buffer = NULL; - uint16_t actual_length = p_msc->cbw.xfer_bytes; + uint16_t actual_length = p_cbw->xfer_bytes; - p_msc->csw.signature = MSC_CSW_SIGNATURE; - p_msc->csw.tag = p_msc->cbw.tag; - p_msc->csw.status = tusbd_msc_scsi_received_isr(edpt_hdl.coreid, p_msc->cbw.lun, p_msc->cbw.command, &p_buffer, &actual_length); - p_msc->csw.data_residue = 0; // TODO expected length, response length + p_csw->signature = MSC_CSW_SIGNATURE; + p_csw->tag = p_cbw->tag; + p_csw->data_residue = 0; - ASSERT( p_msc->cbw.xfer_bytes >= actual_length, VOID_RETURN ); + switch(p_cbw->command[0]) + { + case SCSI_CMD_READ_10: + case SCSI_CMD_WRITE_10: + { + scsi_read10_t const * const p_read10 = &p_cbw->command; // read10 & write10 has the same data structure + uint32_t const lba = __be2le(p_read10->lba); + uint16_t const block_count = __be2h_16(p_read10->block_count); + + uint16_t actual_block_count; + + if (SCSI_CMD_READ_10 == p_cbw->command[0]) + { + actual_block_count = tusbd_msc_read10_cb (edpt_hdl.coreid, p_cbw->lun, &p_buffer, lba, block_count); + }else + { + actual_block_count = tusbh_msc_write10_cb(edpt_hdl.coreid, p_cbw->lun, &p_buffer, lba, block_count); + } + + ASSERT( actual_block_count <= block_count, VOID_RETURN); + + if ( actual_block_count < block_count ) + { + uint32_t const block_size = p_cbw->xfer_bytes / block_count; + actual_length = block_size * actual_block_count; + p_csw->data_residue = p_cbw->xfer_bytes - actual_length; + p_csw->status = MSC_CSW_STATUS_FAILED; + }else + { + p_csw->status = MSC_CSW_STATUS_PASSED; + } + } + break; + + default: + p_csw->status = tusbd_msc_scsi_received_isr(edpt_hdl.coreid, p_cbw->lun, p_cbw->command, &p_buffer, &actual_length); + break; + } + + ASSERT( p_cbw->xfer_bytes >= actual_length, VOID_RETURN ); //------------- Data Phase -------------// - if ( p_msc->cbw.xfer_bytes ) + if ( p_cbw->xfer_bytes ) { if ( p_buffer == NULL || actual_length == 0 ) { // application does not provide data to response --> possibly unsupported SCSI command ASSERT( TUSB_ERROR_NONE == dcd_pipe_stall(p_msc->edpt_in), VOID_RETURN ); - p_msc->csw.status = MSC_CSW_STATUS_FAILED; + p_csw->status = MSC_CSW_STATUS_FAILED; }else { - ASSERT( dcd_pipe_queue_xfer( BIT_TEST_(p_msc->cbw.dir, 7) ? p_msc->edpt_in : p_msc->edpt_out, + ASSERT( dcd_pipe_queue_xfer( BIT_TEST_(p_cbw->dir, 7) ? p_msc->edpt_in : p_msc->edpt_out, p_buffer, actual_length) == TUSB_ERROR_NONE, VOID_RETURN); } } //------------- Status Phase -------------// - ASSERT( dcd_pipe_xfer( p_msc->edpt_in , &p_msc->csw, sizeof(msc_cmd_status_wrapper_t), true) == TUSB_ERROR_NONE, VOID_RETURN ); // need to be true for dcd to clean up qtd !! + ASSERT( dcd_pipe_xfer( p_msc->edpt_in , p_csw, sizeof(msc_cmd_status_wrapper_t), true) == TUSB_ERROR_NONE, VOID_RETURN ); // need to be true for dcd to clean up qtd !! //------------- Queue the next CBW -------------// - ASSERT( dcd_pipe_xfer( p_msc->edpt_out, &p_msc->cbw, sizeof(msc_cmd_block_wrapper_t), true) == TUSB_ERROR_NONE, VOID_RETURN ); + ASSERT( dcd_pipe_xfer( p_msc->edpt_out, p_cbw, sizeof(msc_cmd_block_wrapper_t), true) == TUSB_ERROR_NONE, VOID_RETURN ); } diff --git a/tinyusb/class/msc_device.h b/tinyusb/class/msc_device.h index d8dc6874..53ba5a28 100644 --- a/tinyusb/class/msc_device.h +++ b/tinyusb/class/msc_device.h @@ -66,8 +66,8 @@ void tusbd_msc_unmounted_cb(uint8_t coreid); // p_length [in,out] allocated/maximum length, application update with actual length msc_csw_status_t tusbd_msc_scsi_received_isr (uint8_t coreid, uint8_t lun, uint8_t scsi_cmd[16], void ** pp_buffer, uint16_t* p_length); -tusb_error_t tusbd_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT; -tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT; +uint16_t tusbd_msc_read10_cb (uint8_t coreid, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT; +uint16_t tusbh_msc_write10_cb(uint8_t coreid, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT; /** @} */ /** @} */ diff --git a/tinyusb/device/dcd_lpc175x_6x.c b/tinyusb/device/dcd_lpc175x_6x.c index 4e95f03d..a36e919b 100644 --- a/tinyusb/device/dcd_lpc175x_6x.c +++ b/tinyusb/device/dcd_lpc175x_6x.c @@ -175,9 +175,9 @@ void endpoint_control_isr(void) { tusb_control_request_t control_request; - (void) sie_read(SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT+0, 1); // clear setup bit, can be omitted ??? + (void) sie_read(SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT+0, 1); // clear setup bit - pipe_control_read(&control_request, 8); + pipe_control_read(&control_request, 8); // TODO read before clear setup above usbd_setup_received_isr(0, &control_request); }else diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index 77346fc0..2ca0e01c 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -103,7 +103,7 @@ static usbd_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_STAR // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ tusb_error_t usbd_set_configure_received(uint8_t coreid, uint8_t config_number); -tusb_error_t get_descriptor_subtask(uint8_t coreid, tusb_control_request_t * p_request, uint8_t const ** pp_buffer, uint16_t * p_length); +tusb_error_t get_descriptor_subtask(uint8_t coreid, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer, uint16_t * p_length); //--------------------------------------------------------------------+ // APPLICATION INTERFACE @@ -126,10 +126,11 @@ typedef enum { USBD_EVENTID_SETUP_RECEIVED = 1 }usbd_eventid_t; -typedef struct { +typedef struct ATTR_ALIGNED(2) +{ uint8_t coreid; uint8_t event_id; - uint8_t reserved[2]; + uint8_t data[ MAX_OF(sizeof(tusb_control_request_t), sizeof(endpoint_handle_t)) ]; // hold control request or endpoint handle }usbd_task_event_t; OSAL_TASK_DEF(usbd_task, 150, TUSB_CFG_OS_TASK_PRIO); @@ -139,102 +140,89 @@ OSAL_SEM_DEF(usbd_control_xfer_semaphore_def); static osal_queue_handle_t usbd_queue_hdl; static osal_semaphore_handle_t usbd_control_xfer_sem_hdl; -tusb_error_t usbd_body_subtask(void) +tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * const p_request) { OSAL_SUBTASK_BEGIN - static uint8_t coreid; tusb_error_t error = TUSB_ERROR_NONE; - usbd_task_event_t event; - osal_queue_receive(usbd_queue_hdl, &event, OSAL_TIMEOUT_WAIT_FOREVER, &error); - SUBTASK_ASSERT_STATUS(error); - - coreid = event.coreid; - - if ( USBD_EVENTID_SETUP_RECEIVED == event.event_id ) - { // should copy to setup packet to local variable as the new one may overwrite while we processing here - static tusb_control_request_t control_request; - control_request = usbd_devices[coreid].control_request; - - //------------- Standard Control such as those in enumeration -------------// - if( TUSB_REQUEST_RECIPIENT_DEVICE == control_request.bmRequestType_bit.recipient && - TUSB_REQUEST_TYPE_STANDARD == control_request.bmRequestType_bit.type ) + //------------- Standard Control such as those in enumeration -------------// + if( TUSB_REQUEST_RECIPIENT_DEVICE == p_request->bmRequestType_bit.recipient && + TUSB_REQUEST_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + { + if ( TUSB_REQUEST_GET_DESCRIPTOR == p_request->bRequest ) { - if ( TUSB_REQUEST_GET_DESCRIPTOR == control_request.bRequest ) - { - static uint8_t* p_buffer = NULL; - static uint16_t length = 0; + OSAL_VAR uint8_t* p_buffer = NULL; + OSAL_VAR uint16_t length = 0; - error = get_descriptor_subtask(coreid, &control_request, &p_buffer, &length); + error = get_descriptor_subtask(coreid, p_request, &p_buffer, &length); #ifdef USBD_CONTROL_ONE_PACKET_EACH_XFER - while ( length > USBD_COTNROL_MAX_LENGTH_EACH_XFER && error == TUSB_ERROR_NONE ) - { - usbd_devices[coreid].is_waiting_control_xfer = true; + while ( length > USBD_COTNROL_MAX_LENGTH_EACH_XFER && error == TUSB_ERROR_NONE ) + { + usbd_devices[coreid].is_waiting_control_xfer = true; - dcd_pipe_control_xfer(coreid, control_request.bmRequestType_bit.direction, p_buffer, USBD_COTNROL_MAX_LENGTH_EACH_XFER); // zero length - osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); + dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, USBD_COTNROL_MAX_LENGTH_EACH_XFER); // zero length + osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); - length -= USBD_COTNROL_MAX_LENGTH_EACH_XFER; - p_buffer += USBD_COTNROL_MAX_LENGTH_EACH_XFER; + length -= USBD_COTNROL_MAX_LENGTH_EACH_XFER; + p_buffer += USBD_COTNROL_MAX_LENGTH_EACH_XFER; - usbd_devices[coreid].is_waiting_control_xfer = false; - } + usbd_devices[coreid].is_waiting_control_xfer = false; + } #endif - if ( TUSB_ERROR_NONE == error ) - { - dcd_pipe_control_xfer(coreid, control_request.bmRequestType_bit.direction, p_buffer, length); - } - } - else if ( TUSB_REQUEST_SET_ADDRESS == control_request.bRequest ) + if ( TUSB_ERROR_NONE == error ) { - dcd_controller_set_address(coreid, (uint8_t) control_request.wValue); - usbd_devices[coreid].state = TUSB_DEVICE_STATE_ADDRESSED; - } - else if ( TUSB_REQUEST_SET_CONFIGURATION == control_request.bRequest ) - { - usbd_set_configure_received(coreid, (uint8_t) control_request.wValue); - }else - { - error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length); } } - //------------- Class/Interface Specific Request -------------// - else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == control_request.bmRequestType_bit.recipient) + else if ( TUSB_REQUEST_SET_ADDRESS == p_request->bRequest ) { - tusb_std_class_code_t class_code = usbd_devices[coreid].interface2class[ u16_low_u8(control_request.wIndex) ]; - - if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) && - usbd_class_drivers[class_code].control_request ) - { - error = usbd_class_drivers[class_code].control_request(coreid, &control_request); - }else - { - error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; - } + dcd_controller_set_address(coreid, (uint8_t) p_request->wValue); + usbd_devices[coreid].state = TUSB_DEVICE_STATE_ADDRESSED; } - //------------- Endpoint Request -------------// - else if ( TUSB_REQUEST_RECIPIENT_ENDPOINT == control_request.bmRequestType_bit.recipient && - TUSB_REQUEST_TYPE_STANDARD == control_request.bmRequestType_bit.type && - TUSB_REQUEST_CLEAR_FEATURE == control_request.bRequest ) + else if ( TUSB_REQUEST_SET_CONFIGURATION == p_request->bRequest ) { - dcd_pipe_clear_stall(coreid, u16_low_u8(control_request.wIndex) ); - } else + usbd_set_configure_received(coreid, (uint8_t) p_request->wValue); + }else { error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; } + } + //------------- Class/Interface Specific Request -------------// + else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == p_request->bmRequestType_bit.recipient) + { + tusb_std_class_code_t class_code = usbd_devices[coreid].interface2class[ u16_low_u8(p_request->wIndex) ]; - if(TUSB_ERROR_NONE != error) - { // Response with Protocol Stall if request is not supported - dcd_pipe_control_stall(coreid); - // ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN); + if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) && + usbd_class_drivers[class_code].control_request ) + { + error = usbd_class_drivers[class_code].control_request(coreid, p_request); }else - { // status phase - dcd_pipe_control_xfer(coreid, 1-control_request.bmRequestType_bit.direction, NULL, 0); // zero length + { + error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; } } + //------------- Endpoint Request -------------// + else if ( TUSB_REQUEST_RECIPIENT_ENDPOINT == p_request->bmRequestType_bit.recipient && + TUSB_REQUEST_TYPE_STANDARD == p_request->bmRequestType_bit.type && + TUSB_REQUEST_CLEAR_FEATURE == p_request->bRequest ) + { + dcd_pipe_clear_stall(coreid, u16_low_u8(p_request->wIndex) ); + } else + { + error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + } + + if(TUSB_ERROR_NONE != error) + { // Response with Protocol Stall if request is not supported + dcd_pipe_control_stall(coreid); + // ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN); + }else + { // status phase + dcd_pipe_control_xfer(coreid, 1-p_request->bmRequestType_bit.direction, NULL, 0); // zero length + } OSAL_SUBTASK_END } @@ -246,7 +234,20 @@ OSAL_TASK_FUNCTION(usbd_task) (void* p_task_para) { OSAL_TASK_LOOP_BEGIN - usbd_body_subtask(); + OSAL_VAR usbd_task_event_t event; + tusb_error_t error = TUSB_ERROR_NONE; + + osal_queue_receive(usbd_queue_hdl, &event, OSAL_TIMEOUT_WAIT_FOREVER, &error); + SUBTASK_ASSERT_STATUS(error); + + if ( USBD_EVENTID_SETUP_RECEIVED == event.event_id ) + { + OSAL_SUBTASK_INVOKED_AND_WAIT( usbd_control_request_subtask(event.coreid, (tusb_control_request_t*) event.data), error ); + }else + { + + } + //else {} OSAL_TASK_LOOP_END } @@ -320,7 +321,7 @@ tusb_error_t usbd_set_configure_received(uint8_t coreid, uint8_t config_number) return TUSB_ERROR_NONE; } -tusb_error_t get_descriptor_subtask(uint8_t coreid, tusb_control_request_t * p_request, uint8_t const ** pp_buffer, uint16_t * p_length) +tusb_error_t get_descriptor_subtask(uint8_t coreid, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer, uint16_t * p_length) { tusb_std_descriptor_type_t const desc_type = u16_high_u8(p_request->wValue); uint8_t const desc_index = u16_low_u8( p_request->wValue ); @@ -380,13 +381,15 @@ void usbd_dcd_bus_event_isr(uint8_t coreid, usbd_bus_event_type_t bus_event) void usbd_setup_received_isr(uint8_t coreid, tusb_control_request_t * p_request) { - usbd_devices[coreid].control_request = (*p_request); + usbd_task_event_t event = + { + .coreid = coreid, + .event_id = USBD_EVENTID_SETUP_RECEIVED + }; - osal_queue_send(usbd_queue_hdl, - &(usbd_task_event_t){ - .coreid = coreid, - .event_id = USBD_EVENTID_SETUP_RECEIVED} - ); + memcpy(event.data, p_request, sizeof(tusb_control_request_t)); + + osal_queue_send(usbd_queue_hdl, &event); } void usbd_xfer_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes) diff --git a/tinyusb/device/usbd_dcd.h b/tinyusb/device/usbd_dcd.h index c427fb8c..a4a37cd9 100644 --- a/tinyusb/device/usbd_dcd.h +++ b/tinyusb/device/usbd_dcd.h @@ -69,7 +69,6 @@ typedef enum { typedef struct { volatile uint8_t state; uint8_t is_waiting_control_xfer; // set if task is waiting for control xfer to complete to proceed - tusb_control_request_t control_request; uint8_t interface2class[USBD_INTERFACE_NUM_MAX]; // determine interface number belongs to which class }usbd_device_info_t;