USB设备状态设置-- usb_gadget_set_state()

本文介绍了USB2.0协议中规定的六种USB设备状态及其转换过程,并详细解释了Linux内核中用于设置这些状态的函数usb_gadget_set_state()的工作原理。此外,还探讨了状态信息如何通过sysfs导出供用户空间程序读取。

一、USB设备状态

在USB 2.0协议中第 9.1 USB Device States 章节规定了USB设备的6种状态,包括:
Attached/Powered/Default/Address/Configured/Suspended

其状态迁移图如下:
USB设备状态迁移

在 Linux Kernel ch9.h 文件中用 enum usb_device_state 来标记这几种状态。

// <kernel_dir>/include/uapi/linux/usb/ch9.h

enum usb_device_state {
    /* NOTATTACHED isn't in the USB spec, and this state acts
     * the same as ATTACHED ... but it's clearer this way.
     */
    USB_STATE_NOTATTACHED = 0,

    /* chapter 9 and authentication (wireless) device states */
    USB_STATE_ATTACHED,
    USB_STATE_POWERED,          /* wired */
    USB_STATE_RECONNECTING,         /* auth */
    USB_STATE_UNAUTHENTICATED,      /* auth */
    USB_STATE_DEFAULT,          /* limited function */
    USB_STATE_ADDRESS,
    USB_STATE_CONFIGURED,           /* most functions */

    USB_STATE_SUSPENDED

    /* NOTE:  there are actually four different SUSPENDED
     * states, returning to POWERED, DEFAULT, ADDRESS, or
     * CONFIGURED respectively when SOF tokens flow again.
     * At this level there's no difference between L1 and L2
     * suspend states.  (L2 being original USB 1.1 suspend.)
     */
};

二、状态设置函数usb_gadget_set_state()

// <kernel_dir>/drivers/usb/gadget/udc/udc-core.c

void usb_gadget_set_state(struct usb_gadget *gadget,
        enum usb_device_state state)
{
    gadget->state = state;
    schedule_work(&gadget->work);
}
EXPORT_SYMBOL_GPL(usb_gadget_set_state);

// <kernel_dir>/include/linux/usb/gadget.h
extern void usb_gadget_set_state(struct usb_gadget *gadget,  enum usb_device_state state);

在 udc-core.c 文件中,会去定义usb_gadget_set_state()函数,将状态state的值赋值给gadget->state其中struct usb_gadget是用来标记一个USB设备的信息。此时USB设备的状态就可以确定了。之后启动工作队列schedule_work(&gadget->work);将状态信息给到sysfs。

在USB的枚举阶段,会根据USB所处的状态调用usb_gadget_set_state()去设置USB设备的状态。
比如说在USB设备的枚举阶段,在composite_setup()函数中USB设备接收到了USB Host发过来的USB_REQ_SET_CONFIGURATION命令后调用set_config()设置相应的配置,这之后就会调用usb_gadget_set_state()去设置为USB_STATE_CONFIGURED状态。

三、usb_gadget_state_work()

// <kernel_dir>/drivers/usb/gadget/udc/udc-core.c

* usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
 * @parent: the parent device to this udc. Usually the controller driver's
 * device.
 * @gadget: the gadget to be added to the list.
 * @release: a gadget release function.
 *
 * Returns zero on success, negative errno otherwise.
 */
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
        void (*release)(struct device *dev))

usb_add_gadget_udc_release()中会去绑定 gadget->workusb_gadget_state_work() 函数。

static void usb_gadget_state_work(struct work_struct *work)
{
    struct usb_gadget *gadget = work_to_gadget(work);
    struct usb_udc *udc = gadget->udc;

    if (udc)
        sysfs_notify(&udc->dev.kobj, NULL, "state");
}

这个函数主要目的就是将当前的 state 信息写入到 sysfs 中去。这个信息可以cat出来。

#cat /sys/devices/platform/xxx_udc/state

路径不完全是这个,但是在 /sys/devices 目录下会有对应udc控制器 xxx_udc 的状态节点。不仅包含状态的节点,还包含其他的信息。

-r--r--r-- 0        0              4096 2017-05-01 16:17 a_alt_hnp_support
-r--r--r-- 0        0              4096 2017-05-01 16:17 a_hnp_support
-r--r--r-- 0        0              4096 2017-05-01 16:17 b_hnp_enable
-r--r--r-- 0        0              4096 2017-05-01 16:17 current_speed
lrwxrwxrwx 0        0               2017-05-01 16:17 device -> ../../../panasonic_udc.1
-r--r--r-- 0        0              4096 2017-05-01 16:17 is_a_peripheral
-r--r--r-- 0        0              4096 2017-05-01 16:17 is_otg
-r--r--r-- 0        0              4096 2017-05-01 16:17 maximum_speed
drwxr-xr-x 0        0                   2017-05-01 16:17 power
--w------- 0        0              4096 2017-05-01 16:17 soft_connect
--w------- 0        0              4096 2017-05-01 16:17 srp
-r--r--r-- 0        0              4096 2017-05-01 16:17 state
lrwxrwxrwx 0        0                   2017-05-01 16:17 subsystem -> ../../../../../class/udc
-rw-r--r-- 0        0              4096 2017-05-01 16:17 uevent

这里面的信息其实就是一个USB设备的信息,用 struct usb_gadget 来描述。关于USB Gadget的内容将在后续的文章中整理出来。

### avbab set_device_state 的含义与用法 在 Linux 内核开发中,`set_device_state` 类似的函数通常用于设置设备的状态。虽然没有直接提到 `avbab set_device_state` 的具体定义,但可以推测其功能类似于其他设备状态管理函数,例如 `usb_gadget_set_state()` [^3] 或者其他状态管理机制。 以下是可能的解释和用法: #### 1. **函数定义** 假设 `avbab set_device_state` 是一个用于设置设备状态的 API,其定义可能如下: ```c void avbab_set_device_state(struct device *dev, enum device_state state); ``` - 参数 `struct device *dev`:表示目标设备。 - 参数 `enum device_state state`:表示要设置的目标状态。 #### 2. **功能描述** 该函数的主要作用是将设备的状态从当前状态切换到目标状态。这种状态切换可能涉及以下操作: - 更新设备内部的状态变量。 - 触发相关的回调函数或工作队列。 - 将状态信息同步到用户空间(如通过 sysfs)[^3]。 #### 3. **代码示例** 以下是一个可能的实现示例: ```c #include <linux/device.h> enum device_state { DEVICE_STATE_OFFLINE, DEVICE_STATE_ONLINE, DEVICE_STATE_SUSPENDED, DEVICE_STATE_ERROR, }; void avbab_set_device_state(struct device *dev, enum device_state state) { if (!dev) { pr_err("Device is NULL\n"); return; } // 检查状态是否合法 if (state < DEVICE_STATE_OFFLINE || state > DEVICE_STATE_ERROR) { pr_err("Invalid device state: %d\n", state); return; } // 设置设备状态 dev->state = state; // 触发状态变更通知 schedule_work(&dev->work); pr_info("Device state changed to %d\n", state); } ``` #### 4. **调用示例** 在实际使用中,可以通过以下方式调用该函数: ```c struct device *my_device = get_device(dev); // 获取设备对象 [^1] if (my_device) { avbab_set_device_state(my_device, DEVICE_STATE_ONLINE); put_device(my_device); // 释放设备引用计数 } ``` #### 5. **注意事项** - 确保设备对象有效且非空。 - 状态值必须在合法范围内。 - 如果状态变更涉及到硬件配置(如电源管理),需要确保底层驱动支持相关操作 [^2]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值