关于f_mass_storage.c的文章(转载)

原文地址:http://blog.csdn.net/HellDevil/archive/2010/05/18/5604421.aspx

http://blog.csdn.net/HellDevil/archive/2010/05/06/5561918.aspx

http://blog.csdn.net/HellDevil/archive/2010/01/19/5213888.aspx

http://blog.csdn.net/HellDevil/archive/2010/05/15/5596196.aspx

Android usb驱动模块 g_android.ko rmmod issues


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

具体查看代码在/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中的

view plaincopy to clipboardprint?

  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的时候,出现死锁状态,打开代码进行查询,发现问题出现在

view plaincopy to clipboardprint?

  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)

看看这个函数

view plaincopy to clipboardprint?

  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这个文件中,根据信息提示应该是没因为上次没卸载完全。没办法,在几个与insmodrmmod的函数中加入 打印信息。主要是mass_storage_function_add fsg_function_bindfsg_function_unbind 三个函数,前两个是跟insmod有关,后者跟rmmod有关。

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

view plaincopy to clipboardprint?

  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函数中的

view plaincopy to clipboardprint?

  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太忙了,毕竟也是人阿。呵呵,以前都不敢改他们代码,总是推敲自己是不是哪边错了。

Android usb client mass-storage不能自动挂载到主机端的问题(1)

测试平台:Nvidia ARM架构

操作系统:Andorid(Nvidia修改)

       最近在搞Android usb client,发现当将client线分别接上Android系统机器的client端以及主机Host端的时候,AndroidUSB client两大功能中的ADB可以使用,而mass-storage无法使用,即装有Android系统的机器不能将自己的sdhc卡,以及自身的内存 卡挂到host主机端,并且显示。

       输入 ls -l /dev/sd*

       发现终端显示了个叫/dev/sdb 的节点,尝试mount ,提示 无法mount 未知的文件系统。

       Okay,查看Android系统端的init.rc发现 挂载方式是vold.

       查看vold原代码,发现需要读取vold.conf,并且检测UMS

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

       那么大致猜测下和问题有关的可能是Android系统的这么几个:

       1.rootfs  /etc/vold.conf配置可能有问题

       2.vold 的程序可能有问题

       3.linux driver  /driver/usb/gadget/f_mass_storage.c有问题

       4.UMS功能可能有问题

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

大致猜测了问题的所在,那么下一 步就是一步一步确认了。

1.先看看/etc/vold.conf文件,代码在/out/target/product/XX/system/etc/vold.conf

      

view plaincopy to clipboardprint?

  1. volume_sdcard {  
  2.        media_path   /devices/platform/tegra-sdhci.3/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p4  
  3.        media_type   mmc  
  4.        mount_point /sdcard  
  5. }  
  6. UMS的路径没有,个人经验:一般可以在/sys/devices/platform/  
  7. 下面找到一个叫包含"udc"字符的节点,进入它的子目录,会看到lun0的节点。  


进入/sys/devices/platform

这时候会有两种现象出现:1,就是有相应的节点;2,没有

1.如果有,则应该确定该节点是否和你的f_mass_storage驱动相对应,也就是说,这个节点是你的mass_storage驱动创建的,如果不是需要你去创建。

2.如果没有,那么需要在f_mass_storage.c里面去创建它。

我的情况是第一个,目录下有个叫shdc-udc.0/lun0的节点,但是并没有和我的g_android中的mass-storage驱动对应,所以我必须重新创建个。

nvidia提供给我门的/arch/arm/mach-XXX/nvodm_board.c中会有一系列的device_register的动作

创建/sys/devices/platform下的节点 在这需要加入两句

view plaincopy to clipboardprint?

  1. static struct platform_device fsg_platform_device =  
  2. {  
  3.     .name = "usb_mass_storage",  
  4.     .id   = -1,  
  5. };  
  6. static void __init tegra_machine_init(void)  
  7. {  
  8. ....  
  9.  (void) platform_device_register(&fsg_platform_device);  
  10. ....  
  11. }  
  12. 加入这两句okay  


