chore: Remove tracked build artifacts
This commit is contained in:
@ -1,490 +0,0 @@
|
||||
#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
|
||||
@ -1,23 +0,0 @@
|
||||
#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
|
||||
@ -1,457 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
@ -1,202 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
@ -1,332 +0,0 @@
|
||||
#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
@ -1,76 +0,0 @@
|
||||
#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
|
||||
|
||||
@ -1,463 +0,0 @@
|
||||
/**
|
||||
* @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
@ -1,514 +0,0 @@
|
||||
#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
|
||||
@ -1,31 +0,0 @@
|
||||
/*****************************************************************
|
||||
>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
|
||||
@ -1,258 +0,0 @@
|
||||
#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中断,intrusbe,intrtxe,
|
||||
//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;
|
||||
}
|
||||
@ -1,223 +0,0 @@
|
||||
#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
|
||||
@ -1,459 +0,0 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "device_drive.h"
|
||||
#include "adb.h"
|
||||
#include "usb_config.h"
|
||||
#include "app_config.h"
|
||||
#if TCFG_ADB_ENABLE
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[adb]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#include "adb_rsa_key.c"
|
||||
|
||||
struct adb_device_t adb;
|
||||
|
||||
struct device adb_device;
|
||||
void aoa_switch(struct usb_host_device *host_dev);
|
||||
|
||||
static int set_adb_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_adb_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct interface_ctrl adb_ops = {
|
||||
.interface_class = USB_CLASS_ADB,
|
||||
.set_power = set_adb_power,
|
||||
.get_power = get_adb_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info adb_inf = {
|
||||
.ctrl = (struct interface_ctrl *) &adb_ops,
|
||||
.dev.adb = &adb,
|
||||
};
|
||||
|
||||
u32 usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
for (int i = 0; i < interface->bNumEndpoints; i++) {
|
||||
struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (endpoint->bDescriptorType == USB_DT_ENDPOINT) {
|
||||
if (endpoint->bmAttributes == USB_ENDPOINT_XFER_BULK) {
|
||||
if (endpoint->bEndpointAddress & USB_DIR_IN) {
|
||||
adb.extr_in = endpoint->bEndpointAddress & 0xf;
|
||||
} else {
|
||||
adb.extr_out = endpoint->bEndpointAddress;
|
||||
}
|
||||
}
|
||||
pBuf += USB_DT_ENDPOINT_SIZE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printf("%s() %x %x\n", __func__, adb.extr_in, adb.extr_out);
|
||||
return pBuf - (u8 *)interface ;
|
||||
}
|
||||
|
||||
int usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
adb_device.private_data = host_dev;
|
||||
|
||||
host_dev->interface_info[interface_num] = &adb_inf;
|
||||
|
||||
for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) {
|
||||
struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf;
|
||||
|
||||
if (end_desc->bDescriptorType != USB_DT_ENDPOINT ||
|
||||
end_desc->bLength != USB_DT_ENDPOINT_SIZE) {
|
||||
log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength);
|
||||
return -USB_DT_ENDPOINT;
|
||||
}
|
||||
|
||||
len += USB_DT_ENDPOINT_SIZE;
|
||||
pBuf += USB_DT_ENDPOINT_SIZE;
|
||||
|
||||
if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
|
||||
if (end_desc->bEndpointAddress & USB_DIR_IN) {
|
||||
adb.host_epin = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK);
|
||||
adb.target_epin = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
adb.rxmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
log_debug("D(%d)->H(%d)", adb.target_epin, adb.host_epin);
|
||||
} else {
|
||||
adb.host_epout = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK);
|
||||
adb.target_epout = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
adb.txmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
log_debug("H(%d)->D(%d)", adb.host_epout, adb.target_epout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 *ep_buffer = usb_h_get_ep_buffer(usb_id, adb.host_epin | USB_DIR_IN);
|
||||
usb_h_ep_config(usb_id, adb.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
|
||||
|
||||
|
||||
ep_buffer = usb_h_get_ep_buffer(usb_id, adb.host_epout | USB_DIR_OUT);
|
||||
usb_h_ep_config(usb_id, adb.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int adb_send_packet(struct amessage *msg, const u8 *data_ptr)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
return usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, NULL, 0);
|
||||
}
|
||||
u32 cnt;
|
||||
u32 count = msg->data_length;
|
||||
|
||||
msg->magic = msg->command ^ 0xffffffff;
|
||||
const u8 *_data_ptr = data_ptr;
|
||||
msg->data_check = 0;
|
||||
while (count--) {
|
||||
msg->data_check += *_data_ptr++;
|
||||
}
|
||||
int ret = usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, (u8 *)msg, sizeof(*msg));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (data_ptr != NULL) {
|
||||
return usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, data_ptr, msg->data_length);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int adb_recv(u8 *buffer, u32 len, u32 timeout)
|
||||
{
|
||||
return usb_bulk_only_receive(&adb_device, adb.host_epin, 64, adb.target_epin, buffer, len);
|
||||
}
|
||||
#define check_usb_status(ret) do{\
|
||||
if(ret < 0){\
|
||||
log_info("%s() @ %d %d\n", __func__, __LINE__, ret);\
|
||||
return ret;\
|
||||
}\
|
||||
}while(0);
|
||||
|
||||
static u8 adb_signatrue_data_index ;
|
||||
|
||||
u32 adb_auth()
|
||||
{
|
||||
log_info("%s() %d\n", __func__, __LINE__);
|
||||
struct amessage msg;
|
||||
int ret = 0;
|
||||
u8 *cmd_string;
|
||||
adb.local_id = 0x58525047;
|
||||
adb.remote_id = 0;
|
||||
msg.command = A_CNXN;
|
||||
msg.arg0 = A_VERSION;
|
||||
msg.arg1 = 0x00001000;
|
||||
cmd_string = (u8 *)"host::";
|
||||
msg.data_length = strlen((const char *)cmd_string) + 1;
|
||||
ret = adb_send_packet(&msg, cmd_string);
|
||||
check_usb_status(ret);
|
||||
memset(&msg, 0, 24);
|
||||
ret = adb_recv((u8 *)&msg, 24, 5);
|
||||
check_usb_status(ret);
|
||||
|
||||
if (msg.command == A_CNXN) {
|
||||
if (adb_recv(adb.buffer, msg.data_length, 1 * 100)) {
|
||||
log_error("auth error 0\n");
|
||||
return 0;
|
||||
}
|
||||
log_info("auth not send rsa pub key\n");
|
||||
return 0;
|
||||
} else if (msg.command == A_AUTH) {
|
||||
|
||||
} else {
|
||||
log_error("auth error 1\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
msg.command = A_AUTH;
|
||||
msg.arg0 = ADB_AUTH_SIGNATURE;
|
||||
msg.data_length = sizeof(adb_signatrue_data[0]);
|
||||
if (adb_signatrue_data_index > 2) {
|
||||
adb_signatrue_data_index = 0;
|
||||
}
|
||||
|
||||
adb_signatrue_data_index ++;
|
||||
cmd_string = (u8 *)&adb_signatrue_data[adb_signatrue_data_index][0];
|
||||
ret = adb_send_packet(&msg, cmd_string);
|
||||
check_usb_status(ret);
|
||||
|
||||
ret = adb_send_packet(NULL, NULL);//zero packet
|
||||
check_usb_status(ret);
|
||||
|
||||
memset(&msg, 0, 24);
|
||||
ret = adb_recv((u8 *)&msg, 24, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
if (msg.command != A_AUTH) {
|
||||
log_error("auth error 2\n");
|
||||
return 1;
|
||||
}
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
|
||||
__RETRY:
|
||||
msg.command = A_AUTH;
|
||||
msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
|
||||
msg.arg1 = 0;
|
||||
msg.data_length = sizeof(adb_rsa_pub_key);
|
||||
ret = adb_send_packet(&msg, (u8 *)adb_rsa_pub_key);
|
||||
check_usb_status(ret);
|
||||
|
||||
ret = adb_recv((u8 *)&msg, 24, 30 * 100);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -DEV_ERR_TIMEOUT) {
|
||||
goto __RETRY;
|
||||
}
|
||||
check_usb_status(ret);
|
||||
}
|
||||
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);//最长等待30s,等手机点击确认授权adb
|
||||
if (ret < 0) {
|
||||
if (ret == -DEV_ERR_TIMEOUT) {
|
||||
goto __RETRY;
|
||||
}
|
||||
check_usb_status(ret);
|
||||
}
|
||||
|
||||
if (msg.command == A_AUTH) {
|
||||
goto __RETRY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 adb_shell_login()
|
||||
{
|
||||
log_info("%s() %d\n", __func__, __LINE__);
|
||||
struct amessage msg;
|
||||
u8 *cmd_string;
|
||||
/* __AUTH_SUCCESS: */
|
||||
|
||||
cmd_string = (u8 *)"shell:";
|
||||
msg.command = A_OPEN;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = 0;
|
||||
msg.data_length = strlen((char const *)cmd_string) + 1;
|
||||
int ret = adb_send_packet(&msg, cmd_string);
|
||||
check_usb_status(ret);
|
||||
|
||||
memset(&msg, 0, 24);
|
||||
ret = adb_recv((u8 *)&msg, 24, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
if (msg.command != A_OKAY) {
|
||||
log_error("A_OKAY error\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
ret = adb_recv((u8 *)&msg, 24, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
if (msg.command != A_WRTE) {
|
||||
log_error("A_WRTE error\n");
|
||||
return 5;
|
||||
}
|
||||
adb.remote_id = msg.arg0;
|
||||
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
msg.command = A_OKAY;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = 0;
|
||||
ret = adb_send_packet(&msg, NULL);
|
||||
check_usb_status(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 adb_ex_cmd(const char *cmd_string, u8 *echo_buffer, u32 max_len)
|
||||
{
|
||||
log_info("%s\n", cmd_string);
|
||||
int ret;
|
||||
struct amessage msg;
|
||||
msg.command = A_WRTE;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = strlen(cmd_string);
|
||||
ret = adb_send_packet(&msg, (u8 *)cmd_string);
|
||||
check_usb_status(ret);
|
||||
memset(&msg, 0, 24);
|
||||
memset(echo_buffer, 0, max_len);
|
||||
ret = adb_recv((u8 *)&msg, sizeof(msg), 3 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
if (msg.command != A_OKAY) {
|
||||
return true;
|
||||
}
|
||||
u32 offset = 0;
|
||||
do {
|
||||
ret = adb_recv((u8 *)&msg, sizeof(msg), 3 * 100);
|
||||
check_usb_status(ret);
|
||||
if (msg.command != A_WRTE) {
|
||||
log_info("command %x\n", msg.command);
|
||||
return true;
|
||||
}
|
||||
if ((offset + msg.data_length) > max_len) {
|
||||
log_info("%s", echo_buffer);
|
||||
echo_buffer[offset] = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
ret = adb_recv(&echo_buffer[offset], msg.data_length, 3 * 100);
|
||||
check_usb_status(ret);
|
||||
offset += msg.data_length;
|
||||
|
||||
if (msg.data_length == 0) {
|
||||
log_info("no data_length\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset >= max_len) {
|
||||
|
||||
}
|
||||
/* echo_buffer[offset] = '\n'; */
|
||||
echo_buffer[offset] = 0;
|
||||
|
||||
if (echo_buffer[offset - 2] == 0x24 && echo_buffer[offset - 1] == 0x20) {
|
||||
/* puts("end\n"); */
|
||||
break;
|
||||
} else if (echo_buffer[offset - 2] == 0x23 && echo_buffer[offset - 1] == 0x20) {
|
||||
/* puts("end 1\n"); */
|
||||
break;
|
||||
}
|
||||
msg.command = A_OKAY;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = 0;
|
||||
ret = adb_send_packet(&msg, NULL);
|
||||
check_usb_status(ret);
|
||||
|
||||
} while (1);
|
||||
|
||||
msg.command = A_OKAY;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = 0;
|
||||
/* puts("exit\n"); */
|
||||
return adb_send_packet(&msg, NULL);
|
||||
|
||||
}
|
||||
#define APP_ACTIVITY_PATH "com.zh-jieli.gmaeCenter/com.zh-jieli.gameCenter.activity.guide.SplashActivity\n"
|
||||
#define APP_WEBSITE "http://www.zh-jieli.com\n"
|
||||
#define APP_BASH_IN_PATH "/sdcard/jilei/active.bash"
|
||||
#define APP_BASH_OUT_PATH "/data/local/tmp/active.bash"
|
||||
|
||||
u32 adb_game_active()
|
||||
{
|
||||
log_info("%s() %d\n", __func__, __LINE__);
|
||||
u32 max_len = adb.max_len;;
|
||||
u8 *adb_buffer = adb.buffer;
|
||||
//1,启动app
|
||||
adb_ex_cmd("am start -n " APP_ACTIVITY_PATH, adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
//查找Error字符串,如果找到跳转网页下载app,否则执行adb指令
|
||||
if (strstr((const char *)adb_buffer, "Error") != NULL) {
|
||||
adb_ex_cmd("am start -a android.intent.action.VIEW -d " APP_WEBSITE, adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
} else {
|
||||
adb_ex_cmd("dd if=" APP_BASH_IN_PATH " of=" APP_BASH_OUT_PATH "\n", adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
adb_ex_cmd("chown shell " APP_BASH_OUT_PATH";chmod 777 "APP_BASH_OUT_PATH "\n", adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
adb_ex_cmd("trap \"\" HUP;sh "APP_BASH_OUT_PATH "&\n", adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void mtp_ptp_open_session(u32 is_mtp)
|
||||
{
|
||||
/* usbh_bulk_send_blocking(ADB_HOST_EP, adb_device.extr_out, (u8 *)_open_session, 16); */
|
||||
/* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 12, 3); */
|
||||
|
||||
/* usbh_bulk_send_blocking(ADB_HOST_EP, adb_device.extr_out, (u8 *)get_device_info, sizeof(get_device_info)); */
|
||||
/* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 512, 3); */
|
||||
|
||||
/* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 12, 3); */
|
||||
}
|
||||
|
||||
static void adb_open_session()
|
||||
{
|
||||
struct usb_host_device *host_dev = adb_device.private_data;
|
||||
if (adb.extr_in && adb.extr_out) {
|
||||
get_ms_extended_compat_id(host_dev, adb.buffer);
|
||||
get_device_status(host_dev);
|
||||
get_config_descriptor(host_dev, adb.buffer, 0xff);
|
||||
/* mtp_ptp_open_session(ac6921_data_buffer[0x12] == 0x4d); */
|
||||
}
|
||||
}
|
||||
u32 adb_process()
|
||||
{
|
||||
adb.max_len = 1024;
|
||||
adb.buffer = malloc(adb.max_len);
|
||||
os_time_dly(20);
|
||||
do {
|
||||
|
||||
adb_open_session();
|
||||
|
||||
if (adb_auth()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (adb_shell_login()) {
|
||||
break;
|
||||
}
|
||||
|
||||
adb_game_active();
|
||||
log_info("adb active succ");
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
free(adb.buffer);
|
||||
|
||||
|
||||
log_info("adb active error");
|
||||
return 1;
|
||||
}
|
||||
void adb_switch_aoa(u32 id)
|
||||
{
|
||||
struct usb_host_device *host_dev = adb_device.private_data;
|
||||
aoa_switch(host_dev);
|
||||
/* usb_host_remount(id, 3, 30, 50, 1); */
|
||||
}
|
||||
#endif //TCFG_ADB_ENABLE
|
||||
@ -1,73 +0,0 @@
|
||||
#ifndef __ADB_H__
|
||||
#define __ADB_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
struct adb_device_t {
|
||||
u32 local_id;
|
||||
u32 remote_id;
|
||||
void *buffer;
|
||||
u32 max_len;
|
||||
|
||||
u8 target_epin;
|
||||
u8 target_epout;
|
||||
u8 host_epin;
|
||||
u8 host_epout;
|
||||
|
||||
u8 extr_in;
|
||||
u8 extr_out;
|
||||
};
|
||||
u32 usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
int usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
u32 adb_process();
|
||||
void adb_switch_aoa(u32 id);
|
||||
|
||||
#if 1
|
||||
#define A_SYNC 0x434e5953
|
||||
#define A_CNXN 0x4e584e43
|
||||
#define A_OPEN 0x4e45504f
|
||||
#define A_OKAY 0x59414b4f
|
||||
#define A_CLSE 0x45534c43
|
||||
#define A_WRTE 0x45545257
|
||||
#define A_AUTH 0x48545541
|
||||
//#define S_ID_LOCAL 0x00003456
|
||||
/* AUTH packets first argument */
|
||||
/* Request */
|
||||
#define ADB_AUTH_TOKEN 1
|
||||
/* Response */
|
||||
#define ADB_AUTH_SIGNATURE 2
|
||||
#define ADB_AUTH_RSAPUBLICKEY 3
|
||||
|
||||
#define A_VERSION 0x01000000 // ADB protocol version
|
||||
|
||||
#define ADB_VERSION_MAJOR 1 // Used for help/version information
|
||||
#define ADB_VERSION_MINOR 0 // Used for help/version information
|
||||
|
||||
#else
|
||||
#define A_SYNC 0x53594e43
|
||||
#define A_CNXN 0x434e584e
|
||||
#define A_OPEN 0x4f50454e
|
||||
#define A_OKAY 0x4f4b4159
|
||||
#define A_CLSE 0x434c5345
|
||||
#define A_WRTE 0x57525445
|
||||
|
||||
#define A_VERSION 0x00000001 // ADB protocol version
|
||||
|
||||
#define ADB_VERSION_MAJOR 1 // Used for help/version information
|
||||
#define ADB_VERSION_MINOR 0 // Used for help/version information
|
||||
|
||||
#endif
|
||||
|
||||
struct amessage {
|
||||
unsigned long int command; /* command identifier constant */
|
||||
unsigned long int arg0; /* first argument */
|
||||
unsigned long int arg1; /* second argument */
|
||||
unsigned long int data_length; /* length of payload (0 is allowed) */
|
||||
unsigned long int data_check; /* checksum of data payload */
|
||||
unsigned long int magic; /* command ^ 0xffffffff */
|
||||
};
|
||||
|
||||
#endif /*ADB_H*/
|
||||
@ -1,115 +0,0 @@
|
||||
#include "typedef.h"
|
||||
#include "app_config.h"
|
||||
#if TCFG_ADB_ENABLE
|
||||
static const u8 _open_session[] = {
|
||||
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
|
||||
};
|
||||
static const u8 get_device_info[] = {
|
||||
0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const u8 adb_signatrue_data[][256] = {
|
||||
{
|
||||
0xFA, 0xA6, 0xE3, 0x50, 0x3C, 0xC4, 0x95, 0xFE, 0xBB, 0x46, 0xE0, 0x9F, 0xD9, 0x9A, 0x18, 0xC1,
|
||||
0x28, 0x67, 0xA9, 0x46, 0xF8, 0x20, 0xBF, 0xDB, 0xFE, 0x6B, 0xC8, 0xC4, 0x0A, 0x09, 0xFA, 0x9A,
|
||||
0xCD, 0x51, 0xE3, 0x67, 0xD1, 0xDF, 0xD2, 0x92, 0xD3, 0x9E, 0xFA, 0x17, 0x76, 0x01, 0xF5, 0xE2,
|
||||
0xBD, 0x64, 0x9C, 0x92, 0x82, 0x4B, 0xE4, 0x27, 0x21, 0x22, 0x1A, 0x70, 0x99, 0x8F, 0xC5, 0xD5,
|
||||
0xE2, 0x02, 0x2C, 0xA4, 0x13, 0x08, 0x1E, 0x42, 0x83, 0x5C, 0x7E, 0x3C, 0x1F, 0x97, 0x1B, 0xAF,
|
||||
0x6F, 0x7E, 0x4F, 0xAB, 0xDA, 0x6A, 0x61, 0x56, 0x03, 0x79, 0xB5, 0xF0, 0x97, 0xEE, 0xEC, 0x88,
|
||||
0x6F, 0x9E, 0x8D, 0x41, 0xE2, 0x13, 0x9B, 0x21, 0xEE, 0x6F, 0x09, 0x81, 0x62, 0xC1, 0xB5, 0xE7,
|
||||
0xC2, 0x5C, 0x4A, 0x8C, 0x39, 0xAA, 0x50, 0x08, 0x48, 0xB5, 0x1D, 0xF6, 0x7C, 0x67, 0xD6, 0x39,
|
||||
0x63, 0x7E, 0x5E, 0x49, 0x3D, 0x9B, 0x49, 0x4B, 0x67, 0x8E, 0x06, 0x31, 0x07, 0x4E, 0x56, 0x8A,
|
||||
0xC4, 0x9D, 0x84, 0xA9, 0xF4, 0xFC, 0xE3, 0x2D, 0x1D, 0x2A, 0x98, 0x52, 0x40, 0x49, 0x93, 0x71,
|
||||
0xA7, 0x43, 0x0D, 0x78, 0xEB, 0xFA, 0x49, 0x7A, 0x39, 0xBF, 0xE4, 0x06, 0x08, 0x1B, 0x20, 0x84,
|
||||
0xDC, 0x64, 0xBB, 0xDE, 0x1A, 0x5E, 0x4B, 0xF8, 0x57, 0xBF, 0x9C, 0x8C, 0xB9, 0x1D, 0xEE, 0xB3,
|
||||
0x90, 0x17, 0x03, 0x8B, 0x3E, 0x9F, 0x8A, 0x23, 0xEC, 0x30, 0xA7, 0x24, 0x5E, 0x5B, 0x58, 0xAA,
|
||||
0x5A, 0xAE, 0xE2, 0x14, 0xC1, 0xAE, 0xA3, 0xF9, 0xAF, 0x70, 0xE0, 0x14, 0x7D, 0x73, 0x3B, 0x6D,
|
||||
0x9B, 0x06, 0x2F, 0xAA, 0xFF, 0x7A, 0x2A, 0x56, 0x6F, 0x91, 0x70, 0x6D, 0x4A, 0x18, 0x35, 0x51,
|
||||
0xD5, 0x5D, 0xFB, 0xA1, 0x8B, 0x03, 0xF2, 0x0C, 0x56, 0xF0, 0x5A, 0x4A, 0x08, 0x89, 0xFE, 0x86
|
||||
},
|
||||
{
|
||||
0x60, 0xE6, 0x4A, 0x3D, 0x12, 0xD1, 0x48, 0x25, 0x7D, 0x6E, 0x8E, 0x03, 0xE2, 0xC8, 0xE7, 0x66,
|
||||
0x96, 0xD7, 0xD3, 0xBF, 0xE6, 0x97, 0x13, 0x3A, 0x2D, 0x2B, 0x85, 0xE7, 0xDA, 0x5C, 0x87, 0xD8,
|
||||
0xDC, 0x88, 0xAC, 0xF7, 0xC3, 0xF0, 0x5A, 0xE8, 0x95, 0x66, 0x19, 0xA1, 0xA8, 0x2A, 0xE1, 0x70,
|
||||
0x13, 0xF0, 0x05, 0x59, 0x3D, 0x89, 0x04, 0x65, 0x08, 0x03, 0x9C, 0xDC, 0x71, 0x24, 0xC5, 0x9E,
|
||||
0x4D, 0x82, 0xD8, 0x72, 0x07, 0xFD, 0x8F, 0xD3, 0x37, 0x56, 0x8C, 0xB6, 0x01, 0xDB, 0x08, 0x5B,
|
||||
0xA3, 0x42, 0x8F, 0xF0, 0xCA, 0xDC, 0x80, 0xEB, 0x32, 0xC4, 0x67, 0x1F, 0x73, 0xAF, 0xF0, 0x56,
|
||||
0xBC, 0x89, 0x72, 0xB1, 0x7D, 0xDA, 0xA4, 0x79, 0x7D, 0x02, 0x35, 0x38, 0xBA, 0xA0, 0x36, 0xFE,
|
||||
0x5A, 0x70, 0x93, 0xF5, 0x10, 0x7A, 0x92, 0xE9, 0xD4, 0xB0, 0xED, 0xF3, 0x00, 0xD0, 0x27, 0x79,
|
||||
0x51, 0x54, 0x38, 0x2D, 0x4C, 0xAA, 0x27, 0xEF, 0xA7, 0x8A, 0x34, 0x4E, 0x4B, 0x29, 0x90, 0xC4,
|
||||
0x3E, 0xA8, 0x8D, 0x3D, 0x00, 0xD6, 0x84, 0x11, 0x17, 0x32, 0xD6, 0xE9, 0x33, 0x02, 0xCD, 0x04,
|
||||
0x35, 0x3F, 0x1A, 0xC3, 0x05, 0xCF, 0x6F, 0xF4, 0x39, 0x65, 0xE5, 0x6B, 0x88, 0x1E, 0x25, 0xA1,
|
||||
0xD7, 0xC0, 0x30, 0xE4, 0x0B, 0x2A, 0x61, 0x6D, 0x61, 0xF1, 0x93, 0xAE, 0xC3, 0x42, 0xDC, 0x15,
|
||||
0x1D, 0x87, 0x60, 0x09, 0x92, 0x64, 0xC1, 0x63, 0xAD, 0xCA, 0x36, 0x63, 0x0E, 0x69, 0x51, 0x45,
|
||||
0xD0, 0x18, 0x5E, 0x10, 0x88, 0x7B, 0xD9, 0xDE, 0xA3, 0x12, 0x85, 0xF9, 0x30, 0x01, 0x0A, 0xE1,
|
||||
0x82, 0xD1, 0x49, 0x44, 0xD9, 0x97, 0xE4, 0xF1, 0x55, 0x2D, 0xE2, 0xF3, 0x32, 0xC8, 0xA0, 0xC8,
|
||||
0x81, 0xB9, 0x02, 0x87, 0x5C, 0x19, 0xB7, 0x21, 0x6A, 0xB9, 0xB0, 0x81, 0x61, 0x8C, 0x35, 0x78
|
||||
},
|
||||
{
|
||||
0x0C, 0x7E, 0xDC, 0x78, 0x60, 0x1A, 0xC8, 0x9B, 0x3A, 0x23, 0x0B, 0x1D, 0x6F, 0xAE, 0x71, 0x6D,
|
||||
0xD8, 0x3C, 0xE9, 0xA3, 0x51, 0x90, 0xAA, 0x7B, 0x7E, 0x2F, 0x2B, 0xBD, 0x34, 0xF4, 0x43, 0x3F,
|
||||
0x77, 0xC4, 0x0E, 0x41, 0x04, 0xD9, 0xD4, 0x9C, 0xB3, 0xD2, 0x6B, 0xE1, 0xC6, 0xA8, 0xEF, 0x50,
|
||||
0x00, 0x11, 0xE1, 0x08, 0x8B, 0xB4, 0xF1, 0xE3, 0x3D, 0x56, 0x83, 0x07, 0x7F, 0xB8, 0x47, 0xF2,
|
||||
0x84, 0xD2, 0xA1, 0x50, 0x64, 0x5A, 0x08, 0x42, 0x36, 0x23, 0x09, 0x31, 0x9A, 0x6B, 0x61, 0x6F,
|
||||
0x60, 0x2C, 0xF2, 0x75, 0x4E, 0x6B, 0xB9, 0x15, 0xEE, 0x3C, 0x5E, 0xA2, 0x7F, 0xA0, 0x41, 0xFE,
|
||||
0x00, 0x6A, 0x30, 0x49, 0x2C, 0xEC, 0x17, 0x8B, 0x04, 0x32, 0xE9, 0x7A, 0x68, 0xA0, 0xF4, 0xDF,
|
||||
0x34, 0xF7, 0x1E, 0x6F, 0x19, 0x09, 0x37, 0x87, 0x99, 0xAA, 0x81, 0x1A, 0xCD, 0xF3, 0x1F, 0x89,
|
||||
0x50, 0xB2, 0x17, 0x52, 0x6D, 0x8E, 0xA6, 0x02, 0xC4, 0x2A, 0xAB, 0x3E, 0x5B, 0x38, 0x0C, 0x3F,
|
||||
0x50, 0xAA, 0x5F, 0xFE, 0x47, 0x04, 0xED, 0xCD, 0xEE, 0x7C, 0xD5, 0xED, 0x5F, 0x0E, 0xC6, 0x9C,
|
||||
0x79, 0x10, 0x11, 0x6F, 0x65, 0x58, 0x37, 0x95, 0x54, 0x50, 0x59, 0x68, 0x4C, 0x8E, 0xE7, 0x35,
|
||||
0xF0, 0x96, 0x5A, 0x21, 0x48, 0xB4, 0x53, 0x52, 0xFC, 0xA4, 0x7C, 0x2B, 0xB1, 0xE1, 0x54, 0x2C,
|
||||
0x42, 0x3B, 0x68, 0xBF, 0xBB, 0x68, 0x0D, 0x62, 0x16, 0x2F, 0xF5, 0xC8, 0x5F, 0x95, 0x11, 0xF2,
|
||||
0xDF, 0x03, 0x1E, 0xCB, 0x7C, 0xD0, 0x9C, 0xE9, 0x89, 0x62, 0xEA, 0xC5, 0x4B, 0xA9, 0xD5, 0xCC,
|
||||
0xD2, 0x42, 0x33, 0xA8, 0x7B, 0x2C, 0x56, 0xCF, 0xCE, 0x0D, 0x09, 0x64, 0x62, 0x3F, 0x58, 0x41,
|
||||
0x71, 0x79, 0x5D, 0x1D, 0xDF, 0x08, 0x0B, 0x36, 0x97, 0x16, 0x24, 0x20, 0x76, 0x9C, 0x9E, 0xEA
|
||||
}
|
||||
};
|
||||
static const u8 adb_rsa_pub_key[] = {
|
||||
0x51, 0x41, 0x41, 0x41, 0x41, 0x46, 0x4F, 0x56, 0x4F, 0x6E, 0x49, 0x6C, 0x69, 0x51, 0x58, 0x44,
|
||||
0x73, 0x42, 0x43, 0x42, 0x31, 0x75, 0x6F, 0x68, 0x70, 0x2B, 0x52, 0x71, 0x6E, 0x6E, 0x59, 0x48,
|
||||
0x2F, 0x75, 0x45, 0x58, 0x34, 0x59, 0x6A, 0x50, 0x71, 0x52, 0x4D, 0x35, 0x4B, 0x75, 0x62, 0x56,
|
||||
0x50, 0x71, 0x66, 0x57, 0x35, 0x64, 0x56, 0x46, 0x33, 0x2B, 0x76, 0x57, 0x6B, 0x53, 0x4B, 0x71,
|
||||
0x35, 0x4C, 0x31, 0x42, 0x4F, 0x4E, 0x4D, 0x36, 0x4B, 0x4F, 0x31, 0x69, 0x31, 0x73, 0x69, 0x4F,
|
||||
0x54, 0x69, 0x34, 0x6C, 0x45, 0x30, 0x6F, 0x54, 0x6F, 0x74, 0x30, 0x41, 0x4B, 0x6E, 0x4D, 0x67,
|
||||
0x4E, 0x6A, 0x6F, 0x33, 0x45, 0x4D, 0x65, 0x72, 0x30, 0x6C, 0x57, 0x56, 0x54, 0x54, 0x43, 0x39,
|
||||
0x68, 0x52, 0x66, 0x67, 0x46, 0x65, 0x56, 0x73, 0x43, 0x32, 0x44, 0x74, 0x71, 0x62, 0x61, 0x6D,
|
||||
0x4A, 0x48, 0x63, 0x41, 0x66, 0x59, 0x77, 0x36, 0x54, 0x62, 0x4C, 0x44, 0x6C, 0x4B, 0x70, 0x6A,
|
||||
0x38, 0x34, 0x33, 0x63, 0x31, 0x59, 0x5A, 0x65, 0x59, 0x6D, 0x52, 0x56, 0x4D, 0x7A, 0x4D, 0x34,
|
||||
0x6E, 0x74, 0x49, 0x78, 0x64, 0x56, 0x33, 0x33, 0x76, 0x4B, 0x75, 0x39, 0x38, 0x34, 0x6A, 0x72,
|
||||
0x43, 0x41, 0x47, 0x68, 0x77, 0x4A, 0x41, 0x67, 0x4A, 0x46, 0x53, 0x41, 0x4B, 0x56, 0x59, 0x51,
|
||||
0x55, 0x33, 0x6A, 0x4C, 0x76, 0x41, 0x76, 0x57, 0x45, 0x6C, 0x59, 0x47, 0x37, 0x2F, 0x4B, 0x59,
|
||||
0x6D, 0x55, 0x34, 0x54, 0x71, 0x73, 0x70, 0x64, 0x76, 0x4C, 0x42, 0x6F, 0x65, 0x36, 0x68, 0x64,
|
||||
0x46, 0x44, 0x65, 0x76, 0x4D, 0x4D, 0x43, 0x63, 0x72, 0x6C, 0x44, 0x49, 0x66, 0x65, 0x45, 0x53,
|
||||
0x57, 0x68, 0x42, 0x56, 0x35, 0x67, 0x78, 0x6A, 0x57, 0x41, 0x70, 0x4D, 0x47, 0x67, 0x53, 0x71,
|
||||
0x53, 0x45, 0x6A, 0x70, 0x36, 0x79, 0x62, 0x6A, 0x33, 0x38, 0x50, 0x4C, 0x72, 0x76, 0x49, 0x51,
|
||||
0x48, 0x77, 0x2B, 0x66, 0x70, 0x6F, 0x51, 0x74, 0x6F, 0x4F, 0x4E, 0x65, 0x37, 0x6F, 0x68, 0x66,
|
||||
0x42, 0x77, 0x45, 0x66, 0x47, 0x46, 0x4E, 0x63, 0x33, 0x61, 0x70, 0x48, 0x50, 0x6E, 0x59, 0x53,
|
||||
0x47, 0x4F, 0x67, 0x70, 0x54, 0x78, 0x70, 0x57, 0x57, 0x75, 0x49, 0x42, 0x79, 0x2F, 0x67, 0x38,
|
||||
0x35, 0x2B, 0x65, 0x54, 0x30, 0x44, 0x61, 0x36, 0x53, 0x65, 0x71, 0x33, 0x67, 0x62, 0x4A, 0x59,
|
||||
0x64, 0x75, 0x52, 0x44, 0x65, 0x36, 0x5A, 0x39, 0x63, 0x4A, 0x77, 0x48, 0x79, 0x38, 0x43, 0x34,
|
||||
0x59, 0x79, 0x6B, 0x44, 0x56, 0x45, 0x4B, 0x6A, 0x39, 0x75, 0x52, 0x41, 0x41, 0x45, 0x59, 0x70,
|
||||
0x52, 0x6B, 0x74, 0x39, 0x66, 0x34, 0x79, 0x51, 0x4A, 0x31, 0x73, 0x4D, 0x48, 0x31, 0x5A, 0x75,
|
||||
0x4F, 0x55, 0x46, 0x4A, 0x46, 0x65, 0x74, 0x6B, 0x72, 0x67, 0x32, 0x44, 0x46, 0x61, 0x35, 0x30,
|
||||
0x50, 0x39, 0x48, 0x61, 0x78, 0x6F, 0x4D, 0x59, 0x30, 0x41, 0x79, 0x78, 0x7A, 0x51, 0x72, 0x53,
|
||||
0x77, 0x4D, 0x44, 0x79, 0x6E, 0x36, 0x64, 0x49, 0x65, 0x38, 0x65, 0x58, 0x46, 0x78, 0x51, 0x62,
|
||||
0x56, 0x4D, 0x4F, 0x6C, 0x4B, 0x36, 0x79, 0x33, 0x70, 0x6F, 0x2B, 0x4A, 0x4D, 0x42, 0x34, 0x79,
|
||||
0x4D, 0x42, 0x36, 0x51, 0x77, 0x30, 0x7A, 0x31, 0x35, 0x62, 0x6F, 0x58, 0x4C, 0x78, 0x4D, 0x4B,
|
||||
0x76, 0x4E, 0x59, 0x6E, 0x4B, 0x4E, 0x70, 0x69, 0x6F, 0x33, 0x67, 0x45, 0x78, 0x5A, 0x2B, 0x48,
|
||||
0x68, 0x57, 0x62, 0x43, 0x47, 0x69, 0x37, 0x64, 0x4A, 0x6C, 0x56, 0x47, 0x50, 0x6F, 0x74, 0x34,
|
||||
0x4D, 0x42, 0x45, 0x4C, 0x7A, 0x43, 0x38, 0x66, 0x4C, 0x55, 0x44, 0x69, 0x41, 0x43, 0x49, 0x54,
|
||||
0x37, 0x75, 0x31, 0x58, 0x31, 0x62, 0x68, 0x65, 0x71, 0x6C, 0x35, 0x59, 0x7A, 0x43, 0x30, 0x6C,
|
||||
0x67, 0x2F, 0x4B, 0x48, 0x5A, 0x7A, 0x62, 0x36, 0x6D, 0x63, 0x74, 0x4E, 0x2B, 0x34, 0x62, 0x52,
|
||||
0x74, 0x79, 0x4B, 0x35, 0x75, 0x52, 0x52, 0x4A, 0x70, 0x48, 0x45, 0x56, 0x63, 0x4B, 0x58, 0x57,
|
||||
0x50, 0x34, 0x30, 0x73, 0x31, 0x79, 0x38, 0x37, 0x75, 0x30, 0x6D, 0x49, 0x50, 0x4A, 0x6E, 0x73,
|
||||
0x39, 0x6D, 0x4F, 0x2F, 0x2F, 0x44, 0x41, 0x35, 0x4C, 0x32, 0x6D, 0x64, 0x77, 0x56, 0x79, 0x73,
|
||||
0x72, 0x74, 0x4B, 0x51, 0x69, 0x51, 0x37, 0x36, 0x57, 0x6A, 0x74, 0x59, 0x51, 0x63, 0x41, 0x73,
|
||||
0x46, 0x2B, 0x42, 0x54, 0x4E, 0x56, 0x48, 0x62, 0x41, 0x6E, 0x7A, 0x7A, 0x52, 0x75, 0x6C, 0x52,
|
||||
0x61, 0x43, 0x45, 0x78, 0x2B, 0x6E, 0x30, 0x49, 0x6A, 0x35, 0x34, 0x49, 0x45, 0x41, 0x4F, 0x75,
|
||||
0x55, 0x4B, 0x70, 0x6F, 0x61, 0x48, 0x71, 0x6F, 0x56, 0x4F, 0x33, 0x51, 0x42, 0x36, 0x52, 0x41,
|
||||
0x51, 0x7A, 0x4D, 0x67, 0x70, 0x44, 0x73, 0x41, 0x30, 0x58, 0x34, 0x4C, 0x6A, 0x4F, 0x32, 0x52,
|
||||
0x2B, 0x4D, 0x4B, 0x6F, 0x6D, 0x6F, 0x6C, 0x52, 0x5A, 0x6F, 0x32, 0x34, 0x57, 0x32, 0x41, 0x35,
|
||||
0x57, 0x2B, 0x30, 0x56, 0x4A, 0x77, 0x45, 0x41, 0x41, 0x51, 0x41, 0x3D, 0x20, 0x75, 0x6E, 0x6B,
|
||||
0x6E, 0x6F, 0x77, 0x6E, 0x40, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00
|
||||
};
|
||||
#endif
|
||||
@ -1,232 +0,0 @@
|
||||
/**
|
||||
* @file aoa.c
|
||||
* @brief https://source.android.com/devices/accessories/aoa
|
||||
* http://www.hackermi.com/2015-04/aoa-analyse/
|
||||
* Android 开放配件协议 1.0
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1
|
||||
* @date 2020-03-25
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#include "usb_config.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "device_drive.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb_storage.h"
|
||||
#include "adb.h"
|
||||
#include "aoa.h"
|
||||
#include "usb_hid_keys.h"
|
||||
#if TCFG_AOA_ENABLE
|
||||
#include "gamebox.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[AOA]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
//0x2D00 有一个接口,该接口有两个批量端点,用于输入和输出通信。
|
||||
//0x2D01 有两个接口,每个接口有两个批量端点,用于输入和输出通信。
|
||||
//第一个接口处理标准通信,
|
||||
//第二个接口则处理 ADB 通信。
|
||||
//要使用接口,请找到第一个批量输入和输出端点,
|
||||
//使用 SET_CONFIGURATION (0x09) 设备请求将设备配置的值设为 1,然后使用端点进行通信
|
||||
//
|
||||
|
||||
|
||||
static void aoa_timer_handler(void *priv);
|
||||
static u32 aoa_timer_id;
|
||||
static struct aoa_device_t aoa;
|
||||
static struct device aoa_device;
|
||||
|
||||
static int set_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
if (aoa_timer_id) {
|
||||
usr_timer_del(aoa_timer_id);
|
||||
aoa_timer_id = 0;
|
||||
}
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
static const struct interface_ctrl aoa_ctrl = {
|
||||
.interface_class = USB_CLASS_AOA,
|
||||
.set_power = set_power,
|
||||
.get_power = get_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info aoa_inf = {
|
||||
.ctrl = (struct interface_ctrl *) &aoa_ctrl,
|
||||
.dev.aoa = &aoa,
|
||||
};
|
||||
|
||||
static const char *credetials[] = {"JieLiTec",
|
||||
"GameBox",
|
||||
"Android accessories devcie !",
|
||||
"1.0.0",
|
||||
"http://www.zh-jieli.com",
|
||||
"1234567890ABCDEF",
|
||||
};
|
||||
|
||||
void aoa_switch(struct usb_host_device *host_dev)
|
||||
{
|
||||
u16 version;
|
||||
log_info("aoa_switch");
|
||||
usb_get_aoa_version(host_dev, &version);
|
||||
log_info("AOA version: %x", version);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
log_info("send string [%d] %s", i, credetials[i]);
|
||||
int r = usb_set_credentials(host_dev, credetials[i], i);
|
||||
if (r < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
usb_switch2aoa(host_dev);
|
||||
}
|
||||
|
||||
int usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
aoa_device.private_data = host_dev;
|
||||
host_dev->interface_info[interface_num] = &aoa_inf;
|
||||
|
||||
for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) {
|
||||
struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf;
|
||||
|
||||
if (end_desc->bDescriptorType != USB_DT_ENDPOINT ||
|
||||
end_desc->bLength != USB_DT_ENDPOINT_SIZE) {
|
||||
log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength);
|
||||
return -USB_DT_ENDPOINT;
|
||||
}
|
||||
|
||||
len += USB_DT_ENDPOINT_SIZE;
|
||||
pBuf += USB_DT_ENDPOINT_SIZE;
|
||||
|
||||
if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
|
||||
if (end_desc->bEndpointAddress & USB_DIR_IN) {
|
||||
aoa.target_epin = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
aoa.rxmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
} else {
|
||||
aoa.target_epout = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
aoa.txmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int aoa_tx_data(const u8 *pbuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = aoa_device.private_data;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
g_printf("TX:");
|
||||
printf_buf(pbuf, len);
|
||||
return usb_h_ep_write_async(usb_id, aoa.host_epout, 64, aoa.target_epout, pbuf, len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
}
|
||||
static void aoa_epin_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
u8 buffer[64] = {0};
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
u32 rx_len = usb_h_ep_read_async(usb_id, ep, aoa.target_epin, buffer, sizeof(buffer), USB_ENDPOINT_XFER_BULK, 0);
|
||||
g_printf("RX:");
|
||||
printf_buf(buffer, rx_len);
|
||||
|
||||
usb_h_ep_read_async(usb_id, ep, aoa.target_epin, NULL, 0, USB_ENDPOINT_XFER_BULK, 1);
|
||||
}
|
||||
|
||||
#define Accessory_assigned_ID 0x0001
|
||||
|
||||
u32 aoa_process(u32 mode, u32 id)
|
||||
{
|
||||
struct usb_host_device *host_dev = aoa_device.private_data;
|
||||
struct usb_device_descriptor device_desc;
|
||||
usb_get_device_descriptor(host_dev, &device_desc);
|
||||
|
||||
if ((device_desc.idVendor == 0x18d1) &&
|
||||
((device_desc.idProduct & 0x2d00) == 0x2d00)) {
|
||||
log_info("aoa mode ready idVendor:%x idProduct: %x",
|
||||
device_desc.idVendor, device_desc.idProduct);
|
||||
} else {
|
||||
log_info("aoa switch idVendor:%x idProduct: %x",
|
||||
device_desc.idVendor, device_desc.idProduct);
|
||||
|
||||
aoa_switch(host_dev);
|
||||
|
||||
usb_host_remount(id, 3, 30, 50, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
usb_aoa_register_hid(host_dev, Accessory_assigned_ID, sizeof(hid_report_desc));
|
||||
|
||||
u32 offset = 0;
|
||||
while (offset < sizeof(hid_report_desc)) {
|
||||
u32 cnt = min(sizeof(hid_report_desc) - offset, 63);
|
||||
usb_aoa_set_hid_report_desc(host_dev, Accessory_assigned_ID, offset, &hid_report_desc[offset], cnt);
|
||||
offset += cnt;
|
||||
}
|
||||
|
||||
aoa.host_epout = usb_get_ep_num(id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK);
|
||||
aoa.host_epin = usb_get_ep_num(id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK);
|
||||
log_debug("D(%d)->H(%d)", aoa.target_epin, aoa.host_epin);
|
||||
log_debug("H(%d)->D(%d)", aoa.host_epout, aoa.target_epout);
|
||||
|
||||
usb_h_set_ep_isr(host_dev, aoa.host_epin | USB_DIR_IN, aoa_epin_isr, host_dev);
|
||||
u8 *ep_buffer = usb_h_get_ep_buffer(id, aoa.host_epin | USB_DIR_IN);
|
||||
usb_h_ep_config(id, aoa.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 1, 0, ep_buffer, 64);
|
||||
int r = usb_h_ep_read_async(id, aoa.host_epin, aoa.target_epin, NULL, 0, USB_ENDPOINT_XFER_BULK, 1);
|
||||
|
||||
ep_buffer = usb_h_get_ep_buffer(id, aoa.host_epout | USB_DIR_OUT);
|
||||
usb_h_ep_config(id, aoa.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
|
||||
|
||||
aoa_timer_id = usr_timer_add((void *)0, aoa_timer_handler, 4, 0);
|
||||
g_printf("aoa succ");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void aoa_timer_handler(void *priv)
|
||||
{
|
||||
struct usb_host_device *host_dev = aoa_device.private_data;
|
||||
|
||||
u8 tx_buffer[32];
|
||||
if (mouse_data_send == 1) {
|
||||
tx_buffer[0] = MOUSE_POINT_ID;
|
||||
memcpy(&tx_buffer[1], &mouse_data, sizeof(mouse_data));
|
||||
usb_aoa_send_hid_event(host_dev, Accessory_assigned_ID, tx_buffer, sizeof(mouse_data) + 1);
|
||||
memset(&mouse_data, 0, sizeof(mouse_data)) ;
|
||||
mouse_data_send = 0;
|
||||
}
|
||||
|
||||
tx_buffer[0] = TOUCH_SCREEN_ID;
|
||||
struct touch_screen_t t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
if (point_list_pop(&t)) {
|
||||
memcpy(&tx_buffer[1], &t, sizeof(t));
|
||||
usb_aoa_send_hid_event(host_dev, Accessory_assigned_ID, tx_buffer, sizeof(t) + 1);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@ -1,20 +0,0 @@
|
||||
#ifndef __AOA_H__
|
||||
#define __AOA_H__
|
||||
|
||||
struct aoa_device_t {
|
||||
u16 version;
|
||||
|
||||
u8 target_epin;
|
||||
u8 target_epout;
|
||||
|
||||
u8 host_epin;
|
||||
u8 host_epout;
|
||||
|
||||
struct adb_device_t *adb;
|
||||
};
|
||||
u32 aoa_process(u32 mode, u32 id);
|
||||
int usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
|
||||
|
||||
#endif /*AOA_H*/
|
||||
@ -1,8 +0,0 @@
|
||||
#ifndef _APPLE_MFI_H_
|
||||
#define _APPLE_MFI_H_
|
||||
|
||||
int usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@ -1,820 +0,0 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "device_drive.h"
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "audio.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[AUDIO]"
|
||||
#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_AUDIO_PLAY_TEST */
|
||||
|
||||
struct usb_audio_play {
|
||||
u32 sample_rate;
|
||||
u8 Cur_AlternateSetting;
|
||||
u8 src_channel;
|
||||
u8 play_state;
|
||||
u8 mute;
|
||||
u8 *send_buf;
|
||||
u8 *usb_audio_play_buf;
|
||||
u8 *usb_audio_play_buf2;
|
||||
cbuffer_t usb_audio_play_cbuf;
|
||||
u32 usb_audio_remain_len;
|
||||
OS_SEM sem;
|
||||
int (*put_buf)(void *ptr, u32 len);
|
||||
};
|
||||
struct usb_audio_mic {
|
||||
u8 Cur_AlternateSetting;
|
||||
u32 sample_rate;
|
||||
u8 record_state;
|
||||
u8 *usb_audio_record_buf;
|
||||
u8 *usb_audio_record_buf2;
|
||||
cbuffer_t usb_audio_record_cbuf;
|
||||
int *(*get_buf)(void *ptr, u32 len);
|
||||
};
|
||||
struct usb_audio_info {
|
||||
usb_dev usb_id;
|
||||
struct usb_audio_play player;
|
||||
struct usb_audio_mic microphone;
|
||||
};
|
||||
|
||||
enum {
|
||||
AUDIO_PLAY_IDLE = 0,
|
||||
AUDIO_PLAY_START,
|
||||
AUDIO_PLAY_STOP,
|
||||
AUDIO_PLAY_PAUSE,
|
||||
};
|
||||
enum {
|
||||
AUDIO_RECORD_IDLE = 0,
|
||||
AUDIO_RECORD_START,
|
||||
AUDIO_RECORD_STOP,
|
||||
AUDIO_RECORD_PAUSE,
|
||||
};
|
||||
|
||||
#define EP_MAX_PACKET_SIZE (192)
|
||||
|
||||
struct usb_audio_info _usb_audio_info = {0};
|
||||
#define __this (&_usb_audio_info)
|
||||
|
||||
struct audio_device_t audio_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE];
|
||||
|
||||
static u8 ep_in_dma_buf[256] __attribute__((aligned(4)));
|
||||
static u8 ep_out_dma_buf[256] __attribute__((aligned(4)));
|
||||
|
||||
static int set_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct interface_ctrl uac_ctrl = {
|
||||
.interface_class = USB_CLASS_AUDIO,
|
||||
.set_power = set_power,
|
||||
.get_power = get_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info _uac_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = {
|
||||
{
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][0],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][1],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][2],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][3],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
const struct usb_interface_info *usb_if = &_uac_if[usb_id][interface_num];
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
memset(usb_if->dev.p, 0, sizeof(struct audio_device_t));
|
||||
host_dev->interface_info[interface_num] = usb_if;
|
||||
usb_if->dev.audio->parent = host_dev;
|
||||
|
||||
if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOCONTROL) {
|
||||
log_info("audio control interface : %d\n", interface_num);
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
usb_if->dev.audio->subclass = interface->bInterfaceSubClass;
|
||||
usb_if->dev.audio->interface_num = interface_num;
|
||||
|
||||
return sizeof(struct usb_interface_descriptor);
|
||||
}
|
||||
|
||||
if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING) {
|
||||
usb_if->dev.audio->subclass = interface->bInterfaceSubClass;
|
||||
usb_if->dev.audio->interface_num = interface_num;
|
||||
if (interface->bNumEndpoints == 0) {
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
do {
|
||||
struct usb_interface_descriptor *as_interface = (struct usb_interface_descriptor *)pBuf;
|
||||
if (as_interface->bNumEndpoints == 0 || as_interface->bInterfaceClass != USB_CLASS_AUDIO) {
|
||||
break;
|
||||
}
|
||||
log_info("audio streaming interface : %d ep_num:%d Altersetting:%d", interface_num, as_interface->bNumEndpoints, as_interface->bAlternateSetting);
|
||||
as_t = &usb_if->dev.audio->as[as_interface->bAlternateSetting - 1];
|
||||
as_t->bNumEndpoints = as_interface->bNumEndpoints;
|
||||
pBuf += (USB_DT_INTERFACE_SIZE + UAC_DT_AS_HEADER_SIZE);
|
||||
//解析format
|
||||
struct uac_format_type_i_discrete_descriptor *uac_format_desc = (struct uac_format_type_i_discrete_descriptor *)pBuf;
|
||||
if (uac_format_desc->bDescriptorSubtype == UAC_FORMAT_TYPE) {
|
||||
as_t->bFormatType = uac_format_desc->bFormatType;
|
||||
as_t->bNrChannels = uac_format_desc->bNrChannels;
|
||||
as_t->bSubframeSize = uac_format_desc->bSubframeSize;
|
||||
as_t->bBitResolution = uac_format_desc->bBitResolution;
|
||||
as_t->bSamFreqType = uac_format_desc->bSamFreqType;
|
||||
for (u8 i = 0; i < as_t->bSamFreqType; i++) {
|
||||
memcpy(&as_t->tSamFreq[i], &uac_format_desc->tSamFreq[i], 3);
|
||||
log_info("as bNrChannels:%d bBitResolution:%d tSamFreq : %d", as_t->bNrChannels, as_t->bBitResolution, as_t->tSamFreq[i]);
|
||||
}
|
||||
//Endpointdescriptor
|
||||
pBuf += uac_format_desc->bLength;
|
||||
/* for (int i = 0; i < as_t->bNumEndpoints; i++) { */
|
||||
struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (endpoint->bDescriptorType == USB_DT_ENDPOINT) {
|
||||
as_t->ep_Interval = endpoint->bInterval;
|
||||
as_t->ep_max_packet_size = endpoint->wMaxPacketSize;
|
||||
if (endpoint->bEndpointAddress & USB_DIR_IN) {
|
||||
as_t->ep = endpoint->bEndpointAddress & 0xf;
|
||||
log_info("ep in : %x\n", as_t->ep);
|
||||
usb_if->dev.audio->support = MICROPHONE_SUPPORTED;
|
||||
} else {
|
||||
as_t->ep = endpoint->bEndpointAddress;
|
||||
log_info("ep out : %x\n", as_t->ep);
|
||||
usb_if->dev.audio->support = HEADPHONE_SUPPORTED;
|
||||
}
|
||||
pBuf += (USB_DT_ENDPOINT_AUDIO_SIZE + UAC_ISO_ENDPOINT_DESC_SIZE);
|
||||
}
|
||||
/* } */
|
||||
} else {
|
||||
log_error("uac_format_desc->bDescriptorSubtype err!!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
/* log_info("lennnn:%d\n",pBuf - (u8 *)interface); */
|
||||
return pBuf - (u8 *)interface ;
|
||||
} else {
|
||||
log_info("audio streaming interface : %d ep_num:%d Altersetting:%d\n", interface_num, interface->bNumEndpoints, interface->bAlternateSetting);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__exit:
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
|
||||
}
|
||||
|
||||
static struct audio_device_t *__find_microphone_interface(const struct usb_host_device *host_dev)
|
||||
{
|
||||
struct audio_device_t *audio = NULL;
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
|
||||
if (usb_if &&
|
||||
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
|
||||
audio = usb_if->dev.audio;
|
||||
if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING &&
|
||||
audio->support == MICROPHONE_SUPPORTED) {
|
||||
// find microphone
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static struct audio_device_t *__find_headphone_interface(const struct usb_host_device *host_dev)
|
||||
{
|
||||
struct audio_device_t *audio = NULL;
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
|
||||
if (usb_if &&
|
||||
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
|
||||
audio = usb_if->dev.audio;
|
||||
if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING &&
|
||||
audio->support == HEADPHONE_SUPPORTED) {
|
||||
// find headphone
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static u32 play_vol_convert(u16 v)
|
||||
{
|
||||
//固定音量表,更换声卡需要修改音量表
|
||||
const u16 vol_table[] = {
|
||||
//0-100
|
||||
0xd300, //0
|
||||
0xd58f, 0xd7bf, 0xd9a8, 0xdb5b, 0xdce1, 0xde45, 0xdf8a, 0xe0b6, 0xe1cd, 0xe2d1,
|
||||
0xe3c5, 0xe4ab, 0xe583, 0xe651, 0xe714, 0xe7cd, 0xe87f, 0xe928, 0xe9ca, 0xea66,
|
||||
0xeafc, 0xeb8d, 0xec18, 0xec9e, 0xed20, 0xed9e, 0xee18, 0xee8e, 0xef00, 0xef6f,
|
||||
0xefdc, 0xf045, 0xf0ab, 0xf10f, 0xf171, 0xf1d0, 0xf22c, 0xf287, 0xf2e0, 0xf336,
|
||||
0xf38b, 0xf3de, 0xf42f, 0xf47e, 0xf4cc, 0xf518, 0xf563, 0xf5ad, 0xf5f5, 0xf63c,
|
||||
0xf681, 0xf6c6, 0xf709, 0xf74b, 0xf78c, 0xf7cb, 0xf80a, 0xf848, 0xf885, 0xf8c1,
|
||||
0xf8fc, 0xf936, 0xf96f, 0xf9a8, 0xf9df, 0xfa16, 0xfa4c, 0xfa81, 0xfab6, 0xfaea,
|
||||
0xfb1d, 0xfb50, 0xfb82, 0xfbb3, 0xfbe4, 0xfc14, 0xfc43, 0xfc72, 0xfca0, 0xfcce,
|
||||
0xfcfc, 0xfd28, 0xfd55, 0xfd80, 0xfdab, 0xfdd6, 0xfe01, 0xfe2a, 0xfe54, 0xfe7d,
|
||||
0xfea5, 0xfece, 0xfef5, 0xff1d, 0xff43, 0xff6a, 0xff90, 0xffb6, 0xffdb, 0x0000,
|
||||
};
|
||||
|
||||
if (v <= 100) {
|
||||
return vol_table[v];
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(vol_table) / 2; i++) {
|
||||
if (v <= vol_table[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_usb_audio_play_volume(u16 vol)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
u8 featureUnitID = 6;
|
||||
usb_audio_volume_control(host_dev, featureUnitID, 1, play_vol_convert(vol));
|
||||
usb_audio_volume_control(host_dev, featureUnitID, 2, play_vol_convert(vol));
|
||||
if (vol == 0) {
|
||||
__this->player.mute = 1;
|
||||
usb_audio_mute_control(host_dev, featureUnitID, __this->player.mute); //mute
|
||||
} else {
|
||||
if (__this->player.mute == 1) {
|
||||
__this->player.mute = 0;
|
||||
usb_audio_mute_control(host_dev, featureUnitID, __this->player.mute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USB_AUDIO_PLAY_TEST
|
||||
static 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
|
||||
};
|
||||
#endif
|
||||
static void usb_audio_tx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
u16 ep_max_packet_size = 0;
|
||||
u8 channel = 0;
|
||||
u32 rlen = 0;
|
||||
static u32 usb_audio_tx_len = 0;
|
||||
|
||||
if (__this->player.play_state != AUDIO_PLAY_START) {
|
||||
return;
|
||||
}
|
||||
|
||||
audio = __find_headphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find headphone interface!");
|
||||
return;
|
||||
}
|
||||
|
||||
as_t = &audio->as[__this->player.Cur_AlternateSetting - 1];
|
||||
/* ep_max_packet_size = as_t->ep_max_packet_size; */
|
||||
ep_max_packet_size = EP_MAX_PACKET_SIZE;
|
||||
channel = as_t->bNrChannels;
|
||||
|
||||
//iso send
|
||||
#ifdef USB_AUDIO_PLAY_TEST
|
||||
//For Test
|
||||
int tx_len = 0;
|
||||
#if 1 // 单声道双声道输出
|
||||
s16 buf[240 / 2];
|
||||
for (u8 i = 0, j = 0; i < 240 / 2; i += 2) {
|
||||
buf[i] = sin_48k[j];
|
||||
buf[i + 1] = sin_48k[j];
|
||||
j++;
|
||||
if (j >= sizeof(sin_48k) / sizeof(sin_48k[0])) {
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
//单声道直接输出
|
||||
u8 buf[248];
|
||||
do {
|
||||
memcpy(&buf[tx_len], sin_48k, sizeof(sin_48k));
|
||||
tx_len += sizeof(sin_48k);
|
||||
} while (tx_len < ep_max_packet_size);
|
||||
#endif
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
|
||||
#else
|
||||
if (__this->player.usb_audio_remain_len == 0) {
|
||||
cbuf_read_alloc(&__this->player.usb_audio_play_cbuf, &__this->player.usb_audio_remain_len);
|
||||
usb_audio_tx_len = 0;
|
||||
}
|
||||
if (__this->player.usb_audio_remain_len) {
|
||||
if (usb_audio_tx_len == 0) {
|
||||
rlen = cbuf_read(&__this->player.usb_audio_play_cbuf, __this->player.usb_audio_play_buf2, __this->player.usb_audio_remain_len);
|
||||
if (!rlen) {
|
||||
__this->player.usb_audio_remain_len = 0;
|
||||
usb_audio_tx_len = 0;
|
||||
putchar('C');
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1);
|
||||
os_sem_post(&__this->player.sem);
|
||||
return;
|
||||
}
|
||||
os_sem_post(&__this->player.sem);
|
||||
|
||||
}
|
||||
u8 *send_buf = __this->player.send_buf;
|
||||
u8 *play_buf = __this->player.usb_audio_play_buf2;
|
||||
if (channel == 2) {
|
||||
if (__this->player.src_channel == 1) {
|
||||
//源数据是单声道数据,转双声道输出
|
||||
int j = 0;
|
||||
for (u8 i = 0; i < ep_max_packet_size; i += 4) {
|
||||
//left
|
||||
*(send_buf + i) = *(play_buf + (usb_audio_tx_len + j));
|
||||
*(send_buf + i + 1) = *(play_buf + (usb_audio_tx_len + j + 1));
|
||||
//right
|
||||
|
||||
*(send_buf + i + 2) = *(play_buf + (usb_audio_tx_len + j));
|
||||
*(send_buf + i + 3) = *(play_buf + (usb_audio_tx_len + j + 1));
|
||||
j += 2;
|
||||
}
|
||||
usb_audio_tx_len += j;
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, send_buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
|
||||
} else if (__this->player.src_channel == 2) {
|
||||
//源数据是双声道数据,直接双声道输出
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, play_buf + usb_audio_tx_len, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
|
||||
usb_audio_tx_len += ep_max_packet_size;
|
||||
}
|
||||
} else if (channel == 1) {
|
||||
}
|
||||
if (usb_audio_tx_len >= __this->player.usb_audio_remain_len) {
|
||||
__this->player.usb_audio_remain_len = 0;
|
||||
usb_audio_tx_len = 0;
|
||||
}
|
||||
} else {
|
||||
//audio buf null ,send null packet
|
||||
putchar('E');
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
void set_vol_test(void *p)
|
||||
{
|
||||
struct usb_host_device *host_dev = (struct usb_host_device *)p;
|
||||
static u16 vol = 100;
|
||||
set_usb_audio_play_volume(vol);
|
||||
/* static u8 f = 0; */
|
||||
/* void usb_audio_pause_play(void); */
|
||||
/* void usb_audio_resume_play(void); */
|
||||
/* if (!f) { */
|
||||
/* usb_audio_pause_play(); */
|
||||
/* } else { */
|
||||
/* usb_audio_resume_play(); */
|
||||
/* } */
|
||||
/* f = !f; */
|
||||
vol -= 10;
|
||||
}
|
||||
void audio_play_task(void *p)
|
||||
{
|
||||
log_info(">>> Enter usb audio play task");
|
||||
struct usb_host_device *host_dev = (struct usb_host_device *)p;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 *ptr = NULL;
|
||||
u32 wlen = 0;
|
||||
u32 ret = 0;
|
||||
struct audio_device_t *audio = NULL;
|
||||
audio = __find_headphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->player.Cur_AlternateSetting - 1];
|
||||
/* u32 ep_max_packet_size = as_t->ep_max_packet_size; */
|
||||
u32 ep_max_packet_size = EP_MAX_PACKET_SIZE;
|
||||
log_info("ep max packet : %d\n", ep_max_packet_size);
|
||||
if (__this->player.send_buf) {
|
||||
free(__this->player.send_buf);
|
||||
__this->player.send_buf = NULL;
|
||||
}
|
||||
__this->player.send_buf = zalloc(ep_max_packet_size);
|
||||
u32 usb_audio_buf_size = ep_max_packet_size * 5; //预留5个包的缓存
|
||||
|
||||
/* sys_timer_add(host_dev,set_vol_test,5000); */
|
||||
os_sem_create(&__this->player.sem, 0);
|
||||
u32 host_ep = as_t->host_ep;
|
||||
__this->player.play_state = AUDIO_PLAY_START;
|
||||
//分配双缓存
|
||||
// 一个缓存保存读卡的数据,一个用于usb发送
|
||||
if (!__this->player.usb_audio_play_buf) {
|
||||
__this->player.usb_audio_play_buf = zalloc(usb_audio_buf_size);
|
||||
cbuf_init(&__this->player.usb_audio_play_cbuf, __this->player.usb_audio_play_buf, usb_audio_buf_size);
|
||||
usb_h_ep_write_async(usb_id, host_ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //启动iso传输
|
||||
}
|
||||
if (!__this->player.usb_audio_play_buf2) {
|
||||
__this->player.usb_audio_play_buf2 = zalloc(usb_audio_buf_size);
|
||||
}
|
||||
while (1) {
|
||||
if (__this->player.Cur_AlternateSetting == 0 || __this->player.play_state != AUDIO_PLAY_START) {
|
||||
putchar('C');
|
||||
os_time_dly(50);
|
||||
continue;
|
||||
}
|
||||
ptr = cbuf_write_alloc(&__this->player.usb_audio_play_cbuf, &wlen);
|
||||
if (wlen) {
|
||||
putchar('R');
|
||||
ret = __this->player.put_buf(ptr, wlen);
|
||||
if (ret != wlen) {
|
||||
__this->player.play_state = AUDIO_PLAY_STOP;
|
||||
goto __task_exit;
|
||||
|
||||
}
|
||||
cbuf_write_updata(&__this->player.usb_audio_play_cbuf, wlen);
|
||||
} else {
|
||||
log_w("usb audio play buf not enough!\n");
|
||||
}
|
||||
__task_exit:
|
||||
os_sem_pend(&__this->player.sem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_audio_start_play(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate)
|
||||
{
|
||||
log_info(" usb audio play\n");
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
u8 *ep_buffer = ep_out_dma_buf;
|
||||
u8 find_alternatesetting = 0;
|
||||
audio = __find_headphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find headphone interface!");
|
||||
return;
|
||||
}
|
||||
for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) {
|
||||
as_t = &audio->as[i];
|
||||
if (as_t->bBitResolution == bit_reso) {
|
||||
for (u8 j = 0; j < as_t->bSamFreqType; j++) {
|
||||
if (as_t->tSamFreq[j] == sample_rate) {
|
||||
find_alternatesetting = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!find_alternatesetting) {
|
||||
log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n");
|
||||
return;
|
||||
}
|
||||
|
||||
__this->usb_id = usb_id;
|
||||
//端点分配
|
||||
u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC);
|
||||
ASSERT(host_ep != -1, "ep not enough");
|
||||
|
||||
__this->player.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting
|
||||
__this->player.sample_rate = sample_rate; //选择采样率
|
||||
__this->player.src_channel = channel;
|
||||
as_t = &audio->as[find_alternatesetting - 1];
|
||||
u8 target_ep = as_t->ep;
|
||||
u8 ep_interval = as_t->ep_Interval;
|
||||
as_t->host_ep = host_ep;
|
||||
|
||||
usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface Alternatesetting
|
||||
usb_audio_sampling_frequency_control(host_dev, target_ep, sample_rate);//设置采样率
|
||||
//设置音量
|
||||
/* usb_audio_volume_control(host_dev, 6, 1, vol_convert(5)); */
|
||||
/* usb_audio_volume_control(host_dev, 6, 2, vol_convert(5)); */
|
||||
|
||||
log_info("H2D ep: %x --> %x interval: %d", host_ep, target_ep, ep_interval);
|
||||
usb_h_set_ep_isr(host_dev, host_ep, usb_audio_tx_isr, host_dev);
|
||||
usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, ep_interval, ep_buffer, sizeof(ep_out_dma_buf));
|
||||
task_create(audio_play_task, host_dev, "uac_play");
|
||||
}
|
||||
|
||||
void usb_audio_stop_play(const usb_dev usb_id)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
usb_h_set_ep_isr(NULL, 0, NULL, NULL);
|
||||
__this->player.put_buf(NULL, 0);
|
||||
__this->player.Cur_AlternateSetting = 0;
|
||||
__this->player.sample_rate = 0;
|
||||
__this->player.src_channel = 0;
|
||||
if (__this->player.usb_audio_play_buf) {
|
||||
free(__this->player.usb_audio_play_buf);
|
||||
__this->player.usb_audio_play_buf = NULL;
|
||||
}
|
||||
if (__this->player.usb_audio_play_buf2) {
|
||||
free(__this->player.usb_audio_play_buf2);
|
||||
__this->player.usb_audio_play_buf2 = NULL;
|
||||
}
|
||||
if (__this->player.send_buf) {
|
||||
free(__this->player.send_buf);
|
||||
__this->player.send_buf = NULL;
|
||||
}
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
task_kill("uac_play");
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
}
|
||||
void usb_audio_pause_play(void)
|
||||
{
|
||||
__this->player.play_state = AUDIO_PLAY_PAUSE;
|
||||
}
|
||||
void usb_audio_resume_play(void)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
struct audio_device_t *audio = __find_headphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->player.Cur_AlternateSetting - 1];
|
||||
__this->player.play_state = AUDIO_PLAY_START;
|
||||
usb_h_ep_write_async(__this->usb_id, as_t->host_ep, as_t->ep_max_packet_size, as_t->ep, NULL, as_t->ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //重新启动传输
|
||||
}
|
||||
|
||||
|
||||
static u32 record_vol_convert(u16 v)
|
||||
{
|
||||
//固定音量表,更换声卡需要修改音量表
|
||||
const u16 vol_table[] = {
|
||||
//0-100
|
||||
0xf400,
|
||||
0xf479, 0xf4ee, 0xf560, 0xf5cf, 0xf63a, 0xf6a3, 0xf709, 0xf76c, 0xf7cd, 0xf82b,
|
||||
0xf887, 0xf8e1, 0xf939, 0xf98f, 0xf9e4, 0xfa36, 0xfa87, 0xfad6, 0xfb23, 0xfb6f,
|
||||
0xfbba, 0xfc03, 0xfc4b, 0xfc91, 0xfcd6, 0xfd1a, 0xfd5d, 0xfd9f, 0xfde0, 0xfe1f,
|
||||
0xfe5e, 0xfe9b, 0xfed8, 0xff14, 0xff4e, 0xff88, 0xffc1, 0xfff9, 0x0003, 0x0069,
|
||||
0x00a3, 0x00de, 0x0119, 0x0155, 0x0193, 0x01d1, 0x0210, 0x0251, 0x0292, 0x02d5,
|
||||
0x0318, 0x035d, 0x03a3, 0x03eb, 0x0434, 0x047e, 0x04c9, 0x0517, 0x0565, 0x05b5,
|
||||
0x0607, 0x065b, 0x06b1, 0x0708, 0x0762, 0x07bd, 0x081b, 0x087c, 0x08de, 0x0943,
|
||||
0x09ab, 0x0a16, 0x0a84, 0x0af4, 0x0b69, 0x0be1, 0x0c5c, 0x0cdc, 0x0d60, 0x0de9,
|
||||
0x0e77, 0x0f0a, 0x0fa2, 0x1041, 0x10e7, 0x1195, 0x124a, 0x1308, 0x13d0, 0x14a3,
|
||||
0x1582, 0x166e, 0x176a, 0x1877, 0x1998, 0x1ad0, 0x1c24, 0x1d98, 0x1f33, 0x2100,
|
||||
};
|
||||
|
||||
if (v <= 100) {
|
||||
return vol_table[v];
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(vol_table) / 2; i++) {
|
||||
if (v <= vol_table[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_usb_audio_record_volume(u16 vol)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
u8 featureUnitID = 5;
|
||||
usb_audio_volume_control(host_dev, featureUnitID, 0, record_vol_convert(vol));
|
||||
}
|
||||
|
||||
static u32 write_file_len = 0;
|
||||
static void usb_audio_rx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
u8 buffer[192] = {0};
|
||||
u8 *ptr = NULL;
|
||||
int rlen, wlen = 0;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
audio = __find_microphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find microphone interface!");
|
||||
return;
|
||||
}
|
||||
if (__this->microphone.record_state != AUDIO_RECORD_START) {
|
||||
return;
|
||||
}
|
||||
as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1];
|
||||
u8 channel = as_t->bNrChannels;
|
||||
|
||||
u32 rx_len = usb_h_ep_read_async(usb_id, ep, as_t->ep, buffer, sizeof(buffer), USB_ENDPOINT_XFER_ISOC, 0);
|
||||
/* g_printf("RX:%d\n",rx_len); */
|
||||
/* printf_buf(buffer, rx_len); */
|
||||
cbuf_write(&__this->microphone.usb_audio_record_cbuf, buffer, rx_len);
|
||||
cbuf_write_alloc(&__this->microphone.usb_audio_record_cbuf, &wlen);
|
||||
if (wlen == 0) {
|
||||
putchar('O');
|
||||
if (write_file_len) {
|
||||
log_w("write againnnnn\n");
|
||||
}
|
||||
/* [> printf("R:%d W:%d\n", rx_len,wlen); <] */
|
||||
cbuf_read_alloc(&__this->microphone.usb_audio_record_cbuf, &rlen);
|
||||
cbuf_read(&__this->microphone.usb_audio_record_cbuf, __this->microphone.usb_audio_record_buf2, rlen);
|
||||
write_file_len = rlen;
|
||||
os_taskq_post_msg("uac_record", 2, 0x01, rlen);
|
||||
/* return; */
|
||||
}
|
||||
|
||||
usb_h_ep_read_async(usb_id, ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //触发下一个接收中断
|
||||
}
|
||||
void audio_record_task(void *p)
|
||||
{
|
||||
log_info(">>> Enter usb audio record task");
|
||||
struct usb_host_device *host_dev = (struct usb_host_device *)p;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 *ptr = NULL;
|
||||
u32 rlen = 0;
|
||||
u32 ret = 0;
|
||||
int msg[16];
|
||||
struct audio_device_t *audio = NULL;
|
||||
audio = __find_microphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1];
|
||||
/* u32 ep_max_packet_size = as_t->ep_max_packet_size; */
|
||||
u32 ep_max_packet_size = EP_MAX_PACKET_SIZE;
|
||||
log_info("ep max packet : %d\n", ep_max_packet_size);
|
||||
u32 usb_audio_buf_size = ep_max_packet_size * 50;
|
||||
|
||||
u32 host_ep = as_t->host_ep;
|
||||
u8 target_ep = as_t->ep;
|
||||
//分配双缓存
|
||||
// 一个缓存写卡的数据,一个用于usb接收
|
||||
if (!__this->microphone.usb_audio_record_buf) {
|
||||
__this->microphone.usb_audio_record_buf = zalloc(usb_audio_buf_size);
|
||||
cbuf_init(&__this->microphone.usb_audio_record_cbuf, __this->microphone.usb_audio_record_buf, usb_audio_buf_size);
|
||||
|
||||
}
|
||||
if (!__this->microphone.usb_audio_record_buf2) {
|
||||
__this->microphone.usb_audio_record_buf2 = zalloc(usb_audio_buf_size);
|
||||
}
|
||||
|
||||
usb_h_ep_read_async(usb_id, host_ep, target_ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //启动iso
|
||||
while (1) {
|
||||
ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
|
||||
if (ret == OS_TASKQ) {
|
||||
switch (msg[1]) {
|
||||
case 0x01:
|
||||
ptr = __this->microphone.usb_audio_record_buf2;
|
||||
rlen = msg[2];
|
||||
putchar('W');
|
||||
__this->microphone.get_buf(ptr, rlen);
|
||||
write_file_len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void usb_audio_start_record(const usb_dev usb_id, u8 bit_reso, u32 sample_rate)
|
||||
{
|
||||
log_info(" usb audio record\n");
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
u8 *ep_buffer = ep_in_dma_buf;
|
||||
u8 find_alternatesetting = 0;
|
||||
audio = __find_microphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find microphone interface!");
|
||||
return;
|
||||
}
|
||||
for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) {
|
||||
as_t = &audio->as[i];
|
||||
if (as_t->bBitResolution == bit_reso) {
|
||||
for (u8 j = 0; j < as_t->bSamFreqType; j++) {
|
||||
if (as_t->tSamFreq[j] == sample_rate) {
|
||||
find_alternatesetting = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!find_alternatesetting) {
|
||||
log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n");
|
||||
return;
|
||||
}
|
||||
//端点分配
|
||||
u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_ISOC);
|
||||
ASSERT(host_ep != -1, "ep not enough");
|
||||
__this->usb_id = usb_id;
|
||||
host_ep = host_ep | USB_DIR_IN;
|
||||
|
||||
__this->microphone.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting
|
||||
__this->microphone.sample_rate = sample_rate; //选择采样率
|
||||
as_t = &audio->as[find_alternatesetting - 1];
|
||||
u8 target_ep = as_t->ep;
|
||||
u8 ep_interval = as_t->ep_Interval;
|
||||
as_t->host_ep = host_ep;
|
||||
|
||||
usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface 1 Alternatesetting 1
|
||||
usb_audio_sampling_frequency_control(host_dev, target_ep, sample_rate);//设置采样率
|
||||
//设置音量
|
||||
/* usb_audio_volume_control(host_dev, 6, 1, vol_convert(5)); */
|
||||
/* usb_audio_volume_control(host_dev, 6, 2, vol_convert(5)); */
|
||||
log_info("D2H ep: %x --> %x", target_ep, host_ep);
|
||||
usb_h_set_ep_isr(host_dev, host_ep, usb_audio_rx_isr, host_dev);
|
||||
usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, ep_interval, ep_buffer, sizeof(ep_in_dma_buf));
|
||||
task_create(audio_record_task, host_dev, "uac_record");
|
||||
__this->microphone.record_state = AUDIO_RECORD_START;
|
||||
}
|
||||
void usb_audio_stop_record(const usb_dev usb_id)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
usb_h_set_ep_isr(NULL, 0, NULL, NULL);
|
||||
__this->microphone.get_buf(NULL, 0);
|
||||
__this->microphone.Cur_AlternateSetting = 0;
|
||||
__this->microphone.sample_rate = 0;
|
||||
if (__this->microphone.usb_audio_record_buf) {
|
||||
free(__this->microphone.usb_audio_record_buf);
|
||||
__this->microphone.usb_audio_record_buf = NULL;
|
||||
}
|
||||
if (__this->microphone.usb_audio_record_buf2) {
|
||||
free(__this->microphone.usb_audio_record_buf2);
|
||||
__this->microphone.usb_audio_record_buf2 = NULL;
|
||||
}
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
task_kill("uac_record");
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
}
|
||||
void usb_audio_pause_record(void)
|
||||
{
|
||||
__this->microphone.record_state = AUDIO_RECORD_PAUSE;
|
||||
}
|
||||
void usb_audio_resume_record(void)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
struct audio_device_t *audio = __find_microphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1];
|
||||
__this->microphone.record_state = AUDIO_RECORD_START;
|
||||
usb_h_ep_read_async(__this->usb_id, as_t->host_ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //重新启动接收
|
||||
}
|
||||
|
||||
void usb_audio_start_process(u32 id)
|
||||
{
|
||||
usb_audio_start_play(id, 1, 16, 48000); //开启headphone
|
||||
usb_audio_start_record(id, 16, 48000); //开启microphone
|
||||
}
|
||||
void usb_audio_stop_process(u32 id)
|
||||
{
|
||||
usb_audio_stop_play(id);
|
||||
usb_audio_stop_record(id);
|
||||
}
|
||||
|
||||
|
||||
static void usb_audio_event_handler(struct sys_event *event, void *priv)
|
||||
{
|
||||
const char *audio = NULL;
|
||||
switch (event->type) {
|
||||
case SYS_DEVICE_EVENT:
|
||||
if ((u32)event->arg == DEVICE_EVENT_FROM_USB_HOST) {
|
||||
if ((event->u.dev.event == DEVICE_EVENT_IN) ||
|
||||
(event->u.dev.event == DEVICE_EVENT_CHANGE)) {
|
||||
audio = (const char *)event->u.dev.value;
|
||||
usb_audio_start_process(audio[5] - '0');
|
||||
|
||||
} else if (event->u.dev.event == DEVICE_EVENT_OUT) {
|
||||
log_error("device out %x", event->u.dev.value);
|
||||
usb_audio_stop_process(audio[5] - '0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void usb_host_audio_init(int (*put_buf)(void *ptr, u32 len), int *(*get_buf)(void *ptr, u32 len))
|
||||
{
|
||||
memset(__this, 0, sizeof(struct usb_audio_info));
|
||||
__this->player.put_buf = put_buf;
|
||||
__this->microphone.get_buf = get_buf;
|
||||
register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_USB_HOST, 2,
|
||||
usb_audio_event_handler);
|
||||
}
|
||||
void usb_host_audio_exit()
|
||||
{
|
||||
unregister_sys_event_handler(usb_audio_event_handler);
|
||||
__this->player.put_buf = NULL;
|
||||
__this->microphone.get_buf = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,56 +0,0 @@
|
||||
#ifndef __AUDIO_H__
|
||||
#define __AUDIO_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/device/uac_audio.h"
|
||||
|
||||
|
||||
#define HEADPHONE_SUPPORTED 0x01
|
||||
#define MICROPHONE_SUPPORTED 0x02
|
||||
#define HEADSET_SUPPORTED 0x03
|
||||
|
||||
struct audio_streaming_t {
|
||||
u8 bNumEndpoints;
|
||||
u8 bFormatType; /** FORMAT_TYPE_1 */
|
||||
u8 bNrChannels; /** physical channels in the stream */
|
||||
u8 bSubframeSize;
|
||||
u8 bBitResolution;
|
||||
u8 bSamFreqType;
|
||||
u32 tSamFreq[8];
|
||||
u8 host_ep; //主机传输端点
|
||||
u8 ep; //从机端点(由描述符中指定)
|
||||
u8 ep_Interval;
|
||||
u16 ep_max_packet_size;
|
||||
};
|
||||
|
||||
struct audio_device_t {
|
||||
u8 interface_num; //接口号
|
||||
u8 subclass;
|
||||
u8 support;
|
||||
void *parent;
|
||||
struct audio_streaming_t as[8];
|
||||
};
|
||||
|
||||
int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
// API
|
||||
int usb_audio_play_put_buf(void *ptr, u32 len);
|
||||
int usb_audio_record_get_buf(void *ptr, u32 len);
|
||||
|
||||
//headphone api
|
||||
void set_usb_audio_play_volume(u16 vol);
|
||||
void usb_audio_start_play(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate); //指定播放数据的声道数,位数,采样率
|
||||
void usb_audio_stop_play(const usb_dev usb_id);
|
||||
void usb_audio_pause_play(void);
|
||||
void usb_audio_resume_play(void);
|
||||
|
||||
//microphone api
|
||||
void set_usb_audio_record_volume(u16 vol);
|
||||
void usb_audio_start_record(const usb_dev usb_id, u8 bit_reso, u32 sample_rate); //指定录制数据的位数,采样率
|
||||
void usb_audio_stop_record(const usb_dev usb_id);
|
||||
void usb_audio_pause_record(void);
|
||||
void usb_audio_resume_record(void);
|
||||
#endif
|
||||
@ -1,111 +0,0 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "device_drive.h"
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "audio.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[AUDIO]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#define TEST_FILE_ENABLE (0) //从sd卡读数据; 录制数据至sd卡
|
||||
#if (TEST_FILE_ENABLE)
|
||||
static FILE *play_file = NULL;
|
||||
int usb_audio_play_put_buf(void *ptr, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ptr == NULL && len == 0) {
|
||||
//err
|
||||
if (play_file) {
|
||||
fclose(play_file);
|
||||
play_file = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!play_file) {
|
||||
play_file = fopen("storage/sd0/C/raw.pcm", "r"); //单声道
|
||||
/* play_file = fopen("storage/sd0/C/raw2.pcm", "r"); //双声道 */
|
||||
if (!play_file) {
|
||||
log_e("fopen play file faild!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//读sd卡数据到播放缓存中
|
||||
ret = fread(play_file, ptr, len);
|
||||
if (ret != len) {
|
||||
log_e(" file read buf err %d\n", ret);
|
||||
fclose(play_file);
|
||||
play_file = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static FILE *record_file = NULL;
|
||||
int usb_audio_record_get_buf(void *ptr, u32 len)
|
||||
{
|
||||
#if (TEST_FILE_ENABLE)
|
||||
int ret = 0;
|
||||
static u32 cnt = 0;
|
||||
if (!record_file) {
|
||||
record_file = fopen("storage/sd0/C/record01.pcm", "w+");
|
||||
cnt = 0;
|
||||
if (!record_file) {
|
||||
log_e("fopen play file faild!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
putchar('W');
|
||||
ret = fwrite(record_file, ptr, len);
|
||||
if (ret != len) {
|
||||
log_e(" file write buf err %d\n", ret);
|
||||
fclose(record_file);
|
||||
record_file = NULL;
|
||||
return -1;
|
||||
}
|
||||
//test
|
||||
if (cnt++ >= 800) {
|
||||
cnt = 0;
|
||||
log_info("stop record....\n");
|
||||
fclose(record_file);
|
||||
record_file = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return len;
|
||||
}
|
||||
#else
|
||||
|
||||
//将数据传入usb
|
||||
//ptr:usb数据指针
|
||||
//len:需要传入的数据长度
|
||||
int usb_audio_play_put_buf(void *ptr, u32 len)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
//从usb读取数据
|
||||
//ptr:usb数据指针
|
||||
//len:读取的数据长度
|
||||
int usb_audio_record_get_buf(void *ptr, u32 len)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,657 +0,0 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "device_drive.h"
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "hid.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb_hid_keys.h"
|
||||
|
||||
#define MAIN_ITEM 0
|
||||
#define GLOBAL_ITEM 1
|
||||
#define LOCAL_ITEM 2
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[HID]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
struct hid_device_t hid_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE];
|
||||
|
||||
static int set_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
memset(hid_device[usb_id], 0, sizeof(hid_device[usb_id]));
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct interface_ctrl hid_ctrl = {
|
||||
.interface_class = USB_CLASS_HID,
|
||||
.set_power = set_power,
|
||||
.get_power = get_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info _usb_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = {
|
||||
{
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][0],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][1],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][2],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][3],
|
||||
},
|
||||
},
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
{
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][0],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][1],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][2],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][3],
|
||||
},
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static u8 interval[USB_MAX_HW_NUM][16];
|
||||
|
||||
int usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
|
||||
pBuf += 9;//hid desc;
|
||||
|
||||
const struct usb_interface_info *usb_if = &_usb_if[usb_id][interface_num];
|
||||
|
||||
memset(usb_if->dev.p, 0, sizeof(struct hid_device_t));
|
||||
|
||||
host_dev->interface_info[interface_num] = usb_if;
|
||||
usb_if->dev.hid->parent = host_dev;
|
||||
|
||||
log_info("hid eps %d %d %x %x", interface->bNumEndpoints, interface_num, usb_if, usb_if->dev.p);
|
||||
|
||||
log_info("parent %x hid @ interface %d usb_if %x hid %x",
|
||||
host_dev, interface_num, usb_if, usb_if->dev.hid);
|
||||
|
||||
if ((interface->bInterfaceProtocol == 0x02) ||
|
||||
(interface->bInterfaceProtocol == 0x01)) { //mouse & keyboard
|
||||
|
||||
usb_if->dev.hid->bNumEndpoints = interface->bNumEndpoints;
|
||||
usb_if->dev.hid->report_list[0].usage = interface->bInterfaceProtocol;
|
||||
for (int i = 0 ; i < interface->bNumEndpoints; i++) {
|
||||
endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (USB_DIR_IN & endpoint->bEndpointAddress) {
|
||||
const u8 ep = endpoint->bEndpointAddress & 0x0f;
|
||||
usb_if->dev.hid->ep_pair[i] = ep;
|
||||
interval[usb_id][ep] = endpoint->bInterval;
|
||||
log_info("interfacenum = %d,endpoint = %x interval = %x",
|
||||
interface->bInterfaceNumber, endpoint->bEndpointAddress, endpoint->bInterval);
|
||||
}
|
||||
pBuf += endpoint->bLength;
|
||||
}
|
||||
} else {
|
||||
log_info("vendor");
|
||||
host_dev->interface_info[interface_num] = NULL; //???
|
||||
for (int i = 0 ; i < interface->bNumEndpoints; i++) {
|
||||
endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (USB_DIR_IN & endpoint->bEndpointAddress) {
|
||||
/* interface_endpoint[interface->bInterfaceNumber] = endpoint->bEndpointAddress & 0x0f; */
|
||||
log_info("interfacenum = %d,endpoint = %x interval = %x",
|
||||
interface->bInterfaceNumber, endpoint->bEndpointAddress, endpoint->bInterval);
|
||||
}
|
||||
pBuf += endpoint->bLength;
|
||||
}
|
||||
return sizeof(struct usb_interface_descriptor);
|
||||
}
|
||||
|
||||
return pBuf - (u8 *)interface;
|
||||
}
|
||||
|
||||
static u32 _hid_report_parse(struct hid_device_t *hid, const u8 *report, u32 len)
|
||||
{
|
||||
hid->report_count = 0;
|
||||
struct report_info_t null_rpt;
|
||||
struct report_info_t *const rpt = &null_rpt;
|
||||
|
||||
memset(rpt, 0, sizeof(*rpt));
|
||||
|
||||
unsigned char ops;
|
||||
int index = 0;
|
||||
u8 report_size = 0;
|
||||
u8 report_count = 0;
|
||||
u8 cur_ops_is_report_size_count = 0;
|
||||
u8 old_ops_is_report_size_count = 0;
|
||||
s8 cur_section_bit = 0;
|
||||
u8 input_bit_index = 0;
|
||||
u8 total_bits = 0;
|
||||
u8 output_bit_index = 0;
|
||||
u8 cur_usage = 0;
|
||||
u32 undef_type = 0;
|
||||
u8 undef_usage = 0;
|
||||
u8 collection_deep = 0;
|
||||
|
||||
while (index < len) {
|
||||
ops = (char)report[index++];
|
||||
char bSize = ops & 0x03;
|
||||
bSize = bSize == 3 ? 4 : bSize; // size is 4 when bSize is 3
|
||||
char bType = (ops >> 2) & 0x03;
|
||||
char bTag = (ops >> 4) & 0x0F;
|
||||
|
||||
cur_ops_is_report_size_count = 0;
|
||||
char bSizeActual = 0;
|
||||
int itemVal = 0;
|
||||
for (int j = 0; j < bSize; j++) {
|
||||
if (index + j < len) {
|
||||
itemVal += report[index + j] << (8 * j);
|
||||
bSizeActual++;
|
||||
}
|
||||
}
|
||||
if (undef_type) {
|
||||
undef_type ++;
|
||||
if (bTag == 0x0A) {
|
||||
undef_usage ++;
|
||||
} else if (bTag == 0x0C) {
|
||||
undef_usage --;
|
||||
}
|
||||
if (undef_usage == 0 && undef_type > 2) {
|
||||
undef_type = 0;
|
||||
}
|
||||
index += bSize;
|
||||
continue;
|
||||
}
|
||||
if (undef_type) {
|
||||
index += bSize;
|
||||
continue;
|
||||
}
|
||||
if (itemVal == 0xffb5) {
|
||||
undef_type = 1;
|
||||
index += bSize;
|
||||
continue;
|
||||
} else {
|
||||
undef_type = 0;
|
||||
}
|
||||
if (bType == MAIN_ITEM) {
|
||||
if (old_ops_is_report_size_count) {
|
||||
cur_section_bit += report_size * report_count;
|
||||
}
|
||||
if (bTag == 0x08) {
|
||||
/* log_info("input %X", itemVal); */
|
||||
/* log_info("\tusage %x", cur_usage); */
|
||||
/* log_info("\t\tcur_section_bit %d", cur_section_bit); */
|
||||
if (rpt->usage == 0x02) { //mouse
|
||||
if (cur_usage == 1) {
|
||||
if (rpt->btn_start_bit == 0) {
|
||||
rpt->btn_start_bit = total_bits ;
|
||||
}
|
||||
rpt->btn_width += cur_section_bit ;
|
||||
/* log_info("btn_width %d-%d", rpt->btn_start_bit, rpt->btn_width); */
|
||||
} else if ((cur_usage == 0x30) || (cur_usage == 0x31)) {
|
||||
|
||||
if (rpt->xy_start_bit == 0) {
|
||||
rpt->xy_start_bit = total_bits;
|
||||
}
|
||||
rpt->xy_width = cur_section_bit;
|
||||
/* log_info("xy_width %d-%d", rpt->xy_start_bit, rpt->xy_width); */
|
||||
} else if (cur_usage == 0x38) {
|
||||
if (rpt->wheel_start_bit == 0) {
|
||||
rpt->wheel_start_bit = total_bits;
|
||||
}
|
||||
if (rpt->xy_width || cur_section_bit < 24) {
|
||||
rpt->wheel_width = cur_section_bit;
|
||||
/* log_info("wheel_width %d-%d", rpt->wheel_start_bit, rpt->wheel_width); */
|
||||
} else {
|
||||
rpt->wheel_width = rpt->xy_width = cur_section_bit / 3;
|
||||
|
||||
rpt->xy_start_bit = total_bits;
|
||||
rpt->wheel_start_bit = rpt->xy_start_bit + rpt->xy_width * 2;
|
||||
/* log_info("wheel_width %d-%d", rpt->wheel_start_bit, rpt->wheel_width); */
|
||||
/* log_info("xy_width %d-%d", rpt->xy_start_bit, rpt->xy_width); */
|
||||
}
|
||||
} else if (cur_usage == 0xb8) {
|
||||
rpt->wheel_width = rpt->xy_width = cur_section_bit / 4;
|
||||
rpt->xy_start_bit = total_bits;
|
||||
rpt->wheel_start_bit = rpt->xy_start_bit + rpt->xy_width * 2;
|
||||
}
|
||||
}
|
||||
total_bits += cur_section_bit;
|
||||
/* input_bit[input_bit_index++] = cur_section_bit; */
|
||||
cur_section_bit = -1;
|
||||
} else if (bTag == 0x09) {
|
||||
/* log_info("OUTPUT %X", itemVal); */
|
||||
/* log_info("\tusage %x", cur_usage); */
|
||||
/* log_info("\t\tcur_section_bit %d", cur_section_bit); */
|
||||
/* output_bit[output_bit_index++] = cur_section_bit; */
|
||||
cur_section_bit = -1;
|
||||
} else if (bTag == 0x0B) {
|
||||
/* log_info("Feature %X", itemVal); */
|
||||
/* log_info("\tusage %x", cur_usage); */
|
||||
/* log_info("\t\tcur_section_bit %d", cur_section_bit); */
|
||||
/* output_bit[output_bit_index++] = cur_section_bit; */
|
||||
cur_section_bit = -1;
|
||||
} else if (bTag == 0x0A) {
|
||||
collection_deep ++ ;
|
||||
log_info("Collection %d %x", collection_deep, rpt->usage);
|
||||
} else if (bTag == 0x0C) {
|
||||
collection_deep --;
|
||||
log_info("End Collection %d %x", collection_deep, rpt->usage);
|
||||
if (collection_deep == 0) {
|
||||
if (rpt->usage == 0x02 ||
|
||||
rpt->usage == 0x06 ||
|
||||
rpt->usage == 0x07) {
|
||||
|
||||
memcpy(&hid->report_list[hid->report_count], rpt, sizeof(*rpt));
|
||||
memset(rpt, 0, sizeof(*rpt));
|
||||
|
||||
hid->report_count ++;
|
||||
}
|
||||
}
|
||||
if (index < len) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
log_info("MAIN_ITEM Unknown btag :%x", bTag);
|
||||
return 1;
|
||||
}
|
||||
} else if (bType == GLOBAL_ITEM) {
|
||||
/* log_info("GLOBAL_ITEM"); */
|
||||
if (bTag == 0x00) {
|
||||
/* log_info("Usage Page %x", itemVal); */
|
||||
|
||||
if (rpt->usage == 0x06) {
|
||||
if (itemVal == 0x07) {
|
||||
rpt->usage = 0x07;
|
||||
log_info("re set type %x", 0x07);
|
||||
}
|
||||
}
|
||||
if (itemVal == 0x02) {
|
||||
rpt->usage = 0x02;
|
||||
log_info("re set type %x", 0x02);
|
||||
}
|
||||
|
||||
} else if (bTag == 0x01) {
|
||||
//log_info("Logical Minimum %x", itemVal);
|
||||
} else if (bTag == 0x02) {
|
||||
//log_info("Logical Maximum %x", itemVal);
|
||||
} else if (bTag == 0x03) {
|
||||
/* log_info("Physical Minimum %x", itemVal); */
|
||||
} else if (bTag == 0x04) {
|
||||
/* log_info("Physical Maximum %x", itemVal); */
|
||||
} else if (bTag == 0x05) {
|
||||
/* log_info("Unit Exponent %x", itemVal); */
|
||||
} else if (bTag == 0x06) {
|
||||
/* log_info("Unit %x", itemVal); */
|
||||
} else if (bTag == 0x07) {
|
||||
/* log_info("Report Size %x", itemVal); */
|
||||
report_size = itemVal;
|
||||
cur_ops_is_report_size_count = 1;
|
||||
} else if (bTag == 0x08) {
|
||||
log_info("Report ID %x", itemVal, rpt->usage);
|
||||
rpt->report_id = itemVal;
|
||||
} else if (bTag == 0x09) {
|
||||
/* log_info("Report Count %x", itemVal); */
|
||||
report_count = itemVal;
|
||||
cur_ops_is_report_size_count = 1;
|
||||
} else if (bTag == 0x0A) {
|
||||
/* log_info("Push %x", bSizeActual); */
|
||||
} else if (bTag == 0x0B) {
|
||||
/* log_info("Pop %x", bSizeActual); */
|
||||
} else {
|
||||
log_info("GLOBAL_ITEM Unknown btag :%x", bTag);
|
||||
return 2;
|
||||
}
|
||||
} else if (bType == LOCAL_ITEM) {
|
||||
/* log_info("LOCAL_ITEM"); */
|
||||
if (bTag == 0x00) {
|
||||
if (rpt->usage == 0) {
|
||||
rpt->usage = itemVal;
|
||||
log_info("set type %x", rpt->usage);
|
||||
}
|
||||
if (itemVal == 0x30) { //X
|
||||
} else if (itemVal == 0x31) { //y
|
||||
} else if (itemVal == 0x38) { //wheel
|
||||
} else {
|
||||
}
|
||||
/* log_info("\t change usage %x -> %x", cur_usage, itemVal); */
|
||||
cur_usage = itemVal;
|
||||
if (!collection_deep) {
|
||||
if (itemVal == 0x06 || itemVal == 0x07 || itemVal == 0x02) {
|
||||
//仅限键盘和鼠标
|
||||
rpt->usage = itemVal;
|
||||
log_info("set typee %x", rpt->usage);
|
||||
}
|
||||
}
|
||||
/* type = itemVal; */
|
||||
} else if (bTag == 0x01) {
|
||||
// log_info("Usage Minimum %x", itemVal);
|
||||
} else if (bTag == 0x02) {
|
||||
// log_info("Usage Maximum %x", itemVal);
|
||||
} else if (bTag == 0x03) {
|
||||
/* log_info("Designator Index %x", itemVal); */
|
||||
} else if (bTag == 0x04) {
|
||||
/* log_info("Designator Minimum %x", itemVal); */
|
||||
} else if (bTag == 0x05) {
|
||||
/* log_info("Designator Maximum %x", itemVal); */
|
||||
} else if (bTag == 0x07) {
|
||||
/* log_info("String Index %x", itemVal); */
|
||||
} else if (bTag == 0x08) {
|
||||
/* log_info("String Minimum %x", itemVal); */
|
||||
} else if (bTag == 0x09) {
|
||||
/* log_info("String Maximum %x", itemVal); */
|
||||
} else if (bTag == 0x0A) {
|
||||
/* log_info("Delimiter %x", itemVal); */
|
||||
} else {
|
||||
log_info("LOCAL_ITEM Unknown btag :%x", bTag);
|
||||
return 3;
|
||||
}
|
||||
} else {
|
||||
log_info("OTHER Unknown btag :%x", bTag);
|
||||
return 4;
|
||||
}
|
||||
if (!cur_ops_is_report_size_count && old_ops_is_report_size_count) {
|
||||
if (cur_section_bit != -1) {
|
||||
cur_section_bit += report_size * report_count;
|
||||
} else {
|
||||
cur_section_bit = 0;
|
||||
}
|
||||
}
|
||||
if (cur_section_bit == -1) {
|
||||
cur_section_bit = 0;
|
||||
}
|
||||
old_ops_is_report_size_count = cur_ops_is_report_size_count;
|
||||
index += bSize;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static u32 hid_report_parse(struct hid_device_t *hid, const u8 *report, u32 len)
|
||||
{
|
||||
u8 type = _hid_report_parse(hid, report, len);
|
||||
for (int i = 0; i < hid->report_count; i++) {
|
||||
struct report_info_t *rpt = &hid->report_list[i];
|
||||
if (rpt->usage == 0x02) {
|
||||
if (rpt->report_id == 0) {
|
||||
rpt->report_id = 0xff;
|
||||
}
|
||||
rpt->btn_start_bit /= 8;
|
||||
rpt->btn_width /= 8;
|
||||
rpt->xy_start_bit /= 8;
|
||||
rpt->xy_width /= 8;
|
||||
rpt->wheel_start_bit /= 8;
|
||||
rpt->wheel_width /= 8;
|
||||
|
||||
log_info("mouse report_id %d",
|
||||
rpt->report_id);
|
||||
|
||||
log_info("btn_width %d-%d",
|
||||
rpt->btn_start_bit, rpt->btn_width);
|
||||
log_info("xy_width %d-%d",
|
||||
rpt->xy_start_bit, rpt->xy_width);
|
||||
log_info("wheel_width %d-%d",
|
||||
rpt->wheel_start_bit, rpt->wheel_width);
|
||||
|
||||
if (rpt->btn_width != 2) {
|
||||
rpt->btn_width = 1;
|
||||
}
|
||||
|
||||
log_info("btn_width %d-%d",
|
||||
rpt->btn_start_bit, rpt->btn_width);
|
||||
|
||||
} else if (rpt->usage == 6 || rpt->usage == 7) {
|
||||
if (rpt->report_id == 0) {
|
||||
rpt->report_id = 0xff;
|
||||
}
|
||||
log_info("keyboard report_id %d", rpt->report_id);
|
||||
} else {
|
||||
log_info("unknown usage %d", rpt->usage);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mouse_route(const struct mouse_data_t *p);
|
||||
/* __attribute__((weak)) void mouse_route(const struct mouse_data_t *p) */
|
||||
/* { */
|
||||
/* log_info("btn: %x x-y %d %d wheel %d ac_pan %d", */
|
||||
/* p->btn, p->x, p->y, p->wheel, p->ac_pan); */
|
||||
/* } */
|
||||
static void hid_convert_mouse(const struct report_info_t *mouse, const u8 *buffer)
|
||||
{
|
||||
struct mouse_data_t mouse_data;
|
||||
memset(&mouse_data, 0, sizeof(mouse_data));
|
||||
if (mouse->report_id != 0xff) {
|
||||
if (mouse->report_id != buffer[0]) {
|
||||
log_error("report_id = %x buffer[0] = %x", mouse->report_id, buffer[0]);
|
||||
return;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
const u8 *ptr;
|
||||
ptr = &buffer[mouse->btn_start_bit];
|
||||
if (mouse->btn_width == 2) {
|
||||
mouse_data.btn = ptr[0] | (ptr[1] << 8);
|
||||
} else {
|
||||
mouse_data.btn = ptr[0] ;
|
||||
}
|
||||
s16 tmp;
|
||||
ptr = &buffer[mouse->xy_start_bit];
|
||||
if (mouse->xy_width == 1 || mouse->xy_width == 2) {
|
||||
mouse_data.x = (char)ptr[0];
|
||||
mouse_data.y = (char)ptr[1];
|
||||
} else if (mouse->xy_width == 4) {
|
||||
mouse_data.x = ptr[0] | (ptr[1] << 8);
|
||||
ptr += 2;
|
||||
mouse_data.y = ptr[0] | (ptr[1] << 8);
|
||||
} else if (mouse->xy_width == 3) {
|
||||
tmp = (ptr[1] & 0xf) << 12 | ptr[0] << 4;
|
||||
tmp = tmp >> 4;
|
||||
mouse_data.x = tmp;
|
||||
|
||||
tmp = (ptr[2] << 8) | ((ptr[1] >> 4) << 4);
|
||||
tmp = tmp >> 4;
|
||||
mouse_data.y = tmp;
|
||||
} else {
|
||||
log_error("error mouse xy_width %d", mouse->xy_width);
|
||||
}
|
||||
|
||||
ptr = &buffer[mouse->wheel_start_bit];
|
||||
|
||||
if (mouse->wheel_width == 1) {
|
||||
mouse_data.wheel = (char)ptr[0];
|
||||
} else {
|
||||
mouse_data.wheel = ptr[0] | (ptr[1] << 8);
|
||||
}
|
||||
|
||||
mouse_route(&mouse_data);
|
||||
}
|
||||
__attribute__((weak)) void keyboard_route(const u8 *p)
|
||||
{
|
||||
log_info("keyboard_buffer:");
|
||||
printf_buf(p, 12);
|
||||
}
|
||||
void hid_convert_krbd(const struct report_info_t *kbd, u8 *buffer)
|
||||
{
|
||||
#if 0
|
||||
u8 keyboard_buffer[12];
|
||||
memset(keyboard_buffer, 0, sizeof(keyboard_buffer));
|
||||
if (kbd->report_id != 0xff) {
|
||||
if (kbd->report_id != buffer[0]) {
|
||||
log_error("report_id = %x buffer[0] = %x", kbd->report_id, buffer[0]);
|
||||
return;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
|
||||
u8 idx = 0;
|
||||
u8 index = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (buffer[0] & BIT(i)) {
|
||||
keyboard_buffer[idx++] = 0xe0 + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer[1] == 0) {
|
||||
buffer += 2;
|
||||
}
|
||||
index = idx;
|
||||
for (; idx < 12; idx++) {
|
||||
if (*buffer) {
|
||||
keyboard_buffer[index] = *buffer;
|
||||
index++;
|
||||
}
|
||||
buffer ++;
|
||||
}
|
||||
keyboard_route(keyboard_buffer);
|
||||
#else
|
||||
if (kbd->report_id != 0xff) {
|
||||
if (kbd->report_id != buffer[0]) {
|
||||
log_error("report_id = %x buffer[0] = %x", kbd->report_id, buffer[0]);
|
||||
return;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
u8 keyboard_buffer[8];
|
||||
memset(keyboard_buffer, 0, sizeof(keyboard_buffer));
|
||||
|
||||
keyboard_buffer[0] = *buffer;
|
||||
buffer ++;
|
||||
|
||||
if (*buffer == 0) {
|
||||
buffer ++;
|
||||
}
|
||||
keyboard_buffer[1] = 0;
|
||||
|
||||
/* memcpy(&keyboard_buffer[2], buffer, 6); */
|
||||
u8 pos = 2;
|
||||
for (int i = pos; i < 8; i++) {
|
||||
if (*buffer) {
|
||||
keyboard_buffer[pos] = *buffer;
|
||||
pos++;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
keyboard_route(keyboard_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void hid_route(const struct hid_device_t *hid, const u8 *buffer)
|
||||
{
|
||||
for (int i = 0; i < hid->report_count; i++) {
|
||||
if (hid->report_list[i].usage == 0x02) {
|
||||
hid_convert_mouse(&hid->report_list[i], buffer);
|
||||
} else if ((hid->report_list[i].usage == 0x06) ||
|
||||
(hid->report_list[i].usage == 0x07)) {
|
||||
hid_convert_krbd(&hid->report_list[i], buffer);
|
||||
} else {
|
||||
r_printf("usage %x", hid->report_list[i].usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void hid_isr(struct usb_interface_info *usb_if, u32 ep)
|
||||
{
|
||||
u8 buffer[64] = {0};
|
||||
struct usb_host_device *host_dev = usb_if->dev.hid->parent;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
u32 target_ep = usb_if->dev.hid->ep_pair[ep];
|
||||
u32 rx_len = usb_h_ep_read_async(usb_id, ep, target_ep, buffer, 64, USB_ENDPOINT_XFER_INT, 0);
|
||||
|
||||
if (rx_len) {
|
||||
hid_route(usb_if->dev.hid, buffer);
|
||||
}
|
||||
/* printf_buf(buffer, rx_len); */
|
||||
|
||||
usb_h_ep_read_async(usb_id, ep, target_ep, buffer, 8, USB_ENDPOINT_XFER_INT, 1);
|
||||
}
|
||||
void hid_process(u32 id)
|
||||
{
|
||||
struct usb_host_device *host_dev = host_id2device(id);
|
||||
u8 report[256 + 2];
|
||||
u8 ep_pair[4];
|
||||
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
struct usb_interface_info *usb_if = host_dev->interface_info[i];
|
||||
log_info("parent %x hid @ interface %d usb_if %x hid %x",
|
||||
host_dev, i, usb_if, usb_if ? usb_if->dev.hid : 0);
|
||||
if (usb_if &&
|
||||
(usb_if->ctrl->interface_class == USB_CLASS_HID)) {
|
||||
hid_set_idle(host_dev, i);
|
||||
memset(report, 0, sizeof(report));
|
||||
hid_get_report(host_dev, report, i, 0xff);
|
||||
printf_buf(report, 256);
|
||||
hid_report_parse(usb_if->dev.hid, report, 256);
|
||||
memcpy(ep_pair, usb_if->dev.hid->ep_pair, 4);
|
||||
|
||||
if (usb_if->dev.hid->report_count == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < usb_if->dev.hid->bNumEndpoints; i++) {
|
||||
|
||||
u32 host_ep = usb_get_ep_num(id, USB_DIR_IN, USB_ENDPOINT_XFER_INT);
|
||||
|
||||
ASSERT(host_ep != -1, "ep not enough");
|
||||
|
||||
u32 target_ep = ep_pair[i];
|
||||
|
||||
usb_if->dev.hid->ep_pair[host_ep] = target_ep;
|
||||
|
||||
log_info("D2H ep: %x --> %x interval %d",
|
||||
target_ep, host_ep, interval[id][target_ep]);
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, hid_isr, usb_if);
|
||||
|
||||
u8 *ep_buffer = usb_h_get_ep_buffer(id, host_ep | USB_DIR_OUT);
|
||||
usb_h_ep_config(id, host_ep | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 1,
|
||||
interval[id][target_ep], ep_buffer, 64);
|
||||
int r = usb_h_ep_read_async(id, host_ep, target_ep, NULL, 0, USB_ENDPOINT_XFER_INT, 1);
|
||||
}
|
||||
} else {
|
||||
if (usb_if) {
|
||||
log_error("error hid class %x", usb_if->ctrl->interface_class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,83 +0,0 @@
|
||||
/**@file hid.h
|
||||
* @brief hid驱动头文件(做主机)
|
||||
* @details 结构体声明,功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-9-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC632N
|
||||
* SDK版本:AC632N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-9-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __HID_H__
|
||||
#define __HID_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
|
||||
/**@struct report_info_t
|
||||
* @brief 报告描述符包含的信息结构体\n
|
||||
* 自定义一些私有数据信息存储在该结构体中
|
||||
*/
|
||||
struct report_info_t {
|
||||
u8 report_id; ///<id号,不同hid设备对应不同id
|
||||
u8 usage; ///<描述该数据信息的用途
|
||||
|
||||
u8 btn_start_bit; ///<鼠标按键数据起始位
|
||||
u8 btn_width; ///<鼠标按键数据宽度
|
||||
|
||||
u8 xy_start_bit; ///<鼠标平移数据起始位
|
||||
u8 xy_width; ///<鼠标平移数据宽度
|
||||
|
||||
u8 wheel_start_bit; ///<鼠标滚轮数据起始位
|
||||
u8 wheel_width; ///<鼠标滚轮数据宽度
|
||||
};
|
||||
|
||||
#define MAX_REPORT_COUNT 4
|
||||
|
||||
/**@struct hid_device_t
|
||||
* @brief 报告描述符包含的信息结构体\n
|
||||
* 自定义一些私有数据信息存储在该结构体中
|
||||
*/
|
||||
struct hid_device_t {
|
||||
void *parent; ///<定义的parent指针,指向该hid的所属设备
|
||||
u8 ep_pair[4]; ///<端点对数组,数组下标存放主机端点,对应的元素存放目标端点
|
||||
u8 report_count; ///<报告描述符中item计数器
|
||||
u8 bNumEndpoints; ///<端点数量
|
||||
struct report_info_t report_list[MAX_REPORT_COUNT]; ///<报告描述符结构体
|
||||
};
|
||||
|
||||
/**@brief USB hid设备解析
|
||||
* @param[in] host_dev usb_host_device定义的结构体指针
|
||||
* @param[in] interface_num 接口号
|
||||
* @param[in] *pBuf 数据指针,指向数据存放的地址
|
||||
* @return 接口描述符长度
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_hid_parser(host_dev,interface_num,pBuf);
|
||||
* @encode
|
||||
*/
|
||||
int usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
/**@brief USB hid设备信息处理
|
||||
* @param[in] id usb设备id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_process(id);
|
||||
* @encode
|
||||
*/
|
||||
void hid_process(u32 id);
|
||||
|
||||
#endif /*HID_H*/
|
||||
@ -1,319 +0,0 @@
|
||||
/**
|
||||
* @file usb_bulk_transfer.c
|
||||
* @brief bulk transfer driver
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1.00
|
||||
* @date 2017-02-09
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "jiffies.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_storage.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "app_config.h"
|
||||
#include "device_drive.h"
|
||||
|
||||
#if USB_HOST_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"
|
||||
|
||||
struct usb_request_block {
|
||||
void *ptr;
|
||||
u32 len;
|
||||
u32 target_ep;
|
||||
u16 rxmap;
|
||||
u16 txmap;
|
||||
u32 msg;
|
||||
u32 async_mode;
|
||||
};
|
||||
static struct usb_request_block urb;
|
||||
|
||||
u8 get_async_mode(void)
|
||||
{
|
||||
u8 mode = BULK_ASYNC_MODE_EXIT ;
|
||||
#if UDISK_READ_512_ASYNC_ENABLE
|
||||
local_irq_disable();
|
||||
mode = urb.async_mode;
|
||||
local_irq_enable();
|
||||
#endif
|
||||
return mode;
|
||||
|
||||
}
|
||||
void set_async_mode(u8 mode)
|
||||
{
|
||||
#if UDISK_READ_512_ASYNC_ENABLE
|
||||
local_irq_disable();
|
||||
urb.async_mode = mode;
|
||||
local_irq_enable();
|
||||
#endif
|
||||
}
|
||||
static void usb_bulk_rx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
int l = min(urb.len, urb.rxmap);
|
||||
|
||||
l = usb_h_ep_read_async(usb_id, ep, urb.target_ep, urb.ptr, l, USB_ENDPOINT_XFER_BULK, 0);
|
||||
/* g_printf("%s() %d %d", __func__, l, urb.len); */
|
||||
if (l > 0) {
|
||||
urb.len -= l;
|
||||
if (urb.ptr) {
|
||||
urb.ptr += l;
|
||||
}
|
||||
urb.msg = 0;
|
||||
} else {
|
||||
urb.msg = l;
|
||||
urb.len = 0;
|
||||
}
|
||||
|
||||
if (urb.len == 0) {
|
||||
u32 async_mode = get_async_mode();
|
||||
|
||||
if (async_mode == BULK_ASYNC_MODE_EXIT) {
|
||||
usb_sem_post(host_dev);
|
||||
} else if (async_mode == BULK_ASYNC_MODE_SEM_PEND) {
|
||||
if (urb.msg == 0) {
|
||||
usb_sem_post(host_dev);
|
||||
} else {
|
||||
r_printf("usb async error");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
usb_h_ep_read_async(usb_id, ep, urb.target_ep, urb.ptr, urb.len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
}
|
||||
}
|
||||
s32 usb_bulk_only_receive_async(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
|
||||
urb.ptr = pBuf;
|
||||
urb.len = len;
|
||||
urb.target_ep = target_ep;
|
||||
|
||||
#ifdef CONFIG_USB_SUPPORT_MRX_TX
|
||||
urb.rxmap = 1 * 1024;
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
urb.rxmap = rxmaxp;
|
||||
#else
|
||||
urb.rxmap = 0x40;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
urb.msg = -DEV_ERR_OFFLINE;
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, usb_bulk_rx_isr, host_dev);
|
||||
usb_set_intr_rxe(usb_id, host_ep);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_rxfuncaddr(usb_id, host_ep, devnum);
|
||||
#endif
|
||||
|
||||
int ret = usb_h_ep_read_async(usb_id, host_ep, target_ep, urb.ptr, len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usb_sem_pend(host_dev, 300);
|
||||
|
||||
usb_clr_intr_rxe(usb_id, host_ep);
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, NULL, host_dev);
|
||||
if (ret) {
|
||||
return -DEV_ERR_TIMEOUT;
|
||||
}
|
||||
return urb.msg ? urb.msg : len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_bulk_receive_async_no_wait 启动USB Bulk 异步预读
|
||||
* 不用等信号量,启动传输后返回
|
||||
* @param device 设备句柄
|
||||
* @param pBuf 读buffer缓冲区,芯片所有memory都可以
|
||||
* @param len 需要预读的长度
|
||||
*
|
||||
* @return 负数表示失败
|
||||
*/
|
||||
s32 usb_bulk_receive_async_no_wait(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
|
||||
set_async_mode(BULK_ASYNC_MODE_SEM_PEND);
|
||||
urb.ptr = pBuf;
|
||||
urb.len = len;
|
||||
urb.target_ep = target_ep;
|
||||
|
||||
#ifdef CONFIG_USB_SUPPORT_MRX_TX
|
||||
urb.rxmap = 1 * 1024;
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
urb.rxmap = rxmaxp;
|
||||
#else
|
||||
urb.rxmap = 0x40;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
urb.msg = -DEV_ERR_OFFLINE;
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, usb_bulk_rx_isr, host_dev);
|
||||
usb_set_intr_rxe(usb_id, host_ep);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_rxfuncaddr(usb_id, host_ep, devnum);
|
||||
#endif
|
||||
|
||||
int ret = usb_h_ep_read_async(usb_id, host_ep, target_ep, urb.ptr, len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
if (ret < 0) {
|
||||
if (ret == -DEV_ERR_RXSTALL) {
|
||||
ret = usb_clear_feature(host_dev, target_ep | USB_DIR_IN);
|
||||
if (ret == 0) {
|
||||
return -DEV_ERR_RXSTALL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static s32 _usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
#if 0
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return usb_h_bulk_read(usb_id, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
#else
|
||||
return usb_bulk_only_receive_async(device, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
#endif
|
||||
}
|
||||
s32 usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
int ret = _usb_bulk_only_receive(device, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
if (ret == -DEV_ERR_RXSTALL) {
|
||||
ret = usb_clear_feature(host_dev, target_ep | USB_DIR_IN);
|
||||
if (ret == 0) {
|
||||
return -DEV_ERR_RXSTALL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static void usb_bulk_tx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
int l = min(urb.len, urb.txmap);
|
||||
l = usb_h_ep_write_async(usb_id, ep, urb.txmap, urb.target_ep, urb.ptr, l, USB_ENDPOINT_XFER_BULK, 0);
|
||||
|
||||
if (l > 0) {
|
||||
urb.len -= l;
|
||||
urb.ptr += l;
|
||||
urb.msg = 0;
|
||||
} else {
|
||||
urb.msg = l;
|
||||
urb.len = 0;
|
||||
}
|
||||
|
||||
if (urb.len == 0) {
|
||||
if (urb.msg || l == 0) {
|
||||
usb_sem_post(host_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
s32 usb_bulk_only_send_async(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
|
||||
urb.target_ep = target_ep;
|
||||
#ifdef CONFIG_USB_SUPPORT_MRX_TX
|
||||
urb.txmap = 8 * 1024;
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
urb.txmap = rxmaxp;
|
||||
#else
|
||||
urb.txmap = 0x40;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
urb.msg = -DEV_ERR_OFFLINE;
|
||||
urb.len = len - min(len, urb.txmap);
|
||||
urb.ptr = (u8 *)pBuf + min(len, urb.txmap);
|
||||
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep, usb_bulk_tx_isr, host_dev);
|
||||
usb_set_intr_txe(usb_id, host_ep);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_txfuncaddr(usb_id, host_ep, devnum);
|
||||
#endif
|
||||
|
||||
int ret = usb_h_ep_write_async(usb_id, host_ep, txmaxp, target_ep, pBuf, min(len, urb.txmap), USB_ENDPOINT_XFER_BULK, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usb_sem_pend(host_dev, 250);
|
||||
|
||||
usb_clr_intr_txe(usb_id, host_ep);
|
||||
usb_h_set_ep_isr(host_dev, host_ep, NULL, host_dev);
|
||||
|
||||
if (ret) {
|
||||
r_printf("ret %d", ret);
|
||||
return -DEV_ERR_TIMEOUT;
|
||||
}
|
||||
/* g_printf("%s() %d %d", __func__, urb.len, urb.msg); */
|
||||
return urb.msg ? urb.msg : len;
|
||||
}
|
||||
/**
|
||||
* @brief usb_bulk_only_send
|
||||
*
|
||||
* @param device
|
||||
* @param host_ep 主机的端点号
|
||||
* @param target_ep 目标设备的端点号
|
||||
* @param pBuf
|
||||
* @param len
|
||||
*
|
||||
* @return 负数失败
|
||||
* 正数发送的字节数
|
||||
*/
|
||||
static s32 _usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len)
|
||||
{
|
||||
#if 0
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return usb_h_bulk_write(usb_id, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
#elif 0
|
||||
if (len < 512) {
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return usb_h_bulk_write(usb_id, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
} else {
|
||||
return usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
}
|
||||
#else
|
||||
return usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
#endif
|
||||
}
|
||||
s32 usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
int ret = _usb_bulk_only_send(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
|
||||
if (ret == -DEV_ERR_TXSTALL) {
|
||||
ret = usb_clear_feature(host_dev, target_ep);
|
||||
if (ret == 0) {
|
||||
return -DEV_ERR_TXSTALL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif
|
||||
@ -1,120 +0,0 @@
|
||||
/**@file usb_bulk_transfer.h
|
||||
* @brief usb_bulk_transfer批量传输头文件
|
||||
* @details 功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_BULK_TRANSFER_H__
|
||||
#define __USB_BULK_TRANSFER_H__
|
||||
#include "typedef.h"
|
||||
#include "device/device.h"
|
||||
|
||||
|
||||
/**@brief 批量传输只读取(异步模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] host_ep 主机端点号
|
||||
* @param[in] rxmaxp 接收端点最大包长
|
||||
* @param[in] target_ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_receive_async(device, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_receive_async(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 批量传输只读取(普通模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] host_ep 主机端点号
|
||||
* @param[in] rxmaxp 接收端点最大包长
|
||||
* @param[in] ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_receive(device, host_ep, rxmaxp, ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 ep, u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 批量传输只发送(异步模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] host_ep 主机端点号
|
||||
* @param[in] txmaxp 发送端点最大包长
|
||||
* @param[in] target_ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_send_async(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 批量传输只发送(普通模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] ep 主机端点号
|
||||
* @param[in] txmaxp 发送端点最大包长
|
||||
* @param[in] ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_send(device, host_ep, txmaxp, ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 ep, const u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 获取异步模式当前状态
|
||||
* @param[in] 空
|
||||
* @return 当前状态
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_async_mode();
|
||||
* @encode
|
||||
*/
|
||||
u8 get_async_mode(void);
|
||||
|
||||
/**@brief 设置异步模式
|
||||
* @param[in] mode 需要设置的模式
|
||||
* @return 空
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_async_mode(BULK_ASYNC_MODE_EXIT);退出异步模式
|
||||
* @encode
|
||||
*/
|
||||
void set_async_mode(u8 mode);
|
||||
|
||||
/**@brief 批量传输异步模式读取并且不等待
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] ep 主机端点号
|
||||
* @param[in] rxmaxp 发送端点最大包长
|
||||
* @param[in] target_ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_send(device, host_ep, rxmaxp, ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_receive_async_no_wait(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len);
|
||||
#endif
|
||||
@ -1,637 +0,0 @@
|
||||
/**
|
||||
* @file usb_ctrl_transfer.c
|
||||
* @brief usb 控制传输接口
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1.00
|
||||
* @date 2017-02-09
|
||||
*/
|
||||
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "app_config.h"
|
||||
#include "device_drive.h"
|
||||
#include "gpio.h"
|
||||
#include "usb/scsi.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 USB_HOST_ENABLE
|
||||
|
||||
_WEAK_
|
||||
void usb_dis_ep0_txdly(const usb_dev id)
|
||||
{
|
||||
}
|
||||
static void ep0_h_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
usb_sem_post(host_dev);
|
||||
}
|
||||
/**
|
||||
* @brief usb_ctlXfer
|
||||
*
|
||||
* @param host_dev
|
||||
* @param urb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static int usb_ctlXfer(struct usb_host_device *host_dev, struct ctlXfer *urb)
|
||||
{
|
||||
u32 ret = DEV_ERR_NONE;
|
||||
u8 reg = 0;
|
||||
u32 data_len;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
u32 max_packet_size = host_dev->private_data.ep0_max_packet_size;
|
||||
|
||||
usb_write_faddr(usb_id, devnum);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_txfuncaddr(usb_id, 0, devnum);
|
||||
#endif
|
||||
|
||||
switch (urb->stage) {
|
||||
case USB_PID_SETUP :
|
||||
usb_write_ep0(usb_id, (u8 *)&urb->setup, 8);
|
||||
reg = CSR0H_SetupPkt | CSR0H_TxPktRdy;
|
||||
break;
|
||||
case USB_PID_IN :
|
||||
if (urb->setup.wLength) {
|
||||
reg = CSR0H_ReqPkt;
|
||||
} else {
|
||||
reg = CSR0H_StatusPkt | CSR0H_ReqPkt;
|
||||
}
|
||||
break;
|
||||
case USB_PID_OUT:
|
||||
if (urb->setup.wLength) {
|
||||
data_len = min(urb->setup.wLength, max_packet_size);
|
||||
reg = CSR0H_TxPktRdy;
|
||||
usb_write_ep0(usb_id, urb->buffer, data_len);
|
||||
urb->setup.wLength -= data_len;
|
||||
urb->buffer += data_len;
|
||||
} else {
|
||||
reg = CSR0H_StatusPkt | CSR0H_TxPktRdy;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
#if USB_HOST_ASYNC
|
||||
//config ep0 callback fun
|
||||
usb_h_set_ep_isr(host_dev, 0, ep0_h_isr, host_dev);
|
||||
usb_set_intr_txe(usb_id, 0);
|
||||
#endif
|
||||
|
||||
#ifdef USB_HW_20
|
||||
usb_write_csr0(usb_id, reg | CSR0H_DISPING);
|
||||
#else
|
||||
usb_write_csr0(usb_id, reg);
|
||||
#endif
|
||||
|
||||
u32 st = 0;
|
||||
u32 ot = usb_get_jiffies() + 500;
|
||||
while (1) {
|
||||
if (usb_host_timeout(ot)) {
|
||||
log_error("time out %x\n", reg);
|
||||
ret = -DEV_ERR_TIMEOUT;
|
||||
goto __exit;
|
||||
}
|
||||
if (usb_h_dev_status(usb_id)) {
|
||||
st ++;
|
||||
} else {
|
||||
st = 0;
|
||||
}
|
||||
if (((usb_read_devctl(usb_id) & BIT(2)) == 0) || (st > 1000)) {
|
||||
log_error("usb%d_offline\n", usb_id);
|
||||
ret = -DEV_ERR_OFFLINE;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
#if USB_HOST_ASYNC
|
||||
ret = usb_sem_pend(host_dev, 250); //wait isr
|
||||
if (ret) {
|
||||
log_error("usb%d_offline\n", usb_id);
|
||||
ret = -DEV_ERR_OFFLINE;
|
||||
goto __exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
reg = usb_read_csr0(usb_id);
|
||||
if (reg & CSR0H_RxStall) {
|
||||
log_error(" rxStall CSR0:0x%x", reg);
|
||||
ret = -DEV_ERR_CONTROL_STALL;
|
||||
goto __exit;
|
||||
}
|
||||
if (reg & CSR0H_Error) {
|
||||
log_error(" Error CSR0:0x%x", reg);
|
||||
usb_write_csr0(usb_id, 0);
|
||||
ret = -DEV_ERR_CONTROL;
|
||||
goto __exit;
|
||||
}
|
||||
if (USB_PID_IN == urb->stage) {
|
||||
|
||||
if (reg & CSR0H_RxPktRdy) {
|
||||
data_len = usb_read_count0(usb_id);
|
||||
data_len = min(data_len, urb->setup.wLength);
|
||||
usb_read_ep0(usb_id, urb->buffer, data_len);;
|
||||
urb->buffer += data_len;
|
||||
urb->setup.wLength -= data_len;
|
||||
if (data_len < max_packet_size) {
|
||||
urb->setup.wLength = 0;
|
||||
}
|
||||
if (urb->setup.wLength) {
|
||||
#ifdef USB_HW_20
|
||||
usb_write_csr0(usb_id, CSR0H_ReqPkt | CSR0H_DISPING);
|
||||
#else
|
||||
usb_write_csr0(usb_id, CSR0H_ReqPkt);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef USB_HW_20
|
||||
usb_write_csr0(usb_id, CSR0H_DISPING);
|
||||
#else
|
||||
usb_write_csr0(usb_id, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(reg & CSR0H_TxPktRdy)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
__exit:
|
||||
usb_clr_intr_txe(usb_id, 0);
|
||||
usb_dis_ep0_txdly(usb_id);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief usb_control_transfers
|
||||
*
|
||||
* @param struct host_dev
|
||||
* @param urb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static int usb_control_transfers(struct usb_host_device *host_dev, struct ctlXfer *urb)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
int res;
|
||||
/*SETUP*/
|
||||
|
||||
urb->stage = USB_PID_SETUP; //SETUP transaction
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/*IN or OUT*/
|
||||
urb->stage = USB_PID_IN;
|
||||
|
||||
|
||||
while (urb->setup.wLength) {
|
||||
if (urb->setup.bRequestType & USB_DIR_IN) { //Request Direction
|
||||
urb->stage = USB_PID_IN; //IN transaction
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
urb->stage = USB_PID_OUT;
|
||||
} else {
|
||||
urb->stage = USB_PID_OUT; //OUT transaction
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
urb->stage = USB_PID_IN;
|
||||
}
|
||||
}
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_control_msg
|
||||
*
|
||||
* @param host_dev
|
||||
* @param request
|
||||
* @param requesttype
|
||||
* @param value
|
||||
* @param index
|
||||
* @param data
|
||||
* @param size
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int usb_control_msg(struct usb_host_device *host_dev,
|
||||
u8 request, u8 requesttype,
|
||||
u16 value, u16 index,
|
||||
void *data, u16 size)
|
||||
{
|
||||
struct ctlXfer urb;
|
||||
urb.setup.bRequestType = requesttype;
|
||||
urb.setup.bRequest = request;
|
||||
urb.setup.wValue = cpu_to_le16(value);
|
||||
urb.setup.wIndex = cpu_to_le16(index);
|
||||
urb.setup.wLength = cpu_to_le16(size);
|
||||
urb.buffer = data;
|
||||
|
||||
return usb_control_transfers(host_dev, &urb);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_clear_feature
|
||||
*
|
||||
* @param host_dev
|
||||
* @param ep
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int usb_clear_feature(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, ep, NULL, 0);
|
||||
}
|
||||
|
||||
int set_address(struct usb_host_device *host_dev, u8 devnum)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_ADDRESS, 0, devnum, 0, NULL, 0);
|
||||
}
|
||||
|
||||
int usb_get_device_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_DEVICE << 8),
|
||||
0,
|
||||
desc,
|
||||
USB_DT_DEVICE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
int usb_get_string_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc)
|
||||
{
|
||||
int ret = DEV_ERR_NONE;
|
||||
#if 0
|
||||
struct usb_private_data *private_data = host_dev->private_data ;
|
||||
/**********get string language*********/
|
||||
u8 buf[16];
|
||||
memset(buf, 0x0, sizeof(buf));
|
||||
ret = usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_STRING << 8),
|
||||
0,
|
||||
desc,
|
||||
sizeof(buf)
|
||||
);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(&private_data->language, buf + 2, sizeof(private_data->language));
|
||||
|
||||
/**********get manufacturer string**********/
|
||||
memset(private_data->manufacturer, 0x0, sizeof(private_data->manufacturer));
|
||||
if (desc->iManufacturer) {
|
||||
ret = usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_STRING << 8) | desc->iManufacturer,
|
||||
0,
|
||||
private_data->manufacturer,
|
||||
sizeof(private_data->manufacturer)
|
||||
);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/**********get product string**********/
|
||||
memset(private_data->product, 0x0, sizeof(private_data->product));
|
||||
if (desc->iProduct) {
|
||||
ret = usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_STRING << 8) | desc->iProduct,
|
||||
0,
|
||||
private_data->product,
|
||||
sizeof(private_data->product)
|
||||
);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int set_configuration(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0);
|
||||
}
|
||||
int set_configuration_add_value(struct usb_host_device *host_dev, u16 value)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, value, 0, NULL, 0);
|
||||
}
|
||||
int get_config_descriptor(struct usb_host_device *host_dev, void *cfg_desc, u32 len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_CONFIG << 8),
|
||||
0,
|
||||
cfg_desc,
|
||||
len);
|
||||
}
|
||||
|
||||
int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_CONFIG << 8) | value_l,
|
||||
0,
|
||||
cfg_desc,
|
||||
len);
|
||||
}
|
||||
|
||||
|
||||
int get_msd_max_lun(struct usb_host_device *host_dev, void *lun)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_MSD_MAX_LUN,
|
||||
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0,
|
||||
0,
|
||||
lun,
|
||||
1);
|
||||
}
|
||||
int set_msd_reset(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0xff,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
int hid_set_idle(struct usb_host_device *host_dev, u32 id)
|
||||
{
|
||||
return usb_control_msg(host_dev, 0x0a, 0x21, 0, id << 8, NULL, 0);
|
||||
}
|
||||
int hid_get_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u16 report_len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN | USB_RECIP_INTERFACE,
|
||||
0x2200,
|
||||
report_id,
|
||||
report,
|
||||
report_len);
|
||||
}
|
||||
int hid_set_output_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u8 report_len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0x09,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0x0201,
|
||||
report_id,
|
||||
report,
|
||||
report_len);
|
||||
}
|
||||
int usb_set_remote_wakeup(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0);
|
||||
}
|
||||
int get_device_status(struct usb_host_device *host_dev)
|
||||
{
|
||||
u16 status;
|
||||
return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN, 0, 0, (u8 *)&status, 2);
|
||||
}
|
||||
int usb_get_device_qualifier(struct usb_host_device *host_dev, u8 *buffer)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_DEVICE_QUALIFIER << 8),
|
||||
0,
|
||||
buffer,
|
||||
0x0a);
|
||||
|
||||
}
|
||||
#define AOA_CMD51 0x33
|
||||
#define AOA_CMD52 0x34
|
||||
#define AOA_CMD53 0x35
|
||||
|
||||
|
||||
|
||||
|
||||
int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
AOA_CMD51,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0,
|
||||
0,
|
||||
version,
|
||||
2);
|
||||
}
|
||||
int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
AOA_CMD52,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0,
|
||||
index,
|
||||
(u8 *)string,
|
||||
strlen(string));
|
||||
}
|
||||
int usb_switch2aoa(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
AOA_CMD53,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
int usb_switch2slave(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0x51,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
/* Control request for registering a HID device.
|
||||
* Upon registering, a unique ID is sent by the accessory in the
|
||||
* value parameter. This ID will be used for future commands for
|
||||
* the device
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_REGISTER_HID_DEVICE
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: total length of the HID report descriptor
|
||||
* data none
|
||||
*/
|
||||
#define ACCESSORY_REGISTER_HID 54
|
||||
int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_REGISTER_HID,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
index,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
/* Control request for unregistering a HID device.
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_REGISTER_HID
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: 0
|
||||
* data none
|
||||
*/
|
||||
#define ACCESSORY_UNREGISTER_HID 55
|
||||
int usb_aoa_unregister_hid(struct usb_host_device *host_dev, u16 value)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_UNREGISTER_HID,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Control request for sending the HID report descriptor.
|
||||
* If the HID descriptor is longer than the endpoint zero max packet size,
|
||||
* the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
|
||||
* commands. The data for the descriptor must be sent sequentially
|
||||
* if multiple packets are needed.
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_SET_HID_REPORT_DESC
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: offset of data in descriptor
|
||||
* (needed when HID descriptor is too big for one packet)
|
||||
* data the HID report descriptor
|
||||
*/
|
||||
#define ACCESSORY_SET_HID_REPORT_DESC 56
|
||||
int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_SET_HID_REPORT_DESC,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
offset,
|
||||
(u8 *)pbuf,
|
||||
len);
|
||||
}
|
||||
|
||||
/* Control request for sending HID events.
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_SEND_HID_EVENT
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: 0
|
||||
* data the HID report for the event
|
||||
*/
|
||||
#define ACCESSORY_SEND_HID_EVENT 57
|
||||
int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_SEND_HID_EVENT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
0,
|
||||
(u8 *)pbuf,
|
||||
len);
|
||||
}
|
||||
int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0x01,
|
||||
USB_DIR_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
||||
0x0000,
|
||||
4,
|
||||
buffer,
|
||||
0x28);
|
||||
}
|
||||
|
||||
|
||||
int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting)
|
||||
{
|
||||
log_info("%s Set Interface:%d AlternateSetting:%d", __func__, interface, alternateSetting);
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_SET_INTERFACE,
|
||||
USB_RECIP_INTERFACE,
|
||||
alternateSetting,
|
||||
interface,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
}
|
||||
|
||||
int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate)
|
||||
{
|
||||
log_info("%s ep:%d sampe_rate:%d", __func__, ep, sampe_rate);
|
||||
return usb_control_msg(host_dev,
|
||||
1,
|
||||
USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
|
||||
0x0100,
|
||||
ep,
|
||||
&sampe_rate,
|
||||
3);
|
||||
}
|
||||
int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume)
|
||||
{
|
||||
log_info("%s featureID:%d vol:%x", __func__, feature_id, volume);
|
||||
return usb_control_msg(host_dev,
|
||||
1,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
(0x02 << 8) | channel_num,
|
||||
feature_id << 8,
|
||||
&volume,
|
||||
2);
|
||||
}
|
||||
int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute)
|
||||
{
|
||||
log_info("%s featureID:%d mute:%d", __func__, feature_id, mute);
|
||||
return usb_control_msg(host_dev,
|
||||
1,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0x0100,
|
||||
feature_id << 8,
|
||||
&mute,
|
||||
1);
|
||||
}
|
||||
#endif
|
||||
@ -1,384 +0,0 @@
|
||||
/**@file usb_ctrl_transfer.h
|
||||
* @brief usb_ctrl_transfer控制传输头文件
|
||||
* @details 功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_CTRL_TRANSFER_H__
|
||||
#define __USB_CTRL_TRANSFER_H__
|
||||
|
||||
#include "usb/ch9.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "device/device.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
|
||||
/*
|
||||
* USB Packet IDs (PIDs)
|
||||
*/
|
||||
#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
||||
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
||||
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
||||
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
||||
|
||||
|
||||
|
||||
struct ctlXfer {
|
||||
struct usb_ctrlrequest setup; ///<控制请求
|
||||
void *buffer; ///<控制请求的data
|
||||
u8 stage; ///<当前状态
|
||||
};
|
||||
|
||||
int usb_control_msg(struct usb_host_device *host_dev,
|
||||
u8 request, u8 requesttype,
|
||||
u16 value, u16 index,
|
||||
void *data, u16 size);
|
||||
|
||||
/**@brief USB清除或禁用特定的特性
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] ep 端点号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_clear_feature(host_dev , ep);
|
||||
* @encode
|
||||
*/
|
||||
int usb_clear_feature(struct usb_host_device *usb_dev, u32 ep);
|
||||
|
||||
/**@brief USB设置地址
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] devnum 设备编号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_address(host_dev , ep);
|
||||
* @encode
|
||||
*/
|
||||
int set_address(struct usb_host_device *usb_dev, u8 devnum);
|
||||
|
||||
/**@brief USB获取设备描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] usb_device_descriptor定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_device_descriptor(host_dev , device_desc);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_device_descriptor(struct usb_host_device *usb_dev, struct usb_device_descriptor *desc);
|
||||
|
||||
/**@brief USB获取字符串描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] usb_device_descriptor定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_string_descriptor(host_dev , device_desc);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_string_descriptor(struct usb_host_device *usb_dev, struct usb_device_descriptor *desc);
|
||||
|
||||
/**@brief USB设置相关配置
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_configuration(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int set_configuration(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief USB设置相关配置,添加相关参数
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 当前请求的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_configuration_add_value(host_dev , value);
|
||||
* @encode
|
||||
*/
|
||||
int set_configuration_add_value(struct usb_host_device *host_dev, u16 value);
|
||||
|
||||
/**@brief USB获取配置描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] cfg_desc 自定义的配置描述符指针
|
||||
* @param[in] len 长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_config_descriptor(host_dev , cfg_desc , len);
|
||||
* @encode
|
||||
*/
|
||||
int get_config_descriptor(struct usb_host_device *usb_dev, void *cfg_desc, u32 len);
|
||||
|
||||
/**@brief USB获取配置描述符,添加相关参数
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] cfg_desc 自定义的配置描述符指针
|
||||
* @param[in] len 长度
|
||||
* @param[in] value_l 请求的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_config_descriptor_add_value_l(host_dev , cfg_desc , len , value_l);
|
||||
* @encode
|
||||
*/
|
||||
int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l);
|
||||
|
||||
/**@brief USB获取大容量存储设备的最大逻辑单元号
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] lun 逻辑单元号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_msd_max_lun(host_dev , lun);
|
||||
* @encode
|
||||
*/
|
||||
int get_msd_max_lun(struct usb_host_device *usb_dev, void *lun);
|
||||
|
||||
/**@brief USB设置大容量存储设备复位
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_msd_reset(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int set_msd_reset(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief hid设置为空闲模式
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] id 指定接口或端点号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_set_idle(host_dev , id);
|
||||
* @encode
|
||||
*/
|
||||
int hid_set_idle(struct usb_host_device *usb_dev, u32 id);
|
||||
|
||||
/**@brief hid获取报告描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] report 自定义报告指针,指向报告内容
|
||||
* @param[in] report_id 报告描述符id号
|
||||
* @param[in] report_len 报告描述符长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_get_report(host_dev , report , report_id , report_len);
|
||||
* @encode
|
||||
*/
|
||||
int hid_get_report(struct usb_host_device *usb_dev, u8 *report, u8 report_id, u16 report_len);
|
||||
|
||||
/**@brief hid设置输出报告描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] report 自定义报告指针,指向报告内容
|
||||
* @param[in] report_id
|
||||
* @param[in] report_len
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_set_output_report(host_dev , report , report_id , report_len);
|
||||
* @encode
|
||||
*/
|
||||
int hid_set_output_report(struct usb_host_device *usb_dev, u8 *report, u8 report_id, u8 report_len);
|
||||
|
||||
/**@brief USB设置远程唤醒
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_set_remote_wakeup(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int usb_set_remote_wakeup(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief USB获取设备状态
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_device_status(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int get_device_status(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief USB获取设备限定描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] BUFFER 自定义的指针,指向限定描述符内容
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_device_qualifier(host_dev , buffer);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_device_qualifier(struct usb_host_device *usb_dev, u8 *buffer);
|
||||
|
||||
/**@brief USB获取安卓aoa协议版本
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] version 自定义的指针,指向版本内容
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_aoa_version(host_dev , version);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version);
|
||||
|
||||
/**@brief USB设置证书信息
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] string 字符串指针,指向证书内容
|
||||
* @param[in] index 传递的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_set_credentials(host_dev , string , index);
|
||||
* @encode
|
||||
*/
|
||||
int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index);
|
||||
|
||||
/**@brief USB设置aoa开关
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_switch2aoa(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int usb_switch2aoa(struct usb_host_device *host_dev);
|
||||
|
||||
/**@brief USB设置从机模式开关
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_switch2slave(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int usb_switch2slave(struct usb_host_device *host_dev);
|
||||
|
||||
/**@brief USB hid设备注册
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 请求的参数
|
||||
* @param[in] index 传递的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_aoa_register_hid(host_dev , value , index);
|
||||
* @encode
|
||||
*/
|
||||
int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index);
|
||||
|
||||
/**@brief USB设置hid报告描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 请求的参数
|
||||
* @param[in] offset 偏移量参数
|
||||
* @param[in] pbuf 存放数据的BUFFER指针
|
||||
* @param[in] len 长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_aoa_set_hid_report_desc(host_dev , value , offset , *pbuf , len);
|
||||
* @encode
|
||||
*/
|
||||
int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len);
|
||||
|
||||
/**@brief USB发送hid事件
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 请求的参数
|
||||
* @param[in] pbuf 存放数据的BUFFER指针
|
||||
* @param[in] len 长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_aoa_send_hid_event(host_dev , value , *pbuf , len);
|
||||
* @encode
|
||||
*/
|
||||
int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len);
|
||||
|
||||
/**@brief 获取扩展的大容量存储设备(可兼容)id 号
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] BUFFER 存放数据的BUFFER
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_ms_extended_compat_id(host_dev , value , *pbuf , len);
|
||||
* @encode
|
||||
*/
|
||||
int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer);
|
||||
|
||||
/**@brief USB设置接口
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] interface 接口参数(请求的参数)
|
||||
* @param[in] alternateSetting 交替设置(传递的参数)
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_set_interface(host_dev , interface , alternateSetting);
|
||||
* @encode
|
||||
*/
|
||||
int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting);
|
||||
|
||||
/**@brief USB音频采样频率控制
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] ep 端点号
|
||||
* @param[in] samp_rate 采样率
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_audio_sampling_frequency_control(host_dev , ep , sampe_rate);
|
||||
* @encode
|
||||
*/
|
||||
int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate);
|
||||
|
||||
/**@brief USB音频音量控制
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] feature_id 特征值id号(端点或接口的id)(传递的参数)
|
||||
* @param[in] channel_num 通道编号(请求的参数)
|
||||
* @paeam[in] volume 音量
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_audio_volume_control(host_dev , feature_id , channel_num , volume);
|
||||
* @encode
|
||||
*/
|
||||
int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume);
|
||||
|
||||
/**@brief USB音频静音控制
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] feature_id 特征值id号(端点或接口的id)(传递的参数)
|
||||
* @param[in] mute 静音信号(静音标志)
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_audio_mute_control(host_dev , feature_id , channel_num , volume);
|
||||
* @encode
|
||||
*/
|
||||
int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute);
|
||||
|
||||
#endif
|
||||
@ -1,353 +0,0 @@
|
||||
/**
|
||||
* USB HID Keyboard scan codes as per USB spec 1.11
|
||||
* plus some additional codes
|
||||
*
|
||||
* Created by MightyPork, 2016
|
||||
* Public domain
|
||||
*
|
||||
* Adapted from:
|
||||
* https://source.android.com/devices/input/keyboard-devices.html
|
||||
*/
|
||||
|
||||
#ifndef USB_HID_KEYS
|
||||
#define USB_HID_KEYS
|
||||
|
||||
struct keyboard_data_t {
|
||||
u8 fun_key;
|
||||
u8 res;
|
||||
u8 Keypad[6];
|
||||
} _GNU_PACKED_ ;
|
||||
|
||||
struct mouse_data_t {
|
||||
u8 btn;
|
||||
s16 x;
|
||||
s16 y;
|
||||
s8 wheel;
|
||||
s8 ac_pan;
|
||||
} _GNU_PACKED_ ;
|
||||
struct point_t {
|
||||
u8 tip_switch: 2;
|
||||
/* u8 in_range: 1; */
|
||||
u8 res: 2;
|
||||
u8 cid: 4;
|
||||
s16 x;
|
||||
s16 y;
|
||||
} _GNU_PACKED_ ;
|
||||
|
||||
struct touch_screen_t {
|
||||
struct point_t p[3];
|
||||
} _GNU_PACKED_;
|
||||
|
||||
struct mouse_point_t {
|
||||
u8 btn;
|
||||
s8 x;
|
||||
s8 y;
|
||||
s8 wheel;
|
||||
} _GNU_PACKED_;
|
||||
/**
|
||||
* Modifier masks - used for the first byte in the HID report.
|
||||
* NOTE: The second byte in the report is reserved, 0x00
|
||||
*/
|
||||
#define _KEY_MOD_LCTRL 0x01
|
||||
#define _KEY_MOD_LSHIFT 0x02
|
||||
#define _KEY_MOD_LALT 0x04
|
||||
#define _KEY_MOD_LMETA 0x08
|
||||
#define _KEY_MOD_RCTRL 0x10
|
||||
#define _KEY_MOD_RSHIFT 0x20
|
||||
#define _KEY_MOD_RALT 0x40
|
||||
#define _KEY_MOD_RMETA 0x80
|
||||
|
||||
/**
|
||||
* Scan codes - last N slots in the HID report (usually 6).
|
||||
* 0x00 if no key pressed.
|
||||
*
|
||||
* If more than N keys are pressed, the HID reports
|
||||
* KEY_ERR_OVF in all slots to indicate this condition.
|
||||
*/
|
||||
|
||||
#define _KEY_NONE 0x00 // No key pressed
|
||||
#define _KEY_ERR_OVF 0x01 // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key")
|
||||
// 0x02 // Keyboard POST Fail
|
||||
// 0x03 // Keyboard Error Undefined
|
||||
#define _KEY_A 0x04 // Keyboard a and A
|
||||
#define _KEY_B 0x05 // Keyboard b and B
|
||||
#define _KEY_C 0x06 // Keyboard c and C
|
||||
#define _KEY_D 0x07 // Keyboard d and D
|
||||
#define _KEY_E 0x08 // Keyboard e and E
|
||||
#define _KEY_F 0x09 // Keyboard f and F
|
||||
#define _KEY_G 0x0a // Keyboard g and G
|
||||
#define _KEY_H 0x0b // Keyboard h and H
|
||||
#define _KEY_I 0x0c // Keyboard i and I
|
||||
#define _KEY_J 0x0d // Keyboard j and J
|
||||
#define _KEY_K 0x0e // Keyboard k and K
|
||||
#define _KEY_L 0x0f // Keyboard l and L
|
||||
#define _KEY_M 0x10 // Keyboard m and M
|
||||
#define _KEY_N 0x11 // Keyboard n and N
|
||||
#define _KEY_O 0x12 // Keyboard o and O
|
||||
#define _KEY_P 0x13 // Keyboard p and P
|
||||
#define _KEY_Q 0x14 // Keyboard q and Q
|
||||
#define _KEY_R 0x15 // Keyboard r and R
|
||||
#define _KEY_S 0x16 // Keyboard s and S
|
||||
#define _KEY_T 0x17 // Keyboard t and T
|
||||
#define _KEY_U 0x18 // Keyboard u and U
|
||||
#define _KEY_V 0x19 // Keyboard v and V
|
||||
#define _KEY_W 0x1a // Keyboard w and W
|
||||
#define _KEY_X 0x1b // Keyboard x and X
|
||||
#define _KEY_Y 0x1c // Keyboard y and Y
|
||||
#define _KEY_Z 0x1d // Keyboard z and Z
|
||||
|
||||
#define _KEY_1 0x1e // Keyboard 1 and !
|
||||
#define _KEY_2 0x1f // Keyboard 2 and @
|
||||
#define _KEY_3 0x20 // Keyboard 3 and #
|
||||
#define _KEY_4 0x21 // Keyboard 4 and $
|
||||
#define _KEY_5 0x22 // Keyboard 5 and %
|
||||
#define _KEY_6 0x23 // Keyboard 6 and ^
|
||||
#define _KEY_7 0x24 // Keyboard 7 and &
|
||||
#define _KEY_8 0x25 // Keyboard 8 and *
|
||||
#define _KEY_9 0x26 // Keyboard 9 and (
|
||||
#define _KEY_0 0x27 // Keyboard 0 and )
|
||||
|
||||
#define _KEY_ENTER 0x28 // Keyboard Return (ENTER)
|
||||
#define _KEY_ESC 0x29 // Keyboard ESCAPE
|
||||
#define _KEY_BACKSPACE 0x2a // Keyboard DELETE (Backspace)
|
||||
#define _KEY_TAB 0x2b // Keyboard Tab
|
||||
#define _KEY_SPACE 0x2c // Keyboard Spacebar
|
||||
#define _KEY_MINUS 0x2d // Keyboard - and _
|
||||
#define _KEY_EQUAL 0x2e // Keyboard = and +
|
||||
#define _KEY_LEFTBRACE 0x2f // Keyboard [ and {
|
||||
#define _KEY_RIGHTBRACE 0x30 // Keyboard ] and }
|
||||
#define _KEY_BACKSLASH 0x31 // Keyboard \ and |
|
||||
#define _KEY_HASHTILDE 0x32 // Keyboard Non-US # and ~
|
||||
#define _KEY_SEMICOLON 0x33 // Keyboard ; and :
|
||||
#define _KEY_APOSTROPHE 0x34 // Keyboard ' and "
|
||||
#define _KEY_GRAVE 0x35 // Keyboard ` and ~
|
||||
#define _KEY_COMMA 0x36 // Keyboard , and <
|
||||
#define _KEY_DOT 0x37 // Keyboard . and >
|
||||
#define _KEY_SLASH 0x38 // Keyboard / and ?
|
||||
#define _KEY_CAPSLOCK 0x39 // Keyboard Caps Lock
|
||||
|
||||
#define _KEY_F1 0x3a // Keyboard F1
|
||||
#define _KEY_F2 0x3b // Keyboard F2
|
||||
#define _KEY_F3 0x3c // Keyboard F3
|
||||
#define _KEY_F4 0x3d // Keyboard F4
|
||||
#define _KEY_F5 0x3e // Keyboard F5
|
||||
#define _KEY_F6 0x3f // Keyboard F6
|
||||
#define _KEY_F7 0x40 // Keyboard F7
|
||||
#define _KEY_F8 0x41 // Keyboard F8
|
||||
#define _KEY_F9 0x42 // Keyboard F9
|
||||
#define _KEY_F10 0x43 // Keyboard F10
|
||||
#define _KEY_F11 0x44 // Keyboard F11
|
||||
#define _KEY_F12 0x45 // Keyboard F12
|
||||
|
||||
#define _KEY_SYSRQ 0x46 // Keyboard Print Screen
|
||||
#define _KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock
|
||||
#define _KEY_PAUSE 0x48 // Keyboard Pause
|
||||
#define _KEY_INSERT 0x49 // Keyboard Insert
|
||||
#define _KEY_HOME 0x4a // Keyboard Home
|
||||
#define _KEY_PAGEUP 0x4b // Keyboard Page Up
|
||||
#define _KEY_DELETE 0x4c // Keyboard Delete Forward
|
||||
#define _KEY_END 0x4d // Keyboard End
|
||||
#define _KEY_PAGEDOWN 0x4e // Keyboard Page Down
|
||||
#define _KEY_RIGHT 0x4f // Keyboard Right Arrow
|
||||
#define _KEY_LEFT 0x50 // Keyboard Left Arrow
|
||||
#define _KEY_DOWN 0x51 // Keyboard Down Arrow
|
||||
#define _KEY_UP 0x52 // Keyboard Up Arrow
|
||||
|
||||
#define _KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear
|
||||
#define _KEY_KPSLASH 0x54 // Keypad /
|
||||
#define _KEY_KPASTERISK 0x55 // Keypad *
|
||||
#define _KEY_KPMINUS 0x56 // Keypad -
|
||||
#define _KEY_KPPLUS 0x57 // Keypad +
|
||||
#define _KEY_KPENTER 0x58 // Keypad ENTER
|
||||
#define _KEY_KP1 0x59 // Keypad 1 and End
|
||||
#define _KEY_KP2 0x5a // Keypad 2 and Down Arrow
|
||||
#define _KEY_KP3 0x5b // Keypad 3 and PageDn
|
||||
#define _KEY_KP4 0x5c // Keypad 4 and Left Arrow
|
||||
#define _KEY_KP5 0x5d // Keypad 5
|
||||
#define _KEY_KP6 0x5e // Keypad 6 and Right Arrow
|
||||
#define _KEY_KP7 0x5f // Keypad 7 and Home
|
||||
#define _KEY_KP8 0x60 // Keypad 8 and Up Arrow
|
||||
#define _KEY_KP9 0x61 // Keypad 9 and Page Up
|
||||
#define _KEY_KP0 0x62 // Keypad 0 and Insert
|
||||
#define _KEY_KPDOT 0x63 // Keypad . and Delete
|
||||
|
||||
#define _KEY_102ND 0x64 // Keyboard Non-US \ and |
|
||||
#define _KEY_COMPOSE 0x65 // Keyboard Application
|
||||
#define _KEY_POWER 0x66 // Keyboard Power
|
||||
#define _KEY_KPEQUAL 0x67 // Keypad =
|
||||
|
||||
#define _KEY_F13 0x68 // Keyboard F13
|
||||
#define _KEY_F14 0x69 // Keyboard F14
|
||||
#define _KEY_F15 0x6a // Keyboard F15
|
||||
#define _KEY_F16 0x6b // Keyboard F16
|
||||
#define _KEY_F17 0x6c // Keyboard F17
|
||||
#define _KEY_F18 0x6d // Keyboard F18
|
||||
#define _KEY_F19 0x6e // Keyboard F19
|
||||
#define _KEY_F20 0x6f // Keyboard F20
|
||||
#define _KEY_F21 0x70 // Keyboard F21
|
||||
#define _KEY_F22 0x71 // Keyboard F22
|
||||
#define _KEY_F23 0x72 // Keyboard F23
|
||||
#define _KEY_F24 0x73 // Keyboard F24
|
||||
|
||||
#define _KEY_OPEN 0x74 // Keyboard Execute
|
||||
#define _KEY_HELP 0x75 // Keyboard Help
|
||||
#define _KEY_PROPS 0x76 // Keyboard Menu
|
||||
#define _KEY_FRONT 0x77 // Keyboard Select
|
||||
#define _KEY_STOP 0x78 // Keyboard Stop
|
||||
#define _KEY_AGAIN 0x79 // Keyboard Again
|
||||
#define _KEY_UNDO 0x7a // Keyboard Undo
|
||||
#define _KEY_CUT 0x7b // Keyboard Cut
|
||||
#define _KEY_COPY 0x7c // Keyboard Copy
|
||||
#define _KEY_PASTE 0x7d // Keyboard Paste
|
||||
#define _KEY_FIND 0x7e // Keyboard Find
|
||||
#define _KEY_MUTE 0x7f // Keyboard Mute
|
||||
#define _KEY_VOLUMEUP 0x80 // Keyboard Volume Up
|
||||
#define _KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down
|
||||
// 0x82 Keyboard Locking Caps Lock
|
||||
// 0x83 Keyboard Locking Num Lock
|
||||
// 0x84 Keyboard Locking Scroll Lock
|
||||
#define _KEY_KPCOMMA 0x85 // Keypad Comma
|
||||
// 0x86 Keypad Equal Sign
|
||||
#define _KEY_RO 0x87 // Keyboard International1
|
||||
#define _KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2
|
||||
#define _KEY_YEN 0x89 // Keyboard International3
|
||||
#define _KEY_HENKAN 0x8a // Keyboard International4
|
||||
#define _KEY_MUHENKAN 0x8b // Keyboard International5
|
||||
#define _KEY_KPJPCOMMA 0x8c // Keyboard International6
|
||||
// 0x8d Keyboard International7
|
||||
// 0x8e Keyboard International8
|
||||
// 0x8f Keyboard International9
|
||||
#define _KEY_HANGEUL 0x90 // Keyboard LANG1
|
||||
#define _KEY_HANJA 0x91 // Keyboard LANG2
|
||||
#define _KEY_KATAKANA 0x92 // Keyboard LANG3
|
||||
#define _KEY_HIRAGANA 0x93 // Keyboard LANG4
|
||||
#define _KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5
|
||||
// 0x95 Keyboard LANG6
|
||||
// 0x96 Keyboard LANG7
|
||||
// 0x97 Keyboard LANG8
|
||||
// 0x98 Keyboard LANG9
|
||||
// 0x99 Keyboard Alternate Erase
|
||||
// 0x9a Keyboard SysReq/Attention
|
||||
// 0x9b Keyboard Cancel
|
||||
// 0x9c Keyboard Clear
|
||||
// 0x9d Keyboard Prior
|
||||
// 0x9e Keyboard Return
|
||||
// 0x9f Keyboard Separator
|
||||
// 0xa0 Keyboard Out
|
||||
// 0xa1 Keyboard Oper
|
||||
// 0xa2 Keyboard Clear/Again
|
||||
// 0xa3 Keyboard CrSel/Props
|
||||
// 0xa4 Keyboard ExSel
|
||||
|
||||
// 0xb0 Keypad 00
|
||||
// 0xb1 Keypad 000
|
||||
// 0xb2 Thousands Separator
|
||||
// 0xb3 Decimal Separator
|
||||
// 0xb4 Currency Unit
|
||||
// 0xb5 Currency Sub-unit
|
||||
#define _KEY_KPLEFTPAREN 0xb6 // Keypad (
|
||||
#define _KEY_KPRIGHTPAREN 0xb7 // Keypad )
|
||||
// 0xb8 Keypad {
|
||||
// 0xb9 Keypad }
|
||||
// 0xba Keypad Tab
|
||||
// 0xbb Keypad Backspace
|
||||
// 0xbc Keypad A
|
||||
// 0xbd Keypad B
|
||||
// 0xbe Keypad C
|
||||
// 0xbf Keypad D
|
||||
// 0xc0 Keypad E
|
||||
// 0xc1 Keypad F
|
||||
// 0xc2 Keypad XOR
|
||||
// 0xc3 Keypad ^
|
||||
// 0xc4 Keypad %
|
||||
// 0xc5 Keypad <
|
||||
// 0xc6 Keypad >
|
||||
// 0xc7 Keypad &
|
||||
// 0xc8 Keypad &&
|
||||
// 0xc9 Keypad |
|
||||
// 0xca Keypad ||
|
||||
// 0xcb Keypad :
|
||||
// 0xcc Keypad #
|
||||
// 0xcd Keypad Space
|
||||
// 0xce Keypad @
|
||||
// 0xcf Keypad !
|
||||
// 0xd0 Keypad Memory Store
|
||||
// 0xd1 Keypad Memory Recall
|
||||
// 0xd2 Keypad Memory Clear
|
||||
// 0xd3 Keypad Memory Add
|
||||
// 0xd4 Keypad Memory Subtract
|
||||
// 0xd5 Keypad Memory Multiply
|
||||
// 0xd6 Keypad Memory Divide
|
||||
// 0xd7 Keypad +/-
|
||||
// 0xd8 Keypad Clear
|
||||
// 0xd9 Keypad Clear Entry
|
||||
// 0xda Keypad Binary
|
||||
// 0xdb Keypad Octal
|
||||
// 0xdc Keypad Decimal
|
||||
// 0xdd Keypad Hexadecimal
|
||||
|
||||
#define _KEY_LEFTCTRL 0xe0 // Keyboard Left Control
|
||||
#define _KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift
|
||||
#define _KEY_LEFTALT 0xe2 // Keyboard Left Alt
|
||||
#define _KEY_LEFTMETA 0xe3 // Keyboard Left GUI
|
||||
#define _KEY_RIGHTCTRL 0xe4 // Keyboard Right Control
|
||||
#define _KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift
|
||||
#define _KEY_RIGHTALT 0xe6 // Keyboard Right Alt
|
||||
#define _KEY_RIGHTMETA 0xe7 // Keyboard Right GUI
|
||||
|
||||
#define _KEY_MEDIA_PLAYPAUSE 0xe8
|
||||
#define _KEY_MEDIA_STOPCD 0xe9
|
||||
#define _KEY_MEDIA_PREVIOUSSONG 0xea
|
||||
#define _KEY_MEDIA_NEXTSONG 0xeb
|
||||
#define _KEY_MEDIA_EJECTCD 0xec
|
||||
#define _KEY_MEDIA_VOLUMEUP 0xed
|
||||
#define _KEY_MEDIA_VOLUMEDOWN 0xee
|
||||
#define _KEY_MEDIA_MUTE 0xef
|
||||
#define _KEY_MEDIA_WWW 0xf0
|
||||
#define _KEY_MEDIA_BACK 0xf1
|
||||
#define _KEY_MEDIA_FORWARD 0xf2
|
||||
#define _KEY_MEDIA_STOP 0xf3
|
||||
#define _KEY_MEDIA_FIND 0xf4
|
||||
#define _KEY_MEDIA_SCROLLUP 0xf5
|
||||
#define _KEY_MEDIA_SCROLLDOWN 0xf6
|
||||
#define _KEY_MEDIA_EDIT 0xf7
|
||||
#define _KEY_MEDIA_SLEEP 0xf8
|
||||
#define _KEY_MEDIA_COFFEE 0xf9
|
||||
#define _KEY_MEDIA_REFRESH 0xfa
|
||||
#define _KEY_MEDIA_CALC 0xfb
|
||||
|
||||
#define _KEY_CUSTOM_CTRL_VOL_UP 0x00e9
|
||||
#define _KEY_CUSTOM_CTRL_VOL_DOWN 0x00ea
|
||||
#define _KEY_CUSTOM_CTRL_MUTE 0x00e2
|
||||
#define _KEY_CUSTOM_CTRL_FORWARD 0x00b5
|
||||
#define _KEY_CUSTOM_CTRL_STOP 0x00cd
|
||||
#define _KEY_CUSTOM_CTRL_BACK 0x00b6
|
||||
#define _KEY_CUSTOM_CTRL_MUSIC 0x0183
|
||||
#define _KEY_CUSTOM_CTRL_CALCULATOR 0x0192
|
||||
#define _KEY_CUSTOM_CTRL_SEARCH 0x0221
|
||||
#define _KEY_CUSTOM_CTRL_EMAIL 0x018A
|
||||
#define _KEY_CUSTOM_CTRL_HOME 0x0223
|
||||
#define _KEY_BRIGHTNESS_INCREASE 0x006F
|
||||
#define _KEY_BRIGHTNESS_REDUCTION 0x0070
|
||||
#define _KEY_ZOOM_IN 0x022D
|
||||
#define _KEY_ZOOM_OUT 0x022E
|
||||
#define _KEY_CUSTOM_COPY 0x021B
|
||||
#define _KEY_CUSTOM_CUT 0x021C
|
||||
#define _KEY_CUSTOM_PASTE 0x021D
|
||||
#define _KEY_CUSTOM_SELECT_ALL 0x021E
|
||||
#define _KEY_CUSTOM_SPLIT_SCREEN 0x0196
|
||||
#define _KEY_CUSTOM_LOCK 0x0030
|
||||
#define _KEY_CUSTOM_ESC 0x0223
|
||||
#define _KEY_CUSTOM_CALENDAR 0x018e
|
||||
#define _KEY_CUSTOM_MESSAGE 0X018d
|
||||
|
||||
#define _KEY_CUSTOM_BROWER 0x0231
|
||||
#define _KEY_CUSTOM_PROCESS 0x023a
|
||||
|
||||
#define _KEY_CUSTOM_SET 0x029b
|
||||
|
||||
#define LED_NUM_LOCK 0x01
|
||||
#define LED_CAPS_LOCK 0x02
|
||||
#define LED_SCROLL_CLOCK 0x04
|
||||
#endif
|
||||
|
||||
@ -1,834 +0,0 @@
|
||||
#include "includes.h"
|
||||
#include "app_config.h"
|
||||
#include "device_drive.h"
|
||||
/* #include "os/os_compat.h" */
|
||||
#if USB_HOST_ENABLE
|
||||
#include "usb_config.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_storage.h"
|
||||
#include "adb.h"
|
||||
#include "aoa.h"
|
||||
#include "hid.h"
|
||||
#include "audio.h"
|
||||
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
#include "apple_dock/iAP.h"
|
||||
#include "apple_mfi.h"
|
||||
#endif
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[mount]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
static struct usb_host_device host_devices[USB_MAX_HW_NUM];// SEC(.usb_h_bss);
|
||||
|
||||
#define device_to_usbdev(device) ((struct usb_host_device *)((device)->private_data))
|
||||
|
||||
|
||||
int host_dev_status(const struct usb_host_device *host_dev)
|
||||
{
|
||||
return ((host_dev)->private_data.status);
|
||||
}
|
||||
|
||||
u32 host_device2id(const struct usb_host_device *host_dev)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
return ((host_dev)->private_data.usb_id);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
const struct usb_host_device *host_id2device(const usb_dev id)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
return &host_devices[id];
|
||||
#else
|
||||
return &host_devices[0];
|
||||
#endif
|
||||
}
|
||||
int usb_sem_init(struct usb_host_device *host_dev)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
usb_host_config(usb_id);
|
||||
|
||||
OS_SEM *sem = zalloc(sizeof(OS_SEM));
|
||||
ASSERT(sem, "usb alloc sem error");
|
||||
host_dev->sem = sem;
|
||||
g_printf("%s %x %x ", __func__, host_dev, sem);
|
||||
os_sem_create(host_dev->sem, 0);
|
||||
return 0;
|
||||
}
|
||||
int usb_sem_pend(struct usb_host_device *host_dev, u32 timeout)
|
||||
{
|
||||
if (host_dev->sem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
int ret = os_sem_pend(host_dev->sem, timeout);
|
||||
if (ret) {
|
||||
r_printf("%s %d ", __func__, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int usb_sem_post(struct usb_host_device *host_dev)
|
||||
{
|
||||
if (host_dev->sem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
int ret = os_sem_post(host_dev->sem);
|
||||
if (ret) {
|
||||
r_printf("%s %d ", __func__, ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int usb_sem_del(struct usb_host_device *host_dev)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
r_printf("1");
|
||||
if (host_dev->sem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
r_printf("2");
|
||||
r_printf("3");
|
||||
#if USB_HUB
|
||||
if (host_dev && host_dev->sem && host_dev->father == NULL) {
|
||||
os_sem_del(host_dev->sem, 0);
|
||||
}
|
||||
#else
|
||||
if (host_dev && host_dev->sem) {
|
||||
os_sem_del(host_dev->sem, 0);
|
||||
}
|
||||
#endif
|
||||
r_printf("4");
|
||||
g_printf("%s %x %x ", __func__, host_dev, host_dev->sem);
|
||||
free(host_dev->sem);
|
||||
r_printf("5");
|
||||
host_dev->sem = NULL;
|
||||
r_printf("6");
|
||||
usb_host_free(usb_id);
|
||||
r_printf("7");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find udisk @ interface %d", interface_num);
|
||||
#if TCFG_UDISK_ENABLE
|
||||
return usb_msd_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find udisk @ interface %d", interface_num);
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
return usb_apple_mfi_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find adb @ interface %d", interface_num);
|
||||
#if TCFG_ADB_ENABLE
|
||||
return usb_adb_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find aoa @ interface %d", interface_num);
|
||||
#if TCFG_AOA_ENABLE
|
||||
return usb_aoa_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
|
||||
}
|
||||
static int _usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find hid @ interface %d", interface_num);
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
return usb_hid_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find audio @ interface %d", interface_num);
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
return usb_audio_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find adbmtp @ interface %d", interface_num);
|
||||
#if TCFG_ADB_ENABLE
|
||||
return usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* @brief usb_descriptor_parser
|
||||
*
|
||||
* @param device
|
||||
* @param pBuf
|
||||
* @param total_len
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static int usb_descriptor_parser(struct usb_host_device *host_dev, const u8 *pBuf, u32 total_len, struct usb_device_descriptor *device_desc)
|
||||
{
|
||||
int len = 0;
|
||||
u8 interface_num = 0;
|
||||
struct usb_private_data *private_data = &host_dev->private_data;
|
||||
|
||||
struct usb_config_descriptor *cfg_desc = (struct usb_config_descriptor *)pBuf;
|
||||
|
||||
if (cfg_desc->bDescriptorType != USB_DT_CONFIG ||
|
||||
cfg_desc->bLength < USB_DT_CONFIG_SIZE) {
|
||||
log_error("invalid descriptor for config bDescriptorType = %d bLength= %d",
|
||||
cfg_desc->bDescriptorType, cfg_desc->bLength);
|
||||
return -USB_DT_CONFIG;
|
||||
}
|
||||
|
||||
log_info("idVendor %x idProduct %x", device_desc->idVendor, device_desc->idProduct);
|
||||
|
||||
len += USB_DT_CONFIG_SIZE;
|
||||
pBuf += USB_DT_CONFIG_SIZE;
|
||||
int i = 0;
|
||||
u32 have_find_valid_class = 0;
|
||||
while (len < total_len) {
|
||||
if (interface_num > MAX_HOST_INTERFACE) {
|
||||
log_error("interface_num too much");
|
||||
break;
|
||||
}
|
||||
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
if (interface->bDescriptorType == USB_DT_INTERFACE) {
|
||||
|
||||
printf("inf class %x subclass %x ep %d",
|
||||
interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bNumEndpoints);
|
||||
|
||||
if (interface->bInterfaceClass == USB_CLASS_MASS_STORAGE) {
|
||||
i = _usb_msd_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((device_desc->idVendor == 0x05AC) &&
|
||||
((device_desc->idProduct & 0xff00) == 0x1200)) {
|
||||
i = _usb_apple_mfi_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if (interface->bInterfaceClass == USB_CLASS_AUDIO) {
|
||||
i = _usb_audio_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((interface->bInterfaceClass == 0xff) &&
|
||||
(interface->bInterfaceSubClass == USB_CLASS_ADB)) {
|
||||
i = _usb_adb_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((device_desc->idVendor == 0x18d1) &&
|
||||
((device_desc->idProduct & 0x2d00) == 0x2d00)) {
|
||||
i = _usb_aoa_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if (interface->bInterfaceClass == USB_CLASS_HID) {
|
||||
i = _usb_hid_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((interface->bNumEndpoints == 3) &&
|
||||
(interface->bInterfaceClass == 0xff || interface->bInterfaceClass == 0x06)) {
|
||||
i = _usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
}
|
||||
have_find_valid_class = true;
|
||||
} else if ((interface->bInterfaceClass == 0xff) &&
|
||||
(interface->bInterfaceSubClass == 0xff)) {
|
||||
i = _usb_aoa_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
}
|
||||
have_find_valid_class = true;
|
||||
|
||||
} else {
|
||||
log_info("find unsupport [class %x subClass %x] @ interface %d",
|
||||
interface->bInterfaceClass,
|
||||
interface->bInterfaceSubClass,
|
||||
interface_num);
|
||||
|
||||
len += USB_DT_INTERFACE_SIZE;
|
||||
pBuf += USB_DT_INTERFACE_SIZE;
|
||||
}
|
||||
} else {
|
||||
/* log_error("unknown section %d %d", len, pBuf[0]); */
|
||||
if (pBuf[0]) {
|
||||
len += pBuf[0];
|
||||
pBuf += pBuf[0];
|
||||
} else {
|
||||
len = total_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log_debug("len %d total_len %d", len, total_len);
|
||||
return !have_find_valid_class;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb_host_suspend
|
||||
*
|
||||
* @param usb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
void usb_host_suspend(const usb_dev usb_id)
|
||||
{
|
||||
usb_h_entry_suspend(usb_id);
|
||||
}
|
||||
|
||||
void usb_host_resume(const usb_dev usb_id)
|
||||
{
|
||||
usb_h_resume(usb_id);
|
||||
}
|
||||
|
||||
static u32 _usb_host_mount(const usb_dev usb_id, u32 retry, u32 reset_delay, u32 mount_timeout)
|
||||
{
|
||||
u32 ret = DEV_ERR_NONE;
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
struct usb_private_data *private_data = &host_dev->private_data;
|
||||
|
||||
|
||||
for (int i = 0; i < retry; i++) {
|
||||
usb_h_sie_init(usb_id);
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
usb_write_power(usb_id, BIT(6)); //full-speed
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
||||
usb_write_power(usb_id, BIT(5) | BIT(6)); //high-speed
|
||||
#else
|
||||
#error "USB_SPEED_MODE not defined"
|
||||
#endif
|
||||
ret = usb_host_init(usb_id, reset_delay, mount_timeout);
|
||||
if (ret) {
|
||||
reset_delay += 10;
|
||||
continue;
|
||||
}
|
||||
|
||||
void *const ep0_dma = usb_h_get_ep_buffer(usb_id, 0);
|
||||
usb_set_dma_taddr(usb_id, 0, ep0_dma);
|
||||
|
||||
usb_sie_enable(usb_id);//enable sie intr
|
||||
usb_mdelay(reset_delay);
|
||||
|
||||
/**********get device descriptor*********/
|
||||
struct usb_device_descriptor device_desc;
|
||||
private_data->usb_id = usb_id;
|
||||
private_data->status = 0;
|
||||
private_data->devnum = 0;
|
||||
private_data->ep0_max_packet_size = 8;
|
||||
ret = usb_get_device_descriptor(host_dev, &device_desc);
|
||||
|
||||
/**********set address*********/
|
||||
usb_mdelay(20);
|
||||
u8 devnum = rand32() % 16 + 1;
|
||||
ret = set_address(host_dev, devnum);
|
||||
check_usb_mount(ret);
|
||||
private_data->devnum = devnum ;
|
||||
|
||||
/**********get device descriptor*********/
|
||||
usb_mdelay(20);
|
||||
ret = usb_get_device_descriptor(host_dev, &device_desc);
|
||||
check_usb_mount(ret);
|
||||
private_data->ep0_max_packet_size = device_desc.bMaxPacketSize0;
|
||||
|
||||
/**********get config descriptor*********/
|
||||
struct usb_config_descriptor cfg_desc;
|
||||
ret = get_config_descriptor(host_dev, &cfg_desc, USB_DT_CONFIG_SIZE);
|
||||
check_usb_mount(ret);
|
||||
|
||||
#if USB_H_MALLOC_ENABLE
|
||||
u8 *desc_buf = zalloc(cfg_desc.wTotalLength + 16);
|
||||
ASSERT(desc_buf, "desc_buf");
|
||||
#else
|
||||
u8 desc_buf[128] = {0};
|
||||
cfg_desc.wTotalLength = min(sizeof(desc_buf), cfg_desc.wTotalLength);
|
||||
#endif
|
||||
|
||||
ret = get_config_descriptor(host_dev, desc_buf, cfg_desc.wTotalLength);
|
||||
check_usb_mount(ret);
|
||||
|
||||
/**********set configuration*********/
|
||||
ret = set_configuration(host_dev);
|
||||
/* printf_buf(desc_buf, cfg_desc.wTotalLength); */
|
||||
ret |= usb_descriptor_parser(host_dev, desc_buf, cfg_desc.wTotalLength, &device_desc);
|
||||
#if USB_H_MALLOC_ENABLE
|
||||
log_info("free:desc_buf= %x\n", desc_buf);
|
||||
free(desc_buf);
|
||||
#endif
|
||||
check_usb_mount(ret);
|
||||
|
||||
for (int itf = 0; itf < MAX_HOST_INTERFACE; itf++) {
|
||||
if (host_dev->interface_info[itf]) {
|
||||
host_dev->interface_info[itf]->ctrl->set_power(host_dev, 1);
|
||||
}
|
||||
}
|
||||
break;//succ
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
private_data->status = 1;
|
||||
return DEV_ERR_NONE;
|
||||
|
||||
__exit_fail:
|
||||
printf("usb_probe fail");
|
||||
private_data->status = 0;
|
||||
usb_sie_close(usb_id);
|
||||
return ret;
|
||||
}
|
||||
static int usb_event_notify(const struct usb_host_device *host_dev, u32 ev)
|
||||
{
|
||||
const usb_dev id = host_device2id(host_dev);
|
||||
struct sys_event event;
|
||||
static u32 bmUsbEvent[USB_MAX_HW_NUM];
|
||||
u8 have_post_event = 0;
|
||||
u8 no_send_event = 0;
|
||||
if (ev == 0) {
|
||||
event.u.dev.event = DEVICE_EVENT_IN;
|
||||
} else if (ev == 1) {
|
||||
event.u.dev.event = DEVICE_EVENT_CHANGE;
|
||||
} else {
|
||||
event.u.dev.event = DEVICE_EVENT_OUT;
|
||||
goto __usb_event_out;
|
||||
}
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
no_send_event = 0;
|
||||
event.u.dev.value = 0;
|
||||
if (host_dev->interface_info[i]) {
|
||||
switch (host_dev->interface_info[i]->ctrl->interface_class) {
|
||||
#if TCFG_UDISK_ENABLE
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
if (have_post_event & BIT(0)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(0);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"udisk0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"udisk1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(0);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_ADB_ENABLE
|
||||
case USB_CLASS_ADB:
|
||||
if (have_post_event & BIT(1)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(1);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"adb0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"adb1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(1);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_AOA_ENABLE
|
||||
case USB_CLASS_AOA:
|
||||
if (have_post_event & BIT(2)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(2);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"aoa0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"aoa1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(2);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
case USB_CLASS_HID:
|
||||
if (have_post_event & BIT(3)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(3);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"hid0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"hid1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(3);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
case USB_CLASS_AUDIO:
|
||||
if (have_post_event & BIT(4)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(4);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"audio0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"audio1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(4);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!no_send_event && event.u.dev.value) {
|
||||
log_info("event %x interface %x class %x %s",
|
||||
event.u.dev.event, i,
|
||||
host_dev->interface_info[i]->ctrl->interface_class,
|
||||
(const char *)event.u.dev.value);
|
||||
|
||||
/* printf("usb_host_mount notify >>>>>>>>>>>\n"); */
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
sys_event_notify(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__usb_event_out:
|
||||
if (event.u.dev.event == DEVICE_EVENT_OUT) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (bmUsbEvent[id] & BIT(i)) {
|
||||
switch (i) {
|
||||
#if TCFG_UDISK_ENABLE
|
||||
case 0:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"udisk0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"udisk1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_ADB_ENABLE
|
||||
case 1:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"adb0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"adb1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_AOA_ENABLE
|
||||
case 2:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"aoa0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"aoa1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
case 3:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"hid0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"hid1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
case 4:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"audio0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"audio1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
event.u.dev.value = 0;
|
||||
break;
|
||||
}
|
||||
bmUsbEvent[id] &= ~BIT(i);
|
||||
if (event.u.dev.value) {
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST;
|
||||
have_post_event = 1;
|
||||
sys_event_notify(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (have_post_event) {
|
||||
return DEV_ERR_NONE;
|
||||
} else {
|
||||
return DEV_ERR_UNKNOW_CLASS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char *usb_host_valid_class_to_dev(const usb_dev id, u32 usbclass)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
u32 itf_class;
|
||||
|
||||
for (int i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
if (host_dev->interface_info[i] &&
|
||||
host_dev->interface_info[i]->ctrl) {
|
||||
itf_class = host_dev->interface_info[i]->ctrl->interface_class;
|
||||
if (itf_class == usbclass) {
|
||||
switch (itf_class) {
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
if (usb_id == 0) {
|
||||
return "udisk0";
|
||||
} else if (usb_id == 1) {
|
||||
return "udisk1";
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_ADB:
|
||||
if (usb_id == 0) {
|
||||
return "adb0";
|
||||
} else if (usb_id == 1) {
|
||||
return "adb1";
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_AOA:
|
||||
if (usb_id == 0) {
|
||||
return "aoa0";
|
||||
} else if (usb_id == 1) {
|
||||
return "aoa1";
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
if (usb_id == 0) {
|
||||
return "hid0";
|
||||
} else if (usb_id == 1) {
|
||||
return "hid1";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb_host_mount
|
||||
*
|
||||
* @param usb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
u32 usb_host_mount(const usb_dev id, u32 retry, u32 reset_delay, u32 mount_timeout)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
|
||||
u32 ret;
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
memset(host_dev, 0, sizeof(*host_dev));
|
||||
|
||||
host_dev->private_data.usb_id = id;
|
||||
|
||||
usb_sem_init(host_dev);
|
||||
usb_h_isr_reg(usb_id, 1, 0);
|
||||
|
||||
|
||||
ret = _usb_host_mount(usb_id, retry, reset_delay, mount_timeout);
|
||||
usb_otg_resume(usb_id); //打开usb host之后恢复otg检测
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
return usb_event_notify(host_dev, 0);
|
||||
|
||||
__exit_fail:
|
||||
usb_sie_disable(usb_id);
|
||||
usb_sem_del(host_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 _usb_host_unmount(const usb_dev usb_id)
|
||||
{
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
|
||||
struct usb_private_data *private_data = &host_dev->private_data;
|
||||
private_data->status = 0;
|
||||
|
||||
usb_sem_post(host_dev);//拔掉设备时,让读写线程快速释放
|
||||
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
if (host_dev->interface_info[i] && host_dev->interface_info[i]->ctrl->set_power) {
|
||||
host_dev->interface_info[i]->ctrl->set_power(host_dev, 0);
|
||||
host_dev->interface_info[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
usb_sie_close(usb_id);
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb_host_unmount
|
||||
*
|
||||
* @param usb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/* u32 usb_host_unmount(const usb_dev usb_id, char *device_name) */
|
||||
u32 usb_host_unmount(const usb_dev id)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
u32 ret;
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
struct sys_event event;
|
||||
|
||||
#if (TCFG_UDISK_ENABLE && UDISK_READ_512_ASYNC_ENABLE)
|
||||
_usb_stor_async_wait_sem(host_dev);
|
||||
#endif
|
||||
ret = _usb_host_unmount(usb_id);
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
usb_sem_del(host_dev);
|
||||
|
||||
/* printf("usb_host_unmount notify >>>>>>>>>>>\n"); */
|
||||
usb_event_notify(host_dev, 2);
|
||||
return DEV_ERR_NONE;
|
||||
|
||||
__exit_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 usb_host_remount(const usb_dev id, u32 retry, u32 delay, u32 ot, u8 notify)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
u32 ret;
|
||||
struct sys_event event;
|
||||
|
||||
ret = _usb_host_unmount(usb_id);
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
os_sem_set(host_dev->sem, 0);
|
||||
|
||||
ret = _usb_host_mount(usb_id, retry, delay, ot);
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
usb_event_notify(host_dev, 1);
|
||||
}
|
||||
return DEV_ERR_NONE;
|
||||
|
||||
__exit_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_host_force_reset(const usb_dev usb_id)
|
||||
{
|
||||
//预留以后加上hub的处理
|
||||
usb_h_force_reset(usb_id);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,145 +0,0 @@
|
||||
/**@file usb_storage.h
|
||||
* @brief usb_storage驱动头文件(做主机)
|
||||
* @details 结构体声明,功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_STORAGE_H__
|
||||
#define __USB_STORAGE_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
|
||||
/* u盘预读功能配置, 二选一
|
||||
* 当两种方式都不使能,则表示不开启预读 */
|
||||
#define UDISK_READ_BIGBLOCK_ASYNC_ENABLE 0 //使能大扇区预读方式(不需要额外buf,速度比512预读慢10%)
|
||||
#define UDISK_READ_512_ASYNC_ENABLE 0 //使能512Byte预读方式(需要额外的512byte buffer,速度比大扇区预读快10%)
|
||||
/****************************/
|
||||
|
||||
#define UDISK_READ_ASYNC_BLOCK_NUM (16) //预读扇区数
|
||||
|
||||
//****************************youning***********************************----->
|
||||
#define UDISK_READ_AHEAD_ENABLE 0 //使能U盘预读功能
|
||||
#define UDISK_READ_AHEAD_BLOCK_NUM 16 //U盘预读扇区数量
|
||||
#define check_usb_read_ahead(ret) \
|
||||
if(ret < 0) {\
|
||||
log_error("func:%s,line:%d,lba:%d,ret:%d\n", __func__, __LINE__, lba, ret);\
|
||||
goto __exit;\
|
||||
} //检查函数返回值,0:正确 非0:错误
|
||||
//****************************youning***********************************<-----
|
||||
|
||||
/**@enum usb_sta
|
||||
* @brief USB设备当前状态
|
||||
*/
|
||||
typedef enum usb_sta {
|
||||
DEV_IDLE = 0, ///<空闲状态
|
||||
DEV_INIT, ///<初始化
|
||||
DEV_OPEN, ///<开启
|
||||
DEV_READ, ///<读操作
|
||||
DEV_WRITE, ///<写操作
|
||||
DEV_CLOSE, ///<关闭
|
||||
DEV_SUSPEND, ///<挂起
|
||||
} USB_STA ;
|
||||
|
||||
/**@struct udisk_end_desc
|
||||
* @brief U盘端点描述结构体
|
||||
*
|
||||
*/
|
||||
struct udisk_end_desc {
|
||||
u8 host_epout; ///<主机端点输出
|
||||
u8 target_epout; ///<目标端点输出
|
||||
u8 host_epin; ///<主机端点输入
|
||||
u8 target_epin; ///<目标端点输入
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
u16 rxmaxp; ///<接收最大端点号
|
||||
u16 txmaxp; ///<发送最大端点号
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ENABLE_DISK_HOTPLUG 0
|
||||
|
||||
/**@struct mass_storage
|
||||
* @brief mass_storage协议所使用的相关变量
|
||||
*/
|
||||
struct mass_storage {
|
||||
OS_MUTEX mutex; ///<互斥量
|
||||
|
||||
struct usb_scsi_cbw cbw; ///<CBW指令结构体
|
||||
struct usb_scsi_csw csw; ///<CSW状态结构体
|
||||
struct request_sense_data sense; ///<请求数据检查结构体
|
||||
|
||||
char *name; ///<设备名字
|
||||
struct read_capacity_data capacity[2]; ///<读取数据的能力,包含数据块的编号、大小
|
||||
u8 lun; ///<最大逻辑单元地址
|
||||
u8 curlun; ///<当前逻辑单元地址
|
||||
|
||||
u8 dev_status; ///<设备状态
|
||||
u8 suspend_cnt; ///<挂起状态计数器
|
||||
u8 read_only; ///<只读标志位
|
||||
|
||||
u32 remain_len; ///<剩余的包长度
|
||||
u32 prev_lba; ///<上一次扇区
|
||||
#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE)
|
||||
u8 async_en; ///<异步模式使能
|
||||
u8 need_send_csw; ///<需要发送csw标志位
|
||||
u8 *udisk_512_buf; ///<U盘512K大小BUFFER指针
|
||||
u32 async_prev_lba; ///<异步模式上一次地址
|
||||
#endif
|
||||
#if UDISK_READ_AHEAD_ENABLE
|
||||
u8 *udisk_read_ahead_buf; ///<U盘512byte大小BUFFER指针
|
||||
u32 udisk_read_ahead_lba_last; ///<异步模式上一次地址
|
||||
#endif
|
||||
#if ENABLE_DISK_HOTPLUG
|
||||
u8 media_sta_cur; ///<当前媒介状态 //for card reader, card removable
|
||||
u8 media_sta_prev; ///<上次媒介状态
|
||||
|
||||
int test_unit_ready_tick; ///<测试准备标记
|
||||
#endif
|
||||
};
|
||||
|
||||
enum usb_async_mode {
|
||||
BULK_ASYNC_MODE_EXIT = 0, ///<退出异步模式
|
||||
BULK_ASYNC_MODE_SEM_PEND, ///<异步预读等待信号量
|
||||
};
|
||||
|
||||
#define MASS_LBA_INIT (-2)
|
||||
|
||||
/**@brief 使用mass_storage协议,对大容量存储设备进行解析,端点配置
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] interface_num 接口号
|
||||
* @param[in] *pBuf 指向BUFFER的指针
|
||||
* @return len BUFFER的长度
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_msd_parser(host_dev,interface_num,pBuf);
|
||||
* @encode
|
||||
*/
|
||||
int usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
/**@brief 异步模式等待信号量
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* _usb_stor_async_wait_sem(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int _usb_stor_async_wait_sem(struct usb_host_device *host_dev);
|
||||
|
||||
#endif
|
||||
@ -1,168 +0,0 @@
|
||||
#ifndef __USB_COMMON_DEFINE_H__
|
||||
#define __USB_COMMON_DEFINE_H__
|
||||
|
||||
///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里
|
||||
///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里
|
||||
///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里
|
||||
//
|
||||
/**************************************************************************/
|
||||
/*
|
||||
CLASS BITMAP
|
||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
|
||||
HID AUDIO SPEAKER Mass Storage
|
||||
*/
|
||||
/**************************************************************************/
|
||||
#define MASSSTORAGE_CLASS 0x00000001
|
||||
#define SPEAKER_CLASS 0x00000002
|
||||
#define MIC_CLASS 0x00000004
|
||||
#define HID_CLASS 0x00000008
|
||||
#define CDC_CLASS 0x00000010
|
||||
|
||||
#define AUDIO_CLASS (SPEAKER_CLASS|MIC_CLASS)
|
||||
|
||||
|
||||
#define USB_ROOT2 0
|
||||
|
||||
/// board文件没有定义的宏,在这里定义,防止编译报warning
|
||||
#ifndef TCFG_PC_ENABLE
|
||||
#define TCFG_PC_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_UDISK_ENABLE
|
||||
#define TCFG_UDISK_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_HID_HOST_ENABLE
|
||||
#define TCFG_HID_HOST_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_AOA_ENABLE
|
||||
#define TCFG_AOA_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_ADB_ENABLE
|
||||
#define TCFG_ADB_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_APPLE_DOCK_EN
|
||||
#define TCFG_USB_APPLE_DOCK_EN 0
|
||||
#endif
|
||||
#ifndef TCFG_HOST_AUDIO_ENABLE
|
||||
#define TCFG_HOST_AUDIO_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_CHARGE_ENABLE
|
||||
#define TCFG_CHARGE_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_PORT_CHARGE
|
||||
#define TCFG_USB_PORT_CHARGE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_MIC_ECHO_ENABLE
|
||||
#define TCFG_USB_MIC_ECHO_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_MIC_DATA_FROM_MICEFFECT
|
||||
#define TCFG_USB_MIC_DATA_FROM_MICEFFECT 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
|
||||
#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 0
|
||||
#endif
|
||||
#ifndef TCFG_ONLY_PC_ENABLE //只有pc模式
|
||||
#define TCFG_ONLY_PC_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_TYPE_C_ENABLE //应用于type-c场景
|
||||
#define TCFG_TYPE_C_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_CDC_BACKGROUND_RUN
|
||||
#define TCFG_USB_CDC_BACKGROUND_RUN 0
|
||||
#endif
|
||||
|
||||
/********************************/
|
||||
|
||||
#if TCFG_UDISK_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_AOA_ENABLE || TCFG_ADB_ENABLE || TCFG_HOST_AUDIO_ENABLE
|
||||
#define MOUNT_RETRY 3
|
||||
#define MOUNT_RESET 40
|
||||
#define MOUNT_TIMEOUT 50
|
||||
#define USB_HOST_ENABLE 1
|
||||
#else
|
||||
#define USB_HOST_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_CHARGE_ENABLE && TCFG_USB_PORT_CHARGE
|
||||
#define TCFG_OTG_MODE_CHARGE (OTG_CHARGE_MODE)
|
||||
#else
|
||||
#define TCFG_OTG_MODE_CHARGE 0
|
||||
#endif
|
||||
|
||||
#if (TCFG_PC_ENABLE)
|
||||
#define TCFG_PC_UPDATE 1
|
||||
#define TCFG_OTG_MODE_SLAVE (OTG_SLAVE_MODE)
|
||||
#else
|
||||
#define TCFG_PC_UPDATE 0
|
||||
#define TCFG_OTG_MODE_SLAVE 0
|
||||
#endif
|
||||
|
||||
#if (USB_HOST_ENABLE)
|
||||
#define TCFG_OTG_MODE_HOST (OTG_HOST_MODE)
|
||||
#else
|
||||
#define TCFG_OTG_MODE_HOST 0
|
||||
#endif
|
||||
|
||||
#if TCFG_PC_ENABLE
|
||||
#define TCFG_USB_SLAVE_ENABLE 1
|
||||
#if (USB_DEVICE_CLASS_CONFIG & MASSSTORAGE_CLASS)
|
||||
#define TCFG_USB_SLAVE_MSD_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_MSD_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & AUDIO_CLASS)
|
||||
#define TCFG_USB_SLAVE_AUDIO_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_AUDIO_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & HID_CLASS)
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & CDC_CLASS)
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 0
|
||||
#endif
|
||||
|
||||
#else /* TCFG_PC_ENABLE == 0*/
|
||||
#define TCFG_USB_SLAVE_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_MSD_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_AUDIO_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 0
|
||||
#endif
|
||||
|
||||
#define TCFG_OTG_SLAVE_ONLINE_CNT 3
|
||||
#define TCFG_OTG_SLAVE_OFFLINE_CNT 2
|
||||
|
||||
#define TCFG_OTG_HOST_ONLINE_CNT 2
|
||||
#define TCFG_OTG_HOST_OFFLINE_CNT 3
|
||||
|
||||
#ifndef TCFG_OTG_MODE
|
||||
#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE)
|
||||
#endif
|
||||
|
||||
#define TCFG_OTG_DET_INTERVAL 50
|
||||
|
||||
#if (TCFG_USB_CDC_BACKGROUND_RUN)
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & CDC_CLASS)
|
||||
#error "CDC_CLASS and TCFG_COMM_TYPE==TCFG_USB_COMM 不能同时打开"
|
||||
#else
|
||||
#undef TCFG_USB_SLAVE_CDC_ENABLE
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 1
|
||||
#endif
|
||||
#undef TCFG_USB_SLAVE_ENABLE
|
||||
#define TCFG_USB_SLAVE_ENABLE 1
|
||||
|
||||
#if (!TCFG_PC_ENABLE)
|
||||
#undef TCFG_OTG_MODE
|
||||
#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST | OTG_SLAVE_MODE | TCFG_OTG_MODE_CHARGE)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,354 +0,0 @@
|
||||
#include "usb_config.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "irq.h"
|
||||
#include "init.h"
|
||||
#include "gpio.h"
|
||||
#include "timer.h"
|
||||
#include "app_config.h"
|
||||
#include "lbuf.h"
|
||||
|
||||
#ifdef CONFIG_ADAPTER_ENABLE
|
||||
#include "adapter_usb_hid.h"
|
||||
#endif//CONFIG_ADAPTER_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"
|
||||
|
||||
#define SET_INTERRUPT ___interrupt
|
||||
|
||||
|
||||
#define MAX_EP_TX 5
|
||||
#define MAX_EP_RX 5
|
||||
|
||||
static usb_interrupt usb_interrupt_tx[USB_MAX_HW_NUM][MAX_EP_TX];// SEC(.usb_g_bss);
|
||||
static usb_interrupt usb_interrupt_rx[USB_MAX_HW_NUM][MAX_EP_RX];// SEC(.usb_h_bss);
|
||||
|
||||
static u8 ep0_dma_buffer[EP0_SETUP_LEN] __attribute__((aligned(4))) SEC(.usb_ep0) ;
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
#define MSD_DMA_SIZE (MAXP_SIZE_BULKOUT + MAXP_SIZE_BULKIN)
|
||||
#else
|
||||
#define MSD_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
#define HID_DMA_SIZE 64
|
||||
#else
|
||||
#define HID_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
#define AUDIO_DMA_SIZE 256+192
|
||||
#else
|
||||
#define AUDIO_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
#define CDC_DMA_SIZE (64*3)
|
||||
#else
|
||||
#define CDC_DMA_SIZE (64*2)
|
||||
#endif
|
||||
#else
|
||||
#define CDC_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
struct usb_config_var_t {
|
||||
u8 usb_setup_buffer[USB_SETUP_SIZE];
|
||||
struct usb_ep_addr_t usb_ep_addr;
|
||||
struct usb_setup_t usb_setup;
|
||||
};
|
||||
static struct usb_config_var_t *usb_config_var = {NULL};
|
||||
|
||||
#if USB_MALLOC_ENABLE
|
||||
#else
|
||||
static struct usb_config_var_t _usb_config_var SEC(.usb_config_var);
|
||||
#endif
|
||||
|
||||
|
||||
#define USB_DMA_BUF_ALIGN (8)
|
||||
#ifndef USB_DMA_BUF_MAX_SIZE
|
||||
#define USB_DMA_BUF_MAX_SIZE (HID_DMA_SIZE +USB_DMA_BUF_ALIGN+ AUDIO_DMA_SIZE +USB_DMA_BUF_ALIGN+ MSD_DMA_SIZE*2 + USB_DMA_BUF_ALIGN+CDC_DMA_SIZE + USB_DMA_BUF_ALIGN + 100)
|
||||
#endif//USB_DMA_BUF_MAX_SIZE
|
||||
|
||||
static u8 usb_dma_buf[USB_DMA_BUF_MAX_SIZE] SEC(.usb_msd_dma) __attribute__((aligned(8)));
|
||||
struct lbuff_head *usb_dma_lbuf = NULL;
|
||||
void usb_memory_init()
|
||||
{
|
||||
usb_dma_lbuf = lbuf_init(usb_dma_buf, sizeof(usb_dma_buf), USB_DMA_BUF_ALIGN, 0);
|
||||
log_info("%s() total dma size %x @%x", __func__, sizeof(usb_dma_buf), usb_dma_buf);
|
||||
}
|
||||
|
||||
__attribute__((always_inline_when_const_args))
|
||||
void *usb_alloc_ep_dmabuffer(const usb_dev usb_id, u32 ep, u32 dma_size)
|
||||
{
|
||||
u8 *ep_buffer = NULL;
|
||||
u32 _ep = ep & 0xf;
|
||||
if (ep & USB_DIR_IN) {
|
||||
switch (_ep) {
|
||||
case 0:
|
||||
ep_buffer = ep0_dma_buffer;
|
||||
break;
|
||||
default :
|
||||
ep_buffer = lbuf_alloc(usb_dma_lbuf, dma_size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (_ep) {
|
||||
case 0:
|
||||
ep_buffer = ep0_dma_buffer;
|
||||
break;
|
||||
default :
|
||||
ep_buffer = lbuf_alloc(usb_dma_lbuf, dma_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(ep_buffer, "usb_alloc_ep_dmabuffer ep_buffer = NULL!!!, _ep = %x, dma_size = %d\n", ep, dma_size);
|
||||
|
||||
log_info("ep_buffer = %x, ep = %x, dma_size = %d\n", ep_buffer, ep, dma_size);
|
||||
|
||||
return ep_buffer;
|
||||
}
|
||||
|
||||
|
||||
static u8 sleep_flag = 0;
|
||||
u8 get_sleep_flag()
|
||||
{
|
||||
return sleep_flag ;
|
||||
}
|
||||
|
||||
void set_sleep_flag(u8 sl_flag)
|
||||
{
|
||||
sleep_flag = sl_flag ;
|
||||
}
|
||||
|
||||
static void usb_resume_sign(void *priv)
|
||||
{
|
||||
usb_dev usb_id = usb_device2id(priv);
|
||||
u32 reg = usb_read_power(usb_id);
|
||||
usb_write_power(usb_id, reg | BIT(2));//send resume
|
||||
os_time_dly(2);//10ms~20ms
|
||||
usb_write_power(usb_id, reg);//clean resume
|
||||
}
|
||||
|
||||
void usb_remote_wakeup(const usb_dev usb_id)
|
||||
{
|
||||
struct usb_device_t *usb_device = usb_id2device(usb_id);
|
||||
if (usb_device->bRemoteWakup) {
|
||||
sys_timeout_add(usb_device, usb_resume_sign, 1);
|
||||
}
|
||||
}
|
||||
void usb_phy_resume(const usb_dev usb_id)
|
||||
{
|
||||
usb_iomode(0);
|
||||
|
||||
struct usb_device_t *usb_device = usb_id2device(usb_id);
|
||||
usb_write_faddr(usb_id, usb_device->baddr);
|
||||
|
||||
if (usb_device->baddr == 0) {
|
||||
usb_device->bDeviceStates = USB_DEFAULT;
|
||||
} else {
|
||||
usb_device->bDeviceStates = USB_CONFIGURED;
|
||||
}
|
||||
|
||||
usb_otg_resume(usb_id);
|
||||
}
|
||||
|
||||
void usb_phy_suspend(const usb_dev usb_id)
|
||||
{
|
||||
gpio_set_pull_up(IO_PORT_DP, 1);
|
||||
gpio_set_pull_down(IO_PORT_DP, 0);
|
||||
gpio_set_direction(IO_PORT_DP, 1);
|
||||
|
||||
usb_iomode(1);
|
||||
/* musb_read_usb(0, MUSB_INTRUSB); */
|
||||
|
||||
usb_otg_suspend(usb_id, OTG_KEEP_STATE);
|
||||
}
|
||||
void usb_isr(const usb_dev usb_id)
|
||||
{
|
||||
u32 intr_usb, intr_usbe;
|
||||
u32 intr_tx, intr_txe;
|
||||
u32 intr_rx, intr_rxe;
|
||||
|
||||
__asm__ volatile("ssync");
|
||||
usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx);
|
||||
usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe);
|
||||
struct usb_device_t *usb_device = usb_id2device(usb_id);
|
||||
|
||||
intr_usb &= intr_usbe;
|
||||
intr_tx &= intr_txe;
|
||||
intr_rx &= intr_rxe;
|
||||
|
||||
if (intr_usb & INTRUSB_SUSPEND) {
|
||||
log_error("usb suspend");
|
||||
set_sleep_flag(1);
|
||||
#if USB_SUSPEND_RESUME
|
||||
usb_phy_suspend(usb_id);
|
||||
#endif
|
||||
|
||||
#if USB_SUSPEND_RESUME_SYSTEM_NO_SLEEP
|
||||
printf("\n NULL \n");
|
||||
#endif
|
||||
}
|
||||
if (intr_usb & INTRUSB_RESET_BABBLE) {
|
||||
log_error("usb reset");
|
||||
usb_reset_interface(usb_device);
|
||||
|
||||
#if USB_SUSPEND_RESUME || USB_SUSPEND_RESUME_SYSTEM_NO_SLEEP
|
||||
u32 reg = usb_read_power(usb_id);
|
||||
usb_write_power(usb_id, (reg | INTRUSB_SUSPEND | INTRUSB_RESUME));//enable suspend resume
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr_usb & INTRUSB_RESUME) {
|
||||
log_error("usb resume");
|
||||
#if USB_SUSPEND_RESUME
|
||||
usb_phy_resume(usb_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr_tx & BIT(0)) {
|
||||
if (usb_interrupt_rx[usb_id][0]) {
|
||||
usb_interrupt_rx[usb_id][0](usb_device, 0);
|
||||
} else {
|
||||
usb_control_transfer(usb_device);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_EP_TX; i++) {
|
||||
if (intr_tx & BIT(i)) {
|
||||
if (usb_interrupt_tx[usb_id][i]) {
|
||||
usb_interrupt_tx[usb_id][i](usb_device, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_EP_RX; i++) {
|
||||
if (intr_rx & BIT(i)) {
|
||||
if (usb_interrupt_rx[usb_id][i]) {
|
||||
usb_interrupt_rx[usb_id][i](usb_device, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
__asm__ volatile("csync");
|
||||
}
|
||||
|
||||
void usb_sof_isr(const usb_dev usb_id)
|
||||
{
|
||||
usb_sof_clr_pnd(usb_id);
|
||||
static u32 sof_count = 0;
|
||||
if ((sof_count++ % 1000) == 0) {
|
||||
log_d("sof 1s isr frame:%d", usb_read_sofframe(usb_id));
|
||||
}
|
||||
}
|
||||
void usb_suspend_check(void *p)
|
||||
{
|
||||
usb_dev usb_id = (usb_dev)p;
|
||||
|
||||
static u16 sof_frame = 0;
|
||||
u16 frame = usb_read_sofframe(usb_id);// sof frame 不更新,则usb进入断开或者suspend状态
|
||||
if (frame == sof_frame) {
|
||||
usb_phy_suspend(usb_id);
|
||||
}
|
||||
sof_frame = frame;
|
||||
}
|
||||
|
||||
SET_INTERRUPT
|
||||
void usb0_g_isr()
|
||||
{
|
||||
usb_isr(0);
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb0_sof_isr()
|
||||
{
|
||||
usb_sof_isr(0);
|
||||
}
|
||||
|
||||
#if USB_MAX_HW_NUM == 2
|
||||
SET_INTERRUPT
|
||||
void usb1_g_isr()
|
||||
{
|
||||
usb_isr(1);
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb1_sof_isr()
|
||||
{
|
||||
usb_sof_isr(1);
|
||||
}
|
||||
#endif
|
||||
__attribute__((always_inline_when_const_args))
|
||||
u32 usb_g_set_intr_hander(const usb_dev usb_id, u32 ep, usb_interrupt hander)
|
||||
{
|
||||
if (ep & USB_DIR_IN) {
|
||||
usb_interrupt_tx[usb_id][ep & 0xf] = hander;
|
||||
} else {
|
||||
usb_interrupt_rx[usb_id][ep] = hander;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
|
||||
{
|
||||
if (usb_id == 0) {
|
||||
request_irq(IRQ_USB_CTRL_IDX, priority, usb0_g_isr, cpu_id);
|
||||
} else {
|
||||
#if USB_MAX_HW_NUM == 2
|
||||
request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_g_isr, cpu_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
|
||||
{
|
||||
if (usb_id == 0) {
|
||||
request_irq(IRQ_USB_SOF_IDX, priority, usb0_sof_isr, cpu_id);
|
||||
} else {
|
||||
#if USB_MAX_HW_NUM == 2
|
||||
request_irq(IRQ_USB1_SOF_IDX, priority, usb1_sof_isr, cpu_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
u32 usb_config(const usb_dev usb_id)
|
||||
{
|
||||
memset(usb_interrupt_rx[usb_id], 0, sizeof(usb_interrupt_rx[usb_id]));
|
||||
memset(usb_interrupt_tx[usb_id], 0, sizeof(usb_interrupt_tx[usb_id]));
|
||||
|
||||
if (!usb_config_var) {
|
||||
#if USB_MALLOC_ENABLE
|
||||
usb_config_var = (struct usb_config_var_t *)zalloc(sizeof(struct usb_config_var_t));
|
||||
if (!usb_config_var) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
memset(&_usb_config_var, 0, sizeof(_usb_config_var));
|
||||
usb_config_var = &_usb_config_var;
|
||||
#endif
|
||||
}
|
||||
log_debug("zalloc: usb_config_var = %x\n", usb_config_var);
|
||||
|
||||
usb_var_init(usb_id, &(usb_config_var->usb_ep_addr));
|
||||
usb_setup_init(usb_id, &(usb_config_var->usb_setup), usb_config_var->usb_setup_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 usb_release(const usb_dev usb_id)
|
||||
{
|
||||
log_debug("free zalloc: usb_config_var = %x\n", usb_id, usb_config_var);
|
||||
usb_var_init(usb_id, NULL);
|
||||
usb_setup_init(usb_id, NULL, NULL);
|
||||
#if USB_MALLOC_ENABLE
|
||||
if (usb_config_var) {
|
||||
log_debug("free: usb_config_var = %x\n", usb_config_var);
|
||||
free(usb_config_var);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_config_var = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
/**@file usb_config.h
|
||||
* @brief usb_config配置头文件
|
||||
* @details 功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_CONFIG_H__
|
||||
#define __USB_CONFIG_H__
|
||||
|
||||
#include "typedef.h"
|
||||
#include "asm/usb.h"
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
|
||||
/**@brief USB主机模式配置
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_host_config(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
void usb_host_config(usb_dev usb_id);
|
||||
|
||||
/**@brief USB主机模式释放
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_host_free(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
void usb_host_free(usb_dev usb_id);
|
||||
|
||||
/**@brief USB主机模式获取端点的BUFFER的地址
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] ep 端点号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_h_get_ep_bufeeer(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void *usb_h_get_ep_buffer(const usb_dev usb_id, u32 ep);
|
||||
|
||||
/**@brief USB主机模式中断注册
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] priority 优先级
|
||||
* @param[in] cpu_id cpu的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_h_isr_reg(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void usb_h_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id);
|
||||
|
||||
/**@brief USB从机模式中断注册
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] priority 优先级
|
||||
* @param[in] cpu_id cpu的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_g_isr_reg(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id);
|
||||
|
||||
|
||||
|
||||
/**@brief USB SOF中断注册
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] priority 优先级
|
||||
* @param[in] cpu_id cpu的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_sof_isr_reg(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id);
|
||||
|
||||
/**@brief 分配端点BUFFER的dma地址
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] ep 端点号
|
||||
* @param[in] dma_size 数据长度
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_alloc_ep_dmabuffer(usb_id , ep , size);
|
||||
* @encode
|
||||
*/
|
||||
void *usb_alloc_ep_dmabuffer(const usb_dev usb_id, u32 ep, u32 dma_size);
|
||||
|
||||
/**@brief USB从机初始化配置
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_config(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
u32 usb_config(const usb_dev usb_id);
|
||||
|
||||
/**@brief USB从机释放
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_release(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
u32 usb_release(const usb_dev usb_id);
|
||||
|
||||
/**@brief USB内存空间初始化
|
||||
* @param[in] 无
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_memory_init(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
void usb_memory_init();
|
||||
|
||||
#endif /*USB_CONFIG_H*/
|
||||
@ -1,194 +0,0 @@
|
||||
#include "usb_config.h"
|
||||
#include "usb/scsi.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"
|
||||
|
||||
#define SET_INTERRUPT ___interrupt
|
||||
|
||||
#if TCFG_UDISK_ENABLE || TCFG_ADB_ENABLE ||TCFG_AOA_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_HOST_AUDIO_ENABLE
|
||||
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
#define MAX_HOST_EP_RX 4
|
||||
#define MAX_HOST_EP_TX 4
|
||||
#else
|
||||
#define MAX_HOST_EP_RX 2
|
||||
#define MAX_HOST_EP_TX 2 //ep0 & ep1(msd)
|
||||
#endif
|
||||
|
||||
struct host_var_t {
|
||||
struct usb_ep_addr_t host_ep_addr ;
|
||||
usb_h_interrupt usb_h_interrupt_rx[MAX_HOST_EP_RX] ;
|
||||
usb_h_interrupt usb_h_interrupt_tx[MAX_HOST_EP_TX] ;
|
||||
struct usb_host_device *dev_at_ep[MAX_HOST_EP_RX];
|
||||
};
|
||||
static struct host_var_t *host_var[USB_MAX_HW_NUM];// SEC(.usb_h_bss);
|
||||
static struct host_var_t __host_var[USB_MAX_HW_NUM];
|
||||
#if TCFG_ADB_ENABLE && TCFG_AOA_ENABLE && TCFG_HID_HOST_ENABLE
|
||||
static u8 ep0_dma[USB_MAX_HW_NUM][64 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep1_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep2_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep3_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep4_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
static u8 msd_h_dma_buffer[2][64 + 4] __attribute__((aligned(4))) SEC(.usb_h_dma);
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
||||
static u8 msd_h_dma_buffer[2][512] __attribute__((aligned(4))) SEC(.usb_h_dma);
|
||||
#else
|
||||
#error "USB_SPEED_MODE not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void usb_h_isr(const usb_dev usb_id)
|
||||
{
|
||||
u32 intr_usb, intr_usbe;
|
||||
u32 intr_tx, intr_txe;
|
||||
u32 intr_rx, intr_rxe;
|
||||
|
||||
__asm__ volatile("ssync");
|
||||
|
||||
usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx);
|
||||
usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe);
|
||||
struct usb_host_device *host_dev = NULL;
|
||||
|
||||
/* r_printf("usb_h_isr %x %x %x %x",host_dev,intr_usb,intr_tx,intr_rx); */
|
||||
intr_usb &= intr_usbe;
|
||||
intr_tx &= intr_txe;
|
||||
intr_rx &= intr_rxe;
|
||||
|
||||
if (intr_usb & INTRUSB_SUSPEND) {
|
||||
log_error("usb suspend");
|
||||
}
|
||||
if (intr_usb & INTRUSB_RESET_BABBLE) {
|
||||
log_error("usb reset");
|
||||
}
|
||||
if (intr_usb & INTRUSB_RESUME) {
|
||||
log_error("usb resume");
|
||||
}
|
||||
|
||||
if (intr_tx & BIT(0)) {
|
||||
if (host_var[usb_id]->usb_h_interrupt_tx[0]) {
|
||||
host_dev = host_var[usb_id]->dev_at_ep[0];
|
||||
host_var[usb_id]->usb_h_interrupt_tx[0](host_dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_HOST_EP_TX; i++) {
|
||||
if (intr_tx & BIT(i)) {
|
||||
if (host_var[usb_id]->usb_h_interrupt_tx[i]) {
|
||||
host_dev = host_var[usb_id]->dev_at_ep[i];
|
||||
host_var[usb_id]->usb_h_interrupt_tx[i](host_dev, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_HOST_EP_RX; i++) {
|
||||
if (intr_rx & BIT(i)) {
|
||||
if (host_var[usb_id]->usb_h_interrupt_rx[i]) {
|
||||
host_dev = host_var[usb_id]->dev_at_ep[i];
|
||||
host_var[usb_id]->usb_h_interrupt_rx[i](host_dev, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
__asm__ volatile("csync");
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb0_h_isr()
|
||||
{
|
||||
usb_h_isr(0);
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb1_h_isr()
|
||||
{
|
||||
usb_h_isr(1);
|
||||
}
|
||||
__attribute__((always_inline_when_const_args))
|
||||
u32 usb_h_set_intr_hander(const usb_dev usb_id, u32 ep, usb_h_interrupt hander)
|
||||
{
|
||||
if (ep & USB_DIR_IN) {
|
||||
host_var[usb_id]->usb_h_interrupt_rx[ep & 0xf] = hander;
|
||||
} else {
|
||||
host_var[usb_id]->usb_h_interrupt_tx[ep] = hander;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void usb_h_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
|
||||
{
|
||||
if (usb_id == 0) {
|
||||
request_irq(IRQ_USB_CTRL_IDX, priority, usb0_h_isr, cpu_id);
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
} else if (usb_id == 1) {
|
||||
request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_h_isr, cpu_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline_when_const_args))
|
||||
void *usb_h_get_ep_buffer(const usb_dev usb_id, u32 ep)
|
||||
{
|
||||
#if TCFG_ADB_ENABLE && TCFG_AOA_ENABLE && TCFG_HID_HOST_ENABLE
|
||||
u8 dir = !!(ep & USB_DIR_IN);
|
||||
u8 *p = NULL;
|
||||
switch (ep & 0xf) {
|
||||
case 0:
|
||||
p = &ep0_dma[usb_id][0];
|
||||
break;
|
||||
case 1:
|
||||
p = &ep1_dma[usb_id][dir * 64];
|
||||
break;
|
||||
case 2:
|
||||
p = &ep2_dma[usb_id][dir * 64];
|
||||
break;
|
||||
case 3:
|
||||
p = &ep3_dma[usb_id][dir * 64];
|
||||
break;
|
||||
case 4:
|
||||
p = &ep4_dma[usb_id][dir * 64];
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
#else
|
||||
return msd_h_dma_buffer;
|
||||
#endif
|
||||
}
|
||||
void usb_h_set_ep_isr(struct usb_host_device *host_dev, u32 ep, usb_h_interrupt hander, void *p)
|
||||
{
|
||||
if (host_dev) {
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
host_var[usb_id]->dev_at_ep[ep & 0xf] = p;
|
||||
usb_h_set_intr_hander(usb_id, ep, hander);
|
||||
}
|
||||
}
|
||||
void usb_host_config(usb_dev usb_id)
|
||||
{
|
||||
/* host_var[usb_id] = zalloc(sizeof(struct host_var_t)); */
|
||||
host_var[usb_id] = &__host_var[usb_id];
|
||||
|
||||
ASSERT(host_var[usb_id], "host_var_t");
|
||||
|
||||
g_printf("%s() %x %x", __func__, host_var[usb_id], &(host_var[usb_id]->host_ep_addr));
|
||||
usb_var_init(usb_id, &(host_var[usb_id]->host_ep_addr));
|
||||
}
|
||||
void usb_host_free(usb_dev usb_id)
|
||||
{
|
||||
g_printf("%s() %x", __func__, host_var[usb_id]);
|
||||
OS_ENTER_CRITICAL();
|
||||
/* free(host_var[usb_id]); */
|
||||
/* host_var[usb_id] = NULL; */
|
||||
if (host_var[usb_id]) {
|
||||
memset(host_var[usb_id]->usb_h_interrupt_rx, 0, sizeof(usb_h_interrupt) * MAX_HOST_EP_RX);
|
||||
memset(host_var[usb_id]->usb_h_interrupt_tx, 0, sizeof(usb_h_interrupt) * MAX_HOST_EP_TX);
|
||||
}
|
||||
OS_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
@ -1,190 +0,0 @@
|
||||
#ifndef __USB_STD_CLASS_DEF_H__
|
||||
#define __USB_STD_CLASS_DEF_H__
|
||||
|
||||
#ifndef USB_MALLOC_ENABLE
|
||||
#define USB_MALLOC_ENABLE 0
|
||||
#endif
|
||||
#ifndef USB_HOST_ASYNC
|
||||
#define USB_HOST_ASYNC 1
|
||||
#endif
|
||||
#ifndef USB_H_MALLOC_ENABLE
|
||||
#define USB_H_MALLOC_ENABLE 1
|
||||
#endif
|
||||
#ifndef USB_DEVICE_CLASS_CONFIG
|
||||
#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS|MASSSTORAGE_CLASS)
|
||||
#endif
|
||||
|
||||
///////////MassStorage Class
|
||||
#ifndef MSD_BULK_EP_OUT
|
||||
#define MSD_BULK_EP_OUT 1
|
||||
#endif
|
||||
#ifndef MSD_BULK_EP_IN
|
||||
#define MSD_BULK_EP_IN 1
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_BULKOUT
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define MAXP_SIZE_BULKOUT 64
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define MAXP_SIZE_BULKOUT 512
|
||||
#endif
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_BULKIN
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define MAXP_SIZE_BULKIN 64
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define MAXP_SIZE_BULKIN 512
|
||||
#endif
|
||||
#endif
|
||||
#ifndef MSD_STR_INDEX
|
||||
#define MSD_STR_INDEX 7
|
||||
#endif
|
||||
|
||||
///////////HID class
|
||||
#ifndef HID_EP_IN
|
||||
#define HID_EP_IN 2
|
||||
#endif
|
||||
#ifndef HID_EP_OUT
|
||||
#define HID_EP_OUT 2
|
||||
#endif
|
||||
#ifndef HID_EP_IN_2
|
||||
#define HID_EP_IN_2 3
|
||||
#endif
|
||||
#ifndef HID_EP_OUT_2
|
||||
#define HID_EP_OUT_2 3
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_HIDOUT
|
||||
#define MAXP_SIZE_HIDOUT 16
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_HIDIN
|
||||
#define MAXP_SIZE_HIDIN 16
|
||||
#endif
|
||||
#ifndef HID_INTR_INTERVAL
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define HID_INTR_INTERVAL 1
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define HID_INTR_INTERVAL 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/////////////Audio Class
|
||||
#ifndef UAC_ISO_INTERVAL
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define UAC_ISO_INTERVAL 1
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define UAC_ISO_INTERVAL 4
|
||||
#endif
|
||||
#endif
|
||||
//speaker class
|
||||
#ifndef SPK_AUDIO_RATE
|
||||
#define SPK_AUDIO_RATE 48000
|
||||
#endif
|
||||
#ifndef SPK_AUDIO_RES
|
||||
#define SPK_AUDIO_RES 16
|
||||
#endif
|
||||
#ifndef SPK_CHANNEL
|
||||
#define SPK_CHANNEL 2
|
||||
#endif
|
||||
#ifndef SPK_FRAME_LEN
|
||||
#define SPK_FRAME_LEN (((SPK_AUDIO_RATE) * SPK_AUDIO_RES / 8 * SPK_CHANNEL)/1000+4)
|
||||
#endif
|
||||
#ifndef SPK_PCM_Type
|
||||
#define SPK_PCM_Type (SPK_AUDIO_RES >> 4) // 0=8 ,1=16
|
||||
#endif
|
||||
#ifndef SPK_AUDIO_TYPE
|
||||
#define SPK_AUDIO_TYPE (0x02 - SPK_PCM_Type) // TYPE1_PCM16
|
||||
#endif
|
||||
#ifndef SPK_ISO_EP_OUT
|
||||
#ifdef CONFIG_CPU_BR18
|
||||
#define SPK_ISO_EP_OUT 2
|
||||
#else
|
||||
#define SPK_ISO_EP_OUT 3
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SPEAKER_STR_INDEX
|
||||
#define SPEAKER_STR_INDEX 5
|
||||
#endif
|
||||
#ifndef SPK_INPUT_TERMINAL_ID
|
||||
#define SPK_INPUT_TERMINAL_ID 1
|
||||
#endif
|
||||
#ifndef SPK_FEATURE_UNIT_ID
|
||||
#define SPK_FEATURE_UNIT_ID 2
|
||||
#endif
|
||||
#ifndef SPK_OUTPUT_TERMINAL_ID
|
||||
#define SPK_OUTPUT_TERMINAL_ID 3
|
||||
#endif
|
||||
#ifndef SPK_SELECTOR_UNIT_ID
|
||||
#define SPK_SELECTOR_UNIT_ID 8
|
||||
#endif
|
||||
|
||||
/////////////Microphone Class
|
||||
#ifndef MIC_SamplingFrequency
|
||||
#define MIC_SamplingFrequency 1
|
||||
#endif
|
||||
|
||||
#if MIC_SamplingFrequency == 1
|
||||
#define MIC_AUDIO_RATE 48000
|
||||
#else
|
||||
#define MIC_AUDIO_RATE 192000
|
||||
#define MIC_AUDIO_RATE_1 44100
|
||||
#define MIC_AUDIO_RATE_2 48000
|
||||
#define MIC_AUDIO_RATE_4 96000
|
||||
#endif
|
||||
|
||||
#ifndef MIC_AUDIO_RES
|
||||
#define MIC_AUDIO_RES 16
|
||||
#endif
|
||||
#ifndef MIC_CHANNEL
|
||||
#define MIC_CHANNEL 1
|
||||
#endif
|
||||
#ifndef MIC_FRAME_LEN
|
||||
#define MIC_FRAME_LEN ((MIC_AUDIO_RATE * MIC_AUDIO_RES / 8 * MIC_CHANNEL)/1000)
|
||||
#endif
|
||||
#ifndef MIC_PCM_TYPE
|
||||
#define MIC_PCM_TYPE (MIC_AUDIO_RES >> 4) // 0=8 ,1=16
|
||||
#endif
|
||||
#ifndef MIC_AUDIO_TYPE
|
||||
#define MIC_AUDIO_TYPE (0x02 - MIC_PCM_TYPE)
|
||||
#endif
|
||||
#ifndef MIC_ISO_EP_IN
|
||||
#define MIC_ISO_EP_IN 3
|
||||
#endif
|
||||
#ifndef MIC_STR_INDEX
|
||||
#define MIC_STR_INDEX 6
|
||||
#endif
|
||||
#ifndef MIC_INPUT_TERMINAL_ID
|
||||
#define MIC_INPUT_TERMINAL_ID 4
|
||||
#endif
|
||||
#ifndef MIC_FEATURE_UNIT_ID
|
||||
#define MIC_FEATURE_UNIT_ID 5
|
||||
#endif
|
||||
#ifndef MIC_OUTPUT_TERMINAL_ID
|
||||
#define MIC_OUTPUT_TERMINAL_ID 6
|
||||
#endif
|
||||
#ifndef MIC_SELECTOR_UNIT_ID
|
||||
#define MIC_SELECTOR_UNIT_ID 7
|
||||
#endif
|
||||
|
||||
////////////CDC Class
|
||||
#ifndef CDC_DATA_EP_IN
|
||||
#define CDC_DATA_EP_IN 4
|
||||
#endif
|
||||
#ifndef CDC_DATA_EP_OUT
|
||||
#define CDC_DATA_EP_OUT 4
|
||||
#endif
|
||||
#ifndef CDC_INTR_EP_IN
|
||||
#define CDC_INTR_EP_IN 5
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_CDC_BULKIN
|
||||
#define MAXP_SIZE_CDC_BULKIN 64
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_CDC_BULKOUT
|
||||
#define MAXP_SIZE_CDC_BULKOUT 64
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_CDC_INTRIN
|
||||
#define MAXP_SIZE_CDC_INTRIN 8
|
||||
#endif
|
||||
#ifndef CDC_INTR_EP_ENABLE
|
||||
#define CDC_INTR_EP_ENABLE 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user