当前位置: 首页 > 工具软件 > MTP Target > 使用案例 >

android 4.4打开MTP模式以及USB CD Rom模式打开方法

符棋
2023-12-01

        实现需求:设备端连接pc后,mtp模式开启并映射到外置sdcard某一目录,同时在pc这边的设备管理可以以CD Rom的形式访问设备端相关的ISO镜像。

软件平台:android4.4

硬件环境:MTK


        分两步来实现,首先打开MTP模式,就需要在projectconfig.mk里边添加相关的配置信息,mtk平台使用的是MTK_MASS_STORAGE开关,当value为yes时,USB打开MASS_STORAGE模式,反之,则打开MTP模式,build下的main.mk会判断此开关的值,然后设置persist.sys.usb.config,这只是打开MTP的前提,

下面我们关注一下mtp模式打开的流程:

USB连接之后,底层会有uevent事件上报,UsbManager监测到之后,会发出USB_CONNECT广播,MtpReceiver会监听该广播,将相关状态改变交给handler处理,其实就是判断系统是否打开MTP模式,如果是的话,就开启MtpService,该service的onStartCommand会创建相关目录,

--- a/packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
+++ b/packages/providers/MediaProvider/src/com/android/providers/media/MtpService.java
@@ -54,6 +54,9 @@ public class MtpService extends Service {
         Environment.DIRECTORY_PICTURES,
     };
 
+    private static final String USER_SPACE = "/storage/sdcard1/我导入的音乐";
+    private static final String STORE_IN = "/storage/sdcard0";
+

     /// M: Added Modification for ALPS00255822, bug from WHQL test @{
     private static final String MTP_OPERATION_DEV_PATH =
             "DEVPATH=/devices/virtual/misc/mtp_usb";
@@ -260,6 +263,10 @@ public class MtpService extends Service {
                     file.mkdirs();
                     subdirs[i] = file.getPath();
                 }
+            } else {
+                File file = new File(USER_SPACE);
+                file.mkdirs();
+                subdirs = new String[]{USER_SPACE};

             }
  /*Fix ALPS00444854
     MtpService process is killed by VOLD when user plug out SD card(USB will disconnect)
@@ -404,6 +411,7 @@ public class MtpService extends Service {
     }
 
     private void volumeMountedLocked(String path) {
+        if (path.equals(STORE_IN)) return;  //屏蔽外置存储的处理。
         // Add for update Storage
         StorageVolume[] volumes = mStorageManager.getVolumeList();
         mVolumes = volumes;
@@ -428,9 +436,8 @@ public class MtpService extends Service {
  String PATH_SDCARD0 = "/storage/sdcard0";
  String PATH_SDCARD1 = "/storage/sdcard1";
 
  if (storage.getPath().equals(PATH_SDCARD0) && !storage.isRemovable()){
-
  StorageVolume[] volumes = mStorageManager.getVolumeList();
 
  for (int i = 0; i < volumes.length; i++) {

代码中USER_SPACE定义的目录结构即为pc端映射的目录,由于要求pc端只映射该目录,而默认会有内置的存储卡也会体现出来,因此需要将内置存储的信息屏蔽掉,见代码中注释,在onStartCommand方法的末端,会创建MtpDatabase,同时启动MtpServer,后者就是设备端的守护进程,负责处理pc端发过来的命令请求之类,与pc端交互。

产品需求是pc的设备目录不可以重命名,不能创建与其同级的目录,可以在该目录下创建子目录,可重命名,则还需对代码进行如下修改:

--- a/frameworks/base/media/java/android/mtp/MtpDatabase.java
+++ b/frameworks/base/media/java/android/mtp/MtpDatabase.java
@@ -124,6 +124,9 @@ public class MtpDatabase {
     private static final String STORAGE_FORMAT_PARENT_WHERE = STORAGE_FORMAT_WHERE + " AND "
                                             + Files.FileColumns.PARENT + "=?";
 
+    private static final String VINCI_DIR = "/storage/sdcard1/我导入的音乐";
+
+

     private final MediaScanner mMediaScanner;
 
     static {
@@ -258,12 +261,16 @@ public class MtpDatabase {
     // check to see if the path matches one of our storage subdirectories
     // returns true if we have no special subdirectories
     private boolean isStorageSubDirectory(String path) {
-    if (mSubDirectories == null) return false;
-        for (int i = 0; i < mSubDirectories.length; i++) {

+        if (mSubDirectories == null) return false;
+        /*
+ for (int i = 0; i < mSubDirectories.length; i++) {

             if (path.equals(mSubDirectories[i])) {
                 return true;
             }
         }
+ */
+        if (path.equals(VINCI_DIR)) return true;
+

         return false;
     }

上述逻辑处理是新建目录及重命名目录名时根据logcat捕获到的程序流,因此做了相关处理。

