add keyboard led mask

make usbd control request to subtask
add get/set report via control pipe to hidd
enforce soft DMA to control pipe for lpc11u (lpc17xx not yet)
temp add led_blinking_set_interval to change led blinking interval
refractor dcd_pipe_control_xfer to have interrupt on complete option
add get/set report support of moused_app and keyboardd_app, keyboard LED will make LED blink faster
This commit is contained in:
hathach 2013-12-09 11:15:13 +07:00
parent 1ad78f104e
commit e320659f8a
17 changed files with 263 additions and 159 deletions

View File

@ -80,6 +80,41 @@ void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_
} }
} }
uint16_t tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length)
{
// get other than input report is not supported by this keyboard demo
if ( report_type != HID_REQUEST_REPORT_INPUT ) return 0;
(*pp_report) = &keyboard_report;
return requested_length;
}
void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length)
{
// set other than output report is not supported by this keyboard demo
if ( report_type != HID_REQUEST_REPORT_OUTPUT ) return;
uint8_t kbd_led = p_report_data[0];
uint32_t interval_divider = 1; // each LED will reduce blinking interval by a half
if (kbd_led & KEYBOARD_LED_NUMLOCK)
{
interval_divider *= 2;
}
if (kbd_led & KEYBOARD_LED_CAPSLOCK)
{
interval_divider *= 2;
}
if (kbd_led & KEYBOARD_LED_SCROLLLOCK)
{
interval_divider *= 2;
}
led_blinking_set_interval( 1000 / interval_divider);
}
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// APPLICATION CODE // APPLICATION CODE
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+

View File

@ -108,7 +108,7 @@ int main(void)
#error need to start RTOS schduler #error need to start RTOS schduler
#endif #endif
while(1) { } // should not be reached here while(1) { } // should not reach here
return 0; return 0;
} }
@ -116,13 +116,19 @@ int main(void)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// BLINKING TASK // BLINKING TASK
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda
void led_blinking_set_interval(uint32_t ms)
{
led_blink_interval_ms = ms;
}
OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para) OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para)
{ {
OSAL_TASK_LOOP_BEGIN OSAL_TASK_LOOP_BEGIN
static uint32_t led_on_mask = 0; static uint32_t led_on_mask = 0;
osal_task_delay(1000); osal_task_delay(led_blink_interval_ms);
board_leds(led_on_mask, 1 - led_on_mask); board_leds(led_on_mask, 1 - led_on_mask);
led_on_mask = 1 - led_on_mask; // toggle led_on_mask = 1 - led_on_mask; // toggle

View File

@ -80,6 +80,19 @@ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_byt
} }
} }
uint16_t tusbd_hid_mouse_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length)
{
if ( report_type != HID_REQUEST_REPORT_INPUT ) return 0; // not support other report type for this mouse demo
(*pp_report) = &mouse_report;
return requested_length;
}
void tusbd_hid_mouse_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t report_data[], uint16_t length)
{
// mouse demo does not support set report --> return 0 will result in rejecting (STALL) this request
return 0;
}
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// APPLICATION CODE // APPLICATION CODE
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+

View File

@ -87,7 +87,7 @@
#define TUSB_CFG_DEVICE_HID_MOUSE 1 #define TUSB_CFG_DEVICE_HID_MOUSE 1
#define TUSB_CFG_DEVICE_HID_GENERIC 0 #define TUSB_CFG_DEVICE_HID_GENERIC 0
#define TUSB_CFG_DEVICE_MSC 0 #define TUSB_CFG_DEVICE_MSC 0
#define TUSB_CFG_DEVICE_CDC 0 #define TUSB_CFG_DEVICE_CDC 1

View File

