USB Gadget设备端驱动架构(一):基本架构

参考文献:《Linux 设备驱动开发详解:基于最新的Linux4.0内核》

其他参考: 文中引用的代码版本为 Linux Kernel 4.9 (高通SDM670平台)

USB Gadget设备端驱动架构总目录

一、Gadget基本架构分层

从USB设备侧角度来看,分为三个层次:底层:UDC(USB Device Controller)驱动,中间层:Gadget Function API接口以及实现具体功能的上层:Gadget Function驱动程序。

UDC直接访问底层硬件设备控制器,向上层提供硬件相关的API回调函数,Gadget Function API对UDC的回调函数进行简单的包装,这层API可以看做是中间层,将下层的UDC驱动与上层的Function隔离,从而将功能实现与底层通信分开。最上层的Gadget Function具体控制USB设备的功能,使设备表现出具体的功能,如UVC,MTP等。

二、USB设备描述符

USB设备分为设备(Device),配置(Configuration),接口(Interface),端点(Endpoint)四个层次。

Device可以包含一个多多个配置,配置由多个接口组成,依次类推接口最终具体到USB的端点。接口代表基本的功能。一个配置中的所有接口可以同时有效。

端点是最基本的通信形式,USB设备接口本质上是端点的集合,主机只能通过端点与设备进行通信,来使用设备的功能。每个端点是单向的PIPE,端点0为控制端点,用于设备初始化参数等。端点1,2一般为数据端点。

(1)设备描述符

描述设备通用信息,如USB版本号,供应商,PID,等

内核代码中定义如下 (include/uapi/linux/usb/ch9.h)

 282 /* USB_DT_DEVICE: Device descriptor */
 283 struct usb_device_descriptor {
 284         __u8  bLength;       //描述符长度
 285         __u8  bDescriptorType; //描述符类型编号
 286
 287         __le16 bcdUSB;   //USB版本号
 288         __u8  bDeviceClass; //设备类
 289         __u8  bDeviceSubClass; //设备子类
 290         __u8  bDeviceProtocol; //协议
 291         __u8  bMaxPacketSize0; //端点0 最大包大小
 292         __le16 idVendor;  //VID
 293         __le16 idProduct; //PID
 294         __le16 bcdDevice; //出厂编号
 295         __u8  iManufacturer; //供应商
 296         __u8  iProduct; //产品名称
 297         __u8  iSerialNumber; //序列号
 298         __u8  bNumConfigurations; //可能的配置数量
 299 } __attribute__ ((packed));

例如高通目标设备的设备描述符为:

可以看到当前的信息如下USB版本为2.1, 端点0支持64 byte的数据长度,厂商为高通,供应商为Pico等。

(2)配置描述符

描述配置所需要的接口数量,功耗要求,内核中的代码定义为: (include/uapi/linux/usb/ch9.h)

 339 struct usb_config_descriptor {
 340         __u8  bLength;       //描述符长度
 341         __u8  bDescriptorType;  //描述符类型
 342
 343         __le16 wTotalLength; //配置所返回的所有数据的总长度,即各个描述符长度之和
 344         __u8  bNumInterfaces;  //配置所支持的接口数量
 345         __u8  bConfigurationValue; //设置此配置需要的参数
 346         __u8  iConfiguration; //描述该配置的字符串的索引值
 347         __u8  bmAttributes; //供电模式
 348         __u8  bMaxPower; //最大电流
 349 } __attribute__ ((packed));

(3)接口描述符

接口类,子类适用的协议,USB接口内核中适用usb_interface结构体描述,而USB接口描述符定义如下(include/uapi/linux/usb/ch9.h)

 376 struct usb_interface_descriptor {
 377         __u8  bLength;   //描述符长度
 378         __u8  bDescriptorType;  //描述符类型
 379
 380         __u8  bInterfaceNumber;  //描述符编号
 381         __u8  bAlternateSetting; //备用的接口描述符编号
 382         __u8  bNumEndpoints;  //接口使用的端点数,不包括端点0
 383         __u8  bInterfaceClass; //接口类型
 384         __u8  bInterfaceSubClass; //子类
 385         __u8  bInterfaceProtocol; //协议
 386         __u8  iInterface; //接口的字符串索引值
 387 } __attribute__ ((packed));

