mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
trezorhal: add cdc vcp tx
TODO: rx support TODO: buffering TODO: cleanup
This commit is contained in:
parent
e87d0d3905
commit
38b99b306a
@ -24,27 +24,37 @@
|
|||||||
|
|
||||||
int usb_init_all(void) {
|
int usb_init_all(void) {
|
||||||
static const usb_dev_info_t dev_info = {
|
static const usb_dev_info_t dev_info = {
|
||||||
.vendor_id = 0x1209,
|
.vendor_id = 0x1209,
|
||||||
.product_id = 0x53C1,
|
.product_id = 0x53C1,
|
||||||
.release_num = 0x0002,
|
.release_num = 0x0002,
|
||||||
.product_str = (uint8_t *)"product_str",
|
.product_str = (uint8_t *)"product_str",
|
||||||
.manufacturer_str = (uint8_t *)"manufacturer_str",
|
.manufacturer_str = (uint8_t *)"manufacturer_str",
|
||||||
.serial_number_str = (uint8_t *)"serial_number_str",
|
.serial_number_str = (uint8_t *)"serial_number_str",
|
||||||
.configuration_str = (uint8_t *)"configuration_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 = {
|
static const usb_hid_info_t hid_info = {
|
||||||
.iface_num = 0,
|
.iface_num = 0x00,
|
||||||
.ep_in = 0x81,
|
.ep_in = 0x81,
|
||||||
.ep_out = 0x01,
|
.ep_out = 0x01,
|
||||||
.subclass = 0,
|
.subclass = 0,
|
||||||
.protocol = 0,
|
.protocol = 0,
|
||||||
.rx_buffer = rx_buffer,
|
.rx_buffer = hid_rx_buffer,
|
||||||
.max_packet_len = sizeof(rx_buffer),
|
.max_packet_len = sizeof(hid_rx_buffer),
|
||||||
.polling_interval = 1,
|
.polling_interval = 1,
|
||||||
.report_desc_len = 34,
|
.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 = (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)) {
|
if (0 != usb_init(&dev_info)) {
|
||||||
@ -53,6 +63,9 @@ int usb_init_all(void) {
|
|||||||
if (0 != usb_hid_add(&hid_info)) {
|
if (0 != usb_hid_add(&hid_info)) {
|
||||||
__fatal_error("usb_hid_add failed");
|
__fatal_error("usb_hid_add failed");
|
||||||
}
|
}
|
||||||
|
if (0 != usb_vcp_add(&vcp_info)) {
|
||||||
|
__fatal_error("usb_vcp_add failed");
|
||||||
|
}
|
||||||
if (0 != usb_start()) {
|
if (0 != usb_start()) {
|
||||||
__fatal_error("usb_start failed");
|
__fatal_error("usb_start failed");
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
|
#include "usb.h"
|
||||||
|
|
||||||
// void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len);
|
#define VCP_IFACE 0x01
|
||||||
// int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout);
|
#define VCP_WRITE_TIMEOUT 25
|
||||||
|
|
||||||
int mp_hal_stdin_rx_chr(void) {
|
int mp_hal_stdin_rx_chr(void) {
|
||||||
for (;;) {
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,17 @@ typedef struct __attribute__((packed)) {
|
|||||||
uint8_t iInterface;
|
uint8_t iInterface;
|
||||||
} usb_interface_descriptor_t;
|
} 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)) {
|
typedef struct __attribute__((packed)) {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
uint8_t bDescriptorType;
|
uint8_t bDescriptorType;
|
||||||
|
@ -1,23 +1,79 @@
|
|||||||
typedef struct __attribute__((packed)) {
|
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)) {
|
typedef struct __attribute__((packed)) {
|
||||||
usb_interface_descriptor_t iface;
|
uint8_t bFunctionLength;
|
||||||
usb_vcp_descriptor_t vcp;
|
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_in;
|
||||||
usb_endpoint_descriptor_t ep_out;
|
usb_endpoint_descriptor_t ep_out;
|
||||||
usb_endpoint_descriptor_t ep_cmd;
|
|
||||||
} usb_vcp_descriptor_block_t;
|
} usb_vcp_descriptor_block_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// Interface configuration
|
uint8_t iface_num; // Address of this VCP interface
|
||||||
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_in; // Address of IN endpoint (with the highest bit set)
|
uint8_t ep_cmd; // Address of IN CMD endpoint (with the highest bit set)
|
||||||
uint8_t ep_out; // Address of OUT endpoint
|
uint8_t ep_in; // Address of IN endpoint (with the highest bit set)
|
||||||
uint8_t ep_cmd; // Address of CMD endpoint
|
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;
|
} usb_vcp_info_t;
|
||||||
|
|
||||||
|
// typedef struct {
|
||||||
|
// uint32_t cap;
|
||||||
|
// uint32_t read;
|
||||||
|
// uint32_t write;
|
||||||
|
// uint8_t *buf;
|
||||||
|
// } ring_buffer_t;
|
||||||
|
|
||||||
typedef struct {
|
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;
|
const usb_vcp_descriptor_block_t *desc_block;
|
||||||
} usb_vcp_state_t;
|
} usb_vcp_state_t;
|
||||||
|
|
||||||
|
@ -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
|
/* usb_vcp_add adds and configures new USB VCP interface according to
|
||||||
* configuration options passed in `info`. */
|
* configuration options passed in `info`. */
|
||||||
int usb_vcp_add(const usb_vcp_info_t *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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9,15 +186,54 @@ int usb_vcp_can_read(uint8_t iface_num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int usb_vcp_can_write(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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
|
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) {
|
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();
|
uint32_t start = HAL_GetTick();
|
||||||
while (!usb_vcp_can_write(iface_num)) {
|
while (!usb_vcp_can_write(iface_num)) {
|
||||||
if (HAL_GetTick() - start >= timeout) {
|
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);
|
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) {
|
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;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_vcp_class_deinit(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t cfg_idx) {
|
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;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, USBD_SetupReqTypedef *req) {
|
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;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t usb_vcp_class_data_in(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) {
|
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;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t usb_vcp_class_data_out(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) {
|
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;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
*
|
*
|
||||||
* http://www.st.com/software_license_agreement_liberty_v2
|
* http://www.st.com/software_license_agreement_liberty_v2
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
@ -60,19 +60,19 @@ PCD_HandleTypeDef pcd_hs_handle;
|
|||||||
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||||
{
|
{
|
||||||
GPIO_InitTypeDef GPIO_InitStruct;
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
|
|
||||||
if(hpcd->Instance == USB_OTG_FS)
|
if(hpcd->Instance == USB_OTG_FS)
|
||||||
{
|
{
|
||||||
/* Configure USB FS GPIOs */
|
/* Configure USB FS GPIOs */
|
||||||
__GPIOA_CLK_ENABLE();
|
__GPIOA_CLK_ENABLE();
|
||||||
|
|
||||||
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
|
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* Configure VBUS Pin */
|
/* Configure VBUS Pin */
|
||||||
#if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
|
#if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
|
||||||
// USB VBUS detect pin is always A9
|
// USB VBUS detect pin is always A9
|
||||||
@ -81,19 +81,19 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
|||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MICROPY_HW_USB_OTG_ID_PIN)
|
#if defined(MICROPY_HW_USB_OTG_ID_PIN)
|
||||||
// USB ID pin is always A10
|
// USB ID pin is always A10
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_10;
|
GPIO_InitStruct.Pin = GPIO_PIN_10;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Enable USB FS Clocks */
|
/* Enable USB FS Clocks */
|
||||||
__USB_OTG_FS_CLK_ENABLE();
|
__USB_OTG_FS_CLK_ENABLE();
|
||||||
|
|
||||||
#if defined (MCU_SERIES_L4)
|
#if defined (MCU_SERIES_L4)
|
||||||
/* Enable VDDUSB */
|
/* Enable VDDUSB */
|
||||||
if(__HAL_RCC_PWR_IS_CLK_DISABLED())
|
if(__HAL_RCC_PWR_IS_CLK_DISABLED())
|
||||||
@ -110,10 +110,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
|||||||
|
|
||||||
/* Set USBFS Interrupt priority */
|
/* Set USBFS Interrupt priority */
|
||||||
HAL_NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS, IRQ_SUBPRI_OTG_FS);
|
HAL_NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS, IRQ_SUBPRI_OTG_FS);
|
||||||
|
|
||||||
/* Enable USBFS Interrupt */
|
/* Enable USBFS Interrupt */
|
||||||
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
|
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||||
}
|
}
|
||||||
#if defined(USE_USB_HS)
|
#if defined(USE_USB_HS)
|
||||||
else if(hpcd->Instance == USB_OTG_HS)
|
else if(hpcd->Instance == USB_OTG_HS)
|
||||||
{
|
{
|
||||||
@ -166,63 +166,63 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
|||||||
__GPIOC_CLK_ENABLE();
|
__GPIOC_CLK_ENABLE();
|
||||||
__GPIOH_CLK_ENABLE();
|
__GPIOH_CLK_ENABLE();
|
||||||
__GPIOI_CLK_ENABLE();
|
__GPIOI_CLK_ENABLE();
|
||||||
|
|
||||||
/* CLK */
|
/* CLK */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_5;
|
GPIO_InitStruct.Pin = GPIO_PIN_5;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
||||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* D0 */
|
/* D0 */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_3;
|
GPIO_InitStruct.Pin = GPIO_PIN_3;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
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 */
|
/* D1 D2 D3 D4 D5 D6 D7 */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 |\
|
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_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
||||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* STP */
|
/* STP */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_0;
|
GPIO_InitStruct.Pin = GPIO_PIN_0;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
||||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* NXT */
|
/* NXT */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_4;
|
GPIO_InitStruct.Pin = GPIO_PIN_4;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
||||||
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* DIR */
|
/* DIR */
|
||||||
GPIO_InitStruct.Pin = GPIO_PIN_11;
|
GPIO_InitStruct.Pin = GPIO_PIN_11;
|
||||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||||
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
|
||||||
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
|
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
|
||||||
|
|
||||||
/* Enable USB HS Clocks */
|
/* Enable USB HS Clocks */
|
||||||
__USB_OTG_HS_CLK_ENABLE();
|
__USB_OTG_HS_CLK_ENABLE();
|
||||||
__USB_OTG_HS_ULPI_CLK_ENABLE();
|
__USB_OTG_HS_ULPI_CLK_ENABLE();
|
||||||
#endif // !USE_USB_HS_IN_FS
|
#endif // !USE_USB_HS_IN_FS
|
||||||
|
|
||||||
/* Set USBHS Interrupt to the lowest priority */
|
/* Set USBHS Interrupt to the lowest priority */
|
||||||
HAL_NVIC_SetPriority(OTG_HS_IRQn, IRQ_PRI_OTG_HS, IRQ_SUBPRI_OTG_HS);
|
HAL_NVIC_SetPriority(OTG_HS_IRQn, IRQ_PRI_OTG_HS, IRQ_SUBPRI_OTG_HS);
|
||||||
|
|
||||||
/* Enable USBHS Interrupt */
|
/* Enable USBHS Interrupt */
|
||||||
HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
|
HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
|
||||||
}
|
}
|
||||||
#endif // USE_USB_HS
|
#endif // USE_USB_HS
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -233,18 +233,18 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
|||||||
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
|
void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
|
||||||
{
|
{
|
||||||
if(hpcd->Instance == USB_OTG_FS)
|
if(hpcd->Instance == USB_OTG_FS)
|
||||||
{
|
{
|
||||||
/* Disable USB FS Clocks */
|
/* Disable USB FS Clocks */
|
||||||
__USB_OTG_FS_CLK_DISABLE();
|
__USB_OTG_FS_CLK_DISABLE();
|
||||||
__SYSCFG_CLK_DISABLE();
|
__SYSCFG_CLK_DISABLE();
|
||||||
}
|
}
|
||||||
#if defined(USE_USB_HS)
|
#if defined(USE_USB_HS)
|
||||||
else if(hpcd->Instance == USB_OTG_HS)
|
else if(hpcd->Instance == USB_OTG_HS)
|
||||||
{
|
{
|
||||||
/* Disable USB FS Clocks */
|
/* Disable USB FS Clocks */
|
||||||
__USB_OTG_HS_CLK_DISABLE();
|
__USB_OTG_HS_CLK_DISABLE();
|
||||||
__SYSCFG_CLK_DISABLE();
|
__SYSCFG_CLK_DISABLE();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,13 +290,10 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
|||||||
* @param hpcd: PCD handle
|
* @param hpcd: PCD handle
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
This is now handled by the USB CDC interface.
|
|
||||||
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
||||||
{
|
{
|
||||||
USBD_LL_SOF(hpcd->pData);
|
USBD_LL_SOF(hpcd->pData);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset callback.
|
* @brief Reset callback.
|
||||||
@ -304,7 +301,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
|||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||||
{
|
{
|
||||||
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
|
USBD_SpeedTypeDef speed = USBD_SPEED_FULL;
|
||||||
|
|
||||||
/* Set USB Current Speed */
|
/* Set USB Current Speed */
|
||||||
@ -315,17 +312,17 @@ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
|||||||
speed = USBD_SPEED_HIGH;
|
speed = USBD_SPEED_HIGH;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case PCD_SPEED_FULL:
|
case PCD_SPEED_FULL:
|
||||||
speed = USBD_SPEED_FULL;
|
speed = USBD_SPEED_FULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
speed = USBD_SPEED_FULL;
|
speed = USBD_SPEED_FULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
USBD_LL_SetSpeed(hpcd->pData, speed);
|
USBD_LL_SetSpeed(hpcd->pData, speed);
|
||||||
|
|
||||||
/* Reset Device */
|
/* Reset Device */
|
||||||
USBD_LL_Reset(hpcd->pData);
|
USBD_LL_Reset(hpcd->pData);
|
||||||
}
|
}
|
||||||
@ -353,7 +350,7 @@ void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
|
|||||||
/**
|
/**
|
||||||
* @brief ISOC Out Incomplete callback.
|
* @brief ISOC Out Incomplete callback.
|
||||||
* @param hpcd: PCD handle
|
* @param hpcd: PCD handle
|
||||||
* @param epnum: Endpoint Number
|
* @param epnum: Endpoint Number
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
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.
|
* @brief ISOC In Incomplete callback.
|
||||||
* @param hpcd: PCD handle
|
* @param hpcd: PCD handle
|
||||||
* @param epnum: Endpoint Number
|
* @param epnum: Endpoint Number
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
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)
|
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
|
* @param pdev: Device handle
|
||||||
* @retval USBD Status
|
* @retval USBD Status
|
||||||
*/
|
*/
|
||||||
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
|
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
#if defined(USE_USB_FS)
|
#if defined(USE_USB_FS)
|
||||||
if (pdev->id == USB_PHY_FS_ID)
|
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.dev_endpoints = 6;
|
||||||
pcd_hs_handle.Init.use_dedicated_ep1 = 0;
|
pcd_hs_handle.Init.use_dedicated_ep1 = 0;
|
||||||
pcd_hs_handle.Init.ep0_mps = 0x40;
|
pcd_hs_handle.Init.ep0_mps = 0x40;
|
||||||
|
|
||||||
/* Be aware that enabling USB-DMA mode will result in data being sent only by
|
/* 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
|
multiple of 4 packet sizes. This is due to the fact that USB-DMA does
|
||||||
not allow sending data from non word-aligned addresses.
|
not allow sending data from non word-aligned addresses.
|
||||||
For this specific application, it is advised to not enable this option
|
For this specific application, it is advised to not enable this option
|
||||||
unless required. */
|
unless required. */
|
||||||
pcd_hs_handle.Init.dma_enable = 0;
|
pcd_hs_handle.Init.dma_enable = 0;
|
||||||
|
|
||||||
pcd_hs_handle.Init.low_power_enable = 0;
|
pcd_hs_handle.Init.low_power_enable = 0;
|
||||||
pcd_hs_handle.Init.phy_itface = PCD_PHY_ULPI;
|
pcd_hs_handle.Init.phy_itface = PCD_PHY_ULPI;
|
||||||
pcd_hs_handle.Init.Sof_enable = 1;
|
pcd_hs_handle.Init.Sof_enable = 1;
|
||||||
@ -491,7 +488,7 @@ if (pdev->id == USB_PHY_HS_ID)
|
|||||||
pdev->pData = &pcd_hs_handle;
|
pdev->pData = &pcd_hs_handle;
|
||||||
/*Initialize LL Driver */
|
/*Initialize LL Driver */
|
||||||
HAL_PCD_Init(&pcd_hs_handle);
|
HAL_PCD_Init(&pcd_hs_handle);
|
||||||
|
|
||||||
HAL_PCD_SetRxFiFo(&pcd_hs_handle, 0x200);
|
HAL_PCD_SetRxFiFo(&pcd_hs_handle, 0x200);
|
||||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 0x80);
|
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 0x80);
|
||||||
HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 0x174);
|
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
|
* @param pdev: Device handle
|
||||||
* @retval USBD Status
|
* @retval USBD Status
|
||||||
*/
|
*/
|
||||||
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
|
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
HAL_PCD_DeInit(pdev->pData);
|
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
|
* @param pdev: Device handle
|
||||||
* @retval USBD Status
|
* @retval USBD Status
|
||||||
*/
|
*/
|
||||||
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
|
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
HAL_PCD_Start(pdev->pData);
|
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)
|
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
|
||||||
{
|
{
|
||||||
HAL_PCD_Stop(pdev->pData);
|
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 pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @param ep_type: Endpoint Type
|
* @param ep_type: Endpoint Type
|
||||||
* @param ep_mps: Endpoint Max Packet Size
|
* @param ep_mps: Endpoint Max Packet Size
|
||||||
* @retval USBD Status
|
* @retval USBD Status
|
||||||
*/
|
*/
|
||||||
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
|
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
|
||||||
uint8_t ep_addr,
|
uint8_t ep_addr,
|
||||||
uint8_t ep_type,
|
uint8_t ep_type,
|
||||||
uint16_t ep_mps)
|
uint16_t ep_mps)
|
||||||
{
|
{
|
||||||
HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);
|
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 pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @retval USBD Status
|
* @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);
|
HAL_PCD_EP_Close(pdev->pData, ep_addr);
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Flushes an endpoint of the Low Level Driver.
|
* @brief Flushes an endpoint of the Low Level Driver.
|
||||||
* @param pdev: Device handle
|
* @param pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @retval USBD Status
|
* @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);
|
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.
|
* @brief Sets a Stall condition on an endpoint of the Low Level Driver.
|
||||||
* @param pdev: Device handle
|
* @param pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @retval USBD Status
|
* @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);
|
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.
|
* @brief Clears a Stall condition on an endpoint of the Low Level Driver.
|
||||||
* @param pdev: Device handle
|
* @param pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @retval USBD Status
|
* @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);
|
HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);
|
||||||
return USBD_OK;
|
return USBD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns Stall condition.
|
* @brief Returns Stall condition.
|
||||||
* @param pdev: Device handle
|
* @param pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @retval Stall (1: yes, 0: No)
|
* @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)
|
if((ep_addr & 0x80) == 0x80)
|
||||||
{
|
{
|
||||||
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
|
return hpcd->IN_ep[ep_addr & 0x7F].is_stall;
|
||||||
}
|
}
|
||||||
else
|
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
|
* @brief Assigns an USB address to the device
|
||||||
* @param pdev: Device handle
|
* @param pdev: Device handle
|
||||||
* @param dev_addr: USB address
|
* @param dev_addr: USB address
|
||||||
* @retval USBD Status
|
* @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);
|
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 pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @param pbuf: Pointer to data to be sent
|
* @param pbuf: Pointer to data to be sent
|
||||||
* @param size: Data size
|
* @param size: Data size
|
||||||
* @retval USBD Status
|
* @retval USBD Status
|
||||||
*/
|
*/
|
||||||
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,
|
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev,
|
||||||
uint8_t ep_addr,
|
uint8_t ep_addr,
|
||||||
uint8_t *pbuf,
|
uint8_t *pbuf,
|
||||||
uint16_t size)
|
uint16_t size)
|
||||||
{
|
{
|
||||||
HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, 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 pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @param pbuf:pointer to data to be received
|
* @param pbuf:pointer to data to be received
|
||||||
* @param size: data size
|
* @param size: data size
|
||||||
* @retval USBD Status
|
* @retval USBD Status
|
||||||
*/
|
*/
|
||||||
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
|
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev,
|
||||||
uint8_t ep_addr,
|
uint8_t ep_addr,
|
||||||
uint8_t *pbuf,
|
uint8_t *pbuf,
|
||||||
uint16_t size)
|
uint16_t size)
|
||||||
{
|
{
|
||||||
HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, 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 pdev: Device handle
|
||||||
* @param ep_addr: Endpoint Number
|
* @param ep_addr: Endpoint Number
|
||||||
* @retval Recived Data Size
|
* @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);
|
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
|
* @param Delay: Delay in ms
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void USBD_LL_Delay(uint32_t Delay)
|
void USBD_LL_Delay(uint32_t Delay)
|
||||||
{
|
{
|
||||||
HAL_Delay(Delay);
|
HAL_Delay(Delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||||
|
Loading…
Reference in New Issue
Block a user