@ -182,7 +182,7 @@ void cdcd_close(uint8_t coreid)
memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t)); memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t));
} }
tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
{ {
//------------- Class Specific Request -------------// //------------- Class Specific Request -------------//
if (p_request->bmRequestType_bit.type != TUSB_REQUEST_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; if (p_request->bmRequestType_bit.type != TUSB_REQUEST_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@ -191,17 +191,17 @@ tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const *
{ {
case CDC_REQUEST_GET_LINE_CODING: case CDC_REQUEST_GET_LINE_CODING:
dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction,
&cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) ); &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
break; break;
case CDC_REQUEST_SET_LINE_CODING: case CDC_REQUEST_SET_LINE_CODING:
dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction,
&cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) ); &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
// TODO notify application on xfer complete // TODO notify application on xfer complete
break; break;
case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present
dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0); // dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0);
break; break;

View File

@ -76,7 +76,7 @@ void tusbd_cdc_xfer_cb(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id,
void cdcd_init(void); void cdcd_init(void);
tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length); tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length);
tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * p_request); tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request);
tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
void cdcd_close(uint8_t coreid); void cdcd_close(uint8_t coreid);

View File

@ -199,6 +199,14 @@ typedef enum {
KEYBOARD_MODIFIER_RIGHTGUI = BIT_(7) ///< Right Window KEYBOARD_MODIFIER_RIGHTGUI = BIT_(7) ///< Right Window
}hid_keyboard_modifier_bm_t; }hid_keyboard_modifier_bm_t;
typedef enum {
KEYBOARD_LED_NUMLOCK = BIT_(0), ///< Num Lock LED
KEYBOARD_LED_CAPSLOCK = BIT_(1), ///< Caps Lock LED
KEYBOARD_LED_SCROLLLOCK = BIT_(2), ///< Scroll Lock LED
KEYBOARD_LED_COMPOSE = BIT_(3), ///< Composition Mode
KEYBOARD_LED_KANA = BIT_(4) ///< Kana mode
}hid_keyboard_led_bm_t;
/// @} /// @}
#define HID_KEYCODE_TABLE(ENTRY) \ #define HID_KEYCODE_TABLE(ENTRY) \

View File

