1. 程式人生 > 實用技巧 >linux裝置驅動(26)usb驅動-基本資料和api

linux裝置驅動(26)usb驅動-基本資料和api

usb驅動目錄drivers/usb/*

usb/serial:usb 序列裝置驅動 (例如usb 3G卡、藍芽等);

usb/storage:usb 大儲量磁碟驅動(u盤);

usb/host:usb host usb主機控制器驅動(嵌入式otg:dwc_otg);

usb/core:usb 核心一些處理程式碼,所有的驅動相關處理都在這裡,也都註冊到它裡面。

usb/usb-skeleton.c:經典的usb客戶驅動框架,可以參考。

1 主要資料結構體

1.1 usb device裝置結構體

定義位於:include\linux\usb.h

 1 struct usb_device {
 2     int
devnum;//裝置號,是在USB匯流排的地址 3 char devpath[16];//用於訊息的裝置ID字串 4 u32 route; 5 enum usb_device_state state;//裝置狀態:已配置、未連線等 6 enum usb_device_speed speed; 7 8 struct usb_tt *tt;//處理傳輸者資訊;用於低速、全速裝置和高速HUB 9 int ttport;//位於tt HUB的裝置口 10 11 unsigned int
toggle[2];//每個端點的佔一位,表明端點的方向([0] = IN, [1] = OUT) 12 13 struct usb_device *parent;//上一級HUB指標 14 struct usb_bus *bus;//匯流排指標 15 struct usb_host_endpoint ep0;//端點0資料 16 17 struct device dev;//一般的裝置介面資料結構 18 19 struct usb_device_descriptor descriptor;//USB裝置描述符 20 struct usb_host_bos *bos;
21 struct usb_host_config *config;//裝置的所有配置結構體,配置結構體裡包含了配置描述符 22 23 struct usb_host_config *actconfig;/被啟用的裝置配置 24 struct usb_host_endpoint *ep_in[16];//輸入端點陣列 25 struct usb_host_endpoint *ep_out[16];//輸出端點陣列 26 char **rawdescriptors;//每個配置的raw描述符 27 28 unsigned short bus_mA;//可使用的匯流排電流 29 u8 portnum;//父埠號 30 u8 level;//USB HUB的層數 31 32 unsigned can_submit:1;//URB可被提交標誌 33 unsigned persist_enabled:1;//USB_PERSIST使能標誌 34 unsigned have_langid:1;//string_langid存在標誌 35 unsigned authorized:1; 36 unsigned authenticated:1; 37 unsigned wusb:1;//無線USB標誌 38 unsigned lpm_capable:1; 39 unsigned usb2_hw_lpm_capable:1; 40 unsigned usb2_hw_lpm_enabled:1; 41 unsigned usb3_lpm_enabled:1; 42 int string_langid;//字串語言ID 43 44 /* static strings from the device */裝置的靜態字串 45 char *product;//產品名 46 char *manufacturer;//廠商名 47 char *serial;//產品串號 48 49 struct list_head filelist;//此裝置開啟的usbfs檔案 50 51 int maxchild;//(若為HUB)介面數 52 53 u32 quirks; 54 atomic_t urbnum;//這個裝置所提交的URB計數 55 56 unsigned long active_duration;//啟用後使用計時 57 58 #ifdef CONFIG_PM //電源管理相關 59 unsigned long connect_time; 60 61 unsigned do_remote_wakeup:1; 62 unsigned reset_resume:1; 63 unsigned port_is_suspended:1; 64 #endif 65 struct wusb_dev *wusb_dev; 66 int slot_id; 67 enum usb_device_removable removable; 68 struct usb3_lpm_parameters u1_params; 69 struct usb3_lpm_parameters u2_params; 70 unsigned lpm_disable_count; 71 }

1.2 usb driver結構體

代表usb驅動

 1 struct usb_driver {
 2     const char *name;
 3 
 4     int (*probe) (struct usb_interface *intf,
 5               const struct usb_device_id *id);
 6 
 7     void (*disconnect) (struct usb_interface *intf);
 8 
 9     int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,
10             void *buf);
11 
12     int (*suspend) (struct usb_interface *intf, pm_message_t message);
13     int (*resume) (struct usb_interface *intf);
14     int (*reset_resume)(struct usb_interface *intf);
15 
16     int (*pre_reset)(struct usb_interface *intf);
17     int (*post_reset)(struct usb_interface *intf);
18 
19     const struct usb_device_id *id_table;
20 
21     struct usb_dynids dynids;
22     struct usbdrv_wrap drvwrap;
23     unsigned int no_dynamic_id:1;
24     unsigned int supports_autosuspend:1;
25     unsigned int disable_hub_initiated_lpm:1;
26     unsigned int soft_unbind:1;
27 }

