0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

USB Gadget serial应用实例(上)

麦辣鸡腿堡 来源:嵌入式Linux系统开发 作者:嵌入式Linux系统开 2023-07-13 11:06 次阅读

1. 硬件体验

使用 Linux 自带的 USB Gadget 驱动 /drivers/usb/gadget/legacy/serial.c

使用 USB 线,连接板子的 OTG 口和 PC 的 USB 口。

然后在板子加载驱动程序后,可以看到新的设备节点 /dev/ttyGS0:

# modprobe g_serial
g_serial gadget: Gadget Serial v2.4
g_serial gadget: g_serial ready
g_serial gadget: high-speed config #2: CDC ACM config

# ls /dev/ttyGS0 -l
crw-rw----    1 root     dialout   246,   0 Jan  1 00:30 /dev/ttyGS0

在 PC 上,如果是 Windows 系统,可以在设备管理器里看到新的 USB 串口:

图片

在 PC 上,如果是 VMware 上的 Linux 系统,按下图操作,先把 USB 串口连接到 VMware:

图片

然后在 PC Linux 中可以看到新的设备节点:

book@100ask:~$ dmesg
[  286.903239] usb 1-1: new high-speed USB device number 2 using ehci-pci
[  287.254549] usb 1-1: New USB device found, idVendor=0525, idProduct=a4a7, bcdDevice= 4.09
[  287.254550] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  287.254551] usb 1-1: Product: Gadget Serial v2.4
[  287.254552] usb 1-1: Manufacturer: Linux 4.9.88 with 2184000.usb
[  287.342786] cdc_acm 1-1:2.0: ttyACM0: USB ACM device
[  287.343202] usbcore: registered new interface driver cdc_acm
[  287.343202] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
book@100ask:~$ ls /dev/ttyACM0 -l
crw-rw---- 1 root dialout 166, 0 Mar  5 22:38 /dev/ttyACM0

2. Serial分析

2.1 软件框架

Gadget 串口的框架如下:

图片

u_serial 提供了有 2 种方法来使用 Gadget 串口:

  • u_serial.c 里注册 tty_driver 结构体 gs_tty_driver,在板子上编写 APP 访问设备 /dev/ttyGS0 即可与 Host 交互(Host 要打开 USB 串口)

图片

  • u_serial.c 里注册 console 结构体 gserial_cons。启动 Linux 内核时传入 commandline 参数"console=ttyGS0"后,内核的 printk 的信息通过 Gadget 串口打印出来(Host 要打开 USB 串口):

图片

注册 TTY 和 console 的过程:

gs_bind // driversusbgadgetlegacyserial.c
    status  = serial_register_ports(cdev, &serial_config_driver,"acm");
       fi_serial[i] = usb_get_function_instance(f_name);
 
acm_alloc_instance // driversusbgadgetfunctionf_acm.c
 ret = gserial_alloc_line(&opts- >port_num); // driversusbgadgetfunctionu_serial.c
 
   // 注册TTY
   tty_dev = tty_port_register_device(&ports[port_num].port- >port,
             gs_tty_driver, port_num, NULL);

   // 注册console
   gserial_console_init();
             register_console(&gserial_cons);

2.2 数据传输

2.2.1 APP 访问

注意,在 USB 中数据传输总是由 Host 发起,所以:

  • 板子要事先准备好空间(设置好 out 方向的 usb_request 并放入队列),以便接收 Host 发来的数据;
  • 板子有数据想发送给 Host 时需要设置 in 方向的 usb_request,以便 Host 读取。

板子上的 APP 访问 /dev/ttyGS0 时,就会导致 gs_tty_ops 结构体的对应函数被调用:

图片

APP 调用 open 函数时,会导致如下调用:

gs_open
 gs_start_io(port);
  // 取出 out 端点(对应 Host 来说是 out, 对于板子来说就是输入)
  struct usb_ep  *ep = port- >port_usb- >out;
  
  // 给 out 端点分配 usb_request
        status = gs_alloc_requests(ep, head, gs_read_complete,&port- >read_allocated);

  // 给 in 端点分配 usb_request, 但是在 open 时并没有把 in 方向的 usb_request 放入队列
        status = gs_alloc_requests(port- >port_usb- >in, &port- >write_pool,gs_write_complete, &port- >write_allocated);

        // 把 usb_request 放入队列, 如果 Host 发来数据, 这个 usb_request 的 complete 函数被调用
  started = gs_start_rx(port);
     status = usb_ep_queue(out, req, GFP_ATOMIC);

APP 调用 write 函数时,会导致如下调用:

gs_write
 gs_start_tx(port);
  // 把 usb_request 放入队列, Host读取数据时就可以从中得到数据
  status = usb_ep_queue(in, req, GFP_ATOMIC);

2.2.2 printk

启动 Linux 内核时传入 commandline 参数"console=ttyGS0"后,内核的 printk 的信息通过 Gadget 串口打印出来(Host 要打开 USB 串口)。

内核的 printk 函数会导致 gserial_cons 结构体中的 write 指针即gs_console_write函数被调用:

图片

gs_console_write 函数的调用关系如下:

gs_console_write
 // 把要打印的数据放入环形 buffer
 gs_buf_put(&info- >con_buf, buf, count);
 
 // 唤醒内核线程
 wake_up_process(info- >console_thread);
 