我们会发现/sys/devices/platform/usb_mass_storage/lun0这个目录产生了

这些动作是和你的linux drivermass-storage的驱动内容相对应的。

最后一步,就是需要将新创建的UMS(负责启动usb mass-storage功能) Path加入到你的vold.conf

view plaincopy to clipboardprint?

  1. volume_sdcard {  
  2.        media_path   /devices/platform/tegra-sdhci.3/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p4  
  3.        media_type   mmc  
  4.        mount_point /sdcard  
  5.        ums_path    /devices/platform/usb_mass_storage/lun0  
  6. //加的代码就是这个  
  7. }  


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

打开机器,灌入系统,启动,发现还是不行,在ADB终端中输入sdutil ums enabel 启动ums 实际上我机器已经在开机就启动了UMS功能

logcat显示UMS 挂掉了 一大堆的 堆栈问题 stack 什么的。

估计和内存分配或者指针有关。

估计是vold的代码有问题。

进入android源代码目录/system/core/vold

打开该目录下所有代码,加入打印语句,进行跟踪。

发现当你ums enable时候

1.会进入cmd_dispatch.c执行do_set_ums_enable函数

view plaincopy to clipboardprint?

  1. static int do_set_ums_enable(char *cmd)  
  2. {  
  3.  ...  
  4.  if (!strcmp(cmd, VOLD_CMD_ENABLE_UMS))  
  5.      return volmgr_enable_ums(true);  
  6.  return volmgr_enable_ums(false);  
  7. }  


它又调用了volmgr.c文件中的volmgr_enable_ums(bool enable)