@ -51,7 +51,6 @@
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF // MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
ATTR_USB_MIN_ALIGNMENT uint8_t set_report[ MAX_OF(sizeof(hid_keyboard_report_t), sizeof(hid_mouse_report_t)) ] TUSB_CFG_ATTR_USBRAM;
enum { enum {
HIDD_NUMBER_OF_SUBCLASS = 3 HIDD_NUMBER_OF_SUBCLASS = 3
@ -70,6 +69,8 @@ typedef struct {
void (* const mounted_cb) (uint8_t coreid); void (* const mounted_cb) (uint8_t coreid);
void (* const unmounted_cb) (uint8_t coreid); void (* const unmounted_cb) (uint8_t coreid);
void (* const xfer_cb) (uint8_t, tusb_event_t, uint32_t); void (* const xfer_cb) (uint8_t, tusb_event_t, uint32_t);
uint16_t (* const get_report_cb) (uint8_t, hid_request_report_type_t, void**, uint16_t );
void (* const set_report_cb) (uint8_t, hid_request_report_type_t, uint8_t[], uint16_t);
}hidd_class_driver_t; }hidd_class_driver_t;
extern ATTR_WEAK hidd_interface_t keyboardd_data; extern ATTR_WEAK hidd_interface_t keyboardd_data;
@ -86,7 +87,9 @@ static hidd_class_driver_t const hidd_class_driver[HIDD_NUMBER_OF_SUBCLASS] =
.p_interface = &keyboardd_data, .p_interface = &keyboardd_data,
.mounted_cb = tusbd_hid_keyboard_mounted_cb, .mounted_cb = tusbd_hid_keyboard_mounted_cb,
.unmounted_cb = tusbd_hid_keyboard_unmounted_cb, .unmounted_cb = tusbd_hid_keyboard_unmounted_cb,
.xfer_cb = tusbd_hid_keyboard_cb .xfer_cb = tusbd_hid_keyboard_cb,
.get_report_cb = tusbd_hid_keyboard_get_report_cb,
.set_report_cb = tusbd_hid_keyboard_set_report_cb
}, },
#endif #endif
@ -97,11 +100,17 @@ static hidd_class_driver_t const hidd_class_driver[HIDD_NUMBER_OF_SUBCLASS] =
.p_interface = &moused_data, .p_interface = &moused_data,
.mounted_cb = tusbd_hid_mouse_mounted_cb, .mounted_cb = tusbd_hid_mouse_mounted_cb,
.unmounted_cb = tusbd_hid_mouse_unmounted_cb, .unmounted_cb = tusbd_hid_mouse_unmounted_cb,
.xfer_cb = tusbd_hid_mouse_cb .xfer_cb = tusbd_hid_mouse_cb,
.get_report_cb = tusbd_hid_mouse_get_report_cb,
.set_report_cb = tusbd_hid_mouse_set_report_cb
} }
#endif #endif
}; };
#if TUSB_CFG_DEVICE_HID_KEYBOARD || TUSB_CFG_DEVICE_HID_MOUSE
ATTR_USB_MIN_ALIGNMENT uint8_t m_control_data[ MAX_OF(sizeof(hid_keyboard_report_t), sizeof(hid_mouse_report_t)) ] TUSB_CFG_ATTR_USBRAM;
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// KEYBOARD APPLICATION API // KEYBOARD APPLICATION API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -180,7 +189,7 @@ void hidd_close(uint8_t coreid)
} }
} }
tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) tusb_error_t hidd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
{ {
uint8_t subclass_idx; uint8_t subclass_idx;
for(subclass_idx=0; subclass_idx<HIDD_NUMBER_OF_SUBCLASS; subclass_idx++) for(subclass_idx=0; subclass_idx<HIDD_NUMBER_OF_SUBCLASS; subclass_idx++)
@ -194,7 +203,7 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const *
ASSERT(subclass_idx < HIDD_NUMBER_OF_SUBCLASS, TUSB_ERROR_FAILED); ASSERT(subclass_idx < HIDD_NUMBER_OF_SUBCLASS, TUSB_ERROR_FAILED);
hidd_class_driver_t* const p_driver = &hidd_class_driver[subclass_idx]; hidd_class_driver_t const * const p_driver = &hidd_class_driver[subclass_idx];
hidd_interface_t* const p_hid = p_driver->p_interface; hidd_interface_t* const p_hid = p_driver->p_interface;
//------------- STD Request -------------// //------------- STD Request -------------//
@ -208,39 +217,50 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const *
ASSERT ( p_request->bRequest == TUSB_REQUEST_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT, ASSERT ( p_request->bRequest == TUSB_REQUEST_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT,
TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT); TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);
dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_driver->p_report_desc, p_hid->report_length); dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_driver->p_report_desc, p_hid->report_length, false);
} }
//------------- Class Specific Request -------------// //------------- Class Specific Request -------------//
else if (p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS) else if (p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS)
{ {
switch(p_request->bRequest) OSAL_SUBTASK_BEGIN
if( (HID_REQUEST_CONTROL_GET_REPORT == p_request->bRequest) && (p_driver->get_report_cb != NULL) )
{ {
case HID_REQUEST_CONTROL_SET_IDLE: // wValue = Report Type | Report ID
// idle_rate = u16_high_u8(p_request->wValue); void* p_buffer = NULL;
break;
case HID_REQUEST_CONTROL_SET_REPORT: uint16_t actual_length = p_driver->get_report_cb(coreid, (hid_request_report_type_t) u16_high_u8(p_request->wValue),
{ &p_buffer, p_request->wLength);
// return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; // TODO test STALL control out endpoint (with mouse+keyboard)aaaaa SUBTASK_ASSERT( p_buffer != NULL && actual_length > 0 );
// TODO HIDD set report support dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, actual_length, false);
hid_request_report_type_t report_type = u16_high_u8(p_request->wValue);
uint8_t report_id = u16_low_u8(p_request->wValue);
(void) report_id;
(void) report_type;
dcd_pipe_control_xfer(coreid, TUSB_DIR_HOST_TO_DEV, &set_report, p_request->wLength);
} }
break; else if ( (HID_REQUEST_CONTROL_SET_REPORT == p_request->bRequest) && (p_driver->set_report_cb != NULL) )
{
// return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; // TODO test STALL control out endpoint (with mouse+keyboard)
// wValue = Report Type | Report ID
tusb_error_t error;
case HID_REQUEST_CONTROL_GET_IDLE: dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, &m_control_data, p_request->wLength, true);
case HID_REQUEST_CONTROL_GET_REPORT:
case HID_REQUEST_CONTROL_GET_PROTOCOL: osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); // wait for control xfer complete
case HID_REQUEST_CONTROL_SET_PROTOCOL: SUBTASK_ASSERT_STATUS(error);
default:
p_driver->set_report_cb(coreid, (hid_request_report_type_t) u16_high_u8(p_request->wValue),
&m_control_data, p_request->wLength);
}
else if (HID_REQUEST_CONTROL_SET_IDLE == p_request->bRequest)
{
// uint8_t idle_rate = u16_high_u8(p_request->wValue);
}else
{
// HID_REQUEST_CONTROL_GET_IDLE:
// HID_REQUEST_CONTROL_GET_PROTOCOL:
// HID_REQUEST_CONTROL_SET_PROTOCOL:
return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
} }
OSAL_SUBTASK_END
}else }else
{ {
return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@ -270,7 +290,7 @@ tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int
case HID_PROTOCOL_KEYBOARD: case HID_PROTOCOL_KEYBOARD:
case HID_PROTOCOL_MOUSE: case HID_PROTOCOL_MOUSE:
{ {
hidd_class_driver_t * const p_driver = &hidd_class_driver[p_interface_desc->bInterfaceProtocol]; hidd_class_driver_t const * const p_driver = &hidd_class_driver[p_interface_desc->bInterfaceProtocol];
hidd_interface_t * const p_hid = p_driver->p_interface; hidd_interface_t * const p_hid = p_driver->p_interface;
ASSERT_PTR(p_hid, TUSB_ERROR_FAILED); ASSERT_PTR(p_hid, TUSB_ERROR_FAILED);

View File

@ -94,8 +94,8 @@ void tusbd_hid_keyboard_unmounted_cb(uint8_t coreid);
*/ */
void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes); void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes);
void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t report_data[]); void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length);
void tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report); uint16_t tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length);
/** @} */ /** @} */
/** @} */ /** @} */
@ -108,8 +108,6 @@ void tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t
/** \defgroup Mouse_Device Device /** \defgroup Mouse_Device Device
* @{ */ * @{ */
//bool tusbd_hid_mouse_is_configured(uint8_t coreid);
/** \brief Check if the interface is currently busy or not /** \brief Check if the interface is currently busy or not
* \param[in] coreid USB Controller ID * \param[in] coreid USB Controller ID
* \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to host * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to host
@ -149,6 +147,8 @@ void tusbd_hid_mouse_unmounted_cb(uint8_t coreid);
*/ */
void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes); void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes);
uint16_t tusbd_hid_mouse_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length);
void tusbd_hid_mouse_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length);
/** @} */ /** @} */
/** @} */ /** @} */
@ -161,7 +161,7 @@ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_byt
void hidd_init(void); void hidd_init(void);
tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length); tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length);
tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request); tusb_error_t hidd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request);
tusb_error_t hidd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); tusb_error_t hidd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
void hidd_close(uint8_t coreid); void hidd_close(uint8_t coreid);

