This commit is contained in:
lmx
2025-10-29 13:10:02 +08:00
commit 49a07fa419
2284 changed files with 642060 additions and 0 deletions

View File

@ -0,0 +1,490 @@
#include "usb/device/usb_stack.h"
#include "usb/usb_config.h"
#include "usb/device/cdc.h"
#include "app_config.h"
#include "os/os_api.h"
#include "cdc_defs.h" //need redefine __u8, __u16, __u32
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_SLAVE_CDC_ENABLE
struct usb_cdc_gadget {
u8 *cdc_buffer;
u8 *bulk_ep_out_buffer;
u8 *bulk_ep_in_buffer;
void *priv;
int (*output)(void *priv, u8 *obuf, u32 olen);
void (*wakeup_handler)(struct usb_device_t *usb_device);
OS_MUTEX mutex_data;
#if CDC_INTR_EP_ENABLE
OS_MUTEX mutex_intr;
u8 *intr_ep_in_buffer;
#endif
u8 bmTransceiver;
u8 subtype_data[8];
};
static struct usb_cdc_gadget *cdc_hdl;
#if USB_MALLOC_ENABLE
#else
static u8 _cdc_buffer[MAXP_SIZE_CDC_BULKOUT] SEC(.cdc_var) __attribute__((aligned(4)));
static struct usb_cdc_gadget _cdc_hdl SEC(.cdc_var);
#endif
static const u8 cdc_virtual_comport_desc[] = {
//IAD Descriptor
0x08, //bLength
0x0b, //bDescriptorType
0x00, //bFirstInterface
0x02, //bInterfaceCount
0x02, //bFunctionClass, Comunication and CDC control
0x02, //bFunctionSubClass
0x01, //bFunctionProtocol
0x00, //iFunction
//Interface 0, Alt 0
0x09, //Length
0x04, //DescriptorType:Interface
0x00, //InterfaceNum
0x00, //AlternateSetting
0x01, //NumEndpoint
0x02, //InterfaceClass, Communation and CDC control
0x02, //InterfaceSubClass, Abstract Control Model
0x01, //InterfaceProtocol, AT commands defined by ITU-T V.250 etc
0x00, //Interface String
//CDC Interface Descriptor
0x05, //bLength
0x24, //bDescriptorType
0x00, //bDescriptorSubType, Header Functional Desc
0x10, 0x01, //bcdCDC, version 1.10
//CDC Interface Descriptor
0x05, //bLength
0x24, //bDescriptorType
0x01, //bDescriptorSubType, Call Management Functional Descriptor
0x03, //bmCapabilities, D7..D2 reversed
// D7..D2 reversed
// D1 sends/receives call management information only over a Data Class interface
// D0 handle call management itself
0x01, //bDataInterface
//CDC Interface Descriptor
0x04, //bLength
0x24, //bDescriptorType
0x02, //bDescriptorSubType, Abstract Control Management Functional Descriptor
0x02, //bmCapabilities, D7..D2 reversed
// D7..D4 reversed
// D3 supports the notification Network_Connection
// D2 not supports the request Send_Break
// D1 supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
// D0 supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature
//CDC Interface Descriptor
0x05, //bLength
0x24, //bDescriptorType
0x06, //bDescriptorSubType, Union Functional Descriptor
0x00, //bControlInterface
0x01, //bSubordinateInterface[0]
//Endpoint In
0x07, //bLength
0x05, //bDescritorType
0x82, //bEndpointAddr
0x03, //bmAttributes, interrupt
0x08, 0x00, //wMaxPacketSize
0x01, //bInterval, 1ms
//Interface 1, Alt 0
0x09, //Length
0x04, //DescriptorType:Interface
0x01, //InterfaceNum
0x00, //AlternateSetting
0x02, //NumEndpoint
0x0a, //InterfaceClass, CDC Data
0x00, //InterfaceSubClass
0x00, //InterfaceProtocol
0x00, //Interface String
//Endpoint Out
0x07, //bLength
0x05, //bDescriptor
0x02, //bEndpointAddr
0x02, //bmAttributes, bulk
0x40, 0x00, //wMaxPacketSize
0x00, //bInterval
//Endpoint In
0x07, //bLength
0x05, //bDescritorType
0x83, //bEndpointAddr
0x02, //bmAttributes, bulk
0x40, 0x00, //wMaxPacketSize
0x00, //bInterval
};
static void cdc_endpoint_init(struct usb_device_t *usb_device, u32 itf);
static u32 cdc_setup_rx(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req);
static void usb_cdc_line_coding_init(struct usb_cdc_line_coding *lc)
{
lc->dwDTERate = 460800;
lc->bCharFormat = USB_CDC_1_STOP_BITS;
lc->bParityType = USB_CDC_NO_PARITY;
lc->bDataBits = 8;
}
static void dump_line_coding(struct usb_cdc_line_coding *lc)
{
log_debug("dtw rate : %d", lc->dwDTERate);
log_debug("stop bits : %d", lc->bCharFormat);
log_debug("verify bits : %d", lc->bParityType);
log_debug("data bits : %d", lc->bDataBits);
}
static u32 cdc_setup(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req)
{
const usb_dev usb_id = usb_device2id(usb_device);
int recip_type;
u32 len;
recip_type = ctrl_req->bRequestType & USB_TYPE_MASK;
switch (recip_type) {
case USB_TYPE_CLASS:
switch (ctrl_req->bRequest) {
case USB_CDC_REQ_SET_LINE_CODING:
log_debug("set line coding");
usb_set_setup_recv(usb_device, cdc_setup_rx);
break;
case USB_CDC_REQ_GET_LINE_CODING:
log_debug("get line codling");
len = ctrl_req->wLength < sizeof(struct usb_cdc_line_coding) ?
ctrl_req->wLength : sizeof(struct usb_cdc_line_coding);
if (cdc_hdl == NULL) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
break;
}
usb_set_data_payload(usb_device, ctrl_req, cdc_hdl->subtype_data, len);
dump_line_coding((struct usb_cdc_line_coding *)cdc_hdl->subtype_data);
break;
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
log_debug("set control line state - %d", ctrl_req->wValue);
if (cdc_hdl) {
/* if (ctrl_req->wValue & BIT(0)) { //DTR */
cdc_hdl->bmTransceiver |= BIT(0);
/* } else { */
/* usb_slave->cdc->bmTransceiver &= ~BIT(0); */
/* } */
/* if (ctrl_req->wValue & BIT(1)) { //RTS */
cdc_hdl->bmTransceiver |= BIT(1);
/* } else { */
/* usb_slave->cdc->bmTransceiver &= ~BIT(1); */
/* } */
cdc_hdl->bmTransceiver |= BIT(4); //cfg done
}
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
//cdc_endpoint_init(usb_device, (ctrl_req->wIndex & USB_RECIP_MASK));
break;
default:
log_error("unsupported class req");
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
break;
}
break;
default:
log_error("unsupported req type");
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
break;
}
return 0;
}
static u32 cdc_setup_rx(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req)
{
const usb_dev usb_id = usb_device2id(usb_device);
int recip_type;
struct usb_cdc_line_coding *lc = 0;
u32 len;
u8 read_ep[8];
len = ctrl_req->wLength;
usb_read_ep0(usb_id, read_ep, len);
recip_type = ctrl_req->bRequestType & USB_TYPE_MASK;
switch (recip_type) {
case USB_TYPE_CLASS:
switch (ctrl_req->bRequest) {
case USB_CDC_REQ_SET_LINE_CODING:
log_debug("USB_CDC_REQ_SET_LINE_CODING");
if (cdc_hdl == NULL) {
break;
}
if (len > sizeof(struct usb_cdc_line_coding)) {
len = sizeof(struct usb_cdc_line_coding);
}
memcpy(cdc_hdl->subtype_data, read_ep, len);
lc = (struct usb_cdc_line_coding *)cdc_hdl->subtype_data;
dump_line_coding(lc);
break;
}
break;
}
return USB_EP0_STAGE_SETUP;
}
static void cdc_reset(struct usb_device_t *usb_device, u32 itf)
{
log_error("%s()", __func__);
const usb_dev usb_id = usb_device2id(usb_device);
#if USB_ROOT2
usb_disable_ep(usb_id, CDC_DATA_EP_IN);
#if CDC_INTR_EP_ENABLE
usb_disable_ep(usb_id, CDC_INTR_EP_IN);
#endif
#else
cdc_endpoint_init(usb_device, itf);
#endif
}
u32 cdc_desc_config(const usb_dev usb_id, u8 *ptr, u32 *itf)
{
u8 *tptr;
tptr = ptr;
memcpy(tptr, cdc_virtual_comport_desc, sizeof(cdc_virtual_comport_desc));
//iad interface number
tptr[2] = *itf;
//control interface number
tptr[8 + 2] = *itf;
tptr[8 + 9 + 5 + 4] = *itf + 1;
tptr[8 + 9 + 5 + 5 + 4 + 3] = *itf;
tptr[8 + 9 + 5 + 5 + 4 + 4] = *itf + 1;
//interrupt in ep
tptr[8 + 9 + 5 + 5 + 4 + 5 + 2] = USB_DIR_IN | CDC_INTR_EP_IN;
tptr[8 + 9 + 5 + 5 + 4 + 5 + 4] = MAXP_SIZE_CDC_INTRIN & 0xff;
tptr[8 + 9 + 5 + 5 + 4 + 5 + 5] = (MAXP_SIZE_CDC_INTRIN >> 8) & 0xff;
#if defined(FUSB_MODE) && FUSB_MODE == 0
tptr[8 + 9 + 5 + 5 + 4 + 5 + 6] = 4; //high-speed mode, 125x2^(4-1)=1ms
#endif
//data interface number
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 2] = *itf + 1;
//bulk out ep
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 2] = CDC_DATA_EP_OUT;
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 4] = MAXP_SIZE_CDC_BULKOUT & 0xff;
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 5] = (MAXP_SIZE_CDC_BULKOUT >> 8) & 0xff;
//bulk in ep
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 2] = USB_DIR_IN | CDC_DATA_EP_IN;
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 4] = MAXP_SIZE_CDC_BULKIN & 0xff;
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 5] = (MAXP_SIZE_CDC_BULKIN >> 8) & 0xff;
tptr += sizeof(cdc_virtual_comport_desc);
if (usb_set_interface_hander(usb_id, *itf, cdc_setup) != *itf) {
ASSERT(0, "cdc set interface_hander fail");
}
if (usb_set_reset_hander(usb_id, *itf, cdc_reset) != *itf) {
}
*itf += 2;
return (u32)(tptr - ptr);
}
void cdc_set_wakeup_handler(void (*handle)(struct usb_device_t *usb_device))
{
if (cdc_hdl) {
cdc_hdl->wakeup_handler = handle;
}
}
static void cdc_wakeup_handler(struct usb_device_t *usb_device, u32 ep)
{
if (cdc_hdl && cdc_hdl->wakeup_handler) {
cdc_hdl->wakeup_handler(usb_device);
}
}
void cdc_set_output_handle(void *priv, int (*output_handler)(void *priv, u8 *buf, u32 len))
{
if (cdc_hdl) {
cdc_hdl->output = output_handler;
cdc_hdl->priv = priv;
}
}
static void cdc_intrrx(struct usb_device_t *usb_device, u32 ep)
{
const usb_dev usb_id = usb_device2id(usb_device);
if (cdc_hdl == NULL) {
return;
}
u8 *cdc_rx_buf = cdc_hdl->cdc_buffer;
//由于bulk传输使用双缓冲无法用usb_get_ep_buffer()知道是哪一个buffer需要外部buffer接收数据
u32 len = usb_g_bulk_read(usb_id, CDC_DATA_EP_OUT, cdc_rx_buf, MAXP_SIZE_CDC_BULKOUT, 0);
if (cdc_hdl->output) {
cdc_hdl->output(cdc_hdl->priv, cdc_rx_buf, len);
}
}
static void cdc_endpoint_init(struct usb_device_t *usb_device, u32 itf)
{
ASSERT(cdc_hdl, "cdc not register");
const usb_dev usb_id = usb_device2id(usb_device);
usb_g_ep_config(usb_id, CDC_DATA_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_BULK,
0, cdc_hdl->bulk_ep_in_buffer, MAXP_SIZE_CDC_BULKIN);
usb_g_ep_config(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK,
1, cdc_hdl->bulk_ep_out_buffer, MAXP_SIZE_CDC_BULKOUT);
/* usb_g_set_intr_hander(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, cdc_intrrx); */
usb_g_set_intr_hander(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, cdc_wakeup_handler);
usb_enable_ep(usb_id, CDC_DATA_EP_IN);
#if CDC_INTR_EP_ENABLE
usb_g_ep_config(usb_id, CDC_INTR_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_INT,
0, cdc_hdl->intr_ep_in_buffer, MAXP_SIZE_CDC_INTRIN);
usb_enable_ep(usb_id, CDC_INTR_EP_IN);
#endif
}
u32 cdc_read_data(const usb_dev usb_id, u8 *buf, u32 len)
{
u32 rxlen;
if (cdc_hdl == NULL) {
return 0;
}
u8 *cdc_rx_buf = cdc_hdl->cdc_buffer;
os_mutex_pend(&cdc_hdl->mutex_data, 0);
//由于bulk传输使用双缓冲无法用usb_get_ep_buffer()知道是哪一个buffer需要外部buffer接收数据
rxlen = usb_g_bulk_read(usb_id, CDC_DATA_EP_OUT, cdc_rx_buf, MAXP_SIZE_CDC_BULKOUT, 0);
rxlen = rxlen > len ? len : rxlen;
if (rxlen > 0) {
memcpy(buf, cdc_rx_buf, rxlen);
}
os_mutex_post(&cdc_hdl->mutex_data);
return rxlen;
}
u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len)
{
u32 txlen, offset;
if (cdc_hdl == NULL) {
return 0;
}
if ((cdc_hdl->bmTransceiver & (BIT(1) | BIT(4))) != (BIT(1) | BIT(4))) {
return 0;
}
offset = 0;
os_mutex_pend(&cdc_hdl->mutex_data, 0);
while (offset < len) {
txlen = len - offset > MAXP_SIZE_CDC_BULKIN ?
MAXP_SIZE_CDC_BULKIN : len - offset;
txlen = usb_g_bulk_write(usb_id, CDC_DATA_EP_IN, buf + offset, txlen);
if (txlen == 0) {
break;
}
if ((cdc_hdl->bmTransceiver & (BIT(1) | BIT(4))) != (BIT(1) | BIT(4))) {
break;
}
offset += txlen;
}
//当最后一包的包长等于maxpktsize需要发一个0长包表示结束
if ((offset % MAXP_SIZE_CDC_BULKIN) == 0) {
usb_g_bulk_write(usb_id, CDC_DATA_EP_IN, NULL, 0);
}
os_mutex_post(&cdc_hdl->mutex_data);
return offset;
}
u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len)
{
#if CDC_INTR_EP_ENABLE
u32 txlen, offset;
if (cdc_hdl == NULL) {
return 0;
}
if ((cdc_hdl->bmTransceiver & BIT(4)) == 0) {
return 0;
}
offset = 0;
os_mutex_pend(&cdc_hdl->mutex_intr, 0);
while (offset < len) {
txlen = len - offset > MAXP_SIZE_CDC_INTRIN ?
MAXP_SIZE_CDC_INTRIN : len - offset;
txlen = usb_g_intr_write(usb_id, CDC_INTR_EP_IN, buf + offset, txlen);
if (txlen == 0) {
break;
}
if ((cdc_hdl->bmTransceiver & BIT(4)) == 0) {
break;
}
offset += txlen;
}
os_mutex_post(&cdc_hdl->mutex_intr);
return offset;
#else
return 0;
#endif
}
void cdc_register(const usb_dev usb_id)
{
struct usb_cdc_line_coding *lc;
/* log_info("%s() %d", __func__, __LINE__); */
if (!cdc_hdl) {
#if USB_MALLOC_ENABLE
cdc_hdl = zalloc(sizeof(struct usb_cdc_gadget));
if (!cdc_hdl) {
log_error("cdc_register err 1");
return;
}
cdc_hdl->cdc_buffer = malloc(MAXP_SIZE_CDC_BULKOUT);
if (!cdc_hdl->cdc_buffer) {
log_error("cdc_register err 2");
goto __exit_err;
}
#else
memset(&_cdc_hdl, 0, sizeof(struct usb_cdc_gadget));
cdc_hdl = &_cdc_hdl;
cdc_hdl->cdc_buffer = _cdc_buffer;
#endif
lc = (struct usb_cdc_line_coding *)cdc_hdl->subtype_data;
usb_cdc_line_coding_init(lc);
os_mutex_create(&cdc_hdl->mutex_data);
cdc_hdl->bulk_ep_in_buffer = usb_alloc_ep_dmabuffer(usb_id, CDC_DATA_EP_IN | USB_DIR_IN, MAXP_SIZE_CDC_BULKIN + MAXP_SIZE_CDC_BULKOUT);
cdc_hdl->bulk_ep_out_buffer = cdc_hdl->bulk_ep_in_buffer + MAXP_SIZE_CDC_BULKIN;
#if CDC_INTR_EP_ENABLE
os_mutex_create(&cdc_hdl->mutex_intr);
cdc_hdl->intr_ep_in_buffer = usb_alloc_ep_dmabuffer(usb_id, CDC_INTR_EP_IN | USB_DIR_IN, MAXP_SIZE_CDC_INTRIN);
#endif
}
return;
__exit_err:
#if USB_MALLOC_ENABLE
if (cdc_hdl->cdc_buffer) {
free(cdc_hdl->cdc_buffer);
}
if (cdc_hdl) {
free(cdc_hdl);
}
#endif
cdc_hdl = NULL;
}
void cdc_release(const usb_dev usb_id)
{
/* log_info("%s() %d", __func__, __LINE__); */
if (cdc_hdl) {
#if USB_MALLOC_ENABLE
free(cdc_hdl->cdc_buffer);
free(cdc_hdl);
#endif
cdc_hdl = NULL;
}
}
#endif

