usb hal的实现

源码位置:android/hardware/aw/usb

rc文件位置:

android/system/core/rootdir/init.usb.configfs.rc

android/system/core/rootdir/init.usb.rc

android/device/softwinner/ceres/common/system/init.sun50iw10p1.usb.rc

usb hal实现

1. uevent_event

usb插拔的时候,内核会上传usb相关的uevent事件;接收并处理uevent事件

static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
    char msg[UEVENT_MSG_LEN + 2];
    char *cp;
    int n;

    // 接收内核的uevent事件
    n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
    if (n <= 0)
        return;
    if (n >= UEVENT_MSG_LEN)   /* overflow -- discard */
        return;

    msg[n] = '\0';
    msg[n + 1] = '\0';
    cp = msg;

    while (*cp) {
        // 比对收到的usb uevent信息,如果是usb的,则进行下一步操作
        if ((strcmp(cp, "add@/devices/platform/soc@2900000/10.usbc0/typec/port0/port0-partner") == 0) ||
                (strcmp(cp, "remove@/devices/platform/soc@2900000/10.usbc0/typec/port0/port0-partner") == 0)) {
            ALOGE("uevent received %s", cp);
            if (payload->usb->mCallback != NULL) {
                hidl_vec<PortStatus> currentPortStatus;
                // 1. 获取接口状态
                Status status = getPortStatusHelper(currentPortStatus);
                // 2. 调用上层的回调接口,通知上层
                Return<void> ret =
                    payload->usb->mCallback->notifyPortStatusChange(currentPortStatus, status);
                if (!ret.isOk())
                    ALOGE("error %s", ret.description().c_str());
            }
            break;
        }
        /* advance to after the next \0 */
        while (*cp++);
    }
}

2. getPortStatusHelper

获取当前usb的状态,并填充到currentPortStatus中

Status getPortStatusHelper (hidl_vec<PortStatus>& currentPortStatus) {
  std::unordered_map<std::string, bool> names;
  // 在/sys/class/typec目录下找,names = [port0  port0-partner]
  // 如果/sys/class/typec目录下只有port0,则下面的connected=false;如果有port0-partner,则下面的connected=true
  Status result = getTypeCPortNamesHelper(&names);
  int i = -1;

    if (result == Status::SUCCESS) {
        currentPortStatus.resize(names.size());
        for (std::pair<std::string, bool> port : names) {
            i++;
            // port = port0,connected = 1(有port0-partner)
            ALOGI("port = %s, connected = %d\n", port.first.c_str(), port.second);
            currentPortStatus[i].portName = port.first;

            uint32_t currentRole;
            // 1. 获取"/sys/class/typec/" + portName + "/power_role";节点信息
            if (getCurrentRoleHelper(port.first, port.second,
                               PortRoleType::POWER_ROLE,
                               &currentRole) == Status::SUCCESS) {
                currentPortStatus[i].currentPowerRole =
                static_cast<PortPowerRole> (currentRole);
            } else {
                ALOGE("Error while retreiving portNames");
                goto done;
            }
			// 获取"/sys/class/typec/" + portName + "/data_role";节点信息
            if (getCurrentRoleHelper(port.first, port.second, PortRoleType::DATA_ROLE,
                               &currentRole) == Status::SUCCESS) {
                currentPortStatus[i].currentDataRole =
                        static_cast<PortDataRole> (currentRole);
            } else {
                ALOGE("Error while retreiving current port role");
                goto done;
            }
			// 获取"/sys/class/typec/" + portName + "/data_role";节点信息
            // 注意mode也是data_role节点的信息
            if (getCurrentRoleHelper(port.first, port.second, PortRoleType::MODE,
                               &currentRole) == Status::SUCCESS) {
                currentPortStatus[i].currentMode =
                    static_cast<PortMode> (currentRole);
            } else {
                ALOGE("Error while retreiving current data role");
                goto done;
            }

            currentPortStatus[i].canChangeMode =
                // 如果有这个文件,则返回true
                port.second ? canSwitchRoleHelper(port.first, PortRoleType::MODE) : false;
            currentPortStatus[i].canChangeDataRole =
                port.second ? canSwitchRoleHelper(port.first, PortRoleType::DATA_ROLE) : false;
            currentPortStatus[i].canChangePowerRole =
                port.second ? canSwitchRoleHelper(port.first, PortRoleType::POWER_ROLE) : false;

            // 这三个都是true
            ALOGI("canChangeMode: %d canChagedata: %d canChangePower:%d",
                currentPortStatus[i].canChangeMode,
                currentPortStatus[i].canChangeDataRole,
                currentPortStatus[i].canChangePowerRole);

            // 如果supportModes没有设置上去的话,usb切换界面就是灰色的
            currentPortStatus[i].supportedModes = PortMode::DFP;
        }
        return Status::SUCCESS;
    }
done:
    return Status::ERROR;
}

1. getCurrentRoleHelper

getCurrentRoleHelper:获取节点信息

Status getCurrentRoleHelper(const std::string &portName, bool connected,
                            PortRoleType type, uint32_t *currentRole) {
  std::string filename;
  std::string roleName;
  std::string accessory;

  // Mode
  if (type == PortRoleType::POWER_ROLE) {
    filename = "/sys/class/typec/" + portName + "/power_role";
    *currentRole = static_cast<uint32_t>(PortPowerRole::NONE);
  } else if (type == PortRoleType::DATA_ROLE) {
    filename = "/sys/class/typec/" + portName + "/data_role";
    *currentRole = static_cast<uint32_t>(PortDataRole::NONE);
  } else if (type == PortRoleType::MODE) {
    filename = "/sys/class/typec/" + portName + "/data_role";
    *currentRole = static_cast<uint32_t>(PortMode::NONE);
  } else {
    return Status::ERROR;
  }

  // 注意这个connected,如果没有实现port0-partner节点的话,就无法实现connected切换逻辑了
  if (!connected) return Status::SUCCESS;

  if (readFile(filename, roleName)) {
    ALOGE("getCurrentRole: Failed to open filesystem node: %s",
          filename.c_str());
    return Status::ERROR;
  }

  extractRole(&roleName);

  if (roleName == "dfp")
    *currentRole = static_cast<uint32_t> (PortMode::DFP);
  else if (roleName == "ufp")
    *currentRole = static_cast<uint32_t> (PortMode::UFP);
  else if (roleName == "source")
    *currentRole = static_cast<uint32_t> (PortPowerRole::SOURCE);
  else if (roleName == "sink")
    *currentRole = static_cast<uint32_t> (PortPowerRole::SINK);
  else if (roleName == "host")
    *currentRole = static_cast<uint32_t> (PortDataRole::HOST);
  else if (roleName == "device")
    *currentRole = static_cast<uint32_t> (PortDataRole::DEVICE);
  else if (roleName != "none") {
    return Status::UNRECOGNIZED_ROLE;
  }

  return Status::SUCCESS;
}

4. notifyPortStatusChange

  1. 调用上层的回调接口,将usb的状态currentPortStatus传给上层
// frameworks/base/services/usb/java/com/android/server/usb/UsbPortManager.java
		public void notifyPortStatusChange(
                ArrayList<android.hardware.usb.V1_0.PortStatus> currentPortStatus, int retval) {
            if (!portManager.mSystemReady) {
                return;
            }

            if (retval != Status.SUCCESS) {
                logAndPrint(Log.ERROR, pw, "port status enquiry failed");
                return;
            }

            ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();

            for (android.hardware.usb.V1_0.PortStatus current : currentPortStatus) {
                RawPortInfo temp = new RawPortInfo(current.portName,
                        current.supportedModes, CONTAMINANT_PROTECTION_NONE,
                        current.currentMode,
                        current.canChangeMode, current.currentPowerRole,
                        current.canChangePowerRole,
                        current.currentDataRole, current.canChangeDataRole,
                        false, CONTAMINANT_PROTECTION_NONE,
                        false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
                newPortInfo.add(temp);
                logAndPrint(Log.INFO, pw, "ClientCallback V1_0: " + current.portName);
            }

            Message message = portManager.mHandler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
            message.what = MSG_UPDATE_PORTS;
            message.setData(bundle);
            // 这里发送MSG_UPDATE_PORTS消息
            portManager.mHandler.sendMessage(message);
        }

    private final Handler mHandler = new Handler(FgThread.get().getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_PORTS: {
                    Bundle b = msg.getData();
                    ArrayList<RawPortInfo> PortInfo = b.getParcelableArrayList(PORT_INFO);
                    synchronized (mLock) {
                        // 处理MSG_UPDATE_PORTS消息
                        updatePortsLocked(null, PortInfo);
                    }
                    break;
                }
                case MSG_SYSTEM_READY: {
                    mNotificationManager = (NotificationManager)
                            mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                    updateUsbHalVersion();
                    break;
                }
            }
        }
    };

