Android usb驱动模块 g_android.ko rmmod issues

http://blog.csdn.net/HellDevil/article/details/5213888

我最近在调试Android系统的gadget功能,通过make menuconfig发现gadget是编译成module模式的。里面有很多可选项,其中有个Android的选项,其实就是提供ADB和Storage的功能的。

 

具体查看代码在/drivers/usb/gadget下,三个文件:android.c f_adb.c f_mass_storage.c

g_android.ko 是由这三个文件而来,其中android.c 依赖于f_adb.c 和f_mass_storage.c(这两个文件之间无依赖关系)

可以在android.c中的

 

[cpp]  view plain copy
  1. static int __init android_bind_config(struct usb_configuration *c)  
  2. {  
  3.     struct android_dev *dev = _android_dev;  
  4.     int ret;  
  5.     printk(KERN_DEBUG "android_bind_config/n");  
  6.     ret = mass_storage_function_add(dev->cdev, c, dev->nluns);  
  7.     if (ret)  
  8.         return ret;  
  9.     return adb_function_add(dev->cdev, c);  
  10. }  
 

看到关系

============================================================

下面说说我的问题,

1.当我将Android编译成module模式,既g_android.ko时候,然后放入rootfs中手动加载,Okay, no problem!非常happy。但是,当我关闭adb进程,rmmod g_android的时候,出现死锁状态,打开代码进行查询,发现问题出现在

 

 