至此,MTP模式正式开挂。


下边将pc端挂载设备端ISO文件的流程做如下总结:

diff --git a/build/core/main.mk b/build/core/main.mk
index 10923ee..49a3b2c 100644
--- a/build/core/main.mk
+++ b/build/core/main.mk
@@ -374,11 +374,9 @@ else # !enable_target_debugging
   ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1
 endif # !enable_target_debugging
 
-# default usb function
-ifeq ($(strip $(MTK_MASS_STORAGE)),yes)
-  ADDITIONAL_DEFAULT_PROPERTIES += persist.sys.usb.config=mass_storage
-else
-  ADDITIONAL_DEFAULT_PROPERTIES += persist.sys.usb.config=mtp

+# kongbo change usb function
+ifeq ($(strip $(MTK_STORAGE_MTP)),yes)
+  ADDITIONAL_DEFAULT_PROPERTIES += persist.sys.usb.config=mtp,mass_storage

 endif
 
 # serial port open or not
diff --git a/mediatek/config/mt6572/init.usb.rc b/mediatek/config/mt6572/init.usb.rc
index ae45808..b32d072 100755
--- a/mediatek/config/mt6572/init.usb.rc
+++ b/mediatek/config/mt6572/init.usb.rc
@@ -15,6 +15,7 @@ on post-fs-data
     write /sys/class/android_usb/android0/f_rndis/wceis 1
     write /sys/class/android_usb/android0/f_rndis/manufacturer Vinci
     write /sys/class/android_usb/android0/f_rndis/vendorID $sys.usb.vid
+    write /sys/class/android_usb/android0/f_mass_storage/lun2/file "/dev/block/loop0"
 
 # Used to set USB configuration at boot and to switch the configuration
 # when changing the default configuration


--- a/mediatek/config/vinci_mtk/ProjectConfig.mk
+++ b/mediatek/config/vinci_mtk/ProjectConfig.mk

+# add by kongbo for our device support mtp&&mass_storage
+MTK_STORAGE_MTP=yes
+

 # MTK_MATV_PARALLEL_IF_SUPPORT is used to define mATV video path interface is parallel interface or serial interface.
 MTK_MATV_SERIAL_IF_SUPPORT=yes
 MTK_MAV_PLAYBACK_SUPPORT=no

这是产品配置这方面的改动,此外外挂的ISO镜像文件可能会根据自己的需求去制作,mtk方案的ISO模块是在system/mobile_toolkit目录下生成,开机的时候该ISO文件会被挂载,执行该挂载的命令在init.rc中:

mount iso9660 loop@/system/mobile_toolkit/iAmCdRom.iso /mnt/cd-rom ro

此外,kernel的USB驱动部分,还需做配置调整。

把LUN改成3个,并且最后一个定义为CDROM

kernel\drivers\usb\gadget\android.c

static int mass_storage_function_init(struct android_usb_function *f,

struct usb_composite_dev *cdev)

{

struct mass_storage_function_config *config;

struct fsg_common *common;

int err;

int i;

config = kzalloc(sizeof(struct mass_storage_function_config),

GFP_KERNEL);

if (!config)

return -ENOMEM;

#ifdef MTK_MULTI_STORAGE_SUPPORT

#ifdef MTK_SHARED_SDCARD

#define NLUN_STORAGE 1

#else

#define NLUN_STORAGE 2

#endif

#else

#define NLUN_STORAGE 1

#endif

#define NLUN_STORAGE 3 //add 1/2

config->fsg.nluns = NLUN_STORAGE;

for(i = 0; i < config->fsg.nluns; i++) {

config->fsg.luns[i].removable = 1;

config->fsg.luns[i].nofua = 1;

}

config->fsg.luns[NLUN_STORAGE-1].cdrom = 1; //add 2/2

common = fsg_common_init(NULL, cdev, &config->fsg);

if (IS_ERR(common)) {

kfree(config);

return PTR_ERR(common);

}

err = sysfs_create_link(&f->dev->kobj,

&common->luns[0].dev.kobj,

"lun");

if (err) {

kfree(config);

return err;

}

/*

* "i" starts from "1", cuz dont want to change the naming of

* the original path of "lun0".

*/

for(i = 1; i < config->fsg.nluns; i++) {

char string_lun[5]={0};

sprintf(string_lun, "lun%d",i);

err = sysfs_create_link(&f->dev->kobj,

&common->luns[i].dev.kobj,

string_lun);

if (err) {

kfree(config);

return err;

}

}

common->android_callback = &mass_storage_callback;

config->common = common;

f->config = config;

return 0;

}

至此,CD Rom外挂完成,注:pc端显示的CD Rom名称与制作ISO镜像时命名的文件名一致。

完工,欢迎列位点评切磋啊~~~~~~





 类似资料: