From 38b99b306a16b769493b2ee25d66efa6e7819998 Mon Sep 17 00:00:00 2001 From: Jan Pochyla Date: Thu, 30 Mar 2017 16:06:01 +0200 Subject: [PATCH] trezorhal: add cdc vcp tx TODO: rx support TODO: buffering TODO: cleanup --- micropython/firmware/main.c | 45 +++-- micropython/firmware/mphalport.c | 12 +- micropython/trezorhal/usb.h | 11 ++ micropython/trezorhal/usb_vcp-defs.h | 74 +++++++- micropython/trezorhal/usb_vcp-impl.h | 272 ++++++++++++++++++++++++++- micropython/trezorhal/usbd_conf.c | 201 ++++++++++---------- 6 files changed, 477 insertions(+), 138 deletions(-) diff --git a/micropython/firmware/main.c b/micropython/firmware/main.c index 514fccc448..5e19cd8b35 100644 --- a/micropython/firmware/main.c +++ b/micropython/firmware/main.c @@ -24,27 +24,37 @@ int usb_init_all(void) { static const usb_dev_info_t dev_info = { - .vendor_id = 0x1209, - .product_id = 0x53C1, - .release_num = 0x0002, - .product_str = (uint8_t *)"product_str", - .manufacturer_str = (uint8_t *)"manufacturer_str", + .vendor_id = 0x1209, + .product_id = 0x53C1, + .release_num = 0x0002, + .product_str = (uint8_t *)"product_str", + .manufacturer_str = (uint8_t *)"manufacturer_str", .serial_number_str = (uint8_t *)"serial_number_str", .configuration_str = (uint8_t *)"configuration_str", - .interface_str = (uint8_t *)"interface_str", + .interface_str = (uint8_t *)"interface_str", }; - static uint8_t rx_buffer[64]; + static uint8_t hid_rx_buffer[64]; static const usb_hid_info_t hid_info = { - .iface_num = 0, - .ep_in = 0x81, - .ep_out = 0x01, - .subclass = 0, - .protocol = 0, - .rx_buffer = rx_buffer, - .max_packet_len = sizeof(rx_buffer), + .iface_num = 0x00, + .ep_in = 0x81, + .ep_out = 0x01, + .subclass = 0, + .protocol = 0, + .rx_buffer = hid_rx_buffer, + .max_packet_len = sizeof(hid_rx_buffer), .polling_interval = 1, - .report_desc_len = 34, - .report_desc = (uint8_t*)"\x06\x00\xff\x09\x01\xa1\x01\x09\x20\x15\x00\x26\xff\x00\x75\x08\x95\x40\x81\x02\x09\x21\x15\x00\x26\xff\x00\x75\x08\x95\x40\x91\x02\xc0", + .report_desc_len = 34, + .report_desc = (uint8_t*)"\x06\x00\xff\x09\x01\xa1\x01\x09\x20\x15\x00\x26\xff\x00\x75\x08\x95\x40\x81\x02\x09\x21\x15\x00\x26\xff\x00\x75\x08\x95\x40\x91\x02\xc0", + }; + static const usb_vcp_info_t vcp_info = { + .iface_num = 0x01, + .data_iface_num = 0x02, + .ep_cmd = 0x82, + .ep_in = 0x83, + .ep_out = 0x03, + .polling_interval = 1, + .max_cmd_packet_len = 8, + .max_data_packet_len = 64, }; if (0 != usb_init(&dev_info)) { @@ -53,6 +63,9 @@ int usb_init_all(void) { if (0 != usb_hid_add(&hid_info)) { __fatal_error("usb_hid_add failed"); } + if (0 != usb_vcp_add(&vcp_info)) { + __fatal_error("usb_vcp_add failed"); + } if (0 != usb_start()) { __fatal_error("usb_start failed"); } diff --git a/micropython/firmware/mphalport.c b/micropython/firmware/mphalport.c index ad7a6f3cde..32446fbfd6 100644 --- a/micropython/firmware/mphalport.c +++ b/micropython/firmware/mphalport.c @@ -1,17 +1,15 @@ #include "py/mphal.h" +#include "usb.h" -// void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len); -// int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout); +#define VCP_IFACE 0x01 +#define VCP_WRITE_TIMEOUT 25 int mp_hal_stdin_rx_chr(void) { for (;;) { - // byte c; - // if (USBD_CDC_Rx(&c, 1, 0) != 0) { - // return c; - // } + } } void mp_hal_stdout_tx_strn(const char *str, size_t len) { - // USBD_CDC_TxAlways((const uint8_t*)str, len); + usb_vcp_write_blocking(VCP_IFACE, (const uint8_t *)str, len, VCP_WRITE_TIMEOUT); } diff --git a/micropython/trezorhal/usb.h b/micropython/trezorhal/usb.h index 60118897f3..b8193f6879 100644 --- a/micropython/trezorhal/usb.h +++ b/micropython/trezorhal/usb.h @@ -47,6 +47,17 @@ typedef struct __attribute__((packed)) { uint8_t iInterface; } usb_interface_descriptor_t; +typedef struct __attribute__((packed)) { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +} usb_interface_assoc_descriptor_t; + typedef struct __attribute__((packed)) { uint8_t bLength; uint8_t bDescriptorType; diff --git a/micropython/trezorhal/usb_vcp-defs.h b/micropython/trezorhal/usb_vcp-defs.h index 3816332f23..8507f0a73a 100644 --- a/micropython/trezorhal/usb_vcp-defs.h +++ b/micropython/trezorhal/usb_vcp-defs.h @@ -1,23 +1,79 @@ typedef struct __attribute__((packed)) { -} usb_vcp_descriptor_t; + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint16_t bcdCDC; +} usb_vcp_header_descriptor_t; typedef struct __attribute__((packed)) { - usb_interface_descriptor_t iface; - usb_vcp_descriptor_t vcp; + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} usb_vcp_cm_descriptor_t; + +typedef struct __attribute__((packed)) { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} usb_vcp_acm_descriptor_t; + +typedef struct __attribute__((packed)) { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bControlInterface; + uint8_t bSubordinateInterface0; +} usb_vcp_union_descriptor_t; + +typedef struct __attribute__((packed)) { + usb_interface_assoc_descriptor_t assoc; + usb_interface_descriptor_t iface_cdc; + usb_vcp_header_descriptor_t fheader; // Class-Specific Descriptor Header Format + usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor + usb_vcp_acm_descriptor_t facm; // Abstract Control Management Functional Descriptor + usb_vcp_union_descriptor_t funion; // Union Interface Functional Descriptor + usb_endpoint_descriptor_t ep_cmd; + usb_interface_descriptor_t iface_data; usb_endpoint_descriptor_t ep_in; usb_endpoint_descriptor_t ep_out; - usb_endpoint_descriptor_t ep_cmd; } usb_vcp_descriptor_block_t; typedef struct { - // Interface configuration - uint8_t iface_num; // Address of this VCP interface - uint8_t ep_in; // Address of IN endpoint (with the highest bit set) - uint8_t ep_out; // Address of OUT endpoint - uint8_t ep_cmd; // Address of CMD endpoint + uint8_t iface_num; // Address of this VCP interface + uint8_t data_iface_num; // Address of data interface of the VCP interface association + uint8_t ep_cmd; // Address of IN CMD endpoint (with the highest bit set) + uint8_t ep_in; // Address of IN endpoint (with the highest bit set) + uint8_t ep_out; // Address of OUT endpoint + uint8_t polling_interval; // In units of 1ms + uint8_t max_cmd_packet_len; + uint8_t max_data_packet_len; } usb_vcp_info_t; +// typedef struct { +// uint32_t cap; +// uint32_t read; +// uint32_t write; +// uint8_t *buf; +// } ring_buffer_t; + typedef struct { + uint8_t is_connected; + uint8_t in_idle; + // uint8_t cmd_op_code; + // uint8_t cmd_length; + + // Configuration (copied from usb_vcp_info_t on init) + uint8_t data_iface_num; + uint8_t ep_cmd; + uint8_t ep_in; + uint8_t ep_out; + uint8_t polling_interval; + uint8_t max_cmd_packet_len; + uint8_t max_data_packet_len; + const usb_vcp_descriptor_block_t *desc_block; } usb_vcp_state_t; diff --git a/micropython/trezorhal/usb_vcp-impl.h b/micropython/trezorhal/usb_vcp-impl.h index 2b195ecc7c..bad80614b4 100644 --- a/micropython/trezorhal/usb_vcp-impl.h +++ b/micropython/trezorhal/usb_vcp-impl.h @@ -1,6 +1,183 @@ +#define USB_LEN_ASSOC_DESC (0x08) + +#define USB_DESC_TYPE_ASSOCIATION (0x0b) +#define USB_DESC_TYPE_HEADER (0x00) +#define USB_DESC_TYPE_CALL_MANAGEMENT (0x01) +#define USB_DESC_TYPE_ACM (0x02) +#define USB_DESC_TYPE_UNION (0x06) + +#define USB_CDC_GET_LINE_CODING (0x21) +#define USB_CDC_SET_CONTROL_LINE_STATE (0x22) + +// static int ring_init(ring_buffer_t *b, uint8_t *buf, size_t cap) { +// if (cap == 0 || (cap & (cap - 1)) != 0) { +// return 1; // Capacity needs to be a power of 2 +// } +// b->buf = buf; +// b->cap = cap; +// b->read = 0; +// b->write = 0; +// return 0; +// } + +// static inline size_t ring_length(ring_buffer_t *b) { +// return (b->write - b->read); +// } + +// static inline int ring_empty(ring_buffer_t *b) { +// return ring_length(b) == 0; +// } + +// static inline int ring_full(ring_buffer_t *b) { +// return ring_length(b) == b->cap; +// } + +// uint32_t ring_read(ring_buffer_t *b, uint8_t *buf, uint32_t len) { +// const uint32_t mask = b->cap - 1; +// uint32_t i; +// for (i = 0; (i < len) && !ring_empty(b); i++) { +// buf[i] = b->buf[b->read & mask]; +// b->read++; +// } +// return i; +// } + +// uint32_t ring_write(ring_buffer_t *b, const uint8_t *buf, uint32_t len) { +// const uint32_t mask = b->cap - 1; +// uint32_t i; +// for (i = 0; (i < len) && !ring_full(b); i++) { +// b->buf[b->write & mask] = buf[i]; +// b->write++; +// } +// return i; +// } + /* usb_vcp_add adds and configures new USB VCP interface according to * configuration options passed in `info`. */ int usb_vcp_add(const usb_vcp_info_t *info) { + + usb_iface_t *iface = usb_get_iface(info->iface_num); + + if (iface == NULL) { + return 1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_DISABLED) { + return 1; // Interface is already enabled + } + + usb_vcp_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_vcp_descriptor_block_t)); + + if (d == NULL) { + return 1; // Not enough space in the configuration descriptor + } + + if ((info->ep_cmd & USB_EP_DIR_MSK) != USB_EP_DIR_IN) { + return 1; // CMD EP is invalid + } + if ((info->ep_in & USB_EP_DIR_MSK) != USB_EP_DIR_IN) { + return 1; // IN EP is invalid + } + if ((info->ep_out & USB_EP_DIR_MSK) != USB_EP_DIR_OUT) { + return 1; // OUT EP is invalid + } + + // Interface association descriptor + d->assoc.bLength = USB_LEN_ASSOC_DESC; + d->assoc.bDescriptorType = USB_DESC_TYPE_ASSOCIATION; + d->assoc.bFirstInterface = info->iface_num; + d->assoc.bInterfaceCount = 2; + d->assoc.bFunctionClass = 0x02; // Communication Interface Class + d->assoc.bFunctionSubClass = 0x02; // Abstract Control Model + d->assoc.bFunctionProtocol = 0x01; // Common AT commands + d->assoc.iFunction = 0x00; // Index of string descriptor describing the function + + // Interface descriptor + d->iface_cdc.bLength = USB_LEN_IF_DESC; + d->iface_cdc.bDescriptorType = USB_DESC_TYPE_INTERFACE; + d->iface_cdc.bInterfaceNumber = info->iface_num; + d->iface_cdc.bAlternateSetting = 0x00; + d->iface_cdc.bNumEndpoints = 1; + d->iface_cdc.bInterfaceClass = 0x02; // Communication Interface Class + d->iface_cdc.bInterfaceSubClass = 0x02; // Abstract Control Model + d->iface_cdc.bInterfaceProtocol = 0x01; // Common AT commands + d->iface_cdc.iInterface = 0x00; // Index of string descriptor describing the interface + + // Header Functional Descriptor + d->fheader.bFunctionLength = sizeof(usb_vcp_header_descriptor_t); + d->fheader.bDescriptorType = 0x24; // CS_INTERFACE + d->fheader.bDescriptorSubtype = 0x00; // Header Func desc + d->fheader.bcdCDC = 0x1001; // Spec release number + + // Call Management Functional Descriptor + d->fcm.bFunctionLength = sizeof(usb_vcp_cm_descriptor_t); + d->fcm.bDescriptorType = 0x24; // CS_INTERFACE + d->fcm.bDescriptorSubtype = 0x01; // Call Management Func desc + d->fcm.bmCapabilities = 0x00; // D0+D1 + d->fcm.bDataInterface = info->data_iface_num; + + // ACM Functional Descriptor + d->facm.bFunctionLength = sizeof(usb_vcp_acm_descriptor_t); + d->facm.bDescriptorType = 0x24; // CS_INTERFACE + d->facm.bDescriptorSubtype = 0x02; // Abstract Control Management desc + d->facm.bmCapabilities = 0x02; + + // Union Functional Descriptor + d->funion.bFunctionLength = sizeof(usb_vcp_union_descriptor_t); + d->funion.bDescriptorType = 0x24; // CS_INTERFACE + d->funion.bDescriptorSubtype = 0x06; // Union Func desc + d->funion.bControlInterface = info->iface_num; + d->funion.bSubordinateInterface0 = info->data_iface_num; + + // IN CMD endpoint (control) + d->ep_cmd.bLength = USB_LEN_EP_DESC; + d->ep_cmd.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_cmd.bEndpointAddress = info->ep_cmd; + d->ep_cmd.bmAttributes = USBD_EP_TYPE_INTR; + d->ep_cmd.wMaxPacketSize = info->max_cmd_packet_len; + d->ep_cmd.bInterval = info->polling_interval; + + // Interface descriptor + d->iface_data.bLength = USB_LEN_IF_DESC; + d->iface_data.bDescriptorType = USB_DESC_TYPE_INTERFACE; + d->iface_data.bInterfaceNumber = info->data_iface_num; + d->iface_data.bAlternateSetting = 0x00; + d->iface_data.bNumEndpoints = 2; + d->iface_data.bInterfaceClass = 0x0A; // CDC + d->iface_data.bInterfaceSubClass = 0x00; + d->iface_data.bInterfaceProtocol = 0x00; + d->iface_data.iInterface = 0x00; // Index of string descriptor describing the interface + + // OUT endpoint (receiving) + d->ep_out.bLength = USB_LEN_EP_DESC; + d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_out.bEndpointAddress = info->ep_out; + d->ep_out.bmAttributes = USBD_EP_TYPE_BULK; + d->ep_out.wMaxPacketSize = info->max_data_packet_len; + d->ep_out.bInterval = 0x00; // Ignored for bulk endpoints + + // IN endpoint (sending) + d->ep_in.bLength = USB_LEN_EP_DESC; + d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_in.bEndpointAddress = info->ep_in; + d->ep_in.bmAttributes = USBD_EP_TYPE_BULK; + d->ep_in.wMaxPacketSize = info->max_data_packet_len; + d->ep_in.bInterval = 0x00; // Ignored for bulk endpoints + + // Config descriptor + // TODO: do this in a clean way + usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t)); + usb_config_desc->bNumInterfaces++; + + // Interface state + iface->type = USB_IFACE_TYPE_VCP; + iface->vcp.data_iface_num = info->data_iface_num; + iface->vcp.ep_cmd = info->ep_cmd; + iface->vcp.ep_in = info->ep_in; + iface->vcp.ep_out = info->ep_out; + iface->vcp.max_cmd_packet_len = info->max_cmd_packet_len; + iface->vcp.max_data_packet_len = info->max_data_packet_len; + iface->vcp.desc_block = d; + return 0; } @@ -9,15 +186,54 @@ int usb_vcp_can_read(uint8_t iface_num) { } int usb_vcp_can_write(uint8_t iface_num) { - return 0; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return 0; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return 0; // Invalid interface type + } + if (iface->vcp.in_idle == 0) { + return 0; // Last transmission is not over yet + } + if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { + return 0; // Device is not configured + } + return 1; } int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return -2; // Interface interface type + } + // usb_vcp_state_t *state = &iface->vcp; + // TODO + return 0; } int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { - return 0; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return -2; // Interface interface type + } + usb_vcp_state_t *state = &iface->vcp; + + if (!state->is_connected) { + return 0; + } + + state->in_idle = 0; + USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len); + + return len; } int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, uint32_t timeout) { @@ -35,29 +251,77 @@ int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, uint32_t start = HAL_GetTick(); while (!usb_vcp_can_write(iface_num)) { if (HAL_GetTick() - start >= timeout) { - return 0; // Timeout + return 0; // Timeout } - __WFI(); // Enter sleep mode, waiting for interrupt + __WFI(); // Enter sleep mode, waiting for interrupt } return usb_vcp_write(iface_num, buf, len); } static int usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t cfg_idx) { + // Open endpoints + USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_BULK, state->max_data_packet_len); + USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_BULK, state->max_data_packet_len); + USBD_LL_OpenEP(dev, state->ep_cmd, USBD_EP_TYPE_INTR, state->max_cmd_packet_len); + + // Reset the state + state->in_idle = 1; + + // TODO + // Prepare the OUT EP to receive next packet + // USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, state->max_data_packet_len); + return USBD_OK; } static int usb_vcp_class_deinit(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t cfg_idx) { + // Close endpoints + USBD_LL_CloseEP(dev, state->ep_in); + USBD_LL_CloseEP(dev, state->ep_out); + USBD_LL_CloseEP(dev, state->ep_cmd); + return USBD_OK; } static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, USBD_SetupReqTypedef *req) { + static const uint8_t line_coding[] = { + (uint8_t)(115200 >> 0), + (uint8_t)(115200 >> 8), + (uint8_t)(115200 >> 16), + (uint8_t)(115200 >> 24), + 0, // Stop bits + 0, // Parity + 8, // Number of bits + }; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) { + + // Class request + case USB_REQ_TYPE_CLASS : + switch (req->bRequest) { + + case USB_CDC_GET_LINE_CODING: + USBD_CtlSendData(dev, UNCONST(line_coding), sizeof(line_coding)); + break; + + case USB_CDC_SET_CONTROL_LINE_STATE: + state->is_connected = req->wLength & 1; + break; + } + break; + } + return USBD_OK; } static uint8_t usb_vcp_class_data_in(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) { + if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { + state->in_idle = 1; + } return USBD_OK; } static uint8_t usb_vcp_class_data_out(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) { + // TODO: process received data return USBD_OK; } diff --git a/micropython/trezorhal/usbd_conf.c b/micropython/trezorhal/usbd_conf.c index 1da987d89a..a820fd9047 100644 --- a/micropython/trezorhal/usbd_conf.c +++ b/micropython/trezorhal/usbd_conf.c @@ -20,8 +20,8 @@ * * http://www.st.com/software_license_agreement_liberty_v2 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. @@ -60,19 +60,19 @@ PCD_HandleTypeDef pcd_hs_handle; void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { GPIO_InitTypeDef GPIO_InitStruct; - + if(hpcd->Instance == USB_OTG_FS) { /* Configure USB FS GPIOs */ __GPIOA_CLK_ENABLE(); - + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + /* Configure VBUS Pin */ #if defined(MICROPY_HW_USB_VBUS_DETECT_PIN) // USB VBUS detect pin is always A9 @@ -81,19 +81,19 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); #endif - + #if defined(MICROPY_HW_USB_OTG_ID_PIN) // USB ID pin is always A10 GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); #endif - /* Enable USB FS Clocks */ + /* Enable USB FS Clocks */ __USB_OTG_FS_CLK_ENABLE(); - + #if defined (MCU_SERIES_L4) /* Enable VDDUSB */ if(__HAL_RCC_PWR_IS_CLK_DISABLED()) @@ -110,10 +110,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) /* Set USBFS Interrupt priority */ HAL_NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS, IRQ_SUBPRI_OTG_FS); - + /* Enable USBFS Interrupt */ HAL_NVIC_EnableIRQ(OTG_FS_IRQn); - } + } #if defined(USE_USB_HS) else if(hpcd->Instance == USB_OTG_HS) { @@ -166,63 +166,63 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) __GPIOC_CLK_ENABLE(); __GPIOH_CLK_ENABLE(); __GPIOI_CLK_ENABLE(); - + /* CLK */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + /* D0 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + /* D1 D2 D3 D4 D5 D6 D7 */ GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 |\ GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - /* STP */ + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* STP */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - /* NXT */ + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* NXT */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + /* DIR */ GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); - + /* Enable USB HS Clocks */ __USB_OTG_HS_CLK_ENABLE(); __USB_OTG_HS_ULPI_CLK_ENABLE(); #endif // !USE_USB_HS_IN_FS - + /* Set USBHS Interrupt to the lowest priority */ HAL_NVIC_SetPriority(OTG_HS_IRQn, IRQ_PRI_OTG_HS, IRQ_SUBPRI_OTG_HS); - + /* Enable USBHS Interrupt */ HAL_NVIC_EnableIRQ(OTG_HS_IRQn); - } + } #endif // USE_USB_HS } /** @@ -233,18 +233,18 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { if(hpcd->Instance == USB_OTG_FS) - { - /* Disable USB FS Clocks */ + { + /* Disable USB FS Clocks */ __USB_OTG_FS_CLK_DISABLE(); - __SYSCFG_CLK_DISABLE(); + __SYSCFG_CLK_DISABLE(); } #if defined(USE_USB_HS) else if(hpcd->Instance == USB_OTG_HS) - { - /* Disable USB FS Clocks */ + { + /* Disable USB FS Clocks */ __USB_OTG_HS_CLK_DISABLE(); - __SYSCFG_CLK_DISABLE(); - } + __SYSCFG_CLK_DISABLE(); + } #endif } @@ -290,13 +290,10 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) * @param hpcd: PCD handle * @retval None */ -/* -This is now handled by the USB CDC interface. void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_SOF(hpcd->pData); } -*/ /** * @brief Reset callback. @@ -304,7 +301,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) * @retval None */ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) -{ +{ USBD_SpeedTypeDef speed = USBD_SPEED_FULL; /* Set USB Current Speed */ @@ -315,17 +312,17 @@ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) speed = USBD_SPEED_HIGH; break; #endif - + case PCD_SPEED_FULL: - speed = USBD_SPEED_FULL; + speed = USBD_SPEED_FULL; break; - + default: - speed = USBD_SPEED_FULL; + speed = USBD_SPEED_FULL; break; } - USBD_LL_SetSpeed(hpcd->pData, speed); - + USBD_LL_SetSpeed(hpcd->pData, speed); + /* Reset Device */ USBD_LL_Reset(hpcd->pData); } @@ -353,7 +350,7 @@ void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) /** * @brief ISOC Out Incomplete callback. * @param hpcd: PCD handle - * @param epnum: Endpoint Number + * @param epnum: Endpoint Number * @retval None */ void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) @@ -364,7 +361,7 @@ void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) /** * @brief ISOC In Incomplete callback. * @param hpcd: PCD handle - * @param epnum: Endpoint Number + * @param epnum: Endpoint Number * @retval None */ void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) @@ -396,12 +393,12 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) LL Driver Interface (USB Device Library --> PCD) *******************************************************************************/ /** - * @brief Initializes the Low Level portion of the Device driver. + * @brief Initializes the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev) -{ +{ #if defined(USE_USB_FS) if (pdev->id == USB_PHY_FS_ID) { @@ -473,14 +470,14 @@ if (pdev->id == USB_PHY_HS_ID) pcd_hs_handle.Init.dev_endpoints = 6; pcd_hs_handle.Init.use_dedicated_ep1 = 0; pcd_hs_handle.Init.ep0_mps = 0x40; - + /* Be aware that enabling USB-DMA mode will result in data being sent only by multiple of 4 packet sizes. This is due to the fact that USB-DMA does not allow sending data from non word-aligned addresses. For this specific application, it is advised to not enable this option unless required. */ pcd_hs_handle.Init.dma_enable = 0; - + pcd_hs_handle.Init.low_power_enable = 0; pcd_hs_handle.Init.phy_itface = PCD_PHY_ULPI; pcd_hs_handle.Init.Sof_enable = 1; @@ -491,7 +488,7 @@ if (pdev->id == USB_PHY_HS_ID) pdev->pData = &pcd_hs_handle; /*Initialize LL Driver */ HAL_PCD_Init(&pcd_hs_handle); - + HAL_PCD_SetRxFiFo(&pcd_hs_handle, 0x200); HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 0x80); HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 0x174); @@ -503,25 +500,25 @@ if (pdev->id == USB_PHY_HS_ID) } /** - * @brief De-Initializes the Low Level portion of the Device driver. + * @brief De-Initializes the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) { HAL_PCD_DeInit(pdev->pData); - return USBD_OK; + return USBD_OK; } /** - * @brief Starts the Low Level portion of the Device driver. + * @brief Starts the Low Level portion of the Device driver. * @param pdev: Device handle * @retval USBD Status */ USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) { HAL_PCD_Start(pdev->pData); - return USBD_OK; + return USBD_OK; } /** @@ -532,159 +529,159 @@ USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) { HAL_PCD_Stop(pdev->pData); - return USBD_OK; + return USBD_OK; } /** - * @brief Opens an endpoint of the Low Level Driver. + * @brief Opens an endpoint of the Low Level Driver. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @param ep_type: Endpoint Type - * @param ep_mps: Endpoint Max Packet Size + * @param ep_mps: Endpoint Max Packet Size * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, - uint8_t ep_addr, +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) { HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); - return USBD_OK; + return USBD_OK; } /** - * @brief Closes an endpoint of the Low Level Driver. + * @brief Closes an endpoint of the Low Level Driver. * @param pdev: Device handle - * @param ep_addr: Endpoint Number + * @param ep_addr: Endpoint Number * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_Close(pdev->pData, ep_addr); - return USBD_OK; + return USBD_OK; } /** * @brief Flushes an endpoint of the Low Level Driver. * @param pdev: Device handle - * @param ep_addr: Endpoint Number + * @param ep_addr: Endpoint Number * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_Flush(pdev->pData, ep_addr); - return USBD_OK; + return USBD_OK; } /** * @brief Sets a Stall condition on an endpoint of the Low Level Driver. * @param pdev: Device handle - * @param ep_addr: Endpoint Number + * @param ep_addr: Endpoint Number * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { HAL_PCD_EP_SetStall(pdev->pData, ep_addr); - return USBD_OK; + return USBD_OK; } /** * @brief Clears a Stall condition on an endpoint of the Low Level Driver. * @param pdev: Device handle - * @param ep_addr: Endpoint Number + * @param ep_addr: Endpoint Number * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); - return USBD_OK; + HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); + return USBD_OK; } /** * @brief Returns Stall condition. * @param pdev: Device handle - * @param ep_addr: Endpoint Number + * @param ep_addr: Endpoint Number * @retval Stall (1: yes, 0: No) */ -uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { - PCD_HandleTypeDef *hpcd = pdev->pData; - + PCD_HandleTypeDef *hpcd = pdev->pData; + if((ep_addr & 0x80) == 0x80) { - return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + return hpcd->IN_ep[ep_addr & 0x7F].is_stall; } else { - return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; + return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; } } /** * @brief Assigns an USB address to the device * @param pdev: Device handle - * @param dev_addr: USB address + * @param dev_addr: USB address * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { HAL_PCD_SetAddress(pdev->pData, dev_addr); - return USBD_OK; + return USBD_OK; } /** - * @brief Transmits data over an endpoint + * @brief Transmits data over an endpoint * @param pdev: Device handle * @param ep_addr: Endpoint Number - * @param pbuf: Pointer to data to be sent - * @param size: Data size + * @param pbuf: Pointer to data to be sent + * @param size: Data size * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, - uint8_t ep_addr, +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, uint8_t *pbuf, uint16_t size) { HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); - return USBD_OK; + return USBD_OK; } /** - * @brief Prepares an endpoint for reception + * @brief Prepares an endpoint for reception * @param pdev: Device handle * @param ep_addr: Endpoint Number - * @param pbuf:pointer to data to be received - * @param size: data size + * @param pbuf:pointer to data to be received + * @param size: data size * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, - uint8_t ep_addr, +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, uint8_t *pbuf, uint16_t size) { HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); - return USBD_OK; + return USBD_OK; } /** - * @brief Returns the last transfered packet size. + * @brief Returns the last transfered packet size. * @param pdev: Device handle * @param ep_addr: Endpoint Number * @retval Recived Data Size */ -uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr); } /** - * @brief Delay routine for the USB Device Library + * @brief Delay routine for the USB Device Library * @param Delay: Delay in ms * @retval None */ void USBD_LL_Delay(uint32_t Delay) { - HAL_Delay(Delay); + HAL_Delay(Delay); } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/