测试平台:Nvidia ARM架构
操作系统:Andorid(Nvidia修改)
最近在搞Android usb client,发现当将client线分别接上Android系统机器的client端以及主机Host端的时候,Android的USB 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
volume_sdcard { media_path /devices/platform/tegra-sdhci.3/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p4 media_type mmc mount_point /sdcard } UMS的路径没有,个人经验:一般可以在/sys/devices/platform/ 下面找到一个叫包含"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下的节点 在这需要加入两句
static struct platform_device fsg_platform_device = { .name = "usb_mass_storage", .id = -1, }; static void __init tegra_machine_init(void) { .... (void) platform_device_register(&fsg_platform_device); .... } 加入这两句okay
我们会发现/sys/devices/platform/usb_mass_storage/lun0这个目录产生了
这些动作是和你的linux driver中mass-storage的驱动内容相对应的。
最后一步,就是需要将新创建的UMS(负责启动usb mass-storage功能) Path加入到你的vold.conf中
volume_sdcard { media_path /devices/platform/tegra-sdhci.3/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p4 media_type mmc mount_point /sdcard ums_path /devices/platform/usb_mass_storage/lun0 //加的代码就是这个 }
===========================
打开机器,灌入系统,启动,发现还是不行,在ADB终端中输入sdutil ums enabel 启动ums 实际上我机器已经在开机就启动了UMS功能
logcat显示UMS 挂掉了 一大堆的 堆栈问题 stack 什么的。
估计和内存分配或者指针有关。
估计是vold的代码有问题。
进入android源代码目录/system/core/vold
打开该目录下所有代码,加入打印语句,进行跟踪。
发现当你ums enable时候
1.会进入cmd_dispatch.c执行do_set_ums_enable函数
static int do_set_ums_enable(char *cmd) { ... if (!strcmp(cmd, VOLD_CMD_ENABLE_UMS)) return volmgr_enable_ums(true); return volmgr_enable_ums(false); }
它又调用了volmgr.c文件中的volmgr_enable_ums(bool enable)
int volmgr_enable_ums(bool enable) { ... volume_t *v = vol_root //链表,链表中存储了每个存储设备的相关信息,如state. ums_path, mount_point这些来自于/etc/vold.conf while(v) { if(v->ums_path) if(enable){ ... volmgr_shutdown_volume(v, _cb_volstopped_for_ums_enable_false);//程序执行到这句话 挂掉了 ... } } }
首先我们看看,程序是如何读取/etc/vold.conf配置信息并存储的
主要是这么几个函数volmgr_readconfig, volmgr_config_volume,等等,这里不详细讲,只是大概讲下,
首先 会建立一个大的链表,通过比配vold.conf中volume_XX来确定有多少成员 如volum_sdcard1 volum_sdcard2
表示有两个成员
然后,会在每个成员里在建一个链表,用于存储ums_path mount_point这些
最后再将这些东西重新在组织成个链表v。
=========================================
继续上面的代码说
跟踪volmgr_shutdown_volume()--->volmgr_stop_volume()--->_cb_volstopped_for_ums_enable()
staitc void _cb_volstopped_for_ums_enable(volume_t *v, void *arg) { char* devdir_path ... devdir_path = blkdev_get_devpath(v->dev->disk);//挂了 ... }
继续跟下去到blkdev.c
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->dev和v->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是空的。正在继续看。。估计这几天应该能搞清除。
写的不好,也不怎么详细,只是自己一点调试的看法和经验希望能帮助自己和大家,谢谢