Android 启用/禁用通过otg连接T卡功能

1.调用方法:

private String setSDOTGEnable(boolean enable) {
    if (enable)
		mDPM.clearUserRestriction(admin, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
	else
		mDPM.addUserRestriction(admin, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);	
}

2.在【mt67xx_11.0】上调用以上方法并不能控制到ES文件浏览器识别SD卡,增加以下控制:

--- a/alps/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/alps/frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -50,6 +50,10 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedList;
+//add for setSDOTGEnable
+import android.os.UserHandle;
+import android.os.UserManager;
+//add end
 
 /**
  * UsbHostManager manages USB state in host mode.
@@ -353,6 +357,13 @@ public class UsbHostManager {
     @SuppressWarnings("unused")
     private boolean usbDeviceAdded(String deviceAddress, int deviceClass, int deviceSubclass,
             byte[] descriptors) {
+        //add by lfy for setSDOTGEnable
+        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        boolean flag = um.hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
 UserHandle.of(um.getUserHandle()));
+        if (flag) {
+            return false;
+        }
+        //add end
         if (DEBUG) {

以上方法实现的启用/禁用otg功能在使用过程中需要在调接口前先插拔otg设备,完善缺陷修改如下:
1.在禁用前先unmount已挂载的设备&在启用后mount已插入的设备,顺序不能乱

if(!enable){
	unmountSD(!enable);   //禁用前先unmount已挂载的设备
	mDPM.addUserRestriction(admin, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
}else{
	mDPM.clearUserRestriction(admin, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
	unmountSD(!enable);  //在启用后mount已插入的设备
}

private void unmountSD(boolean disabled) {
	try {   //一定要有try...catch
	    android.util.Log.d("lfy","mountUnmountSD......");
	    StorageManager mStorageManager = mContext.getSystemService(StorageManager.class);
	    StorageVolume[] volumeList = mStorageManager.getVolumeList();
	    if (volumeList.length > 0) {
	    	for (StorageVolume vol : volumeList) {
		    	android.util.Log.d(TAG," mountUnmountSD...vol="+vol+",getId="+vol.getId()+",path="+vol.getPath()+",InternalPath="+vol.getInternalPath()+",filePath="+vol.getPathFile().getPath()+",getDescription="+vol.getDescription(mContext));
				if (disabled) {
					if (!"/storage/emulated/0".equals(vol.getPath()) && "mounted".equals(vol.getState())) {
						mStorageManager.unmount(vol.getId());
					}
                }else{
                    if (!"/storage/emulated/0".equals(vol.getPath()) && "unmounted".equals(vol.getState())) {
						mStorageManager.mount(vol.getId());
					}
                }
		    }
	    }
	} catch(Exception e){
		android.util.Log.d("lfy","[FuncTools] mountUnmountSD...e="+e);
       e.printStackTrace();
    }
}

2.打印log
在这里插入图片描述

3.如果unmountSD顺序调用错误(统一在enable判断前调用会报如下错误)
在这里插入图片描述
4.报错信息具体出处:

//frameworks/base/services/core/java/com/android/server/StorageManagerService.java
@Override
 public void mount(String volId) {
     enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);

     final VolumeInfo vol = findVolumeByIdOrThrow(volId);
     if (isMountDisallowed(vol)) {   //决定存储是否能挂载的关键
         throw new SecurityException("Mounting " + volId + " restricted by policy");
     }

     mount(vol);
 }

/**
 * Decide if volume is mountable per device policies.
 */
private boolean isMountDisallowed(VolumeInfo vol) {
    UserManager userManager = mContext.getSystemService(UserManager.class);

    boolean isUsbRestricted = false;
    if (vol.disk != null && vol.disk.isUsb()) {
        isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
                Binder.getCallingUserHandle());
    }

    boolean isTypeRestricted = false;
    if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
            || vol.type == VolumeInfo.TYPE_STUB) {
        isTypeRestricted = userManager
                .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
                Binder.getCallingUserHandle());
    }

    return isUsbRestricted || isTypeRestricted;
}
<think>好的,我现在需要帮助用户解决关于STM32F407调用MX_USB_Device_Init时未连接USB导致死的问题。首先,我得理解用户的问题场景。他们在使用STM32F407开发板,可能在初始化USB设备时,如果没有连接USB线,程序会死。用户想知道原因和解决方法。 首先,我应该回顾STM32的USB库相关知识。MX_USB_DEVICE_Init是自动生成的初始化函数,通常由STM32CubeMX配置生成。这个函数会初始化USB外设,设置相关的中断和描述符等。 接下来,用户提到的问题可能涉及到硬件检测或软件配置。根据引用内容,特别是引用[2]提到要选择Device Only模式,并且不要启用VBUS检测,否则可能导致识别问题。这可能是一个关键点。VBUS检测通常用于判断USB主机是否提供了电源,如果配置为需要检测VBUS,但实际未连接USB线,VBUS信号不存在,可能导致USB初始化失败或进入错误状态。 另外,引用[3]提到USBX作为USB堆栈与硬件驱动的交互,如果初始化过程中没有正确处理硬件状态,可能导致阻塞。例如,某些驱动程序可能会等待VBUS有效信号,而如果VBUS检测被启用,但实际未连接,程序可能在等待状态。 可能的原因有几个方面: 1. VBUS检测被启用,导致等待VBUS信号。 2. 硬件引脚配置错误,如PA11和PA12是否正确连接,跳线帽是否接好。 3. 中断或超时处理不当,初始化过程中没有处理错误情况。 4. 电源管理配置问题,导致USB外设无法正确初始化。 解决方法可能包括: - 检查CubeMX配置,禁用VBUS检测,如引用[2]所述。 - 确保USB引脚正确配置,并检查硬件连接。 - 添加超时机制或错误处理,避免无限等待。 - 在初始化前检查VBUS状态,或调整初始化流程。 需要验证这些可能性,并给出具体的步骤。例如,用户应检查CubeMX中的USB_DEVICE配置,是否选择了正确的模式,VBUS是否禁用。同时,硬件连接必须正确,PA11和PA12必须连接到USB接口,跳线帽正确连接,否则USB无法通信。 此外,软件层面可能需要修改,例如在初始化之前检测VBUS是否存在,或者在初始化失败时进行重试或跳过。如果USB堆栈在初始化时等待某个事件,可能需要调整代码结构,避免阻塞主循环。 总结起来,核心问题可能是VBUS检测导致初始化死,解决方法是在配置中禁用VBUS,并确保硬件连接正确。同时,软件中加入错误处理机制,防止无限等待。</think>在STM32F407中调用`MX_USB_DEVICE_Init()`时未连接USB设备导致死的问题,通常与硬件配置、USB协议栈行为或电源管理相关。以下是具体原因和解决方法: --- ### **1. 核心原因分析** - **VBUS检测未关闭** 若USB配置中启用了VBUS检测(默认可能开启),系统会持续等待来自USB主机的VBUS电压信号(5V)。未连接USB时,VBUS信号缺失,导致USB外设进入阻塞状态[^2]。 - **硬件引脚配置错误** USB通信需严格使用PA11(D-)和PA12(D+)引脚。若硬件跳线帽未连接或引脚被复用,初始化时会因通信异常死。 - **USB协议栈超时机制缺失** USB初始化过程可能依赖中断或轮询机制。若未实现超时处理,协议栈会无限等待USB连接事件,导致程序死[^3]。 --- ### **2. 解决方法** #### **步骤1:修改CubeMX配置** 1. 在CubeMX的USB_DEVICE配置中,选择**Device Only**模式。 2. **禁用VBUS检测**: - 在`USB_DEVICE` → `Configuration` → `Advanced`中,将**VBUS Sensing**设为`Disable`。 3. 确保时钟配置正确(例如:USB时钟需为48MHz)。 #### **步骤2:检查硬件连接** - 确认开发板的USB引脚(PA11和PA12)已通过跳线帽连接到USB接口。 - 测量VBUS引脚电压(若未禁用VBUS检测),确保未连接时无电压干扰。 #### **步骤3:添加超时机制** 在代码中插入超时逻辑,避免无限等待USB连接: ```c void MX_USB_DEVICE_Init(void) { // 初始化USB设备 MX_USB_DEVICE_Init(); // 添加超时检测(示例) uint32_t timeout = 1000000; // 根据实际情况调整 while (HAL_GetTick() < timeout) { if (USBD_GetState(&hUsbDeviceFS) == USBD_STATE_CONFIGURED) { break; // USB已连接并配置成功 } } if (HAL_GetTick() >= timeout) { // 处理超时:关闭USB或进入低功耗模式 __HAL_PCD_DISABLE(&hpcd_USB_OTG_FS); } } ``` #### **步骤4:优化电源管理** 若需支持热插拔,可启用USB中断检测VBUS动态变化,但需在初始化时跳过VBUS检测: ```c // 在main.c中 int main(void) { HAL_Init(); MX_USB_DEVICE_Init(); while (1) { if (HAL_PCD_GetVBUSState(&hpcd_USB_OTG_FS) == 0) { // VBUS未连接时的处理逻辑 } // ... } } ``` --- ### **3. 关键验证点** - 通过逻辑分析仪检查PA11/PA12是否有信号活动。 - 使用`USBD_GetState()`函数监控USB状态变化。 - 在CubeMX生成的代码中确认`USB_OTG_GCCFG`寄存器的`VBUSIG`位已禁用(对应VBUS检测关闭)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值