diff --git a/BUILD.gn b/BUILD.gn index 7d068efee3a73bfac29031f967e7517ed8227685..49ea8b16c1c4d175ec4416efa3928656cf70190f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -49,6 +49,7 @@ ohos_executable("hdcd") { "src/daemon/jdwp.cpp", "src/daemon/main.cpp", "src/daemon/shell.cpp", + "src/daemon/system_depend.cpp", ] sources += hdc_common_sources diff --git a/src/common/async_cmd.cpp b/src/common/async_cmd.cpp index 54d3a473c3344a49cbed417198cfc8a2a8f56e7b..6aca12399d28d430ec9957c90477ed1b52129ecc 100644 --- a/src/common/async_cmd.cpp +++ b/src/common/async_cmd.cpp @@ -56,7 +56,7 @@ void AsyncCmd::DoRelease() bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn) { #if defined _WIN32 || defined HDC_HOST - WRITE_LOG(LOG_FATAL, "Not support for win32-host"); + WRITE_LOG(LOG_FATAL, "Not support for win32 or host side"); return false; #endif loop = loopIn; diff --git a/src/common/async_cmd.h b/src/common/async_cmd.h index 86532585705ed281748cd89ac82c6de5cbbee5bf..403a09bdee2678d13dbf6d30522d49a39bd8c0d4 100644 --- a/src/common/async_cmd.h +++ b/src/common/async_cmd.h @@ -24,12 +24,12 @@ public: enum AsyncCmdOption { OPTION_COMMAND_ONETIME = 1, USB_OPTION_RESERVE2 = 2, - OPTION_READBACK_OUT = 4, // PS: Not used, remove it later + OPTION_READBACK_OUT = 4, // deprecated, remove it later USB_OPTION_RESERVE8 = 8, }; // 1)is finish 2)exitStatus 3)resultString(maybe empty) using CmdResultCallback = std::function; - // PS: Not used, remove it later + // deprecated, remove it later static uint32_t GetDefaultOption() { return OPTION_COMMAND_ONETIME; diff --git a/src/common/base.cpp b/src/common/base.cpp index 418ec87294efd3cf1defef97568daf191bb21ee0..85fa0f411a5f069234442d601072d6de3aff8518 100644 --- a/src/common/base.cpp +++ b/src/common/base.cpp @@ -23,16 +23,11 @@ #include #include #include -#ifdef __MUSL__ -extern "C" { -#include "parameter.h" -} -#endif using namespace std::chrono; namespace Hdc { namespace Base { - uint8_t g_logLevel = 0; + uint8_t g_logLevel = LOG_DEBUG; // tmp set,now debugmode.LOG_OFF when release;; void SetLogLevel(const uint8_t logLevel) { g_logLevel = logLevel; @@ -45,7 +40,7 @@ namespace Base { { string tmpString = GetFileNameAny(debugInfo); debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); - if (g_logLevel < LOG_ALL) { + if (g_logLevel < LOG_DEBUG) { debugInfo = ""; threadIdString = ""; } else { @@ -108,7 +103,7 @@ namespace Base { logLevelString = std::to_string(logLevel); } string msTimeSurplus; - if (g_logLevel > LOG_DEBUG) { + if (g_logLevel >= LOG_DEBUG) { const auto sSinceUnix0Rest = duration_cast(sinceUnix0).count() % (TIME_BASE * TIME_BASE); msTimeSurplus = StringFormat(".%06llu", sSinceUnix0Rest); } @@ -196,7 +191,7 @@ namespace Base { uv_tcp_keepalive(tcpHandle, 1, GLOBAL_TIMEOUT); // if MAX_SIZE_IOBUF==5k,bufMaxSize at least 40k. It must be set to io 8 times is more appropriate, // otherwise asynchronous IO is too fast, a lot of IO is wasted on IOloop, transmission speed will decrease - int bufMaxSize = GetMaxBufSize() * 10; + int bufMaxSize = HDC_SOCKETPAIR_SIZE; uv_recv_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); uv_send_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); } @@ -544,42 +539,6 @@ namespace Base { return bytesRead; } - bool SetHdcProperty(const char *key, const char *value) - { -#ifndef __MUSL__ -#ifdef HDC_PCDEBUG - WRITE_LOG(LOG_DEBUG, "Setproperty, key:%s value:%s", key, value); -#else - string sKey = key; - string sValue = value; - string sBuf = "setprop " + sKey + " " + value; - system(sBuf.c_str()); -#endif -#else - SetParameter(key, value); -#endif - return true; - } - - bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf) - { -#ifndef __MUSL__ -#ifdef HDC_PCDEBUG - WRITE_LOG(LOG_DEBUG, "Getproperty, key:%s value:%s", key, value); -#else - string sKey = key; - string sBuf = "getprop " + sKey; - RunPipeComand(sBuf.c_str(), value, sizeOutBuf, true); -#endif -#else - string sKey = key; - string sBuf = "param get " + sKey; - RunPipeComand(sBuf.c_str(), value, sizeOutBuf, true); -#endif - value[sizeOutBuf - 1] = '\0'; - return true; - } - // bufLen == 0: alloc buffer in heap, need free it later // >0: read max nBuffLen bytes to *buff // ret value: <0 or bytes read @@ -1197,16 +1156,6 @@ namespace Base { return ret; } - int open_osfhandle(uv_os_fd_t os_fd) - { - // equal libuv's uv_open_osfhandle, libuv 1.23 added. old libuv not impl... -#ifdef _WIN32 - return _open_osfhandle((intptr_t)os_fd, 0); -#else - return os_fd; -#endif - } - uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) { uv_os_sock_t dupFd = -1; @@ -1222,21 +1171,11 @@ namespace Base { if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { return ERR_API_FAIL; } - dupFd = dup(open_osfhandle(fdOs)); + dupFd = dup(uv_open_osfhandle(fdOs)); #endif return dupFd; } - vector Md5Sum(uint8_t *buf, int size) - { - vector ret; - uint8_t md5Hash[MD5_DIGEST_LENGTH] = { 0 }; - if (EVP_Digest(buf, size, md5Hash, NULL, EVP_md5(), NULL)) { - ret.insert(ret.begin(), md5Hash, md5Hash + sizeof(md5Hash)); - } - return ret; - } - string GetCwd() { char path[PATH_MAX] = ""; diff --git a/src/common/base.h b/src/common/base.h index 7c7a6854cacd0a166ab3359a07960fcb8dfd6207..d0e80d05bb23a70e9e1bf4eac7e1dd12f6432aa6 100644 --- a/src/common/base.h +++ b/src/common/base.h @@ -18,6 +18,7 @@ namespace Hdc { namespace Base { + extern uint8_t g_logLevel; void SetLogLevel(const uint8_t logLevel); void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...); void PrintMessage(const char *fmt, ...); @@ -49,9 +50,6 @@ namespace Base { void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack); void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack); char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex); - bool SetHdcProperty(const char *key, const char *value); - // value needs to save results which can't be const - bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf); bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLF); // results need to save in buf which can't be const int ReadBinFile(const char *pathName, void **buf, const int bufLen); @@ -138,7 +136,6 @@ namespace Base { string GetTmpDir(); void RemoveLogFile(); uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp); - vector Md5Sum(uint8_t *buf, int size); bool IsRoot(); char GetPathSep(); bool IsAbsolutePath(string &path); @@ -150,6 +147,18 @@ namespace Base { { return MAX_USBFFS_BULK; } +#ifdef HDC_SUPPORT_FLASHD + // deprecated, remove later + inline bool SetHdcProperty(const char *key, const char *value) + { + return false; + } + // deprecated, remove later + inline bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf) + { + return false; + } +#endif } // namespace base } // namespace Hdc diff --git a/src/common/define.h b/src/common/define.h index 4e4dafa5a35a7a5503e34ce59da4eec5dc114ffa..0d63052c16302cb07c4c4a324d80b8eb4abfe05d 100644 --- a/src/common/define.h +++ b/src/common/define.h @@ -48,8 +48,9 @@ constexpr uint16_t DEVICE_CHECK_INTERVAL = 3000; // ms constexpr uint16_t MAX_SIZE_IOBUF = 15360; constexpr uint16_t MAX_USBFFS_BULK = 16384; // double-word(hex)=[0]major[1][2]minor[3][4]version[5]fix(a-p)[6][7]reserve -constexpr uint32_t HDC_VERSION_NUMBER = 0x10101a00; // 1.1.1b=0x10101100 +constexpr uint32_t HDC_VERSION_NUMBER = 0x10101b00; // 1.1.1b=0x10101100 constexpr uint32_t HDC_BUF_MAX_BYTES = INT_MAX; +constexpr uint32_t HDC_SOCKETPAIR_SIZE = MAX_SIZE_IOBUF * 10; const string WHITE_SPACES = " \t\n\r"; const string UT_TMP_PATH = "/tmp/hdc-ut"; diff --git a/src/common/define_plus.h b/src/common/define_plus.h index 34879d87a27b40205346fe5029e2263d57612b53..486ebcb6a3f291f929c446b54078318047cb6c9a 100644 --- a/src/common/define_plus.h +++ b/src/common/define_plus.h @@ -16,7 +16,6 @@ #define DEFINE_PLUS_H namespace Hdc { -constexpr uint8_t LOG_LEVEL_FULL = 5; // ############################# enum define ################################### enum LogLevel { LOG_OFF, @@ -118,18 +117,22 @@ enum HdcCommand { CMD_KERNEL_ECHO, CMD_KERNEL_ECHO_RAW, CMD_KERNEL_ENABLE_KEEPALIVE, + CMD_KERNEL_WAKEUP_SLAVETASK, // One-pass simple commands - CMD_UNITY_EXECUTE = 1000, + CMD_UNITY_COMMAND_HEAD = 1000, // not use + CMD_UNITY_EXECUTE, CMD_UNITY_REMOUNT, CMD_UNITY_REBOOT, CMD_UNITY_RUNMODE, CMD_UNITY_HILOG, CMD_UNITY_TERMINATE, CMD_UNITY_ROOTRUN, + CMD_JDWP_LIST, + CMD_JDWP_TRACK, + CMD_UNITY_COMMAND_TAIL, // not use + // It will be separated from unity in the near future CMD_UNITY_BUGREPORT_INIT, CMD_UNITY_BUGREPORT_DATA, - CMD_UNITY_JPID, - CMD_TRACK_JPID, // Shell commands types CMD_SHELL_INIT = 2000, CMD_SHELL_DATA, @@ -158,6 +161,9 @@ enum HdcCommand { CMD_APP_DATA, CMD_APP_FINISH, CMD_APP_UNINSTALL, + + // deprecated, remove later + CMD_UNITY_JPID = CMD_JDWP_LIST, }; enum UsbProtocolOption { @@ -195,6 +201,7 @@ struct TaskInformation { bool taskStop; bool taskFree; bool serverOrDaemon; + bool masterSlave; uv_loop_t *runLoop; void *taskClass; void *ownerSessionClass; @@ -203,38 +210,58 @@ using HTaskInfo = TaskInformation *; #pragma pack(pop) +#ifdef HDC_HOST +struct HostUSBEndpoint { + HostUSBEndpoint() + { + endpoint = 0; + sizeEpBuf = 16384; // MAX_USBFFS_BULK + transfer = libusb_alloc_transfer(0); + isShutdown = true; + isComplete = true; + } + ~HostUSBEndpoint() + { + libusb_free_transfer(transfer); + } + uint8_t endpoint; + uint8_t buf[16384]; // MAX_USBFFS_BULK + bool isComplete; + bool isShutdown; + bool bulkInOut; // true is bulkIn + uint16_t sizeEpBuf; + mutex mutexIo; + mutex mutexCb; + condition_variable cv; + libusb_transfer *transfer; +}; +#endif + struct HdcUSB { #ifdef HDC_HOST libusb_context *ctxUSB = nullptr; // child-use, main null libusb_device *device; libusb_device_handle *devHandle; - uint8_t interfaceNumber; uint16_t retryCount; - // D2H device to host endpoint's address - uint8_t epDevice; - // H2D host to device endpoint's address - uint8_t epHost; uint8_t devId; uint8_t busId; - uint16_t sizeEpBuf; + uint8_t interfaceNumber; string serialNumber; string usbMountPoint; - uint8_t *bufDevice; - uint8_t *bufHost; - libusb_transfer *transferRecv; - bool recvIOComplete; - bool sendIOComplete; - uv_thread_t threadUsbChildWork; + HostUSBEndpoint hostBulkIn; + HostUSBEndpoint hostBulkOut; + #else // usb accessory FunctionFS // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle int bulkOut; // EP1 device recv int bulkIn; // EP2 device send #endif - mutex lockDeviceHandle; + uint32_t payloadSize; uint16_t wMaxPacketSizeSend; - uint32_t bulkinDataSize; bool resetIO; // if true, must break write and read,default false + mutex lockDeviceHandle; + mutex lockSendUsbBlock; }; using HUSB = struct HdcUSB *; diff --git a/src/common/forward.cpp b/src/common/forward.cpp index ff34f3b7e0f9d7df54a0dbe45c8b9f7cf2415909..aa1fd77fceed1506c490a1b0c97324b4f1f9ceeb 100644 --- a/src/common/forward.cpp +++ b/src/common/forward.cpp @@ -755,7 +755,7 @@ bool HdcForwardBase::CommandDispatch(const uint16_t command, uint8_t *payload, c string sError; // prepare if (CMD_FORWARD_INIT == command) { - string strCommand(reinterpret_cast(payload), payloadSize); + string strCommand(reinterpret_cast(payload), payloadSize); if (!BeginForward(strCommand, sError)) { ret = false; goto Finish; diff --git a/src/common/session.cpp b/src/common/session.cpp index 42eee8c36b24434aa7a14a2fa13d0a05a372335b..5f6ab035c7e7bd8c402b89b070e57ede68d96508 100644 --- a/src/common/session.cpp +++ b/src/common/session.cpp @@ -18,6 +18,8 @@ namespace Hdc { 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 string threadNum = std::to_string(SIZE_THREAD_POOL); uv_os_setenv("UV_THREADPOOL_SIZE", threadNum.c_str()); @@ -314,16 +316,6 @@ int HdcSessionBase::MallocSessionByConnectType(HSession hSession) } hSession->hUSB = hUSB; hSession->hUSB->wMaxPacketSizeSend = MAX_PACKET_SIZE_HISPEED; -#ifdef HDC_HOST - int max = Base::GetUsbffsBulkSize(); - hUSB->sizeEpBuf = max; - hUSB->bufDevice = new uint8_t[max](); - hUSB->bufHost = new uint8_t[max](); - hUSB->transferRecv = libusb_alloc_transfer(0); - hUSB->recvIOComplete = true; - hUSB->sendIOComplete = true; -#else -#endif break; } default: @@ -410,11 +402,6 @@ void HdcSessionBase::FreeSessionByConnectType(HSession hSession) libusb_close(hUSB->devHandle); hUSB->devHandle = nullptr; } - - delete[] hUSB->bufDevice; - delete[] hUSB->bufHost; - libusb_free_transfer(hUSB->transferRecv); - libusb_exit(hUSB->ctxUSB); #else if (hUSB->bulkIn > 0) { close(hUSB->bulkIn); @@ -485,12 +472,10 @@ void HdcSessionBase::FreeSessionOpeate(uv_timer_t *handle) } WRITE_LOG(LOG_DEBUG, "FreeSessionOpeate ref:%u", uint32_t(hSession->ref)); #ifdef HDC_HOST - if (hSession->hUSB != nullptr && (!hSession->hUSB->recvIOComplete || !hSession->hUSB->sendIOComplete)) { - if (!hSession->hUSB->recvIOComplete) { - HdcUSBBase *pUSB = ((HdcUSBBase *)hSession->classModule); - pUSB->CancelUsbLoopRead(hSession->hUSB); - } - // send will be end with timeout + if (hSession->hUSB != nullptr + && (!hSession->hUSB->hostBulkIn.isShutdown || !hSession->hUSB->hostBulkOut.isShutdown)) { + HdcUSBBase *pUSB = ((HdcUSBBase *)hSession->classModule); + pUSB->CancelUsbIo(hSession); return; } #endif @@ -758,8 +743,7 @@ int HdcSessionBase::FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read) } else if (childRet == 0) { // Not enough a IO break; - } else { - // <0 + } else { // <0 hSession->availTailIndex = 0; // Preventing malicious data packages indexBuf = ERR_BUF_SIZE; break; @@ -780,7 +764,7 @@ int HdcSessionBase::FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read) void HdcSessionBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) { HSession context = (HSession)handle->data; - Base::ReallocBuf(&context->ioBuf, &context->bufSize, Base::GetMaxBufSize() * 4); + Base::ReallocBuf(&context->ioBuf, &context->bufSize, HDC_SOCKETPAIR_SIZE); buf->base = (char *)context->ioBuf + context->availTailIndex; int size = context->bufSize - context->availTailIndex; buf->len = std::min(size, static_cast(sizeWanted)); @@ -1047,35 +1031,65 @@ void HdcSessionBase::LogMsg(const uint32_t sessionId, const uint32_t channelId, ServerCommand(sessionId, channelId, CMD_KERNEL_ECHO, buf.data(), buf.size()); } +bool HdcSessionBase::NeedNewTaskInfo(const uint16_t command, bool &masterTask) +{ + // referer from HdcServerForClient::DoCommandRemote + bool ret = false; + bool taskMasterInit = false; + masterTask = false; + switch (command) { + case CMD_FILE_INIT: + case CMD_FORWARD_INIT: + case CMD_APP_INIT: + case CMD_APP_UNINSTALL: + case CMD_UNITY_BUGREPORT_INIT: + case CMD_APP_SIDELOAD: + taskMasterInit = true; + break; + default: + break; + } + if (!serverOrDaemon + && (command == CMD_SHELL_INIT || (command > CMD_UNITY_COMMAND_HEAD && command < CMD_UNITY_COMMAND_TAIL))) { + // daemon's single side command + ret = true; + } else if (command == CMD_KERNEL_WAKEUP_SLAVETASK) { + // slave tasks + ret = true; + } else if (taskMasterInit) { + // task init command + masterTask = true; + ret = true; + } + return ret; +} // Heavy and time-consuming work was putted in the new thread to do, and does // not occupy the main thread bool HdcSessionBase::DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, int payloadSize) { bool ret = true; + HTaskInfo hTaskInfo = nullptr; + bool masterTask = false; while (true) { - HTaskInfo hTaskInfo = AdminTask(OP_QUERY, hSession, channelId, nullptr); - if (!hTaskInfo) { + // Some basic commands do not have a local task constructor. example: Interactive shell, some uinty commands + if (NeedNewTaskInfo(command, masterTask)) { WRITE_LOG(LOG_DEBUG, "New HTaskInfo"); hTaskInfo = new TaskInformation(); hTaskInfo->channelId = channelId; hTaskInfo->sessionId = hSession->sessionId; hTaskInfo->runLoop = &hSession->childLoop; hTaskInfo->serverOrDaemon = serverOrDaemon; + hTaskInfo->masterSlave = masterTask; + AdminTask(OP_ADD, hSession, channelId, hTaskInfo); + } else { + hTaskInfo = AdminTask(OP_QUERY, hSession, channelId, nullptr); } - if (hTaskInfo->taskStop) { - WRITE_LOG(LOG_DEBUG, "RedirectToTask jump stopped task:%u", channelId); - break; - } - if (hTaskInfo->taskFree) { - WRITE_LOG(LOG_DEBUG, "Jump delete HTaskInfo"); + if (!hTaskInfo || hTaskInfo->taskStop || hTaskInfo->taskFree) { + WRITE_LOG(LOG_ALL, "Dead HTaskInfo, ignore, channelId:%u command:%u", channelId, command); break; } ret = RedirectToTask(hTaskInfo, hSession, channelId, command, payload, payloadSize); - if (!hTaskInfo->hasInitial) { - AdminTask(OP_ADD, hSession, channelId, hTaskInfo); - hTaskInfo->hasInitial = true; - } break; } return ret; diff --git a/src/common/session.h b/src/common/session.h index 440cb84feb5f595931c9e87ce0dcbf0627c6ee6e..9e7422f7961eaee56495efe23c84285fdc45c2b5 100644 --- a/src/common/session.h +++ b/src/common/session.h @@ -45,16 +45,20 @@ public: HdcSessionBase(bool serverOrDaemonIn); virtual ~HdcSessionBase(); - virtual void AttachChannel(HSession hSession, const uint32_t channelId) {}; - virtual void DeatchChannel(HSession hSession, const uint32_t channelId) {}; - virtual bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, - const uint16_t command, uint8_t *payload, const int payloadSize) + virtual void AttachChannel(HSession hSession, const uint32_t channelId) + { + } + virtual void DeatchChannel(HSession hSession, const uint32_t channelId) { - return true; } virtual void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) { } + virtual bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) + { + return true; + } // Thread security interface for global stop programs void PostStopInstanceMessage(bool restart = false); void ReMainLoopForInstanceClear(); @@ -128,9 +132,10 @@ protected: bool ret = true; T *ptrTask = nullptr; if (!hTaskInfo->hasInitial) { + hTaskInfo->taskType = taskType; ptrTask = new T(hTaskInfo); + hTaskInfo->hasInitial = true; hTaskInfo->taskClass = ptrTask; - hTaskInfo->taskType = taskType; } else { ptrTask = (T *)hTaskInfo->taskClass; } @@ -173,6 +178,7 @@ private: void FreeSessionByConnectType(HSession hSession); bool WorkThreadStartSession(HSession hSession); uint32_t GetSessionPseudoUid(); + bool NeedNewTaskInfo(const uint16_t command, bool &masterTask); map mapSession; uv_rwlock_t lockMapSession; diff --git a/src/common/task.cpp b/src/common/task.cpp index 13383b310b4df8d9945fb2a5a2227d6d227013e5..add408ad9c1c83ec753135d96fcc47c8db03dcc6 100644 --- a/src/common/task.cpp +++ b/src/common/task.cpp @@ -26,6 +26,8 @@ HdcTaskBase::HdcTaskBase(HTaskInfo hTaskInfo) childReady = false; singalStop = false; refCount = 0; + if (taskInfo->masterSlave) + SendToAnother(CMD_KERNEL_WAKEUP_SLAVETASK, nullptr, 0); } HdcTaskBase::~HdcTaskBase() diff --git a/src/common/transfer.cpp b/src/common/transfer.cpp index c4c169cd5ee43cc3a2fe7d88a6fc43cbee6df2f8..68c7edb5d8aceacd7275035cddd28cfcd0b73a7f 100644 --- a/src/common/transfer.cpp +++ b/src/common/transfer.cpp @@ -47,6 +47,8 @@ bool HdcTransferBase::ResetCtx(CtxFile *context, bool full) } context->closeNotify = false; context->indexIO = 0; + context->lastErrno = 0; + context->ioFinish = false; return true; } @@ -58,6 +60,11 @@ int HdcTransferBase::SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sen bool ret = false; while (true) { if (!buf || !ioContext || bytes < 0) { + WRITE_LOG(LOG_DEBUG, "SimpleFileIO param check failed"); + break; + } + if (context->ioFinish) { + WRITE_LOG(LOG_DEBUG, "SimpleFileIO to closed IOStream"); break; } uv_fs_t *req = &ioContext->fs; @@ -102,6 +109,7 @@ void HdcTransferBase::OnFileClose(uv_fs_t *req) HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; if (context->closeNotify) { // close-step2 + // maybe successful finish or failed finish thisClass->WhenTransferFinish(context); } --thisClass->refCount; @@ -174,48 +182,45 @@ bool HdcTransferBase::SendIOPayload(CtxFile *context, int index, uint8_t *data, void HdcTransferBase::OnFileIO(uv_fs_t *req) { - bool tryFinishIO = false; CtxFileIO *contextIO = (CtxFileIO *)req->data; CtxFile *context = (CtxFile *)contextIO->context; HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; uint8_t *bufIO = contextIO->bufIO; uv_fs_req_cleanup(req); - --thisClass->refCount; while (true) { if (req->result < 0) { WRITE_LOG(LOG_DEBUG, "OnFileIO error: %s", uv_strerror((int)req->result)); context->closeNotify = true; - tryFinishIO = true; + context->lastErrno = abs(req->result); + context->ioFinish = true; break; } context->indexIO += req->result; if (req->fs_type == UV_FS_READ) { if (!thisClass->SendIOPayload(context, context->indexIO - req->result, bufIO, req->result)) { - tryFinishIO = true; + context->ioFinish = true; break; } if (context->indexIO < context->fileSize) { thisClass->SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize() * thisClass->maxTransferBufFactor); } else { - tryFinishIO = true; + context->ioFinish = true; } } else if (req->fs_type == UV_FS_WRITE) { // write if (context->indexIO >= context->fileSize) { // The active end must first read it first, but you can't make Finish first, because Slave may not // end.Only slave receives complete talents Finish context->closeNotify = true; - tryFinishIO = true; + context->ioFinish = true; thisClass->SetFileTime(context); } } else { - tryFinishIO = true; + context->ioFinish = true; } break; } - delete[] bufIO; - delete contextIO; // Req is part of the Contextio structure, no free release - if (tryFinishIO) { + if (context->ioFinish) { // close-step1 ++thisClass->refCount; if (req->fs_type == UV_FS_WRITE) { @@ -223,6 +228,9 @@ void HdcTransferBase::OnFileIO(uv_fs_t *req) } uv_fs_close(thisClass->loopTask, &context->fsCloseReq, context->fsOpenReq.result, OnFileClose); } + --thisClass->refCount; + delete[] bufIO; + delete contextIO; // Req is part of the Contextio structure, no free release } void HdcTransferBase::OnFileOpen(uv_fs_t *req) diff --git a/src/common/transfer.h b/src/common/transfer.h index 135f81f2c350acfee8a81f3d56cb03a591d36dd1..61e2c58046a421e951e8f057a355bb85be35df3e 100644 --- a/src/common/transfer.h +++ b/src/common/transfer.h @@ -52,20 +52,23 @@ public: protected: // Static file context - struct CtxFile { // The structure cannot be initialized by MEMSET - bool master; // Document transmission initiative - bool closeNotify; - void *thisClass; + struct CtxFile { // The structure cannot be initialized by MEMSET, will rename to CtxTransfer uint64_t fileSize; uint64_t indexIO; // Id or written IO bytes - uv_loop_t *loop; - uv_fs_cb cb; + uint64_t transferBegin; string localName; string localPath; string remotePath; + bool master; // Document transmission initiative + bool closeNotify; + bool ioFinish; + void *thisClass; + uint32_t lastErrno; + + uv_loop_t *loop; uv_fs_t fsOpenReq; uv_fs_t fsCloseReq; - uint64_t transferBegin; + uv_fs_cb cb; vector taskQueue; TransferConfig transferConfig; // Used for network IO configuration initialization }; diff --git a/src/common/usb.cpp b/src/common/usb.cpp index c971bd02a22d69375d3127f84eecdc0ef70dd1c8..b61996a38735a33d1603b2eb130f19defccf1e1c 100644 --- a/src/common/usb.cpp +++ b/src/common/usb.cpp @@ -76,7 +76,7 @@ int HdcUSBBase::SendUSBBlock(HSession hSession, uint8_t *data, const int length) int childRet = 0; int ret = ERR_IO_FAIL; auto header = BuildPacketHeader(hSession->sessionId, USB_OPTION_HEADER, length); - hSession->hUSB->lockDeviceHandle.lock(); + hSession->hUSB->lockSendUsbBlock.lock(); do { if ((childRet = SendUSBRaw(hSession, header.data(), header.size())) <= 0) { WRITE_LOG(LOG_FATAL, "SendUSBRaw index failed"); @@ -97,7 +97,7 @@ int HdcUSBBase::SendUSBBlock(HSession hSession, uint8_t *data, const int length) } ret = length; } while (false); - hSession->hUSB->lockDeviceHandle.unlock(); + hSession->hUSB->lockSendUsbBlock.unlock(); return ret; } @@ -129,15 +129,16 @@ bool HdcUSBBase::IsUsbPacketHeader(uint8_t *ioBuf, int ioBytes) void HdcUSBBase::PreSendUsbSoftReset(HSession hSession, uint32_t sessionIdOld) { HUSB hUSB = hSession->hUSB; + int childRet = 0; if (hSession->serverOrDaemon && !hUSB->resetIO) { - uint32_t sid = sessionIdOld; - // or we can sendmsg to childthread send? - hUSB->lockDeviceHandle.lock(); - ++hSession->ref; + hUSB->lockSendUsbBlock.lock(); WRITE_LOG(LOG_WARN, "SendToHdcStream check, sessionId not matched"); - SendUsbSoftReset(hSession, sid); - --hSession->ref; - hUSB->lockDeviceHandle.unlock(); + auto header = BuildPacketHeader(sessionIdOld, USB_OPTION_RESET, 0); + if ((childRet = SendUSBRaw(hSession, header.data(), header.size())) <= 0) { + WRITE_LOG(LOG_FATAL, "PreSendUsbSoftReset send failed"); + } + hUSB->lockSendUsbBlock.unlock(); + hUSB->resetIO = true; } } @@ -159,10 +160,10 @@ int HdcUSBBase::CheckPacketOption(HSession hSession, uint8_t *appendData, int da } if (header->option & USB_OPTION_HEADER) { // header packet - hUSB->bulkinDataSize = header->dataSize; + hUSB->payloadSize = header->dataSize; } // soft ZLP - return hUSB->bulkinDataSize; + return hUSB->payloadSize; } // return value: <0 error; = 0 all finish; >0 need size @@ -173,7 +174,7 @@ int HdcUSBBase::SendToHdcStream(HSession hSession, uv_stream_t *stream, uint8_t if (IsUsbPacketHeader(appendData, dataSize)) { return CheckPacketOption(hSession, appendData, dataSize); } - if (hUSB->bulkinDataSize <= (uint32_t)childRet) { + if (hUSB->payloadSize <= (uint32_t)childRet) { // last session data PreSendUsbSoftReset(hSession, 0); // 0 == reset current return 0; @@ -182,8 +183,8 @@ int HdcUSBBase::SendToHdcStream(HSession hSession, uv_stream_t *stream, uint8_t WRITE_LOG(LOG_FATAL, "Error usb send to stream dataSize:%d", dataSize); return ERR_IO_FAIL; } - hUSB->bulkinDataSize -= childRet; - return hUSB->bulkinDataSize; + hUSB->payloadSize -= childRet; + return hUSB->payloadSize; } } \ No newline at end of file diff --git a/src/common/usb.h b/src/common/usb.h index 0c9361ec783a11692bac89b4fe0c488368ded3ac..046890f25ebb6a8f4728ab74e1d35d034d9e4c99 100644 --- a/src/common/usb.h +++ b/src/common/usb.h @@ -22,7 +22,7 @@ public: HdcUSBBase(const bool serverOrDaemonIn, void *ptrMainBase); virtual ~HdcUSBBase(); virtual bool ReadyForWorkThread(HSession hSession); - virtual void CancelUsbLoopRead(HUSB hUSB) {}; + virtual void CancelUsbIo(HSession hSession) {}; int SendUSBBlock(HSession hSession, uint8_t *data, const int length); protected: @@ -44,7 +44,6 @@ protected: const string USB_PACKET_FLAG = "UB"; // must 2bytes private: - virtual void SendUsbSoftReset(HSession hSession, uint32_t sessionIdOld) {}; static void ReadUSB(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); vector BuildPacketHeader(uint32_t sessionId, uint8_t option, uint32_t dataSize); int CheckPacketOption(HSession hSession, uint8_t *appendData, int dataSize); diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 2bff0d4ae24db47be14941a272fd26370b8a5699..db9516ddddd2c4f590b78c13d8e9ae80d060e6cd 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -80,14 +80,11 @@ void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB) clsUSBServ = new HdcDaemonUSB(false, this); ((HdcDaemonUSB *)clsUSBServ)->Initial(); } - clsJdwp = new HdcJdwp(&loopMain); ((HdcJdwp *)clsJdwp)->Initial(); - // enable security - char value[4] = "0"; - Base::GetHdcProperty("ro.hdc.secure", value, sizeof(value)); - string secure = value; + string secure; + SystemDepend::GetDevItem("ro.hdc.secure", secure); enableSecure = (Base::Trim(secure) == "1"); } @@ -106,8 +103,8 @@ bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uin case CMD_UNITY_ROOTRUN: case CMD_UNITY_TERMINATE: case CMD_UNITY_BUGREPORT_INIT: - case CMD_UNITY_JPID: - case CMD_TRACK_JPID: + case CMD_JDWP_LIST: + case CMD_JDWP_TRACK: ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); break; case CMD_SHELL_INIT: @@ -137,7 +134,7 @@ bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uin ret = TaskCommandDispatch(hTaskInfo, TASK_FORWARD, command, payload, payloadSize); break; default: - ret = false; + //ignore unknow command break; } return ret; @@ -298,4 +295,15 @@ void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) uint32_t fd = *(uint32_t *)(buf + 5); // 5 : fd offset ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd); }; + +void HdcDaemon::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) +{ + if (!freeOrClear) { + return; // ignore step 1 + } + if (clsUSBServ != nullptr) { + auto clsUsbModule = reinterpret_cast(clsUSBServ); + clsUsbModule->OnSessionFreeFinally(hSession); + } +} } // namespace Hdc diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index b25929f4747a8f1517715a82ab183d5d0b3df743..73c759951680cccef6f640023f82f07e03b58dbe 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -39,6 +39,12 @@ private: void ClearInstanceResource(); bool DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize); void TryStopInstance(); +// deprecated, remove later +#ifdef HDC_SUPPORT_FLASHD +// null +#else + void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear); +#endif bool enableSecure; }; diff --git a/src/daemon/daemon_app.cpp b/src/daemon/daemon_app.cpp index b472039f33cb64336bf6d9fc47274407bcaa6ac4..1d2f70bc616a2963a5805650e2d620733b667ba3 100644 --- a/src/daemon/daemon_app.cpp +++ b/src/daemon/daemon_app.cpp @@ -36,6 +36,7 @@ bool HdcDaemonApp::ReadyForRelease() if (!asyncCommand.ReadyForRelease()) { return false; } + WRITE_LOG(LOG_DEBUG, "HdcDaemonApp ready for release"); return true; } @@ -142,14 +143,15 @@ void HdcDaemonApp::Sideload(const char *pathOTA) void HdcDaemonApp::WhenTransferFinish(CtxFile *context) { + if (context->lastErrno > 0) { + WRITE_LOG(LOG_DEBUG, "HdcDaemonApp WhenTransferFinish with errno:%d", context->lastErrno); + return; + } if (ctxNow.transferConfig.functionName == CMDSTR_APP_SIDELOAD) { Sideload(context->localPath.c_str()); } else if (ctxNow.transferConfig.functionName == CMDSTR_APP_INSTALL) { PackageShell(true, context->transferConfig.options.c_str(), context->localPath.c_str()); } else { - WRITE_LOG(LOG_WARN, "WhenTransferFinish error funcnm:[%s] lpath:[%s]", - ctxNow.transferConfig.functionName.c_str(), context->localPath.c_str()); - PackageShell(true, context->transferConfig.options.c_str(), context->localPath.c_str()); } }; } \ No newline at end of file diff --git a/src/daemon/daemon_common.h b/src/daemon/daemon_common.h index d2a07325ea8417fc32b640b5d07ca6f93799fdc9..b96e2b38607e17a0c7624f6edd3887659476ce92 100644 --- a/src/daemon/daemon_common.h +++ b/src/daemon/daemon_common.h @@ -24,6 +24,7 @@ #include "../common/serial_struct.h" #ifndef HDC_HOST // daemon used +#include "system_depend.h" #include "jdwp.h" #include "daemon.h" #include "daemon_unity.h" diff --git a/src/daemon/daemon_tcp.cpp b/src/daemon/daemon_tcp.cpp index 35e90be14b7cdc20463e39b5f2bb1fb6d6e10098..3df9c23f37a5863fa6463109dca773f2572bffd5 100644 --- a/src/daemon/daemon_tcp.cpp +++ b/src/daemon/daemon_tcp.cpp @@ -19,10 +19,9 @@ HdcDaemonTCP::HdcDaemonTCP(const bool serverOrDaemonIn, void *ptrMainBase) : HdcTCPBase(serverOrDaemonIn, ptrMainBase) { // If the listening value for the property setting is obtained, it will be 0 randomly assigned. - char strTCPPort[BUF_SIZE_TINY] = ""; - const uint16_t BUFF_SIZE = 8; - Base::GetHdcProperty("persist.hdc.port", strTCPPort, BUFF_SIZE); - tcpListenPort = atoi(strTCPPort); + string strTCPPort; + SystemDepend::GetDevItem("persist.hdc.port", strTCPPort); + tcpListenPort = atoi(strTCPPort.c_str()); if (tcpListenPort <= 0) { tcpListenPort = 0; } diff --git a/src/daemon/daemon_unity.cpp b/src/daemon/daemon_unity.cpp index a91381cfbca909f8f0565e4129cd60a8676ae8fa..ebabd9c88bc99a0d9feed8baaabad92e176ec108 100644 --- a/src/daemon/daemon_unity.cpp +++ b/src/daemon/daemon_unity.cpp @@ -14,11 +14,6 @@ */ #include "daemon_unity.h" #include -#ifdef __MUSL__ -extern "C" { -#include "init_reboot.h" -} -#endif namespace Hdc { HdcDaemonUnity::HdcDaemonUnity(HTaskInfo hTaskInfo) @@ -36,7 +31,6 @@ void HdcDaemonUnity::StopTask() { // Remove jpid tracker when stopping task RemoveJdwpTracker(); - asyncCommand.DoRelease(); } @@ -179,24 +173,7 @@ bool HdcDaemonUnity::RemountDevice() bool HdcDaemonUnity::RebootDevice(const string &cmd) { sync(); -#ifndef __MUSL__ - string propertyVal; - if (!cmd.size()) { - propertyVal = "reboot"; - } else { - propertyVal = Base::StringFormat("reboot,%s", cmd.c_str()); - } - return Base::SetHdcProperty(rebootProperty.c_str(), propertyVal.c_str()); -#else - string reason; - if (cmd == "recovery") { - reason = "updater"; - } else if (cmd == "bootloader") { - reason = "updater"; - } - WRITE_LOG(LOG_DEBUG, "DoReboot with args:[%s] for cmd:[%s]", reason.c_str(), cmd.c_str()); - return DoReboot(reason.c_str()); -#endif + return SystemDepend::RebootDevice(cmd); } bool HdcDaemonUnity::SetDeviceRunMode(void *daemonIn, const char *cmd) @@ -204,12 +181,12 @@ bool HdcDaemonUnity::SetDeviceRunMode(void *daemonIn, const char *cmd) HdcDaemon *daemon = (HdcDaemon *)daemonIn; WRITE_LOG(LOG_DEBUG, "Set run mode:%s", cmd); if (!strcmp(CMDSTR_TMODE_USB.c_str(), cmd)) { - Base::SetHdcProperty("persist.hdc.mode", CMDSTR_TMODE_USB.c_str()); + SystemDepend::SetDevItem("persist.hdc.mode", CMDSTR_TMODE_USB.c_str()); } else if (!strncmp("port", cmd, strlen("port"))) { - Base::SetHdcProperty("persist.hdc.mode", CMDSTR_TMODE_TCP.c_str()); + SystemDepend::SetDevItem("persist.hdc.mode", CMDSTR_TMODE_TCP.c_str()); if (!strncmp("port ", cmd, strlen("port "))) { const char *port = cmd + 5; - Base::SetHdcProperty("persist.hdc.port", port); + SystemDepend::SetDevItem("persist.hdc.port", port); } } else { LogMsg(MSG_FAIL, "Unknow command"); @@ -294,9 +271,9 @@ bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, c case CMD_UNITY_ROOTRUN: { ret = false; if (payloadSize != 0 && !strcmp((char *)strPayload.c_str(), "r")) { - Base::SetHdcProperty("persist.hdc.root", "0"); + SystemDepend::SetDevItem("persist.hdc.root", "0"); } else { - Base::SetHdcProperty("persist.hdc.root", "1"); + SystemDepend::SetDevItem("persist.hdc.root", "1"); } daemon->PostStopInstanceMessage(true); break; @@ -310,12 +287,12 @@ bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, c ExecuteShell((char *)CMDSTR_BUGREPORT.c_str()); break; } - case CMD_UNITY_JPID: { + case CMD_JDWP_LIST: { ret = false; ListJdwpProcess(daemon); break; } - case CMD_TRACK_JPID: { + case CMD_JDWP_TRACK: { if (!TrackJdwpProcess(daemon)) { ret = false; } diff --git a/src/daemon/daemon_unity.h b/src/daemon/daemon_unity.h index 91e5575d6ac82a59ee9c0f19661b23fc2bb4e8dc..9dcd64ac7a7426a3e5591fc3e9271f66b773ad18 100644 --- a/src/daemon/daemon_unity.h +++ b/src/daemon/daemon_unity.h @@ -39,7 +39,6 @@ private: bool TrackJdwpProcess(void *daemonIn); void RemoveJdwpTracker(); - const string rebootProperty = "sys.powerctl"; AsyncCmd asyncCommand; uint16_t currentDataCommand; #ifdef UNIT_TEST diff --git a/src/daemon/daemon_usb.cpp b/src/daemon/daemon_usb.cpp index 0c3662d1569cb567409bf5095584089da3017374..9833aa28f03bcf75b9576a8b2115ab99c6a9ca07 100644 --- a/src/daemon/daemon_usb.cpp +++ b/src/daemon/daemon_usb.cpp @@ -19,18 +19,19 @@ namespace Hdc { HdcDaemonUSB::HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase) : HdcUSBBase(serverOrDaemonIn, ptrMainBase) { - Base::ZeroStruct(sendEP); Base::ZeroStruct(usbHandle); - uv_mutex_init(&sendEP); } HdcDaemonUSB::~HdcDaemonUSB() { // Closed in the IO loop, no longer closing CLOSE ENDPOINT - uv_mutex_destroy(&sendEP); if (controlEp > 0) { close(controlEp); } + if (ctxRecv.buf) { + delete[] ctxRecv.buf; + } + uv_fs_req_cleanup(&ctxRecv.req); } void HdcDaemonUSB::Stop() @@ -87,8 +88,16 @@ int HdcDaemonUSB::Initial() basePath = GetDevPath(USB_FFS_BASE); 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 -1; + 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); @@ -97,10 +106,45 @@ int HdcDaemonUSB::Initial() return 0; } +// make gnuc++ happy. Clang support direct assignment value to structure, buf g++ weakness +void HdcDaemonUSB::FillUsbV2Head(usb_functionfs_desc_v2 &descUsbFfs) +{ + descUsbFfs.head.magic = LONG_LE(FUNCTIONFS_DESCRIPTORS_MAGIC_V2); + descUsbFfs.head.length = LONG_LE(sizeof(descUsbFfs)); + descUsbFfs.head.flags + = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC; + descUsbFfs.config1Count = 3; + descUsbFfs.config2Count = 3; + descUsbFfs.config3Count = 5; + descUsbFfs.configWosCount = 1; + descUsbFfs.config1Desc = config1; + descUsbFfs.config2Desc = config2; + descUsbFfs.config3Desc = config3; + descUsbFfs.wosHead.interface = 1; + descUsbFfs.wosHead.dwLength = LONG_LE(sizeof(descUsbFfs.wosHead) + sizeof(descUsbFfs.wosDesc)); + descUsbFfs.wosHead.bcdVersion = SHORT_LE(1); + descUsbFfs.wosHead.wIndex = SHORT_LE(4); + descUsbFfs.wosHead.bCount = 1; + descUsbFfs.wosHead.Reserved = 0; + descUsbFfs.wosDesc.bFirstInterfaceNumber = 0; + descUsbFfs.wosDesc.Reserved1 = 1; + descUsbFfs.wosDesc.CompatibleID[0] = 'W'; + descUsbFfs.wosDesc.CompatibleID[1] = 'I'; + descUsbFfs.wosDesc.CompatibleID[2] = 'N'; + descUsbFfs.wosDesc.CompatibleID[3] = 'U'; + descUsbFfs.wosDesc.CompatibleID[4] = 'S'; + descUsbFfs.wosDesc.CompatibleID[5] = 'B'; + descUsbFfs.wosDesc.CompatibleID[6] = '\0'; + Base::ZeroArray(descUsbFfs.wosDesc.SubCompatibleID); + Base::ZeroArray(descUsbFfs.wosDesc.Reserved2); +} + // DAEMON end USB module USB-FFS EP port connection int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) { int ret = ERR_GENERIC; + struct usb_functionfs_desc_v2 descUsbFfs = {}; + FillUsbV2Head(descUsbFfs); while (true) { if (controlEp <= 0) { // After the control port sends the instruction, the device is initialized by the device to the HOST host, @@ -112,7 +156,7 @@ int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) WRITE_LOG(LOG_WARN, "%s: cannot open control endpoint: errno=%d", ep0Path.c_str(), errno); break; } - if (write(controlEp, &USB_FFS_DESC, sizeof(USB_FFS_DESC)) < 0) { + if (write(controlEp, &descUsbFfs, sizeof(descUsbFfs)) < 0) { WRITE_LOG(LOG_WARN, "%s: write ffs configs failed: errno=%d", ep0Path.c_str(), errno); break; } @@ -121,7 +165,7 @@ int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) break; } // active usbrc,Send USB initialization singal - Base::SetHdcProperty("sys.usb.ffs.ready", "1"); + SystemDepend::SetDevItem("sys.usb.ffs.ready", "1"); WRITE_LOG(LOG_DEBUG, "ConnectEPPoint ctrl init finish, set usb-ffs ready"); } string outPath = basePath + "/ep1"; @@ -178,7 +222,6 @@ void HdcDaemonUSB::ResetOldSession(uint32_t sessionId) if (hSession == nullptr) { return; } - hSession->hUSB->resetIO = true; // The Host side is restarted, but the USB cable is still connected WRITE_LOG(LOG_WARN, "Hostside softreset to restart daemon, old sessionId:%u", sessionId); daemon->FreeSession(sessionId); @@ -228,12 +271,12 @@ int HdcDaemonUSB::CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop) isAlive = false; uv_fs_close(loop, req, bulkFd, [](uv_fs_t *req) { auto ctx = (CtxCloseBulkEp *)req->data; + WRITE_LOG(LOG_DEBUG, "Try to abort blukin write callback %s", ctx->bulkInOut ? "bulkin" : "bulkout"); if (ctx->bulkInOut) { ctx->thisClass->usbHandle.bulkIn = 0; } else { ctx->thisClass->usbHandle.bulkOut = 0; } - WRITE_LOG(LOG_DEBUG, "Try to abort blukin write callback %s", ctx->bulkInOut ? "bulkin" : "bulkout"); uv_fs_req_cleanup(req); delete ctx; }); @@ -246,7 +289,7 @@ int HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t int childRet = 0; int ret = ERR_IO_FAIL; int offset = 0; - while (modRunning && isAlive && !hSession->isDead && !hSession->hUSB->resetIO) { + while (modRunning && isAlive && !hSession->isDead) { childRet = write(bulkIn, (uint8_t *)data + offset, length - offset); if (childRet <= 0) { int err = errno; @@ -267,9 +310,8 @@ int HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t if (offset == length) { ret = length; } else { - WRITE_LOG(LOG_FATAL, - "BulkinWrite write failed, nsize:%d really:%d modRunning:%d isAlive:%d SessionDead:%d usbReset:%d", - length, offset, modRunning, isAlive, hSession->isDead, hSession->hUSB->resetIO); + WRITE_LOG(LOG_FATAL, "BulkinWrite write failed, nsize:%d really:%d modRunning:%d isAlive:%d SessionDead:%d", + length, offset, modRunning, isAlive, hSession->isDead); } return ret; } @@ -277,12 +319,7 @@ int HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t int HdcDaemonUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) { HdcDaemon *daemon = (HdcDaemon *)hSession->classInstance; - // Prevent memory stacking, send temporary way to use asynchronous - // Generally sent in the same thread, but when new session is created, there is a possibility that the old - // session is not retired. At present, the radical transmission method is currently opened directly in various - // threads, and it can be used exclusive File-DESC transmission mode in each thread. The late stage can be used - // as asynchronous + SendPipe to the main thread transmission. - uv_mutex_lock(&sendEP); + std::unique_lock lock(mutexUsbFfs); ++hSession->ref; int ret = SendUSBIOSync(hSession, &usbHandle, data, length); --hSession->ref; @@ -290,7 +327,6 @@ int HdcDaemonUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) daemon->FreeSession(hSession->sessionId); WRITE_LOG(LOG_DEBUG, "SendUSBRaw try to freesession"); } - uv_mutex_unlock(&sendEP); return ret; } @@ -300,6 +336,15 @@ void HdcDaemonUSB::OnNewHandshakeOK(const uint32_t sessionId) currentSessionId = sessionId; // sync with server, and set server's real Id } +// MainThreadCall, when seession was freeed +void HdcDaemonUSB::OnSessionFreeFinally(const HSession hSession) +{ + if (currentSessionId == hSession->sessionId) { + isAlive = false; + // uv_cancel ctxRecv.req == UV_EBUSY, not effect immediately. It must be close by logic + } +} + HSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO) { HdcDaemon *daemon = reinterpret_cast(clsMainBase); @@ -333,8 +378,6 @@ int HdcDaemonUSB::UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int int HdcDaemonUSB::DispatchToWorkThread(uint32_t sessionId, uint8_t *readBuf, int readBytes) { - // Format:USBPacket1 payload1...USBPacketn - // payloadn-[USBHead1(PayloadHead1+Payload1)]+[USBHead2(Payload2)]+...+[USBHeadN(PayloadN)] HSession hChildSession = nullptr; HdcDaemon *daemon = reinterpret_cast(clsMainBase); int childRet = RET_SUCCESS; @@ -391,39 +434,51 @@ void HdcDaemonUSB::OnUSBRead(uv_fs_t *req) uint32_t sessionId = 0; bool ret = false; int childRet = 0; - --thisClass->ref; + if (bytesIOBytes > hUSB->wMaxPacketSizeSend && bytesIOBytes != thisClass->saveNextReadSize) { + WRITE_LOG(LOG_WARN, "Not full packet, wanted:%d really:%d", thisClass->saveNextReadSize, bytesIOBytes); + } while (thisClass->isAlive) { // Don't care is module running, first deal with this if (bytesIOBytes < 0) { - WRITE_LOG(LOG_WARN, "USBIO failed1 %s", uv_strerror(bytesIOBytes)); - break; - } else if (bytesIOBytes == 0) { - // zero packet - WRITE_LOG(LOG_WARN, "Zero packet received"); - ret = true; - break; - } - if (thisClass->JumpAntiquePacket(*bufPtr, bytesIOBytes)) { - WRITE_LOG(LOG_DEBUG, "JumpAntiquePacket auto jump"); - ret = true; - break; - } - // guess is head of packet - if ((childRet = thisClass->AvailablePacket((uint8_t *)bufPtr, bytesIOBytes, &sessionId)) != RET_SUCCESS) { - if (childRet != ERR_IO_SOFT_RESET) { - WRITE_LOG(LOG_WARN, "AvailablePacket check failed, ret:%d buf:%-50s", bytesIOBytes, bufPtr); + // logic alive and EINTER is gdb attach + // + // [about gdb attach known issue] + // When GDB debugging is loaded, the number of USB read interrupts of libuv will increase. Multiple + // interrupts will increase the correctness of USB data reading. Setting GDB to asynchronous mode or using + // log debugging can avoid this problem + if (bytesIOBytes != -EINTR) { // Epoll will be broken when gdb attach + WRITE_LOG(LOG_WARN, "USBIO ret:%d failed:%s", bytesIOBytes, uv_strerror(bytesIOBytes)); + ret = false; break; + } else { + WRITE_LOG(LOG_ALL, "OnUSBRead signal EINTR"); } - // reset packet - childRet = 0; // need max size + } else if (bytesIOBytes == 0) { // zero packet + WRITE_LOG(LOG_ALL, "Zero packet received"); } else { - // AvailablePacket case - if ((childRet = thisClass->DispatchToWorkThread(sessionId, bufPtr, bytesIOBytes)) < 0) { - WRITE_LOG(LOG_FATAL, "DispatchToWorkThread failed"); + if (thisClass->JumpAntiquePacket(*bufPtr, bytesIOBytes)) { + WRITE_LOG(LOG_DEBUG, "JumpAntiquePacket auto jump"); + ret = true; break; } + // guess is head of packet + if ((childRet = thisClass->AvailablePacket((uint8_t *)bufPtr, bytesIOBytes, &sessionId)) != RET_SUCCESS) { + if (childRet != ERR_IO_SOFT_RESET) { + WRITE_LOG(LOG_WARN, "AvailablePacket check failed, ret:%d buf:%-50s", bytesIOBytes, bufPtr); + break; + } + // reset packet + childRet = 0; // need max size + } else { + // AvailablePacket case + if ((childRet = thisClass->DispatchToWorkThread(sessionId, bufPtr, bytesIOBytes)) < 0) { + WRITE_LOG(LOG_FATAL, "DispatchToWorkThread failed"); + break; + } + } } int nextReadSize = childRet == 0 ? hUSB->wMaxPacketSizeSend : std::min(childRet, Base::GetUsbffsBulkSize()); + thisClass->saveNextReadSize = nextReadSize; if (thisClass->LoopUSBRead(hUSB, nextReadSize) < 0) { WRITE_LOG(LOG_FATAL, "LoopUSBRead failed"); break; @@ -433,45 +488,28 @@ void HdcDaemonUSB::OnUSBRead(uv_fs_t *req) } if (!ret) { thisClass->isAlive = false; + thisClass->ctxRecv.atPollQueue = false; } - delete[] ctxIo->buf; - uv_fs_req_cleanup(req); - delete ctxIo; } int HdcDaemonUSB::LoopUSBRead(HUSB hUSB, int readMaxWanted) { int ret = ERR_GENERIC; HdcDaemon *daemon = reinterpret_cast(clsMainBase); - auto ctxIo = new CtxUvFileCommonIo(); - auto buf = new uint8_t[readMaxWanted](); - uv_fs_t *req = nullptr; uv_buf_t iov; - if (ctxIo == nullptr || buf == nullptr) { - goto FAILED; - } - ctxIo->buf = buf; - ctxIo->bufSize = readMaxWanted; - ctxIo->data = hUSB; - ctxIo->thisClass = this; - req = &ctxIo->req; - req->data = ctxIo; - iov = uv_buf_init(reinterpret_cast(ctxIo->buf), ctxIo->bufSize); + ctxRecv.data = hUSB; + ctxRecv.bufSize = readMaxWanted; + ctxRecv.req = {}; + uv_fs_t *req = &ctxRecv.req; + req->data = &ctxRecv; + iov = uv_buf_init(reinterpret_cast(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"); - goto FAILED; - } - ++this->ref; - return 0; -FAILED: - if (ctxIo != nullptr) { - delete ctxIo; - } - if (buf != nullptr) { - delete[] buf; + return ERR_API_FAIL; } - return ERR_GENERIC; + ctxRecv.atPollQueue = true; + return RET_SUCCESS; } // Because USB can connect to only one host,daemonUSB is only one Session by default @@ -480,16 +518,18 @@ void HdcDaemonUSB::WatchEPTimer(uv_timer_t *handle) HdcDaemonUSB *thisClass = (HdcDaemonUSB *)handle->data; HUSB hUSB = &thisClass->usbHandle; HdcDaemon *daemon = reinterpret_cast(thisClass->clsMainBase); - if (thisClass->isAlive || thisClass->ref > 0) { + if (thisClass->isAlive || thisClass->ctxRecv.atPollQueue) { return; } bool resetEp = false; do { if (hUSB->bulkIn > 0) { + WRITE_LOG(LOG_DEBUG, "Watchdog close bulkin"); thisClass->CloseBulkEp(true, thisClass->usbHandle.bulkIn, &daemon->loopMain); resetEp = true; } if (hUSB->bulkOut > 0) { + WRITE_LOG(LOG_DEBUG, "Watchdog close bulkout"); thisClass->CloseBulkEp(false, thisClass->usbHandle.bulkOut, &daemon->loopMain); resetEp = true; } diff --git a/src/daemon/daemon_usb.h b/src/daemon/daemon_usb.h index 1d2a88455f33091d9b3c63acb85ce4d5ffd749bb..fdb97091c4045d58a7f19350256e9637aa9f7b9e 100644 --- a/src/daemon/daemon_usb.h +++ b/src/daemon/daemon_usb.h @@ -25,14 +25,17 @@ public: void Stop(); int SendUSBRaw(HSession hSession, uint8_t *data, const int length); void OnNewHandshakeOK(const uint32_t sessionId); + void OnSessionFreeFinally(const HSession hSession); private: struct CtxUvFileCommonIo { - uv_fs_t req; - uint8_t *buf; - int bufSize; void *thisClass; void *data; + uint8_t *buf; + int bufSizeMax; + int bufSize; + bool atPollQueue; + uv_fs_t req; }; static void OnUSBRead(uv_fs_t *req); static void WatchEPTimer(uv_timer_t *handle); @@ -50,15 +53,17 @@ private: void ResetOldSession(uint32_t sessionId); int GetMaxPacketSize(int fdFfs); int UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int dataSize); + void FillUsbV2Head(struct usb_functionfs_desc_v2 &descUsbFfs); HdcUSB usbHandle; string basePath; // usb device's base path uint32_t currentSessionId = 0; // USB mode,limit only one session - std::atomic ref = 0; - uv_timer_t checkEP; // server-use - uv_mutex_t sendEP; + uv_timer_t checkEP; // server-use + mutex mutexUsbFfs; bool isAlive = false; int controlEp = 0; // EP0 + CtxUvFileCommonIo ctxRecv = {}; + int saveNextReadSize = 0; }; } // namespace Hdc #endif \ No newline at end of file diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 2cd546806e5d97779644139f45fa84cc13f2d1e9..c9e6580b831eb8e5b65b62bb07df6697b6ba1156 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -34,10 +34,9 @@ bool ForkChildCheck(int argc, const char *argv[]) // hdcd #service start forground // hdcd -b #service start backgroundRun // hdcd -fork #fork - char modeSet[BUF_SIZE_TINY] = ""; - Base::GetHdcProperty("persist.hdc.mode", modeSet, BUF_SIZE_TINY); Base::PrintMessage("Background mode, persist.hdc.mode"); - string workMode = modeSet; + string workMode; + SystemDepend::GetDevItem("persist.hdc.mode", workMode); workMode = Base::Trim(workMode); if (workMode == CMDSTR_TMODE_TCP) { WRITE_LOG(LOG_DEBUG, "Property enable TCP"); @@ -100,7 +99,7 @@ bool GetDaemonCommandlineOptions(int argc, const char *argv[]) { int ch; // hdcd -l4 ... - WRITE_LOG(LOG_DEBUG, "Fgcli mode"); + WRITE_LOG(LOG_DEBUG, "Forground cli-mode"); // Both settings are running with parameters while ((ch = getopt(argc, (char *const *)argv, "utl:")) != -1) { switch (ch) { @@ -134,10 +133,8 @@ bool GetDaemonCommandlineOptions(int argc, const char *argv[]) void NeedDropPriv() { - char droprootSet[BUF_SIZE_TINY] = ""; - Base::GetHdcProperty("persist.hdc.root", droprootSet, BUF_SIZE_TINY); - droprootSet[sizeof(droprootSet) - 1] = '\0'; - string rootMode = droprootSet; + string rootMode; + SystemDepend::GetDevItem("persist.hdc.root", rootMode); if (Base::Trim(rootMode) == "1") { setuid(0); g_rootRun = true; @@ -165,7 +162,6 @@ int main(int argc, const char *argv[]) } if (argc == 1 || (argc == CMD_ARG1_COUNT && (!strcmp(argv[1], "-forkchild") || !strcmp(argv[1], "-b")))) { Hdc::Base::RemoveLogFile(); - Base::SetLogLevel(LOG_LEVEL_FULL); ForkChildCheck(argc, argv); } else { GetDaemonCommandlineOptions(argc, argv); @@ -181,6 +177,7 @@ int main(int argc, const char *argv[]) umask(0); signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); + signal(SIGALRM, SIG_IGN); WRITE_LOG(LOG_DEBUG, "HdcDaemon main run"); HdcDaemon daemon(false); daemon.InitMod(g_enableTcp, g_enableUsb); diff --git a/src/daemon/system_depend.cpp b/src/daemon/system_depend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23b4ccf2e7223c092bb08d1d78eaf67e315a4599 --- /dev/null +++ b/src/daemon/system_depend.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* +############ +This file is used to support compatibility between platforms, differences between old and new projects and +compilation platforms + +defined __MUSL__ Has migrated to the latest version of harmony project + +defined HARMONY_PROJECT +With openharmony toolchains suport. If not defined, it should be [device]buildroot or [PC]msys64(...)/ubuntu-apt(...) +envirments +############ +*/ +#include "system_depend.h" +#include "../common/base.h" +#if defined(__MUSL__) && defined(HARMONY_PROJECT) +extern "C" { +#include "init_reboot.h" +#include "parameter.h" +} +#endif + +namespace Hdc { +namespace SystemDepend { + bool SetDevItem(const char *key, const char *value) + { + bool ret = true; +#if defined __MUSL__ +#ifdef HARMONY_PROJECT + ret = SetParameter(key, value) == 0; +#else + char outBuf[256] = ""; + string stringBuf = Base::StringFormat("param set %s %s", key, value); + Base::RunPipeComand(stringBuf.c_str(), outBuf, sizeof(outBuf), true); +#endif // HARMONY_PROJECT +#else // not __MUSL__ +#ifdef HDC_PCDEBUG + WRITE_LOG(LOG_DEBUG, "SetDevItem, key:%s value:%s", key, value); +#else + string keyValue = key; + string stringBuf = "setprop " + keyValue + " " + value; + system(stringBuf.c_str()); +#endif // HDC_PCDEBUG +#endif // __MUSL__ + return ret; + } + + bool GetDevItem(const char *key, string &out, string preDefine) + { + bool ret = true; + char tmpStringBuf[BUF_SIZE_MEDIUM] = ""; +#if defined __MUSL__ +#ifdef HARMONY_PROJECT + const string strKey(key); + if (GetParameter(key, preDefine.c_str(), tmpStringBuf, BUF_SIZE_MEDIUM) < 0) { + ret = false; + Base::ZeroStruct(tmpStringBuf); + } +#else + string sFailString = Base::StringFormat("Get parameter \"%s\" fail", key); + string stringBuf = "param get " + string(key); + Base::RunPipeComand(stringBuf.c_str(), tmpStringBuf, BUF_SIZE_MEDIUM - 1, true); + if (!strcmp(sFailString.c_str(), tmpStringBuf)) { + // failed + ret = false; + Base::ZeroStruct(tmpStringBuf); + } +#endif +#else // not __MUSL__ +#ifdef HDC_PCDEBUG + WRITE_LOG(LOG_DEBUG, "GetDevItem, key:%s", key); +#else + string stringBuf = "getprop " + string(key); + Base::RunPipeComand(stringBuf.c_str(), tmpStringBuf, BUF_SIZE_MEDIUM - 1, true); +#endif // HDC_PCDEBUG +#endif //__MUSL__ + out = tmpStringBuf; + return ret; + } + + bool CallDoReboot(const char *reason) + { +#ifdef HARMONY_PROJECT + return DoReboot(reason); +#else + // todo + return false; +#endif + } + + bool RebootDevice(const string &cmd) + { +#if defined __MUSL__ + string reason; + if (cmd == "recovery") { + reason = "updater"; + } else if (cmd == "bootloader") { + reason = "updater"; + } + WRITE_LOG(LOG_DEBUG, "DoReboot with args:[%s] for cmd:[%s]", reason.c_str(), cmd.c_str()); + return CallDoReboot(reason.c_str()); +#else + const string rebootProperty = "sys.powerctl"; + string propertyVal; + if (!cmd.size()) { + propertyVal = "reboot"; + } else { + propertyVal = Base::StringFormat("reboot,%s", cmd.c_str()); + } + return SetDevItem(rebootProperty.c_str(), propertyVal.c_str()); +#endif + } +} +} // namespace Hdc diff --git a/src/daemon/system_depend.h b/src/daemon/system_depend.h new file mode 100644 index 0000000000000000000000000000000000000000..a1fc2d3477a80fb796a0596fa03b6c11c5f16068 --- /dev/null +++ b/src/daemon/system_depend.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SYSTEM_DEPEND_H +#define HDC_SYSTEM_DEPEND_H +#include "daemon_common.h" + +namespace Hdc { +namespace SystemDepend { +#ifdef HDC_SUPPORT_FLASHD + // deprecated, remove later + inline bool GetDevItem(const char *key, string value) + { + return false; + }; + inline bool SetDevItem(const char *key, const char *value) + { + return false; + }; +#else + bool GetDevItem(const char *key, string &out, string preDefine = ""); + bool SetDevItem(const char *key, const char *value); +#endif + bool RebootDevice(const string &cmd); +} // namespace SystemDepend +} // namespace Hdc + +#endif // HDC_BASE_H \ No newline at end of file diff --git a/src/daemon/usb_ffs.h b/src/daemon/usb_ffs.h index 1998daaf582d55e5ce38f2b65cc14fd03a1702d8..c8bb1ee0663732fca4ac3bcde90323dab2d9896a 100644 --- a/src/daemon/usb_ffs.h +++ b/src/daemon/usb_ffs.h @@ -173,7 +173,7 @@ static struct UsbFunctionDesc config2 = { }, }; -static const struct { +struct usb_functionfs_desc_v2 { struct usb_functionfs_descs_head_v2 head; __le32 config1Count; __le32 config2Count; @@ -183,36 +183,7 @@ static const struct { struct UsbFuncConfig config3Desc; struct usb_os_desc_header wosHead; struct usb_ext_compat_desc wosDesc; -} __attribute__((packed)) USB_FFS_DESC = { - .head = - { - .magic = LONG_LE(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), - .length = LONG_LE(sizeof(USB_FFS_DESC)), - .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | - FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC - }, - .config1Count = 3, - .config2Count = 3, - .config3Count = 5, - .configWosCount = 1, - .config1Desc = config1, - .config2Desc = config2, - .config3Desc = config3, - .wosHead = { - .interface = 1, - .dwLength = LONG_LE(sizeof(USB_FFS_DESC.wosHead) + sizeof(USB_FFS_DESC.wosDesc)), - .bcdVersion = SHORT_LE(1), - .wIndex = SHORT_LE(4), - .bCount = 1, - .Reserved = 0, - }, - .wosDesc = { - .bFirstInterfaceNumber = 0, - .Reserved1 = 1, - .CompatibleID = { 'W', 'I', 'N', 'U', 'S', 'B', '\0', '\0'}, - .SubCompatibleID = {0}, - .Reserved2 = {0}, - } -}; +} __attribute__((packed)); + } // namespace Hdc #endif diff --git a/src/host/host_usb.cpp b/src/host/host_usb.cpp index 0af6229032dcc624d7b087192244f959da2406c5..f2b50ec1cd1ebc86114d736ca67380289d2e8653 100644 --- a/src/host/host_usb.cpp +++ b/src/host/host_usb.cpp @@ -14,6 +14,7 @@ */ #include "host_usb.h" #include "server.h" +#include namespace Hdc { HdcHostUSB::HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin) @@ -57,55 +58,6 @@ int HdcHostUSB::Initial() return 0; } -// windows/mac's control port reset seems invalid? So we try to use soft interrupt -// if all platform 'libusb_reset_device()' work ok, commit this function and use it replace -// main thread call -void HdcHostUSB::SendUsbSoftReset(HSession hSession, uint32_t sessionIdOld) -{ - struct ResetCtx { - USBHead usbPayloadHeader; - HSession hSession; - }; - ResetCtx *ctxReset = new ResetCtx(); - ctxReset->hSession = hSession; - HUSB hUSB = hSession->hUSB; - - USBHead &usbPayloadHeader = ctxReset->usbPayloadHeader; - usbPayloadHeader.option = USB_OPTION_RESET; - usbPayloadHeader.dataSize = 0; - usbPayloadHeader.sessionId = htonl(sessionIdOld); - if (memcpy_s(usbPayloadHeader.flag, sizeof(usbPayloadHeader.flag), USB_PACKET_FLAG.c_str(), - sizeof(usbPayloadHeader.flag)) != EOK) { - WRITE_LOG(LOG_FATAL, "SendUsbSoftReset memcpy failed"); - delete ctxReset; - return; - } - auto resetUsbCallback = [](struct libusb_transfer *transfer) -> void LIBUSB_CALL { - ResetCtx *ctxReset = (ResetCtx *)transfer->user_data; - if (LIBUSB_TRANSFER_COMPLETED != transfer->status) { - WRITE_LOG(LOG_FATAL, "SendUSBRaw status:%d", transfer->status); - } - --ctxReset->hSession->ref; - ctxReset->hSession->hUSB->sendIOComplete = true; - delete ctxReset; - libusb_free_transfer(transfer); - // has send soft reset, next reset daemon's send - WRITE_LOG(LOG_DEBUG, "Device reset singal send"); - }; - libusb_transfer *transferUsb = libusb_alloc_transfer(0); - libusb_fill_bulk_transfer(transferUsb, hUSB->devHandle, hUSB->epHost, (uint8_t *)&usbPayloadHeader, sizeof(USBHead), - resetUsbCallback, ctxReset, GLOBAL_TIMEOUT * TIME_BASE); - int err = libusb_submit_transfer(transferUsb); - --hSession->ref; - if (err < 0) { - WRITE_LOG(LOG_FATAL, "libusb_submit_transfer failed, err:%d", err); - delete ctxReset; - } else { - hUSB->sendIOComplete = false; - } - hUSB->resetIO = true; -} - bool HdcHostUSB::DetectMyNeed(libusb_device *device, string &sn) { bool ret = false; @@ -311,14 +263,16 @@ int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB) const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k]; if ((ep_desc->bmAttributes & 0x03) == LIBUSB_TRANSFER_TYPE_BULK) { if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) { - hUSB->epDevice = ep_desc->bEndpointAddress; + hUSB->hostBulkIn.endpoint = ep_desc->bEndpointAddress; + hUSB->hostBulkIn.bulkInOut = true; } else { - hUSB->epHost = ep_desc->bEndpointAddress; + hUSB->hostBulkOut.endpoint = ep_desc->bEndpointAddress; hUSB->wMaxPacketSizeSend = ep_desc->wMaxPacketSize; + hUSB->hostBulkOut.bulkInOut = false; } } } - if (hUSB->epDevice == 0 || hUSB->epHost == 0) { + if (hUSB->hostBulkIn.endpoint == 0 || hUSB->hostBulkOut.endpoint == 0) { break; } ret = 0; @@ -328,11 +282,27 @@ int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB) return ret; } -void HdcHostUSB::CancelUsbLoopRead(HUSB hUSB) +// multi-thread calll +void HdcHostUSB::CancelUsbIo(HSession hSession) { - if (hUSB->transferRecv != nullptr && !hUSB->recvIOComplete) { - libusb_cancel_transfer(hUSB->transferRecv); - hUSB->recvIOComplete = true; + WRITE_LOG(LOG_DEBUG, "HostUSB CancelUsbIo, ref:%u", uint32_t(hSession->ref)); + HUSB hUSB = hSession->hUSB; + std::unique_lock lock(hUSB->lockDeviceHandle); + if (!hUSB->hostBulkIn.isShutdown) { + if (!hUSB->hostBulkIn.isComplete) { + libusb_cancel_transfer(hUSB->hostBulkIn.transfer); + hUSB->hostBulkIn.cv.notify_one(); + } else { + hUSB->hostBulkIn.isShutdown = true; + } + } + if (!hUSB->hostBulkOut.isShutdown) { + if (!hUSB->hostBulkOut.isComplete) { + libusb_cancel_transfer(hUSB->hostBulkOut.transfer); + hUSB->hostBulkOut.cv.notify_one(); + } else { + hUSB->hostBulkOut.isShutdown = true; + } } } @@ -368,73 +338,106 @@ int HdcHostUSB::UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int d return index; } -bool HdcHostUSB::SubmitUsbWorkthread(HSession hSession, libusb_transfer *transfer, const int nextReadSize, - const int timeout) +void LIBUSB_CALL HdcHostUSB::USBBulkCallback(struct libusb_transfer *transfer) { - HUSB hUSB = hSession->hUSB; - ++hSession->ref; - libusb_fill_bulk_transfer(transfer, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, nextReadSize, - ReadUSBBulkCallback, hSession, timeout); - int childRet = libusb_submit_transfer(transfer); - if (childRet < 0) { - --hSession->ref; - WRITE_LOG(LOG_FATAL, "libusb_submit_transfer failed, err:%d", childRet); - return false; + auto *ep = static_cast(transfer->user_data); + std::unique_lock lock(ep->mutexIo); + bool retrySumit = false; + int childRet = 0; + do { + if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { + WRITE_LOG(LOG_FATAL, "USBBulkCallback1 failed, ret:%d", transfer->status); + break; + } + if (!ep->bulkInOut && transfer->actual_length != transfer->length) { + transfer->length -= transfer->actual_length; + transfer->buffer += transfer->actual_length; + retrySumit = true; + break; + } + } while (false); + while (retrySumit) { + childRet = libusb_submit_transfer(transfer); + if (childRet != 0) { + WRITE_LOG(LOG_FATAL, "USBBulkCallback2 failed, ret:%d", childRet); + transfer->status = LIBUSB_TRANSFER_ERROR; + break; + } + return; } - return true; + ep->isComplete = true; + ep->cv.notify_one(); } -// at usb 3rd thread -void LIBUSB_CALL HdcHostUSB::ReadUSBBulkCallback(struct libusb_transfer *transfer) +int HdcHostUSB::SubmitUsbBio(HSession hSession, bool sendOrRecv, uint8_t *buf, int bufSize) { - HSession hSession = (HSession)transfer->user_data; - HdcHostUSB *thisClass = (HdcHostUSB *)hSession->classModule; HUSB hUSB = hSession->hUSB; - bool bOK = false; + int timeout = 0; int childRet = 0; - constexpr int infinity = 0; // ignore timeout + int ret = ERR_IO_FAIL; + HostUSBEndpoint *ep = nullptr; - while (true) { - if (!thisClass->modRunning || (hSession->isDead && 0 == hSession->ref)) - break; - if (LIBUSB_TRANSFER_COMPLETED != transfer->status) { - WRITE_LOG(LOG_FATAL, "Host usb not LIBUSB_TRANSFER_COMPLETED, status:%d", transfer->status); - break; - } - childRet - = thisClass->SendToHdcStream(hSession, reinterpret_cast(&hSession->dataPipe[STREAM_MAIN]), - hUSB->bufDevice, transfer->actual_length); + if (sendOrRecv) { + timeout = GLOBAL_TIMEOUT * TIME_BASE; + ep = &hUSB->hostBulkOut; + } else { + timeout = 0; // infinity + ep = &hUSB->hostBulkIn; + } + hUSB->lockDeviceHandle.lock(); + ep->isComplete = false; + do { + std::unique_lock lock(ep->mutexIo); + libusb_fill_bulk_transfer(ep->transfer, hUSB->devHandle, ep->endpoint, buf, bufSize, USBBulkCallback, ep, + timeout); + childRet = libusb_submit_transfer(ep->transfer); + hUSB->lockDeviceHandle.unlock(); if (childRet < 0) { + WRITE_LOG(LOG_FATAL, "SubmitUsbBio libusb_submit_transfer failed, ret:%d", childRet); break; } - // loop self - int nextReadSize = childRet == 0 ? hUSB->wMaxPacketSizeSend : std::min(childRet, Base::GetUsbffsBulkSize()); - if (!thisClass->SubmitUsbWorkthread(hSession, transfer, nextReadSize, infinity)) { + ep->cv.wait(lock, [ep]() { return ep->isComplete; }); + if (ep->transfer->status != 0) { + WRITE_LOG(LOG_FATAL, "SubmitUsbBio transfer failed, status:%d", ep->transfer->status); break; } - bOK = true; - break; - } - if (!bOK) { - auto server = reinterpret_cast(thisClass->clsMainBase); - server->FreeSession(hSession->sessionId); - hUSB->recvIOComplete = true; - WRITE_LOG(LOG_WARN, "ReadUSBBulkCallback failed"); - } - --hSession->ref; // until function finsh, dec ref + ret = ep->transfer->actual_length; + } while (false); + return ret; } -void HdcHostUSB::RegisterReadCallback(HSession hSession) +void HdcHostUSB::BeginUsbRead(HSession hSession) { HUSB hUSB = hSession->hUSB; - if (hSession->isDead || !modRunning) { - return; - } - hSession->hUSB->transferRecv->user_data = hSession; - if (SubmitUsbWorkthread(hSession, hUSB->transferRecv, hUSB->wMaxPacketSizeSend, GLOBAL_TIMEOUT * TIME_BASE)) { - // success - hSession->hUSB->recvIOComplete = false; - } + hUSB->hostBulkIn.isShutdown = false; + hUSB->hostBulkOut.isShutdown = false; + ++hSession->ref; + // loop read + std::thread([this, hSession, hUSB]() { + int childRet = 0; + int nextReadSize = 0; + while (!hSession->isDead) { + // if readIO < wMaxPacketSizeSend, libusb report overflow + nextReadSize = (childRet < hUSB->wMaxPacketSizeSend ? hUSB->wMaxPacketSizeSend + : std::min(childRet, Base::GetUsbffsBulkSize())); + childRet = SubmitUsbBio(hSession, false, hUSB->hostBulkIn.buf, nextReadSize); + if (childRet < 0) { + WRITE_LOG(LOG_FATAL, "Read usb failed, ret:%d", childRet); + break; + } + childRet = SendToHdcStream(hSession, reinterpret_cast(&hSession->dataPipe[STREAM_MAIN]), + hUSB->hostBulkIn.buf, childRet); + if (childRet < 0) { + WRITE_LOG(LOG_FATAL, "SendToHdcStream failed, ret:%d", childRet); + break; + } + } + --hSession->ref; + auto server = reinterpret_cast(clsMainBase); + hUSB->hostBulkIn.isShutdown = true; + server->FreeSession(hSession->sessionId); + WRITE_LOG(LOG_DEBUG, "Usb loop read finish"); + }).detach(); } // ==0 Represents new equipment and is what we need,<0 my need @@ -469,22 +472,13 @@ int HdcHostUSB::OpenDeviceMyNeed(HUSB hUSB) int HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) { int ret = ERR_GENERIC; - int childRet = -1; - int reallySize = 0; - HUSB hUSB = hSession->hUSB; HdcSessionBase *server = reinterpret_cast(hSession->classInstance); ++hSession->ref; - do { - childRet = libusb_bulk_transfer(hUSB->devHandle, hUSB->epHost, data, length, &reallySize, - GLOBAL_TIMEOUT * TIME_BASE); - if (childRet < 0 || reallySize != length) { - WRITE_LOG(LOG_FATAL, "SendUSBRaw failed, ret:%d reallySize:%d", childRet, reallySize); - break; - } - ret = length; - } while (false); + ret = SubmitUsbBio(hSession, true, data, length); if (ret < 0) { - hSession->hUSB->sendIOComplete = true; + WRITE_LOG(LOG_FATAL, "Send usb failed, ret:%d", ret); + CancelUsbIo(hSession); + hSession->hUSB->hostBulkOut.isShutdown = true; server->FreeSession(hSession->sessionId); } --hSession->ref; @@ -540,39 +534,19 @@ bool HdcHostUSB::ReadyForWorkThread(HSession hSession) return true; }; -// Target session USB operates in this thread -void HdcHostUSB::SessionUsbWorkThread(void *arg) -{ - HSession hSession = (HSession)arg; - constexpr uint8_t USB_HANDLE_TIMEOUT = DEVICE_CHECK_INTERVAL / TIME_BASE; - WRITE_LOG(LOG_DEBUG, "SessionUsbWorkThread work thread:%p", uv_thread_self()); - // run until all USB callback finish(ref == 1, It's the only one left) - while (!hSession->isDead || hSession->ref > 1) { - struct timeval zerotime; - zerotime.tv_sec = USB_HANDLE_TIMEOUT; - zerotime.tv_usec = 0; // if == 0,windows will be high CPU load - libusb_handle_events_timeout(hSession->hUSB->ctxUSB, &zerotime); - } - --hSession->ref; - WRITE_LOG(LOG_DEBUG, "Session usb workthread finish"); -} - // Determines that daemonInfo must have the device HSession HdcHostUSB::ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi) { HdcServer *pServer = (HdcServer *)clsMainBase; HUSB hUSB = hSession->hUSB; hUSB->usbMountPoint = pdi->usbMountPoint; - - libusb_init((libusb_context **)&hUSB->ctxUSB); - ++hSession->ref; - uv_thread_create(&hUSB->threadUsbChildWork, SessionUsbWorkThread, hSession); + hUSB->ctxUSB = ctxUSB; if (!FindDeviceByID(hUSB, hUSB->usbMountPoint.c_str(), hUSB->ctxUSB)) { pServer->FreeSession(hSession->sessionId); return nullptr; } UpdateUSBDaemonInfo(hUSB, hSession, STATUS_CONNECTED); - RegisterReadCallback(hSession); + BeginUsbRead(hSession); hUSB->usbMountPoint = pdi->usbMountPoint; WRITE_LOG(LOG_DEBUG, "HSession HdcHostUSB::ConnectDaemon"); diff --git a/src/host/host_usb.h b/src/host/host_usb.h index e32c6191bbd29b7871b56ca1daaa8812c1841fb9..d6c65564340688f9bcd97f8181bbedbea0940261 100644 --- a/src/host/host_usb.h +++ b/src/host/host_usb.h @@ -35,11 +35,10 @@ private: }; static int LIBUSB_CALL HotplugHostUSBCallback(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *userData); - static void UsbWorkThread(void *arg); // 3rd thread - static void SessionUsbWorkThread(void *arg); // 3rd thread + static void UsbWorkThread(void *arg); // 3rd thread static void WatchUsbNodeChange(uv_timer_t *handle); static void KickoutZombie(HSession hSession); - static void LIBUSB_CALL ReadUSBBulkCallback(struct libusb_transfer *transfer); + static void LIBUSB_CALL USBBulkCallback(struct libusb_transfer *transfer); int StartupUSBWork(); int CheckActiveConfig(libusb_device *device, HUSB hUSB); int OpenDeviceMyNeed(HUSB hUSB); @@ -48,20 +47,19 @@ private: bool ReadyForWorkThread(HSession hSession); bool FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB); bool DetectMyNeed(libusb_device *device, string &sn); - void SendUsbSoftReset(HSession hSession, uint32_t sessionIdOld); void RestoreHdcProtocol(HUSB hUsb, const uint8_t *buf, int bufSize); void UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus); - void RegisterReadCallback(HSession hSession); + void BeginUsbRead(HSession hSession); void ReviewUsbNodeLater(string &nodeKey); - void CancelUsbLoopRead(HUSB hUSB); + void CancelUsbIo(HSession hSession); int UsbToHdcProtocol(uv_stream_t *stream, uint8_t *appendData, int dataSize); + int SubmitUsbBio(HSession hSession, bool sendOrRecv, uint8_t *buf, int bufSize); libusb_context *ctxUSB; uv_timer_t devListWatcher; map mapIgnoreDevice; private: - bool SubmitUsbWorkthread(HSession hSession, libusb_transfer *transfer, const int nextReadSize, const int timeout); uv_thread_t threadUsbWork; }; } // namespace Hdc diff --git a/src/host/main.cpp b/src/host/main.cpp index 7e6fbb4129d377a19d55422c214f3b1934964f66..0481b9573234d6c5846901a2fee79161417b69f0 100644 --- a/src/host/main.cpp +++ b/src/host/main.cpp @@ -24,14 +24,14 @@ using namespace HdcTest; #include "server_for_client.h" using namespace Hdc; -static bool g_isServerMode = false; -static bool g_isPullServer = true; -static bool g_isPcDebugRun = false; -static bool g_isTCPorUSB = false; -static auto g_logLevel = LOG_LEVEL_FULL; -static int g_isTestMethod = 0; -static string g_connectKey = ""; -static string g_serverListenString = DEFAULT_SERVER_ADDR; +bool g_isServerMode = false; +bool g_isPullServer = true; +bool g_isPcDebugRun = false; +bool g_isTCPorUSB = false; +bool g_isCustomLoglevel = false; +int g_isTestMethod = 0; +string g_connectKey = ""; +string g_serverListenString = DEFAULT_SERVER_ADDR; namespace Hdc { // return value: 0 == not command, 1 == one command, 2 == double command @@ -251,7 +251,7 @@ bool GetCommandlineOptions(int optArgc, const char *optArgv[]) needExit = true; return needExit; } - g_logLevel = logLevel; + g_isCustomLoglevel = true; Base::SetLogLevel(logLevel); break; } @@ -323,11 +323,13 @@ int main(int argc, const char *argv[]) if (g_isServerMode) { // -m server.Run alone in the background, no -s will be listen loopback address Hdc::Base::RemoveLogFile(); - Base::SetLogLevel(g_logLevel); // default level LOG_LEVEL_FULL Hdc::RunServerMode(g_serverListenString); } else if (g_isPcDebugRun) { Hdc::RunPcDebugMode(g_isPullServer, g_isTCPorUSB, g_isTestMethod); } else { + if (!g_isCustomLoglevel) { + Base::SetLogLevel(LOG_INFO); + } Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer); } WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Main finish main"); diff --git a/src/host/server.cpp b/src/host/server.cpp index c7a4bb07793e0b3932655bdd576077456ae92d2e..b3ee2c858f670867e6e388342ce186f4b1ec0653 100644 --- a/src/host/server.cpp +++ b/src/host/server.cpp @@ -96,7 +96,7 @@ bool HdcServer::PullupServerWin32(const char *path, const char *listenString) runPath = uvPath.substr(uvPath.find_last_of("/\\") + 1); } WRITE_LOG(LOG_DEBUG, "server shortpath:[%s] runPath:[%s]", shortPath, runPath.c_str()); - if (sprintf_s(buf, sizeof(buf), "-l5 -s %s -m", listenString) < 0) { + if (sprintf_s(buf, sizeof(buf), "-l0 -s %s -m", listenString) < 0) { return retVal; } WRITE_LOG(LOG_DEBUG, "Run server in debug-forground, cmd:%s, args:%s", runPath.c_str(), buf); @@ -110,8 +110,8 @@ bool HdcServer::PullupServerWin32(const char *path, const char *listenString) si.wShowWindow = SW_HIDE; #endif if (!CreateProcess(runPath.c_str(), buf, nullptr, nullptr, true, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) { - WRITE_LOG(LOG_WARN, "CreateProcess failed with cmd:%s, args:%s, Error Code %d", - runPath.c_str(), buf, GetLastError()); + WRITE_LOG(LOG_WARN, "CreateProcess failed with cmd:%s, args:%s, Error Code %d", runPath.c_str(), buf, + GetLastError()); retVal = false; } else { retVal = true; @@ -767,7 +767,7 @@ bool HdcServer::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uin ret = TaskCommandDispatch(hTaskInfo, TASK_APP, command, payload, payloadSize); break; default: - ret = false; + // ignore unknow command break; } return ret; diff --git a/src/host/server_for_client.cpp b/src/host/server_for_client.cpp index d861f9ba1db66314e1bbcc12da30121a900cacc2..d2b47e1280ac91cd8f61088b7895bd811710ea4e 100644 --- a/src/host/server_for_client.cpp +++ b/src/host/server_for_client.cpp @@ -457,8 +457,8 @@ bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandI case CMD_UNITY_RUNMODE: case CMD_UNITY_HILOG: case CMD_UNITY_ROOTRUN: - case CMD_TRACK_JPID: - case CMD_UNITY_JPID: { + case CMD_JDWP_TRACK: + case CMD_JDWP_LIST: { if (!SendToDaemon(hChannel, formatCommand->cmdFlag, reinterpret_cast(const_cast(formatCommand->parameters.c_str())), sizeSend)) { diff --git a/src/host/translate.cpp b/src/host/translate.cpp index ed61853facfd28707c3a5c28402c9b4ece839cc5..e68066472f20ba3f5950cb2e4e2553718264614c 100644 --- a/src/host/translate.cpp +++ b/src/host/translate.cpp @@ -237,9 +237,9 @@ namespace TranslateCommand { } else if (!strcmp(input.c_str(), CMDSTR_TARGET_MOUNT.c_str())) { outCmd->cmdFlag = CMD_UNITY_REMOUNT; } else if (!strcmp(input.c_str(), CMDSTR_LIST_JDWP.c_str())) { - outCmd->cmdFlag = CMD_UNITY_JPID; + outCmd->cmdFlag = CMD_JDWP_LIST; } else if (!strcmp(input.c_str(), CMDSTR_TRACK_JDWP.c_str())) { - outCmd->cmdFlag = CMD_TRACK_JPID; + outCmd->cmdFlag = CMD_JDWP_TRACK; } else if (!strncmp(input.c_str(), CMDSTR_TARGET_REBOOT.c_str(), CMDSTR_TARGET_REBOOT.size())) { TargetReboot(input.c_str(), outCmd); } else if (!strncmp(input.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size())) { diff --git a/src/test/ut_mod.cpp b/src/test/ut_mod.cpp index d6315e09c2e7f22dfb6fd8f7c096bf91d03d3cc9..64ace3bd879d24a488f452b0d2509333f1b7581d 100644 --- a/src/test/ut_mod.cpp +++ b/src/test/ut_mod.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ #include "ut_mod.h" +#include +#include using namespace Hdc; namespace HdcTest { @@ -109,6 +111,16 @@ bool TestShellExecute(void *runtimePtr) return ret; } +vector Md5Sum(uint8_t *buf, int size) +{ + vector ret; + uint8_t md5Hash[MD5_DIGEST_LENGTH] = { 0 }; + if (EVP_Digest(buf, size, md5Hash, NULL, EVP_md5(), NULL)) { + ret.insert(ret.begin(), md5Hash, md5Hash + sizeof(md5Hash)); + } + return ret; +} + // file send like recv in our code, so just test send is enough bool TestFileCommand(void *runtimePtr) { @@ -132,8 +144,8 @@ bool TestFileCommand(void *runtimePtr) if ((sizeRemote = Base::ReadBinFile(remoteFile.c_str(), (void **)&bufRemote, 0)) < 0) { break; }; - auto localHash = Base::Md5Sum(bufLocal, sizeLocal); - auto remoteHash = Base::Md5Sum(bufRemote, sizeRemote); + auto localHash = Md5Sum(bufLocal, sizeLocal); + auto remoteHash = Md5Sum(bufRemote, sizeRemote); if (memcmp(localHash.data(), remoteHash.data(), localHash.size())) { break; }