| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /*
- * Copyright (c) 2025, sakumisu
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "usbh_core.h"
- #include "usbh_serial.h"
- static rt_err_t rt_usbh_serial_open(struct rt_device *dev, rt_uint16_t oflag)
- {
- struct usbh_serial *serial;
- RT_ASSERT(dev != RT_NULL && dev->user_data != RT_NULL);
- serial = (struct usbh_serial *)dev->user_data;
- serial = usbh_serial_open(serial->hport->config.intf[serial->intf].devname, USBH_SERIAL_O_RDWR | USBH_SERIAL_O_NONBLOCK);
- if (serial == RT_NULL) {
- USB_LOG_ERR("serial open failed\n");
- return -RT_ERROR;
- }
- struct usbh_serial_termios termios;
- memset(&termios, 0, sizeof(termios));
- termios.baudrate = 115200;
- termios.stopbits = 0;
- termios.parity = 0;
- termios.databits = 8;
- termios.rtscts = false;
- termios.rx_timeout = 0;
- usbh_serial_control(serial, USBH_SERIAL_CMD_SET_ATTR, &termios);
- return RT_EOK;
- }
- static rt_err_t rt_usbh_serial_close(struct rt_device *dev)
- {
- struct usbh_serial *serial;
- RT_ASSERT(dev != RT_NULL && dev->user_data != RT_NULL);
- serial = (struct usbh_serial *)dev->user_data;
- usbh_serial_close(serial);
- return RT_EOK;
- }
- static rt_ssize_t rt_usbh_serial_read(struct rt_device *dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
- {
- struct usbh_serial *serial;
- RT_ASSERT(dev != RT_NULL && dev->user_data != RT_NULL);
- serial = (struct usbh_serial *)dev->user_data;
- return usbh_serial_read(serial, buffer, size);
- }
- static rt_ssize_t rt_usbh_serial_write(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
- {
- struct usbh_serial *serial;
- int ret = 0;
- rt_uint8_t *align_buf;
- RT_ASSERT(dev != RT_NULL && dev->user_data != RT_NULL);
- serial = (struct usbh_serial *)dev->user_data;
- align_buf = (rt_uint8_t *)buffer;
- if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
- align_buf = rt_malloc_align(USB_ALIGN_UP(size, CONFIG_USB_ALIGN_SIZE), CONFIG_USB_ALIGN_SIZE);
- if (!align_buf) {
- USB_LOG_ERR("serial get align buf failed\n");
- return 0;
- }
- usb_memcpy(align_buf, buffer, size);
- }
- ret = usbh_serial_write(serial, align_buf, size);
- if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
- rt_free_align(align_buf);
- }
- return ret;
- }
- static rt_err_t rt_usbh_serial_control(struct rt_device *dev,
- int cmd,
- void *args)
- {
- struct usbh_serial *serial;
- struct serial_configure *config;
- int ret = -RT_EINVAL;
- RT_ASSERT(dev != RT_NULL && dev->user_data != RT_NULL);
- serial = (struct usbh_serial *)dev->user_data;
- switch (cmd) {
- case RT_DEVICE_CTRL_CONFIG: {
- config = (struct serial_configure *)args;
- struct usbh_serial_termios termios;
- memset(&termios, 0, sizeof(termios));
- termios.baudrate = config->baud_rate;
- termios.stopbits = 0;
- termios.parity = config->parity;
- termios.databits = config->data_bits;
- termios.rtscts = false;
- termios.rx_timeout = 0;
- usbh_serial_control(serial, USBH_SERIAL_CMD_SET_ATTR, &termios);
- } break;
- default:
- break;
- }
- return ret;
- }
- #ifdef RT_USING_DEVICE_OPS
- const static struct rt_device_ops usbh_serial_ops = {
- NULL,
- rt_usbh_serial_open,
- rt_usbh_serial_close,
- rt_usbh_serial_read,
- rt_usbh_serial_write,
- rt_usbh_serial_control
- };
- #endif
- rt_err_t usbh_serial_register(struct usbh_serial *serial)
- {
- rt_err_t ret;
- struct rt_device *device;
- RT_ASSERT(serial != RT_NULL);
- device = rt_malloc(sizeof(struct rt_device));
- if (device == RT_NULL) {
- USB_LOG_ERR("serial device malloc failed\n");
- return -RT_ENOMEM;
- }
- memset(device, 0, sizeof(struct rt_device));
- device->type = RT_Device_Class_Char;
- device->rx_indicate = RT_NULL;
- device->tx_complete = RT_NULL;
- #ifdef RT_USING_DEVICE_OPS
- device->ops = &usbh_serial_ops;
- #else
- device->init = NULL;
- device->open = rt_usbh_serial_open;
- device->close = rt_usbh_serial_close;
- device->read = rt_usbh_serial_read;
- device->write = rt_usbh_serial_write;
- device->control = rt_usbh_serial_control;
- #endif
- device->user_data = serial;
- serial->user_data = device;
- /* skip /dev/ to avoid BAD file */
- const char *dev_name = serial->hport->config.intf[serial->intf].devname;
- if (strncmp(dev_name, "/dev/", 5) == 0) {
- dev_name += 5;
- }
- /* register a character device */
- ret = rt_device_register(device, dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_REMOVABLE);
- #ifdef RT_USING_POSIX_DEVIO
- /* set fops */
- device->fops = &usbh_serial_fops;
- #endif
- return ret;
- }
- void usbh_serial_unregister(struct usbh_serial *serial)
- {
- struct rt_device *device;
- RT_ASSERT(serial != NULL && serial->user_data != NULL);
- device = (struct rt_device *)serial->user_data;
- rt_device_unregister(device);
- rt_free(device);
- }
- void usbh_serial_run(struct usbh_serial *serial)
- {
- usbh_serial_register(serial);
- }
- void usbh_serial_stop(struct usbh_serial *serial)
- {
- usbh_serial_unregister(serial);
- }
|