一、USB設備狀態
在USB 2.0協議中第 9.1 USB Device States 章節規定了USB設備的6種狀態,包括:
Attached/Powered/Default/Address/Configured/Suspended
其狀態遷移圖如下:
在 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->work 到 usb_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的內容將在后續的文章中整理出來。