openharmony标准系统移植之适配hdc功能
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;}