From ce865721a56bade9a99661e425b9dd85d7510296 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jul 2013 01:52:56 +0700 Subject: [PATCH] add test & code to send rndis msg query for permanent address (MAC address) --- .../test/host/cdc/test_cdc_rndis_host.c | 45 ++++++++++- tinyusb/class/cdc_rndis.h | 76 ++++++++++--------- tinyusb/class/cdc_rndis_host.c | 39 +++++++--- tinyusb/class/cdc_rndis_host.h | 1 + tinyusb/host/usbh.c | 5 +- tinyusb/host/usbh_hcd.h | 1 + 6 files changed, 117 insertions(+), 50 deletions(-) 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 ca3baf943..9ccd24404 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 @@ -127,6 +127,28 @@ rndis_msg_initialize_cmplt_t msg_init_cmplt = .packet_alignment_factor = 5 // aligment of each RNDIS message (payload) = 2^factor }; +rndis_msg_query_t msg_query_permanent_addr = +{ + .type = RNDIS_MSG_QUERY, + .length = sizeof(rndis_msg_query_t)+6, + .request_id = 1, + .oid = OID_802_3_PERMANENT_ADDRESS, + .buffer_length = 6, + .buffer_offset = 20, + .oid_buffer = {0, 0, 0, 0, 0, 0} +}; + +rndis_msg_query_cmplt_t msg_query_permanent_addr_cmplt = +{ + .type = RNDIS_MSG_QUERY_CMPLT, + .length = sizeof(rndis_msg_query_cmplt_t)+6, + .request_id = 1, + .status = RNDIS_STATUS_SUCCESS, + .buffer_length = 6, + .buffer_offset = 16, + .oid_buffer = "CAFEBB" +}; + void test_rndis_send_initalize_failed(void) { usbh_control_xfer_subtask_ExpectWithArrayAndReturn( @@ -188,20 +210,34 @@ tusb_error_t stub_control_xfer(uint8_t addr, uint8_t bmRequestType, uint8_t bReq switch(num_call) { - case 0: + case 0: // initialize 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: + case 1: // initialize complete 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; + case 2: // query for OID_802_3_PERMANENT_ADDRESS + TEST_ASSERT_EQUAL(0x21, bmRequestType); + TEST_ASSERT_EQUAL(SEND_ENCAPSULATED_COMMAND, bRequest); + TEST_ASSERT_EQUAL(34, wLength); // sizeof(rndis_msg_query_t) + 6 MAC address + TEST_ASSERT_EQUAL_HEX8_ARRAY(&msg_query_permanent_addr, data, wLength); + break; + + case 3: // query complete for OID_802_3_PERMANENT_ADDRESS + TEST_ASSERT_EQUAL(0xA1, bmRequestType); + TEST_ASSERT_EQUAL(GET_ENCAPSULATED_RESPONSE, bRequest); + TEST_ASSERT( wLength >= 0x0400 ); // Microsoft Specs + memcpy(data, &msg_query_permanent_addr_cmplt, 30); + break; + default: return TUSB_ERROR_OSAL_TIMEOUT; } @@ -211,11 +247,11 @@ tusb_error_t stub_control_xfer(uint8_t addr, uint8_t bmRequestType, uint8_t bReq void test_rndis_initialization_sequence_ok(void) { - // 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); osal_semaphore_post_ExpectAndReturn(p_rndis->sem_notification_hdl, TUSB_ERROR_NONE); tusbh_cdc_rndis_mounted_cb_Expect(dev_addr); @@ -225,4 +261,5 @@ void test_rndis_initialization_sequence_ok(void) TEST_ASSERT(p_cdc->is_rndis); TEST_ASSERT_EQUAL(msg_init_cmplt.max_xfer_size, p_rndis->max_xfer_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY("CAFEBB", p_rndis->mac_address, 6); } diff --git a/tinyusb/class/cdc_rndis.h b/tinyusb/class/cdc_rndis.h index f858dd53f..ad667ab2e 100644 --- a/tinyusb/class/cdc_rndis.h +++ b/tinyusb/class/cdc_rndis.h @@ -86,6 +86,8 @@ typedef enum { //--------------------------------------------------------------------+ // MESSAGE STRUCTURE //--------------------------------------------------------------------+ + +//------------- Initialize -------------// typedef struct { uint32_t type; uint32_t length; @@ -95,23 +97,61 @@ typedef struct { uint32_t max_xfer_size; }rndis_msg_initialize_t; +typedef struct { + uint32_t type; + uint32_t length; + uint32_t request_id; + uint32_t status; + uint32_t major_version; + uint32_t minor_version; + uint32_t device_flags; + uint32_t medium; // medium type, is 0x00 for RNDIS_MEDIUM_802_3 + uint32_t max_packet_per_xfer; + uint32_t max_xfer_size; + uint32_t packet_alignment_factor; + uint32_t reserved[2]; +} rndis_msg_initialize_cmplt_t; + +//------------- Query -------------// typedef struct { uint32_t type; uint32_t length; uint32_t request_id; uint32_t oid; uint32_t buffer_length; - uint32_t buffer_offset; + uint32_t buffer_offset; // from beginning of request_id field uint32_t reserved; - uint32_t oid_buffer[0]; + uint8_t oid_buffer[]; // flexible array member } rndis_msg_query_t, rndis_msg_set_t; +STATIC_ASSERT(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); + +typedef struct { + uint32_t type; + uint32_t length; + uint32_t request_id; + uint32_t status; + uint32_t buffer_length; + uint32_t buffer_offset; + uint8_t oid_buffer[]; // flexible array member +} rndis_msg_query_cmplt_t; + +STATIC_ASSERT(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); + +//------------- Reset -------------// typedef struct { uint32_t type; uint32_t length; uint32_t reserved; } rndis_msg_reset_t; +typedef struct { + uint32_t type; + uint32_t length; + uint32_t status; + uint32_t addressing_reset; +} rndis_msg_reset_cmplt_t; + //typedef struct { // uint32_t type; // uint32_t length; @@ -129,31 +169,6 @@ typedef struct { uint32_t request_id; } rndis_msg_keep_alive_t, rndis_msg_halt_t; -typedef struct { - uint32_t type; - uint32_t length; - uint32_t request_id; - uint32_t status; - uint32_t major_version; - uint32_t minor_version; - uint32_t device_flags; - uint32_t medium; // medium type, is 0x00 for RNDIS_MEDIUM_802_3 - uint32_t max_packet_per_xfer; - uint32_t max_xfer_size; - uint32_t packet_alignment_factor; - uint32_t reserved[2]; -} rndis_msg_initialize_cmplt_t; - -typedef struct { - uint32_t type; - uint32_t length; - uint32_t request_id; - uint32_t status; - uint32_t buffer_length; - uint32_t buffer_offset; - uint32_t oid_buffer[0]; -} rndis_msg_query_cmplt_t; - typedef struct { uint32_t type; uint32_t length; @@ -161,13 +176,6 @@ typedef struct { uint32_t status; } rndis_msg_set_cmplt_t, rndis_msg_keep_alive_cmplt_t; -typedef struct { - uint32_t type; - uint32_t length; - uint32_t status; - uint32_t addressing_reset; -} rndis_msg_reset_cmplt_t; - typedef struct { uint32_t type; uint32_t length; diff --git a/tinyusb/class/cdc_rndis_host.c b/tinyusb/class/cdc_rndis_host.c index bafdfe499..35ee88500 100644 --- a/tinyusb/class/cdc_rndis_host.c +++ b/tinyusb/class/cdc_rndis_host.c @@ -55,7 +55,7 @@ #define RNDIS_MSG_PAYLOAD_MAX (1024*4) static uint8_t msg_notification[TUSB_CFG_HOST_DEVICE_MAX][8] TUSB_CFG_ATTR_USBRAM; -static uint32_t msg_payload[RNDIS_MSG_PAYLOAD_MAX/4] TUSB_CFG_ATTR_USBRAM; +static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX] TUSB_CFG_ATTR_USBRAM ATTR_ALIGNED(4); STATIC_ rndish_data_t rndish_data[TUSB_CFG_HOST_DEVICE_MAX]; @@ -67,7 +67,7 @@ STATIC_ rndish_data_t rndish_data[TUSB_CFG_HOST_DEVICE_MAX]; static tusb_error_t rndis_body_subtask(void); static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, uint8_t const * p_mess, uint32_t mess_length, - uint8_t *p_response , uint32_t* response_length ); + uint8_t *p_response ); //--------------------------------------------------------------------+ // IMPLEMENTATION @@ -139,24 +139,44 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) .max_xfer_size = 0x4000 // TODO mimic windows }; - uint32_t response_length; OSAL_SUBTASK_INVOKED_AND_WAIT( send_message_get_response_subtask( dev_addr, p_cdc, - (uint8_t*) msg_payload, sizeof(rndis_msg_initialize_t), - (uint8_t*) msg_payload, &response_length), + msg_payload, sizeof(rndis_msg_initialize_t), + msg_payload), error ); if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); rndis_msg_initialize_cmplt_t * const p_init_cmpt = (rndis_msg_initialize_cmplt_t *) msg_payload; + // TODO currently not support multiple data packets per xfer SUBTASK_ASSERT(p_init_cmpt->type == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; - //------------- Message Initialize -------------// + //------------- Message Query 802.3 Permanent Address -------------// + *((rndis_msg_query_t*) msg_payload) = (rndis_msg_query_t) + { + .type = RNDIS_MSG_QUERY, + .length = sizeof(rndis_msg_query_t) + 6, // size message and MAC address + .request_id = 1, // TODO should use some magic number + .oid = OID_802_3_PERMANENT_ADDRESS, + .buffer_length = 6, // sizeof MAC address + .buffer_offset = 20, // offset(rndis_msg_query_t, oid_buffer) - offset(rndis_msg_query_t, request_id) + }; + memclr_( ((rndis_msg_query_t*) msg_payload)->oid_buffer, 6); + OSAL_SUBTASK_INVOKED_AND_WAIT( + send_message_get_response_subtask( dev_addr, p_cdc, + msg_payload, sizeof(rndis_msg_query_t) + 6, + msg_payload), + error + ); + if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); + + rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; + memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); if ( tusbh_cdc_rndis_mounted_cb ) { @@ -200,7 +220,7 @@ void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, tusb_event_t ev static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, uint8_t const * p_mess, uint32_t mess_length, - uint8_t *p_response , uint32_t* response_length ) + uint8_t *p_response) { tusb_error_t error; @@ -209,8 +229,8 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da //------------- Send RNDIS Control Message -------------// 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, - mess_length, p_mess), + SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, + mess_length, p_mess), error ); if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); @@ -230,7 +250,6 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da ); if ( TUSB_ERROR_NONE != error ) SUBTASK_EXIT(error); - OSAL_SUBTASK_END } diff --git a/tinyusb/class/cdc_rndis_host.h b/tinyusb/class/cdc_rndis_host.h index 5ca691587..ab0186949 100644 --- a/tinyusb/class/cdc_rndis_host.h +++ b/tinyusb/class/cdc_rndis_host.h @@ -63,6 +63,7 @@ typedef struct { OSAL_SEM_DEF(semaphore_notification); osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe uint32_t max_xfer_size; // got from device's msg initialize complete + uint8_t mac_address[6]; }rndish_data_t; void rndish_init(void); diff --git a/tinyusb/host/usbh.c b/tinyusb/host/usbh.c index 2f8278f1f..a4cbabb9d 100644 --- a/tinyusb/host/usbh.c +++ b/tinyusb/host/usbh.c @@ -185,7 +185,7 @@ tusb_error_t usbh_init(void) //------------- USBH control transfer -------------// // function called within a task, requesting os blocking services, subtask input parameter must be static/global variables or constant tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType, uint8_t bRequest, - uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data ) + uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data) { tusb_error_t error; @@ -253,7 +253,8 @@ void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t even uint8_t class_index = std_class_code_to_index(class_code); if (TUSB_XFER_CONTROL == pipe_hdl.xfer_type) { - usbh_devices[ pipe_hdl.dev_addr ].control.pipe_status = event; + usbh_devices[ pipe_hdl.dev_addr ].control.pipe_status = event; +// usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary osal_semaphore_post( usbh_devices[ pipe_hdl.dev_addr ].control.sem_hdl ); }else if (usbh_class_drivers[class_index].isr) { diff --git a/tinyusb/host/usbh_hcd.h b/tinyusb/host/usbh_hcd.h index 2e251396c..7d5b03a72 100644 --- a/tinyusb/host/usbh_hcd.h +++ b/tinyusb/host/usbh_hcd.h @@ -98,6 +98,7 @@ typedef struct { // TODO internal structure, re-order members //------------- control pipe -------------// struct { volatile uint8_t pipe_status; +// uint8_t xferred_bytes; TODO not yet necessary tusb_control_request_t request; OSAL_SEM_DEF(semaphore); // TODO move to semaphore pool ?