View File

@ -113,7 +113,7 @@ tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int
return TUSB_ERROR_NONE; return TUSB_ERROR_NONE;
} }
tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) tusb_error_t mscd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
{ {
ASSERT(p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT); ASSERT(p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);

View File

@ -126,7 +126,7 @@ msc_csw_status_t tusbd_msc_scsi_received_isr (uint8_t coreid, uint8_t lun, uint8
void mscd_init(void); void mscd_init(void);
tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length); tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length);
tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * p_request); tusb_error_t mscd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request);
tusb_error_t mscd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes); tusb_error_t mscd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
void mscd_close(uint8_t coreid); void mscd_close(uint8_t coreid);

View File

@ -83,6 +83,8 @@
#include "std_descriptors.h" #include "std_descriptors.h"
#include "std_request.h" #include "std_request.h"
#include "osal/osal.h"
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// MACROS // MACROS
@ -93,6 +95,7 @@
#define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat #define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat
#define MAX_OF(a, b) ( (a) > (b) ? (a) : (b) ) #define MAX_OF(a, b) ( (a) > (b) ? (a) : (b) )
#define MIN_OF(a, b) ( (a) < (b) ? (a) : (b) )
#define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) #define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff))
#define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff)) #define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff))

View File

@ -81,7 +81,7 @@ void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr);
void dcd_controller_set_configuration(uint8_t coreid); void dcd_controller_set_configuration(uint8_t coreid);
//------------- PIPE API -------------// //------------- PIPE API -------------//
tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length); tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length, bool int_on_complete);
void dcd_pipe_control_stall(uint8_t coreid); void dcd_pipe_control_stall(uint8_t coreid);
endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT;