(4)端点描述符

端点地址,方向类型支持的最大包大小,中断类型包含轮询频率,内核中定义为:(include/uapi/linux/usb/ch9.h)

 394 struct usb_endpoint_descriptor {
 395         __u8  bLength;
 396         __u8  bDescriptorType;
 397
 398         __u8  bEndpointAddress;//端点地址,0-3是断点号,7位是方向(0输入,1输出)
 399         __u8  bmAttributes; //端点属性 bit0-1, 00控制,01同步 02批量 03中断
 400         __le16 wMaxPacketSize;//包长度
 401         __u8  bInterval;//轮询数据时间间隔,同步为1,中断为1-255 其他忽略
 402
 403         /* NOTE:  these two are _only_ in audio endpoints. */
 404         /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
 405         __u8  bRefresh;
 406         __u8  bSynchAddress;
 407 } __attribute__ ((packed));

三、Gadget的核心数据结构

USB设备控制器usb_gadget,UDC操作usb_gadget_ops, 描述一个端点的usb_ep以及描述端点操作的usb_ep_ops

(1)USB设备控制器描述 usb_gadget  (include/linux/usb/gadget.h)

 504 struct usb_gadget {
 505         struct work_struct              work;
 506         struct usb_udc                  *udc;
 507         /* readonly to gadget driver */
 508         const struct usb_gadget_ops     *ops;
 509         struct usb_ep                   *ep0;
 510         struct list_head                ep_list;        /* of usb_ep */
 511         enum usb_device_speed           speed;
 512         enum usb_device_speed           max_speed;
 513         enum usb_device_state           state;
 514         const char                      *name;
 515         struct device                   dev;
 516         unsigned                        out_epnum;
 517         unsigned                        in_epnum;
 518         unsigned                        mA;
 519         struct usb_otg_caps             *otg_caps;
 520
 521         unsigned                        sg_supported:1;
 522         unsigned                        is_otg:1;
 523         unsigned                        is_a_peripheral:1;
 524         unsigned                        b_hnp_enable:1;
 525         unsigned                        a_hnp_support:1;
 526         unsigned                        a_alt_hnp_support:1;
 527         unsigned                        hnp_polling_support:1;
 528         unsigned                        host_request_flag:1;
 529         unsigned                        quirk_ep_out_aligned_size:1;
 530         unsigned                        quirk_altset_not_supp:1;
 531         unsigned                        quirk_stall_not_supp:1;
 532         unsigned                        quirk_zlp_not_supp:1;
 533         unsigned                        quirk_avoids_skb_reserve:1;
 534         unsigned                        is_selfpowered:1;
 535         unsigned                        deactivated:1;
 536         unsigned                        connected:1;
 537         bool                            remote_wakeup;
 538         bool                            bam2bam_func_enabled;
 539         u32                             extra_buf_alloc;
 540         bool                            l1_supported;
 541         bool                            is_chipidea;
 542 };