View File

@ -0,0 +1,23 @@
#ifndef __CDC_H__
#define __CDC_H__
#include "usb/device/usb_stack.h"
#ifdef __cplusplus
extern "C" {
#endif
u32 cdc_desc_config(const usb_dev usb_id, u8 *ptr, u32 *itf);
void cdc_set_wakeup_handler(void (*handle)(struct usb_device_t *usb_device));
void cdc_set_output_handle(void *priv, int (*output_handler)(void *priv, u8 *buf, u32 len));
u32 cdc_read_data(const usb_dev usb_id, u8 *buf, u32 len);
u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len);
u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len);
void cdc_register(const usb_dev usb_id);
void cdc_release(const usb_dev usb_id);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,457 @@
/*
* USB Communications Device Class (CDC) definitions
*
* CDC says how to talk to lots of different types of network adapters,
* notably ethernet adapters and various modems. It's used mostly with
* firmware based USB peripherals.
*/
#ifndef __LINUX_USB_CDC_H
#define __LINUX_USB_CDC_H
#include "typedef.h" /* __u8 etc */
#ifdef __le16
#undef __le16
#endif
typedef unsigned short __le16;
#ifdef __le32
#undef __le32
#endif
typedef unsigned int __le32;
#ifdef __u8
#undef __u8
#endif
typedef unsigned char __u8;
#ifdef __u16
#undef __u16
#endif
typedef unsigned short __u16;
#ifdef __u32
#undef __u32
#endif
typedef unsigned int __u32;
#define USB_CDC_SUBCLASS_ACM 0x02
#define USB_CDC_SUBCLASS_ETHERNET 0x06
#define USB_CDC_SUBCLASS_WHCM 0x08
#define USB_CDC_SUBCLASS_DMM 0x09
#define USB_CDC_SUBCLASS_MDLM 0x0a
#define USB_CDC_SUBCLASS_OBEX 0x0b
#define USB_CDC_SUBCLASS_EEM 0x0c
#define USB_CDC_SUBCLASS_NCM 0x0d
#define USB_CDC_SUBCLASS_MBIM 0x0e
#define USB_CDC_PROTO_NONE 0
#define USB_CDC_ACM_PROTO_AT_V25TER 1
#define USB_CDC_ACM_PROTO_AT_PCCA101 2
#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3
#define USB_CDC_ACM_PROTO_AT_GSM 4
#define USB_CDC_ACM_PROTO_AT_3G 5
#define USB_CDC_ACM_PROTO_AT_CDMA 6
#define USB_CDC_ACM_PROTO_VENDOR 0xff
#define USB_CDC_PROTO_EEM 7
#define USB_CDC_NCM_PROTO_NTB 1
#define USB_CDC_MBIM_PROTO_NTB 2
/*-------------------------------------------------------------------------*/
/*
* Class-Specific descriptors ... there are a couple dozen of them
*/
#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
#define USB_CDC_COUNTRY_TYPE 0x07
#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */
#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
#define USB_CDC_WHCM_TYPE 0x11
#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
#define USB_CDC_DMM_TYPE 0x14
#define USB_CDC_OBEX_TYPE 0x15
#define USB_CDC_NCM_TYPE 0x1a
#define USB_CDC_MBIM_TYPE 0x1b
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
struct usb_cdc_header_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__le16 bcdCDC;
} __attribute__((packed));
/* "Call Management Descriptor" from CDC spec 5.2.3.2 */
struct usb_cdc_call_mgmt_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bmCapabilities;
#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01
#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02
__u8 bDataInterface;
} __attribute__((packed));
/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */
struct usb_cdc_acm_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bmCapabilities;
} __attribute__((packed));
/* capabilities from 5.2.3.3 */
#define USB_CDC_COMM_FEATURE 0x01
#define USB_CDC_CAP_LINE 0x02
#define USB_CDC_CAP_BRK 0x04
#define USB_CDC_CAP_NOTIFY 0x08
/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
struct usb_cdc_union_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bMasterInterface0;
__u8 bSlaveInterface0;
/* ... and there could be other slave interfaces */
} __attribute__((packed));
/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */
struct usb_cdc_country_functional_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 iCountryCodeRelDate;
__le16 wCountyCode0;
/* ... and there can be a lot of country codes */
} __attribute__((packed));
/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */
struct usb_cdc_network_terminal_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 bEntityId;
__u8 iName;
__u8 bChannelIndex;
__u8 bPhysicalInterface;
} __attribute__((packed));
/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
struct usb_cdc_ether_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__u8 iMACAddress;
__le32 bmEthernetStatistics;
__le16 wMaxSegmentSize;
__le16 wNumberMCFilters;
__u8 bNumberPowerFilters;
} __attribute__((packed));
/* "Telephone Control Model Functional Descriptor" from CDC WMC spec 6.3..3 */
struct usb_cdc_dmm_desc {
__u8 bFunctionLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u16 bcdVersion;
__le16 wMaxCommand;
} __attribute__((packed));
/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
struct usb_cdc_mdlm_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__le16 bcdVersion;
__u8 bGUID[16];
} __attribute__((packed));
/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
struct usb_cdc_mdlm_detail_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
/* type is associated with mdlm_desc.bGUID */
__u8 bGuidDescriptorType;
__u8 bDetailData[0];
} __attribute__((packed));
/* "OBEX Control Model Functional Descriptor" */
struct usb_cdc_obex_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__le16 bcdVersion;
} __attribute__((packed));
/* "NCM Control Model Functional Descriptor" */
struct usb_cdc_ncm_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__le16 bcdNcmVersion;
__u8 bmNetworkCapabilities;
} __attribute__((packed));
/* "MBIM Control Model Functional Descriptor" */
struct usb_cdc_mbim_desc {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubType;
__le16 bcdMBIMVersion;
__le16 wMaxControlMessage;
__u8 bNumberFilters;
__u8 bMaxFilterSize;
__le16 wMaxSegmentSize;
__u8 bmNetworkCapabilities;
} __attribute__((packed));
/*-------------------------------------------------------------------------*/
/*
* Class-Specific Control Requests (6.2)
*
* section 3.6.2.1 table 4 has the ACM profile, for modems.
* section 3.8.2 table 10 has the ethernet profile.
*
* Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
* heavily dependent on the encapsulated (proprietary) command mechanism.
*/
#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
#define USB_CDC_REQ_SET_LINE_CODING 0x20
#define USB_CDC_REQ_GET_LINE_CODING 0x21
#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
#define USB_CDC_REQ_SEND_BREAK 0x23
#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43
#define USB_CDC_GET_ETHERNET_STATISTIC 0x44
#define USB_CDC_GET_NTB_PARAMETERS 0x80
#define USB_CDC_GET_NET_ADDRESS 0x81
#define USB_CDC_SET_NET_ADDRESS 0x82
#define USB_CDC_GET_NTB_FORMAT 0x83
#define USB_CDC_SET_NTB_FORMAT 0x84
#define USB_CDC_GET_NTB_INPUT_SIZE 0x85
#define USB_CDC_SET_NTB_INPUT_SIZE 0x86
#define USB_CDC_GET_MAX_DATAGRAM_SIZE 0x87
#define USB_CDC_SET_MAX_DATAGRAM_SIZE 0x88
#define USB_CDC_GET_CRC_MODE 0x89
#define USB_CDC_SET_CRC_MODE 0x8a
/* Line Coding Structure from CDC spec 6.2.13 */
struct usb_cdc_line_coding {
__le32 dwDTERate;
__u8 bCharFormat;
#define USB_CDC_1_STOP_BITS 0
#define USB_CDC_1_5_STOP_BITS 1
#define USB_CDC_2_STOP_BITS 2
__u8 bParityType;
#define USB_CDC_NO_PARITY 0
#define USB_CDC_ODD_PARITY 1
#define USB_CDC_EVEN_PARITY 2
#define USB_CDC_MARK_PARITY 3
#define USB_CDC_SPACE_PARITY 4
__u8 bDataBits;
} __attribute__((packed));
/* table 62; bits in multicast filter */
#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0)
#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */
#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2)
#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3)
#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */
/*-------------------------------------------------------------------------*/
/*
* Class-Specific Notifications (6.3) sent by interrupt transfers
*
* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
* section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
* RNDIS also defines its own bit-incompatible notifications
*/
#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00
#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01
#define USB_CDC_NOTIFY_SERIAL_STATE 0x20
#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a
struct usb_cdc_notification {
__u8 bmRequestType;
__u8 bNotificationType;
__le16 wValue;
__le16 wIndex;
__le16 wLength;
} __attribute__((packed));
struct usb_cdc_speed_change {
__le32 DLBitRRate; /* contains the downlink bit rate (IN pipe) */
__le32 ULBitRate; /* contains the uplink bit rate (OUT pipe) */
} __attribute__((packed));
/*-------------------------------------------------------------------------*/
/*
* Class Specific structures and constants
*
* CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1
*
*/
struct usb_cdc_ncm_ntb_parameters {
__le16 wLength;
__le16 bmNtbFormatsSupported;
__le32 dwNtbInMaxSize;
__le16 wNdpInDivisor;
__le16 wNdpInPayloadRemainder;
__le16 wNdpInAlignment;
__le16 wPadding1;
__le32 dwNtbOutMaxSize;
__le16 wNdpOutDivisor;
__le16 wNdpOutPayloadRemainder;
__le16 wNdpOutAlignment;
__le16 wNtbOutMaxDatagrams;
} __attribute__((packed));
/*
* CDC NCM transfer headers, CDC NCM subclass 3.2
*/
#define USB_CDC_NCM_NTH16_SIGN 0x484D434E /* NCMH */
#define USB_CDC_NCM_NTH32_SIGN 0x686D636E /* ncmh */
struct usb_cdc_ncm_nth16 {
__le32 dwSignature;
__le16 wHeaderLength;
__le16 wSequence;
__le16 wBlockLength;
__le16 wNdpIndex;
} __attribute__((packed));
struct usb_cdc_ncm_nth32 {
__le32 dwSignature;
__le16 wHeaderLength;
__le16 wSequence;
__le32 dwBlockLength;
__le32 dwNdpIndex;
} __attribute__((packed));
/*
* CDC NCM datagram pointers, CDC NCM subclass 3.3
*/
#define USB_CDC_NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */
#define USB_CDC_NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */
#define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */
#define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */
#define USB_CDC_MBIM_NDP16_IPS_SIGN 0x00535049 /* IPS<sessionID> : IPS0 for now */
#define USB_CDC_MBIM_NDP32_IPS_SIGN 0x00737069 /* ips<sessionID> : ips0 for now */
#define USB_CDC_MBIM_NDP16_DSS_SIGN 0x00535344 /* DSS<sessionID> */
#define USB_CDC_MBIM_NDP32_DSS_SIGN 0x00737364 /* dss<sessionID> */
/* 16-bit NCM Datagram Pointer Entry */
struct usb_cdc_ncm_dpe16 {
__le16 wDatagramIndex;
__le16 wDatagramLength;
} __attribute__((__packed__));
/* 16-bit NCM Datagram Pointer Table */
struct usb_cdc_ncm_ndp16 {
__le32 dwSignature;
__le16 wLength;
__le16 wNextNdpIndex;
struct usb_cdc_ncm_dpe16 dpe16[0];
} __attribute__((packed));
/* 32-bit NCM Datagram Pointer Entry */
struct usb_cdc_ncm_dpe32 {
__le32 dwDatagramIndex;
__le32 dwDatagramLength;
} __attribute__((__packed__));
/* 32-bit NCM Datagram Pointer Table */
struct usb_cdc_ncm_ndp32 {
__le32 dwSignature;
__le16 wLength;
__le16 wReserved6;
__le32 dwNextNdpIndex;
__le32 dwReserved12;
struct usb_cdc_ncm_dpe32 dpe32[0];
} __attribute__((packed));
/* CDC NCM subclass 3.2.1 and 3.2.2 */
#define USB_CDC_NCM_NDP16_INDEX_MIN 0x000C
#define USB_CDC_NCM_NDP32_INDEX_MIN 0x0010
/* CDC NCM subclass 3.3.3 Datagram Formatting */
#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC 0x30
#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC 0X31
/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */
#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS 0x00
#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO 0xFE
/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */
#define USB_CDC_NCM_NCAP_ETH_FILTER (1 << 0)
#define USB_CDC_NCM_NCAP_NET_ADDRESS (1 << 1)
#define USB_CDC_NCM_NCAP_ENCAP_COMMAND (1 << 2)
#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE (1 << 3)
#define USB_CDC_NCM_NCAP_CRC_MODE (1 << 4)
#define USB_CDC_NCM_NCAP_NTB_INPUT_SIZE (1 << 5)
/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
#define USB_CDC_NCM_NTB16_SUPPORTED (1 << 0)
#define USB_CDC_NCM_NTB32_SUPPORTED (1 << 1)
/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE 0x04
#define USB_CDC_NCM_NTB_MAX_LENGTH 0x1C
/* CDC NCM subclass 6.2.5 SetNtbFormat */
#define USB_CDC_NCM_NTB16_FORMAT 0x00
#define USB_CDC_NCM_NTB32_FORMAT 0x01
/* CDC NCM subclass 6.2.7 SetNtbInputSize */
#define USB_CDC_NCM_NTB_MIN_IN_SIZE 2048
#define USB_CDC_NCM_NTB_MIN_OUT_SIZE 2048
/* NTB Input Size Structure */
struct usb_cdc_ncm_ndp_input_size {
__le32 dwNtbInMaxSize;
__le16 wNtbInMaxDatagrams;
__le16 wReserved;
} __attribute__((packed));
/* CDC NCM subclass 6.2.11 SetCrcMode */
#define USB_CDC_NCM_CRC_NOT_APPENDED 0x00
#define USB_CDC_NCM_CRC_APPENDED 0x01
#endif /* __LINUX_USB_CDC_H */