1. updatePortsLocked

    /**
     * Simulated ports directly add the new roles to mSimulatedPorts before calling.
     * USB hal callback populates and sends the newPortInfo.
     */
    private void updatePortsLocked(IndentingPrintWriter pw, ArrayList<RawPortInfo> newPortInfo) {
        for (int i = mPorts.size(); i-- > 0; ) {
            mPorts.valueAt(i).mDisposition = PortInfo.DISPOSITION_REMOVED;
        }

        // Enumerate all extant ports.
        if (!mSimulatedPorts.isEmpty()) {
            final int count = mSimulatedPorts.size();
            for (int i = 0; i < count; i++) {
                final RawPortInfo portInfo = mSimulatedPorts.valueAt(i);
                addOrUpdatePortLocked(portInfo.portId, portInfo.supportedModes,
                        portInfo.supportedContaminantProtectionModes,
                        portInfo.currentMode, portInfo.canChangeMode,
                        portInfo.currentPowerRole, portInfo.canChangePowerRole,
                        portInfo.currentDataRole, portInfo.canChangeDataRole,
                        portInfo.supportsEnableContaminantPresenceProtection,
                        portInfo.contaminantProtectionStatus,
                        portInfo.supportsEnableContaminantPresenceDetection,
                        portInfo.contaminantDetectionStatus, pw);
            }
        } else {
            // 不是simulation的,走这里
            for (RawPortInfo currentPortInfo : newPortInfo) {
                // 1. 这里会修改portInfo.mDisposition的值
                addOrUpdatePortLocked(currentPortInfo.portId, currentPortInfo.supportedModes,
                        currentPortInfo.supportedContaminantProtectionModes,
                        currentPortInfo.currentMode, currentPortInfo.canChangeMode,
                        currentPortInfo.currentPowerRole, currentPortInfo.canChangePowerRole,
                        currentPortInfo.currentDataRole, currentPortInfo.canChangeDataRole,
                        currentPortInfo.supportsEnableContaminantPresenceProtection,
                        currentPortInfo.contaminantProtectionStatus,
                        currentPortInfo.supportsEnableContaminantPresenceDetection,
                        currentPortInfo.contaminantDetectionStatus, pw);
            }
        }

        // Process the updates.
        // Once finished, the list of ports will only contain ports in DISPOSITION_READY.
        for (int i = mPorts.size(); i-- > 0; ) {
            final PortInfo portInfo = mPorts.valueAt(i);
            switch (portInfo.mDisposition) {
                case PortInfo.DISPOSITION_ADDED:
                    handlePortAddedLocked(portInfo, pw);
                    portInfo.mDisposition = PortInfo.DISPOSITION_READY;
                    break;
                    // 2. 插入USB的时候,走这里
                case PortInfo.DISPOSITION_CHANGED:
                    handlePortChangedLocked(portInfo, pw);
                    portInfo.mDisposition = PortInfo.DISPOSITION_READY;
                    break;
                case PortInfo.DISPOSITION_REMOVED:
                    mPorts.removeAt(i);
                    portInfo.mUsbPortStatus = null; // must do this early
                    handlePortRemovedLocked(portInfo, pw);
                    break;
            }
        }
    }
1. addOrUpdatePortLocked
        // 连接的状态,就是mCurrentMode不为0
    public boolean isConnected() {
        return mCurrentMode != 0;
    }

// Must only be called by updatePortsLocked.
    private void addOrUpdatePortLocked(String portId, int supportedModes,
            int supportedContaminantProtectionModes,
            int currentMode, boolean canChangeMode,
            int currentPowerRole, boolean canChangePowerRole,
            int currentDataRole, boolean canChangeDataRole,
            boolean supportsEnableContaminantPresenceProtection,
            int contaminantProtectionStatus,
            boolean supportsEnableContaminantPresenceDetection,
            int contaminantDetectionStatus,
            IndentingPrintWriter pw) {
        // Only allow mode switch capability for dual role ports.
        // Validate that the current mode matches the supported modes we expect.
        // 这里会影响connected
        if ((supportedModes & MODE_DUAL) != MODE_DUAL) {
            canChangeMode = false;
            if (currentMode != 0 && currentMode != supportedModes) {
                logAndPrint(Log.WARN, pw, "Ignoring inconsistent current mode from USB "
                        + "port driver: supportedModes=" + UsbPort.modeToString(supportedModes)
                        + ", currentMode=" + UsbPort.modeToString(currentMode));
                currentMode = 0;
            }
        }

        // Determine the supported role combinations.
        // Note that the policy is designed to prefer setting the power and data
        // role independently rather than changing the mode.
        int supportedRoleCombinations = UsbPort.combineRolesAsBit(
                currentPowerRole, currentDataRole);
        if (currentMode != 0 && currentPowerRole != 0 && currentDataRole != 0) {
            if (canChangePowerRole && canChangeDataRole) {
                // Can change both power and data role independently.
                // Assume all combinations are possible.
                supportedRoleCombinations |=
                        COMBO_SOURCE_HOST | COMBO_SOURCE_DEVICE
                                | COMBO_SINK_HOST | COMBO_SINK_DEVICE;
            } else if (canChangePowerRole) {
                // Can only change power role.
                // Assume data role must remain at its current value.
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        POWER_ROLE_SOURCE, currentDataRole);
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        POWER_ROLE_SINK, currentDataRole);
            } else if (canChangeDataRole) {
                // Can only change data role.
                // Assume power role must remain at its current value.
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        currentPowerRole, DATA_ROLE_HOST);
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        currentPowerRole, DATA_ROLE_DEVICE);
            } else if (canChangeMode) {
                // Can only change the mode.
                // Assume both standard UFP and DFP configurations will become available
                // when this happens.
                supportedRoleCombinations |= COMBO_SOURCE_HOST | COMBO_SINK_DEVICE;
            }
        }

        // Update the port data structures.
        PortInfo portInfo = mPorts.get(portId);
        if (portInfo == null) {
            portInfo = new PortInfo(mContext.getSystemService(UsbManager.class),
                portId, supportedModes, supportedContaminantProtectionModes,
                supportsEnableContaminantPresenceProtection,
                supportsEnableContaminantPresenceDetection);
            portInfo.setStatus(currentMode, canChangeMode,
                    currentPowerRole, canChangePowerRole,
                    currentDataRole, canChangeDataRole,
                    supportedRoleCombinations, contaminantProtectionStatus,
                    contaminantDetectionStatus);
            mPorts.put(portId, portInfo);
            // 由dumpsys usb可以知道,断开的时候,portInfo也不会为null,所以走这里
        } else {
            // Validate that ports aren't changing definition out from under us.
            if (supportedModes != portInfo.mUsbPort.getSupportedModes()) {
                logAndPrint(Log.WARN, pw, "Ignoring inconsistent list of supported modes from "
                        + "USB port driver (should be immutable): "
                        + "previous=" + UsbPort.modeToString(
                        portInfo.mUsbPort.getSupportedModes())
                        + ", current=" + UsbPort.modeToString(supportedModes));
            }

            if (supportsEnableContaminantPresenceProtection
                    != portInfo.mUsbPort.supportsEnableContaminantPresenceProtection()) {
                logAndPrint(Log.WARN, pw,
                        "Ignoring inconsistent supportsEnableContaminantPresenceProtection"
                        + "USB port driver (should be immutable): "
                        + "previous="
                        + portInfo.mUsbPort.supportsEnableContaminantPresenceProtection()
                        + ", current=" + supportsEnableContaminantPresenceProtection);
            }

            if (supportsEnableContaminantPresenceDetection
                    != portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()) {
                logAndPrint(Log.WARN, pw,
                        "Ignoring inconsistent supportsEnableContaminantPresenceDetection "
                        + "USB port driver (should be immutable): "
                        + "previous="
                        + portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()
                        + ", current=" + supportsEnableContaminantPresenceDetection);
            }


            // 走这里
            if (portInfo.setStatus(currentMode, canChangeMode,
                    currentPowerRole, canChangePowerRole,
                    currentDataRole, canChangeDataRole,
                    supportedRoleCombinations, contaminantProtectionStatus,
                    contaminantDetectionStatus)) {
                // 返回值是为true,走这里
                portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
            } else {
                portInfo.mDisposition = PortInfo.DISPOSITION_READY;
            }
        }
    }

1. setStatus
        public boolean setStatus(int currentMode, boolean canChangeMode,
                int currentPowerRole, boolean canChangePowerRole,
                int currentDataRole, boolean canChangeDataRole,
                int supportedRoleCombinations, int contaminantProtectionStatus,
                int contaminantDetectionStatus) {
            boolean dispositionChanged = false;

            mCanChangeMode = canChangeMode;
            mCanChangePowerRole = canChangePowerRole;
            mCanChangeDataRole = canChangeDataRole;
            // mUsbPortStatus在断开状态也是不为null的
            if (mUsbPortStatus == null
                // 但是currentmode是不相同的
                    || mUsbPortStatus.getCurrentMode() != currentMode
                    || mUsbPortStatus.getCurrentPowerRole() != currentPowerRole
                    || mUsbPortStatus.getCurrentDataRole() != currentDataRole
                    || mUsbPortStatus.getSupportedRoleCombinations()
                    != supportedRoleCombinations
                    || mUsbPortStatus.getContaminantProtectionStatus()
                    != contaminantProtectionStatus
                    || mUsbPortStatus.getContaminantDetectionStatus()
                    != contaminantDetectionStatus) {
                mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
                        supportedRoleCombinations, contaminantProtectionStatus,
                        contaminantDetectionStatus);
                dispositionChanged = true;
            }

            if (mUsbPortStatus.isConnected() && mConnectedAtMillis == 0) {
                mConnectedAtMillis = SystemClock.elapsedRealtime();
                mLastConnectDurationMillis = 0;
            } else if (!mUsbPortStatus.isConnected() && mConnectedAtMillis != 0) {
                mLastConnectDurationMillis = SystemClock.elapsedRealtime() - mConnectedAtMillis;
                mConnectedAtMillis = 0;
            }

            // 所以这里返回true
            return dispositionChanged;
        }