1.3 usb bus結構體

代表usb匯流排

 1 struct usb_bus {
 2     struct device *controller;    /* host/master side hardware */
 3     int busnum;            /* Bus number (in order of reg) */
 4     const char *bus_name;        /* stable id (PCI slot_name etc) */
 5     u8 uses_dma;            /* Does the host controller use DMA? */
 6     u8 uses_pio_for_control;    /*
 7                      * Does the host controller use PIO
 8                      * for control transfers?
 9                      */
10     u8 otg_port;            /* 0, or number of OTG/HNP port */
11     unsigned is_b_host:1;        /* true during some HNP roleswitches */
12     unsigned b_hnp_enable:1;    /* OTG: did A-Host enable HNP? */
13     unsigned no_stop_on_short:1;    /*
14                      * Quirk: some controllers don't stop
15                      * the ep queue on a short transfer
16                      * with the URB_SHORT_NOT_OK flag set.
17                      */
18     unsigned sg_tablesize;        /* 0 or largest number of sg list entries */
19 
20     int devnum_next;        /* Next open device number in
21                      * round-robin allocation */
22 
23     struct usb_devmap devmap;    /* device address allocation map */
24     struct usb_device *root_hub;    /* Root hub */
25     struct usb_bus *hs_companion;    /* Companion EHCI bus, if any */
26     struct list_head bus_list;    /* list of busses */
27 
28     int bandwidth_allocated;    /* on this bus: how much of the time
29                      * reserved for periodic (intr/iso)
30                      * requests is used, on average?
31                      * Units: microseconds/frame.
32                      * Limits: Full/low speed reserve 90%,
33                      * while high speed reserves 80%.
34                      */
35     int bandwidth_int_reqs;        /* number of Interrupt requests */
36     int bandwidth_isoc_reqs;    /* number of Isoc. requests */
37 
38     unsigned resuming_ports;    /* bit array: resuming root-hub ports */
39 
40 #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
41     struct mon_bus *mon_bus;    /* non-null when associated */
42     int monitored;            /* non-zero when monitored */
43 #endif
44 }

1.4usb_interface 結構體

 1 struct usb_interface {
 2     /* array of alternate settings for this interface,
 3      * stored in no particular order */
 4     struct usb_host_interface *altsetting;
 5 
 6     struct usb_host_interface *cur_altsetting;    /* the currently   //當前使用的設定,usb_host_interface中desc成員就是usb介面描述符
 7                      * active alternate setting */
 8     unsigned num_altsetting;    /* number of alternate settings */可選的設定數量
 9 
10     /* If there is an interface association descriptor then it will list
11      * the associated interfaces */
12     struct usb_interface_assoc_descriptor *intf_assoc;
13 
14     int minor;            /* minor number this interface is//如果繫結到這個介面的 USB 驅動使用 USB 主裝置號, 這個變數包含由 USB 核心分配給介面的次裝置號. 這隻在一個成功的呼叫 usb_register_dev後才有效
15                      * bound to */
16     enum usb_interface_condition condition;        /* state of binding */
17     unsigned sysfs_files_created:1;    /* the sysfs attributes exist */
18     unsigned ep_devs_created:1;    /* endpoint "devices" exist */
19     unsigned unregistering:1;    /* unregistration is in progress */
20     unsigned needs_remote_wakeup:1;    /* driver requires remote wakeup */
21     unsigned needs_altsetting0:1;    /* switch to altsetting 0 is pending */
22     unsigned needs_binding:1;    /* needs delayed unbind/rebind */
23     unsigned reset_running:1;
24     unsigned resetting_device:1;    /* true: bandwidth alloc after reset */
25 
26     struct device dev;        /* interface specific device info */
27     struct device *usb_dev;
28     atomic_t pm_usage_cnt;        /* usage counter for autosuspend */
29     struct work_struct reset_ws;    /* for resets in atomic context */
30 }

1.5usb_host_interface 結構體

具體到介面描述符,它當然就是描述介面本身的資訊的。一個介面可以有多個設定,使用不同的設定,描述介面的資訊會有些不同,所以介面描述符並沒有放在struct usb_interface結構裡,而是放在表示介面設定的struct usb_host_interface結構裡。

 1 struct usb_host_interface {
 2     struct usb_interface_descriptor    desc;//usb介面描述符
 3 
 4     int extralen;
 5     unsigned char *extra;   /* Extra descriptors */
 6 
 7     /* array of desc.bNumEndpoint endpoints associated with this
 8      * interface setting.  these will be in no particular order.
 9      */
10     struct usb_host_endpoint *endpoint;//這個設定所使用的端點
11 
12     char *string;        /* iInterface string, if present */
13 }