View File

@ -200,6 +200,61 @@ static void bus_reset(void)
LPC_USB->INTEN = INT_MASK_DEVICE_STATUS | BIT_(0) | BIT_(1); // enable device status & control endpoints LPC_USB->INTEN = INT_MASK_DEVICE_STATUS | BIT_(0) | BIT_(1); // enable device status & control endpoints
} }
static void endpoint_non_control_isr(uint32_t int_status)
{
for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++ )
{
if ( BIT_TEST_(int_status, ep_id) )
{
dcd_11u_13u_qhd_t * const arr_qhd = dcd_data.qhd[ep_id];
// when double buffering, the complete buffer is opposed to the current active buffer in EPINUSE
uint8_t const buff_idx = LPC_USB->EPINUSE & BIT_(ep_id) ? 0 : 1;
uint16_t const xferred_bytes = dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] - arr_qhd[buff_idx].total_bytes;
dcd_data.current_td[ep_id].xferred_total += xferred_bytes;
// there are still data to transfer.
if ( (arr_qhd[buff_idx].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) )
{ // NOTE although buff_addr_offset has been increased when xfer is completed
// but we still need to increase it one more as we are using double buffering.
queue_xfer_to_buffer(ep_id, buff_idx, arr_qhd[buff_idx].buff_addr_offset+1, dcd_data.current_td[ep_id].remaining_bytes);
}
// short packet or (no more byte and both buffers are finished)
else if ( (arr_qhd[buff_idx].total_bytes > 0) || !arr_qhd[1-buff_idx].active )
{ // current TD (request) is completed
LPC_USB->EPSKIP = BIT_SET_(LPC_USB->EPSKIP, ep_id); // skip other endpoint in case of short-package
dcd_data.current_td[ep_id].remaining_bytes = 0;
if ( BIT_TEST_(dcd_data.current_ioc, ep_id) )
{
endpoint_handle_t edpt_hdl =
{
.coreid = 0,
.index = ep_id,
.class_code = dcd_data.class_code[ep_id]
};
dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index);
// TODO no way determine if the transfer is failed or not
usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.current_td[ep_id].xferred_total);
}
//------------- Next TD is available -------------//
if ( dcd_data.next_td[ep_id].total_bytes != 0 )
{
queue_xfer_in_next_td(ep_id);
}
}else
{
// transfer complete, there is no more remaining bytes, but this buffer is not the last transaction (the other is)
}
}
}
}
void dcd_isr(uint8_t coreid) void dcd_isr(uint8_t coreid)
{ {
(void) coreid; (void) coreid;
@ -248,7 +303,7 @@ void dcd_isr(uint8_t coreid)
// } // }
} }
//------------- Control Endpoint -------------// //------------- Setup Received -------------//
if ( BIT_TEST_(int_status, 0) && (dev_cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) ) if ( BIT_TEST_(int_status, 0) && (dev_cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) )
{ // received control request from host { // received control request from host
// copy setup request & acknowledge so that the next setup can be received by hw // copy setup request & acknowledge so that the next setup can be received by hw
@ -260,42 +315,17 @@ void dcd_isr(uint8_t coreid)
LPC_USB->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; LPC_USB->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK;
dcd_data.qhd[0][1].buff_addr_offset = addr_offset(&dcd_data.setup_request); dcd_data.qhd[0][1].buff_addr_offset = addr_offset(&dcd_data.setup_request);
} }
//------------- Control Endpoint -------------//
else if ( int_status & 0x03 ) else if ( int_status & 0x03 )
{ // either control endpoints { // either control endpoints
endpoint_handle_t edpt_hdl = uint8_t const ep_id = ( int_status & BIT_(0) ) ? 0 : 1;
{
.coreid = coreid,
.index = BIT_TEST_(int_status, 1) ? 1 : 0
};
// FIXME xferred_byte for control xfer is not needed now !!!
usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0);
}
//------------- Non-Control Endpoints -------------//
for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++ )
{
if ( BIT_TEST_(int_status, ep_id) )
{
dcd_11u_13u_qhd_t * const arr_qhd = dcd_data.qhd[ep_id];
// when double buffering, the complete buffer is opposed to the current active buffer in EPINUSE
uint8_t const buff_idx = LPC_USB->EPINUSE & BIT_(ep_id) ? 0 : 1;
uint16_t const xferred_bytes = dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] - arr_qhd[buff_idx].total_bytes;
dcd_data.current_td[ep_id].xferred_total += xferred_bytes;
// there are still data to transfer. // there are still data to transfer.
if ( (arr_qhd[buff_idx].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) ) if ( (dcd_data.qhd[ep_id][0].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) )
{ // NOTE although buff_addr_offset has been increased when xfer is completed {
// but we still need to increase it one more as we are using double buffering. queue_xfer_to_buffer(ep_id, 0, dcd_data.qhd[ep_id][0].buff_addr_offset, dcd_data.current_td[ep_id].remaining_bytes);
queue_xfer_to_buffer(ep_id, buff_idx, arr_qhd[buff_idx].buff_addr_offset+1, dcd_data.current_td[ep_id].remaining_bytes); }else
} {
// short packet or (no more byte and both buffers are finished)
else if ( (arr_qhd[buff_idx].total_bytes > 0) || !arr_qhd[1-buff_idx].active )
{ // current TD (request) is completed
LPC_USB->EPSKIP = BIT_SET_(LPC_USB->EPSKIP, ep_id); // skip other endpoint in case of short-package
dcd_data.current_td[ep_id].remaining_bytes = 0; dcd_data.current_td[ep_id].remaining_bytes = 0;
if ( BIT_TEST_(dcd_data.current_ioc, ep_id) ) if ( BIT_TEST_(dcd_data.current_ioc, ep_id) )
@ -303,45 +333,55 @@ void dcd_isr(uint8_t coreid)
endpoint_handle_t edpt_hdl = endpoint_handle_t edpt_hdl =
{ {
.coreid = coreid, .coreid = coreid,
.index = ep_id, .index = 0
.class_code = dcd_data.class_code[ep_id]
}; };
dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index); dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index);
// TODO no way determine if the transfer is failed or not // FIXME xferred_byte for control xfer is not needed now !!!
usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.current_td[ep_id].xferred_total); usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0);
}
}
} }
//------------- Next TD is available -------------// //------------- Non-Control Endpoints -------------//
if ( dcd_data.next_td[ep_id].total_bytes != 0 ) endpoint_non_control_isr(int_status);
{
queue_xfer_in_next_td(ep_id);
}
}
}
}
} }
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// CONTROL PIPE API // CONTROL PIPE API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
void dcd_pipe_control_stall(uint8_t coreid) void dcd_pipe_control_stall(uint8_t coreid)
{ // TODO cannot able to STALL Control OUT endpoint !!!!! {
(void) coreid; (void) coreid;
// TODO cannot able to STALL Control OUT endpoint !!!!! FIXME try some walk-around
dcd_data.qhd[0][0].stall = dcd_data.qhd[1][0].stall = 1; dcd_data.qhd[0][0].stall = dcd_data.qhd[1][0].stall = 1;
} }
tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length) tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length, bool int_on_complete)
{ {
(void) coreid; (void) coreid;
uint8_t const ep_id = dir; // IN : 1, OUT = 0 // determine Endpoint where Data & Status phase occurred (IN or OUT)
uint8_t const ep_data = (dir == TUSB_DIR_DEV_TO_HOST) ? 1 : 0;
uint8_t const ep_status = 1 - ep_data;
dcd_data.qhd[ep_id][0].buff_addr_offset = (length ? addr_offset(p_buffer) : 0 ); dcd_data.current_ioc = int_on_complete ? BIT_SET_(dcd_data.current_ioc, ep_status) : BIT_CLR_(dcd_data.current_ioc, ep_status);
dcd_data.qhd[ep_id][0].total_bytes = length;
dcd_data.qhd[ep_id][0].active = 1 ; //------------- Data Phase -------------//
if (length)
{
dcd_data.current_td[ep_data].remaining_bytes = length;
dcd_data.current_td[ep_data].xferred_total = 0;
queue_xfer_to_buffer(ep_data, 0, addr_offset(p_buffer), length);
}
//------------- Status Phase -------------//
dcd_data.current_td[ep_status].remaining_bytes = 0;
dcd_data.current_td[ep_status].xferred_total = 0;
queue_xfer_to_buffer(ep_status, 0, NULL, 0);
return TUSB_ERROR_NONE; return TUSB_ERROR_NONE;
} }

