设备驱动中的gadget(kernel-4.7)

本文详细介绍了Linux USB Gadget Driver的功能,核心数据结构包括USB_Gadget对象、Gadget器件操作函数集等。讨论了UDC驱动程序的角色,中断处理函数和端点操作函数的重要性,以及如何在设备层和功能层实现USB设备的不同功能。
摘要由CSDN通过智能技术生成

Linux USB Gadget Driver功能

为了与主机端驱动设备的USB Device Driver概念进行区别,将在外围器件中运行的驱动程序称为USB Gadget Driver。其中,Host端驱动设备的驱动程序是master或者client driver,设备端gadget driver是slave或者function driver。

Gadget Driver和USB Host端驱动程序类似,都是使用请求队列来对I/O包进行缓冲,这些请求可以被提交和取消。它们的结构、消息和常量的定义也和USB技术规范第九章的内容一致。同时也是通过bind和unbind将driver与device建立关系。

Linux USB Gadget Driver核心数据结构

USB_Gadget对象


/**
 * struct usb_gadget - represents a usb slave device
 * @work: (internal use) Workqueue to be used for sysfs_notify()
 * @udc: struct usb_udc pointer for this gadget
 * @ops: Function pointers used to access hardware-specific operations.
 * @ep0: Endpoint zero, used when reading or writing responses to
 *  driver setup() requests
 * @ep_list: List of other endpoints supported by the device.
 * @speed: Speed of current connection to USB host.
 * @max_speed: Maximal speed the UDC can handle.  UDC must support this
 *      and all slower speeds.
 * @state: the state we are now (attached, suspended, configured, etc)
 * @name: Identifies the controller hardware type.  Used in diagnostics
 *  and sometimes configuration.
 * @dev: Driver model state for this abstract device.
 * @out_epnum: last used out ep number
 * @in_epnum: last used in ep number
 * @otg_caps: OTG capabilities of this gadget.
 * @sg_supported: true if we can handle scatter-gather
 * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
 *  gadget driver must provide a USB OTG descriptor.
 * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
 *  is in the Mini-AB jack, and HNP has been used to switch roles
 *  so that the "A" device currently acts as A-Peripheral, not A-Host.
 * @a_hnp_support: OTG device feature flag, indicating that the A-Host
 *  supports HNP at this port.
 * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host
 *  only supports HNP on a different root port.
 * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
 *  enabled HNP support.
 * @hnp_polling_support: OTG device feature flag, indicating if the OTG device
 *  in peripheral mode can support HNP polling.
 * @host_request_flag: OTG device feature flag, indicating if A-Peripheral
 *  or B-Peripheral wants to take host role.
 * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
 *  MaxPacketSize.
 * @is_selfpowered: if the gadget is self-powered.
 * @deactivated: True if gadget is deactivated - in deactivated state it cannot
 *  be connected.
 * @connected: True if gadget is connected.
 *
 * Gadgets have a mostly-portable "gadget driver" implementing device
 * functions, handling all usb configurations and interfaces.  Gadget
 * drivers talk to hardware-specific code indirectly, through ops vectors.
 * That insulates the gadget driver from hardware details, and packages
 * the hardware endpoints through generic i/o queues.  The "usb_gadget"
 * and "usb_ep" interfaces provide that insulation from the hardware.
 *
 * Except for the driver data, all fields in this structure are
 * read-only to the gadget driver.  That driver data is part of the
 * "driver model" infrastructure in 2.6 (and later) kernels, and for
 * earlier systems is grouped in a similar structure that's not known
 * to the rest of the kernel.
 *
 * Values of the three OTG device feature flags are updated before the
 * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before
 * driver suspend() calls.  They are valid only when is_otg, and when the
 * device is acting as a B-Peripheral (so is_a_peripheral is false).
 */
struct usb_gadget {
    struct work_struct      work;
    struct usb_udc          *udc;
    /* readonly to gadget driver */
    const struct usb_gadget_ops *ops; //Gadget设备操作函数集
    struct usb_ep           *ep0;//控制端点,只对setup包响应
    struct list_head        ep_list;/* of usb_ep *///将设备的所有端点连成链表,ep0不在其中
    enum usb_device_speed       speed; //高速、全速和低速
    enum usb_device_speed       max_speed;
    enum usb_device_state       state;
    const char          *name; //器件名称
    struct device           dev; //内核设备模型使用
    unsigned            out_epnum;
    unsigned            in_epnum;
    struct usb_otg_caps     *otg_caps;

