Android RK356X TVSettings USB調試開關
- 平臺
- 概述
- 操作-打開USB調試
- 實現源碼
- 補充說明
平臺
RK3568 + Android 11
概述
RK3568 是瑞芯微(Rockchip)推出的一款高性能處理器,支持 USB OTG(On-The-Go)和 USB Host 功能。USB OTG 和 Host 的切換功能是 RK3568 的一項重要特性,允許設備在不同的 USB 角色之間動態切換,從而實現更靈活的應用場景。
USB OTG 和 Host 的切換功能
-
USB OTG(On-The-Go)
USB OTG 是一種允許設備在主機(Host)和設備(Device)之間動態切換的功能。通過 OTG 功能,RK3568 可以在以下兩種模式之間切換:
? 主機模式(Host Mode):RK3568 作為主機,連接其他 USB 設備(如 U 盤、鍵盤、鼠標等),并控制數據傳輸。? 設備模式(Device Mode):RK3568 作為從設備,連接到主機(如 PC),被主機控制和數據傳輸。
-
動態切換
RK3568 支持在運行時動態切換 USB OTG 和 Host 模式,無需重新啟動設備或重新插拔 USB 線纜。這種切換功能依賴于硬件設計和軟件驅動的支持。
應用場景
USB OTG 和 Host 的切換功能在以下場景中有廣泛應用:
-
移動設備
? 在智能手機、平板電腦等設備中,OTG 功能允許用戶通過 USB 連接外部設備(如 U 盤、鍵盤、鼠標等),擴展設備的功能。? 例如,用戶可以將手機作為主機,連接 U 盤進行文件傳輸,或者連接鍵盤和鼠標進行辦公。
-
嵌入式設備
? 在嵌入式系統中,RK3568 的 OTG 功能可以用于連接各種 USB 設備,如打印機、攝像頭、傳感器等。? 通過動態切換,設備可以在主機和從機模式之間切換,適應不同的應用需求。
-
工業控制
? 在工業自動化領域,RK3568 可以作為主機連接傳感器、控制器等設備,也可以作為從機連接到上位機(如 PC)進行數據采集和監控。? 動態切換功能使得設備可以根據任務需求靈活調整角色。
-
車載系統
? 在車載娛樂系統或導航設備中,OTG 功能可以用于連接外部存儲設備(如 U 盤)播放媒體文件,或者連接診斷工具進行系統維護。? 動態切換功能使得設備可以同時支持多種連接方式。
-
物聯網設備
? 在物聯網設備中,RK3568 可以通過 OTG 功能連接各種傳感器或執行器,實現數據采集和控制。? 通過動態切換,設備可以根據網絡環境或任務需求調整角色。
-
調試和開發
? 在開發階段,OTG 功能可以用于連接調試工具(如 JTAG 調試器)或燒錄固件。? 動態切換功能使得開發者可以方便地在不同模式之間切換,提高開發效率。
技術實現
RK3568 的 USB OTG 和 Host 切換功能依賴于以下硬件和軟件支持:
? 硬件支持:RK3568 集成了 USB OTG 控制器,支持動態角色切換。
? 軟件驅動:需要操作系統(如 Linux)提供相應的驅動程序和工具,支持 OTG 功能的動態切換。
? 外部電路設計:需要設計合適的 USB 接口電路,支持 OTG 功能(如 ID 引腳檢測)。
操作-打開USB調試
設置 > 設備偏好設置 > 開發者選項 > USB 連接狀態
實現源碼
packages/apps/TvSettings/Settings/src/com/android/tv/settings/system/development/DevelopmentFragment.java
import com.android.tv.settings.dialog.UsbModeSettings;
/*** Displays preferences for application developers.*/
public class DevelopmentFragment extends SettingsPreferenceFragmentimplements Preference.OnPreferenceChangeListener,EnableDevelopmentDialog.Callback, OemUnlockDialog.Callback, AdbDialog.Callback {private static final String TAG = "DevelopmentSettings";private static final String ENABLE_DEVELOPER = "development_settings_enable";private static final String ENABLE_ADB = "enable_adb";private static final String ENABLE_USB = "enable_usb";//...省略代碼...@Overridepublic void onCreatePreferences(Bundle savedInstanceState, String rootKey) {mLogdSizeController = new LogdSizePreferenceController(getActivity());mLogpersistController = new LogpersistPreferenceController(getActivity(), getLifecycle());mUsbModeSetting = new UsbModeSettings(getPreferenceManager().getContext());if (!mUm.isAdminUser()|| mUm.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)|| Settings.Global.getInt(mContentResolver,Settings.Global.DEVICE_PROVISIONED, 0) == 0) {// Block access to developer options if the user is not the owner, if user policy// restricts it, or if the device has not been provisionedmUnavailable = true;addPreferencesFromResource(R.xml.development_prefs_not_available);return;}addPreferencesFromResource(R.xml.development_prefs);final PreferenceScreen preferenceScreen = getPreferenceScreen();// Don't add to prefs lists or it'll disable itself when switched offmEnableDeveloper = (SwitchPreference) findPreference(ENABLE_DEVELOPER);final PreferenceGroup debugDebuggingCategory = (PreferenceGroup)findPreference(DEBUG_DEBUGGING_CATEGORY_KEY);mEnableAdb = findAndInitSwitchPref(ENABLE_ADB);mEnableUsb = findAndInitSwitchPref(ENABLE_USB);mEnableInternetAdb = findAndInitSwitchPref(ENABLE_INTERNET_ADB);mEnableAbc = findAndInitSwitchPref(ENABLE_ABC);mEnableUsb.setChecked(mUsbModeSetting.getDefaultValue());if (mEnableUsb.isChecked()){mEnableUsb.setSummary(R.string.usb_connect_to_computer);} else {mEnableUsb.setSummary(R.string.usb_disconnect_to_computer);}//...省略代碼....}
packages/apps/TvSettings/Settings/src/com/android/tv/settings/dialog/UsbModeSettings.java
package com.android.tv.settings.dialog;import com.android.tv.settings.R;import android.content.Context;
import android.os.Handler;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import android.os.storage.StorageManager;
import android.os.storage.StorageEventListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemProperties;
import android.text.TextUtils;import android.util.Log;public class UsbModeSettings {private static final String TAG = "UsbModeSettings";// 0 otg 1 host 2 peripheralpublic static final String HOST_MODE = new String("host");public static final String SLAVE_MODE = new String("otg");public static final String PROP_FAKE_DATA_ROLE = "persist.fake_data_role";private static final String FILE_NAME_RK3399 = "/sys/kernel/debug/usb@fe800000/rk_usb_force_mode";private static final String FILE_NAME_RK3328 = "/sys/devices/platform/ff450000.syscon/ff450000.syscon:usb2-phy@100/otg_mode";private static final String FILE_NAME_RK3229 = "/sys/devices/platform/11000000.syscon/11000000.syscon:usb2-phy@760/otg_mode";private static final String FILE_NAME_RK356X = "/sys/devices/platform/fe8a0000.usb2-phy/otg_mode";private File file = null;private StorageManager mStorageManager = null;private String mMode = "";private String mSocName = "";private Context mContext;private boolean mLock = false;public UsbModeSettings(Context context) {mContext = context;mSocName = SystemProperties.get("sys.rk.soc");if (TextUtils.isEmpty(mSocName)) {mSocName = SystemProperties.get("ro.board.platform");}if(!TextUtils.isEmpty(mSocName) && mSocName.contains("rk3399")){file = new File(FILE_NAME_RK3399);}else{file = new File(FILE_NAME_RK3328);}file = getFile();mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);boolean ret = checkFile();String mode = ReadFromFile(file);if(ret && !TextUtils.isEmpty(mode)) {mMode = mode;}}private File getFile() {String fileName = FILE_NAME_RK3328;if (!TextUtils.isEmpty(mSocName) && mSocName.contains("rk3399")) {fileName = FILE_NAME_RK3399;} else if (!TextUtils.isEmpty(mSocName) && (mSocName.contains("rk322x") || mSocName.contains("rk3128h"))) {fileName = FILE_NAME_RK3229;} else if (!TextUtils.isEmpty(mSocName) && mSocName.contains("rk356x")) {fileName = FILE_NAME_RK356X;} else {fileName = FILE_NAME_RK3328;}return new File(fileName);}public boolean getDefaultValue() {if (isRk3368()) {//通過prop和init來設置otg模式return getFakeDataRole();}if (checkFile()) {Log.d("UsbModeSelect", "/data/otg.cfg not exist,but temp file exist");if (isRk3368()) {return getFakeDataRole();}if (mMode.equals(HOST_MODE)) {return false;} else {return true;}} else {mMode = HOST_MODE;return false;}}private String ReadFromFile(File file) {if (checkFile()) {try {FileInputStream fin = new FileInputStream(file);BufferedReader reader = new BufferedReader(new InputStreamReader(fin));String config = reader.readLine();fin.close();return config;} catch (IOException e) {Log.i(TAG, "ReadFromFile exception:" + e);e.printStackTrace();}}return null;}private void Write2File(File file, String mode) {if (!checkFile() || (mode == null))return;Log.d("UsbModeSelect", "Write2File,write mode = " + mode);try {FileOutputStream fout = new FileOutputStream(file);PrintWriter pWriter = new PrintWriter(fout);pWriter.println(mode);pWriter.flush();pWriter.close();fout.close();} catch (IOException re) {}}public void onUsbModeClick(String mode) {if (isRk3368()) {setPropFakeDataRole(mode);return;}if (mLock)return;mLock = true;mMode = mode;synchronized (this) {Log.d("UsbModeSettings", "synchronized start");new Thread(mUsbSwitch).start();}}private Runnable mUsbSwitch = new Runnable() {public synchronized void run() {Log.d("UsbModeSettings", "mUsbSwitch Runnable() in*******************");if (mStorageManager != null) {if (mMode == HOST_MODE) {mStorageManager.disableUsbMassStorage();Log.d("UsbModeSettings", "mStorageManager.disableUsbMassStorage()*******************");Write2File(file, mMode);} else {Write2File(file, mMode);Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage() in *******************");mStorageManager.enableUsbMassStorage();Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage() out*******************");}}Log.d("UsbModeSettings", "mUsbSwitch Runnable() out*******************");mLock = false;}};private boolean checkFile() {if (file == null) {Log.e(TAG, "file is null pointer");return false;}String fileName = file.getName();if (!file.exists()) {Log.e(TAG, fileName + " not exist!!!");return false;}if (!file.canRead()) {Log.e(TAG, fileName + " can't read!!!");return false;}if (!file.canWrite()) {Log.e(TAG, fileName + " can't write!!!");return false;}return true;}// 判斷是否為3368芯片private boolean isRk3368() {if (!TextUtils.isEmpty(mSocName) && mSocName.contains("rk3368")) {return true;} else {return false;}}private boolean getFakeDataRole() {String fakeDataRole = SystemProperties.get(PROP_FAKE_DATA_ROLE, SLAVE_MODE);Log.d(TAG, "prop fakeDataRole = " + fakeDataRole);if (!TextUtils.isEmpty(fakeDataRole) && fakeDataRole.equals(SLAVE_MODE)) {return true;} else {return false;}}// 將mode轉換為Int值,3368的mode為0,1,2private void setPropFakeDataRole(String mode) {Log.d(TAG, "setprop mode = " + mode);SystemProperties.set(PROP_FAKE_DATA_ROLE, mode);}
}
補充說明
- 以上源碼接口需要
system
及以上權限 - StorageManager部分接口可以通過反射獲得.
提取關鍵代碼:
@Overridepublic void onClick(View v) {StorageManager mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);File file = new File(FILE_NAME_RK356X);//切換為 OTG (USB 調試)if(R.id.btOtg == v.getId()) {Write2File(file, SLAVE_MODE);Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage() in *******************");enableUsbMassStorage(mStorageManager);Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage() out*******************");} else if(R.id.btHost == v.getId()) {//切換為HOSTdisableUsbMassStorage(mStorageManager);Log.d("UsbModeSettings", "mStorageManager.disableUsbMassStorage()*******************");Write2File(file, HOST_MODE);}}//寫入 USB的模式: otg 或 hostprivate void Write2File(File file, String mode) {if (!new File(FILE_NAME_RK356X).exists() || (mode == null))return;Log.d("UsbModeSelect", "Write2File,write mode = " + mode);try {FileOutputStream fout = new FileOutputStream(file);PrintWriter pWriter = new PrintWriter(fout);pWriter.println(mode);pWriter.flush();pWriter.close();fout.close();} catch (IOException re) {}}//反射接口void enableUsbMassStorage(StorageManager sm){try {Method enableUsbMassStorage = sm.getClass().getMethod("enableUsbMassStorage");enableUsbMassStorage.invoke(sm);} catch (Exception e){e.printStackTrace();}}void disableUsbMassStorage(StorageManager sm){try {Method disableUsbMassStorage = sm.getClass().getMethod("disableUsbMassStorage");disableUsbMassStorage.invoke(sm);} catch (Exception e){e.printStackTrace();}}