mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-16 17:18:56 +00:00
219 lines
5.9 KiB
C
219 lines
5.9 KiB
C
/*
|
|
* Copyright (c) 2025, ArtInChip
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include "usbh_core.h"
|
|
// #include "usbh_serial.h"
|
|
|
|
#define DEV_FORMAT "/dev/ttyUSB%d"
|
|
|
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_serial_buf[USB_ALIGN_UP(64, CONFIG_USB_ALIGN_SIZE)];
|
|
|
|
#define CONFIG_USBHOST_MAX_SERIAL_CLASS 5
|
|
|
|
struct usbh_serial {
|
|
struct usbh_hubport *hport;
|
|
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
|
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
|
struct usbh_urb bulkout_urb;
|
|
struct usbh_urb bulkin_urb;
|
|
|
|
uint8_t intf;
|
|
uint8_t minor;
|
|
|
|
void *user_data;
|
|
};
|
|
|
|
static struct usbh_serial g_serial_class[CONFIG_USBHOST_MAX_SERIAL_CLASS];
|
|
static uint32_t g_devinuse = 0;
|
|
|
|
__WEAK void usbh_serial_run(struct usbh_serial *serial_class)
|
|
{
|
|
(void)serial_class;
|
|
}
|
|
|
|
__WEAK void usbh_serial_stop(struct usbh_serial *serial_class)
|
|
{
|
|
(void)serial_class;
|
|
}
|
|
|
|
static struct usbh_serial *usbh_serial_class_alloc(void)
|
|
{
|
|
uint8_t devno;
|
|
|
|
for (devno = 0; devno < CONFIG_USBHOST_MAX_SERIAL_CLASS; devno++) {
|
|
if ((g_devinuse & (1U << devno)) == 0) {
|
|
g_devinuse |= (1U << devno);
|
|
memset(&g_serial_class[devno], 0, sizeof(struct usbh_serial));
|
|
g_serial_class[devno].minor = devno;
|
|
return &g_serial_class[devno];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void usbh_serial_class_free(struct usbh_serial *serial_class)
|
|
{
|
|
uint8_t devno = serial_class->minor;
|
|
|
|
if (devno < 32) {
|
|
g_devinuse &= ~(1U << devno);
|
|
}
|
|
memset(serial_class, 0, sizeof(struct usbh_serial));
|
|
}
|
|
|
|
|
|
static int usbh_serial_connect(struct usbh_hubport *hport, uint8_t intf)
|
|
{
|
|
struct usb_endpoint_descriptor *ep_desc;
|
|
int ret = 0;
|
|
|
|
struct usbh_serial *serial_class = usbh_serial_class_alloc();
|
|
if (serial_class == NULL) {
|
|
USB_LOG_ERR("Fail to alloc serial_class\r\n");
|
|
return -USB_ERR_NOMEM;
|
|
}
|
|
|
|
serial_class->hport = hport;
|
|
serial_class->intf = intf;
|
|
|
|
hport->config.intf[intf].priv = serial_class;
|
|
|
|
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
|
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
|
|
|
if (ep_desc->bEndpointAddress & 0x80) {
|
|
USBH_EP_INIT(serial_class->bulkin, ep_desc);
|
|
} else {
|
|
USBH_EP_INIT(serial_class->bulkout, ep_desc);
|
|
}
|
|
}
|
|
|
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, serial_class->minor);
|
|
|
|
USB_LOG_INFO("Register Serial Class:%s\r\n", hport->config.intf[intf].devname);
|
|
|
|
usbh_serial_run(serial_class);
|
|
return ret;
|
|
}
|
|
|
|
static int usbh_serial_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
|
{
|
|
int ret = 0;
|
|
|
|
struct usbh_serial *serial_class = (struct usbh_serial *)hport->config.intf[intf].priv;
|
|
|
|
if (serial_class) {
|
|
if (serial_class->bulkin) {
|
|
usbh_kill_urb(&serial_class->bulkin_urb);
|
|
}
|
|
|
|
if (serial_class->bulkout) {
|
|
usbh_kill_urb(&serial_class->bulkout_urb);
|
|
}
|
|
|
|
if (hport->config.intf[intf].devname[0] != '\0') {
|
|
usb_osal_thread_schedule_other();
|
|
USB_LOG_INFO("Unregister Serial Class:%s\r\n", hport->config.intf[intf].devname);
|
|
usbh_serial_stop(serial_class);
|
|
}
|
|
|
|
usbh_serial_class_free(serial_class);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int usbh_serial_bulk_in_transfer(struct usbh_serial *serial_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
|
{
|
|
int ret;
|
|
struct usbh_urb *urb = &serial_class->bulkin_urb;
|
|
|
|
usbh_bulk_urb_fill(urb, serial_class->hport, serial_class->bulkin, buffer, buflen, timeout, NULL, NULL);
|
|
ret = usbh_submit_urb(urb);
|
|
if (ret == 0) {
|
|
ret = urb->actual_length;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int usbh_serial_bulk_out_transfer(struct usbh_serial *serial_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
|
|
{
|
|
int ret;
|
|
struct usbh_urb *urb = &serial_class->bulkout_urb;
|
|
|
|
usbh_bulk_urb_fill(urb, serial_class->hport, serial_class->bulkout, buffer, buflen, timeout, NULL, NULL);
|
|
ret = usbh_submit_urb(urb);
|
|
if (ret == 0) {
|
|
ret = urb->actual_length;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//ttyusb 0 AT
|
|
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX char serial_buffer[512];
|
|
int cmd_ttyusb_debug(int argc, char *argv[])
|
|
{
|
|
int ret;
|
|
struct usbh_serial *serial_class;
|
|
int len = 0;
|
|
|
|
char dev_name[20] = {0};
|
|
if (argc != 3) {
|
|
printf("ttyusb [NO] [AT]\n");
|
|
return -1;
|
|
}
|
|
|
|
snprintf(dev_name, 20, "/dev/ttyUSB%s", argv[1]);
|
|
|
|
while ((serial_class = (struct usbh_serial *)usbh_find_class_instance(dev_name)) == NULL) {
|
|
printf("Can't find name %s\n", dev_name);
|
|
return -1;
|
|
}
|
|
|
|
memset(serial_buffer, 0, 512);
|
|
strncpy(serial_buffer, argv[2], 511);
|
|
len = strlen(serial_buffer);
|
|
serial_buffer[len++] = '\r';
|
|
serial_buffer[len++] = '\n';
|
|
|
|
printf("%s send: %s\n", dev_name, serial_buffer);
|
|
ret = usbh_serial_bulk_out_transfer(serial_class, (uint8_t *)serial_buffer, len, 100);
|
|
if (ret < 0) {
|
|
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
|
return -1;
|
|
} else {
|
|
USB_LOG_RAW("send over:%d\r\n", serial_class->bulkout_urb.actual_length);
|
|
}
|
|
|
|
ret = usbh_serial_bulk_in_transfer(serial_class, (uint8_t *)serial_buffer, 512, 100);
|
|
if (ret < 0) {
|
|
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
|
return -1;
|
|
} else {
|
|
}
|
|
|
|
printf("%s receive: %s\n", dev_name, serial_buffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
MSH_CMD_EXPORT_ALIAS(cmd_ttyusb_debug, ttyusb, ttycmd);
|
|
|
|
const struct usbh_class_driver serial_class_driver = {
|
|
.driver_name = "serial",
|
|
.connect = usbh_serial_connect,
|
|
.disconnect = usbh_serial_disconnect
|
|
};
|
|
|
|
CLASS_INFO_DEFINE const struct usbh_class_info serial_class_info = {
|
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS,//USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
|
.class = 0xff,
|
|
.subclass = 0,
|
|
.protocol = 0,
|
|
.vid = 0,
|
|
.pid = 0,
|
|
.class_driver = &serial_class_driver
|
|
};
|