View File

@ -49,13 +49,6 @@
#include "tusb_descriptors.h" // TODO callback include #include "tusb_descriptors.h" // TODO callback include
#include "usbd_dcd.h" #include "usbd_dcd.h"
// Some MCUs cannot transfer more than 64 bytes each queue, thus require special task-alike treatment
#if TUSB_CFG_MCU == MCU_LPC11UXX || TUSB_CFG_MCU == MCU_LPC175X_6X
#define USBD_CONTROL_ONE_PACKET_EACH_XFER // for each Transfer, cannot queue more than packet size
enum {
USBD_COTNROL_MAX_LENGTH_EACH_XFER = 64
};
#endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF // MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -69,7 +62,7 @@ static usbd_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_STAR
{ {
.init = hidd_init, .init = hidd_init,
.open = hidd_open, .open = hidd_open,
.control_request = hidd_control_request, .control_request_subtask = hidd_control_request_subtask,
.xfer_cb = hidd_xfer_cb, .xfer_cb = hidd_xfer_cb,
.close = hidd_close .close = hidd_close
}, },
@ -80,7 +73,7 @@ static usbd_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_STAR
{ {
.init = mscd_init, .init = mscd_init,
.open = mscd_open, .open = mscd_open,
.control_request = mscd_control_request, .control_request_subtask = mscd_control_request_subtask,
.xfer_cb = mscd_xfer_cb, .xfer_cb = mscd_xfer_cb,
.close = mscd_close .close = mscd_close
}, },
@ -91,7 +84,7 @@ static usbd_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_STAR
{ {
.init = cdcd_init, .init = cdcd_init,
.open = cdcd_open, .open = cdcd_open,
.control_request = cdcd_control_request, .control_request_subtask = cdcd_control_request_subtask,
.xfer_cb = cdcd_xfer_cb, .xfer_cb = cdcd_xfer_cb,
.close = cdcd_close .close = cdcd_close
}, },
@ -151,7 +144,7 @@ OSAL_QUEUE_DEF(usbd_queue_def, USBD_TASK_QUEUE_DEPTH, usbd_task_event_t);
OSAL_SEM_DEF(usbd_control_xfer_semaphore_def); OSAL_SEM_DEF(usbd_control_xfer_semaphore_def);
static osal_queue_handle_t usbd_queue_hdl; static osal_queue_handle_t usbd_queue_hdl;
static osal_semaphore_handle_t usbd_control_xfer_sem_hdl; /*static*/ osal_semaphore_handle_t usbd_control_xfer_sem_hdl; // TODO may need to change to static with wrapper function
tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * const p_request) tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * const p_request)
{ {
@ -165,29 +158,14 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t
{ {
if ( TUSB_REQUEST_GET_DESCRIPTOR == p_request->bRequest ) if ( TUSB_REQUEST_GET_DESCRIPTOR == p_request->bRequest )
{ {
OSAL_VAR uint8_t* p_buffer = NULL; uint8_t* p_buffer = NULL;
OSAL_VAR uint16_t length = 0; uint16_t length = 0;
error = get_descriptor_subtask(coreid, p_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;
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;
usbd_devices[coreid].is_waiting_control_xfer = false;
}
#endif
if ( TUSB_ERROR_NONE == error ) if ( TUSB_ERROR_NONE == error )
{ {
dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length); dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length, false);
} }
} }
else if ( TUSB_REQUEST_SET_ADDRESS == p_request->bRequest ) else if ( TUSB_REQUEST_SET_ADDRESS == p_request->bRequest )
@ -207,12 +185,14 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t
//------------- Class/Interface Specific Request -------------// //------------- Class/Interface Specific Request -------------//
else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == p_request->bmRequestType_bit.recipient) 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) ]; OSAL_VAR tusb_std_class_code_t class_code;
class_code = usbd_devices[coreid].interface2class[ u16_low_u8(p_request->wIndex) ];
if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) && if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) &&
usbd_class_drivers[class_code].control_request ) usbd_class_drivers[class_code].control_request_subtask )
{ {
error = usbd_class_drivers[class_code].control_request(coreid, p_request); OSAL_SUBTASK_INVOKED_AND_WAIT( usbd_class_drivers[class_code].control_request_subtask(coreid, p_request), error );
}else }else
{ {
error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@ -234,9 +214,9 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t
{ // Response with Protocol Stall if request is not supported { // Response with Protocol Stall if request is not supported
dcd_pipe_control_stall(coreid); dcd_pipe_control_stall(coreid);
// ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN); // ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN);
}else }else if (p_request->wLength == 0)
{ // status phase {
dcd_pipe_control_xfer(coreid, 1-p_request->bmRequestType_bit.direction, NULL, 0); // zero length dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0, false); // zero length for non-data
} }
OSAL_SUBTASK_END OSAL_SUBTASK_END
@ -417,11 +397,8 @@ void usbd_setup_received_isr(uint8_t coreid, tusb_control_request_t * p_request)
void usbd_xfer_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes) void usbd_xfer_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes)
{ {
if (edpt_hdl.class_code == 0 ) // Control Transfer if (edpt_hdl.class_code == 0 ) // Control Transfer
{
if (usbd_devices[edpt_hdl.coreid].is_waiting_control_xfer)
{ {
osal_semaphore_post( usbd_control_xfer_sem_hdl ); osal_semaphore_post( usbd_control_xfer_sem_hdl );
}
}else }else
{ {
usbd_task_event_t task_event = usbd_task_event_t task_event =

View File

@ -70,7 +70,7 @@
typedef struct { typedef struct {
void (* const init) (void); void (* const init) (void);
tusb_error_t (* const open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*); tusb_error_t (* const open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*);
tusb_error_t (* const control_request) (uint8_t, tusb_control_request_t const *); tusb_error_t (* const control_request_subtask) (uint8_t, tusb_control_request_t const *);
tusb_error_t (* const xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t); tusb_error_t (* const xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t);
void (* const close) (uint8_t); void (* const close) (uint8_t);
} usbd_class_driver_t; } usbd_class_driver_t;
@ -90,8 +90,11 @@ bool tusbd_is_configured(uint8_t coreid) ATTR_WARN_UNUSED_RESULT;
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
#ifdef _TINY_USB_SOURCE_FILE_ #ifdef _TINY_USB_SOURCE_FILE_
extern osal_semaphore_handle_t usbd_control_xfer_sem_hdl;
tusb_error_t usbd_init(void); tusb_error_t usbd_init(void);
OSAL_TASK_FUNCTION (usbd_task) (void* p_task_para); OSAL_TASK_FUNCTION (usbd_task) (void* p_task_para);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -68,7 +68,6 @@ typedef enum {
typedef struct { typedef struct {
volatile uint8_t state; volatile uint8_t state;
uint8_t is_waiting_control_xfer; // set if task is waiting for control xfer to complete to proceed
uint8_t interface2class[USBD_INTERFACE_NUM_MAX]; // determine interface number belongs to which class uint8_t interface2class[USBD_INTERFACE_NUM_MAX]; // determine interface number belongs to which class
}usbd_device_info_t; }usbd_device_info_t;