四极管: android4.2 大容量存储及挂载PC(一) 之前保存丢失,重复编辑

USB On-The-Go and Embedded Host

Virtually every portable device now uses USB for PC connectivity. As these products increase in popularity, there is a growing need for them to communicate both with USB peripherals and directly with each other when a PC is not available. There is also an increase in the number of other, non-PC hosts (Embedded Hosts) which support USB in order to connect to USB peripherals.

   具体E问地址为:http://www.usb.org/developers/onthego/

 

先看android VOLD:

 

root@ubuntu:/cm10/4.2/system/vold# ls
Android.mk           Devmapper.h       logwrapper.c        Process.cpp       Volume.cpp     
Asec.h               DirectVolume.cpp  Loop.cpp            Process.h         Volume.h     
CleanSpec.mk         DirectVolume.h    Loop.h              ResponseCode.cpp  VolumeManager.cpp     
CommandListener.cpp  Ext4.cpp          main.cpp            ResponseCode.h    VolumeManager.h     
CommandListener.h    Ext4.h            NetlinkHandler.cpp  tests             Xwarp.cpp     
cryptfs.c            Fat.cpp           NetlinkHandler.h    vdc.c             Xwarp.h     
cryptfs.h            Fat.h             NetlinkManager.cpp  VoldCommand.cpp     
Devmapper.cpp        hash.h            NetlinkManager.h    VoldCommand.h

简单梳理一下,在vold中处理otg,将需要与PC机共享的磁盘设备写到一个文件里面,作为一个标志,再广播给上层,传播一个大容量存储的状态。

查看源码:

vi ./CommandListener.cpp
#define MASS_STORAGE_FILE_PATH  "/sys/class/android_usb/android0/f_mass_storage/lun/file"   //标志文件

 1、连接PC部分。

在该函数中做分支解析:

int CommandListener::VolumeCmd::runCommand(SocketClient *cli,   
                                                      int argc, char **argv)



 

else if (!strcmp(argv[1], "share")) {   
        if (argc != 4) {   
            cli->sendMsg(ResponseCode::CommandSyntaxError,   
                    "Usage: volume share <path> <method>", false);   
            return 0;   
        }   
        rc = vm->shareVolume(argv[2], argv[3]);   //进入shareVolume函数对各状态进行判断,其中可判断INAND或SD卡状态,如果不存在或者忙状态,则返回错误值。


具体看看shareVolume函数如何实现:

vi VoldCommand.cpp


 

int VolumeManager::shareVolume(const char *label, const char *method) {   
    Volume *v = lookupVolume(label);   
  
    if (!v) {   
        errno = ENOENT;   
        return -1;   
    }   
  
    /*   
     * Eventually, we'll want to support additional share back-ends,   
     * some of which may work while the media is mounted. For now,   
     * we just support UMS   
     */
    if (strcmp(method, "ums")) {   
        errno = ENOSYS;   
        return -1;   
    }   
  
    if (v->getState() == Volume::State_NoMedia) {   
        errno = ENODEV;   
        return -1;   
    }   
  
    if (v->getState() != Volume::State_Idle) {   
        // You need to unmount manually befoe sharing   
        errno = EBUSY;   
        return -1;   
    }   
  
    if (mVolManagerDisabled) {   
        errno = EBUSY;   
        return -1;   
    }   
  /*getShareDevice函数直接返回SD卡的设备号,部分版本该函数为getDiskDeve*/‍ 
    dev_t d = v->getShareDevice();   
    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {   
        // This volume does not support raw disk access   
        errno = EINVAL;   
        return -1;   
    }   
  
    int fd;   
    char nodepath[255];   
    snprintf(nodepath,   
             sizeof(nodepath), "/dev/block/vold/%d:%d",   
             MAJOR(d), MINOR(d));   
  /*重要的文件读写函数在这里体现,PC机欲识别android设备中的存储器,需将SD卡的设备节点路径写到MASS_STORAGE_FILE_PATH 文件中去,打开大容量存储功能*/
    if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) {   
        SLOGE("Unable to open ums lunfile (%s)", strerror(errno));   
        return -1;   
    }   
  
    if (write(fd, nodepath, strlen(nodepath)) < 0) {   
        SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));   
        close(fd);   
        return -1;   
    }   
  
    close(fd);         ​  
    v->handleVolumeShared();   /*该函数在Volume中,在子类DirectVolume中实现,广播ums状态。*/
    if (mUmsSharingCount++ == 0) {   /*4.0以上的版本增加了一下的判断*/
        FILE* fp;   
        mSavedDirtyRatio = -1; // in case we fail   
        if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {   
            char line[16];   
            if (fgets(line, sizeof(line), fp) && sscanf(line, "%d", &mSavedDirtyRatio)) {   
                fprintf(fp, "%d\n", mUmsDirtyRatio);   
            } else {   
                SLOGE("Failed to read dirty_ratio (%s)", strerror(errno));   
            }   
            fclose(fp);   
        } else {   
            SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));   
        }   
    }   
    return 0;   
}

 二、断开PC部分

int VolumeManager::unshareVolume(const char *label, const char *method) {
    Volume *v = lookupVolume(label);
    if (!v) {
        errno = ENOENT;
        return -1;
    }
    if (strcmp(method, "ums")) {
        errno = ENOSYS;
        return -1;
    }
    if (v->getState() != Volume::State_Shared) {
        errno = EINVAL;
        return -1;
    }
    int fd;
    if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) {
        SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
        return -1;
    }
 /*断开连接,使用ums模式,磁盘不能多处操作,只能使用PC或者只是使用android设备,将控制权交给PC机,断开时将MASS_STORAGE_FILE_PATH 写为空值。后期升级为MTP方式,可实现同时控制。*/
    char ch = 0;
    if (write(fd, &ch, 1) < 0) {
        SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
        close(fd);
        return -1;
    }
    close(fd);
/*和连接电脑一样,如下函数为广播OTG断开状态*/
    v->handleVolumeUnshared();
    if (--mUmsSharingCount == 0 && mSavedDirtyRatio != -1) {
        FILE* fp;
        if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
            fprintf(fp, "%d\n", mSavedDirtyRatio);
            fclose(fp);
        } else {
            SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
        }
        mSavedDirtyRatio = -1;
    }
    return 0;
}

3、将状态广播Framework

vi ./CommandListener.cpp
  if (!rc) {
        cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
    } else {
        int erno = errno;
        rc = ResponseCode::convertFromErrno();
        cli->sendMsg(rc, "volume operation failed", true);
    }


 

接下来往kernel方向分析传入的接口。




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值