mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 17:38:39 +00:00
core/usb: avoid naks in hid/webusb rx interfaces
This commit is contained in:
parent
6afff3cc0e
commit
ecc4313a34
@ -179,20 +179,6 @@ static void usb_desc_add_iface(size_t desc_len) {
|
|||||||
usb_config_desc->wTotalLength);
|
usb_config_desc->wTotalLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t usb_ep_set_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) {
|
|
||||||
PCD_HandleTypeDef *hpcd = dev->pData;
|
|
||||||
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
|
||||||
USBx_OUTEP(ep_num)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
|
|
||||||
return USBD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t usb_ep_clear_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) {
|
|
||||||
PCD_HandleTypeDef *hpcd = dev->pData;
|
|
||||||
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
|
||||||
USBx_OUTEP(ep_num)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
|
|
||||||
return USBD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB interface implementations
|
* USB interface implementations
|
||||||
*/
|
*/
|
||||||
|
@ -158,20 +158,23 @@ int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
|
|||||||
if (iface->type != USB_IFACE_TYPE_HID) {
|
if (iface->type != USB_IFACE_TYPE_HID) {
|
||||||
return -2; // Invalid interface type
|
return -2; // Invalid interface type
|
||||||
}
|
}
|
||||||
usb_hid_state_t *state = &iface->hid;
|
volatile usb_hid_state_t *state = &iface->hid;
|
||||||
|
|
||||||
// Copy maximum possible amount of data and truncate the buffer length
|
// Copy maximum possible amount of data
|
||||||
if (len < state->last_read_len) {
|
uint32_t last_read_len = state->last_read_len;
|
||||||
|
if (len < last_read_len) {
|
||||||
return 0; // Not enough data in the read buffer
|
return 0; // Not enough data in the read buffer
|
||||||
}
|
}
|
||||||
len = state->last_read_len;
|
memcpy(buf, state->rx_buffer, last_read_len);
|
||||||
|
|
||||||
|
// Reset the length to indicate we are ready to read next packet
|
||||||
state->last_read_len = 0;
|
state->last_read_len = 0;
|
||||||
memcpy(buf, state->rx_buffer, len);
|
|
||||||
|
|
||||||
// Clear NAK to indicate we are ready to read more data
|
// Prepare the OUT EP to receive next packet
|
||||||
usb_ep_clear_nak(&usb_dev_handle, state->ep_out);
|
USBD_LL_PrepareReceive(&usb_dev_handle, state->ep_out, state->rx_buffer,
|
||||||
|
state->max_packet_len);
|
||||||
|
|
||||||
return len;
|
return last_read_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
||||||
@ -182,7 +185,7 @@ int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
|||||||
if (iface->type != USB_IFACE_TYPE_HID) {
|
if (iface->type != USB_IFACE_TYPE_HID) {
|
||||||
return -2; // Invalid interface type
|
return -2; // Invalid interface type
|
||||||
}
|
}
|
||||||
usb_hid_state_t *state = &iface->hid;
|
volatile usb_hid_state_t *state = &iface->hid;
|
||||||
|
|
||||||
if (state->ep_in_is_idle == 0) {
|
if (state->ep_in_is_idle == 0) {
|
||||||
return 0; // Last transmission is not over yet
|
return 0; // Last transmission is not over yet
|
||||||
@ -344,17 +347,8 @@ static void usb_hid_class_data_in(USBD_HandleTypeDef *dev,
|
|||||||
static void usb_hid_class_data_out(USBD_HandleTypeDef *dev,
|
static void usb_hid_class_data_out(USBD_HandleTypeDef *dev,
|
||||||
usb_hid_state_t *state, uint8_t ep_num) {
|
usb_hid_state_t *state, uint8_t ep_num) {
|
||||||
if (ep_num == state->ep_out) {
|
if (ep_num == state->ep_out) {
|
||||||
|
// Save the report length to indicate we have read something, but don't
|
||||||
|
// schedule next reading until user reads this one
|
||||||
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
|
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
|
||||||
|
|
||||||
// Prepare the OUT EP to receive next packet
|
|
||||||
// User should provide state->rx_buffer that is big enough for
|
|
||||||
// state->max_packet_len bytes
|
|
||||||
USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer,
|
|
||||||
state->max_packet_len);
|
|
||||||
|
|
||||||
if (state->last_read_len > 0) {
|
|
||||||
// Block the OUT EP until we process received data
|
|
||||||
usb_ep_set_nak(dev, ep_num);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,20 +134,23 @@ int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) {
|
|||||||
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
|
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
|
||||||
return -2; // Invalid interface type
|
return -2; // Invalid interface type
|
||||||
}
|
}
|
||||||
usb_webusb_state_t *state = &iface->webusb;
|
volatile usb_webusb_state_t *state = &iface->webusb;
|
||||||
|
|
||||||
// Copy maximum possible amount of data and truncate the buffer length
|
// Copy maximum possible amount of data
|
||||||
if (len < state->last_read_len) {
|
uint32_t last_read_len = state->last_read_len;
|
||||||
|
if (len < last_read_len) {
|
||||||
return 0; // Not enough data in the read buffer
|
return 0; // Not enough data in the read buffer
|
||||||
}
|
}
|
||||||
len = state->last_read_len;
|
memcpy(buf, state->rx_buffer, last_read_len);
|
||||||
|
|
||||||
|
// Reset the length to indicate we are ready to read next packet
|
||||||
state->last_read_len = 0;
|
state->last_read_len = 0;
|
||||||
memcpy(buf, state->rx_buffer, len);
|
|
||||||
|
|
||||||
// Clear NAK to indicate we are ready to read more data
|
// Prepare the OUT EP to receive next packet
|
||||||
usb_ep_clear_nak(&usb_dev_handle, state->ep_out);
|
USBD_LL_PrepareReceive(&usb_dev_handle, state->ep_out, state->rx_buffer,
|
||||||
|
state->max_packet_len);
|
||||||
|
|
||||||
return len;
|
return last_read_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
||||||
@ -158,7 +161,7 @@ int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
|||||||
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
|
if (iface->type != USB_IFACE_TYPE_WEBUSB) {
|
||||||
return -2; // Invalid interface type
|
return -2; // Invalid interface type
|
||||||
}
|
}
|
||||||
usb_webusb_state_t *state = &iface->webusb;
|
volatile usb_webusb_state_t *state = &iface->webusb;
|
||||||
|
|
||||||
state->ep_in_is_idle = 0;
|
state->ep_in_is_idle = 0;
|
||||||
USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len);
|
USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len);
|
||||||
@ -268,17 +271,8 @@ static void usb_webusb_class_data_out(USBD_HandleTypeDef *dev,
|
|||||||
usb_webusb_state_t *state,
|
usb_webusb_state_t *state,
|
||||||
uint8_t ep_num) {
|
uint8_t ep_num) {
|
||||||
if (ep_num == state->ep_out) {
|
if (ep_num == state->ep_out) {
|
||||||
|
// Save the report length to indicate we have read something, but don't
|
||||||
|
// schedule next reading until user reads this one
|
||||||
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
|
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
|
||||||
|
|
||||||
// Prepare the OUT EP to receive next packet
|
|
||||||
// User should provide state->rx_buffer that is big enough for
|
|
||||||
// state->max_packet_len bytes
|
|
||||||
USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer,
|
|
||||||
state->max_packet_len);
|
|
||||||
|
|
||||||
if (state->last_read_len > 0) {
|
|
||||||
// Block the OUT EP until we process received data
|
|
||||||
usb_ep_set_nak(dev, ep_num);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user