openharmony标准系统移植之适配hdc功能

本文记录了在OpenHarmony上HDC调试工具的适配过程,重点介绍了daemon目录的作用,以及HDCDaemon和HdcSessionBase的主要函数执行流程。通过代码片段展示了如何设置日志缓存和初始化USB功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

openharmony上有一个重要的调试工具HDC,作为移植上的一点现进行一点适配记录。我们设备端主要运行的代码路径为developtools/hdc_standard/src/daemon,为啥是这个目录见下图,官方给的说明。
在这里插入图片描述
所以能很轻松的找到函数入口,入口为developtools/hdc_standard/src/daemon/main.cpp文件里面的main函数,接下来就是分析执行流程。

展示的是去掉了相关判断的部分代码,并不是完整代码
void SetLogCache(bool enable){g_logCache = enable;}

int main(int argc, const char *argv[])
{
	Hdc::Base::SetLogCache(false); //设置 g_logCache = false;
    Hdc::Base::RemoveLogFile(); //因为g_logCache  = false,所以不执行任何操作
    ForkChildCheck(argc, argv); //设置 g_enableUsb = true;g_enableUart = true;
    NeedDropPriv();
    umask(0);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGALRM, SIG_IGN);
    WRITE_LOG(LOG_DEBUG, "HdcDaemon main run");
    HdcDaemon daemon(false); //执行函数 HdcDaemon::HdcDaemon 和 HdcSessionBase::HdcSessionBase

    daemon.InitMod(g_enableTcp, g_enableUsb, g_enableUart); //执行  HdcDaemon::InitMod(0,1,1)
    daemon.WorkerPendding(); //执行 HdcSessionBase::WorkerPendding,这里因为运行了loop循环,s所以下面的无法执行,所以不做分析
    return 0;
}

HdcDaemon::HdcDaemon(bool serverOrDaemonIn)
    : HdcSessionBase(serverOrDaemonIn)
{
    clsTCPServ = nullptr;
    clsUSBServ = nullptr;
    clsUARTServ = nullptr;
    clsJdwp = nullptr;
    enableSecure = false;
}
HdcSessionBase::HdcSessionBase(bool serverOrDaemonIn)
{
    // print version pid
    WRITE_LOG(LOG_INFO, "Program running. %s Pid:%u", Base::GetVersion().c_str(), getpid());
    // server/daemon common initialization code
    threadPoolCount = SIZE_THREAD_POOL;
    string uvThreadEnv("UV_THREADPOOL_SIZE");
    string uvThreadVal = std::to_string(threadPoolCount); 
    setenv(uvThreadEnv.c_str(), uvThreadVal.c_str(), 1); //用来改变或增加环境变量的内容 UV_THREADPOOL_SIZE = 16
    uv_loop_init(&loopMain);
    WRITE_LOG(LOG_DEBUG, "loopMain init");
    uv_rwlock_init(&mainAsync);
    uv_async_init(&loopMain, &asyncMainLoop, MainAsyncCallback);
    uv_rwlock_init(&lockMapSession);
    serverOrDaemon = false;
    ctxUSB = nullptr;
    wantRestart = false;
    threadSessionMain = uv_thread_self();
}
void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, [[maybe_unused]] bool bEnableUART)
{
    WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod");

    WRITE_LOG(LOG_DEBUG, "bEnableTCP:%d,bEnableUSB:%d", bEnableTCP, bEnableUSB);

    if (bEnableUSB) {
        // usb
        clsUSBServ = new(std::nothrow) HdcDaemonUSB(false, this); //执行HdcDaemonUSB::HdcDaemonUSB和 HdcUSBBase::HdcUSBBase函数
        if (clsUSBServ == nullptr) {
            WRITE_LOG(LOG_FATAL, "InitMod new clsUSBServ failed");
            return;
        }
        ((HdcDaemonUSB *)clsUSBServ)->Initial(); // 执行 HdcDaemonUSB::Initial函数
    }

    WRITE_LOG(LOG_DEBUG, "bEnableUART:%d", bEnableUART);
    if (bEnableUART) {
        // UART
        clsUARTServ = new(std::nothrow) HdcDaemonUART(*this);
        if (clsUARTServ == nullptr) {
            WRITE_LOG(LOG_FATAL, "InitMod new clsUARTServ failed");
            return;
        }
        ((HdcDaemonUART *)clsUARTServ)->Initial();
    }
    clsJdwp = new(std::nothrow) HdcJdwp(&loopMain);
    if (clsJdwp == nullptr) {
        WRITE_LOG(LOG_FATAL, "InitMod new clsJdwp failed");
        return;
    }
    ((HdcJdwp *)clsJdwp)->Initial();
    // enable security
    string secure;
    SystemDepend::GetDevItem("ro.hdc.secure", secure);
    enableSecure = (Base::Trim(secure) == "1");
}