2. handlePortChangedLocked

    private void handlePortChangedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
        logAndPrint(Log.INFO, pw, "USB port changed: " + portInfo);
        enableContaminantDetectionIfNeeded(portInfo, pw);
        handlePortLocked(portInfo, pw);
    }
1. enableContaminantDetectionIfNeeded

直接返回,啥都没做

    private void enableContaminantDetectionIfNeeded(PortInfo portInfo, IndentingPrintWriter pw) {
        if (!mConnected.containsKey(portInfo.mUsbPort.getId())) {
            return;
        }

        if (mConnected.get(portInfo.mUsbPort.getId())
                && !portInfo.mUsbPortStatus.isConnected()
                && portInfo.mUsbPortStatus.getContaminantDetectionStatus()
                == UsbPortStatus.CONTAMINANT_DETECTION_DISABLED) {
            // Contaminant detection might have been temporarily disabled by the user
            // through SystemUI.
            // Re-enable contaminant detection when the accessory is unplugged.
            enableContaminantDetection(portInfo.mUsbPort.getId(), true, pw);
        }
    }
2. handlePortLocked
    private void handlePortLocked(PortInfo portInfo, IndentingPrintWriter pw) {
        sendPortChangedBroadcastLocked(portInfo);
        logToStatsd(portInfo, pw);
        // 在状态栏中发通知
        updateContaminantNotification();
    }
1. sendPortChangedBroadcastLocked
    private void sendPortChangedBroadcastLocked(PortInfo portInfo) {
        // 发送ACTION_USB_PORT_CHANGED广播,然后将usb插入相关的数据,通过intent发送出去
        final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
        intent.addFlags(
                Intent.FLAG_RECEIVER_FOREGROUND |
                        Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        intent.putExtra(UsbManager.EXTRA_PORT, ParcelableUsbPort.of(portInfo.mUsbPort));
        intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);

        // Guard against possible reentrance by posting the broadcast from the handler
        // instead of from within the critical section.
        mHandler.post(() -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                Manifest.permission.MANAGE_USB));
    }

5. settings应用中注册的广播接收器

// android/packages/apps/Settings/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
	private UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener =
            (connected, functions, powerRole, dataRole) -> {
                for (UsbDetailsController controller : mControllers) {
                    controller.refresh(connected, functions, powerRole, dataRole);
                }
            };

    @Override
    public void onReceive(Context context, Intent intent) {
        if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
            mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED)
                    || intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED);
            long functions = UsbManager.FUNCTION_NONE;
            if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MTP)
                    && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
                functions |= UsbManager.FUNCTION_MTP;
            }
            if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_PTP)
                    && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
                functions |= UsbManager.FUNCTION_PTP;
            }
            if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MIDI)) {
                functions |= UsbManager.FUNCTION_MIDI;
            }
            if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_RNDIS)) {
                functions |= UsbManager.FUNCTION_RNDIS;
            }
            if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_ACCESSORY)) {
                functions |= UsbManager.FUNCTION_ACCESSORY;
            }
            mFunctions = functions;
            mDataRole = mUsbBackend.getDataRole();
            mPowerRole = mUsbBackend.getPowerRole();
        } else if (UsbManager.ACTION_USB_PORT_CHANGED.equals(intent.getAction())) {
            UsbPortStatus portStatus = intent.getExtras()
                    .getParcelable(UsbManager.EXTRA_PORT_STATUS);
            if (portStatus != null) {
                mDataRole = portStatus.getCurrentDataRole();
                mPowerRole = portStatus.getCurrentPowerRole();
            }
        }
        if (mUsbConnectionListener != null) {
            mUsbConnectionListener.onUsbConnectionChanged(mConnected, mFunctions, mPowerRole,
                    mDataRole);
        }
    }

1. refresh

    @Override
    protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
        if (DEBUG) {
            Log.d(TAG, "refresh() connected : " + connected + ", functions : " + functions
                    + ", powerRole : " + powerRole + ", dataRole : " + dataRole);
        }
        // connected为true,以及dataRole为device,设置页面才会亮
        if (!connected || dataRole != DATA_ROLE_DEVICE) {
            mProfilesContainer.setEnabled(false);
        } else {
            // Functions are only available in device mode
            mProfilesContainer.setEnabled(true);
        }
        RadioButtonPreference pref;
        for (long option : FUNCTIONS_MAP.keySet()) {
            int title = FUNCTIONS_MAP.get(option);
            pref = getProfilePreference(UsbBackend.usbFunctionsToString(option), title);
            // Only show supported options
            if (mUsbBackend.areFunctionsSupported(option)) {
                if (isAccessoryMode(functions)) {
                    pref.setChecked(UsbManager.FUNCTION_MTP == option);
                } else {
                    pref.setChecked(functions == option);
                }
            } else {
                mProfilesContainer.removePreference(pref);
            }
        }
    }

综上:点亮settings中的usb连接页面的条件:supportedModes和currentMode和dataRole的值

6. dumpsys usb

1. 连接状态

USB MANAGER STATE (dumpsys usb):
{
  device_manager={
    handler={
      current_functions_applied=true
      screen_locked=false
      connected=true
      configured=true
      host_connected=false
      source_power=false
      sink_power=true
      usb_charging=false
      hide_usb_notification=false
      audio_accessory_connected=false
      kernel_state=CONFIGURED
    }
  }
  host_manager={
    num_connects=0
  }
  port_manager={
    is_simulation_active=false
    usb_ports={
      port={
        id=port0
        supported_modes=dfp
      }
      status={
        connected=true
        current_mode=dfp
        power_role=sink
        data_role=device
        role_combinations={
          power_role=sink
          data_role=device
        }
        contaminant_presence_status=not-supported
      }
      can_change_mode=false
      can_change_power_role=false
      can_change_data_role=false
      connected_at_millis=66553985
      last_connect_duration_millis=0
    }
  }
  alsa_manager={
    cards_parser=-1
  }
  settings_manager={
    user_settings={
      user_id=0
      device_attached_activities=[
        {
          activity={
            package_name=com.android.gallery3d
            class_name=com.android.gallery3d.ingest.IngestActivity
          }
          filters={
            vendor_id=-1
            product_id=-1
            class=6
            subclass=1
            protocol=1
            manufacturer_name=null
            product_name=null
            serial_number=null
          }
        }
        {
          activity={
            package_name=com.android.mtp
            class_name=com.android.mtp.ReceiverActivity
          }
          filters=[
            {
              vendor_id=-1
              product_id=-1
              class=255
              subclass=255
              protocol=0
              manufacturer_name=null
              product_name=null
              serial_number=null
            }
            {
              vendor_id=-1
              product_id=-1
              class=6
              subclass=1
              protocol=1
              manufacturer_name=null
              product_name=null
              serial_number=null
            }
          ]
        }
      ]
    }
    profile_group_settings={
      parent_user_id=0
    }
  }
  permissions_manager={
    user_permissions={
      user_id=0
    }
  }
}

2. 断开状态

USB MANAGER STATE (dumpsys usb):
{
  device_manager={
    handler={
      current_functions_applied=true
      screen_locked=false
      connected=false
      configured=false
      host_connected=false
      source_power=false
      sink_power=false
      usb_charging=false
      hide_usb_notification=false
      audio_accessory_connected=false
      kernel_state=DISCONNECTED
    }
  }
  host_manager={
    num_connects=0
  }
  port_manager={
    is_simulation_active=false
    usb_ports={
      port={
        id=port0
        supported_modes=dfp
      }
      status={
        connected=false
        current_mode=none
        power_role=no-power
        data_role=no-data
        role_combinations={
          power_role=no-power
          data_role=no-data
        }
        contaminant_presence_status=not-supported
      }
      can_change_mode=false
      can_change_power_role=false
      can_change_data_role=false
      connected_at_millis=0
      last_connect_duration_millis=595999
    }
  }
  alsa_manager={
    cards_parser=-1
  }
  settings_manager={
    user_settings={
      user_id=0
      device_attached_activities=[
        {
          activity={
            package_name=com.android.gallery3d
            class_name=com.android.gallery3d.ingest.IngestActivity
          }
          filters={
            vendor_id=-1
            product_id=-1
            class=6
            subclass=1
            protocol=1
            manufacturer_name=null
            product_name=null
            serial_number=null
          }
        }
        {
          activity={
            package_name=com.android.mtp
            class_name=com.android.mtp.ReceiverActivity
          }
          filters=[
            {
              vendor_id=-1
              product_id=-1
              class=255
              subclass=255
              protocol=0
              manufacturer_name=null
              product_name=null
              serial_number=null
            }
            {
              vendor_id=-1
              product_id=-1
              class=6
              subclass=1
              protocol=1
              manufacturer_name=null
              product_name=null
              serial_number=null
            }
          ]
        }
      ]
    }
    profile_group_settings={
      parent_user_id=0
    }
  }
  permissions_manager={
    user_permissions={
      user_id=0
    }
  }
}

