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

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

3天内不再提示

从获取描述符的角度理解Gadget框架

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

安装好 gadget 驱动程序后(比如 modprobe g_zero), 它只是构造好了各类描述符。在设备的枚举过程会读取描述符。

使用 OTG 线连接电脑和开发板时,电脑软件会执行如下操作:

  • 使用控制传输,读取设备信息(设备描述符):第一次读取时,它只需要得到 8 字节数据,因为第 8 个数据表示端点 0 能传输的最大数据长度。
  • Host 分配地址给设备,然后把新地址发给设备。
  • 使用新地址,重新读取设备描述符,设备描述符长度是 18
  • 读取配置描述符:它传入的长度是 255,想一次性把当前配置描述符、它下面的接口描述符、端点描述符全部读出来。
  • 读取字符描述符。

上述过程里,设备方都是接收到 Host 发给 endpoint 0 的数据,然后做出回应。不同的 Gadget 设备,在返回描述符给主机时,这些操作都是一样的,只是回应的数据不同而已。源码分析的起点都是某个中断函数:

  • IMX6ULL:ci_irq(drivers/usb/chipidea/core.c)
  • STM32MP157: dwc2_hsotg_irq(drivers/usb/dwc2/gadget.c)

4.1 IMX6ULL 的核心函数

IMX6ULL 芯片中 USB 控制器型号是 chipidea,在Linux-4.9.88driversusbchipideacore.c中注册了中断函数:

ci_hdrc_probe
 ret = devm_request_irq(dev, ci- >irq, ci_irq, IRQF_SHARED,
   ci- >platdata- >name, ci);

发生中断后,对于 endpoint 0 的数据处理流程如下:

// Linux-4.9.88driversusbchipideacore.c
ci_irq
 /* Handle device/host interrupt */
 if (ci- >role != CI_ROLE_END)
  ret = ci_role(ci)- >irq(ci);  // udc_irq
   
   // Linux-4.9.88driversusbchipideaudc.c
   udc_irq
                if (USBi_UI  & intr)
                 // Linux-4.9.88driversusbchipideaudc.c
                    isr_tr_complete_handler(ci);
                        /* Only handle setup packet below */
                        if (i == 0 &&
                            hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(0)))
                            // Linux-4.9.88driversusbchipideaudc.c
                            isr_setup_packet_handler(ci);

函数isr_setup_packet_handler就是处理 endpoint 0 接收到的控制传输的关键。

4.2 STM32MP157的核心函数

STM32MP157 芯片中 USB 控制器型号是 dwc2,在Linux-5.4driversusbdwc2gadget.c中注册了中断函数:

dwc2_gadget_init
 ret = devm_request_irq(hsotg- >dev, hsotg- >irq, dwc2_hsotg_irq,
          IRQF_SHARED, dev_name(hsotg- >dev), hsotg);

发生中断后,函数dwc2_hsotg_irq被调用,它处理 endpoint 中断有两种方法:

  • 使用 DMA 时:调用dwc2_hsotg_epint来处理
  • 不使用 DMA 时:调用dwc2_hsotg_handle_rx来处理

dwc2_hsotg_epint为例进行分析,对于 endpoint 0 的数据处理流程如下:

// Linux-5.4driversusbdwc2gadget.c
dwc2_hsotg_irq
  // 处理endpoint中断
  for (ep = 0; ep < hsotg- >num_of_eps && daint_out; ep++, daint_out > >= 1) {
   if (daint_out & 1)
    dwc2_hsotg_epint(hsotg, ep, 0);
  }

  for (ep = 0; ep < hsotg- >num_of_eps  && daint_in; ep++, daint_in > >= 1) {
   if (daint_in & 1)
    dwc2_hsotg_epint(hsotg, ep, 1);
  }

函数dwc2_hsotg_epint中,对于 endpoint 0 的处理如下:

// Linux-5.4driversusbdwc2gadget.c
dwc2_hsotg_epint
    if (idx == 0 && !hs_ep- >req)
     dwc2_hsotg_enqueue_setup(hsotg);