(2)USB设备控制器的操作函数  (include/linux/usb/gadget.h)

 418 struct usb_gadget_ops {
 419         int     (*get_frame)(struct usb_gadget *);
 420         int     (*wakeup)(struct usb_gadget *);
 421         int     (*func_wakeup)(struct usb_gadget *, int interface_id);
 422         int     (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
 423         int     (*vbus_session) (struct usb_gadget *, int is_active);
 424         int     (*vbus_draw) (struct usb_gadget *, unsigned mA);
 425         int     (*pullup) (struct usb_gadget *, int is_on);
 426         int     (*ioctl)(struct usb_gadget *,
 427                                 unsigned code, unsigned long param);
 428         void    (*get_config_params)(struct usb_dcd_config_params *);
 429         int     (*udc_start)(struct usb_gadget *,
 430                         struct usb_gadget_driver *);
 431         int     (*udc_stop)(struct usb_gadget *);
 432         struct usb_ep *(*match_ep)(struct usb_gadget *,
 433                         struct usb_endpoint_descriptor *,
 434                         struct usb_ss_ep_comp_descriptor *);
 435         int     (*restart)(struct usb_gadget *);
 436 };

(3)USB端点描述 (include/linux/usb/gadget.h)

 321 struct usb_ep {
 322         void                    *driver_data;
 323
 324         const char              *name;
 325         const struct usb_ep_ops *ops;
 326         struct list_head        ep_list;
 327         struct usb_ep_caps      caps;
 328         bool                    claimed;
 329         bool                    enabled;
 330         unsigned                maxpacket:16;
 331         unsigned                maxpacket_limit:16;
 332         unsigned                max_streams:16;
 333         unsigned                mult:2;
 334         unsigned                maxburst:5;
 335         u8                      address;
 336         const struct usb_endpoint_descriptor    *desc;
 337         const struct usb_ss_ep_comp_descriptor  *comp_desc;
 338         enum ep_type            ep_type;
 339         u8                      ep_num;
 340         u8                      ep_intr_num;
 341         bool                    endless;
 342 };

(4)USB端点操作 (include/linux/usb/gadget.h)


 226 struct usb_ep_ops {
 227         int (*enable) (struct usb_ep *ep,
 228                 const struct usb_endpoint_descriptor *desc);
 229         int (*disable) (struct usb_ep *ep);
 230
 231         struct usb_request *(*alloc_request) (struct usb_ep *ep,
 232                 gfp_t gfp_flags);
 233         void (*free_request) (struct usb_ep *ep, struct usb_request *req);
 234
 235         int (*queue) (struct usb_ep *ep, struct usb_request *req,
 236                 gfp_t gfp_flags);
 237         int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
 238
 239         int (*set_halt) (struct usb_ep *ep, int value);
 240         int (*set_wedge) (struct usb_ep *ep);
 241
 242         int (*fifo_status) (struct usb_ep *ep);
 243         void (*fifo_flush) (struct usb_ep *ep);
 244         int (*gsi_ep_op)(struct usb_ep *ep, void *op_data,
 245                 enum gsi_ep_op op);
 246
 247 };

在UDC驱动中,封装并实现上述的四个描述和操作的结构体,通过usb_add_gadget_udc()来注册UDC(drivers/usb/gadget/udc/core.c)

1278 int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
1279 {
1280         return usb_add_gadget_udc_release(parent, gadget, NULL);
1281 }

1162 int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
1163                 void (*release)(struct device *dev))

在function中需要填充usb_interface_descriptor , usb_endpoint_descriptor, 合成usb_descriptor_header,实现usb_function的成员函数

这些描述符以UVC为例,都在f_uvc.c中定义,按照第二部分USB描述符的结构编辑。

例如:

 79 static struct usb_interface_descriptor uvc_control_intf = {
 80         .bLength                = USB_DT_INTERFACE_SIZE,
 81         .bDescriptorType        = USB_DT_INTERFACE,
 82         .bInterfaceNumber       = UVC_INTF_VIDEO_CONTROL,
 83         .bAlternateSetting      = 0,
 84         .bNumEndpoints          = 1,
 85         .bInterfaceClass        = USB_CLASS_VIDEO,
 86         .bInterfaceSubClass     = UVC_SC_VIDEOCONTROL,
 87         .bInterfaceProtocol     = 0x01,
 88         .iInterface             = 0,
 89 };

同时需要实现usb_function结构体的成员函数,usb_function结构体定义于(include/linux/usb/composite.h)