MTP切换

1. rc文件设置属性的方式来切换mtp

1. refresh

  1. 下拉菜单,打开settings应用切换mtp
packages/apps/Settings/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
    @Override
    protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
    	// 对上面connected device和this device部分的控制
        if (!connected || dataRole != DATA_ROLE_DEVICE) {
            mProfilesContainer.setEnabled(false);
        } else {
            // Functions are only available in device mode
            mProfilesContainer.setEnabled(true);
        }
        RadioButtonPreference pref;
        // 对下面File Transfer和USB tethering部分的控制
        for (long option : FUNCTIONS_MAP.keySet()) {
            int title = FUNCTIONS_MAP.get(option);
            pref = getProfilePreference(UsbBackend.usbFunctionsToString(option), title);
            // Only show supported options
            if (mUsbBackend.areFunctionsSupported(option)) {
            	// 如果点了,则点亮
                pref.setChecked(functions == option);
            } else {
                mProfilesContainer.removePreference(pref);
            }
        }
    }

2. onRadioButtonClicked

  1. 点击并切换到mtp上
    @Override
    public void onRadioButtonClicked(RadioButtonPreference preference) {
        final long function = UsbBackend.usbFunctionsFromString(preference.getKey());
        final long previousFunction = mUsbBackend.getCurrentFunctions();
        if (function != previousFunction && !Utils.isMonkeyRunning()) {
            mPreviousFunction = previousFunction;

            //Update the UI in advance to make it looks smooth
            final RadioButtonPreference prevPref =
                    (RadioButtonPreference) mProfilesContainer.findPreference(
                            UsbBackend.usbFunctionsToString(mPreviousFunction));
            if (prevPref != null) {
                prevPref.setChecked(false);
                preference.setChecked(true);
            }

            if (function == UsbManager.FUNCTION_RNDIS) {
                // We need to have entitlement check for usb tethering, so use API in
                // ConnectivityManager.
                // 如果是点了网络共享的,则走这里
                mConnectivityManager.startTethering(TETHERING_USB, true /* showProvisioningUi */,
                        mOnStartTetheringCallback);
            } else {
                // mtp的走这里,最后走到了usbmanager服务中
                mUsbBackend.setCurrentFunctions(function);
            }
        }
    }

3. setCurrentFunctions

  1. usbdevicemanager切换functions,打开DEBUG。
    public void setCurrentFunctions(long functions) {
        if (DEBUG) {
            Slog.d(TAG, "setCurrentFunctions(" + UsbManager.usbFunctionsToString(functions) + ")");
        }
        if (functions == UsbManager.FUNCTION_NONE) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_CHARGING);
        } else if (functions == UsbManager.FUNCTION_MTP) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MTP);
        } else if (functions == UsbManager.FUNCTION_PTP) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_PTP);
        } else if (functions == UsbManager.FUNCTION_MIDI) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_MIDI);
        } else if (functions == UsbManager.FUNCTION_RNDIS) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_RNDIS);
        } else if (functions == UsbManager.FUNCTION_ACCESSORY) {
            MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_ACCESSORY);
        }
        // 发送消息,后调用setEnabledFunctions(functions, false);
        mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions);
    }

4. setEnabledFunctions

  1. setEnabledFunctions设置functions,如果hal支持,则会调用hal的函数,否则调用usbhandlerlegacy上的函数
        // frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
		@Override
        protected void setEnabledFunctions(long usbFunctions, boolean forceRestart) {
            boolean usbDataUnlocked = isUsbDataTransferActive(usbFunctions);
            if (DEBUG) {
                Slog.d(TAG, "setEnabledFunctions functions=" + usbFunctions + ", "
                        + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked);
            }

            if (usbDataUnlocked != mUsbDataUnlocked) {
                mUsbDataUnlocked = usbDataUnlocked;
                updateUsbNotification(false);
                forceRestart = true;
            }

            /**
             * Try to set the enabled functions.
             */
            final long oldFunctions = mCurrentFunctions;
            final boolean oldFunctionsApplied = mCurrentFunctionsApplied;
            // 调用trySetEnabledFunctions设置functions函数
            if (trySetEnabledFunctions(usbFunctions, forceRestart)) {
                return;
            }

            /**
             * Didn't work.  Try to revert changes.
             * We always reapply the policy in case certain constraints changed such as
             * user restrictions independently of any other new functions we were
             * trying to activate.
             */
            if (oldFunctionsApplied && oldFunctions != usbFunctions) {
                Slog.e(TAG, "Failsafe 1: Restoring previous USB functions.");
                if (trySetEnabledFunctions(oldFunctions, false)) {
                    return;
                }
            }

            /**
             * Still didn't work.  Try to restore the default functions.
             */
            Slog.e(TAG, "Failsafe 2: Restoring default USB functions.");
            if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
                return;
            }

            /**
             * Now we're desperate.  Ignore the default functions.
             * Try to get ADB working if enabled.
             */
            Slog.e(TAG, "Failsafe 3: Restoring empty function list (with ADB if enabled).");
            if (trySetEnabledFunctions(UsbManager.FUNCTION_NONE, false)) {
                return;
            }

            /**
             * Ouch.
             */
            Slog.e(TAG, "Unable to set any USB functions!");
        }

5. trySetEnabledFunctions

  1. 调用trySetEnabledFunctions函数设置functions
        private boolean trySetEnabledFunctions(long usbFunctions, boolean forceRestart) {
            String functions = null;
            if (usbFunctions != UsbManager.FUNCTION_NONE) {
                functions = UsbManager.usbFunctionsToString(usbFunctions);
            }
            mCurrentFunctions = usbFunctions;
            if (functions == null || applyAdbFunction(functions)
                    .equals(UsbManager.USB_FUNCTION_NONE)) {
                functions = UsbManager.usbFunctionsToString(getChargingFunctions());
            }
            functions = applyAdbFunction(functions);

            String oemFunctions = applyOemOverrideFunction(functions);

            if (!isNormalBoot() && !mCurrentFunctionsStr.equals(functions)) {
                setSystemProperty(getPersistProp(true), functions);
            }

            if ((!functions.equals(oemFunctions)
                    && !mCurrentOemFunctions.equals(oemFunctions))
                    || !mCurrentFunctionsStr.equals(functions)
                    || !mCurrentFunctionsApplied
                    || forceRestart) {
                Slog.i(TAG, "Setting USB config to " + functions);
                mCurrentFunctionsStr = functions;
                mCurrentOemFunctions = oemFunctions;
                mCurrentFunctionsApplied = false;

                /**
                 * Kick the USB stack to close existing connections.
                 */
                // 先把sys.usb.config属性设为none
                setUsbConfig(UsbManager.USB_FUNCTION_NONE);

                if (!waitForState(UsbManager.USB_FUNCTION_NONE)) {
                    Slog.e(TAG, "Failed to kick USB config");
                    return false;
                }

                /**
                 * Set the new USB configuration.
                 */
                // 然后把sys.usb.config属性设置为新的functions(如mtp)
                setUsbConfig(oemFunctions);

                if (mBootCompleted
                        && (containsFunction(functions, UsbManager.USB_FUNCTION_MTP)
                        || containsFunction(functions, UsbManager.USB_FUNCTION_PTP))) {
                    /**
                     * Start up dependent services.
                     */
                    updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
                }

                if (!waitForState(oemFunctions)) {
                    Slog.e(TAG, "Failed to switch USB config to " + functions);
                    return false;
                }

                mCurrentFunctionsApplied = true;
            }
            return true;
        }

6. setUsbConfig

  1. 设置属性,来设置functions
        private void setUsbConfig(String config) {
            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
            /**
             * set the new configuration
             * we always set it due to b/23631400, where adbd was getting killed
             * and not restarted due to property timeouts on some devices
             */
            // 设置sys.usb.config属性
            setSystemProperty(USB_CONFIG_PROPERTY, config);
        }

7. rc中设置usbfunction

1. init.usb.configfs.rc
// android/system/core/rootdir/init.usb.configfs.rc
1. 一般是先设置为none,
on property:sys.usb.config=none && property:sys.usb.configfs=1
    write /config/usb_gadget/g1/UDC "none"
    stop adbd
    setprop sys.usb.ffs.ready 0
    write /config/usb_gadget/g1/bDeviceClass 0
    write /config/usb_gadget/g1/bDeviceSubClass 0
    write /config/usb_gadget/g1/bDeviceProtocol 0
    rm /config/usb_gadget/g1/configs/b.1/f1
    rm /config/usb_gadget/g1/configs/b.1/f2
    rm /config/usb_gadget/g1/configs/b.1/f3
    rmdir /config/usb_gadget/g1/functions/rndis.gs4
    setprop sys.usb.state ${sys.usb.config}