    unsigned            sg_supported:1;
    unsigned            is_otg:1;
    unsigned            is_a_peripheral:1;
    unsigned            b_hnp_enable:1;
    unsigned            a_hnp_support:1;
    unsigned            a_alt_hnp_support:1;
    unsigned            hnp_polling_support:1;
    unsigned            host_request_flag:1;
    unsigned            quirk_ep_out_aligned_size:1;
    unsigned            quirk_altset_not_supp:1;
    unsigned            quirk_stall_not_supp:1;
    unsigned            quirk_zlp_not_supp:1;
    unsigned            is_selfpowered:1;
    unsigned            deactivated:1;
    unsigned            connected:1;
};

Gadget器件操作函数集
操作UDC硬件的API,但操作端点的函数由端点操作函数集完成

/* the rest of the api to the controller hardware: device operations,
 * which don't involve endpoints (or i/o).
 */
struct usb_gadget_ops {
    int (*get_frame)(struct usb_gadget *);
    int (*wakeup)(struct usb_gadget *);
    int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
    int (*vbus_session) (struct usb_gadget *, int is_active);
    int (*vbus_draw) (struct usb_gadget *, unsigned mA);
    int (*pullup) (struct usb_gadget *, int is_on);
    int (*ioctl)(struct usb_gadget *,
                unsigned code, unsigned long param);
    void    (*get_config_params)(struct usb_dcd_config_params *);
    int (*udc_start)(struct usb_gadget *,
            struct usb_gadget_driver *);
    int (*udc_stop)(struct usb_gadget *);
    struct usb_ep *(*match_ep)(struct usb_gadget *,
            struct usb_endpoint_descriptor *,
            struct usb_ss_ep_comp_descriptor *);
};

USB Gadget driver对象


/*-------------------------------------------------------------------------*/

/**
 * struct usb_gadget_driver - driver for usb 'slave' devices
 * @function: String describing the gadget's function
 * @max_speed: Highest speed the driver handles.
 * @setup: Invoked for ep0 control requests that aren't handled by
 *  the hardware level driver. Most calls must be handled by
 *  the gadget driver, including descriptor and configuration
 *  management.  The 16 bit members of the setup data are in
 *  USB byte order. Called in_interrupt; this may not sleep.  Driver
 *  queues a response to ep0, or returns negative to stall.
 * @disconnect: Invoked after all transfers have been stopped,
 *  when the host is disconnected.  May be called in_interrupt; this
 *  may not sleep.  Some devices can't detect disconnect, so this might
 *  not be called except as part of controller shutdown.
 * @bind: the driver's bind callback
 * @unbind: Invoked when the driver is unbound from a gadget,
 *  usually from rmmod (after a disconnect is reported).
 *  Called in a context that permits sleeping.
 * @suspend: Invoked on USB suspend.  May be called in_interrupt.
 * @resume: Invoked on USB resume.  May be called in_interrupt.
 * @reset: Invoked on USB bus reset. It is mandatory for all gadget drivers
 *  and should be called in_interrupt.
 * @driver: Driver model state for this driver.
 * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL,
 *  this driver will be bound to any available UDC.
 * @pending: UDC core private data used for deferred probe of this driver.
 * @match_existing_only: If udc is not found, return an error and don't add this
 *      gadget driver to list of pending driver
 *
 * Devices are disabled till a gadget driver successfully bind()s, which
 * means the driver will handle setup() requests needed to enumerate (and
 * meet "chapter 9" requirements) then do some useful work.
 *
 * If gadget->is_otg is true, the gadget driver must provide an OTG
 * descriptor during enumeration, or else fail the bind() call.  In such
 * cases, no USB traffic may flow until both bind() returns without
 * having called usb_gadget_disconnect(), and the USB host stack has
 * initialized.
 *
 * Drivers use hardware-specific knowledge to configure the usb hardware.
 * endpoint addressing is only one of several hardware characteristics that
 * are in descriptors the ep0 implementation returns from setup() calls.
 *
 * Except for ep0 implementation, most driver code shouldn't need change to
 * run on top of different usb controllers.  It'll use endpoints set up by
 * that ep0 implementation.
 *
 * The usb controller driver handles a few standard usb requests.  Those
 * include set_address, and feature flags for devices, interfaces, and
 * endpoints (the get_status, set_feature, and clear_feature requests).
 *
 * Accordingly, the driver's setup() callback must always implement all
 * get_descriptor requests, returning at least a device descriptor and
 * a configuration descriptor.  Drivers must make sure the endpoint
 * descriptors match any hardware constraints. Some hardware also constrains
 * other descriptors. (The pxa250 allows only configurations 1, 2, or 3).
 *
 * The driver's setup() callback must also implement set_configuration,
 * and should also implement set_interface, get_configuration, and
 * get_interface.  Setting a configuration (or interface) is where
 * endpoints should be activated or (config 0) shut down.
 *
 * (Note that only the default control endpoint is supported.  Neither
 * hosts nor devices generally support control traffic except to ep0.)
 *
 * Most devices will ignore USB suspend/resume operations, and so will
 * not provide those callbacks.  However, some may need to change modes
 * when the host is not longer directing those activities.  For example,
 * local controls (buttons, dials, etc) may need to be re-enabled since
 * the (remote) host can't do that any longer; or an error state might
 * be cleared, to make the device behave identically whether or not
 * power is maintained.
 */