1.6 usb配置結構體

 1 struct usb_host_config {
 2     struct usb_config_descriptor    desc;//usb配置結構體
 3 
 4     char *string;        /* iConfiguration string, if present */
 5 
 6     /* List of any Interface Association Descriptors in this
 7      * configuration. */
 8     struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
 9 
10     /* the interfaces associated with this configuration,
11      * stored in no particular order */
12     struct usb_interface *interface[USB_MAXINTERFACES];//配置所包含的介面,這個陣列的順序未必是按照配置裡介面號的順序
13 
14     /* Interface information available even when this is not the
15      * active configuration */
16     struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];//usb介面的快取
17 
18     unsigned char *extra;   /* Extra descriptors */
19     int extralen;
20 }

1.7 usb端點結構體

 1 struct usb_host_endpoint {
 2     struct usb_endpoint_descriptor        desc;//usb端點描述符
 3     struct usb_ss_ep_comp_descriptor    ss_ep_comp;
 4     struct list_head        urb_list;//端點要處理的urb佇列.urb是usb通訊的主角,裝置中的每個端點都可以處理一個urb佇列.要想和你的usb通訊,就得建立一個urb,並且為它賦好值,交給咱們的usb core,它會找到合適的host controller,從而進行具體的資料傳輸。
 5     void                *hcpriv;//這是提供給HCD(host controller driver)用的
 6     struct ep_device        *ep_dev;    /* For sysfs info */
 7 
 8     unsigned char *extra;   /* Extra descriptors */
 9     int extralen;
10     int enabled;
11 };

2 主要api

2.1 usb驅動註冊函式

定義位於:include\linux\usb.h和drivers\usb\core\driver.c

 1 /* use a define to avoid include chaining to get THIS_MODULE & friends */
 2 #define usb_register(driver) \
 3     usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
 4 
 5 int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
 6             const char *mod_name)
 7 {
 8     int retval = 0;
 9 
10     if (usb_disabled())
11         return -ENODEV;
12 
13     new_driver->drvwrap.for_devices = 0;
14     new_driver->drvwrap.driver.name = (char *) new_driver->name;
15     new_driver->drvwrap.driver.bus = &usb_bus_type;
16     new_driver->drvwrap.driver.probe = usb_probe_interface;
17     new_driver->drvwrap.driver.remove = usb_unbind_interface;
18     new_driver->drvwrap.driver.owner = owner;
19     new_driver->drvwrap.driver.mod_name = mod_name;
20     spin_lock_init(&new_driver->dynids.lock);
21     INIT_LIST_HEAD(&new_driver->dynids.list);
22 
23     retval = driver_register(&new_driver->drvwrap.driver);//註冊usb驅動
24     if (retval)
25         goto out;
26 
27     retval = usb_create_newid_files(new_driver);
28     if (retval)
29         goto out_newid;
30 
31     pr_info("%s: registered new interface driver %s\n",
32             usbcore_name, new_driver->name);
33 
34 out:
35     return retval;
36 
37 out_newid:
38     driver_unregister(&new_driver->drvwrap.driver);
39 
40     printk(KERN_ERR "%s: error %d registering interface "
41             "    driver %s\n",
42             usbcore_name, retval, new_driver->name);
43     goto out;
44 }