2. 然后设为mtp和adb
on property:sys.usb.config=mtp,adb && property:sys.usb.configfs=1
    start adbd

on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb && property:sys.usb.configfs=1
    write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "mtp_adb"
    symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1
    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
    write /config/usb_gadget/g1/UDC ${sys.usb.controller}
    setprop sys.usb.state ${sys.usb.config}
2. init.sun50iw10p1.usb.rc
android/device/softwinner/ceres/common/system/init.sun50iw10p1.usb.rc
1. 先设置为none
on property:sys.usb.config=none && property:sys.usb.configfs=1
    write /config/usb_gadget/g1/os_desc/use 0
    
2. 然后设置为mtp,adb
on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb && property:sys.usb.configfs=1
    write /config/usb_gadget/g1/idProduct 0x1007
    write /config/usb_gadget/g1/os_desc/use 1
    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
    symlink /config/usb_gadget/g1/functions/ffs.mtp /config/usb_gadget/g1/configs/b.1/f2

命令行切换到mtp

注意:对于win7的电脑,可能命令行切换到mtp会失败

setprop sys.usb.config none
setprop sys.usb.config mtp,adb

2. usb gadget hal进行mtp切换

前面中refresh -> onRadioButtonClicked -> setCurrentFunctions -> setEnabledFunctions -> trySetEnabledFunctions的调用都是一样的。

这里会调用UsbHandlerHal中的handleMessage函数来处理MSG_SET_CURRENT_FUNCTIONS消息

不同点在setUsbConfig函数了:

1. setUsbConfig

	private void setUsbConfig(long config, boolean chargingFunctions) {
            if (true) Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest);
            /**
             * Cancel any ongoing requests, if present.
             */
            removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
            removeMessages(MSG_SET_FUNCTIONS_TIMEOUT);
            removeMessages(MSG_SET_CHARGING_FUNCTIONS);

            synchronized (mGadgetProxyLock) {
                if (mGadgetProxy == null) {
                    Slog.e(TAG, "setUsbConfig mGadgetProxy is null");
                    return;
                }
                try {
                    if ((config & UsbManager.FUNCTION_ADB) != 0) {
                        /**
                         * Start adbd if ADB function is included in the configuration.
                         */
                        LocalServices.getService(AdbManagerInternal.class)
                                .startAdbdForTransport(AdbTransportType.USB);
                    } else {
                        /**
                         * Stop adbd otherwise
                         */
                        LocalServices.getService(AdbManagerInternal.class)
                                .stopAdbdForTransport(AdbTransportType.USB);
                    }
                    UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
                            config, chargingFunctions);
                    // 这里调用gadget hal来设置function
                    mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback,
                            SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS);
                    sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions,
                            SET_FUNCTIONS_TIMEOUT_MS);
                    if (mConnected) {
                        // Only queue timeout of enumeration when the USB is connected
                        sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions,
                                SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS);
                    }
                    if (DEBUG) Slog.d(TAG, "timeout message queued");
                } catch (RemoteException e) {
                    Slog.e(TAG, "Remoteexception while calling setCurrentUsbFunctions", e);
                }
            }
        }

2. setCurrentUsbFunctions

Return<void> UsbGadget::setCurrentUsbFunctions(
    uint64_t functions, const sp<V1_0::IUsbGadgetCallback> &callback,
    uint64_t timeout) {
  std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);

  mCurrentUsbFunctions = functions;
  mCurrentUsbFunctionsApplied = false;

  // Unlink the gadget and stop the monitor if running.
    // 1. 先将function设为none
  V1_0::Status status = tearDownGadget();
  if (status != Status::SUCCESS) {
    ALOGE("tearDownGadget error");
    goto error;
  }

  ALOGI("Returned from tearDown gadget");

  // Leave the gadget pulled down to give time for the host to sense disconnect.
  usleep(DISCONNECT_WAIT_US);

  if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) {
    if (callback == NULL) return Void();
    Return<void> ret =
        callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
    if (!ret.isOk())
      ALOGE("Error while calling setCurrentUsbFunctionsCb %s",
            ret.description().c_str());
    return Void();
  }

    // 2. 然后设置idVendor和idProduct
  status = validateAndSetVidPid(functions);

  if (status != Status::SUCCESS) {
    ALOGE("validateAndSetVidPid error");
    goto error;
  }

    // 3. 最后设置functions
  status = setupFunctions(functions, callback, timeout);
  if (status != Status::SUCCESS) {
    ALOGE("setupFunctions error");
    goto error;
  }

  ALOGI("Usb Gadget setcurrent functions called successfully");
  return Void();