View File

@ -0,0 +1,202 @@
/**
* @file descriptor.c
* @brief overwrite usb device descriptor
* @version 1.00
* @date 2019-05-06
*/
#include "usb/device/usb_stack.h"
#include "usb/device/descriptor.h"
#include "usb/device/uac_audio.h"
#include "app_config.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_SLAVE_ENABLE
static const u8 sDeviceDescriptor[] = { //<Device Descriptor
USB_DT_DEVICE_SIZE, // bLength: Size of descriptor
USB_DT_DEVICE, // bDescriptorType: Device
#if defined(FUSB_MODE) && FUSB_MODE
0x10, 0x01, // bcdUSB: USB 1.1
#elif defined(FUSB_MODE) && (FUSB_MODE ==0 )
0x00, 0x02, // bcdUSB: USB 2.0
#else
#error "USB_SPEED_MODE not defined"
#endif
0x00, // bDeviceClass: none
0x00, // bDeviceSubClass: none
0x00, // bDeviceProtocol: none
EP0_SETUP_LEN,//EP0_LEN, // bMaxPacketSize0: 8/64 bytes
'J', 'L', // idVendor: 0x4a4c - JL
'U', 'A', // idProduct: chip id
0x00, 0x01, // bcdDevice: version 1.0
0x01, // iManufacturer: Index to string descriptor that contains the string <Your Name> in Unicode
0x02, // iProduct: Index to string descriptor that contains the string <Your Product Name> in Unicode
0x03, // iSerialNumber: none
0x01 // bNumConfigurations: 1
};
static const u8 LANGUAGE_STR[] = {
0x04, 0x03, 0x09, 0x04
};
static const u8 product_string[] = {
42,
0x03,
'U', 0x00,
'S', 0x00,
'B', 0x00,
' ', 0x00,
'C', 0x00,
'o', 0x00,
'm', 0x00,
'p', 0x00,
'o', 0x00,
's', 0x00,
'i', 0x00,
't', 0x00,
'e', 0x00,
' ', 0x00,
'D', 0x00,
'e', 0x00,
'v', 0x00,
'i', 0x00,
'c', 0x00,
'e', 0x00,
};
static const u8 MANUFACTURE_STR[] = {
34, //该描述符的长度为34字节
0x03, //字符串描述符的类型编码为0x03
0x4a, 0x00, //J
0x69, 0x00, //i
0x65, 0x00, //e
0x6c, 0x00, //l
0x69, 0x00, //i
0x20, 0x00, //
0x54, 0x00, //T
0x65, 0x00, //e
0x63, 0x00, //c
0x68, 0x00, //h
0x6e, 0x00, //n
0x6f, 0x00, //o
0x6c, 0x00, //l
0x6f, 0x00, //o
0x67, 0x00, //g
0x79, 0x00, //y
};
static const u8 sConfigDescriptor[] = { //<Config Descriptor
//ConfiguraTIon
USB_DT_CONFIG_SIZE, //bLength
USB_DT_CONFIG, //DescriptorType : ConfigDescriptor
0, 0, //TotalLength
0,//bNumInterfaces: 在set_descriptor函数里面计算
0x01, //bConfigurationValue - ID of this configuration
0x00, //Unused
#if USB_ROOT2 || USB_SUSPEND_RESUME || USB_SUSPEND_RESUME_SYSTEM_NO_SLEEP
0xA0, //Attributes:Bus Power remotewakeup
#else
0x80, //Attributes:Bus Power
#endif
50, //MaxPower * 2ma
};
static const u8 serial_string[] = {
0x22, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x36, 0x00, 0x46, 0x00, 0x36, 0x00,
0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x36, 0x00, 0x42, 0x00, 0x32, 0x00, 0x32, 0x00, 0x45, 0x00,
0x37, 0x00
};
void get_device_descriptor(u8 *ptr)
{
memcpy(ptr, sDeviceDescriptor, USB_DT_DEVICE_SIZE);
}
void get_language_str(u8 *ptr)
{
memcpy(ptr, LANGUAGE_STR, LANGUAGE_STR[0]);
}
void get_manufacture_str(u8 *ptr)
{
memcpy(ptr, MANUFACTURE_STR, MANUFACTURE_STR[0]);
}
void get_iserialnumber_str(u8 *ptr)
{
#if USB_ROOT2
memcpy(ptr, serial_string, serial_string[0]);
#else
extern __attribute__((weak)) u8 *get_norflash_uuid(void);
u8 flash_id[16] = {0};
int i;
u8 bcd;
if (get_norflash_uuid && get_norflash_uuid()) {
ptr[0] = 0x22;
ptr[1] = 0x03;
memset(&ptr[2], 0, 0x20);
memcpy(flash_id, get_norflash_uuid(), 16);
//take 8 bytes from flash uuid
for (i = 0; i < 8; i++) {
bcd = flash_id[i] >> 4;
if (bcd > 9) {
bcd = bcd - 0xa + 'A';
} else {
bcd = bcd + '0';
}
ptr[2 + i * 4] = bcd;
bcd = flash_id[i] & 0xf;
if (bcd > 9) {
bcd = bcd - 0xa + 'A';
} else {
bcd = bcd + '0';
}
ptr[2 + i * 4 + 2] = bcd;
}
} else {
memcpy(ptr, serial_string, serial_string[0]);
}
#endif
}
#if USB_ROOT2
static const u8 ee_string[] = {0x12, 0x03, 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00, 0x54,
0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x90, 0x00
};
void get_string_ee(u8 *ptr)
{
memcpy(ptr, ee_string, ee_string[0]);
}
#endif
void get_product_str(u8 *ptr)
{
memcpy(ptr, product_string, product_string[0]);
}
const u8 *usb_get_config_desc()
{
return sConfigDescriptor;
}
const u8 *usb_get_string_desc(u32 id)
{
const u8 *pstr = uac_get_string(id);
if (pstr != NULL) {
return pstr;
}
return NULL;
}
#endif