1.2 usb裝置分配函式

 1 struct usb_device *usb_alloc_dev(struct usb_device *parent,
 2                  struct usb_bus *bus, unsigned port1)
 3 {
 4     struct usb_device *dev;
 5     struct usb_hcd *usb_hcd = bus_to_hcd(bus);
 6     unsigned root_hub = 0;
 7 
 8     dev = kzalloc(sizeof(*dev), GFP_KERNEL);//分配usb裝置
 9     if (!dev)
10         return NULL;
11 
12     if (!usb_get_hcd(usb_hcd)) {
13         kfree(dev);
14         return NULL;
15     }
16     /* Root hubs aren't true devices, so don't allocate HCD resources */
17     if (usb_hcd->driver->alloc_dev && parent &&
18         !usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
19         usb_put_hcd(bus_to_hcd(bus));
20         kfree(dev);
21         return NULL;
22     }
23 
24     device_initialize(&dev->dev);//初始化usb裝置
25     dev->dev.bus = &usb_bus_type;//指定usb匯流排
26     dev->dev.type = &usb_device_type;
27     dev->dev.groups = usb_device_groups;
28     dev->dev.dma_mask = bus->controller->dma_mask;
29     set_dev_node(&dev->dev, dev_to_node(bus->controller));
30     dev->state = USB_STATE_ATTACHED;
31     dev->lpm_disable_count = 1;
32     atomic_set(&dev->urbnum, 0);
33 
34     INIT_LIST_HEAD(&dev->ep0.urb_list);
35     dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
36     dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
37     /* ep0 maxpacket comes later, from device descriptor */
38     usb_enable_endpoint(dev, &dev->ep0, false);
39     dev->can_submit = 1;
40 
41     /* Save readable and stable topology id, distinguishing devices
42      * by location for diagnostics, tools, driver model, etc.  The
43      * string is a path along hub ports, from the root.  Each device's
44      * dev->devpath will be stable until USB is re-cabled, and hubs
45      * are often labeled with these port numbers.  The name isn't
46      * as stable:  bus->busnum changes easily from modprobe order,
47      * cardbus or pci hotplugging, and so on.
48      */
49     if (unlikely(!parent)) {
50         dev->devpath[0] = '0';
51         dev->route = 0;
52 
53         dev->dev.parent = bus->controller;
54         dev_set_name(&dev->dev, "usb%d", bus->busnum);
55         root_hub = 1;
56     } else {
57         /* match any labeling on the hubs; it's one-based */
58         if (parent->devpath[0] == '0') {
59             snprintf(dev->devpath, sizeof dev->devpath,
60                 "%d", port1);
61             /* Root ports are not counted in route string */
62             dev->route = 0;
63         } else {
64             snprintf(dev->devpath, sizeof dev->devpath,
65                 "%s.%d", parent->devpath, port1);
66             /* Route string assumes hubs have less than 16 ports */
67             if (port1 < 15)
68                 dev->route = parent->route +
69                     (port1 << ((parent->level - 1)*4));
70             else
71                 dev->route = parent->route +
72                     (15 << ((parent->level - 1)*4));
73         }
74 
75         dev->dev.parent = &parent->dev;
76         dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);//設定usb裝置名字
77 
78         /* hub driver sets up TT records */
79     }
80 
81     dev->portnum = port1;
82     dev->bus = bus;
83     dev->parent = parent;
84     INIT_LIST_HEAD(&dev->filelist);
85 
86 #ifdef    CONFIG_PM
87     pm_runtime_set_autosuspend_delay(&dev->dev,
88             usb_autosuspend_delay * 1000);
89     dev->connect_time = jiffies;
90     dev->active_duration = -jiffies;
91 #endif
92     if (root_hub)    /* Root hub always ok [and always wired] */
93         dev->authorized = 1;
94     else {
95         dev->authorized = usb_hcd->authorized_default;
96         dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
97     }
98     return dev;
99 }

1.3 usb初始化函式

包括usb 匯流排的初始化,usb驅動的註冊。usb_init 定義位於:drivers\usb\core\usb.c

 1 static int __init usb_init(void)
 2 {
 3     int retval;
 4     if (nousb) {
 5         pr_info("%s: USB support disabled\n", usbcore_name);
 6         return 0;
 7     }
 8     usb_init_pool_max();
 9 
10     retval = usb_debugfs_init();
11     if (retval)
12         goto out;
13 
14     usb_acpi_register();
15     retval = bus_register(&usb_bus_type);//usb匯流排註冊
16     if (retval)
17         goto bus_register_failed;
18     retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
19     if (retval)
20         goto bus_notifier_failed;
21     retval = usb_major_init();
22     if (retval)
23         goto major_init_failed;
24     retval = usb_register(&usbfs_driver);//usb驅動註冊
25     if (retval)
26         goto driver_register_failed;
27     retval = usb_devio_init();
28     if (retval)
29         goto usb_devio_init_failed;
30     retval = usb_hub_init();
31     if (retval)
32         goto hub_init_failed;
33     retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
34     if (!retval)
35         goto out;
36 
37     usb_hub_cleanup();
38 hub_init_failed:
39     usb_devio_cleanup();
40 usb_devio_init_failed:
41     usb_deregister(&usbfs_driver);
42 driver_register_failed:
43     usb_major_cleanup();
44 major_init_failed:
45     bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
46 bus_notifier_failed:
47     bus_unregister(&usb_bus_type);
48 bus_register_failed:
49     usb_acpi_unregister();
50     usb_debugfs_cleanup();
51 out:
52     return retval;
53 }

usb匯流排的定義初始化,位於drivers\usb\core\driver.c:

1 struct bus_type usb_bus_type = {
2     .name =        "usb",
3     .match =    usb_device_match,
4     .uevent =    usb_uevent,
5 };

參考博文:https://blog.csdn.net/zqixiao_09/article/details/51057086?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

https://www.cnblogs.com/lifexy/p/7631900.html