error:
  ALOGI("Usb Gadget setcurrent functions failed");
  if (callback == NULL) return Void();
  Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
  if (!ret.isOk())
    ALOGE("Error while calling setCurrentUsbFunctionsCb %s",
          ret.description().c_str());
  return Void();
}
1. tearDownGadget
V1_0::Status UsbGadget::tearDownGadget() {
  ALOGI("setCurrentUsbFunctions None");

    // 1. 往/config/usb_gadget/g1/UDC 写none
  if (!WriteStringToFile("none", PULLUP_PATH))
    ALOGI("Gadget cannot be pulled down");

    // 往/config/usb_gadget/g1/bDeviceClass 写0
  if (!WriteStringToFile("0", DEVICE_CLASS_PATH)) return Status::ERROR;

    // 往/config/usb_gadget/g1/bDeviceSubClass 写0
  if (!WriteStringToFile("0", DEVICE_SUB_CLASS_PATH)) return Status::ERROR;

    // 往/config/usb_gadget/g1/bDeviceProtocol 写0
  if (!WriteStringToFile("0", DEVICE_PROTOCOL_PATH)) return Status::ERROR;

    // 往/config/usb_gadget/g1/os_desc/use 写0
  if (!WriteStringToFile("0", DESC_USE_PATH)) return Status::ERROR;

    // /config/usb_gadget/g1/os_desc/use/configs/b.1/ 目录下的所有
  if (unlinkFunctions(CONFIG_PATH)) return Status::ERROR;

  if (mMonitorCreated) {
    uint64_t flag = 100;
    unsigned long ret;

    // Stop the monitor thread by writing into signal fd.
      // 停止monitor
    ret = TEMP_FAILURE_RETRY(write(mEventFd, &flag, sizeof(flag)));
    if (ret < 0) {
        ALOGE("Error writing errno=%d", errno);
    } else if (ret < sizeof(flag)) {
        ALOGE("Short write length=%zd", ret);
    }

    ALOGI("mMonitor signalled to exit");
    mMonitor->join();
    mMonitorCreated = false;
    ALOGI("mMonitor destroyed");
  } else {
    ALOGI("mMonitor not running");
  }

  mInotifyFd.reset(-1);
  mEventFd.reset(-1);
  mEpollFd.reset(-1);
  mEndpointList.clear();
  return Status::SUCCESS;
}
1. unlinkFunctions
static int unlinkFunctions(const char *path) {
  DIR *config = opendir(path);
  struct dirent *function;
  char filepath[MAX_FILE_PATH_LENGTH];
  int ret = 0;

  if (config == NULL) return -1;

  // d_type does not seems to be supported in /config
  // so filtering by name.
  while (((function = readdir(config)) != NULL)) {
      // 选择/config/usb_gadget/g1/configs/b.1/function进行删除,FUNCTION_NAME为function
      // 和function匹配的
    if ((strstr(function->d_name, FUNCTION_NAME) == NULL)) continue;
    // build the path for each file in the folder.
    sprintf(filepath, "%s/%s", path, function->d_name);
    ret = remove(filepath);
    if (ret) {
      ALOGE("Unable  remove file %s errno:%d", filepath, errno);
      break;
    }
  }

  closedir(config);
  return ret;
}
2. validateAndSetVidPid
static V1_0::Status validateAndSetVidPid(uint64_t functions) {
  V1_0::Status ret = Status::SUCCESS;
  std::string vendorFunctions = getVendorFunctions();

  switch (functions) {
          // 如果是mtp的话
    case static_cast<uint64_t>(GadgetFunction::MTP):
      if (vendorFunctions == "diag") {
        ret = setVidPid("0x05C6", "0x901B");
      } else {
          if (!(vendorFunctions == "user" || vendorFunctions == "")) {
              ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
              ret = Status::CONFIGURATION_NOT_SUPPORTED;
          } else {
              // 设置idVendor和idProduct
              ret = setVidPid("0x1f3a", "0x1006");
          }
      }
      break;
    case GadgetFunction::ADB | GadgetFunction::MTP:
      if (vendorFunctions == "diag") {
        ret = setVidPid("0x05C6", "0x903A");
      } else {
          if (!(vendorFunctions == "user" || vendorFunctions == "")) {
              ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
              ret = Status::CONFIGURATION_NOT_SUPPORTED;
          } else {
              ret = setVidPid("0x1f3a", "0x1007");
          }
      }
      break;
    case static_cast<uint64_t>(GadgetFunction::RNDIS):
      if (vendorFunctions == "diag") {
        ret = setVidPid("0x05C6", "0x902C");
      } else if (vendorFunctions == "serial_cdev,diag") {
        ret = setVidPid("0x05C6", "0x90B5");
      } else {
          if (!(vendorFunctions == "user" || vendorFunctions == "")) {
              ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
              ret = Status::CONFIGURATION_NOT_SUPPORTED;
          } else {
              ret = setVidPid("0x1f3a", "0x100a");
          }
      }
      break;
    case GadgetFunction::ADB | GadgetFunction::RNDIS:
      if (vendorFunctions == "diag") {
        ret = setVidPid("0x05C6", "0x902D");
      } else if (vendorFunctions == "serial_cdev,diag") {
        ret = setVidPid("0x05C6", "0x90B6");
      } else {
          if (!(vendorFunctions == "user" || vendorFunctions == "")) {
              ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
              ret = Status::CONFIGURATION_NOT_SUPPORTED;
          } else {
              ret = setVidPid("0x1f3a", "0x100b");
          }
      }
      break;
    case static_cast<uint64_t>(GadgetFunction::PTP):
        if (!(vendorFunctions == "user" || vendorFunctions == "")) {
            ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
            ret = Status::CONFIGURATION_NOT_SUPPORTED;
        } else {
            ret = setVidPid("0x1f3a", "0x1008");
        }
        break;
    case GadgetFunction::ADB | GadgetFunction::PTP:
        if (!(vendorFunctions == "user" || vendorFunctions == "")) {
            ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
            ret = Status::CONFIGURATION_NOT_SUPPORTED;
        } else {
            ret = setVidPid("0x1f3a", "0x1009");
        }
        break;
    case static_cast<uint64_t>(GadgetFunction::ADB):
      if (vendorFunctions == "diag") {
        ret = setVidPid("0x05C6", "0x901D");
      } else if (vendorFunctions == "diag,serial_cdev,rmnet_gsi") {
        ret = setVidPid("0x05C6", "0x9091");
      } else if (vendorFunctions == "diag,serial_cdev") {
        ret = setVidPid("0x05C6", "0x901F");
      } else {
          if (!(vendorFunctions == "user" || vendorFunctions == "")) {
              ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
              ret = Status::CONFIGURATION_NOT_SUPPORTED;
          } else {
              ret = setVidPid("0x1f3a", "0x1001");
          }
      }
      break;
    case static_cast<uint64_t>(GadgetFunction::MIDI):
        if (!(vendorFunctions == "user" || vendorFunctions == "")) {
            ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
            ret = Status::CONFIGURATION_NOT_SUPPORTED;
        } else {
            ret = setVidPid("0x1f3a", "0x4ee8");
        }
        break;
    case GadgetFunction::ADB | GadgetFunction::MIDI:
        if (!(vendorFunctions == "user" || vendorFunctions == "")) {
            ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
            ret = Status::CONFIGURATION_NOT_SUPPORTED;
        } else {
            ret = setVidPid("0x1f3a", "0x4ee9");
        }
        break;
    case static_cast<uint64_t>(GadgetFunction::ACCESSORY):
      if (!(vendorFunctions == "user" || vendorFunctions == ""))
        ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
      ret = setVidPid("0x18d1", "0x2d00");
      break;
    case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
      if (!(vendorFunctions == "user" || vendorFunctions == ""))
        ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
      ret = setVidPid("0x18d1", "0x2d01");
      break;
    case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE):
      if (!(vendorFunctions == "user" || vendorFunctions == ""))
        ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
      ret = setVidPid("0x1f3a", "0x2d02");
      break;
    case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
      if (!(vendorFunctions == "user" || vendorFunctions == ""))
        ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
      ret = setVidPid("0x1f3a", "0x2d03");
      break;
    case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
      if (!(vendorFunctions == "user" || vendorFunctions == ""))
        ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
      ret = setVidPid("0x18d1", "0x2d04");
      break;
    case GadgetFunction::ADB | GadgetFunction::ACCESSORY |
         GadgetFunction::AUDIO_SOURCE:
      if (!(vendorFunctions == "user" || vendorFunctions == ""))
        ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
      ret = setVidPid("0x18d1", "0x2d05");
      break;
    default:
      ALOGE("Combination not supported");
      ret = Status::CONFIGURATION_NOT_SUPPORTED;
  }
  return ret;
}
1. setVidPid
static V1_0::Status setVidPid(const char *vid, const char *pid) {
    // 往/config/usb_gadget/g1/idVendor 写
    // 这个idVendor是固定的,为0x1f3a
  if (!WriteStringToFile(vid, VENDOR_ID_PATH)) return Status::ERROR;
	// 往/config/usb_gadget/g1/idProduct 写
  if (!WriteStringToFile(pid, PRODUCT_ID_PATH)) return Status::ERROR;

  return Status::SUCCESS;
}
3. setupFunctions
// 设置adb的function的操作,和rc文件中是对应的
V1_0::Status UsbGadget::setupAdbFunction(bool *ffsEnabled, int inotifyFd, int i)
{
  *ffsEnabled = true;
  ALOGI("setCurrentUsbFunctions Adb");
  if (!WriteStringToFile("1", DESC_USE_PATH))
    return Status::ERROR;
  if (inotify_add_watch(inotifyFd, "/dev/usb-ffs/adb/", IN_ALL_EVENTS) == -1)
    return Status::ERROR;

  if (linkFunction("ffs.adb", i)) return Status::ERROR;
  mEndpointList.push_back("/dev/usb-ffs/adb/ep1");
  mEndpointList.push_back("/dev/usb-ffs/adb/ep2");
  ALOGI("Service started");
  return Status::SUCCESS;
}
// 设置mtp的function的操作,和rc文件中是对应的
V1_0::Status UsbGadget::setupMtpFunction(bool *ffsEnabled, int inotifyFd, int i)
{
  *ffsEnabled = true;
  ALOGI("setCurrentUsbFunctions mtp");
  if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR;

  if (inotify_add_watch(inotifyFd, "/dev/usb-ffs/mtp/", IN_ALL_EVENTS) == -1)
    return Status::ERROR;

  if (linkFunction("ffs.mtp", i)) return Status::ERROR;

  // Add endpoints to be monitored.
  mEndpointList.push_back("/dev/usb-ffs/mtp/ep1");
  mEndpointList.push_back("/dev/usb-ffs/mtp/ep2");
  mEndpointList.push_back("/dev/usb-ffs/mtp/ep3");
  return Status::SUCCESS;
}

// 设置ptp的function的操作,和rc文件中是对应的
V1_0::Status UsbGadget::setupPtpFunction(bool *ffsEnabled, int inotifyFd, int i)
{
  *ffsEnabled = true;
  ALOGI("setCurrentUsbFunctions ptp");
  if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR;

  if (inotify_add_watch(inotifyFd, "/dev/usb-ffs/ptp/", IN_ALL_EVENTS) == -1)
    return Status::ERROR;

  if (linkFunction("ffs.ptp", i)) return Status::ERROR;

  // Add endpoints to be monitored.
  mEndpointList.push_back("/dev/usb-ffs/ptp/ep1");
  mEndpointList.push_back("/dev/usb-ffs/ptp/ep2");
  mEndpointList.push_back("/dev/usb-ffs/ptp/ep3");
  return Status::SUCCESS;
}