view plaincopy to clipboardprint?

  1. int volmgr_enable_ums(bool enable)  
  2. {  
  3.  ...  
  4.   volume_t *v = vol_root //链表,链表中存储了每个存储设备的相关信息,如state. ums_path, mount_point这些来自于/etc/vold.conf  
  5.   while(v)  
  6.   {  
  7.       if(v->ums_path)  
  8.          if(enable){  
  9.             ...  
  10.             volmgr_shutdown_volume(v, _cb_volstopped_for_ums_enable_false);//程序执行到这句话 挂掉了  
  11.             ...  
  12.           }  
  13.   }  
  14.   


首先我们看看,程序是如何读取/etc/vold.conf配置信息并存储的

主要是这么几个函数volmgr_readconfig, volmgr_config_volume,等等,这里不详细讲,只是大概讲下,

首先 会建立一个大的链表,通过比配vold.confvolume_XX来确定有多少成员 volum_sdcard1 volum_sdcard2

表示有两个成员

然后,会在每个成员里在建一个链表,用于存储ums_path mount_point这些

最后再将这些东西重新在组织成个链表v

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

继续上面的代码说

跟踪volmgr_shutdown_volume()--->volmgr_stop_volume()--->_cb_volstopped_for_ums_enable()

view plaincopy to clipboardprint?

  1. staitc void _cb_volstopped_for_ums_enable(volume_t *v, void *arg)  
  2. {  
  3.       char* devdir_path  
  4.       ...  
  5.       devdir_path = blkdev_get_devpath(v->dev->disk);//挂了  
  6.       ...  
  7. }  


继续跟下去到blkdev.c

view plaincopy to clipboardprint?

  1. char *blkdev_get_devpath(blkdev_t *blk)  
  2. {  
  3.      ....  
  4.      char *dp = malloc(256);  
  5.      sprintf(dp, "%s/vold/%d:%d", blk->major, blk->minor);//挂掉  
  6. }  
  7. 经过调试 发现blk是空指针。  
  8. 在看调用它的函数 _cb_volstopped_for_ums_enable  
  9. 发现v->dev->disk空的指针  

char *blkdev_get_devpath(blkdev_t *blk) { .... char *dp = malloc(256); sprintf(dp, "%s/vold/%d:%d", blk->major, blk->minor);//挂掉 } 经过调试 发现blk是空指针。 在看调用它的函数 _cb_volstopped_for_ums_enable 发现v->dev->disk空的指针  

继续返回跟踪 ,发现v->dev->disk始终是空

怪不得,马的又没作异常处理,草了

在其他地方 发现v->devv->dev->disk是相同类型,有的地方用v->dev->major,有的地方用v->dev->disk->major

看了 下没见到v->dev->disk的初始化,悲剧阿。。。

于是尝试将v->dev作形参传入,而不是v->dev->disk

发现okay.汗查看/dev/vold/下面的设备号 v->dev->major:v->dev->minor打出来的一致。

当机器启动时,插入usb client cable.主机端可以自动挂载mass-storage

Oh, yeah success! 

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

不知道为什么v->dev->disk是空的。正在继续看。。估计这几天应该能搞清除。

写的不好,也不怎么详细,只是自己一点调试的看法和经验希望能帮助自己和大家,谢谢

Android usb client mass-storage挂载单个存储设备研究

上次,初步接触Android usb client 的挂载问题,所以写了第一篇研究的感受,许多地方还有点问题,有些现象还不够清晰,所以想继续写下去。

     首先,通过上次的验证,看到的现象,是可以挂载了,但是每一次只能挂载一个存储设备。

     其次,我上次所说的关于驱动的设备节点,也有问题,其实本身就有一个tegra-udc.c创建的/sys/devices/platform/tegra-udc.0/lun0这么个节点在,所以不需要在创建什么mass-storage节点。

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

()首先,我们看看第一个问题,怎么每次只挂了一个设备在上面呢?

    1.VOLD首先会去读取vold.conf的文件中配置内容(尾插入的链表方式)存储存储设备的必要信息(上次讲过,就是EMMCpartition 4

    接着,会去通过uevent读取动态插入的存储设备信息,以头插入链表的方式,并将第一个链表和这次的链表结合起来(auto_add_volume ),使得动态存储设备在链表头几个,而静态存储设备在链表后面。这种顺序,在我的环境中是正确的,因为我的虽有的动态存储设备是挂载在 partition 4上面的。用过手机或者有一点挂载卸载经验的人都知道,如果想要顺利卸载partition 4 需要卸载它的里面目录,否则partition 4一直显示busy而不能卸载。为什么要卸载了存储设备再挂呢,这是因为防止两边同时操作。

这里要说明下,就是如果想要动态存储设备通过ums_path路径的检测,需要在auto_add_volume函数里的ums_path下,明确指定目录,使得动态存储设备,能够被正确挂载。

    2.当在client卸载成功时,就需要挂载到host端了,我一路跟踪,发现这段voldvolmgr.c代码起了作用

    

view plaincopy to clipboardprint?

  1. static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg)  
  2. {  
  3.     int rc;  
  4.     char *devdir_path;  
  5. #if DEBUG_VOLMGR  
  6.     LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point);  
  7. #endif  
  8.     //check dev->disk whether is NULL  
  9.     if (v->dev->disk)  
  10.        devdir_path = blkdev_get_devpath(v->dev->disk);  
  11.     else  
  12.        devdir_path = blkdev_get_devpath(v->dev);  
  13.          
  14.     if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) {//重点  
  15.         free(devdir_path);  
  16.         LOGE("Error enabling ums (%d)", rc);  
  17.         return;  
  18.     }  
  19.     free(devdir_path);  
  20.     volume_setstate(v, volstate_ums);  
  21.     pthread_mutex_unlock(mutex);  
  22. }  


    最主要的是ums_enable(),是这句话让设备挂载到主机端,继续跟下去

    在同目录下的ums.c代码中

    