void HdcSessionBase::WorkerPendding()
{
    uv_run(&loopMain, UV_RUN_DEFAULT);
    ClearInstanceResource();
}
int HdcDaemonUSB::Initial()
{
    // after Linux-3.8,kernel switch to the USB Function FS
    // Implement USB hdc function in user space
    WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB init");
    basePath = GetDevPath(USB_FFS_BASE); // constexpr auto USB_FFS_BASE = "/dev/usb-ffs/";
    if (access((basePath + "/ep0").c_str(), F_OK) != 0) {
        WRITE_LOG(LOG_DEBUG, "Only support usb-ffs, make sure kernel3.8+ and usb-ffs enabled, usbmode disabled");
        return ERR_API_FAIL;
    }
    ctxRecv.thisClass = this;
    ctxRecv.bufSizeMax = Base::GetUsbffsBulkSize();
    ctxRecv.buf = new uint8_t[ctxRecv.bufSizeMax]();
    if (!ctxRecv.buf) {
        WRITE_LOG(LOG_FATAL, "Init alloc memory failed");
        return ERR_BUF_ALLOC;
    }

    HdcDaemon *daemon = (HdcDaemon *)clsMainBase;
    WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB::Initiall");
    uv_timer_init(&daemon->loopMain, &checkEP); // 初始化一个定时器,初始化定时器句柄
    checkEP.data = this;
    uv_timer_start(&checkEP, WatchEPTimer, 0, 1000);  //constexpr uint16_t TIME_BASE = 1000;
    //设置定时器  checkEP: 定时器句柄;WatchEPTimer : 回调函数,定时时间到的时候会调用这个函数;0 : 在 uv_run() 之后多久启动定时器,单位是毫秒;TIME_BASE : 定时器循环定时的时间,也就是重复调用的时间,单位是毫秒
    return 0;
}

运行结果如下图,可以看到重复调用了WatchEPTimer这个函数
在这里插入图片描述
所以会一直执行如下函数去读取数据

nt HdcDaemonUSB::LoopUSBRead(HUSB hUSB, int readMaxWanted)
{
    int ret = ERR_GENERIC;
    HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(clsMainBase);
    uv_buf_t iov;
    ctxRecv.data = hUSB;
    ctxRecv.bufSize = readMaxWanted;
    ctxRecv.req = {};
    uv_fs_t *req = &ctxRecv.req;
    req->data = &ctxRecv;
    iov = uv_buf_init(reinterpret_cast<char *>(ctxRecv.buf), ctxRecv.bufSize);
    ret = uv_fs_read(&daemon->loopMain, req, hUSB->bulkOut, &iov, 1, -1, OnUSBRead);
    if (ret < 0) {
        WRITE_LOG(LOG_FATAL, "uv_fs_read < 0");
        return ERR_API_FAIL;
    }
    ctxRecv.atPollQueue = true;
    return RET_SUCCESS;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值