View File

@ -0,0 +1,332 @@
#include "os/os_api.h"
#include "usb/device/usb_stack.h"
#include "usb/device/hid.h"
#include "usb_config.h"
#include "app_config.h"
#if TCFG_USB_SLAVE_USER_HID
#undef TCFG_USB_SLAVE_HID_ENABLE
#define TCFG_USB_SLAVE_HID_ENABLE 0
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
static const u8 sHIDDescriptor[] = {
//HID
//InterfaceDeszcriptor:
USB_DT_INTERFACE_SIZE, // Length
USB_DT_INTERFACE, // DescriptorType
/* 0x04, // bInterface number */
0x00, // bInterface number
0x00, // AlternateSetting
0x01, // NumEndpoint
/* 0x02, // NumEndpoint */
USB_CLASS_HID, // Class = Human Interface Device
0x00, // Subclass, 0 No subclass, 1 Boot Interface subclass
0x00, // Procotol, 0 None, 1 Keyboard, 2 Mouse
0x00, // Interface Name
//HIDDescriptor:
0x09, // bLength
USB_HID_DT_HID, // bDescriptorType, HID Descriptor
0x00, 0x01, // bcdHID, HID Class Specification release NO.
0x00, // bCuntryCode, Country localization (=none)
0x01, // bNumDescriptors, Number of descriptors to follow
0x22, // bDescriptorType, Report Desc. 0x22, Physical Desc. 0x23
0,//LOW(ReportLength)
0, //HIGH(ReportLength)
//EndpointDescriptor:
USB_DT_ENDPOINT_SIZE, // bLength
USB_DT_ENDPOINT, // bDescriptorType, Type
USB_DIR_IN | HID_EP_IN, // bEndpointAddress
USB_ENDPOINT_XFER_INT, // Interrupt
LOBYTE(MAXP_SIZE_HIDIN), HIBYTE(MAXP_SIZE_HIDIN),// Maximum packet size
HID_INTR_INTERVAL, // Poll every 10msec seconds
//@Endpoint Descriptor:
/* USB_DT_ENDPOINT_SIZE, // bLength
USB_DT_ENDPOINT, // bDescriptorType, Type
USB_DIR_OUT | HID_EP_OUT, // bEndpointAddress
USB_ENDPOINT_XFER_INT, // Interrupt
LOBYTE(MAXP_SIZE_HIDOUT), HIBYTE(MAXP_SIZE_HIDOUT),// Maximum packet size
HID_INTR_INTERVAL, // bInterval, for high speed 2^(n-1) * 125us, for full/low speed n * 1ms */
};
static const u8 sHIDReportDesc[] = {
USAGE_PAGE(1, CONSUMER_PAGE),
USAGE(1, CONSUMER_CONTROL),
COLLECTION(1, APPLICATION),
LOGICAL_MIN(1, 0x00),
LOGICAL_MAX(1, 0x01),
USAGE(1, VOLUME_INC),
USAGE(1, VOLUME_DEC),
USAGE(1, MUTE),
USAGE(1, PLAY_PAUSE),
USAGE(1, SCAN_NEXT_TRACK),
USAGE(1, SCAN_PREV_TRACK),
USAGE(1, FAST_FORWARD),
USAGE(1, STOP),
USAGE(1, TRACKING_INC),
USAGE(1, TRACKING_DEC),
USAGE(1, STOP_EJECT),
USAGE(1, VOLUME),
USAGE(2, BALANCE_LEFT),
USAGE(2, BALANCE_RIGHT),
USAGE(1, PLAY),
USAGE(1, PAUSE),
REPORT_SIZE(1, 0x01),
REPORT_COUNT(1, 0x10),
INPUT(1, 0x42),
END_COLLECTION,
};
static u32 get_hid_report_desc_len(u32 index)
{
u32 len = 0;
len = sizeof(sHIDReportDesc);
return len;
}
static void *get_hid_report_desc(u32 index)
{
u8 *ptr = NULL;
ptr = (u8 *)sHIDReportDesc;
return ptr;
}
static u8 *hid_ep_in_dma;
/* static u8 *hid_ep_out_dma; */
static u32 hid_tx_data(struct usb_device_t *usb_device, const u8 *buffer, u32 len)
{
const usb_dev usb_id = usb_device2id(usb_device);
return usb_g_intr_write(usb_id, HID_EP_IN, buffer, len);
}
static void hid_rx_data(struct usb_device_t *usb_device, u32 ep)
{
/* const usb_dev usb_id = usb_device2id(usb_device); */
/* u32 rx_len = usb_g_intr_read(usb_id, ep, NULL, 64, 0); */
/* hid_tx_data(usb_device, hid_ep_out_dma, rx_len); */
}
static void hid_endpoint_init(struct usb_device_t *usb_device, u32 itf)
{
const usb_dev usb_id = usb_device2id(usb_device);
usb_g_ep_config(usb_id, HID_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 0, hid_ep_in_dma, MAXP_SIZE_HIDIN);
usb_enable_ep(usb_id, HID_EP_IN);
/* usb_g_set_intr_hander(usb_id, HID_EP_OUT, hid_rx_data); */
/* usb_g_ep_config(usb_id, HID_EP_OUT, USB_ENDPOINT_XFER_INT, 1, ep_buffer, MAXP_SIZE_HIDOUT); */
}
u32 hid_register(const usb_dev usb_id)
{
hid_ep_in_dma = usb_alloc_ep_dmabuffer(usb_id, HID_EP_IN | USB_DIR_IN, MAXP_SIZE_HIDIN);
/* hid_ep_out_dma = hid_ep_in_dma + MAXP_SIZE_HIDIN; */
return 0;
}
void hid_release(const usb_dev usb_id)
{
return ;
}
static void hid_reset(struct usb_device_t *usb_device, u32 itf)
{
const usb_dev usb_id = usb_device2id(usb_device);
log_debug("%s", __func__);
#if USB_ROOT2
usb_disable_ep(usb_id, HID_EP_IN);
#else
hid_endpoint_init(usb_device, itf);
#endif
}
static u32 hid_recv_output_report(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 ret = 0;
u8 read_ep[8];
u8 mute;
u16 volume = 0;
usb_read_ep0(usb_id, read_ep, MIN(sizeof(read_ep), setup->wLength));
ret = USB_EP0_STAGE_SETUP;
put_buf(read_ep, 8);
return ret;
}
static u32 hid_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 tx_len;
u8 *tx_payload = usb_get_setup_buffer(usb_device);
u32 bRequestType = req->bRequestType & USB_TYPE_MASK;
switch (bRequestType) {
case USB_TYPE_STANDARD:
switch (req->bRequest) {
case USB_REQ_GET_DESCRIPTOR:
switch (HIBYTE(req->wValue)) {
case USB_HID_DT_HID:
tx_payload = (u8 *)sHIDDescriptor + USB_DT_INTERFACE_SIZE;
tx_len = 9;
tx_payload = usb_set_data_payload(usb_device, req, tx_payload, tx_len);
tx_payload[7] = LOBYTE(get_hid_report_desc_len(req->wIndex));
tx_payload[8] = HIBYTE(get_hid_report_desc_len(req->wIndex));
break;
case USB_HID_DT_REPORT:
hid_endpoint_init(usb_device, req->wIndex);
tx_len = get_hid_report_desc_len(req->wIndex);
tx_payload = get_hid_report_desc(req->wIndex);
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
break;
}// USB_REQ_GET_DESCRIPTOR
break;
case USB_REQ_SET_DESCRIPTOR:
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
break;
case USB_REQ_SET_INTERFACE:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
//只有一个interface 没有Alternate
if (req->wValue == 0) { //alt 0
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
}
break;
case USB_REQ_GET_INTERFACE:
if (req->wValue || (req->wLength != 1)) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
tx_len = 1;
tx_payload[0] = 0x00;
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
}
break;
case USB_REQ_GET_STATUS:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
break;
}//bRequest @ USB_TYPE_STANDARD
break;
case USB_TYPE_CLASS: {
switch (req->bRequest) {
case USB_REQ_SET_IDLE:
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
break;
case USB_REQ_GET_IDLE:
tx_len = 1;
tx_payload[0] = 0;
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
break;
case USB_REQ_SET_REPORT:
usb_set_setup_recv(usb_device, hid_recv_output_report);
break;
}//bRequest @ USB_TYPE_CLASS
}
break;
}
return 0;
}
u32 hid_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num)
{
log_debug("hid interface num:%d\n", *cur_itf_num);
u8 *_ptr = ptr;
memcpy(ptr, sHIDDescriptor, sizeof(sHIDDescriptor));
ptr[2] = *cur_itf_num;
if (usb_set_interface_hander(usb_id, *cur_itf_num, hid_itf_hander) != *cur_itf_num) {
ASSERT(0, "hid set interface_hander fail");
}
if (usb_set_reset_hander(usb_id, *cur_itf_num, hid_reset) != *cur_itf_num) {
ASSERT(0, "hid set interface_reset_hander fail");
}
ptr[USB_DT_INTERFACE_SIZE + 7] = LOBYTE(get_hid_report_desc_len(0));
ptr[USB_DT_INTERFACE_SIZE + 8] = HIBYTE(get_hid_report_desc_len(0));
*cur_itf_num = *cur_itf_num + 1;
return sizeof(sHIDDescriptor) ;
}
void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key)
{
const usb_dev usb_id = usb_device2id(usb_device);
if (usb_get_ep_status(usb_id, HID_EP_IN)) {
return;
}
u16 key_buf = hid_key;
hid_tx_data(usb_device, (const u8 *)&key_buf, 2);
os_time_dly(2);
key_buf = 0;
hid_tx_data(usb_device, (const u8 *)&key_buf, 2);
}
void hid_key_handler_send_one_packet(struct usb_device_t *usb_device, u32 hid_key)
{
const usb_dev usb_id = usb_device2id(usb_device);
u16 key_buf = hid_key;
hid_tx_data(usb_device, (const u8 *)&key_buf, 2);
}
struct hid_button {
u8 report_id;
u8 button1: 1;
u8 button2: 1;
u8 button3: 1;
u8 no_button: 5;
u8 X_axis;
u8 Y_axis;
};
struct hid_button hid_key;
void hid_test(struct usb_device_t *usb_device)
{
static u32 tx_count = 0;
hid_key_handler(usb_device, BIT(tx_count));
tx_count ++;
if (BIT(tx_count) > USB_AUDIO_PAUSE) {
tx_count = 0;
}
}
#else
void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key)
{
}
void hid_key_handler_for_one_packet(struct usb_device_t *usb_device, u32 hid_key)
{
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
#include "system/includes.h"
#include "usb/device/msd.h"
#include "usb/scsi.h"
#include "usb_config.h"
#include "app_config.h"
#include "cpu.h"
#include "asm/debug.h"
#define WRITE_FLASH 0xFB
#define READ_FLASH 0xFD
#define OTHER_CMD 0xFC
typedef enum {
UPGRADE_NULL = 0,
UPGRADE_USB_HARD_KEY,
UPGRADE_USB_SOFT_KEY,
UPGRADE_UART_KEY,
} UPGRADE_STATE;
extern void nvram_set_boot_state(u32 state);
extern void hw_mmu_disable(void);
extern void ram_protect_close(void);
AT(.volatile_ram_code)
void go_mask_usb_updata()
{
#ifdef CONFIG_CPU_BR18
gpio_set_die(IO_PORTD_02, 0);
gpio_set_die(IO_PORTB_04, 0);
cpu_reset();
#else
local_irq_disable();
ram_protect_close();
//FIXME
/* hw_mmu_disable(); */
nvram_set_boot_state(UPGRADE_USB_SOFT_KEY);
JL_CLOCK->PWR_CON |= (1 << 4);
#endif
/* chip_reset(); */
/* cpu_reset(); */
while (1);
}
#if TCFG_PC_UPDATE
u32 _usb_bulk_rw_test(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw);
u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw)
{
/* if (_usb_bulk_rw_test(usb_device, cbw)) { */
/* return TRUE; */
/* } */
switch (cbw->operationCode) {
//////////////////////Boot Loader Custom CMD
case WRITE_FLASH:
case READ_FLASH:
case OTHER_CMD:
log_d("goto mask pc mode\n");
go_mask_usb_updata();
break;
default:
return FALSE;
}
return TRUE;
}
#else
u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw)
{
return FALSE;
}
#endif