函数dwc2_hsotg_enqueue_setup被调用时,Gadget 设备已经收到了 SETUP 令牌包,但是还没收到 DATA0 令牌包。dwc2_hsotg_enqueue_setup的作用是,设置、启动一个 request,核心在于设置了 request 的 complete 函数(当 SETTUP 事务完成后这个函数被调用):

图片

当控制传输的"setup事务"完成时,函数dwc2_hsotg_complete_setup被调用。

4.3 如何处理控制传输

无论是 MX6ULL 的函数isr_setup_packet_handler,还是 STM32M157 的函数dwc2_hsotg_complete_setup,它们都是在 Gadget 设备收到"SETUP事务"后才被调用。接收完"SETUP事务"后,就可以从里面知道这个控制传输想做什么(req.bRequest 是什么),然后就可以处理它了。

怎么处理呢?可以分为 3 层:

图片

  • UDC 驱动程序:类似"设置地址"的控制传输,在底层的 UDC 驱动程序里就可以处理,
    • 这类请求有:
      USB_REQ_SET_ADDRESS
      USB_REQ_SET_FEATURE     // 有一些请求可能需要上报改 gadget driver
      USB_REQ_CLEAR_FEATURE   // 有一些请求可能需要上报改 gadget driver
      USB_REQ_GET_STATUS      // 有一些请求可能需要上报改 gadget driver
      
    • 驱动程序位置
      IMX6ULL: Linux-4.9.88driversusbchipideaudc.c, 函数 isr_setup_packet_handler
      STM32MP157: Linux-5.4driversusbdwc2gadget.c, 函数 dwc2_hsotg_complete_setup
      
  • gadget driver:涉及描述符的操作
    • 这类请求有:
      USB_REQ_GET_DESCRIPTOR
      USB_REQ_SET_CONFIGURATION
      USB_REQ_GET_CONFIGURATION
      USB_REQ_SET_INTERFACE
      USB_REQ_GET_INTERFACE
      USB_REQ_GET_STATUS     // 底层 UDC 驱动无法处理的话, gadget driver 来处理
      USB_REQ_CLEAR_FEATURE  // 底层 UDC 驱动无法处理的话, gadget driver 来处理
      USB_REQ_SET_FEATURE    // 底层 UDC 驱动无法处理的话, gadget driver 来处理
      
    • 驱动程序位置
      文件:driversusbgadgetcomposite.c
      函数:composite_setup
      
  • usb_configuration 或 usb_function 的处理:这是二选一的。大部分设备使用控制传输实现标准的 USB 请求,但是也可以用控制传输来进行实现相关的请求,对于这些非标准的请求,就需要上层驱动来处理。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5082

    文章

    19123

    浏览量

    305122
  • Linux
    +关注

    关注

    87

    文章

    11304

    浏览量

    209469
  • 框架
    +关注

    关注

    0

    文章

    403

    浏览量

    17483
