diff --git a/demos/host/src/tusb_config.h b/demos/host/src/tusb_config.h index d6a0d6162..8596660de 100644 --- a/demos/host/src/tusb_config.h +++ b/demos/host/src/tusb_config.h @@ -60,12 +60,12 @@ // CONTROLLER CONFIGURATION //--------------------------------------------------------------------+ #define TUSB_CFG_CONTROLLER0_MODE (TUSB_MODE_HOST) -#define TUSB_CFG_CONTROLLER1_MODE (TUSB_MODE_HOST) +#define TUSB_CFG_CONTROLLER1_MODE (TUSB_MODE_NONE) //--------------------------------------------------------------------+ // HOST CONFIGURATION //--------------------------------------------------------------------+ -#define TUSB_CFG_HOST_DEVICE_MAX 2 +#define TUSB_CFG_HOST_DEVICE_MAX 1 #define TUSB_CFG_CONFIGURATION_MAX 1 //------------- USBD -------------// diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c index abc844b05..44c824d6b 100644 --- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c +++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c @@ -112,6 +112,21 @@ rndis_msg_initialize_t msg_init = .max_xfer_size = 0x4000 // TODO mimic windows }; +rndis_msg_initialize_cmplt_t msg_init_cmplt = +{ + .type = RNDIS_MSG_INITIALIZE_CMPLT, + .length = sizeof(rndis_msg_initialize_cmplt_t), + .request_id = 1, + .status = RNDIS_STATUS_SUCCESS, + .major_version = 1, + .minor_version = 0, + .device_flags = 0x10, + .medium = 0, // TODO cannot find info on this + .max_packet_per_xfer = 1, + .max_xfer_size = 0x4000, // TODO change later + .packet_alignment_factor = 5 // aligment of each RNDIS message (payload) = 2^factor +}; + void test_rndis_send_initalize_failed(void) { usbh_control_xfer_subtask_ExpectWithArrayAndReturn( @@ -164,12 +179,41 @@ void test_rndis_initialization_notification_timeout(void) TEST_ASSERT_FALSE(p_cdc->is_rndis); } +tusb_error_t stub_control_xfer(uint8_t addr, uint8_t bmRequestType, uint8_t bRequest, + uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data, int num_call ) +{ + TEST_ASSERT_EQUAL(p_comm_interface->bInterfaceNumber, wIndex); + TEST_ASSERT_EQUAL(0, wValue); + TEST_ASSERT_EQUAL(dev_addr, addr); + + switch(num_call) + { + case 0: + TEST_ASSERT_EQUAL(0x21, bmRequestType); + TEST_ASSERT_EQUAL(SEND_ENCAPSULATED_COMMAND, bRequest); + TEST_ASSERT_EQUAL(0x18, wLength); + TEST_ASSERT_EQUAL_HEX8_ARRAY(&msg_init, data, wLength); + break; + + case 1: + TEST_ASSERT_EQUAL(0xA1, bmRequestType); + TEST_ASSERT_EQUAL(GET_ENCAPSULATED_RESPONSE, bRequest); + TEST_ASSERT( wLength >= 0x0400 ); // Microsoft Specs + memcpy(data, &msg_init_cmplt, 0x30); + break; + + default: + return TUSB_ERROR_OSAL_TIMEOUT; + } + + return TUSB_ERROR_NONE; +} + void test_rndis_initialization_sequence_ok(void) { - usbh_control_xfer_subtask_ExpectWithArrayAndReturn( - dev_addr, 0x21, SEND_ENCAPSULATED_COMMAND, 0, p_comm_interface->bInterfaceNumber, - sizeof(rndis_msg_initialize_t), (uint8_t*)&msg_init, sizeof(rndis_msg_initialize_t), TUSB_ERROR_NONE); - + // send initialize msg + usbh_control_xfer_subtask_StubWithCallback(stub_control_xfer); + // notification waiting hcd_pipe_xfer_StubWithCallback(stub_pipe_notification_xfer); osal_semaphore_wait_StubWithCallback(stub_sem_wait_success); osal_semaphore_post_ExpectAndReturn(p_rndis->sem_notification_hdl, TUSB_ERROR_NONE); diff --git a/tinyusb/class/cdc_host.c b/tinyusb/class/cdc_host.c index ebe108658..5dd37810b 100644 --- a/tinyusb/class/cdc_host.c +++ b/tinyusb/class/cdc_host.c @@ -73,7 +73,7 @@ STATIC_ INLINE_ bool tusbh_cdc_is_mounted(uint8_t dev_addr) static inline cdc_pipeid_t get_app_pipeid(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE; static inline cdc_pipeid_t get_app_pipeid(pipe_handle_t pipe_hdl) { - cdch_data_t const * p_cdc = cdch_data + (pipe_hdl.dev_addr-1); + cdch_data_t const * p_cdc = &cdch_data[pipe_hdl.dev_addr-1]; return pipehandle_is_equal( pipe_hdl, p_cdc->pipe_notification ) ? CDC_PIPE_NOTIFICATION : pipehandle_is_equal( pipe_hdl, p_cdc->pipe_in ) ? CDC_PIPE_DATA_IN : @@ -148,7 +148,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con } uint8_t const * p_desc = descriptor_next ( (uint8_t const *) p_interface_desc ); - cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; + cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; // non-static variable cannot be used after OS service call p_cdc->interface_number = p_interface_desc->bInterfaceNumber; p_cdc->interface_protocol = p_interface_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com @@ -203,25 +203,26 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con #if TUSB_CFG_HOST_CDC_RNDIS // TODO move to rndis_host.c //------------- RNDIS -------------// - if ( 0xff == p_cdc->interface_protocol && pipehandle_is_valid(p_cdc->pipe_notification) ) + if ( 0xff == cdch_data[dev_addr-1].interface_protocol && pipehandle_is_valid(cdch_data[dev_addr-1].pipe_notification) ) { - p_cdc->is_rndis = true; // set as true at first + cdch_data[dev_addr-1].is_rndis = true; // set as true at first - OSAL_SUBTASK_INVOKED_AND_WAIT( rndish_open_subtask(dev_addr, p_cdc), error ); + OSAL_SUBTASK_INVOKED_AND_WAIT( rndish_open_subtask(dev_addr, &cdch_data[dev_addr-1]), error ); if (TUSB_ERROR_NONE != error) { - p_cdc->is_rndis = false; + cdch_data[dev_addr-1].is_rndis = false; } } - if ( !p_cdc->is_rndis ) // device is not an rndis + if ( !cdch_data[dev_addr-1].is_rndis ) // device is not an rndis #endif - - // FIXME mounted class flag is not set yet - if (tusbh_cdc_mounted_cb) { - tusbh_cdc_mounted_cb(dev_addr); + // FIXME mounted class flag is not set yet + if (tusbh_cdc_mounted_cb) + { + tusbh_cdc_mounted_cb(dev_addr); + } } OSAL_SUBTASK_END @@ -229,7 +230,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con void cdch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) { - cdch_data_t *p_cdc = cdch_data + (pipe_hdl.dev_addr - 1); + cdch_data_t *p_cdc = &cdch_data[pipe_hdl.dev_addr - 1]; #if TUSB_CFG_HOST_CDC_RNDIS if ( p_cdc->is_rndis ) diff --git a/tinyusb/class/cdc_rndis_host.c b/tinyusb/class/cdc_rndis_host.c index b01bebc7a..3f098c902 100644 --- a/tinyusb/class/cdc_rndis_host.c +++ b/tinyusb/class/cdc_rndis_host.c @@ -52,9 +52,14 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +#define RNDIS_MSG_PAYLOAD_MAX (1024*4) + static uint8_t msg_notification[TUSB_CFG_HOST_DEVICE_MAX][8] TUSB_CFG_ATTR_USBRAM; STATIC_ rndish_data_t rndish_data[TUSB_CFG_HOST_DEVICE_MAX]; +// TODO Microsoft requires message length for any get command must be at least 0x400 bytes +static uint32_t msg_payload[RNDIS_MSG_PAYLOAD_MAX/4] TUSB_CFG_ATTR_USBRAM; + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -117,35 +122,41 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) { tusb_error_t error; - static rndis_msg_initialize_t msg_init = - { - .type = RNDIS_MSG_INITIALIZE, - .length = sizeof(rndis_msg_initialize_t), - .request_id = 1, // TODO should use some magic number - .major_version = 1, - .minor_version = 0, - .max_xfer_size = 0x4000 // TODO mimic windows - }; + *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) + { + .type = RNDIS_MSG_INITIALIZE, + .length = sizeof(rndis_msg_initialize_t), + .request_id = 1, // TODO should use some magic number + .major_version = 1, + .minor_version = 0, + .max_xfer_size = 0x4000 // TODO mimic windows + }; OSAL_SUBTASK_BEGIN - //------------- Send & Receive Initialize -------------// + //------------- Send RNDIS Message Initialize -------------// OSAL_SUBTASK_INVOKED_AND_WAIT( usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE), SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, - sizeof(rndis_msg_initialize_t), (uint8_t*)&msg_init ), + sizeof(rndis_msg_initialize_t), (uint8_t*) msg_payload ), error ); - - if ( TUSB_ERROR_NONE != error ) - SUBTASK_EXIT(error); + if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); //------------- waiting for Response Available notification -------------// (void) hcd_pipe_xfer(p_cdc->pipe_notification, msg_notification[dev_addr], 8, true); osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); + if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); - if ( TUSB_ERROR_NONE != error ) - SUBTASK_EXIT(error); + //------------- Get RNDIS Message Initialize Complete -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE), + GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, + RNDIS_MSG_PAYLOAD_MAX, (uint8_t*) msg_payload ), + error + ); + + if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); if ( tusbh_cdc_rndis_mounted_cb ) { diff --git a/tinyusb/osal/osal_none.h b/tinyusb/osal/osal_none.h index 79acb8a8e..4eddffd1e 100644 --- a/tinyusb/osal/osal_none.h +++ b/tinyusb/osal/osal_none.h @@ -123,21 +123,23 @@ static inline volatile uint32_t osal_tick_get(void) //--------------------------------------------------------------------+ //------------- Sub Task -------------// #define OSAL_SUBTASK_INVOKED_AND_WAIT(subtask, status) \ - do {\ - state = __LINE__; case __LINE__:\ - {\ - status = subtask; /* invoke sub task */\ - if (TUSB_ERROR_OSAL_WAITING == status) /* sub task not finished -> continue waiting */\ - return TUSB_ERROR_OSAL_WAITING;\ - }\ - }while(0) + do {\ + state = __LINE__; case __LINE__:\ + {\ + status = subtask; /* invoke sub task */\ + if (TUSB_ERROR_OSAL_WAITING == status) /* sub task not finished -> continue waiting */\ + return TUSB_ERROR_OSAL_WAITING;\ + }\ + }while(0) #define OSAL_SUBTASK_BEGIN OSAL_TASK_LOOP_BEGIN #define OSAL_SUBTASK_END OSAL_TASK_LOOP_END //------------- Sub Task Assert -------------// #define SUBTASK_EXIT(error) \ - TASK_RESTART; return error + do {\ + TASK_RESTART; return error;\ + }while(0) #define _SUBTASK_ASSERT_ERROR_HANDLER(error, func_call) \ func_call; TASK_RESTART; return error