add field to endpoint maxpacketsize (mult)

refractor hidh_open_subtask & hidh_keyboard_open
add ATTR_PACKED_STRUCT(x)
- TODO remove ugly pre_pack & post pack
This commit is contained in:
hathach 2013-03-26 13:07:42 +07:00
parent 03d045ecde
commit 3c767e9f44
6 changed files with 114 additions and 106 deletions

View File

@ -122,7 +122,7 @@ tusb_descriptor_endpoint_t const desc_ept_bulk_in =
void verify_bulk_open_qhd(ehci_qhd_t *p_qhd, tusb_descriptor_endpoint_t const * desc_endpoint, uint8_t class_code)
{
verify_open_qhd(p_qhd, desc_endpoint->bEndpointAddress, desc_endpoint->wMaxPacketSize);
verify_open_qhd(p_qhd, desc_endpoint->bEndpointAddress, desc_endpoint->wMaxPacketSize.size);
TEST_ASSERT_FALSE(p_qhd->head_list_flag);
TEST_ASSERT_EQUAL(0, p_qhd->data_toggle_control);

View File

@ -121,7 +121,7 @@ tusb_descriptor_endpoint_t const desc_ept_interrupt_out =
};
void verify_int_qhd(ehci_qhd_t *p_qhd, tusb_descriptor_endpoint_t const * desc_endpoint, uint8_t class_code)
{
verify_open_qhd(p_qhd, desc_endpoint->bEndpointAddress, desc_endpoint->wMaxPacketSize);
verify_open_qhd(p_qhd, desc_endpoint->bEndpointAddress, desc_endpoint->wMaxPacketSize.size);
TEST_ASSERT_FALSE(p_qhd->head_list_flag);
TEST_ASSERT_FALSE(p_qhd->data_toggle_control);

View File

@ -53,6 +53,12 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
//--------------------------------------------------------------------+
// KEYBOARD PUBLIC API (parameter validation required)
//--------------------------------------------------------------------+
#if TUSB_CFG_HOST_HID_KEYBOARD
STATIC_ hidh_keyboard_info_t keyboard_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
static inline hidh_keyboard_info_t* get_kbd_data(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
@ -61,108 +67,6 @@ static inline hidh_keyboard_info_t* get_kbd_data(uint8_t dev_addr)
return &keyboard_data[dev_addr-1];
}
//--------------------------------------------------------------------+
// CLASS-USBD API (don't require to verify parameters)
//--------------------------------------------------------------------+
void hidh_init(void)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
memclr_(&keyboard_data, sizeof(hidh_keyboard_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
#endif
#if TUSB_CFG_HOST_HID_MOUSE
hidh_mouse_init();
#endif
#if TUSB_CFG_HOST_HID_GENERIC
hidh_generic_init();
#endif
}
tusb_error_t hidh_keyboard_open_subtask(uint8_t dev_addr, uint8_t const *descriptor, uint16_t *p_length)
{
hidh_keyboard_info_t *p_keyboard = get_kbd_data(dev_addr);
uint8_t const *p_desc = descriptor;
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip interface
(*p_length) = p_desc - descriptor; // set ASAP, in case of error, p_length has to be not zero to prevent infinite re-open
//------------- HID descriptor -------------//
tusb_hid_descriptor_hid_t* const p_desc_hid = (tusb_hid_descriptor_hid_t* const) p_desc;
ASSERT_INT(HID_DESC_HID, p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA);
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // TODO skip HID, only support std keyboard
(*p_length) = p_desc - descriptor;
//------------- Endpoint Descriptor -------------//
ASSERT_INT(TUSB_DESC_ENDPOINT, p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_INVALID_PARA);
p_keyboard->pipe_hdl = hcd_pipe_open(dev_addr, (tusb_descriptor_endpoint_t*) p_desc, TUSB_CLASS_HID);
p_keyboard->report_size = ( ((tusb_descriptor_endpoint_t*) p_desc)->wMaxPacketSize & (BIT_(12)-1) );
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // advance endpoint descriptor
(*p_length) = p_desc - descriptor;
ASSERT (pipehandle_is_valid(p_keyboard->pipe_hdl), TUSB_ERROR_HCD_FAILED);
return TUSB_ERROR_NONE;
}
tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
{
uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
if (p_interface_desc->bInterfaceSubClass == HID_SUBCLASS_BOOT)
{
switch(p_interface_desc->bInterfaceProtocol)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD:
return hidh_keyboard_open_subtask(dev_addr, p_desc, p_length);
break;
#endif
#if TUSB_CFG_HOST_HID_MOUSE
case HID_PROTOCOL_MOUSE:
return hidh_keyboard_open_subtask(dev_addr, p_desc, p_length);
break;
#endif
default: // unknown protocol --> skip this interface
*p_length = p_interface_desc->bLength;
return TUSB_ERROR_NONE;
}
}else
{
// open generic
*p_length = p_interface_desc->bLength;
return TUSB_ERROR_NONE;
}
}
void hidh_isr(pipe_handle_t pipe_hdl, tusb_bus_event_t event)
{
}
void hidh_close(uint8_t dev_addr)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
// hidh_keyboard_close(dev_addr);
#endif
#if TUSB_CFG_HOST_HID_MOUSE
hidh_mouse_close(dev_addr);
#endif
#if TUSB_CFG_HOST_HID_GENERIC
hidh_generic_close(dev_addr);
#endif
}
//--------------------------------------------------------------------+
// KEYBOARD PUBLIC API (parameter validation required)
//--------------------------------------------------------------------+
#if TUSB_CFG_HOST_HID_KEYBOARD
bool tusbh_hid_keyboard_is_supported(uint8_t dev_addr)
{
@ -187,4 +91,101 @@ tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, uint8_t instance_nu
#endif
//--------------------------------------------------------------------+
// CLASS-USBD API (don't require to verify parameters)
//--------------------------------------------------------------------+
void hidh_init(void)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
memclr_(&keyboard_data, sizeof(hidh_keyboard_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
#endif
#if TUSB_CFG_HOST_HID_MOUSE
hidh_mouse_init();
#endif
#if TUSB_CFG_HOST_HID_GENERIC
hidh_generic_init();
#endif
}
tusb_error_t hidh_keyboard_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *p_endpoint_desc)
{
hidh_keyboard_info_t *p_keyboard = get_kbd_data(dev_addr);
p_keyboard->pipe_hdl = hcd_pipe_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID);
p_keyboard->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor
ASSERT (pipehandle_is_valid(p_keyboard->pipe_hdl), TUSB_ERROR_HCD_FAILED);
return TUSB_ERROR_NONE;
}
tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
{
uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
//------------- HID descriptor -------------//
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
ASSERT_INT(HID_DESC_HID, p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA);
//------------- TODO skip Get Report Descriptor -------------//
uint8_t *p_report_desc = NULL; // report descriptor has to be global & in USB RAM
//------------- Endpoint Descriptor -------------//
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
ASSERT_INT(TUSB_DESC_ENDPOINT, p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_INVALID_PARA);
if (p_interface_desc->bInterfaceSubClass == HID_SUBCLASS_BOOT)
{
switch(p_interface_desc->bInterfaceProtocol)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD:
ASSERT_STATUS ( hidh_keyboard_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc) );
break;
#endif
#if TUSB_CFG_HOST_HID_MOUSE
case HID_PROTOCOL_MOUSE:
ASSERT_STATUS ( hidh_keyboard_open(dev_addr, p_desc, p_length) );
break;
#endif
default: // unknown protocol --> skip this interface
return TUSB_ERROR_NONE;
}
*p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
}else
{
// open generic
*p_length = 0;
}
return TUSB_ERROR_NONE;
}
void hidh_isr(pipe_handle_t pipe_hdl, tusb_bus_event_t event)
{
}
void hidh_close(uint8_t dev_addr)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
// hidh_keyboard_close(dev_addr);
#endif
#if TUSB_CFG_HOST_HID_MOUSE
hidh_mouse_close(dev_addr);
#endif
#if TUSB_CFG_HOST_HID_GENERIC
hidh_generic_close(dev_addr);
#endif
}
#endif

View File

@ -74,6 +74,8 @@
#define ATTR_PACKED __attribute__ ((packed))
#define ATTR_PREPACKED
#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed))
/** @} */
/**

View File

@ -117,7 +117,12 @@ typedef ATTR_PREPACKED struct ATTR_PACKED {
uint8_t : 2;
} bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host.
uint16_t wMaxPacketSize ; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero.
ATTR_PACKED_STRUCT(struct) {
uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero.
uint16_t hs_period_mult : 2;
uint16_t : 0;
}wMaxPacketSize;
uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information.
} tusb_descriptor_endpoint_t;

View File

@ -513,7 +513,7 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
ehci_qhd_t * const p_qhd = qhd_find_free(dev_addr);
ASSERT_PTR(p_qhd, null_handle);
qhd_init(p_qhd, dev_addr, p_endpoint_desc->wMaxPacketSize, p_endpoint_desc->bEndpointAddress, p_endpoint_desc->bmAttributes.xfer);
qhd_init(p_qhd, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress, p_endpoint_desc->bmAttributes.xfer);
p_qhd->class_code = class_code;
ehci_qhd_t * list_head;