插拔USB设备后HarmonyOS 鸿蒙Next usb_host服务必进死循环

发布于 1周前 作者 phonegap100 来自 鸿蒙OS

插拔USB设备后HarmonyOS 鸿蒙Next usb_host服务必进死循环 OHM 4.1.7.3、使用USBDDK、dayu开发板与其它多款投产的OHM设备上,我们测试出如下必现问题:

  1. 先后打开两个USB设备(不同种类的设备),然后拔除先打开的设备,就再也不能打开新USB设备了;
  2. 插拔最后打开的USB设备不会有问题;
  3. 交换两个设备所接USB口、交换打开顺序,仍必现;
  4. 当前发现是usb_host服务进死循环了,导致新打开操作卡在OH_Usb_ClaimInterface调;
  5. 重启系统或手动重启usb_host该服务可以恢复;

最简示例,打开USB设备代码

#define LOG_TAG "tagUSBTest"
#include <usb/usb_ddk_types.h>
#include <usb/usb_ddk_api.h>
#define GET_DEV_HANDLE(busNum, devID) ((uint64_t)busNum << 32 | devID & 0xFFFFFFFF)
static int g_initUSBDDK = -1;
static uint64_t openDevice(int iBus, int iDev) {
    if (g_initUSBDDK < 0) {
        g_initUSBDDK = OH_Usb_Init();
    }
    uint64_t l_uTemp = GET_DEV_HANDLE(iBus, iDev);

    struct UsbDeviceDescriptor l_desc = {};
    int l_iRet = OH_Usb_GetDeviceDescriptor(l_uTemp, &l_desc);
    OH_LOG_INFO("Found usb-%d-%d:vid_%4x&pid_%4x", iBus, iDev, l_desc.idVendor, l_desc.idProduct);

    uint64_t l_hInterface = 0;
    if (0 == l_iRet) {
        l_iRet = OH_Usb_ClaimInterface(l_uTemp, 0, &l_hInterface);
        OH_LOG_INFO("Open usb-%d-%d = %d", iBus, iDev, l_iRet);
    }
    return l_hInterface;
}

static napi_value OpenDeviceA(napi_env env, napi_callback_info info) {
    napi_value l_result;
    uint64_t l_h = openDevice(4, 2);
    napi_create_int64(env, l_h, &l_result);
    return l_result;
}

static napi_value OpenDeviceB(napi_env env, napi_callback_info info) {
    napi_value l_result;
    uint64_t l_h = openDevice(5, 2);
    napi_create_int64(env, l_h, &l_result);
    return l_result;
}

触发故障后,usb_host会在Hilog中不停打印 “IoAsyncReceiveProcess RawHandleRequest failed ret: -202”

追查代码发现 usb_io_manage.c文件中的IoAsyncReceiveProcess 调用对错误码-202的处理会形成死循环调用

调用链为IoAsyncReceiveProcess -->usb_raw_api_library.c:RawHandleRequest–>linux_adapter.c:AdapterUrbCompleteHandle 返回 -202

usb_io_manage.c:

static int32_t IoAsyncReceiveProcess(const void *interfacePoolArg)
{
    if (interfacePoolArg == NULL) {
        HDF_LOGE("%s: invalid param", __func__);
        return HDF_ERR_INVALID_PARAM;
    }

    struct UsbInterfacePool *interfacePool = (struct UsbInterfacePool *)interfacePoolArg;
    if (RawRegisterSignal() != HDF_SUCCESS) {
        HDF_LOGE("%s:%d RawRegisterSignal error", __func__, __LINE__);
    }

    while (true) {
        if (!interfacePool->ioProcessTid) {
            interfacePool->ioProcessTid = RawGetTid();
        }

        if (interfacePool->device == NULL) {
            HDF_LOGE("%s:%d interfacePool->device is NULL!", __func__, __LINE__);
            OsalMSleep(USB_IO_SLEEP_MS_TIME);
            continue;
        }

        if (interfacePool->device->devHandle == NULL) {
            HDF_LOGE("%s:%d interfacePool->device->devHandle is NULL!", __func__, __LINE__);
            OsalMSleep(USB_IO_SLEEP_MS_TIME);
            continue;
        }

        if (interfacePool->ioProcessStopStatus != USB_POOL_PROCESS_RUNNING) {
            break;
        }

        int32_t ret = RawHandleRequest(interfacePool->device->devHandle);
        if (ret < 0) {
            HDF_LOGE("%s RawHandleRequest failed ret: %d", __func__, ret);
            OsalMSleep(USB_IO_SLEEP_MS_TIME);
            continue;  // 100ms 死循环
        }
    }

    OsalMutexLock(&interfacePool->ioStopLock);
    interfacePool->ioProcessStopStatus = USB_POOL_PROCESS_STOPED;
    OsalSemPost(&interfacePool->submitRequestQueue.sem);
    OsalMutexUnlock(&interfacePool->ioStopLock);

    return HDF_SUCCESS;
}