View File

@ -0,0 +1,463 @@
/**
* @file task_pc.c
* @brief 从机模式
* @author chenrixin@zh-jieli.com
* @version 1.0.0
* @date 2020-02-29
*/
#include "system/app_core.h"
#include "system/includes.h"
#include "server/server_core.h"
#include "app_config.h"
#include "app_action.h"
#include "os/os_api.h"
#include "device/sdmmc.h"
#include "app_charge.h"
#include "asm/charge.h"
#if TCFG_USB_SLAVE_ENABLE
#if USB_PC_NO_APP_MODE == 0
#include "app_task.h"
#endif
#include "usb/usb_config.h"
#include "usb/device/usb_stack.h"
#if TCFG_USB_SLAVE_HID_ENABLE
#include "usb/device/hid.h"
#endif
#if TCFG_USB_SLAVE_MSD_ENABLE
#include "usb/device/msd.h"
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
#include "usb/device/cdc.h"
#endif
#if (TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0)
#include "dev_multiplex_api.h"
#endif
#if TCFG_USB_APPLE_DOCK_EN
#include "apple_dock/iAP.h"
#endif
#if (TCFG_CFG_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE)
#include "cfg_tool.h"
#endif
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
#include "asm/chargestore.h"
#endif
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB_TASK]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define USB_TASK_NAME "usb_msd"
#define USBSTACK_EVENT 0x80
#define USBSTACK_MSD_RUN 0x81
#define USBSTACK_MSD_RELASE 0x82
#define USBSTACK_HID 0x83
#define USBSTACK_MSD_RESET 0x84
extern int usb_audio_demo_init(void);
extern void usb_audio_demo_exit(void);
static usb_dev usbfd = 0;//SEC(.usb_g_bss);
static OS_MUTEX msd_mutex ;//SEC(.usb_g_bss);
static u8 msd_in_task;
static u8 msd_run_reset;
static void usb_task(void *p)
{
int ret = 0;
int msg[16];
while (1) {
ret = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
if (ret != OS_TASKQ) {
continue;
}
if (msg[0] != Q_MSG) {
continue;
}
switch (msg[1]) {
#if TCFG_USB_SLAVE_MSD_ENABLE
case USBSTACK_MSD_RUN:
os_mutex_pend(&msd_mutex, 0);
msd_in_task = 1;
#if TCFG_USB_APPLE_DOCK_EN
apple_mfi_link((void *)msg[2]);
#else
USB_MassStorage((void *)msg[2]);
#endif
if (msd_run_reset) {
msd_reset((struct usb_device_t *)msg[2], 0);
msd_run_reset = 0;
}
msd_in_task = 0;
os_mutex_post(&msd_mutex);
break;
case USBSTACK_MSD_RELASE:
os_sem_post((OS_SEM *)msg[2]);
while (1) {
os_time_dly(10000);
}
break;
// case USBSTACK_MSD_RESET:
// os_mutex_pend(&msd_mutex, 0);
// msd_reset((struct usb_device_t *)msg[2], (u32)msg[3]);
// os_mutex_post(&msd_mutex);
// break;
#endif
default:
break;
}
}
}
static void usb_msd_wakeup(struct usb_device_t *usb_device)
{
os_taskq_post_msg(USB_TASK_NAME, 2, USBSTACK_MSD_RUN, usb_device);
}
static void usb_msd_reset_wakeup(struct usb_device_t *usb_device, u32 itf_num)
{
/* os_taskq_post_msg(USB_TASK_NAME, 3, USBSTACK_MSD_RESET, usb_device, itf_num); */
if (msd_in_task) {
msd_run_reset = 1;
} else {
#if TCFG_USB_SLAVE_MSD_ENABLE
msd_reset(usb_device, 0);
#endif
}
}
static void usb_msd_init()
{
r_printf("%s()", __func__);
int err;
os_mutex_create(&msd_mutex);
err = task_create(usb_task, NULL, USB_TASK_NAME);
if (err != OS_NO_ERR) {
r_printf("usb_msd task creat fail %x\n", err);
}
}
static void usb_msd_free()
{
r_printf("%s()", __func__);
os_mutex_del(&msd_mutex, 0);
int err;
OS_SEM sem;
os_sem_create(&sem, 0);
os_taskq_post_msg(USB_TASK_NAME, 2, USBSTACK_MSD_RELASE, (int)&sem);
os_sem_pend(&sem, 0);
err = task_kill(USB_TASK_NAME);
if (!err) {
r_printf("usb_msd_uninit succ!!\n");
} else {
r_printf("usb_msd_uninit fail!!\n");
}
}
#if TCFG_USB_SLAVE_CDC_ENABLE
static void usb_cdc_wakeup(struct usb_device_t *usb_device)
{
//回调函数在中断里,正式使用不要在这里加太多东西阻塞中断,
//或者先post到任务由任务调用cdc_read_data()读取再执行后续工作
const usb_dev usb_id = usb_device2id(usb_device);
u8 buf[64] = {0};
static u8 buf_rx[256] = {0};
static u8 rx_len_total = 0;
u32 rlen;
log_debug("cdc rx hook");
rlen = cdc_read_data(usb_id, buf, 64);
/* put_buf(buf, rlen);//固件三部测试使用 */
/* cdc_write_data(usb_id, buf, rlen);//固件三部测试使用 */
if ((buf[0] == 0x5A) && (buf[1] == 0xAA) && (buf[2] == 0xA5)) {
memset(buf_rx, 0, 256);
memcpy(buf_rx, buf, rlen);
/* log_info("need len = %d\n", buf_rx[5] + 6); */
/* log_info("rx len = %d\n", rlen); */
if ((buf_rx[5] + 6) == rlen) {
rx_len_total = 0;
#if TCFG_CFG_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE
#if (TCFG_COMM_TYPE == TCFG_USB_COMM)
/* put_buf(buf_rx, rlen); */
online_cfg_tool_data_deal(buf_rx, rlen);
#else
put_buf(buf, rlen);
cdc_write_data(usb_id, buf, rlen);
#endif
#endif
} else {
rx_len_total += rlen;
}
} else {
if ((rx_len_total + rlen) > 256) {
memset(buf_rx, 0, 256);
rx_len_total = 0;
return;
}
memcpy(buf_rx + rx_len_total, buf, rlen);
/* log_info("need len = %d\n", buf_rx[5] + 6); */
/* log_info("rx len = %d\n", rx_len_total + rlen); */
if ((buf_rx[5] + 6) == (rx_len_total + rlen)) {
#if TCFG_CFG_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE
#if (TCFG_COMM_TYPE == TCFG_USB_COMM)
/* put_buf(buf_rx, rx_len_total + rlen); */
online_cfg_tool_data_deal(buf_rx, rx_len_total + rlen);
#else
put_buf(buf, rlen);
cdc_write_data(usb_id, buf, rlen);
#endif
#endif
rx_len_total = 0;
} else {
rx_len_total += rlen;
}
}
}
#endif
void usb_start()
{
#if TCFG_USB_SLAVE_AUDIO_ENABLE
usb_audio_demo_init();
#endif
#ifdef USB_DEVICE_CLASS_CONFIG
g_printf("USB_DEVICE_CLASS_CONFIG:%x", USB_DEVICE_CLASS_CONFIG);
#if TCFG_USB_CDC_BACKGROUND_RUN
usb_device_mode(usbfd, USB_DEVICE_CLASS_CONFIG | CDC_CLASS);
#else
usb_device_mode(usbfd, USB_DEVICE_CLASS_CONFIG);
#endif
#endif
#if TCFG_USB_SLAVE_MSD_ENABLE
//没有复用时候判断 sd开关
//复用时候判断是否参与复用
#if (!TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_SD0_ENABLE)\
||(TCFG_SD0_ENABLE && TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_DM_MULTIPLEX_WITH_SD_PORT != 0)
msd_register_disk("sd0", NULL);
#endif
#if (!TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_SD1_ENABLE)\
||(TCFG_SD1_ENABLE && TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_DM_MULTIPLEX_WITH_SD_PORT != 1)
msd_register_disk("sd1", NULL);
#endif
#if TCFG_NOR_FAT
msd_register_disk("fat_nor", NULL);
#endif
#if TCFG_VIR_UDISK_ENABLE
msd_register_disk("vir_udisk0", NULL);
#endif
msd_set_wakeup_handle(usb_msd_wakeup);
msd_set_reset_wakeup_handle(usb_msd_reset_wakeup);
usb_msd_init();
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
cdc_set_wakeup_handler(usb_cdc_wakeup);
#endif
}
static void usb_remove_disk()
{
#if TCFG_USB_SLAVE_MSD_ENABLE
os_mutex_pend(&msd_mutex, 0);
msd_unregister_all();
os_mutex_post(&msd_mutex);
#endif
}
void usb_pause()
{
log_info("usb pause");
usb_sie_disable(usbfd);
#if TCFG_USB_SLAVE_MSD_ENABLE
if (msd_set_wakeup_handle(NULL)) {
usb_remove_disk();
usb_msd_free();
}
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
usb_audio_demo_exit();
#endif
usb_device_mode(usbfd, 0);
}
void usb_stop()
{
log_info("App Stop - usb");
usb_pause();
usb_sie_close(usbfd);
}
#if TCFG_USB_CDC_BACKGROUND_RUN
void usb_cdc_background_run()
{
g_printf("CDC is running in the background");
usb_device_mode(0, CDC_CLASS);
cdc_set_wakeup_handler(usb_cdc_wakeup);
}
#endif
int pc_device_event_handler(struct sys_event *event)
{
if ((int)event->arg != DEVICE_EVENT_FROM_OTG) {
return false;
}
int switch_app_case = false;
const char *usb_msg = (const char *)event->u.dev.value;
log_debug("usb event : %d DEVICE_EVENT_FROM_OTG %s", event->u.dev.event, usb_msg);
if (usb_msg[0] == 's') {
if (event->u.dev.event == DEVICE_EVENT_IN) {
log_info("usb %c online", usb_msg[2]);
usbfd = usb_msg[2] - '0';
#if USB_PC_NO_APP_MODE
usb_start();
#elif TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
#if TCFG_USB_CDC_BACKGROUND_RUN
mult_sdio_suspend();
usb_cdc_background_run();
switch_app_case = 0;
#else
usb_otg_suspend(0, OTG_KEEP_STATE);
mult_sdio_suspend();
usb_pause();
mult_sdio_resume();
switch_app_case = 0;
#endif//TCFG_USB_CDC_BACKGROUND_RUN
#else
#if (TWFG_APP_POWERON_IGNORE_DEV && TCFG_USB_CDC_BACKGROUND_RUN && TCFG_PC_ENABLE)
if (jiffies_to_msecs(jiffies) < TWFG_APP_POWERON_IGNORE_DEV) {
usb_cdc_background_run();
switch_app_case = 0;
} else {
usb_pause();
switch_app_case = 1;
}
#elif (TCFG_USB_CDC_BACKGROUND_RUN)
usb_cdc_background_run();
switch_app_case = 0;
#elif (TWFG_APP_POWERON_IGNORE_DEV == 0)
usb_pause();
switch_app_case = 1;
#else
usb_pause();
switch_app_case = 1;
#endif
#endif
} else if (event->u.dev.event == DEVICE_EVENT_OUT) {
log_info("usb %c offline", usb_msg[2]);
#if USB_PC_NO_APP_MODE
usb_stop();
#else
#ifdef CONFIG_SOUNDBOX
if (true == app_check_curr_task(APP_PC_TASK)) {
#else
if (app_get_curr_task() == APP_PC_TASK) {
#endif
switch_app_case = 2;
} else {
/* 此处的模式限制会在USB已连接,蓝牙播歌切换到蓝牙模式后再拔出USB的情况下,
无法检测到再次插入USB */
#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
mult_sdio_suspend();
#endif
usb_stop();
#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
mult_sdio_resume();
#endif
}
#endif
}
}
return switch_app_case;
}
#if USB_PC_NO_APP_MODE
void usbstack_init()
{
register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_OTG, 2,
(void (*)(struct sys_event *))pc_device_event_handler);
}
void usbstack_exit()
{
unregister_sys_event_handler((void (*)(struct sys_event *))pc_device_event_handler);
}
#endif
#if (TCFG_OTG_MODE & OTG_DET_DM_ONLY)
static void otg_sof_check_before_hook()
{
log_debug("sof_check_before");
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
power_wakeup_index_enable(2, 0);
chargestore_api_stop();
#endif
}
static void otg_sof_check_after_hook()
{
log_debug("sof_check_after");
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
chargestore_api_restart();
power_wakeup_index_enable(2, 1);
#endif
}
static int otg_sof_check_hook_register()
{
//需要在otg定时器启动之前即devices_init()之前)注册钩子函数
usb_otg_sof_check_register_hooks(otg_sof_check_before_hook,
otg_sof_check_after_hook);
return 0;
}
early_initcall(otg_sof_check_hook_register);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,514 @@
#include "app_config.h"
#include "system/includes.h"
#include "printf.h"
#include "usb/usb_config.h"
#include "usb/device/usb_stack.h"
#if TCFG_USB_SLAVE_AUDIO_ENABLE
#include "usb/device/uac_audio.h"
#include "uac_stream.h"
#include "audio_config.h"
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
#include "audio_track.h"
/* #endif */
#define LOG_TAG_CONST USB
#define LOG_TAG "[UAC]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define UAC_DEBUG_ECHO_MODE 0
static volatile u8 speaker_stream_is_open = 0;
struct uac_speaker_handle {
cbuffer_t cbuf;
volatile u8 need_resume;
u8 channel;
u8 alive;
void *buffer;
void *audio_track;
//void (*rx_handler)(int, void *, int);
};
static void (*uac_rx_handler)(int, void *, int) = NULL;
#if (SOUNDCARD_ENABLE)
#define UAC_BUFFER_SIZE (4 * 1024)
#else
#define UAC_BUFFER_SIZE (1 * 1024)
#endif
#define UAC_BUFFER_MAX (UAC_BUFFER_SIZE * 50 / 100)
static struct uac_speaker_handle *uac_speaker = NULL;
#if USB_MALLOC_ENABLE
#else
static struct uac_speaker_handle uac_speaker_handle SEC(.uac_var);
static u8 uac_rx_buffer[UAC_BUFFER_SIZE] ALIGNED(4) SEC(.uac_rx);
#endif
u32 uac_speaker_stream_length()
{
return UAC_BUFFER_SIZE;
}
u32 uac_speaker_stream_size()
{
if (!speaker_stream_is_open) {
return 0;
}
if (uac_speaker) {
return cbuf_get_data_size(&uac_speaker->cbuf);
}
return 0;
}
u32 uac_speaker_get_alive()
{
if (uac_speaker) {
return uac_speaker->alive;
}
return 0;
}
void uac_speaker_set_alive(u8 alive)
{
local_irq_disable();
if (uac_speaker) {
uac_speaker->alive = alive;
}
local_irq_enable();
}
void uac_speaker_stream_buf_clear(void)
{
if (speaker_stream_is_open) {
cbuf_clear(&uac_speaker->cbuf);
}
}
void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int))
{
uac_rx_handler = rx_handler;
/* if (uac_speaker) { */
/* uac_speaker->rx_handler = rx_handler; */
/* } */
}
int uac_speaker_stream_sample_rate(void)
{
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
if (uac_speaker && uac_speaker->audio_track) {
int sr = audio_local_sample_track_rate(uac_speaker->audio_track);
if ((sr < (SPK_AUDIO_RATE + 100)) && (sr > (SPK_AUDIO_RATE - 100))) {
return sr;
}
/* printf("uac audio_track reset \n"); */
/* local_irq_disable(); */
/* audio_local_sample_track_close(uac_speaker->audio_track); */
/* uac_speaker->audio_track = audio_local_sample_track_open(SPK_CHANNEL, SPK_AUDIO_RATE, 1000); */
/* local_irq_enable(); */
}
/* #endif */
return SPK_AUDIO_RATE;
}
void uac_speaker_stream_write(const u8 *obuf, u32 len)
{
if (speaker_stream_is_open) {
//write dac
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
if (uac_speaker->audio_track) {
audio_local_sample_track_in_period(uac_speaker->audio_track, (len >> 1) / uac_speaker->channel);
}
/* #endif */
int wlen = cbuf_write(&uac_speaker->cbuf, (void *)obuf, len);
if (wlen != len) {
//putchar('W');
}
//if (uac_speaker->rx_handler) {
if (uac_rx_handler) {
/* if (uac_speaker->cbuf.data_len >= UAC_BUFFER_MAX) { */
// 马上就要满了,赶紧取走
uac_speaker->need_resume = 1; //2020-12-22注:无需唤醒
/* } */
if (uac_speaker->need_resume) {
uac_speaker->need_resume = 0;
uac_rx_handler(0, (void *)obuf, len);
//uac_speaker->rx_handler(0, (void *)obuf, len);
}
}
uac_speaker->alive = 0;
}
}
int uac_speaker_read(void *priv, void *data, u32 len)
{
int r_len;
int err = 0;
local_irq_disable();
if (!speaker_stream_is_open) {
local_irq_enable();
return 0;
}
r_len = cbuf_get_data_size(&uac_speaker->cbuf);
if (r_len) {
r_len = r_len > len ? len : r_len;
r_len = cbuf_read(&uac_speaker->cbuf, data, r_len);
if (!r_len) {
putchar('U');
}
}
if (r_len == 0) {
uac_speaker->need_resume = 1;
}
local_irq_enable();
return r_len;
}
void uac_speaker_stream_open(u32 samplerate, u32 ch)
{
if (speaker_stream_is_open) {
return;
}
log_info("%s", __func__);
if (!uac_speaker) {
#if USB_MALLOC_ENABLE
uac_speaker = zalloc(sizeof(struct uac_speaker_handle));
if (!uac_speaker) {
return;
}
uac_speaker->buffer = malloc(UAC_BUFFER_SIZE);
if (!uac_speaker->buffer) {
free(uac_speaker);
uac_speaker = NULL;
goto __err;
}
#else
uac_speaker = &uac_speaker_handle;
memset(uac_speaker, 0, sizeof(struct uac_speaker_handle));
uac_speaker->buffer = uac_rx_buffer;
#endif
uac_speaker->channel = ch;
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
uac_speaker->audio_track = audio_local_sample_track_open(ch, samplerate, 1000);
/* #endif */
}
//uac_speaker->rx_handler = NULL;
cbuf_init(&uac_speaker->cbuf, uac_speaker->buffer, UAC_BUFFER_SIZE);
speaker_stream_is_open = 1;
struct sys_event event;
event.type = SYS_DEVICE_EVENT;
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
event.u.dev.event = USB_AUDIO_PLAY_OPEN;
event.u.dev.value = (int)((ch << 24) | samplerate);
#if !UAC_DEBUG_ECHO_MODE
sys_event_notify(&event);
#endif
return;
__err:
return;
}
void uac_speaker_stream_close()
{
if (speaker_stream_is_open == 0) {
return;
}
log_info("%s", __func__);
speaker_stream_is_open = 0;
if (uac_speaker) {
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
audio_local_sample_track_close(uac_speaker->audio_track);
/* #endif */
uac_speaker->audio_track = NULL;
#if USB_MALLOC_ENABLE
if (uac_speaker->buffer) {
free(uac_speaker->buffer);
}
free(uac_speaker);
#endif
uac_speaker = NULL;
}
struct sys_event event;
event.type = SYS_DEVICE_EVENT;
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
event.u.dev.event = USB_AUDIO_PLAY_CLOSE;
event.u.dev.value = (int)0;
#if !UAC_DEBUG_ECHO_MODE
sys_event_notify(&event);
#endif
}
int uac_get_spk_vol()
{
int max_vol = get_max_sys_vol();
int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
if (vol * 100 / max_vol < 100) {
return vol * 100 / max_vol;
} else {
return 99;
}
return 0;
}
static u8 flag_uac_event_enable = 1;
void set_uac_event_flag(u8 en)
{
flag_uac_event_enable = en;
}
u8 get_uac_event_flag(void)
{
return flag_uac_event_enable;
}
static volatile u32 mic_stream_is_open;
u8 uac_get_mic_stream_status(void)
{
return mic_stream_is_open;
}
void uac_mute_volume(u32 type, u32 l_vol, u32 r_vol)
{
struct sys_event event;
event.type = SYS_DEVICE_EVENT;
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
static u32 last_spk_l_vol = (u32) - 1, last_spk_r_vol = (u32) - 1;
static u32 last_mic_vol = (u32) - 1;
if (!get_uac_event_flag()) {
return;
}
switch (type) {
case MIC_FEATURE_UNIT_ID: //MIC
if (mic_stream_is_open == 0) {
return ;
}
if (l_vol == last_mic_vol) {
return;
}
last_mic_vol = l_vol;
event.u.dev.event = USB_AUDIO_SET_MIC_VOL;
break;
case SPK_FEATURE_UNIT_ID: //SPK
if (speaker_stream_is_open == 0) {
return;
}
if (l_vol == last_spk_l_vol && r_vol == last_spk_r_vol) {
return;
}
last_spk_l_vol = l_vol;
last_spk_r_vol = r_vol;
event.u.dev.event = USB_AUDIO_SET_PLAY_VOL;
break;
default:
break;
}
event.u.dev.value = (int)(r_vol << 16 | l_vol);
#if !UAC_DEBUG_ECHO_MODE
sys_event_notify(&event);
#endif
}
static int (*mic_tx_handler)(int, void *, int) = NULL;
int uac_mic_stream_read(u8 *buf, u32 len)
{
if (mic_stream_is_open == 0) {
return 0;
}
#if 0//48K 1ksin
const s16 sin_48k[] = {
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
};
u16 *l_ch = (u16 *)buf;
u16 *r_ch = (u16 *)buf;
r_ch++;
for (int i = 0; i < len / 2; i++) {
*l_ch = sin_48k[i];
*r_ch = sin_48k[i];
l_ch += 1;
r_ch += 1;
}
return len;
#elif UAC_DEBUG_ECHO_MODE
#if MIC_CHANNEL == 2
uac_speaker_read(NULL, buf, len);
const s16 sin_48k[] = {
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
};
u16 *r_ch = (u16 *)buf;
r_ch++;
for (int i = 0; i < len / 4; i++) {
*r_ch = sin_48k[i];
r_ch += 2;
}
#else
uac_speaker_read(NULL, buf, len * 2);
u16 *r_ch = (u16 *)buf;
for (int i = 0; i < len / 2; i++) {
r_ch[i] = r_ch[i * 2];
}
#endif
return len;
#else
if (mic_tx_handler) {
#if 1
return mic_tx_handler(0, buf, len);
#else
//16bit ---> 24bit
int rlen = mic_tx_handler(0, tmp_buf, len / 3 * 2);
rlen /= 2; //sampe point
for (int i = 0 ; i < rlen ; i++) {
buf[i * 3] = 0;
buf[i * 3 + 1] = tmp_buf[i * 2];
buf[i * 3 + 2] = tmp_buf[i * 2 + 1];
}
#endif
} else {
//putchar('N');
}
return 0;
#endif
return 0;
}
void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(int, void *, int))
{
mic_tx_handler = tx_handler;
}
static u32 mic_close_tid = 0;
static u8 mic_sw;
u32 uac_mic_stream_open(u32 samplerate, u32 frame_len, u32 ch)
{
mic_sw = 1;
if (mic_stream_is_open) {
return 0;
}
/* mic_tx_handler = NULL; */
log_info("%s", __func__);
struct sys_event event;
event.type = SYS_DEVICE_EVENT;
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
event.u.dev.event = USB_AUDIO_MIC_OPEN;
event.u.dev.value = (int)((ch << 24) | samplerate);
mic_stream_is_open = 1;
#if !UAC_DEBUG_ECHO_MODE
sys_event_notify(&event);
#endif
return 0;
}
static void uac_mic_stream_close_delay()
{
mic_close_tid = 0;
if (!mic_sw) {
} else {
return ;
}
log_info("%s", __func__);
struct sys_event event;
event.type = SYS_DEVICE_EVENT;
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
event.u.dev.event = USB_AUDIO_MIC_CLOSE;
event.u.dev.value = (int)0;
mic_stream_is_open = 0;
#if !UAC_DEBUG_ECHO_MODE
sys_event_notify(&event);
#endif
}
void uac_mic_stream_close()
{
mic_sw = 0;
if (mic_stream_is_open == 0) {
return ;
}
//FIXME:
//未知原因出现频繁开关mic导致出现audio或者蓝牙工作异常
//收到mic关闭命令后延时1s再发消息通知audio模块执行关闭动作
//如果在1s之内继续收到usb下发的关闭命令则继续推迟1s。
if (mic_close_tid == 0) {
mic_close_tid = sys_hi_timeout_add(NULL, uac_mic_stream_close_delay, 1000);
} else {
sys_hi_timeout_modify(mic_close_tid, 1000);
}
}
_WEAK_
s8 app_audio_get_volume(u8 state)
{
return 88;
}
_WEAK_
void usb_audio_demo_exit(void)
{
}
_WEAK_
int usb_audio_demo_init(void)
{
return 0;
}
_WEAK_
u8 get_max_sys_vol(void)
{
return 100;
}
_WEAK_
void *audio_local_sample_track_open(u8 channel, int sample_rate, int period)
{
return NULL;
}
_WEAK_
int audio_local_sample_track_in_period(void *c, int samples)
{
return 0;
}
_WEAK_
void audio_local_sample_track_close(void *c)
{
}
#endif