struct usb_gadget_driver {
    char            *function; //驱动名称
    enum usb_device_speed   max_speed; //USB设备速度类型
    int         (*bind)(struct usb_gadget *gadget,
                    struct usb_gadget_driver *driver); //将驱动和设备绑定,一般在驱动注册时调用
    void            (*unbind)(struct usb_gadget *);//卸载驱动时调用,rmmod时调用
    int         (*setup)(struct usb_gadget *,
                    const struct usb_ctrlrequest *); //处理ep0的控制请求,在中断中调用,不能睡眠
    void            (*disconnect)(struct usb_gadget *); //可能在中断中调用不能睡眠
    void            (*suspend)(struct usb_gadget *); //电源管理模式相关,设备挂起
    void            (*resume)(struct usb_gadget *); //电源管理模式相关,设备恢复
    void            (*reset)(struct usb_gadget *);

    /* FIXME support safe rmmod */
    struct device_driver    driver; //内核设备管理使用

    char            *udc_name;
    struct list_head    pending;
    unsigned                match_existing_only:1;
};

描述一个I/O请求


struct usb_ep;

/**
 * struct usb_request - describes one i/o request
 * @buf: Buffer used for data.  Always provide this; some controllers
 *  only use PIO, or don't use DMA for some endpoints.
 * @dma: DMA address corresponding to 'buf'.  If you don't set this
 *  field, and the usb controller needs one, it is responsible
 *  for mapping and unmapping the buffer.
 * @sg: a scatterlist for SG-capable controllers.
 * @num_sgs: number of SG entries
 * @num_mapped_sgs: number of SG entries mapped to DMA (internal)
 * @length: Length of that data
 * @stream_id: The stream id, when USB3.0 bulk streams are being used
 * @no_interrupt: If true, hints that no completion irq is needed.
 *  Helpful sometimes with deep request queues that are handled
 *  directly by DMA controllers.
 * @zero: If true, when writing data, makes the last packet be "short"
 *     by adding a zero length packet as needed;
 * @short_not_ok: When reading data, makes short packets be
 *     treated as errors (queue stops advancing till cleanup).
 * @complete: Function called when request completes, so this request and
 *  its buffer may be re-used.  The function will always be called with
 *  interrupts disabled, and it must not sleep.
 *  Reads terminate with a short packet, or when the buffer fills,
 *  whichever comes first.  When writes terminate, some data bytes
 *  will usually still be in flight (often in a hardware fifo).
 *  Errors (for reads or writes) stop the queue from advancing
 *  until the completion function returns, so that any transfers
 *  invalidated by the error may first be dequeued.
 * @context: For use by the completion callback
 * @list: For use by the gadget driver.
 * @status: Reports completion code, zero or a negative errno.
 *  Normally, faults block the transfer queue from advancing until
 *  the completion callback returns.
 *  Code "-ESHUTDOWN" indicates completion caused by device disconnect,
 *  or when the driver disabled the endpoint.
 * @actual: Reports bytes transferred to/from the buffer.  For reads (OUT
 *  transfers) this may be less than the requested length.  If the
 *  short_not_ok flag is set, short reads are treated as errors
 *  even when status otherwise indicates successful completion.
 *  Note that for writes (IN transfers) some data bytes may still
 *  reside in a device-side FIFO when the request is reported as
 *  complete.
 *
 * These are allocated/freed through the endpoint they're used with.  The
 * hardware's driver can add extra per-request data to the memory it returns,
 * which often avoids separate memory allocations (potential failures),
 * later when the request is queued.
 *
 * Request flags affect request handling, such as whether a zero length
 * packet is written (the "zero" flag), whether a short read should be
 * treated as an error (blocking request queue advance, the "short_not_ok"
 * flag), or hinting that an interrupt is not required (the "no_interrupt"
 * flag, for use with deep request queues).
 *
 * Bulk endpoints can use any size buffers, and can also be used for interrupt
 * transfers. interrupt-only endpoints can be much less functional.
 *
 * NOTE:  this is analogous to 'struct urb' on the host side, except that
 * it's thinner and promotes more pre-allocation.
 */