usb_raw_api_library.c:

int32_t RawHandleRequest(const struct UsbDeviceHandle *devHandle)
{
    struct UsbOsAdapterOps *osAdapterOps = UsbAdapterGetOps();
    int32_t ret;

    if (!osAdapterOps->urbCompleteHandle) {
        return HDF_ERR_NOT_SUPPORT;
    }

    ret = osAdapterOps->urbCompleteHandle(devHandle);
    if (ret < 0) {}

    return ret;
}

linux_adapter.c:

static int32_t AdapterUrbCompleteHandle(const struct UsbDeviceHandle *devHandle)
{
    struct UsbAdapterUrb *urb = NULL;
    struct UsbHostRequest *request = NULL;
    int32_t ret;

    if (devHandle == NULL) {
        HDF_LOGE("%s:%d invalid parameter", __func__, __LINE__);
        return HDF_ERR_INVALID_PARAM;
    }

    ret = ioctl(devHandle->fd, USBDEVFS_REAPURB, &urb);
    if (ret < 0) {
        if (errno == EAGAIN) {
            return 1;
        }
        if (errno == ENODEV) {
            return HDF_DEV_ERR_NO_DEVICE; // 这里返回了 -202
        }

        return HDF_ERR_IO;
    }
}

更多关于插拔USB设备后HarmonyOS 鸿蒙Next usb_host服务必进死循环的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

你好,这个问题下个版本将会修复哈

更多关于插拔USB设备后HarmonyOS 鸿蒙Next usb_host服务必进死循环的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


大佬,想问一下你有没有使用过OH_Usb_SendPipeRequest这个接口

正常的操作不插拔,是可以通讯的,当然要用到 OH_Usb_SendPipeRequest

以上内容没有图片,因此不添加图片。

那你有没有碰到返回-18的情况,我每次执行后都是这个结果,

我是按照这个文档做的[1],USB设备只有中断传输模式,

该问题已反馈研发人员进一步分析,请耐心等待!

针对帖子标题中提到的问题“插拔USB设备后HarmonyOS 鸿蒙Next usb_host服务必进死循环”,以下是可能的解答:

在HarmonyOS鸿蒙Next系统中,若插拔USB设备导致usb_host服务进入死循环,这通常与系统的USB驱动或相关服务处理逻辑存在缺陷有关。可能的原因包括但不限于:

  1. USB驱动异常:插拔USB设备时,如果系统未能正确处理USB驱动的状态变化,可能会导致服务陷入死循环。

  2. 服务处理逻辑错误:usb_host服务在处理USB插拔事件时,可能存在逻辑上的错误,导致服务无法正确恢复或重置状态。

  3. 系统资源冲突:插拔USB设备可能引发系统资源(如内存、进程等)的冲突或泄漏,进而影响usb_host服务的正常运行。

针对此问题,建议检查系统的USB驱动更新情况,以及是否有可用的系统补丁或更新来解决此问题。同时,也可以尝试重置系统或恢复出厂设置(注意备份数据),以查看问题是否依旧存在。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。他们将能够提供进一步的帮助和支持。

回到顶部