View File

@ -0,0 +1,31 @@
/*****************************************************************
>file name : usb_audio.h
>author : lichao
>create time : Wed 22 May 2019 10:39:35 AM CST
*****************************************************************/
#ifndef _UAC_STREAM_H_
#define _UAC_STREAM_H_
#include "typedef.h"
enum uac_event {
USB_AUDIO_PLAY_OPEN = 0x0,
USB_AUDIO_PLAY_CLOSE,
USB_AUDIO_MIC_OPEN,
USB_AUDIO_MIC_CLOSE,
// USB_AUDIO_MUTE,
USB_AUDIO_SET_PLAY_VOL,
USB_AUDIO_SET_MIC_VOL,
};
void uac_speaker_stream_buf_clear(void);
u32 uac_speaker_stream_length();
u32 uac_speaker_stream_size();
void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int));
void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(int, void *, int));
int uac_speaker_stream_sample_rate(void);
int uac_speaker_read(void *priv, void *data, u32 len);
u32 uac_speaker_get_alive();
void uac_speaker_set_alive(u8 alive);
#endif

View File

@ -0,0 +1,258 @@
#include "usb/device/usb_stack.h"
#include "usb_config.h"
#include "usb/device/msd.h"
#include "usb/scsi.h"
#include "usb/device/hid.h"
#include "usb/device/uac_audio.h"
#include "usb/device/cdc.h"
#include "irq.h"
#include "init.h"
#include "gpio.h"
#include "app_config.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_SLAVE_ENABLE
static void usb_device_init(const usb_dev usb_id)
{
usb_config(usb_id);
usb_g_sie_init(usb_id);
#if defined(FUSB_MODE) && FUSB_MODE
usb_write_power(usb_id, 0x40);
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
usb_write_power(usb_id, 0x60);
#endif
usb_slave_init(usb_id);
u8 *ep0_dma_buffer = usb_alloc_ep_dmabuffer(usb_id, 0, 64);
usb_set_dma_raddr(usb_id, 0, ep0_dma_buffer);
usb_set_dma_raddr(usb_id, 1, ep0_dma_buffer);
usb_set_dma_raddr(usb_id, 2, ep0_dma_buffer);
usb_set_dma_raddr(usb_id, 3, ep0_dma_buffer);
usb_set_dma_raddr(usb_id, 4, ep0_dma_buffer);
usb_write_intr_usbe(usb_id, INTRUSB_RESET_BABBLE | INTRUSB_SUSPEND);
usb_clr_intr_txe(usb_id, -1);
usb_clr_intr_rxe(usb_id, -1);
usb_set_intr_txe(usb_id, 0);
usb_set_intr_rxe(usb_id, 0);
usb_g_isr_reg(usb_id, 3, 0);
/* usb_sof_isr_reg(usb_id,3,0); */
/* usb_sofie_enable(usb_id); */
/* USB_DEBUG_PRINTF("ep0 addr %x %x\n", usb_get_dma_taddr(0), ep0_dma_buffer); */
}
static void usb_device_hold(const usb_dev usb_id)
{
usb_g_hold(usb_id);
usb_release(usb_id);
}
static int usb_ep_conflict_check(const usb_dev usb_id);
int usb_device_mode(const usb_dev usb_id, const u32 class)
{
/* usb_device_set_class(CLASS_CONFIG); */
u8 class_index = 0;
if (class == 0) {
gpio_direction_input(IO_PORT_DM + 2 * usb_id);
gpio_set_pull_up(IO_PORT_DM + 2 * usb_id, 0);
gpio_set_pull_down(IO_PORT_DM + 2 * usb_id, 0);
gpio_set_die(IO_PORT_DM + 2 * usb_id, 0);
gpio_direction_input(IO_PORT_DP + 2 * usb_id);
gpio_set_pull_up(IO_PORT_DP + 2 * usb_id, 0);
gpio_set_pull_down(IO_PORT_DP + 2 * usb_id, 0);
gpio_set_die(IO_PORT_DP + 2 * usb_id, 0);
os_time_dly(15);
gpio_set_die(IO_PORT_DM + 2 * usb_id, 1);
gpio_set_die(IO_PORT_DP + 2 * usb_id, 1);
#if TCFG_USB_SLAVE_MSD_ENABLE
msd_release(usb_id);
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
uac_release(usb_id);
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
cdc_release(usb_id);
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
hid_release(usb_id);
#endif
usb_device_hold(usb_id);
return 0;
}
/* int ret = usb_ep_conflict_check(usb_id); */
/* if (ret) { */
/* return ret; */
/* } */
usb_memory_init();
usb_add_desc_config(usb_id, MAX_INTERFACE_NUM, NULL);
#if TCFG_USB_SLAVE_MSD_ENABLE
if ((class & MASSSTORAGE_CLASS) == MASSSTORAGE_CLASS) {
log_info("add desc msd");
usb_add_desc_config(usb_id, class_index++, msd_desc_config);
msd_register(usb_id);
}
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
if ((class & AUDIO_CLASS) == AUDIO_CLASS) {
log_info("add audio desc");
usb_add_desc_config(usb_id, class_index++, uac_audio_desc_config);
uac_register(usb_id, AUDIO_CLASS);
} else if ((class & SPEAKER_CLASS) == SPEAKER_CLASS) {
log_info("add desc speaker");
usb_add_desc_config(usb_id, class_index++, uac_spk_desc_config);
uac_register(usb_id, SPEAKER_CLASS);
} else if ((class & MIC_CLASS) == MIC_CLASS) {
log_info("add desc mic");
usb_add_desc_config(usb_id, class_index++, uac_mic_desc_config);
uac_register(usb_id, MIC_CLASS);
}
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
if ((class & HID_CLASS) == HID_CLASS) {
log_info("add desc std hid");
usb_add_desc_config(usb_id, class_index++, hid_desc_config);
hid_register(usb_id);
}
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
if ((class & CDC_CLASS) == CDC_CLASS) {
log_info("add desc cdc");
usb_add_desc_config(usb_id, class_index++, cdc_desc_config);
cdc_register(usb_id);
}
#endif
usb_device_init(usb_id);
user_setup_filter_install(usb_id2device(usb_id));
return 0;
}
/* module_initcall(usb_device_mode); */
static int usb_ep_conflict_check(const usb_dev usb_id)
{
u8 usb_ep_tx_list[] = {
#if TCFG_USB_SLAVE_MSD_ENABLE
MSD_BULK_EP_IN,
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
HID_EP_IN,
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
MIC_ISO_EP_IN,
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
CDC_DATA_EP_IN,
#if CDC_INTR_EP_ENABLE
CDC_INTR_EP_IN,
#endif
#endif
};
u8 usb_ep_rx_list[] = {
#if TCFG_USB_SLAVE_MSD_ENABLE
MSD_BULK_EP_OUT,
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
HID_EP_OUT,
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
SPK_ISO_EP_OUT,
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
CDC_DATA_EP_OUT,
#endif
};
int ret = 0;
int i, j;
for (i = 0; i < sizeof(usb_ep_tx_list) - 1; i++) {
for (j = i + 1; j < sizeof(usb_ep_tx_list); j++) {
if (usb_ep_tx_list[i] == usb_ep_tx_list[j]) {
ret = -1;
ASSERT(0, "ep%d conflict, dir in\n", usb_ep_tx_list[i]);
goto __exit;
}
}
}
for (i = 0; i < sizeof(usb_ep_rx_list) - 1; i++) {
for (j = i + 1; j < sizeof(usb_ep_rx_list); j++) {
if (usb_ep_rx_list[i] == usb_ep_rx_list[j]) {
ret = -1;
ASSERT(0, "ep%d conflict, dir out\n", usb_ep_rx_list[i]);
goto __exit;
}
}
}
__exit:
return ret;
}
#endif
/*
* @brief otg检测中sof初始化不要放在TCFG_USB_SLAVE_ENABLE里
* @parm id usb设备号
* @return 0 ,忽略sof检查1 等待sof信号
*/
u32 usb_otg_sof_check_init(const usb_dev id)
{
/* return 0;// */
u8 *ep0_dma_buffer = usb_alloc_ep_dmabuffer(id, 0, 64);
usb_g_sie_init(id);
#ifdef USB_HW_20
//husb调用完usb_g_sie_init()或者收到usb reset中断intrusbeintrtxe
//intrrxe会复位成默认值不手动清零以及关中断会收到usb reset中断由于
//空指针问题导致异常
usb_write_intr_usbe(id, 0);
usb_clr_intr_txe(id, -1);
usb_clr_intr_rxe(id, -1);
if (id == 0) {
unrequest_irq(IRQ_USB_CTRL_IDX);
#if USB_MAX_HW_NUM > 1
} else {
unrequest_irq(IRQ_USB1_CTRL_IDX);
#endif
}
#endif
#if defined(FUSB_MODE) && FUSB_MODE
usb_write_power(id, 0x40);
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
usb_write_power(id, 0x60);
#endif
usb_set_dma_raddr(id, 0, ep0_dma_buffer);
for (int ep = 1; ep < USB_MAX_HW_EPNUM; ep++) {
usb_disable_ep(id, ep);
}
usb_sof_clr_pnd(id);
return 1;
}

