Android OTG支持USB读卡器

  我们知道,三星Android手机将USB读卡器通过OTG线插入Micro USB插口后,插拔读卡器里的SD卡,文件管理器也能够识别卡的插拔;而很多手机的OTG连上USB读卡器也来插拔SD卡,会发现文件管理器无法加载SD卡。而将USB读卡器放到Windows上或者桌面Linux上,我们发现插拔读卡器里的SD卡也是有效的。

  究其原因是Android的用户空间或者内核空间没有处理好SCSI 的TUR(Test Unit Ready)命令

  由于项目需要,我实现了Android OTG支持读卡器里的SD卡插拔,需要修改的地方分为两部分,一部分是kernel,一部分是vold。

对于kernel部分:

当用户空间打开诸如/dev/block/sda的设备节点时,kernel会调用到kernel/fs/block_dev.c里的__blkdev_get()函数,该函数会向USB读卡器发送TUR命令来测试读卡器里的media是否已插入,如果插入返回1,否则是0,当Kernel发现media状态从1->0或者0->1转换时,就会设置bdev->bd_invalidated为true,这样到1185行:

if (bdev->bd_invalidated) {

if (!ret) {

rescan_partitions(disk, bdev);

} else if (ret == -ENOMEDIUM){

invalidate_partitions(disk, bdev);

}

}

该函数会重新无效或者扫描分区,但事实上无论你怎么插拔SD卡,这两个函数都没有执行完毕,关键原因是有一个打开计数没有清空,把上面函数改成如下的形式:

if (bdev->bd_invalidated) {

if (!ret) {

bdev->bd_part_count = 0;

rescan_partitions(disk, bdev);

} else if (ret == -ENOMEDIUM){

bdev->bd_part_count = 0;

invalidate_partitions(disk, bdev);

}

}

配合用户空间周期性打开/dev/block/sda设备节点,你再插拔SD卡就会发现,插入SD卡时,/dev/block/sda1设备节点会出现,拔除SD卡时,/dev/block/sda1设备节点消失。代码跳到1125行,将无效或者扫描分区前同样加上bdev->bd_part_count = 0,即解决了内核无法扫描读卡器SD卡插拔的问题。

对于vold部分:

在vold进程中需要加入周期性打开和关闭/dev/block/sda设备节点的轮训线程,才能使内核周期性向读卡器发送TUR命

令来检查读卡器中的SD卡是否存在,我们可以将该轮训线程放于DirectVolume.cpp中,示例函数如下:

Android OTG支持USB读卡器

我们的OTG U盘是挂载在/storage/UsbDriveA、/storage/UsbDriveB、/storage/UsbDriveC、/storage/UsbDriveD、

/storage/UsbDriveE、/storage/UsbDriveF目录下的。

同时需要在DirectVolume.cpp中加入其它几个函数,由于代码保护问题,在本文中就不粘贴代码了,有需要的人可以向我索取源代码。

增加的几个函数名如下:

int DirectVolume::adjustDiskPartNum(int diskNumParts, int pendingPartMap);

bool DirectVolume::isUsbDrive(const char *tag);

bool DirectVolume::isUsbDrive();

void DirectVolume::diskRemoved(int major, int minor);

void DirectVolume::diskRemoved();

上一篇:tmux-2.3 conf


下一篇:cdoj1092-韩爷的梦 (字符串hash)【hash】