sim/usb: add sim usb device

Signed-off-by: zhangyuan21 <zhangyuan21@xiaomi.com>
This commit is contained in:
zhangyuan21 2022-12-01 09:54:11 +08:00 committed by Alan Carvalho de Assis
parent 699c930987
commit c61c694a77
14 changed files with 2700 additions and 0 deletions

View File

@ -605,4 +605,34 @@ config SIM_UART3_NAME
endmenu
config SIM_USB_DEV
bool "Linux USB Device"
select USBDEV
---help---
Build in support for simulated usb device
if SIM_USB_DEV
config SIM_USB_RAW_GADGET
bool "Simulated USB Raw Gadget Dev"
default n
depends on HOST_LINUX
---help---
Use USB Raw Gadget and Dummy HCD/UDC to set up virtual
USB Device and Host controller that connected to each
other inside the kernel.
Get Raw Gadget:
Get Raw Gadget code at https://github.com/xairy/raw-gadget.
Make Raw Gadget:
Run make in the raw_gadget and dummy_hcd directory. If raw_gadget
build fail, you need to check which register interface meets your
kenel version, usb_gadget_probe_driver or usb_gadget_register_driver.
Install Raw Gadget:
Run ./insmod.sh in the raw_gadget and dummy_hcd directory.
endif
endif # ARCH_SIM

View File

@ -198,6 +198,13 @@ ifeq ($(CONFIG_SIM_SPI_LINUX),y)
HOSTSRCS += sim_linuxspi.c
endif
ifeq ($(CONFIG_SIM_USB_DEV),y)
CSRCS += sim_usbdev.c
ifeq ($(CONFIG_SIM_USB_RAW_GADGET),y)
HOSTSRCS += sim_rawgadget.c
endif
endif
ifeq ($(CONFIG_RPTUN),y)
CSRCS += sim_rptun.c
endif

View File