199 struct usb_function {
200         const char                      *name;
201         int                             intf_id;
202         struct usb_gadget_strings       **strings;
203         struct usb_descriptor_header    **fs_descriptors;//全速低俗描述符表
204         struct usb_descriptor_header    **hs_descriptors;//高速描述符表
205         struct usb_descriptor_header    **ss_descriptors;//超高速描述符表
206         struct usb_descriptor_header    **ssp_descriptors;
207
208         struct usb_configuration        *config;
209
210         struct usb_os_desc_table        *os_desc_table;
211         unsigned                        os_desc_n;
212
213         /* REVISIT:  bind() functions can be marked __init, which
214          * makes trouble for section mismatch analysis.  See if
215          * we can't restructure things to avoid mismatching.
216          * Related:  unbind() may kfree() but bind() won't...
217          */
218
219         /* configuration management:  bind/unbind */
220         int                     (*bind)(struct usb_configuration *,
221                                         struct usb_function *);//获取IO缓冲端点等资源
222         void                    (*unbind)(struct usb_configuration *,
223                                         struct usb_function *);
224         void                    (*free_func)(struct usb_function *f);
225         struct module           *mod;
226
227         /* runtime state management */
228         int                     (*set_alt)(struct usb_function *,
229                                         unsigned interface, unsigned alt);
230         int                     (*get_alt)(struct usb_function *,
231                                         unsigned interface);
232         void                    (*disable)(struct usb_function *);
233         int                     (*setup)(struct usb_function *,
234                                         const struct usb_ctrlrequest *);
235         bool                    (*req_match)(struct usb_function *,
236                                         const struct usb_ctrlrequest *,
237                                         bool config0);
238         void                    (*suspend)(struct usb_function *);
239         void                    (*resume)(struct usb_function *);
240
241         /* USB 3.0 additions */
242         int                     (*get_status)(struct usb_function *);
243         int                     (*func_suspend)(struct usb_function *,
244                                                 u8 suspend_opt);
245         unsigned                func_is_suspended:1;
246         unsigned                func_wakeup_allowed:1;
247         unsigned                func_wakeup_pending:1;
248         /* private: */
249         /* internals */
250         struct list_head                list;
251         DECLARE_BITMAP(endpoints, 32);
252         const struct usb_function_instance *fi;
253
254         unsigned int            bind_deactivated:1;
255 };

以UVC为例挂载时需要执行的流程为

uvc_init
uvc_alloc_inst
uvcg_attach_configfs

uvc_alloc
uvc_function_bind
uvc_copy_descriptors
uvc_copy_descriptors
uvc_copy_descriptors
uvc_register_video

上述的描述符以及usb_function成员函数填充好以后,内核通过下面这个API来完成function的注册(drivers/usb/gadget/function.c)

 int usb_function_register(struct usb_function_driver *newf);
 90 int usb_function_register(struct usb_function_driver *newf)
 91 {
 92         struct usb_function_driver *fd;
 93         int ret;
 94         pr_err("SOLEN in %s",__func__);
 95         ret = -EEXIST;
 96         mutex_lock(&func_lock);
 97         list_for_each_entry(fd, &func_list, list) {
 98                 if (!strcmp(fd->name, newf->name))
 99                         {
100                         pr_err("SOLEN in %s go to out",__func__);
101                         goto out;
102                         }
103         }
104         ret = 0;
105         list_add_tail(&newf->list, &func_list);
106         pr_err("SOLEN in list_add_tail \n");
107 out:
108         mutex_unlock(&func_lock);
109         return ret;
110 }

四、端口通讯

(一)USB_REQUEST

Gadget使用usb_request来描述传输请求,(include/linux/usb/gadget.h)

 193 struct usb_request {
 194         void                    *buf;
 195         unsigned                length;
 196         dma_addr_t              dma;
 197
 198         struct scatterlist      *sg;
 199         unsigned                num_sgs;
 200         unsigned                num_mapped_sgs;
 201
 202         unsigned                stream_id:16;
 203         unsigned                no_interrupt:1;
 204         unsigned                zero:1;
 205         unsigned                short_not_ok:1;
 206
 207         void                    (*complete)(struct usb_ep *ep,
 208                                         struct usb_request *req);
 209         void                    *context;
 210         struct list_head        list;
 211
 212         int                     status;
 213         unsigned                actual;
 214         unsigned int            udc_priv;
 215 };

 

猜你喜欢

转载自blog.csdn.net/musicalspace/article/details/81183798
今日推荐