V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
  const sp<V1_0::IUsbGadgetCallback> &callback, uint64_t timeout)  {
  std::unique_lock<std::mutex> lk(mLock);

  unique_fd inotifyFd(inotify_init());
  if (inotifyFd < 0) {
    ALOGE("inotify init failed");
    return Status::ERROR;
  }

  bool ffsEnabled = false;
// 对于每一种组合,都进行设置function操作
  switch (functions) {
    case static_cast<uint64_t>(GadgetFunction::MTP):
      if (setupMtpFunction(&ffsEnabled, inotifyFd, 0) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::MTP:
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 0) != Status::SUCCESS)
        return Status::ERROR;
      if (setupMtpFunction(&ffsEnabled, inotifyFd, 1) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case static_cast<uint64_t>(GadgetFunction::RNDIS):
      ALOGI("setCurrentUsbFunctions rndis");
      if (linkFunction("rndis.gs4", 0)) return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::RNDIS:
      ALOGI("setCurrentUsbFunctions rndis");
      if (linkFunction("rndis.gs4", 1)) return Status::ERROR;
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 0) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case static_cast<uint64_t>(GadgetFunction::PTP):
      if (setupPtpFunction(&ffsEnabled, inotifyFd, 0) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::PTP:
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 0) != Status::SUCCESS)
        return Status::ERROR;
      if (setupPtpFunction(&ffsEnabled, inotifyFd, 1) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case static_cast<uint64_t>(GadgetFunction::ADB):
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 0) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case static_cast<uint64_t>(GadgetFunction::MIDI):
      ALOGI("setCurrentUsbFunctions MIDI");
      if (linkFunction("midi.gs5", 0)) return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::MIDI:
      ALOGI("setCurrentUsbFunctions MIDI");
      if (linkFunction("midi.gs5", 0)) return Status::ERROR;
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 1) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case static_cast<uint64_t>(GadgetFunction::ACCESSORY):
      ALOGI("setCurrentUsbFunctions Accessory");
      if (linkFunction("accessory.gs2", 0)) return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
      ALOGI("setCurrentUsbFunctions Accessory");
      if (linkFunction("accessory.gs2", 0)) return Status::ERROR;
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 1) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE):
      ALOGI("setCurrentUsbFunctions Audio Source");
      if (linkFunction("audio_source.gs3", 0)) return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
      ALOGI("setCurrentUsbFunctions Audio Source");
      if (linkFunction("audio_source.gs3", 0)) return Status::ERROR;
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 1) != Status::SUCCESS)
        return Status::ERROR;
      break;
    case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
      ALOGI("setCurrentUsbFunctions Accessory");
      if (linkFunction("accessory.gs2", 0)) return Status::ERROR;
      ALOGI("setCurrentUsbFunctions Audio Source");
      if (linkFunction("audio_source.gs3", 1)) return Status::ERROR;
      break;
    case GadgetFunction::ADB | GadgetFunction::ACCESSORY |
         GadgetFunction::AUDIO_SOURCE:
      ALOGI("setCurrentUsbFunctions Accessory");
      if (linkFunction("accessory.gs2", 0)) return Status::ERROR;
      ALOGI("setCurrentUsbFunctions Audio Source");
      if (linkFunction("audio_source.gs3", 1)) return Status::ERROR;
      if (setupAdbFunction(&ffsEnabled, inotifyFd, 2) != Status::SUCCESS)
        return Status::ERROR;
      break;
    default:
      ALOGE("Combination not supported");
      return Status::CONFIGURATION_NOT_SUPPORTED;
  }


  std::string vendorFunctions = getVendorFunctions();
  if (vendorFunctions != "") {
    ALOGI("enable usbradio debug functions");
    char *function = strtok(const_cast<char *>(vendorFunctions.c_str()), ",");
    while (function != NULL) {
      if (string(function) == "diag" && linkFunction("diag.diag", 0))
        return Status::ERROR;
      if (string(function) == "serial_cdev" && linkFunction("cser.dun.0", 0))
        return Status::ERROR;
      if (string(function) == "rmnet_gsi" && linkFunction("gsi.rmnet", 0))
        return Status::ERROR;
      function = strtok(NULL, ",");
    }
  }

  // Pull up the gadget right away when there are no ffs functions.
  if (!ffsEnabled) {
    if (!WriteStringToFile(GADGET_NAME, PULLUP_PATH)) return Status::ERROR;
    mCurrentUsbFunctionsApplied = true;
    if (callback)
      callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
    return Status::SUCCESS;
  }

  unique_fd eventFd(eventfd(0, 0));
  if (eventFd == -1) {
    ALOGE("mEventFd failed to create %d", errno);
    return Status::ERROR;
  }

  unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
  if (epollFd == -1) {
    ALOGE("mEpollFd failed to create %d", errno);
    return Status::ERROR;
  }

  if (addEpollFd(epollFd, inotifyFd) == -1) return Status::ERROR;

  if (addEpollFd(epollFd, eventFd) == -1) return Status::ERROR;

  mEpollFd = move(epollFd);
  mInotifyFd = move(inotifyFd);
  mEventFd = move(eventFd);
  gadgetPullup = false;

  // Monitors the ffs paths to pull up the gadget when descriptors are written.
  // Also takes of the pulling up the gadget again if the userspace process
  // dies and restarts.
  mMonitor = unique_ptr<thread>(new thread(monitorFfs, this));
  mMonitorCreated = true;
  if (DEBUG) ALOGI("Mainthread in Cv");

  if (callback) {
    if (mCv.wait_for(lk, timeout * 1ms, [] { return gadgetPullup; })) {
      ALOGI("monitorFfs signalled true");
    } else {
      ALOGI("monitorFfs signalled error");
      // continue monitoring as the descriptors might be written at a later
      // point.
    }
    Return<void> ret = callback->setCurrentUsbFunctionsCb(
        functions, gadgetPullup ? Status::SUCCESS : Status::ERROR);
    if (!ret.isOk())
      ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str());
  }

  return Status::SUCCESS;
}

配置

Android R的rc文件配置

  1. 由于Android R使用了Linux 5.4的新内核,然后使用了新的usb驱动,adb和mtp所对应的f1和f2和Android Q对应的反了。
注意:
在Android R中需要先symlink adb为f1,然后symlink mtp为f2,这样的顺序下,mtp才能正常工作
write /config/usb_gadget/g1/os_desc/use 1是为了过CTS测试,CTS测试会判断该值是否为1的

diff --git a/init.sun50iw10p1.usb.rc b/init.sun50iw10p1.usb.rc
index 9c142fd..1e65b62 100644
--- a/init.sun50iw10p1.usb.rc
+++ b/init.sun50iw10p1.usb.rc
@@ -46,13 +46,19 @@ on property:sys.usb.config=mtp && property:sys.usb.configfs=1
 on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x1007
     write /config/usb_gadget/g1/os_desc/use 1
-    symlink /config/usb_gadget/g1/functions/ffs.mtp /config/usb_gadget/g1/configs/b.1/f1
+    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
+    symlink /config/usb_gadget/g1/functions/ffs.mtp /config/usb_gadget/g1/configs/b.1/f2

 on property:sys.usb.config=rndis && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x100a
+    write /config/usb_gadget/g1/os_desc/use 1
+    symlink /config/usb_gadget/g1/functions/ffs.rndis /config/usb_gadget/g1/configs/b.1/f1

 on property:sys.usb.ffs.ready=1 && property:sys.usb.config=rndis,adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x100b
+    write /config/usb_gadget/g1/os_desc/use 1
+    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
+    symlink /config/usb_gadget/g1/functions/ffs.rndis /config/usb_gadget/g1/configs/b.1/f2

 on property:sys.usb.config=ptp && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x1008
@@ -62,10 +68,12 @@ on property:sys.usb.config=ptp && property:sys.usb.configfs=1
 on property:sys.usb.ffs.ready=1 && property:sys.usb.config=ptp,adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x1009
     write /config/usb_gadget/g1/os_desc/use 1
-    symlink /config/usb_gadget/g1/functions/ffs.ptp /config/usb_gadget/g1/configs/b.1/f1
+    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
+    symlink /config/usb_gadget/g1/functions/ffs.ptp /config/usb_gadget/g1/configs/b.1/f2

 on property:sys.usb.config=adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x1001
+    write /config/usb_gadget/g1/os_desc/use 1

 on property:sys.usb.config=midi && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x4ee8

mk文件中

# 在device/softwinner/ceres/common/misc/config.mk中添加:
PRODUCT_PACKAGES += \
	android.hardware.usb@1.0-service.aw

问题记录

1. cts-verify的usb accessory和usb device测试 fail项

debug手段:打开frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java文件中的DEBUG选项

  1. usb主机端会发送消息给usb客户端
  2. usb客户端接收到消息之后,会触发一个uevent
UsbDeviceManager: USB UEVENT: {SUBSYSTEM=misc, MAJOR=10, SEQNUMQ=26593, ACTION=change, ACCESSORY=START, DEVNAME=usb_accessory, MINOR=50,DEVPATH=/devices/virtual/misc/usb_accessory}
  1. 处理接收到的uevent
frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
	private final class UsbUEventObserver extends UEventObserver {
        @Override
        public void onUEvent(UEventObserver.UEvent event) {
            if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());

            String state = event.get("USB_STATE");
            String accessory = event.get("ACCESSORY");
            if (state != null) {
                mHandler.updateState(state);
            } else if ("START".equals(accessory)) {
                if (DEBUG) Slog.d(TAG, "got accessory start");
                startAccessoryMode();
            }
        }
    }
  1. 启动accessory模式
frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
	private void startAccessoryMode() {
        if (!mHasUsbAccessory) return;

		// 底层通过ioctl获取信息
        mAccessoryStrings = nativeGetAccessoryStrings();
        boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
        // don't start accessory mode if our mandatory strings have not been set
        // 启动accessory模式的条件,就是因为mAccessoryStrings字符串为null,导致无法启动accessory模式
        boolean enableAccessory = (mAccessoryStrings != null &&
                mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
                mAccessoryStrings[UsbAccessory.MODEL_STRING] != null);

        long functions = UsbManager.FUNCTION_NONE;
        if (enableAccessory) {
            functions |= UsbManager.FUNCTION_ACCESSORY;
        }
        if (enableAudio) {
            functions |= UsbManager.FUNCTION_AUDIO_SOURCE;
        }

        if (functions != UsbManager.FUNCTION_NONE) {
            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT),
                    ACCESSORY_REQUEST_TIMEOUT);
            setCurrentFunctions(functions);
        }
    }
  1. 获取字符串信息