@ -0,0 +1,903 @@
/****************************************************************************
* arch/sim/src/sim/posix/sim_rawgadget.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <pthread.h>
#include <linux/usb/ch9.h>
#include "sim_internal.h"
#include "sim_usbdev.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ERROR(fmt, ...) \
syslog(LOG_ERR, "sim_rawgadget: " fmt "\n", ##__VA_ARGS__)
#define INFO(fmt, ...) \
syslog(LOG_INFO, "sim_rawgadget: " fmt "\n", ##__VA_ARGS__)
#define DEBUG(fmt, ...)
#define USB_RAW_IOCTL_INIT _IOW('U', 0, struct usb_raw_init_s)
#define USB_RAW_IOCTL_RUN _IO('U', 1)
#define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event_s)
#define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io_s)
#define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io_s)
#define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor)
#define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32)
#define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io_s)
#define USB_RAW_IOCTL_EP_READ _IOWR('U', 8, struct usb_raw_ep_io_s)
#define USB_RAW_IOCTL_CONFIGURE _IO('U', 9)
#define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32)
#define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info_s)
#define USB_RAW_IOCTL_EP0_STALL _IO('U', 12)
#define USB_RAW_IOCTL_EP_SET_HALT _IOW('U', 13, __u32)
#define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32)
#define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32)
#define USB_RAW_EP_NUM(addr) ((addr) & USB_ENDPOINT_NUMBER_MASK)
#define USB_RAW_EP_DIR(addr) ((addr) & USB_ENDPOINT_DIR_MASK)
#define USB_RAW_EPS_NUM_MAX 30
#define USB_RAW_EP_NAME_MAX 16
#define USB_RAW_EP_ADDR_ANY 0xff
#define UDC_NAME_LENGTH_MAX 128
#define USB_RAW_EP0_MAX_LEN 256
#define USB_RAW_EP_MAX_LEN 1024
#define USB_RAW_RX_BUF_NUM 8
#define USB_RAW_DEVICE "dummy_udc.0"
#define USB_RAW_DRIVER "dummy_udc"
#define USB_RAW_FIFO_USED(fifo) ((fifo)->write - (fifo)->read)
#define USB_RAW_FIFO_UNUSED(fifo) ((fifo)->elem_num - USB_RAW_FIFO_USED(fifo))
#define USB_RAW_FIFO_MASK(fifo) ((fifo)->elem_num - 1)
#define USB_RAW_FIFO_PUSH(fifo) ((fifo)->write++)
#define USB_RAW_FIFO_POP(fifo) ((fifo)->read++)
/****************************************************************************
* Private Types
****************************************************************************/
enum usb_raw_event_type_e
{
USB_RAW_EVENT_INVALID,
USB_RAW_EVENT_CONNECT,
USB_RAW_EVENT_CONTROL,
};
struct usb_raw_init_s
{
uint8_t driver_name[UDC_NAME_LENGTH_MAX];
uint8_t device_name[UDC_NAME_LENGTH_MAX];
uint8_t speed;
};
struct usb_raw_event_s
{
uint32_t type;
uint32_t length;
uint8_t data[0];
};
struct usb_raw_ep_io_s
{
uint16_t ep;
uint16_t flags;
uint32_t length;
uint8_t data[0];
};
struct usb_raw_control_io_s
{
struct usb_raw_ep_io_s inner;
uint8_t data[USB_RAW_EP0_MAX_LEN];
};
struct usb_raw_data_io_s
{
struct usb_raw_ep_io_s inner;
uint8_t data[USB_RAW_EP_MAX_LEN];
};
struct usb_raw_ep_caps_s
{
uint32_t type_control : 1;
uint32_t type_iso : 1;
uint32_t type_bulk : 1;
uint32_t type_int : 1;
uint32_t dir_in : 1;
uint32_t dir_out : 1;
};
struct usb_raw_ep_limits_s
{
uint16_t maxpacket_limit;
uint16_t max_streams;
uint32_t reserved;
};
struct usb_raw_ep_info_s
{
uint8_t name[USB_RAW_EP_NAME_MAX];
uint32_t addr;
struct usb_raw_ep_caps_s caps;
struct usb_raw_ep_limits_s limits;
};
struct usb_raw_eps_info_s
{
struct usb_raw_ep_info_s eps[USB_RAW_EPS_NUM_MAX];
};
struct usb_raw_control_event_s
{
struct usb_raw_event_s inner;
struct usb_ctrlrequest ctrl;
};
struct usb_raw_fifo_s
{
uint16_t read;
uint16_t write;
uint16_t elem_size;
uint16_t elem_num;
uint8_t *elems;
};
struct usb_raw_ep_entry_s
{
bool halted;
uint16_t addr;
uint16_t raw_epaddr;
uint16_t raw_epid;
struct usb_raw_fifo_s fifo;
pthread_t ep_thread;
};
struct usb_raw_gadget_dev_t
{
int fd;
uint16_t eps_num;
pthread_t ep0_thread;
struct usb_raw_control_io_s ep0_ctrl;
struct usb_raw_ep_entry_s eps_entry[USB_RAW_EPS_NUM_MAX];
struct usb_raw_eps_info_s eps_info;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static struct usb_raw_gadget_dev_t g_raw_gadget_dev =
{
.fd = -1,
};
/****************************************************************************
* Private Functions
****************************************************************************/
static void host_raw_fifocreate(struct usb_raw_fifo_s *fifo,
uint16_t elem_size, uint16_t elem_num)
{
if (elem_num & (elem_num - 1))
{
ERROR("USB raw fifo num error");
return;
}
fifo->write = 0;
fifo->read = 0;
fifo->elem_size = elem_size;
fifo->elem_num = elem_num;
fifo->elems = (uint8_t *)malloc(elem_size * elem_num);
}
static void host_raw_fifodelete(struct usb_raw_fifo_s *fifo)
{
fifo->write = 0;
fifo->read = 0;
free(fifo->elems);
}
static uint8_t *host_raw_fiforead(struct usb_raw_fifo_s *fifo)
{
uint16_t r_idx;
if (USB_RAW_FIFO_USED(fifo) == 0)
{
return NULL;
}
r_idx = fifo->read & USB_RAW_FIFO_MASK(fifo);
return &fifo->elems[fifo->elem_size * r_idx];
}
static uint8_t *host_raw_fifoalloc(struct usb_raw_fifo_s *fifo)
{
uint16_t w_idx;
if (USB_RAW_FIFO_UNUSED(fifo) == 0)
{
ERROR("USB raw get fifo fail");
return NULL;
}
w_idx = fifo->write & USB_RAW_FIFO_MASK(fifo);
return &fifo->elems[fifo->elem_size * w_idx];
}
static int host_raw_open(void)
{
int fd = open("/dev/raw-gadget", O_RDWR);
if (fd < 0)
{
ERROR("open fail");
}
return fd;
}
static void host_raw_close(int fd)
{
if (fd >= 0)
{
close(fd);
}
}
static void host_raw_init(int fd, enum usb_device_speed speed,
const char *driver, const char *device)
{
struct usb_raw_init_s arg;
strcpy((char *)&arg.driver_name[0], driver);
strcpy((char *)&arg.device_name[0], device);
arg.speed = speed;
int rv = ioctl(fd, USB_RAW_IOCTL_INIT, &arg);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_INIT) fail");
}
}
static int host_raw_run(int fd)
{
int rv = ioctl(fd, USB_RAW_IOCTL_RUN, 0);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_RUN) fail");
}
return rv;
}
static int host_raw_eventfetch(int fd, struct usb_raw_event_s *event)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EVENT_FETCH, event);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EVENT_FETCH) fail");
}
return rv;
}
static int host_raw_ep0read(int fd, struct usb_raw_ep_io_s *io)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP0_READ, io);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP0_READ)");
}
return rv;
}
static int host_raw_ep0write(int fd, struct usb_raw_ep_io_s *io)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP0_WRITE, io);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP0_WRITE) fail");
}
return rv;
}
static int host_raw_epenable(int fd, struct usb_endpoint_descriptor *desc)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP_ENABLE, desc);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP_ENABLE) fail");
}
return rv;
}
static int host_raw_epdisable(int fd, uint8_t epno)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP_DISABLE, epno);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP_DISABLE) fail");
}
return rv;
}
static int host_raw_epread(int fd, struct usb_raw_ep_io_s *io)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP_READ, io);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP_READ) fail");
}
return rv;
}
static int host_raw_epwrite(int fd, struct usb_raw_ep_io_s *io)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP_WRITE, io);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP_WRITE) fail");
}
return rv;
}
static void host_raw_configure(int fd)
{
int rv = ioctl(fd, USB_RAW_IOCTL_CONFIGURE, 0);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_CONFIGURED) fail");
}
}
static void host_raw_vbusdraw(int fd, uint32_t power)
{
int rv = ioctl(fd, USB_RAW_IOCTL_VBUS_DRAW, power);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_VBUS_DRAW) fail");
}
}
static int host_raw_epsinfo(int fd, struct usb_raw_eps_info_s *info)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EPS_INFO, info);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EPS_INFO) fail");
}
return rv;
}
static int host_raw_ep0stall(int fd)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP0_STALL, 0);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP0_STALL) fail");
}
return rv;
}
static int host_raw_epsethalt(int fd, int ep)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP_SET_HALT, ep);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP_SET_HALT) fail");
}
return rv;
}
static int host_raw_epclearhalt(int fd, int ep)
{
int rv = ioctl(fd, USB_RAW_IOCTL_EP_CLEAR_HALT, ep);
if (rv < 0)
{
ERROR("ioctl(USB_RAW_IOCTL_EP_CLEAR_HALT) fail");
}
return rv;
}
static void
host_raw_setctrlreq(struct host_usb_ctrlreq_s *host_req,
const struct usb_ctrlrequest *raw_req)
{
host_req->type = raw_req->bRequestType;
host_req->req = raw_req->bRequest;
host_req->value = raw_req->wValue;
host_req->index = raw_req->wIndex;
host_req->len = raw_req->wLength;
}
static void
host_raw_getepdesc(struct usb_endpoint_descriptor *raw_epdesc,
const struct host_usb_epdesc_s *host_epdesc)
{
raw_epdesc->bLength = host_epdesc->len;
raw_epdesc->bDescriptorType = host_epdesc->type;
raw_epdesc->bEndpointAddress = host_epdesc->addr;
raw_epdesc->bmAttributes = host_epdesc->attr;
raw_epdesc->wMaxPacketSize = host_epdesc->mxpacketsize;
raw_epdesc->bInterval = host_epdesc->interval;
}
static int host_raw_connecthandle(struct usb_raw_gadget_dev_t *dev)
{
struct usb_raw_eps_info_s *info = &dev->eps_info;
int i;
memset(info, 0, sizeof(struct usb_raw_eps_info_s));
dev->eps_num = host_raw_epsinfo(dev->fd, info);
for (i = 0; i < dev->eps_num; i++)
{
INFO("ep #%d:", i);
INFO(" name: %s", &info->eps[i].name[0]);
INFO(" addr: %u", info->eps[i].addr);
INFO(" type: %s %s %s",
info->eps[i].caps.type_iso ? "iso" : "___",
info->eps[i].caps.type_bulk ? "blk" : "___",
info->eps[i].caps.type_int ? "int" : "___");
INFO(" dir : %s %s",
info->eps[i].caps.dir_in ? "in " : "___",
info->eps[i].caps.dir_out ? "out" : "___");
INFO(" maxpacket_limit: %u",
info->eps[i].limits.maxpacket_limit);
INFO(" max_streams: %u", info->eps[i].limits.max_streams);
}
return 0;
}
static bool
host_raw_check_epaddress(struct usb_endpoint_descriptor *epd)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
struct usb_raw_eps_info_s *eps_info = &dev->eps_info;
uint16_t ep_cnt;
for (ep_cnt = 0; ep_cnt < dev->eps_num; ep_cnt++)
{
struct usb_raw_ep_info_s *ep = &eps_info->eps[ep_cnt];
if (ep->addr != USB_RAW_EP_NUM(epd->bEndpointAddress) &&
ep->addr != USB_RAW_EP_ADDR_ANY)
{
continue;
}
if ((usb_endpoint_dir_in(epd) && !ep->caps.dir_in) ||
(usb_endpoint_dir_out(epd) && !ep->caps.dir_out))
{
continue;
}
if ((usb_endpoint_type(epd) == USB_ENDPOINT_XFER_BULK &&
!ep->caps.type_bulk) ||
(usb_endpoint_type(epd) == USB_ENDPOINT_XFER_INT &&
!ep->caps.type_int) ||
(usb_endpoint_type(epd) == USB_ENDPOINT_XFER_ISOC &&
!ep->caps.type_iso))
{
continue;
}
return true;
}
return false;
}
static int host_raw_ctrlhandle(struct usb_raw_gadget_dev_t *dev,
struct usb_raw_control_event_s *event)
{
struct usb_raw_ep_entry_s *entry = &dev->eps_entry[0];
struct usb_raw_ep_io_s *io = &dev->ep0_ctrl.inner;
struct host_usb_ctrlreq_s *host_ctrl_req;
int ret = -1;
host_ctrl_req = (struct host_usb_ctrlreq_s *)
host_raw_fifoalloc(&entry->fifo);
if (!host_ctrl_req)
{
ERROR("EP0 get raw fifo error");
return ret;
}
host_raw_setctrlreq(host_ctrl_req, &event->ctrl);
if (!(event->ctrl.bRequestType & USB_DIR_IN))
{
io->ep = 0;
io->flags = 0;
io->length = USB_RAW_EP0_MAX_LEN;
ret = host_raw_ep0read(dev->fd, io);
if (ret < 0)
{
ERROR("EP0 read out data error");
return ret;
}
memcpy(host_ctrl_req->data, io->data, ret);
}
USB_RAW_FIFO_PUSH(&entry->fifo);
return ret;
}
static void *host_raw_ep0handle(void *arg)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
struct usb_raw_ep_entry_s *entry = &dev->eps_entry[0];
struct usb_raw_control_event_s event;
while (dev->fd >= 0)
{
event.inner.type = 0;
event.inner.length = sizeof(event.ctrl);
if (host_raw_eventfetch(dev->fd, &event.inner) < 0)
{
ERROR("EP0 event fetch fail.");
continue;
}
if (event.inner.type == USB_RAW_EVENT_CONNECT)
{
host_raw_connecthandle(dev);
}
else if (event.inner.type == USB_RAW_EVENT_CONTROL)
{
host_raw_ctrlhandle(dev, &event);
}
else
{
ERROR("EP0 receive wrong event.");
}
}
host_raw_fifodelete(&entry->fifo);
return NULL;
}
static void *host_raw_ephandle(void *arg)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
struct usb_raw_ep_entry_s *entry = arg;
struct usb_raw_data_io_s *io;
while (dev->fd >= 0)
{
io = (struct usb_raw_data_io_s *)
host_raw_fifoalloc(&entry->fifo);
if (io)
{
if (entry->halted)
{
host_raw_epclearhalt(dev->fd, entry->raw_epid);
entry->halted = false;
}
io->inner.ep = entry->raw_epid;
io->inner.flags = 0;
io->inner.length = USB_RAW_EP_MAX_LEN;
io->inner.length = host_raw_epread(dev->fd, &io->inner);
USB_RAW_FIFO_PUSH(&entry->fifo);
}
else
{
if (!entry->halted)
{
host_raw_epsethalt(dev->fd, entry->raw_epid);
entry->halted = true;
}
usleep(10);
}
}
host_raw_fifodelete(&entry->fifo);
return NULL;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int host_usbdev_init(uint32_t speed)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
const char *device = USB_RAW_DEVICE;
const char *driver = USB_RAW_DRIVER;
int fd;
fd = host_raw_open();
if (fd < 0)
{
ERROR("USB raw open error");
return -1;
}
host_raw_init(fd, speed, driver, device);
host_raw_run(fd);
host_raw_vbusdraw(fd, 0x32);
host_raw_configure(fd);
dev->fd = fd;
host_raw_fifocreate(&dev->eps_entry[0].fifo,
(sizeof(struct host_usb_ctrlreq_s)
+ USB_RAW_EP0_MAX_LEN),
USB_RAW_RX_BUF_NUM);
return pthread_create(&dev->ep0_thread, NULL,
host_raw_ep0handle, NULL);
}
int host_usbdev_deinit(void)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
host_raw_close(dev->fd);
return 0;
}
int host_usbdev_epconfig(uint8_t epno,
const struct host_usb_epdesc_s *epdesc)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
struct usb_endpoint_descriptor raw_epdesc;
struct usb_raw_ep_entry_s *entry;
int ret = -1;
if (dev->fd < 0)
{
ERROR("USB raw not enable");
return ret;
}
if (epno > USB_RAW_EPS_NUM_MAX)
{
ERROR("USB raw ep num error");
return ret;
}
if (epdesc->mxpacketsize > USB_RAW_EP_MAX_LEN)
{
ERROR("USB raw ep max packet size error");
return ret;
}
host_raw_getepdesc(&raw_epdesc, epdesc);
if (!host_raw_check_epaddress(&raw_epdesc))
{
ERROR("USB raw check ep address fail");
return ret;
}
ret = host_raw_epenable(dev->fd, &raw_epdesc);
if (ret < 0)
{
ERROR("USB raw ep enable fail");
return ret;
}
entry = &dev->eps_entry[epno];
entry->addr = epdesc->addr;
entry->raw_epaddr = raw_epdesc.bEndpointAddress;
entry->raw_epid = ret;
entry->halted = false;
if (USB_RAW_EP_DIR(epdesc->addr) == USB_DIR_OUT)
{
host_raw_fifocreate(&entry->fifo,
sizeof(struct usb_raw_data_io_s),
USB_RAW_RX_BUF_NUM);
ret = pthread_create(&entry->ep_thread, NULL,
host_raw_ephandle,
(void *)entry);
}
return ret;
}
int host_usbdev_epdisable(uint8_t epno)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
int ret = -1;
if (dev->fd >= 0)
{
struct usb_raw_ep_entry_s *entry = &dev->eps_entry[epno];
ret = host_raw_epdisable(dev->fd, entry->raw_epid);
}
return ret;
}
int host_usbdev_pullup(bool enable)
{
/* not support */
return -1;
}
int host_usbdev_epstall(uint8_t epno, bool resume)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
int ret = -1;
if (dev->fd >= 0)
{
if (!resume && epno == 0)
{
ret = host_raw_ep0stall(dev->fd);
}
}
return ret;
}
int host_usbdev_epcancel(uint8_t epno)
{
/* not support */
return -1;
}
int host_usbdev_epwrite(uint8_t epno, uint8_t flags,
uint8_t *data, uint16_t len)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
struct usb_raw_ep_entry_s *entry;
struct usb_raw_ep_io_s *io;
int ret = -1;
if (dev->fd < 0)
{
ERROR("USB raw not enable");
return -1;
}
if (epno > USB_RAW_EPS_NUM_MAX)
{
ERROR("USB raw ep num error");
return ret;
}
entry = &dev->eps_entry[epno];
io = malloc(sizeof(struct usb_raw_ep_io_s) + len);
if (!io)
{
ERROR("Host usb malloc ep write io fail");
return -1;
}
io->flags = flags;
io->length = len;
io->ep = entry->raw_epid;
memcpy(io->data, data, len);
if (epno == 0)
{
ret = host_raw_ep0write(dev->fd, io);
}
else
{
ret = host_raw_epwrite(dev->fd, io);
}
free(io);
return ret;
}
uint8_t *host_usbdev_epread(uint8_t epno, uint16_t *len)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
struct usb_raw_ep_entry_s *entry;
struct usb_raw_ep_io_s *io;
if (dev->fd < 0)
{
ERROR("USB raw not enable");
return NULL;
}
if (epno > USB_RAW_EPS_NUM_MAX)
{
ERROR("USB raw ep num error");
return NULL;
}
entry = &dev->eps_entry[epno];
io = (struct usb_raw_ep_io_s *)
host_raw_fiforead(&entry->fifo);
if (io)
{
*len = io->length;
return io->data;
}
return NULL;
}
struct host_usb_ctrlreq_s *host_usbdev_ep0read(void)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
if (dev->fd < 0)
{
ERROR("USB raw not enable");
return NULL;
}
return (struct host_usb_ctrlreq_s *)
host_raw_fiforead(&dev->eps_entry[0].fifo);
}
void host_usbdev_epread_end(uint8_t epno)
{
struct usb_raw_gadget_dev_t *dev = &g_raw_gadget_dev;
USB_RAW_FIFO_POP(&dev->eps_entry[epno].fifo);
}