view plaincopy to clipboardprint?

  1. int ums_enable(char *dev_fspath, char *lun_syspath)  
  2. {  
  3.     LOG_VOL("ums_enable(%s, %s):", dev_fspath, lun_syspath);  
  4.     int fd;  
  5.     char filename[255];  
  6.     sprintf(filename, "/sys/%s/file", lun_syspath);  
  7.     if ((fd = open(filename, O_WRONLY)) < 0) {  
  8.         LOGE("Unable to open '%s' (%s)", filename, strerror(errno));  
  9.         return -errno;  
  10.     }  
  11.     if (write(fd, dev_fspath, strlen(dev_fspath)) < 0) {  
  12.         LOGE("Unable to write to ums lunfile (%s)", strerror(errno));  
  13.         close(fd);  
  14.         return -errno;  
  15.     }  
  16.       
  17.     close(fd);  
  18.     return 0;  
  19. }  


    open 一个"/sys/devices/platform/tegra-udc.0/lun0/file"文件

    然后向file文件 写入一个 "/dev/block/vold/major:minor"path路径,而这个路径对应的是各个存储设备

    我尝试了写入不同的路径到file里(通过adb 中写入 如:echo "/dev/block/vold/179:0">/sys/devices/platform/tegra-udc.0/lun0/file)。

    每写一个路径,就会挂载一个相应的存储设备到host端,但是当你挂载下个设备时候必须echo  "">file中,先从hostunmount前一个设备才能挂载当前设备。

    继续跟踪代码到kernenl,发现/driver/usb/gadget/f_mass_storage.c作了某些动作,挂载了设备

  

view plaincopy to clipboardprint?

  1. static ssize_t store_file(struct device *dev, struct device_attribute *attr,  
  2.         const char *buf, size_t count)  
  3. {  
  4.     struct lun  *curlun = dev_to_lun(dev);  
  5.     struct fsg_dev  *fsg = dev_get_drvdata(dev);  
  6.     int     rc = 0;  
  7.     DBG(fsg, "store_file: \"%s\"\n", buf);  
  8. #if 0  
  9.     /* disabled because we need to allow closing the backing file if the media was removed */  
  10.     if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) {  
  11.         LDBG(curlun, "eject attempt prevented\n");  
  12.         return -EBUSY;              /* "Door is locked" */  
  13.     }  
  14. #endif  
  15.     /* Remove a trailing newline */  
  16.     if (count > 0 && buf[count-1] == '\n')  
  17.         ((char *) buf)[count-1] = 0;  
  18.     /* Eject current medium */  
  19.     down_write(&fsg->filesem);  
  20.     if (backing_file_is_open(curlun)) {  
  21.         close_backing_file(fsg, curlun);  
  22.         curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;  
  23.           
  24.     }  
  25.     /* Load new medium */  
  26.     if (count > 0 && buf[0]) {  
  27.         rc = open_backing_file(fsg, curlun, buf);  
  28.         if (rc == 0)  
  29.             curlun->unit_attention_data =  
  30.                     SS_NOT_READY_TO_READY_TRANSITION;  
  31.                   
  32.     }  
  33.     up_write(&fsg->filesem);  
  34.     return (rc < 0 ? rc : count);  
  35. }  


   知道sysfs的原理的人 都知道static DEVICE_ATTR(file, 0444, show_file, store_file);是负责读(cat/read)或直写(echo/write)设备属性文件的宏,具体实现就是上面这句(写)。

   看来看去 主要就是open_backing_file()函数的作用。还没怎么研究透,只知道肯定是这句起了作用,它打开了vold目录下的设备节点,并且初始化 了一些东西。看到的现象就是,host端只识别单设备不同分区的挂载,但是不识别多存储设备的同时挂载。

   我不知道,到底是什么问题,让所有设备只挂载到一个设备节点上去了(冲突),而不是以往的/dev/sdb sdc sde等。

   希望能够学习解决

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

()第二个问题 其实也没什么,只是 先从UDC(usb device controller)的驱动走了下,当时没注意。

不知道Android手机是不是驱动有这种只挂载单一存储设备的限制,至少目前看是这样的。想想也正常,手机一般只有一个SD插槽,自己本身内存有限,挂一个SD的存储设备无可厚非。。。