frameworks/base/services/core/jni/com_android_server_UsbDeviceManager.cpp
static jobjectArray android_server_UsbDeviceManager_getAccessoryStrings(JNIEnv *env,
                                                                        jobject /* thiz */)
{
    int fd = open(DRIVER_NAME, O_RDWR);
    if (fd < 0) {
        ALOGE("could not open %s", DRIVER_NAME);
        return NULL;
    }
    jclass stringClass = env->FindClass("java/lang/String");
    jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL);
    if (!strArray) goto out;
    // 通过ioctl系统调用来获取信息,由于我们是32位的android,而/dev/usb_accessory设备不支持32位的ioctl,所以获取信息失败了。
    set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0);
    set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1);
    set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2);
    set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3);
    set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4);
    set_accessory_string(env, fd, ACCESSORY_GET_STRING_SERIAL, strArray, 5);

out:
    close(fd);
    return strArray;
}
  1. 补丁:内核usb_accessory驱动支持32位的ioctl
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c
index 7aa2656a2328..af8f8c264295 100644
--- a/drivers/usb/gadget/function/f_accessory.c
+++ b/drivers/usb/gadget/function/f_accessory.c
@@ -41,6 +41,9 @@

 #include <linux/configfs.h>
 #include <linux/usb/composite.h>
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif

 #define MAX_INST_NAME_LEN        40
 #define BULK_BUFFER_SIZE    16384
@@ -750,6 +753,14 @@ static long acc_ioctl(struct file *fp, unsigned code, unsigned long value)
        return ret;
 }

+#ifdef CONFIG_COMPAT
+static long acc_compat_ioctl(struct file *fp, unsigned code,
+                               unsigned long value)
+{
+       return acc_ioctl(fp, code, (unsigned long) compat_ptr(value));
+}
+#endif
+
 static int acc_open(struct inode *ip, struct file *fp)
 {
        printk(KERN_INFO "acc_open\n");
@@ -779,6 +790,9 @@ static const struct file_operations acc_fops = {
        .read = acc_read,
        .write = acc_write,
        .unlocked_ioctl = acc_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = acc_compat_ioctl,
+#endif
        .open = acc_open,
        .release = acc_release,
 };
  1. 修改idVendor为Google的
diff --git a/init.sun50iw10p1.usb.rc b/init.sun50iw10p1.usb.rc
index 042f14b..ec84960 100644
--- a/init.sun50iw10p1.usb.rc
+++ b/init.sun50iw10p1.usb.rc
@@ -85,9 +85,11 @@ on property:sys.usb.config=midi,adb && property:sys.usb.configfs=1

 on property:sys.usb.config=accessory && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x2d00
+    write /config/usb_gadget/g1/idVendor 0x18d1

 on property:sys.usb.config=accessory,adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x2d01
+    write /config/usb_gadget/g1/idVendor 0x18d1

 on property:sys.usb.config=audio_source && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x2d02
@@ -97,9 +99,11 @@ on property:sys.usb.config=audio_source,adb && property:sys.usb.configfs=1

 on property:sys.usb.config=accessory,audio_source && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x2d04
+    write /config/usb_gadget/g1/idVendor 0x18d1

 on property:sys.usb.config=accessory,audio_source,adb && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x2d05
+    write /config/usb_gadget/g1/idVendor 0x18d1


 on property:persist.sys.usb0device=1

2. 支持usb网络共享功能

  1. rc文件没有配置好导致的;测试:手机插入Linux电脑,Linux电脑就可以上网了
diff --git a/init.sun50iw10p1.usb.rc b/init.sun50iw10p1.usb.rc
index 1e65b62..042f14b 100644
--- a/init.sun50iw10p1.usb.rc
+++ b/init.sun50iw10p1.usb.rc
@@ -50,15 +50,17 @@ on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb && property:s
     symlink /config/usb_gadget/g1/functions/ffs.mtp /config/usb_gadget/g1/configs/b.1/f2

 on property:sys.usb.config=rndis && property:sys.usb.configfs=1
+    mkdir /config/usb_gadget/g1/functions/rndis.gs4
     write /config/usb_gadget/g1/idProduct 0x100a
     write /config/usb_gadget/g1/os_desc/use 1
-    symlink /config/usb_gadget/g1/functions/ffs.rndis /config/usb_gadget/g1/configs/b.1/f1
+    symlink /config/usb_gadget/g1/functions/rndis.gs4 /config/usb_gadget/g1/configs/b.1/f1

 on property:sys.usb.ffs.ready=1 && property:sys.usb.config=rndis,adb && property:sys.usb.configfs=1
+    mkdir /config/usb_gadget/g1/functions/rndis.gs4
     write /config/usb_gadget/g1/idProduct 0x100b
     write /config/usb_gadget/g1/os_desc/use 1
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
-    symlink /config/usb_gadget/g1/functions/ffs.rndis /config/usb_gadget/g1/configs/b.1/f2
+    symlink /config/usb_gadget/g1/functions/rndis.gs4 /config/usb_gadget/g1/configs/b.1/f2

 on property:sys.usb.config=ptp && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x1008

3. MTP切换之后又跳转回来的问题

  1. 设置sys.usb.config属性为none之后,会收到一个DISCONNECTED的UEVENT:android_work: sent uevent USB_STATE=DISCONNECTED
    /*
     * Listens for uevent messages from the kernel to monitor the USB state
     */
    private final class UsbUEventObserver extends UEventObserver {
        @Override
        public void onUEvent(UEventObserver.UEvent event) {
            if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());

            String state = event.get("USB_STATE");
            String accessory = event.get("ACCESSORY");
            if (state != null) {
                // 会调用updateState来更新状态
                mHandler.updateState(state);
            } else if ("START".equals(accessory)) {
                if (DEBUG) Slog.d(TAG, "got accessory start");
                startAccessoryMode();
            }
        }
    }
  1. 调用updateState函数更新状态
        public void updateState(String state) {
            int connected, configured;

            if ("DISCONNECTED".equals(state)) {
                connected = 0;
                configured = 0;
            } else if ("CONNECTED".equals(state)) {
                connected = 1;
                configured = 0;
            } else if ("CONFIGURED".equals(state)) {
                connected = 1;
                configured = 1;
            } else {
                Slog.e(TAG, "unknown state " + state);
                return;
            }
            // 如果1s之内,状态发生变化了,则会remove掉MSG_UPDATE_STATE消息。
            removeMessages(MSG_UPDATE_STATE);
            // 如果为connected,则会remove掉MSG_FUNCTION_SWITCH_TIMEOUT消息
            if (connected == 1) removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT);
            Message msg = Message.obtain(this, MSG_UPDATE_STATE);
            msg.arg1 = connected;
            msg.arg2 = configured;
            // debounce disconnects to avoid problems bringing up USB tethering
            // 对于DISCONNECTED状态,会在这里发送一个延迟时间为1s的msg。
            sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
        }
  1. MSG_UPDATE_STATE消息更新
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_STATE:
                    mConnected = (msg.arg1 == 1);
                    mConfigured = (msg.arg2 == 1);

                    updateUsbNotification(false);
                    updateAdbNotification(false);
                    if (mBootCompleted) {
                        // 对于连上的情况,则发送连上usb的广播
                        updateUsbStateBroadcastIfNeeded(getAppliedFunctions(mCurrentFunctions));
                    }
                    if ((mCurrentFunctions & UsbManager.FUNCTION_ACCESSORY) != 0) {
                        updateCurrentAccessory();
                    }
                    if (mBootCompleted) {
                        if (!mConnected && !hasMessages(MSG_ACCESSORY_MODE_ENTER_TIMEOUT)
                                && !hasMessages(MSG_FUNCTION_SWITCH_TIMEOUT)) {
                            // restore defaults when USB is disconnected
                            if (!mScreenLocked
                                    && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
                                setScreenUnlockedFunctions();
                            } else {
                                // 如果没有remove掉MSG_UPDATE_STATE消息的话,在这里就会设置function为none,然后界面就会跳转回原来的位置
                                setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
                            }
                        }
                        updateUsbFunctions();
                    } else {
                        mPendingBootBroadcast = true;
                    }
  1. 解决办法:如果因为系统很卡,而无法及时跳转的话,可以加大延迟的时间,将private static final int UPDATE_DELAY = 1000;设置为2000或3000

4. usb网络共享功能,win10驱动装不上

调节下adb和rndis的链接顺序,rndis在前,adb在后

diff --git a/common/system/init.sun50iw10p1.usb.rc b/common/system/init.sun50iw10p1.usb.rc
index ec84960..fe50181 100644
--- a/common/system/init.sun50iw10p1.usb.rc
+++ b/common/system/init.sun50iw10p1.usb.rc
@@ -59,8 +59,8 @@ on property:sys.usb.ffs.ready=1 && property:sys.usb.config=rndis,adb && property
     mkdir /config/usb_gadget/g1/functions/rndis.gs4
     write /config/usb_gadget/g1/idProduct 0x100b
     write /config/usb_gadget/g1/os_desc/use 1
-    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
     symlink /config/usb_gadget/g1/functions/rndis.gs4 /config/usb_gadget/g1/configs/b.1/f2
+    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
 
 on property:sys.usb.config=ptp && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0x1008
posted @ 2021-04-20 21:53  pyjetson  阅读(2440)  评论(0)    收藏  举报