struct usb_request {
    void            *buf;  //数据缓存区
    unsigned        length; //数据长度
    dma_addr_t      dma;  //与buf关联的DMA地址,DMA传输时使用

    struct scatterlist  *sg;
    unsigned        num_sgs;
    unsigned        num_mapped_sgs;

    unsigned        stream_id:16;
    unsigned        no_interrupt:1; //当为true时,表示没有完成函数,则通过中断通知传输完成,这个由DMA控制器直接控制
    unsigned        zero:1; //当输出的最后一个数据包不够长度是是否填充0
    unsigned        short_not_ok:1; //当接收的数据不够指定长度时,是否报错

    void            (*complete)(struct usb_ep *ep,
                    struct usb_request *req); //请求完成函数
    void            *context;  //被completion回调函数使用
    struct list_head    list;  //被Gadget Driver使用,插入队列

    int         status;  //返回完成结果,0表示成功
    unsigned        actual;  //实际传输的数据长度
};

端点


/**
 * struct usb_ep - device side representation of USB endpoint
 * @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk"
 * @ops: Function pointers used to access hardware-specific operations.
 * @ep_list:the gadget's ep_list holds all of its endpoints
 * @caps:The structure describing types and directions supported by endoint.
 * @maxpacket:The maximum packet size used on this endpoint.  The initial
 *  value can sometimes be reduced (hardware allowing), according to
 *      the endpoint descriptor used to configure the endpoint.
 * @maxpacket_limit:The maximum packet size value which can be handled by this
 *  endpoint. It's set once by UDC driver when endpoint is initialized, and
 *  should not be changed. Should not be confused with maxpacket.
 * @max_streams: The maximum number of streams supported
 *  by this EP (0 - 16, actual number is 2^n)
 * @mult: multiplier, 'mult' value for SS Isoc EPs
 * @maxburst: the maximum number of bursts supported by this EP (for usb3)
 * @driver_data:for use by the gadget driver.
 * @address: used to identify the endpoint when finding descriptor that
 *  matches connection speed
 * @desc: endpoint descriptor.  This pointer is set before the endpoint is
 *  enabled and remains valid until the endpoint is disabled.
 * @comp_desc: In case of SuperSpeed support, this is the endpoint companion
 *  descriptor that is used to configure the endpoint
 *
 * the bus controller driver lists all the general purpose endpoints in
 * gadget->ep_list.  the control endpoint (gadget->ep0) is not in that list,
 * and is accessed only in response to a driver setup() callback.
 */

struct usb_ep {
    void            *driver_data;   //端点私有数据
    const char      *name;  //端点名称
    const struct usb_ep_ops *ops; //端点操作函数集
    struct list_head    ep_list;  //Gadget设备建立所有端点的链表
    struct usb_ep_caps  caps;
    bool            claimed;
    bool            enabled;
    unsigned        maxpacket:16; //这个端点使用的最大包长度
    unsigned        maxpacket_limit:16;
    unsigned        max_streams:16;
    unsigned        mult:2;
    unsigned        maxburst:5;
    u8          address;
    const struct usb_endpoint_descriptor    *desc;
    const struct usb_ss_ep_comp_descriptor  *comp_desc;
};

端点操作函数集



struct usb_gadget;
struct usb_gadget_driver;
struct usb_udc;

/* the rest of the api to the controller hardware: device operations,
 * which don't involve endpoints (or i/o).
 */
struct usb_gadget_ops {
    int (*get_frame)(struct usb_gadget *);
    int (*wakeup)(struct usb_gadget *);
    int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
    int (*vbus_session) (struct usb_gadget *, int is_active);
    int (*vbus_draw) (struct usb_gadget *, unsigned mA);
    int (*pullup) (struct usb_gadget *, int is_on);
    int (*ioctl)(struct usb_gadget *,
                unsigned</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值