// 内核线程
gs_console_thread
 // 被唤醒后
 
 // 取出输入端点和它的 usb_request
 req = info- >console_req;
 ep = port- >port_usb- >in;
 
 // 从环形 buffer 得到数据、设置 usb_request
 xfer = gs_buf_get(&info- >con_buf, req- >buf, size);
 req- >length = xfer;
 
 // 把 usb_request 放入队列,以便 Host 读取
 ret = usb_ep_queue(ep, req, GFP_ATOMIC);
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4983

    文章

    18297

    浏览量

    288624
  • 驱动
    +关注

    关注

    11

    文章

    1718

    浏览量

    84359
  • Linux
    +关注

    关注

    87

    文章

    10993

    浏览量

    206747
收藏 人收藏

    评论

    相关推荐

    Cypress USBSERIAL如何转换

    嗨,我有一个太阳能逆变器与CyPress USB到串行控制器VID 0665 PID 5161。我试着用Linux来使用这个串口。Windows系统发现串行控制器LAS是一个输入设备(HID)。我
    发表于 10-17 16:10

    如何配置USB OTG为Gadget serial device?

    现需要将OKA40i-C板子的OTG下载口配置为虚拟串口,实现u***串行通信,利用linux已存在的u***转虚拟串口驱动:USB Gadget Drivers (Serial
    发表于 01-04 06:47

    分享一种将RK3399配置成USB gadget设备的方法

    一个USB gadget设备(比如配置成一个hid 键盘),就得在type-c实现,实际中这个功能有广泛的应用,比如pc主机和RK3399进行数据通信,用此就是一种很好的方式,RK3399的
    发表于 05-24 10:35

    基于Linux内核的Rockchip USB Gadget UAC开发资料分享

    1、Rockchip USB Gadget UAC开发步骤本文档提供 Rockchip 平台基于 Linux 内核的 USB Gadget UAC(
    发表于 08-10 16:03

    RK3288使用USB GADGET实现大容量存储脚本

    (){mount -t configfs none /sys/kernel/configmkdir /sys/kernel/config/usb_gadget/rockchip -m
    发表于 11-18 16:33

    求助,关于USB gadget安装虚拟网口问题求解

    1.make linux-menuconfig USB support ----> <*>USB Gadget Support ---->
    发表于 09-01 06:14

    Universal Serial Bus(USB) Devi

    Universal Serial Bus Device Class Definition for Printing Devices The Universal Serial Bus (USB
    发表于 04-11 19:32 16次下载

    Universal Serial Bus (USB)HID协

    Universal Serial Bus (USB)HID协议手册 THIS SPECIFICATION IS PROVIDED
    发表于 03-12 09:27 154次下载

    usb+serial+controller驱动程序分享

    主要介绍usb+serial+controller驱动程序。
    发表于 03-17 09:44 33次下载

    [嵌入式linux]将linux板卡虚拟为USB网卡设备(Ethernet Gadget

    kernel menuconfig-> Device Drivers ->USB support -> USB Gadget Support 建议最好选成M,作为内核驱动模块,便于
    发表于 11-02 11:36 11次下载
    [嵌入式linux]将linux板卡虚拟为<b class='flag-5'>USB</b>网卡设备(Ethernet <b class='flag-5'>Gadget</b>)

    AMD Xilinx Linux 2022.1 USB Gadget使用

    有客户使用Linux中的USB Gadget功能,把MPSoC器件做USB从设备
    的头像 发表于 07-07 14:15 480次阅读

    USB Gadget 应用实例ADB实现

    里,定义了多个接口描述符,这是 APP 提出的请求。如果 Gadget 设备有足够的端点,那么就会在在 functionfs 跟目录下创建出这些端点,比如 ep1、ep2。 ADB 程序的调用关系如下
    的头像 发表于 07-13 10:56 2351次阅读
    <b class='flag-5'>USB</b> <b class='flag-5'>Gadget</b> 应用<b class='flag-5'>实例</b>ADB实现

    USB Gadget serial应用实例(下)

    3. 编程 PC: open /read/ write /dev/ ttyACM0板子: open /read/ write /dev/ ttyGS0参考:https: //stackoverflow.com/questions/7469139/what-is-the-equivalent-to-getch-getche-in-linux 源码: # include # include # include # include # include # include # include # include # include # include static struct termios old , current ; /* Initialize new terminal i/o settings */ void initTermios ( int echo) { tcgetattr ( 0 , /* grab old terminal i/o settings */ current = old; /* make new settings same as old settings */ current.c_lflag /* disable buffered i/o */ if (echo) { current.c_lflag |= ECHO;
    的头像 发表于 07-13 11:10 487次阅读

    USB Gadget zero应用实例程序

    1. 编写程序 1.1 编程思路 涉及的程序如下图所示: PC 端基于 libusb 编写应用程序,开发板端直接使用 Linux 自带的 USB Gadget 驱动 zero.c【/drivers
    的头像 发表于 07-13 11:14 635次阅读
    <b class='flag-5'>USB</b> <b class='flag-5'>Gadget</b> zero应用<b class='flag-5'>实例</b>程序

    从硬件软件角度理解Gadget框架

    2. 从硬件软件角度理解 Gadget 框架 USB 传输的核心是 endpoint,使用 endpoint 可以收发数据。在 endpoint 之上,就可以模拟 USB 串口、USB
    的头像 发表于 07-13 11:32 612次阅读
    从硬件软件角度理解<b class='flag-5'>Gadget</b>框架