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;
}