View File

@ -0,0 +1,223 @@
#include "usb/device/usb_stack.h"
#include "usb_config.h"
#include "usb/device/msd.h"
#include "usb/scsi.h"
#include "usb/device/hid.h"
#include "usb/device/uac_audio.h"
#include "irq.h"
#include "init.h"
#include "gpio.h"
#include "app_config.h"
#if TCFG_USB_APPLE_DOCK_EN
#include "apple_dock/iAP.h"
#endif
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_SLAVE_ENABLE
static const u8 user_stirng[] = {
24,
0x03,
'U', 0x00,
'S', 0x00,
'B', 0x00,
'A', 0x00,
'u', 0x00,
'd', 0x00,
'i', 0x00,
'o', 0x00,
'1', 0x00,
'.', 0x00,
'0', 0x00,
};
#if TCFG_USB_APPLE_DOCK_EN
static const u8 IAP_interface_string[] = {
0x1c, 0x03,
//iAP Interface
0x69, 0x00, 0x41, 0x00, 0x50, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x74, 0x00,
0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00
};
#endif
static u8 root2_testing;
u32 usb_root2_testing()
{
#if USB_ROOT2
return root2_testing;
#else
return 0;
#endif
}
u32 check_ep_vaild(u32 ep)
{
u32 en = 0;
switch (ep) {
case 0:
en = 1;
break;
#if TCFG_USB_SLAVE_MSD_ENABLE
case 1:
en = 1;
break;
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
case 2:
en = 1;
break;
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
case 3:
en = 1;
break;
#endif
case 4:
break;
}
return en;
}
static u32 setup_endpoint(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 tx_len = 0;
u8 *tx_payload = usb_get_setup_buffer(usb_device);
#if TCFG_USB_SLAVE_AUDIO_ENABLE
if (uac_setup_endpoint(usb_device, req)) {
return 1;
}
#endif
u32 ep = LOBYTE(req->wIndex) & 0x0f;
if (check_ep_vaild(ep) == 0) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
return 1;// not zero user handle this request
}
return 0;
}
static u32 setup_device(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 ret = 0;
switch (req->bRequest) {
case USB_REQ_GET_DESCRIPTOR:
switch (HIBYTE(req->wValue)) {
case USB_DT_STRING:
switch (LOBYTE(req->wValue)) {
#if TCFG_USB_SLAVE_AUDIO_ENABLE
case SPEAKER_STR_INDEX:
case MIC_STR_INDEX:
if (usb_device->bDeviceStates == USB_DEFAULT) {
ret = 0;
} else {
usb_set_data_payload(usb_device, req, user_stirng, sizeof(user_stirng));
ret = 1;
}
break;
#endif
#if TCFG_USB_APPLE_DOCK_EN
case MSD_STR_INDEX:
if (apple_mfi_chip_online_lib()) {
y_printf("MSD_STR_INDEX \n");
usb_set_data_payload(usb_device, req, IAP_interface_string, sizeof(IAP_interface_string));
apple_mfi_pass_ready_set_api();
extern void apple_usb_msd_wakeup(struct usb_device_t *usb_device);
apple_usb_msd_wakeup(usb_device);
ret = 1;
break;
}
#endif
default:
break;
}
break;
case USB_DT_DEVICE:
#if USB_ROOT2
if (req->wLength == 0xffff) {
root2_testing = 1;
}
#endif
break;
}
break;
case USB_REQ_SET_CONFIGURATION:
break;
case USB_REQ_SET_ADDRESS:
/* if(req->wLength || req->wIndex){ */
/* ret = 1; */
/* usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); */
/* dump_setup_request(req); */
/* log_debug_hexdump((u8 *)req, 8); */
/* } */
break;
}
return ret;
}
static u32 setup_other(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
{
u32 ret = 0;
u32 tx_len;
u8 *tx_payload = usb_get_setup_buffer(usb_device);
switch (req->bRequest) {
case USB_REQ_GET_STATUS:
#if TCFG_TYPEC_EARPHONE_TEST_FILTER
tx_len = 1;
tx_payload[0] = 0xfe;
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
#endif
break;
default:
ret = 1 ;
break;
}
return ret;
}
static u32 user_setup_filter(struct usb_device_t *usb_device, struct usb_ctrlrequest *request)
{
// dump_setup_request(request);
// log_debug_hexdump((u8 *)request, 8);
u32 ret = 0;
u32 recip = request->bRequestType & USB_RECIP_MASK;
switch (recip) {
case USB_RECIP_DEVICE:
ret = setup_device(usb_device, request);
break;
case USB_RECIP_INTERFACE:
break;
case USB_RECIP_ENDPOINT:
ret = setup_endpoint(usb_device, request);
break;
case USB_RECIP_OTHER:
ret = setup_other(usb_device, request);
break;
}
#if 0
const char *statas[] = {"USB_ATTACHED", "USB_POWERED", "USB_DEFAULT",
"USB_ADDRESS", "USB_CONFIGURED", "USB_SUSPENDED"
};
const char *phases[] = {"SETUP", "IN", "OUT",
"STALL",
};
printf("state:%s phase: %s", statas[usb_device->bDeviceStates],
phases[usb_device->bsetup_phase]);
#endif
return ret;// not zero user handle this request
}
void user_setup_filter_install(struct usb_device_t *usb_device)
{
usb_set_setup_hook(usb_device, user_setup_filter);
}
#endif