希望是自己代码的问题,还在解决中,希望有研究的达人,一起研究分享下这方面的经验。谢谢,估计很快会写(三),还在尝试,希望写下一篇的时候,能解决这个问题。

Android usb client mass-storage 多存储设备挂载问题解决

这是写的第三篇文章,废话不多说,接着上次的问题--不能同一时间挂载多个存储设备,继续探讨。

昨天,和一位linux 达人,在交流,无意中提到了这个问题,然后让他看了看现象,他说我的/devices/platform/tegra-udc.0/gadget这个目录,可能有问题。

于是查了下LUN是什么(Logical units)逻辑单元,跟SCSI有关,仔细查了下f_mass_storage.c的代码,里面的代码是fsg什么的,继续查了下

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

The File-backed Storage Gadget (FSG) provides support for the USB Mass Storage class. It can appear to a host as a set of up to 8 SCSI disk drives (called Logical UNits orLUNs), although most of the time a single LUN is all you will need. The information stored for each LUN must be maintained by the gadget somewhere, either in a normal file or in a block device such as a disk partition or even a ramdisk. This file or block device is called the backing storage for the gadget, and you tell FSG where the backing storage is when you load the gadget driver:

来自:http://www.linux-usb.org/gadget/file_storage.html

翻译一下:文件备份存储装置提供usb mass storage类的支持。它在主机端显示一连串最多高达8个的SCSI驱动盘符(被称作逻辑单元或者LUN,不过大多数时间里你只需要用到一个LUN 每个LUN的信息必须被保存在某个gadget中,信息不是存在一个普通文件,就是存在一个块设备中,例如一个盘分区,甚至是一个ramdisk。这个文 件或者块设备对于gadget被称作“backing storage”, 而当你试图加载gadget驱动的时候,你可以告诉FSG"backing storage"在哪里。(英文不行,翻译可能有问题,达人请指正)。

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

okay 大概知道,怎么回事了,应该是存储设备对应lun的多少的问题。按照linux的那套,其实一个client 对应一个lun是正确的,但是现在情况是需要让client去把自己作为host,处理挂载自己身上的N个存储设备,所以按照道理来说,一个设备应该有一 lun,多个设备就多个lun

进行验证,尝试去利用现在已经有的唯一的一个lun/file,向里面写挂载存储设备的路径,并且追加,证明确实只支持一个设备的写入,不支持什么追加。

现在有两种解决方式:

1.在主机端,模拟个文件 系统,将client的所有设备都挂载到这个文件系统上(那位达人给我的建议),客观的说,这应该是最科学的,在不该原有设计思路的最好的方式。不过实在是能力有限,无从下手。。于是想了下面一个方法。

2.就是假设,模拟多个lun节点,根据代码/drivers/usb/gadget/f_mass_storage.c中的MAX_LUNS 8的定义,先模拟8lun设备看看情况

看代码:

view plaincopy to clipboardprint?

  1. tatic int __init  
  2. fsg_function_bind(struct usb_configuration *c, struct usb_function *f)  
  3. {  
  4.     ...  
  5.     /* Find out how many LUNs there should be */  
  6.     i = MAX_LUNS;//fsg->nluns;  hook modify the i = MAX_LUNS.  
  7.     if (i == 0)  
  8.         i = 1;  
  9.     if (i > MAX_LUNS) {  
  10.         ERROR(fsg, "invalid number of LUNs: %d\n", i);  
  11.         rc = -EINVAL;  
  12.         goto out;  
  13.     }  
  14.     /* Create the LUNs, open their backing files, and register the 
  15.      * LUN devices in sysfs. */  
  16.     fsg->luns = kzalloc(i * sizeof(struct lun), GFP_KERNEL);  
  17.     if (!fsg->luns) {  
  18.         rc = -ENOMEM;  
  19.         goto out;  
  20.     }  
  21.     fsg->nluns = i;  
  22. ...  
  23. }  


原来的i = fsg->nluns给我改成了MAX_LUNS,这只是临时改的,应该按照道理来说 需要判断有多少个存储设备被挂载,然后给i的值赋多少。不过后来想想这样该貌似有问题,于是继续跟踪,发现在/arch/arm/mach-xxx /xx-board.c文件中有

view plaincopy to clipboardprint?

  1. static struct android_usb_platform_data android_usb_plat =  
  2. {  
  3.     .vendor_id = 0x0955,  
  4.     .product_id = 0x7000,  
  5.     .adb_product_id = 0x7100,  
  6.     .product_name = "ADB Composite Device",  
  7.     .manufacturer_name = "NVIDIA Corporation",  
  8.     .serial_number = "0000000000000000",  
  9.     .nluns = 1,  
  10.     .bulk_size = 16384,  
  11. };  


nluns = 1;看来是这个问题阿。所以改动成3,

然后编译驱动,加载之,发现/sys/devices/platform/tegra-udc.0/gadget下会出现lun0-lun73个节点,

尝试把client端的每个存储设备的挂载信息写到对应的lun中的file下,如echo "/dev/block/vold/179:0">file

结果证明全能挂载了okay.

如果需要自动挂载这些存储设备,而不是手动,需要改vold代码中的volmgr.cauto_add_volume()函数里,当每往链表中添加设备信息时候,给ums_path的值添上相应的lun路径 就行了。

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

不过这种方法虽然可以作出来,但是并不是好的方法,只是投机取巧,会被人鄙视的,在这因为研究学习用,所以写了出来。现在还在继续研究模拟文件系统如何挂载的方式,希望能有所突破


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SELECT bs.report_no, bs.sample_id, bs.test_id, bs.service_type, bs.sample_name, bs.total_fee, bs.receivable_fee, bs.sample_no, bs.ranges, bs.grade, bs.sample_remark AS remark, bs.factory, bs.item_name, bs.apply_dept, bs.specification, bs.factory_number, bs.calibrat_point, bs.mandatory_flag, bs.inspection_type, bs.report_org_name, bs.plan_complete_date, bs.standard_instrument_name, bs.bleeding_site_name, bs.arrive_date, DATEDIFF( bs.plan_complete_date, NOW()) AS surplus_days, bs.order_no, bs.order_type, bs.customer_name, bs.order_id, bs.business_type, bs.group_id, bs.group_name, bs.item_id, bs.is_merge, bs.pass_time, bs.audit_time, bs.report_id, bs.compile_time, bs.generate_time, bs.pass_user_name, bs.audit_user_name, bs.compile_user_name, bs.report_state, bs.is_just_certificate, bs.label_price, bs.labor_cost, bs.product_type, bs.batch_number, bs.original_number, bs.type_no, bs.template_id, bs.template_version, bs.standard_instrument_id, bs.standard_instrument_name, bs.report_query_code, bs.test_user_id, bs.test_user_name, bs.test_time, bs.review_user_id, bs.review_user_name, bs.review_time, bs.or_number, bs.test_result, bs.test_result_text, bs.test_date, bs.test_address, bs.result_value, bs.unit, bs.test_dept_id, bs.test_dept_name, bs.sample_mass, bs.form, bs.color, bs.clarity, bs.amplification_detection, bs.precious_metal, bs.remarks, bs.photo, bs.identifying_code, bs.diamond_quality, bs.hand_ring, bs.craft, bs.instrument_photo, bs.customer_item_basis, bs.quality_photo, bs.check_point, bs.check_code, bs.mass_unit, bs.manufacturer_name, bs.manufacturer_addr, bs.result_sample_describe AS sampleDescribe, bs.test_rule AS metalRuleIdsStr, bsa.attach_id FROM view_sample_info bs JOIN bus_sample_report bsr ON bs.report_id = bsr.id JOIN bus_sample sa ON bsr.sample_id = sa.id JOIN bus_sample_attr bsa ON sa.id = bsa.id 需要按照bs.report_no 的整数来从小到大进行排序
最新发布
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值