[c-sharp] view plain copy
  1. struct usb_request *req_get(struct adb_dev *dev, struct list_head *head, int DD)  
  2. {  
  3. unsigned long flags;  
  4. struct usb_request *req;  
  5. spin_lock_irqsave(&dev->lock, flags);//被锁了,郁闷  
  6. if (list_empty(head)) {  
  7. req = 0;  
  8. else {  
  9. req = list_first_entry(head, struct usb_request, list);  
  10. list_del(&req->list);  
  11. }  
  12. spin_unlock_irqrestore(&dev->lock, flags);  
  13. return req;  
  14. }  

 

一直死锁,通过打开kernel hacking中的spinlock debug发现 是自己把自己锁了,找阿找阿。。。。

看了下rmmod时候 函数调用过程当我rmmod的时候,首先会去执行__exit cleanup(void)中的usb_composite_unregister(&android_usb_driver)这句话中还调用composite.c中的函数 (不细说),反正最后会调到f_adb.c中的

adb_function_unbind(struct usb_configuration *c, struct usb_function *f)

看看这个函数

  1. static void  
  2. adb_function_unbind(struct usb_configuration *c, struct usb_function *f)  
  3. {  
  4.       
  5.     struct adb_dev  *dev = func_to_dev(f);  
  6.     struct usb_request *req;  
  7.    
  8.     spin_lock_irq(&dev->lock);//锁死你个req_get,谁叫我们共用一个dev->lock  
  9.       
  10.     while ((req=req_get(dev, &dev->rx_idle,0)))//被所到死  
  11.          {  
  12.         adb_request_free(req, dev->ep_out);  
  13.      }  
  14.     while ((req=req_get(dev, &dev->tx_idle,0)))  
  15.     {  
  16.          adb_request_free(req, dev->ep_in);  
  17.     }  
  18.     dev->online = 0;  
  19.     dev->error = 1;  
  20.     spin_unlock_irq(&dev->lock);  
  21.     
  22.     misc_deregister(&adb_device);  
  23.     kfree(_adb_dev);  
  24.       
  25.     _adb_dev = NULL;  
  26.       
  27. }  

所以感觉 req_get代码中的spinlock有问题,没办法,只能写了个req_get_free_lock(不加锁)替代while循环中的req_get函数

rebuild 内核,Okay 卸载g_android.ko 没问题 哈哈。正当自己高兴的时候,发现乐极生悲了。。。

===========================================================

卸载完了g_android.ko 我再次insmod g_android.ko 挂了,不过不是kernel panic而是提示

"sysfs: duplicate filename 'usb_mass_storage' can not be created"

恩 这次出在f_mass_storage.c这个文件中,根据信息提示应该是没因为上次没卸载完全。没办法,在几个与insmod和rmmod的函数中加入打印信息。主要是mass_storage_function_add, fsg_function_bind,fsg_function_unbind三个函数,前两个是跟insmod有关,后者跟rmmod有关。

通过打印信息发现一个Android开发者的 小纰漏 导致的问题,就是在

[cpp]  view plain copy
  1. int __init mass_storage_function_add(struct usb_composite_dev *cdev,  
  2.     struct usb_configuration *c, int nluns)  
  3. {  
  4.     int     rc;  
  5.     struct fsg_dev  *fsg;  
  6.     printk(KERN_INFO "mass_storage_function_add/n");  
  7.     rc = fsg_alloc();  
  8.     if (rc)  
  9.         return rc;  
  10.     fsg = the_fsg;  
  11.     fsg->nluns = nluns;  
  12.      
  13.     spin_lock_init(&fsg->lock);  
  14.     init_rwsem(&fsg->filesem);  
  15.     kref_init(&fsg->ref);  
  16.     init_completion(&fsg->thread_notifier);  
  17.       
  18.     the_fsg->buf_size = BULK_BUFFER_SIZE;  
  19.     the_fsg->sdev.name = DRIVER_NAME;  
  20.     the_fsg->sdev.print_name = print_switch_name;  
  21.     the_fsg->sdev.print_state = print_switch_state;  
  22.       
  23.       
  24.     rc = switch_dev_register(&the_fsg->sdev);//卸载的时候没有swith_dev_unregister  
  25.       
  26.       
  27.     if (rc < 0)  
  28.         goto err_switch_dev_register;  
  29.     wake_lock_init(&the_fsg->wake_lock, WAKE_LOCK_SUSPEND,  
  30.                "usb_mass_storage");  
  31.       
  32.     fsg->cdev = cdev;  
  33.     fsg->function.name = shortname;  
  34.     fsg->function.descriptors = fs_function;  
  35.     fsg->function.bind = fsg_function_bind;  
  36.     fsg->function.unbind = fsg_function_unbind;  
  37.     fsg->function.setup = fsg_function_setup;  
  38.     fsg->function.set_alt = fsg_function_set_alt;  
  39.     fsg->function.disable = fsg_function_disable;  
  40.       
  41.     rc = usb_add_function(c, &fsg->function);  
  42.       
  43.     if (rc != 0)  
  44.         goto err_usb_add_function;  
  45.     return 0;  
  46. err_usb_add_function:  
  47.     switch_dev_unregister(&the_fsg->sdev);  
  48. err_switch_dev_register:  
  49.     kref_put(&the_fsg->ref, fsg_release);  
  50.       
  51.     return rc;  
  52. }  
 

在掉用过/drivers/switch/class_switch.c 中的 switch_dev_register后,除了出错处理再也没作擦屁股的动作(unregister)汗,这不是占着XX不拉什么吗?没办法,去fsg_function_unbind函数中的

[cpp]  view plain copy
  1. for (i = 0; i < fsg->nluns; ++i) {  
  2.         curlun = &fsg->luns[i];  
  3.         if (curlun->registered) {  
  4.             switch_dev_unregister(&the_fsg->sdev);//加入擦屁股的一句  
  5.             device_remove_file(&curlun->dev, &dev_attr_file);  
  6.             device_unregister(&curlun->dev);  
  7.             curlun->registered = 0;  
  8.         }  
  9.     }  
 

Okay 万事Okay 主阿!其实都不是什么大的问题拉。但是导致的现象确很恐怖。android developer太忙了,毕竟也是人阿。呵呵,以前都不敢改他们代码,总是推敲自己是不是哪边错了。想报bug去android开发者论坛,但是被该死的河蟹给和谐了,打不开report issue界面。感谢伟大的政府让我们这些P民,成为白痴和弱智。

草泥马的 !


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值