View File

@ -203,6 +203,10 @@ static int sim_loop_task(int argc, char **argv)
sim_video_loop();
#endif
#ifdef CONFIG_SIM_USB_DEV
sim_usbdev_loop();
#endif
#ifdef CONFIG_MOTOR_FOC_DUMMY
/* Update simulated FOC device */
@ -289,6 +293,10 @@ void up_initialize(void)
audio_register("pcm1c", sim_audio_initialize(false, true));
#endif
#ifdef CONFIG_SIM_USB_DEV
sim_usbdev_initialize();
#endif
kthread_create("loop_task", SCHED_PRIORITY_MAX,
CONFIG_DEFAULT_TASK_STACKSIZE,
sim_loop_task, NULL);

View File

@ -383,6 +383,13 @@ int sim_video_initialize(void);
void sim_video_loop(void);
#endif
/* sim_usbdev.c *************************************************************/
#ifdef CONFIG_SIM_USB_DEV
void sim_usbdev_initialize(void);
int sim_usbdev_loop(void);
#endif
/* Debug ********************************************************************/
#ifdef CONFIG_STACK_COLORATION

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
/****************************************************************************
* arch/sim/src/sim/sim_usbdev.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_SIM_SRC_SIM_USB_DEV_H
#define __ARCH_SIM_SRC_SIM_USB_DEV_H
/****************************************************************************
* Included Files
****************************************************************************/
#ifdef __SIM__
#include "config.h"
#endif
#include <stdint.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/* NuttX Endpoint descriptor */
struct host_usb_epdesc_s
{
uint8_t len; /* Descriptor length */
uint8_t type; /* Descriptor type */
uint8_t addr; /* Endpoint address */
uint8_t attr; /* Endpoint attributes */
uint16_t mxpacketsize; /* Maximum packet size */
uint8_t interval; /* Interval */
};
/* This structure is used to send control requests to a USB device. */
struct host_usb_ctrlreq_s
{
uint8_t type; /* Matches request type */
uint8_t req; /* Matches request field */
uint16_t value;
uint16_t index;
uint16_t len;
uint8_t data[0];
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Host USB Interface */
int host_usbdev_init(uint32_t speed);
int host_usbdev_deinit(void);
int host_usbdev_pullup(bool enable);
int host_usbdev_epconfig(uint8_t epno,
const struct host_usb_epdesc_s *epdesc);
int host_usbdev_epdisable(uint8_t epno);
int host_usbdev_epstall(uint8_t epno, bool resume);
int host_usbdev_epcancel(uint8_t epno);
int host_usbdev_epwrite(uint8_t epno, uint8_t flags,
uint8_t *data, uint16_t len);
struct host_usb_ctrlreq_s *host_usbdev_ep0read(void);
uint8_t *host_usbdev_epread(uint8_t epno, uint16_t *len);
void host_usbdev_epread_end(uint8_t epno);
#endif /* __ARCH_SIM_SRC_SIM_USB_DEV_H */

View File

@ -59,4 +59,13 @@ config SIM_WTGAHRS2_UARTN
We can select the number according to which SIM_UARTX_NAME is used to sensor.
This range is 0-4.
config SIM_RNDIS_MACADDR
hex "RNDIS MAC address"
default 0xfadedeadbeef
depends on RNDIS
---help---
If the hardware has no built-in MAC address then the fixed,
software-assigned MAC address MAC address must provided
with this selection.
endif

View File

@ -1435,3 +1435,117 @@ wamr
[0]crcfinal : 0xa14c
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 5.000000 / Clang 15.0.7 Using NuttX compilation options / Defined by the NuttX configuration
usbdev
This is a configuration with sim usbdev support.
1. Raw Gadget setup
Get Raw Gadget:
Get Raw Gadget code at https://github.com/xairy/raw-gadget.
Make Raw Gadget:
Run make in the raw_gadget and dummy_hcd directory. If raw_gadget build
fail, you need to check which register interface meets your kenel version,
usb_gadget_probe_driver or usb_gadget_register_driver.
Install Raw Gadget:
Run ./insmod.sh in the raw_gadget and dummy_hcd directory.
2. Configuration
sim:usbdev contains two different sets of composite devices:
conn0: adb & rndis
conn1: cdcacm & cdcecm
You can use the sim:usbdev configuration:
./tools/configure.sh sim:usbdev
3. How to run
Run nuttx with root mode, then you can use it as the following:
1> Run ADB:
NuttX enter command:
$ conn 0
$ adbd &
Host PC enter the ADB command:
$ adb kill-server
$ adb devices
List of devices attached
* daemon not running; starting now at tcp:5037
* daemon started successfully
0101 device
If ADB connection fails, make sure the udev rule is added correctly.
Edit /etc/udev/rules.d/51-android.rules file and add the following to it:
SUBSYSTEM=="usb", ATTR{idVendor}=="1630", ATTR{idProduct}=="0042", MODE="0666", GROUP="plugdev"
Then you can use commands such as adb shell, adb push, adb pull as normal.
2> Run RNDIS:
NuttX enter command:
$ conn 0
$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:00:00:00:00:00 at UP
inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
$ dhcpd_start eth0
eth0 Link encap:Ethernet HWaddr 00:00:00:00:00:00 at UP
inet addr:10.0.0.1 DRaddr:10.0.0.1 Mask:255.255.255.0
Host PC, you can see the network device named usb0:
$ ifconfig
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 602
inet 10.0.0.4 netmask 255.255.255.0 broadcast 10.0.0.255
ether 36:50:3d:62:b5:80 txqueuelen 1000 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 43 bytes 8544 (8.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Then you can test the network connection using the ping command or telnet.
3> Run CDCACM:
NuttX enter command:
$ conn 1
If the connection is successful, you can see /dev/ttyACM devices on both NuttX
and host PC.
Then you can use echo and cat command to test:
NuttX:
nsh> echo hello > /dev/ttyACM0
Host PC:
$ cat /dev/ttyACM0
hello
3> Run CDCECM:
NuttX enter command:
$ conn 1
$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:e0:de:ad:be:ef at UP
inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
$ dhcpd_start eth0
$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:e0:de:ad:be:ef at UP
inet addr:10.0.0.1 DRaddr:10.0.0.1 Mask:255.255.255.0
Host PC, you can see the network device named enx020000112233:
$ ifconfig
enx020000112233: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 576
inet 10.0.0.4 netmask 255.255.255.0 broadcast 10.0.0.255
ether 02:00:00:11:22:33 txqueuelen 1000 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 58 bytes 9143 (9.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Then you can test the network connection using the ping command or telnet.

View File

@ -0,0 +1,82 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_SIM_UART_DMA is not set
CONFIG_ADBD_FILE_SERVICE=y
CONFIG_ADBD_FILE_SYMLINK=y
CONFIG_ADBD_SHELL_SERVICE=y
CONFIG_ADBD_USB_SERVER=y
CONFIG_ARCH="sim"
CONFIG_ARCH_BOARD="sim"
CONFIG_ARCH_BOARD_SIM=y
CONFIG_ARCH_CHIP="sim"
CONFIG_ARCH_SIM=y
CONFIG_BOARDCTL_POWEROFF=y
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BUILTIN=y
CONFIG_CDCACM=y
CONFIG_CDCACM_COMPOSITE=y
CONFIG_CDCECM_COMPOSITE=y
CONFIG_COMPOSITE_IAD=y
CONFIG_COMPOSITE_PRODUCTID=0x0042
CONFIG_COMPOSITE_VENDORID=0x1630
CONFIG_DEBUG_ERROR=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_SCHED=y
CONFIG_DEBUG_SCHED_ERROR=y
CONFIG_DEBUG_SCHED_WARN=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEBUG_USB=y
CONFIG_DEBUG_USB_ERROR=y
CONFIG_DEBUG_USB_INFO=y
CONFIG_DEBUG_USB_WARN=y
CONFIG_DEBUG_WARN=y
CONFIG_EXAMPLES_DHCPD=y
CONFIG_FS_PROCFS=y
CONFIG_FS_TMPFS=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_LIBC_DLFCN=y
CONFIG_LIBUV=y
CONFIG_NETUTILS_DHCPD=y
CONFIG_NETUTILS_TELNETC=y
CONFIG_NETUTILS_TELNETD=y
CONFIG_NET_BROADCAST=y
CONFIG_NET_CDCECM=y
CONFIG_NET_ICMP=y
CONFIG_NET_ICMP_SOCKET=y
CONFIG_NET_LL_GUARDSIZE=50
CONFIG_NET_SOCKOPTS=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_RNDIS=y
CONFIG_RNDIS_COMPOSITE=y
CONFIG_SCHED_CHILD_STATUS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_SIM_USB_DEV=y
CONFIG_SIM_USB_RAW_GADGET=y
CONFIG_SYSLOG_CHARDEV=y
CONFIG_SYSLOG_MAX_CHANNELS=2
CONFIG_SYSTEM_ADBD=y
CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_COMPOSITE=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_TESTING_OSTEST=y
CONFIG_TLS_TASK_NELEM=4
CONFIG_USBADB=y
CONFIG_USBADB_COMPOSITE=y
CONFIG_USBDEV_COMPOSITE=y
CONFIG_USBDEV_DUALSPEED=y

View File

@ -67,4 +67,8 @@ ifeq ($(CONFIG_MOTOR_FOC_DUMMY),y)
CSRCS += sim_foc.c
endif
ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
CSRCS += sim_composite.c
endif
include $(TOPDIR)/boards/Board.mk

View File

@ -53,6 +53,8 @@
#include <nuttx/wireless/bluetooth/bt_null.h>
#include <nuttx/wireless/bluetooth/bt_uart_shim.h>
#include <nuttx/wireless/ieee802154/ieee802154_loopback.h>
#include <nuttx/usb/adb.h>
#include <nuttx/usb/rndis.h>
#ifdef CONFIG_LCD_DEV
#include <nuttx/lcd/lcd_dev.h>
@ -496,5 +498,22 @@ int sim_bringup(void)
rc_dummy_initialize(0);
#endif
#if defined(CONFIG_USBADB) && !defined(CONFIG_USBADB_COMPOSITE)
usbdev_adb_initialize();
#endif
#if defined(CONFIG_RNDIS) && !defined(CONFIG_RNDIS_COMPOSITE)
/* Set up a MAC address for the RNDIS device. */
uint8_t mac[6];
mac[0] = (CONFIG_SIM_RNDIS_MACADDR >> (8 * 5)) & 0xff;
mac[1] = (CONFIG_SIM_RNDIS_MACADDR >> (8 * 4)) & 0xff;
mac[2] = (CONFIG_SIM_RNDIS_MACADDR >> (8 * 3)) & 0xff;
mac[3] = (CONFIG_SIM_RNDIS_MACADDR >> (8 * 2)) & 0xff;
mac[4] = (CONFIG_SIM_RNDIS_MACADDR >> (8 * 1)) & 0xff;
mac[5] = (CONFIG_SIM_RNDIS_MACADDR >> (8 * 0)) & 0xff;
usbdev_rndis_initialize(mac);
#endif
return ret;
}

View File

@ -0,0 +1,260 @@
/****************************************************************************
* boards/sim/sim/sim/src/sim_composite.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/board.h>
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/adb.h>
#include <nuttx/usb/rndis.h>
#include <nuttx/usb/cdcacm.h>
#include <nuttx/usb/cdcecm.h>
#include <nuttx/usb/composite.h>
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: board_composite0_connect
*
* Description:
* Connect the USB composite device on the specified USB device port for
* configuration 0.
*
* Input Parameters:
* port - The USB device port.
*
* Returned Value:
* A non-NULL handle value is returned on success. NULL is returned on
* any failure.
*
****************************************************************************/
static void *board_composite0_connect(int port)
{
struct composite_devdesc_s dev[2];
int ifnobase = 0;
int strbase = COMPOSITE_NSTRIDS - 1;
int dev_idx = 0;
#ifdef CONFIG_RNDIS
/* Configure the RNDIS USB device */
usbdev_rndis_get_composite_devdesc(&dev[dev_idx]);
/* Interfaces */
dev[dev_idx].devinfo.ifnobase = ifnobase;
dev[dev_idx].minor = 0;
/* Strings */
dev[dev_idx].devinfo.strbase = strbase;
/* Endpoints */
dev[dev_idx].devinfo.epno[RNDIS_EP_BULKIN_IDX] = 1;
dev[dev_idx].devinfo.epno[RNDIS_EP_BULKOUT_IDX] = 2;
dev[dev_idx].devinfo.epno[RNDIS_EP_INTIN_IDX] = 5;
/* Count up the base numbers */
ifnobase += dev[dev_idx].devinfo.ninterfaces;
strbase += dev[dev_idx].devinfo.nstrings;
dev_idx += 1;
#endif
#ifdef CONFIG_USBADB
/* Configure the ADB USB device */
usbdev_adb_get_composite_devdesc(&dev[dev_idx]);
/* Interfaces */
dev[dev_idx].devinfo.ifnobase = ifnobase;
dev[dev_idx].minor = 0;
/* Strings */
dev[dev_idx].devinfo.strbase = strbase;
/* Endpoints */
dev[dev_idx].devinfo.epno[USBADB_EP_BULKIN_IDX] = 6;
dev[dev_idx].devinfo.epno[USBADB_EP_BULKOUT_IDX] = 7;
/* Count up the base numbers */
ifnobase += dev[dev_idx].devinfo.ninterfaces;
strbase += dev[dev_idx].devinfo.nstrings;
dev_idx += 1;
#endif
return composite_initialize(dev_idx, dev);
}
/****************************************************************************
* Name: board_composite1_connect
*
* Description:
* Connect the USB composite device on the specified USB device port for
* configuration 1.
*
* Input Parameters:
* port - The USB device port.
*
* Returned Value:
* A non-NULL handle value is returned on success. NULL is returned on
* any failure.
*
****************************************************************************/
static void *board_composite1_connect(int port)
{
struct composite_devdesc_s dev[2];
int ifnobase = 0;
int strbase = COMPOSITE_NSTRIDS - 1;
int dev_idx = 0;
#ifdef CONFIG_CDCACM
/* Configure the CDC/ACM device */
cdcacm_get_composite_devdesc(&dev[dev_idx]);
/* The callback functions for the CDC/ACM class */
dev[dev_idx].classobject = cdcacm_classobject;
dev[dev_idx].uninitialize = cdcacm_uninitialize;
/* Interfaces */
dev[dev_idx].devinfo.ifnobase = ifnobase;
dev[dev_idx].minor = 0;
/* Strings */
dev[dev_idx].devinfo.strbase = strbase;
/* Endpoints */
dev[dev_idx].devinfo.epno[CDCACM_EP_INTIN_IDX] = 5;
dev[dev_idx].devinfo.epno[CDCACM_EP_BULKIN_IDX] = 6;
dev[dev_idx].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 7;
/* Count up the base numbers */
ifnobase += dev[dev_idx].devinfo.ninterfaces;
strbase += dev[dev_idx].devinfo.nstrings;
dev_idx += 1;
#endif
#ifdef CONFIG_NET_CDCECM
/* Configure the CDC/ECM device */
cdcecm_get_composite_devdesc(&dev[dev_idx]);
/* Interfaces */
dev[dev_idx].devinfo.ifnobase = ifnobase;
dev[dev_idx].minor = 0;
/* Strings */
dev[dev_idx].devinfo.strbase = strbase;
/* Endpoints */
dev[dev_idx].devinfo.epno[CDCECM_EP_INTIN_IDX] = 10;
dev[dev_idx].devinfo.epno[CDCECM_EP_BULKIN_IDX] = 11;
dev[dev_idx].devinfo.epno[CDCECM_EP_BULKOUT_IDX] = 12;
/* Count up the base numbers */
ifnobase += dev[dev_idx].devinfo.ninterfaces;
strbase += dev[dev_idx].devinfo.nstrings;
dev_idx += 1;
#endif
return composite_initialize(dev_idx, dev);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_composite_initialize
*
* Description:
* Perform architecture specific initialization of a composite USB device.
*
****************************************************************************/
int board_composite_initialize(int port)
{
return OK;
}
/****************************************************************************
* Name: board_composite_connect
*
* Description:
* Connect the USB composite device on the specified USB device port using
* the specified configuration. The interpretation of the configid is
* board specific.
*
* Input Parameters:
* port - The USB device port.
* configid - The USB composite configuration
*
* Returned Value:
* A non-NULL handle value is returned on success. NULL is returned on
* any failure.
*
****************************************************************************/
void *board_composite_connect(int port, int configid)
{
if (configid == 0)
{
return board_composite0_connect(port);
}
else
{
return board_composite1_connect(port);
}
}
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */

View File

@ -505,6 +505,22 @@ static const char *g_white_list[] =
"NimMain",
/* Ref:
* sim/posix/sim_rawgadget.c
*/
"bRequestType",
"bRequest",
"wValue",
"wIndex",
"wLength",
"bLength",
"bDescriptorType",
"bEndpointAddress",
"bmAttributes",
"wMaxPacketSize",
"bInterval",
NULL
};