基于android4.0的usb gadget分析专题(1)

分析前还是先扯几句吧:今天有心情看点代码,就做一点笔记吧,不过android的usb gadget代码不多,但是层次复杂,再加上没人写这方便的文章,所以也没有什么可以参考的,只能自己悟啦,再看之前建议你把设备驱动模型搞懂,要不跟代 码会跟的你吐血的,设备驱动模型网上有很多啦,你花上几个小时跟下代码就基本知道什么意思啦,我记得有个博客是http://blog.csdn.net/king_208讲的相当棒,好啦,不懂驱动模型的就去看吧!下面分析几个大的函数吧!

点击(此处)折叠或打开

  1. struct android_dev {
  2.     struct android_usb_function **functions;
  3.     struct list_head enabled_functions;
  4.     struct usb_composite_dev *cdev;
  5.     struct device *dev;
  6.     bool enabled;
  7.     struct mutex mutex;
  8.     bool connected;
  9.     bool sw_connected;
  10.     struct work_struct work;
  11. };

上面的这个结构相当重要,几乎贯穿了整个usb gadget驱动,相当于一个全局的纽带。

  1. static int __init init(void)
  2. {
  3.     struct android_dev *dev;
  4.     int err;
  5.     /*下面创建一个class,创建这个class的目的是支持用户空间的udev,自动创建设备节点*/
  6.     android_class = class_create(THIS_MODULE, "android_usb");
  7.     if (IS_ERR(android_class))
  8.         return PTR_ERR(android_class);
  9.     dev = kzalloc(sizeof(*dev), GFP_KERNEL);//分配一个该结构体的实例
  10.     if (!dev)
  11.         return -ENOMEM;
  12.     dev->functions = supported_functions;// 初始化该结构体的functions成员
  13.  
  14.    /*该结构体的定义如下*/
  15.    static struct android_usb_function *supported_functions[] = {
        &adb_function,//支持的adb功能
        &acm_function,
        &mtp_function,
        &ptp_function,
        &rndis_function,
        &mass_storage_function,//支持的大容量存储功能
        &accessory_function,
        NULL
       }; 
  16.     INIT_LIST_HEAD(&dev->enabled_functions);//初始化dev的enabled_functions成员链表头
  17.     INIT_WORK(&dev->work, android_work);//初始化dev的work成员,支持的工作队列
  18.     mutex_init(&dev->mutex);//初始化dev的成员mutex互斥锁
  19.     err = android_create_device(dev);//在该函数中继续初始化android_dev中的成员dev,其中用到上面的android_class类,支持动态创建设备节点,并为该设备创建属性。
  20.     if (err) {
  21.         class_destroy(android_class);
  22.         kfree(dev);
  23.         return err;
  24.     }
  25.     /*把初始化好的android_dev变量dev,存到一个全局变量中,供后面访问*/
  26.     _android_dev = dev;
  27.     /* 对composite driver中的setup和disconnect函数重新赋值 */
  28.     composite_driver.setup = android_setup;
  29.     composite_driver.disconnect = android_disconnect;
  30.     /*下面这个函数才是函数的开始,到里面牵涉的东西会越来越多,后面先把他的两个参数给贴出了*/
  31.     return usb_composite_probe(&android_usb_driver, android_bind);
  32. }

composite_driver的定义如下

  1. static struct usb_gadget_driver composite_driver = {
  2.     .speed        = USB_SPEED_HIGH,
  3.     .unbind        = composite_unbind,
  4.  
  5.      /*下面这两个函数会重新赋值*/
  6.     .setup        = composite_setup,
  7.     .disconnect    = composite_disconnect,
  8.     .suspend    = composite_suspend,
  9.     .resume        = composite_resume,
  10.     .driver    = {
  11.         .owner        = THIS_MODULE,
  12.     },
  13. };

这是上面的函数的第一个参数

  1. static struct usb_composite_driver android_usb_driver = {
  2.     .name        = "android_usb",//该复合设备驱动的名称
  3.     .dev        = &device_desc,//设备描述符
  4.     .strings    = dev_strings,
  5.     .unbind        = android_usb_unbind,
  6. };

这是上面的函数的第二个参数

  1. static int android_bind(struct usb_composite_dev *cdev)
  2. {
  3.     struct android_dev *dev = _android_dev;
  4.     struct usb_gadget    *gadget = cdev->gadget;
  5.     int            gcnum, id, ret;
  6.     usb_gadget_disconnect(gadget);
  7.     ret = android_init_functions(dev->functions, cdev);
  8.     if (ret)
  9.         return ret;
  10.     /* Allocate string descriptor numbers ... note that string
  11.      * contents can be overridden by the composite_dev glue.
  12.      */
  13.     id = usb_string_id(cdev);
  14.     if (id < 0)
  15.         return id;
  16.     strings_dev[STRING_MANUFACTURER_IDX].id = id;
  17.     device_desc.iManufacturer = id;
  18.     id = usb_string_id(cdev);
  19.     if (id < 0)
  20.         return id;
  21.     strings_dev[STRING_PRODUCT_IDX].id = id;
  22.     device_desc.iProduct = id;
  23.     /* Default strings - should be updated by userspace */
  24.     strncpy(manufacturer_string, "Android", sizeof(manufacturer_string) - 1);
  25.     strncpy(product_string, "Android", sizeof(product_string) - 1);
  26.     strncpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1);
  27.     id = usb_string_id(cdev);
  28.     if (id < 0)
  29.         return id;
  30.     strings_dev[STRING_SERIAL_IDX].id = id;
  31.     device_desc.iSerialNumber = id;
  32.     gcnum = usb_gadget_controller_number(gadget);
  33.     if (gcnum >= 0)
  34.         device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
  35.     else {
  36.         /* gadget zero is so simple (for now, no altsettings) that
  37.          * it SHOULD NOT have problems with bulk-capable hardware.
  38.          * so just warn about unrcognized controllers -- don't panic.
  39.          *
  40.          * things like configuration and altsetting numbering
  41.          * can need hardware-specific attention though.
  42.          */
  43.         pr_warning("%s: controller '%s' not recognized\n",
  44.             longname, gadget->name);
  45.         device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
  46.     }
  47.     usb_gadget_set_selfpowered(gadget);
  48.     dev->cdev = cdev;
  49.     return 0;
  50. }

好啦,今天就到此结束吧,最后了解下一个概念,复合设备,什么是复合设备呢?
Example:  a device with a single configuration supporting both network
 link and mass storage functions is a composite device.  Those functions
 might alternatively be packaged in individual configurations, but in
 the composite model the host can use both functions at the same time.
英语就不用我解释了吧,相信大家都能看懂,真要是不懂的话,找google大神。今天已经很晚啦,有空继续分析。

posted @ 2015-07-26 17:37  zxiaocheng  阅读(751)  评论(0)    收藏  举报