收藏 人收藏

    评论

    相关推荐

    UBL UBOOT 描述符

       在DM368的开发包目录下/psp/flash-utils/DM36x/GNU:执行make 可以省成UBL:ubl_DM36x_nand.bin ;我想问的是如何添加UBL 的描述符?烧写到
    发表于 06-21 08:48

    USB设备检测过程的USB设备的描述符

    USB 设备的总体信息,它是枚举过程中主机设备读取的第一个描述符。设备描述符总共有 18 个字节,分为 14 个字段,如表 6-5 所示。(2)配置描述符配置、接口以及端点
    发表于 11-12 09:23

    ARM中,Linux 文件描述符到底是什么?

    进程所有打开的文件。内核空间是虚拟地址空间的一部分,想死磕的读者请猛击《C语言内存精讲》,不想纠缠细节的读者可以这样理解:进程启动后要占用内存,其中一部分内存分配给了文件描述符表。除了文件描述符表,系统
    发表于 10-23 16:11

    USB HID报告及报告描述符简介

    在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串
    发表于 04-12 11:13 4037次阅读

    Descriptor描述符解释

    Descriptor即描述符,是一个完整的数据结构,可以通过C语言等编程实现,并存储在USB设备中,用于描述一个USB设备的所有属性,USB主机是通过一系列命令来要求设备发送这些信息的。
    发表于 07-16 09:39 2645次阅读

    Linux中文件及文件描述符概述

    6.2 Linux中文件及文件描述符概述 在Linux中对目录和设备的操作都等同于文件的操作,因此,大大简化了系统对不同设备的处理,提高了效率。Linux中的文件主要分为4种:普通文件、目录文件
    发表于 10-18 14:35 0次下载

    USB设备键值表描述符说明资料免费下载

    本文档的主要内容详细介绍的是USB设备键值表描述符说明资料免费下载包括了:1.设备描述符的结构,2. 配置描述符的结构,3. 接口描述符的结构,4. HID
    发表于 07-16 16:56 35次下载
    USB设备键值表<b class='flag-5'>描述符</b>说明资料免费下载

    USB各描述符之间的依赖是怎么样的

    USB 是个通用的总线,端口都是统一的。但是USB 设备却各种各样,例如USB 鼠标, USB键盘, U盘等等,那么USB 主机是如何识别出不同的设备的呢?这就要依赖于描述符了。USB 的描述符主要有设备描述符,配置
    发表于 07-23 16:53 8次下载
    USB各<b class='flag-5'>描述符</b>之间的依赖是怎么样的

    隐藏描述符工具应用程序免费下载

    本文档的主要内容详细介绍的是HID Descriptor Tool隐藏描述符工具应用程序免费下载。
    发表于 01-08 08:00 11次下载
    隐藏<b class='flag-5'>描述符</b>工具应用程序免费下载

    Linux系统编程中的文件描述符调用

    表示,文件描述符的范围0开始,到上限值-1,默认情况下,上限值为1024,也就是说,进程默认情况下最多可以打开1024个文件。负数是不合法的文件描述符,当函数调用出错时,返回的文件描述符
    的头像 发表于 09-02 09:50 1682次阅读
    Linux系统编程中的文件<b class='flag-5'>描述符</b>调用

    科普一下什么是USB的描述符

    以及行为呢?这就要通过描述符来实现了。那么什么是USB的描述符呢?其实就是一些传递的协议信息,比如设备的类型、厂商ID、产品ID、端点情况、版本号等信息。 既然描述符是协议信息,那么不同的版本也会有所不同,比如USB1.1协议定
    的头像 发表于 12-02 14:41 3961次阅读

    USB Gadget zero应用实例程序

    interface 进而得到 endpoint 读写数据:操作 endpoint 1.2 zero 设备的描述符 在 Ubuntu 里执行如下命令,根据 VID:PID 获取设备信息: $ lsusb -v -d 0525 :a4a0 可以列出 zero 设备的
    的头像 发表于 07-13 11:14 1083次阅读
    USB <b class='flag-5'>Gadget</b> zero应用实例程序

    硬件软件角度理解Gadget框架

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

    Gadget框架构造描述符

    假设你要【模拟】一个 USB 设备: 这个 USB 设备含有厂家信息:它记录在设备描述符里,所以设备描述符应该由你提供 这个芯片可能有多种配置,这也是由你决定,所以配置描述符应该由你提供 某个配置下
    的头像 发表于 07-13 11:34 650次阅读
    <b class='flag-5'>Gadget</b><b class='flag-5'>框架</b>构造<b class='flag-5'>描述符</b>

    Python的优雅之处:Descriptor(描述符

    学习 Python 这么久了,说起 Python 的优雅之处,能让我脱口而出的, Descriptor(描述符)特性可以排得上号。 描述符 是Python 语言独有的特性,它不仅在应用层使用,在语言
    的头像 发表于 11-02 10:52 1008次阅读
    Python的优雅之处:Descriptor(<b class='flag-5'>描述符</b>)