diff --git a/usb/gadget/function/include/usb_mtp.h b/usb/gadget/function/include/usb_mtp.h deleted file mode 100644 index c380f78b84..0000000000 --- a/usb/gadget/function/include/usb_mtp.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2022 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 HDF_USB_MTP_H -#define HDF_USB_MTP_H - -#include "data_fifo.h" -#include "hdf_base.h" -#include "hdf_device_desc.h" -#include "osal_atomic.h" -#include "osal_mutex.h" -#include "osal_spinlock.h" -#include "usb_ddk.h" -#include "usb_object.h" -#include "usbfn_request.h" - -#define MTP_MAX_FILE_SIZE 0xFFFFFFFFL - -enum UsbMtpCmd { - USB_MTP_OPEN = 0, - USB_MTP_CLOSE, - USB_MTP_READ, - USB_MTP_WRITE, - USB_MTP_SEND_FILE, - USB_MTP_RECEIVE_FILE, - USB_MTP_SEND_EVENT, - USB_MTP_SEND_FILE_WITH_HEADER, - USB_MTP_INIT = 100, /* alloc MTP resource */ - USB_MTP_RELEASE = 101, /* release MTP resource */ -}; - -/* used in hdi interface, application */ -struct UsbMtpFileRange { - /* file descriptor for file to transfer */ - int fd; - /* offset in file for start of transfer */ - int64_t offset; - /* number of bytes to transfer */ - int64_t length; - /* MTP command ID for data header, used only for MTP_SEND_FILE_WITH_HEADER */ - uint16_t command; - /* MTP transaction ID for data header, used only for MTP_SEND_FILE_WITH_HEADER */ - uint32_t transactionId; -}; - -/* used in driver, hdi interface, application */ -struct UsbMtpEvent { - /* size of the event */ - size_t length; - /* event data to send */ - void *data; -}; - -/* used in driver, hdi interface, subset of struct UsbMtpFileRange */ -struct UsbMtpDriverFileRange { - /* offset in file for start of transfer */ - int64_t offset; - /* number of bytes to transfer */ - int64_t length; - /* MTP command ID for data header, used only for MTP_SEND_FILE_WITH_HEADER */ - uint16_t command; - /* MTP transaction ID for data header, used only for MTP_SEND_FILE_WITH_HEADER */ - uint32_t transactionId; -}; - -struct UsbMtpDataHeader { - uint32_t length; - uint16_t type; /* defined mtp data type */ - uint16_t cmdCode; /* Operation, Response or Event Code in mtp */ - uint32_t transactionId; -}; - -struct UsbMtpDataPacket { - struct UsbMtpDataHeader header; - void *payload; -}; - -struct UsbMtpPipe { - uint8_t id; - uint16_t maxPacketSize; - struct UsbFnInterface *ctrlIface; -}; - -struct UsbMtpInterface { - struct UsbFnInterface *fn; - UsbFnInterfaceHandle handle; -}; - -struct UsbMtpPort { - struct UsbMtpDevice *mtpDev; - struct OsalMutex lock; - struct DListHead readPool; - struct DListHead readQueue; - int32_t readStarted; - int32_t readAllocated; - struct DataFifo readFifo; - struct DListHead writePool; - int32_t writeStarted; - int32_t writeAllocated; - struct DataFifo writeFifo; - bool writeBusy; - bool suspended; - bool startDelayed; - int32_t refCount; -}; - -struct MtpNotifyMethod; -struct UsbMtpDevice { - struct IDeviceIoService ioService; - struct HdfDeviceObject *hdfDevice; - struct UsbFnDevice *fnDev; - struct UsbMtpInterface ctrlIface; - struct UsbMtpInterface intrIface; - struct UsbMtpInterface dataIface; - struct UsbMtpPipe notifyPipe; - struct UsbMtpPipe dataInPipe; - struct UsbMtpPipe dataOutPipe; - struct DListHead ctrlPool; - int32_t ctrlReqNum; - struct UsbFnRequest *notifyReq; - struct OsalMutex mutex; - uint8_t mtpState; /* record mtp state, example: MTP_STATE_OFFLINE */ - const char *udcName; - bool initFlag; - bool isSendEventDone; - struct UsbMtpPort *mtpPort; - struct MtpNotifyMethod *notifyUser; - void *xferData; - int64_t xferFileOffset; - int64_t xferFileLength; - uint8_t xferSendHeader; /* two value: 0 1 */ - uint16_t xferCommand; /* refer to struct UsbMtpFileRange.command */ - uint32_t xferTransactionId; /* refer to struct UsbMtpFileRange.transactionId */ - int xferResult; -}; - -struct CtrlInfo { - uint8_t request; - struct UsbMtpDevice *mtpDev; -}; - -struct MtpNotifyMethod { - void (*Connect)(struct UsbMtpDevice *mtpDev); - void (*Disconnect)(struct UsbMtpDevice *mtpDev); -}; - -#endif /* HDF_USB_MTP_H */ diff --git a/usb/gadget/function/mtp/include/usbfn_mtp_impl.h b/usb/gadget/function/mtp/include/usbfn_mtp_impl.h index 7fc392c4a4..cc605e1ed6 100644 --- a/usb/gadget/function/mtp/include/usbfn_mtp_impl.h +++ b/usb/gadget/function/mtp/include/usbfn_mtp_impl.h @@ -17,6 +17,7 @@ #define OHOS_HDI_USB_GADGET_MTP_V1_0_USBFNMTPIMPL_H #include +#include #include "data_fifo.h" #include "hdf_base.h" @@ -126,11 +127,10 @@ struct UsbMtpDevice { struct UsbFnRequest *notifyReq; struct UsbMtpPort *mtpPort; const char *udcName; - int64_t asyncRecvFileActual; - int64_t asyncRecvFileExpect; - int64_t asyncRecvFileTruncate; /* total file length: offset + length */ - int64_t asyncSendFileActual; /* already send actual */ - int64_t asyncSendFileExpect; /* already send expect */ + uint64_t asyncRecvFileActual; + uint64_t asyncRecvFileExpect; + uint64_t asyncSendFileActual; /* already send actual */ + uint64_t asyncSendFileExpect; /* already send expect */ uint8_t asyncXferFile; uint8_t needZLP; uint32_t asyncRecvWriteTempCount; @@ -141,8 +141,8 @@ struct UsbMtpDevice { uint16_t xferCommand; /* refer to struct UsbMtpFileRange.command */ uint32_t xferTransactionId; /* refer to struct UsbMtpFileRange.transactionId */ int32_t xferFd; - int64_t xferFileOffset; - int64_t xferFileLength; + uint64_t xferFileOffset; + uint64_t xferFileLength; }; struct CtrlInfo { @@ -232,16 +232,14 @@ private: void UsbMtpDeviceFreeNotifyRequest(); int32_t WriteEx(const std::vector &data, uint8_t sendZLP, uint32_t &xferActual); - int32_t UsbMtpPortSendFileFillFirstReq(struct UsbFnRequest *req, int64_t &oneReqLeft); + int32_t UsbMtpPortSendFileFillFirstReq(struct UsbFnRequest *req, uint64_t &oneReqLeft); int32_t UsbMtpPortSendFileEx(); - int32_t UsbMtpPortSendFileLeftAsync(int64_t oneReqLeft); + int32_t UsbMtpPortSendFileLeftAsync(uint64_t oneReqLeft); int32_t ReceiveFileEx(); uint32_t BufCopyToVector(void *buf, uint32_t bufSize, std::vector &vectorData); uint32_t BufCopyFromVector( void *buf, uint32_t bufSize, const std::vector &vectorData, uint32_t vectorOffset); - uint32_t BufCopyToFile(void *buf, uint32_t bufSize, int32_t fd); - uint32_t BufCopyFromFile(void *buf, uint32_t bufSize, int32_t fd); static struct UsbMtpDevice *mtpDev_; static struct UsbMtpPort *mtpPort_; diff --git a/usb/gadget/function/mtp/src/usbfn_mtp_impl.cpp b/usb/gadget/function/mtp/src/usbfn_mtp_impl.cpp index b27d8ec441..afcd03dfc9 100755 --- a/usb/gadget/function/mtp/src/usbfn_mtp_impl.cpp +++ b/usb/gadget/function/mtp/src/usbfn_mtp_impl.cpp @@ -105,7 +105,7 @@ sem_t UsbfnMtpImpl::asyncReq_ {0}; constexpr uint32_t BULK_IN_TIMEOUT_JIFFIES = 0; /* sync timeout, set to 0 means wait forever */ constexpr uint32_t BULK_OUT_TIMEOUT_JIFFIES = 0; /* sync timeout, set to 0 means wait forever */ constexpr uint32_t INTR_IN_TIMEOUT_JIFFIES = 0; /* sync timeout, set to 0 means wait forever */ -constexpr int64_t MTP_MAX_FILE_SIZE = 0xFFFFFFFFLL; +constexpr uint64_t MTP_MAX_FILE_SIZE = 0xFFFFFFFFULL; constexpr uint32_t WRITE_FILE_TEMP_SLICE = 100 * 1024; /* 100KB */ enum UsbMtpNeedZeroLengthPacket { @@ -139,7 +139,7 @@ void UsbfnMtpImpl::UsbFnRequestReadComplete(uint8_t pipe, struct UsbFnRequest *r } int32_t ret = UsbMtpPortRxPush(mtpPort, req); if (ret != HDF_SUCCESS) { - HDF_LOGW("%{public}s: rx push failed(%{%{public}d/%{public}d}): %{public}d, state=%{public}d", __func__, + HDF_LOGW("%{public}s: rx push failed(%{%{public}d/%{public}d}): %{public}d, state=%{public}hhu", __func__, mtpPort->readStarted, mtpPort->readAllocated, ret, mtpPort->mtpDev->mtpState); } if (mtpPort->readStarted == 0 && mtpPort->writeStarted == 0 && mtpPort->mtpDev->mtpState == MTP_STATE_CANCELED) { @@ -164,7 +164,7 @@ void UsbfnMtpImpl::UsbFnRequestWriteComplete(uint8_t pipe, struct UsbFnRequest * mtpPort->writeStarted--; int32_t ret = UsbMtpPortTxReqCheck(mtpPort, req); if (ret != HDF_SUCCESS) { - HDF_LOGW("%{public}s: tx check failed(%{%{public}d/%{public}d}): %{public}d, state=%{public}d", __func__, + HDF_LOGW("%{public}s: tx check failed(%{%{public}d/%{public}d}): %{public}d, state=%{public}hhu", __func__, mtpPort->readStarted, mtpPort->readAllocated, ret, mtpPort->mtpDev->mtpState); } if (mtpPort->readStarted == 0 && mtpPort->writeStarted == 0 && mtpPort->mtpDev->mtpState == MTP_STATE_CANCELED) { @@ -214,12 +214,12 @@ int32_t UsbfnMtpImpl::UsbMtpPortTxReqCheck(struct UsbMtpPort *mtpPort, struct Us struct UsbMtpDevice *mtpDev = mtpPort->mtpDev; switch (req->status) { case USB_REQUEST_COMPLETED: - mtpDev->asyncSendFileActual += req->actual; + mtpDev->asyncSendFileActual += static_cast(req->actual); if (mtpDev->asyncSendFileActual == mtpDev->xferFileLength && ((req->actual == 0 && mtpDev->needZLP == ZLP_TRY) || mtpDev->needZLP == ZLP_NO_NEED)) { - HDF_LOGI("%{public}s: async tx done: req(%{public}d/%{public}d)%{public}d/%{public}d, send " - "%{public}" PRId64 "/%{public}" PRId64 "/%{public}" PRId64 ", ZLP=%{public}d", - __func__, mtpPort->writeStarted, mtpPort->writeAllocated, req->actual, req->length, + HDF_LOGV("%{public}s: async tx done: req(%{public}d/%{public}d)%{public}u/%{public}u, send " + "%{public}" PRIu64 "/%{public}" PRIu64 "/%{public}" PRIu64 ", ZLP=%{public}hhu", __func__, + mtpPort->writeStarted, mtpPort->writeAllocated, req->actual, req->length, mtpDev->asyncSendFileExpect, mtpDev->asyncSendFileActual, mtpDev->xferFileLength, mtpDev->needZLP); sem_post(&asyncReq_); return HDF_SUCCESS; @@ -257,9 +257,9 @@ int32_t UsbfnMtpImpl::UsbMtpPortProcessLastTxPacket(struct UsbMtpPort *mtpPort, int32_t UsbfnMtpImpl::UsbMtpPortSubmitAsyncTxReq(struct UsbMtpPort *mtpPort, struct UsbFnRequest *req) { - size_t readRet = read(mtpPort->mtpDev->xferFd, req->buf, req->length); - if (readRet != req->length) { - HDF_LOGE("%{public}s: read failed: %{public}zu < %{public}d", __func__, readRet, req->length); + ssize_t readRet = read(mtpPort->mtpDev->xferFd, req->buf, static_cast(req->length)); + if (readRet != static_cast(req->length)) { + HDF_LOGE("%{public}s: read failed: %{public}zd < %{public}u", __func__, readRet, req->length); return HDF_FAILURE; } DListRemove(&req->list); @@ -285,7 +285,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortStartTxAsync(struct UsbMtpPort *mtpPort, bool ca struct UsbMtpDevice *mtpDev = mtpPort->mtpDev; struct DListHead *pool = &mtpPort->writePool; - int64_t reqMax = static_cast(mtpDev->dataInPipe.maxPacketSize); + uint64_t reqMax = static_cast(mtpDev->dataInPipe.maxPacketSize); while (!DListIsEmpty(pool)) { if (mtpDev->needZLP == ZLP_NO_NEED) { if (mtpDev->asyncSendFileExpect >= mtpDev->xferFileLength) { @@ -311,7 +311,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortStartTxAsync(struct UsbMtpPort *mtpPort, bool ca sem_post(&asyncReq_); return ret; } - mtpDev->asyncSendFileExpect += static_cast(req->length); + mtpDev->asyncSendFileExpect += static_cast(req->length); } return HDF_SUCCESS; } @@ -614,7 +614,7 @@ int32_t UsbfnMtpImpl::UsbMtpDeviceEnable(struct UsbMtpDevice *mtpDev) return HDF_DEV_ERR_DEV_INIT_FAIL; } - /* the mtpDev is enabled, start the io stream */ + /* the mtpDev is enabled, ready for transfer */ mtpDev->mtpState = MTP_STATE_READY; mtpPort->startDelayed = true; return HDF_SUCCESS; @@ -628,7 +628,7 @@ int32_t UsbfnMtpImpl::UsbMtpDeviceDisable(struct UsbMtpDevice *mtpDev) return HDF_DEV_ERR_DEV_INIT_FAIL; } - /* The udc has been disabled due to some problem */ + /* Disable event: The USB Device Controller has been disabled due to some problem */ mtpPort->startDelayed = false; mtpDev->mtpState = MTP_STATE_OFFLINE; return HDF_SUCCESS; @@ -642,7 +642,7 @@ void UsbfnMtpImpl::UsbMtpDeviceEp0EventDispatch(struct UsbFnEvent *event) } struct UsbMtpDevice *mtpDev = static_cast(event->context); - HDF_LOGI("%{public}s EP0 event: [%{public}d], state=%{public}d", __func__, event->type, mtpDev->mtpState); + HDF_LOGI("%{public}s EP0 event: [%{public}d], state=%{public}hhu", __func__, event->type, mtpDev->mtpState); switch (event->type) { case USBFN_STATE_BIND: HDF_LOGI("%{public}s: EP0 [bind] ignore", __func__); @@ -685,10 +685,9 @@ int32_t UsbfnMtpImpl::UsbMtpDeviceParseEachPipe(struct UsbMtpInterface &iface) HDF_LOGE("%{public}s: ifce is invalid", __func__); return HDF_ERR_INVALID_PARAM; } - HDF_LOGI("%{public}s: interface: idx=%{public}d numPipes=%{public}d ifClass=%{public}d subclass=%{public}d " - "prtocol=%{public}d cfgIndex=%{public}d ", - __func__, fnIface->info.index, fnIface->info.numPipes, fnIface->info.interfaceClass, fnIface->info.subclass, - fnIface->info.protocol, fnIface->info.configIndex); + HDF_LOGI("%{public}s: interface: idx=%{public}hhu numPipes=%{public}hhu ifClass=%{public}hhu subclass=%{public}hhu " + "protocol=%{public}hhu cfgIndex=%{public}hhu", __func__, fnIface->info.index, fnIface->info.numPipes, + fnIface->info.interfaceClass, fnIface->info.subclass, fnIface->info.protocol, fnIface->info.configIndex); for (uint32_t i = 0; i < fnIface->info.numPipes; ++i) { struct UsbFnPipeInfo pipeInfo; (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo)); @@ -697,8 +696,7 @@ int32_t UsbfnMtpImpl::UsbMtpDeviceParseEachPipe(struct UsbMtpInterface &iface) HDF_LOGE("%{public}s: get pipe info error", __func__); return ret; } - HDF_LOGI("%{public}s: pipe info detail: id=%{public}d type=%{public}d dir=%{public}d maxPacketSize=%{public}d " - "interval=%{public}d", + HDF_LOGI("%{public}s: pipe: id=%{public}d type=%{public}d dir=%{public}d max=%{public}d interval=%{public}d", __func__, pipeInfo.id, pipeInfo.type, pipeInfo.dir, pipeInfo.maxPacketSize, pipeInfo.interval); switch (pipeInfo.type) { case USB_PIPE_TYPE_INTERRUPT: @@ -746,7 +744,6 @@ bool UsbfnMtpImpl::UsbFnInterfaceIsUsbMtpPtpDevice(struct UsbFnInterface *iface) { HDF_LOGI("%{public}s: iIf=%{public}d ifClass=%{public}d, subclass=%{public}d, protocol=%{public}d", __func__, iface->info.configIndex, iface->info.interfaceClass, iface->info.subclass, iface->info.protocol); - if (iface->info.interfaceClass == USB_MTP_DEVICE_CLASS && iface->info.subclass == USB_MTP_DEVICE_SUBCLASS && iface->info.protocol == USB_MTP_DEVICE_PROTOCOL) { HDF_LOGI("%{public}s: this is mtp device", __func__); @@ -1001,25 +998,18 @@ uint32_t UsbfnMtpImpl::BufCopyFromVector( return count; } -uint32_t UsbfnMtpImpl::BufCopyToFile(void *buf, uint32_t bufSize, int32_t fd) -{ - return write(fd, buf, bufSize); -} - -uint32_t UsbfnMtpImpl::BufCopyFromFile(void *buf, uint32_t bufSize, int32_t fd) -{ - return read(fd, buf, bufSize); -} - int32_t UsbfnMtpImpl::Read(std::vector &data) { if (mtpPort_ == nullptr || mtpDev_ == nullptr || mtpDev_->initFlag == false) { HDF_LOGE("%{public}s: no init", __func__); return HDF_DEV_ERR_DEV_INIT_FAIL; } - std::lock_guard guard(mtpRunning_); + if (mtpDev_->mtpState == MTP_STATE_OFFLINE) { + HDF_LOGE("%{public}s: device disconnect, no-operation", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } struct DListHead *pool = &mtpPort_->readPool; struct UsbFnRequest *req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); if (req == nullptr) { @@ -1039,7 +1029,7 @@ int32_t UsbfnMtpImpl::Read(std::vector &data) (void)BufCopyToVector(req->buf, req->actual, data); break; case USB_REQUEST_NO_DEVICE: - HDF_LOGV("%{public}s: device disconnected", __func__); + HDF_LOGE("%{public}s: device disconnect", __func__); mtpDev_->mtpState = MTP_STATE_OFFLINE; return HDF_DEV_ERR_NO_DEVICE; default: @@ -1072,8 +1062,7 @@ int32_t UsbfnMtpImpl::WriteEx(const std::vector &data, uint8_t needZLP, ret = UsbFnSubmitRequestSync(req, BULK_IN_TIMEOUT_JIFFIES); DListInsertTail(&req->list, pool); if (needZLP == ZLP_TRY) { - needZLP = ZLP_DONE; - HDF_LOGI("%{public}s: send zero packet done: %{public}d", __func__, ret); + HDF_LOGV("%{public}s: send zero packet done: %{public}d", __func__, ret); return ret; } if (ret != HDF_SUCCESS) { @@ -1107,7 +1096,7 @@ int32_t UsbfnMtpImpl::Write(const std::vector &data) std::lock_guard guard(mtpRunning_); if (mtpDev_->mtpState == MTP_STATE_OFFLINE) { - HDF_LOGE("%{public}s: device disconnect, stop rx", __func__); + HDF_LOGE("%{public}s: device disconnect", __func__); return HDF_DEV_ERR_NO_DEVICE; } if (data.size() == 0) { @@ -1139,7 +1128,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortRxCheckReq(struct UsbMtpPort *mtpPort, struct Us return HDF_FAILURE; } if (req->actual == 0) { - HDF_LOGI("%{public}s: recv ZLP packet, end xfer", __func__); + HDF_LOGV("%{public}s: recv ZLP packet, end xfer", __func__); mtpDev->asyncXferFile = ASYNC_XFER_FILE_DONE; return HDF_SUCCESS; } @@ -1155,19 +1144,17 @@ int32_t UsbfnMtpImpl::UsbMtpPortRxCheckReq(struct UsbMtpPort *mtpPort, struct Us } /* specific length */ if (req->actual < req->length) { - HDF_LOGE("%{public}s: normal packet(error): reqActual=%{public}d reqLen=%{public}d", __func__, req->actual, - req->length); + HDF_LOGE("%{public}s: normal packet(error): %{public}u < %{public}u", __func__, req->actual, req->length); return HDF_FAILURE; } if (req->actual != 0) { writeToFile = true; } - if (mtpDev->asyncRecvFileActual + req->actual == mtpDev->xferFileLength) { + if (mtpDev->asyncRecvFileActual + static_cast(req->actual) == mtpDev->xferFileLength) { mtpDev->asyncXferFile = ASYNC_XFER_FILE_DONE; - HDF_LOGI("%{public}s: last packet: req(%{public}d/%{public}d) %{public}d/%{public}d, recv %{public}" PRId64 - "/%{public}" PRId64 "/%{public}" PRId64 "", - __func__, mtpPort->readStarted, mtpPort->readAllocated, req->actual, req->length, - mtpDev->asyncRecvFileExpect, mtpDev->asyncRecvFileActual, mtpDev->xferFileLength); + HDF_LOGV("%{public}s: last packet: req(%{public}d/%{public}d)%{public}u/%{public}u, recv %{public}" PRIu64 + "/%{public}" PRIu64 "/%{public}" PRIu64 "", __func__, mtpPort->readStarted, mtpPort->readAllocated, + req->actual, req->length, mtpDev->asyncRecvFileExpect, mtpDev->asyncRecvFileActual, mtpDev->xferFileLength); } return HDF_SUCCESS; } @@ -1175,14 +1162,13 @@ int32_t UsbfnMtpImpl::UsbMtpPortRxCheckReq(struct UsbMtpPort *mtpPort, struct Us int32_t UsbfnMtpImpl::UsbMtpPortProcessAsyncRxDone(struct UsbMtpPort *mtpPort) { struct UsbMtpDevice *mtpDev = mtpPort->mtpDev; - HDF_LOGI("%{public}s: recv done, ignore other packet(%{public}d/%{public}d):%{public}" PRId64 "/%{public}" PRId64 - "/%{public}" PRId64 "", - __func__, mtpPort->readStarted, mtpPort->readAllocated, mtpDev->asyncRecvFileExpect, + HDF_LOGV("%{public}s: recv done, ignore other packet(%{public}d/%{public}d):%{public}" PRIu64 "/%{public}" PRIu64 + "/%{public}" PRIu64 "", __func__, mtpPort->readStarted, mtpPort->readAllocated, mtpDev->asyncRecvFileExpect, mtpDev->asyncRecvFileActual, mtpDev->xferFileLength); if (mtpPort->readStarted == 0) { sem_post(&asyncReq_); } else if (mtpDev->xferFileLength == MTP_MAX_FILE_SIZE) { - HDF_LOGI("%{public}s: cancel redundant req", __func__); + HDF_LOGV("%{public}s: cancel redundant req", __func__); while (!DListIsEmpty(&mtpPort->readQueue)) { struct UsbFnRequest *req = DLIST_FIRST_ENTRY(&mtpPort->readQueue, struct UsbFnRequest, list); (void)UsbFnCancelRequest(req); @@ -1215,22 +1201,22 @@ int32_t UsbfnMtpImpl::UsbMtpPortRxPush(struct UsbMtpPort *mtpPort, struct UsbFnR } mtpDev->asyncRecvWriteTempCount += req->actual; if (mtpDev->asyncRecvWriteTempCount >= WRITE_FILE_TEMP_SLICE) { - size_t writeRet = - write(mtpDev->xferFd, static_cast(mtpDev->asyncRecvWriteTempContent), WRITE_FILE_TEMP_SLICE); - if (writeRet != WRITE_FILE_TEMP_SLICE) { - HDF_LOGE("%{public}s: write temp failed", __func__); + ssize_t writeRet = write(mtpDev->xferFd, static_cast(mtpDev->asyncRecvWriteTempContent), + static_cast(WRITE_FILE_TEMP_SLICE)); + if (writeRet != static_cast(WRITE_FILE_TEMP_SLICE)) { + HDF_LOGE("%{public}s: write temp failed: %{public}zd", __func__, writeRet); mtpDev->asyncXferFile = ASYNC_XFER_FILE_DONE; sem_post(&asyncReq_); return HDF_FAILURE; } mtpDev->asyncRecvWriteTempCount = 0; } - mtpDev->asyncRecvFileActual += req->actual; + mtpDev->asyncRecvFileActual += static_cast(req->actual); } if (mtpDev->asyncXferFile == ASYNC_XFER_FILE_DONE) { - size_t writeRet = write( - mtpDev->xferFd, static_cast(mtpDev->asyncRecvWriteTempContent), mtpDev->asyncRecvWriteTempCount); - if (writeRet != mtpDev->asyncRecvWriteTempCount) { + ssize_t writeRet = write(mtpDev->xferFd, static_cast(mtpDev->asyncRecvWriteTempContent), + static_cast(mtpDev->asyncRecvWriteTempCount)); + if (writeRet != static_cast(mtpDev->asyncRecvWriteTempCount)) { HDF_LOGE("%{public}s: write last failed: %{public}d", __func__, mtpDev->asyncRecvWriteTempCount); mtpDev->asyncXferFile = ASYNC_XFER_FILE_DONE; sem_post(&asyncReq_); @@ -1249,7 +1235,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortStartSubmitRxReq(struct UsbMtpPort *mtpPort, boo struct DListHead *pool = &mtpPort->readPool; struct UsbMtpDevice *mtpDev = mtpPort->mtpDev; struct UsbFnRequest *req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); - int64_t reqMax = static_cast(mtpDev->dataOutPipe.maxPacketSize); + uint64_t reqMax = static_cast(mtpDev->dataOutPipe.maxPacketSize); if (mtpDev->asyncRecvFileExpect + reqMax < mtpDev->xferFileLength) { req->length = static_cast(mtpDev->dataOutPipe.maxPacketSize); } else { @@ -1271,7 +1257,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortStartSubmitRxReq(struct UsbMtpPort *mtpPort, boo return ret; } mtpPort->readStarted++; - mtpDev->asyncRecvFileExpect += static_cast(req->length); + mtpDev->asyncRecvFileExpect += static_cast(req->length); return HDF_SUCCESS; } @@ -1295,10 +1281,10 @@ int32_t UsbfnMtpImpl::UsbMtpPortStartRxAsync(struct UsbMtpPort *mtpPort) } if ((mtpDev->xferFileLength != MTP_MAX_FILE_SIZE && mtpDev->asyncRecvFileExpect >= mtpDev->xferFileLength) || mtpDev->asyncXferFile == ASYNC_XFER_FILE_DONE) { - HDF_LOGW("%{public}s: no need rx req[%{public}d/%{public}d]:%{public}" PRId64 "/%{public}" PRId64 - "/%{public}" PRId64 ", xfer=%{public}d", - __func__, mtpPort->readStarted, mtpPort->readAllocated, mtpDev->asyncRecvFileExpect, - mtpDev->asyncRecvFileActual, mtpDev->xferFileLength, mtpDev->asyncXferFile); + HDF_LOGV("%{public}s: no need rx req[%{public}d/%{public}d]:%{public}" PRIu64 "/%{public}" PRIu64 + "/%{public}" PRIu64 ", xfer=%{public}hhu", __func__, mtpPort->readStarted, mtpPort->readAllocated, + mtpDev->asyncRecvFileExpect, mtpDev->asyncRecvFileActual, mtpDev->xferFileLength, + mtpDev->asyncXferFile); return ret; } ret = UsbMtpPortStartSubmitRxReq(mtpPort, false); @@ -1321,7 +1307,7 @@ int32_t UsbfnMtpImpl::ReceiveFileEx() HDF_LOGE("%{public}s: start async tx failed: %{public}d", __func__, ret); return HDF_ERR_IO; } - HDF_LOGI("%{public}s: wait async rx", __func__); + HDF_LOGV("%{public}s: wait async rx", __func__); sem_wait(&asyncReq_); (void)OsalMemFree(mtpDev_->asyncRecvWriteTempContent); if (syncfs(mtpDev_->xferFd) != 0) { @@ -1329,7 +1315,7 @@ int32_t UsbfnMtpImpl::ReceiveFileEx() return HDF_ERR_IO; } if (mtpDev_->xferFileLength == MTP_MAX_FILE_SIZE) { - HDF_LOGI("%{public}s: no specific length, reset state", __func__); + HDF_LOGV("%{public}s: no specific length, reset state", __func__); mtpDev_->mtpState = MTP_STATE_READY; return mtpDev_->asyncXferFile == ASYNC_XFER_FILE_DONE ? HDF_SUCCESS : HDF_ERR_IO; } @@ -1342,14 +1328,12 @@ int32_t UsbfnMtpImpl::ReceiveFile(const UsbFnMtpFileSlice &mfs) HDF_LOGE("%{public}s: no init", __func__); return HDF_DEV_ERR_DEV_INIT_FAIL; } - std::lock_guard guard(mtpRunning_); - HDF_LOGI("%{public}s: info: cmd=%{public}d, transid=%{public}d, len=%{public}" PRId64 " offset=%{public}" PRId64 - ", state=%{public}d", - __func__, mfs.command, mfs.transactionId, mfs.length, mfs.offset, mtpDev_->mtpState); + HDF_LOGV("%{public}s: info: cmd=%{public}d, transid=%{public}d, len=%{public}" PRId64 " offset=%{public}" PRId64 + ", state=%{public}hhu", __func__, mfs.command, mfs.transactionId, mfs.length, mfs.offset, mtpDev_->mtpState); if (mtpDev_->mtpState == MTP_STATE_OFFLINE) { - HDF_LOGE("%{public}s: device disconnect, stop rx", __func__); + HDF_LOGE("%{public}s: device disconnect", __func__); return HDF_DEV_ERR_NO_DEVICE; } if (mfs.length <= 0) { @@ -1358,12 +1342,12 @@ int32_t UsbfnMtpImpl::ReceiveFile(const UsbFnMtpFileSlice &mfs) } mtpDev_->xferFd = mfs.fd; mtpDev_->xferFileOffset = mfs.offset; - mtpDev_->xferFileLength = mfs.length; + mtpDev_->xferFileLength = static_cast(mfs.length); lseek(mfs.fd, mfs.offset, SEEK_SET); mtpDev_->asyncRecvFileActual = 0; mtpDev_->asyncRecvFileExpect = 0; mtpDev_->needZLP = ZLP_NO_NEED; - if ((mfs.length & (mtpDev_->dataInPipe.maxPacketSize - 1)) == 0) { + if ((mtpDev_->xferFileLength & (mtpDev_->dataInPipe.maxPacketSize - 1)) == 0) { mtpDev_->needZLP = ZLP_NEED; } int32_t ret = ReceiveFileEx(); @@ -1373,11 +1357,11 @@ int32_t UsbfnMtpImpl::ReceiveFile(const UsbFnMtpFileSlice &mfs) return ret; } -int32_t UsbfnMtpImpl::UsbMtpPortSendFileFillFirstReq(struct UsbFnRequest *req, int64_t &oneReqLeft) +int32_t UsbfnMtpImpl::UsbMtpPortSendFileFillFirstReq(struct UsbFnRequest *req, uint64_t &oneReqLeft) { - int64_t hdrSize = static_cast((mtpDev_->xferSendHeader == 1) ? sizeof(struct UsbMtpDataHeader) : 0); - int64_t needXferCount = mtpDev_->xferFileLength + static_cast(hdrSize); - int64_t reqMax = static_cast(mtpDev_->dataInPipe.maxPacketSize); + uint64_t hdrSize = static_cast((mtpDev_->xferSendHeader == 1) ? sizeof(struct UsbMtpDataHeader) : 0); + uint64_t needXferCount = mtpDev_->xferFileLength + hdrSize; + uint64_t reqMax = static_cast(mtpDev_->dataInPipe.maxPacketSize); req->length = (reqMax > needXferCount) ? static_cast(needXferCount) : static_cast(reqMax); if (hdrSize != 0) { /* write MTP header first */ @@ -1392,7 +1376,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortSendFileFillFirstReq(struct UsbFnRequest *req, i } uint8_t *bufOffset = static_cast(req->buf) + hdrSize; oneReqLeft = (hdrSize + mtpDev_->xferFileLength < reqMax) ? mtpDev_->xferFileLength : reqMax - hdrSize; - ssize_t readRet = read(mtpDev_->xferFd, static_cast(bufOffset), oneReqLeft); + ssize_t readRet = read(mtpDev_->xferFd, static_cast(bufOffset), static_cast(oneReqLeft)); if (readRet != static_cast(oneReqLeft)) { HDF_LOGE("%{public}s: read failed: %{public}zd vs %{public}" PRId64 "", __func__, readRet, oneReqLeft); return HDF_FAILURE; @@ -1409,7 +1393,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortSendFileEx() return HDF_DEV_ERR_DEV_INIT_FAIL; } DListRemove(&req->list); - int64_t oneReqLeft = 0; + uint64_t oneReqLeft = 0; int32_t ret = UsbMtpPortSendFileFillFirstReq(req, oneReqLeft); if (ret != HDF_SUCCESS) { HDF_LOGE("%{public}s: fill first sync bulk-in req failed: %{public}d", __func__, ret); @@ -1440,7 +1424,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortSendFileEx() return ret; } -int32_t UsbfnMtpImpl::UsbMtpPortSendFileLeftAsync(int64_t oneReqLeft) +int32_t UsbfnMtpImpl::UsbMtpPortSendFileLeftAsync(uint64_t oneReqLeft) { mtpDev_->xferFileLength -= oneReqLeft; mtpDev_->asyncSendFileActual = 0; @@ -1451,7 +1435,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortSendFileLeftAsync(int64_t oneReqLeft) HDF_LOGE("%{public}s: start async tx failed", __func__); return HDF_ERR_IO; } - HDF_LOGI("%{public}s: wait async tx", __func__); + HDF_LOGV("%{public}s: wait async tx", __func__); sem_wait(&asyncReq_); return (mtpDev_->mtpState == MTP_STATE_ERROR) ? HDF_ERR_IO : HDF_SUCCESS; } @@ -1465,32 +1449,30 @@ int32_t UsbfnMtpImpl::SendFile(const UsbFnMtpFileSlice &mfs) std::lock_guard guard(mtpRunning_); mtpDev_->xferFd = mfs.fd; - mtpDev_->xferFileOffset = mfs.offset; - mtpDev_->xferFileLength = mfs.length; + mtpDev_->xferFileOffset = static_cast(mfs.offset); + mtpDev_->xferFileLength = static_cast(mfs.length); mtpDev_->xferCommand = mfs.command; mtpDev_->xferTransactionId = mfs.transactionId; mtpDev_->xferSendHeader = (mfs.command == 0 && mfs.transactionId == 0) ? 0 : 1; - uint32_t hdrSize = (mtpDev_->xferSendHeader == 1) ? sizeof(struct UsbMtpDataHeader) : 0; - int64_t needXferCount = mfs.length + static_cast(hdrSize); + uint64_t hdrSize = (mtpDev_->xferSendHeader == 1) ? static_cast(sizeof(struct UsbMtpDataHeader)) : 0; + uint64_t needXferCount = mfs.length + hdrSize; lseek(mfs.fd, mfs.offset, SEEK_SET); - HDF_LOGI("%{public}s: info: cmd=%{public}d, transid=%{public}d, len=%{public}" PRId64 " offset=%{public}" PRId64 - "; " - "Xfer=%{public}" PRId64 "(header=%{public}u), state=%{public}d", - __func__, mfs.command, mfs.transactionId, mfs.length, mfs.offset, needXferCount, hdrSize, mtpDev_->mtpState); + HDF_LOGV("%{public}s: info: cmd=%{public}d, transid=%{public}d, len=%{public}" PRId64 " offset=%{public}" PRId64 + "; Xfer=%{public}" PRIu64 "(header=%{public}" PRIu64 "), state=%{public}hhu", __func__, mfs.command, + mfs.transactionId, mfs.length, mfs.offset, needXferCount, hdrSize, mtpDev_->mtpState); - if (needXferCount == 0) { + if (needXferCount == 0 || mfs.length < 0) { HDF_LOGW("%{public}s: no data need to send", __func__); return HDF_SUCCESS; } if (mtpDev_->mtpState == MTP_STATE_OFFLINE) { - HDF_LOGE("%{public}s: device disconnect, stop rx", __func__); + HDF_LOGE("%{public}s: device disconnect", __func__); return HDF_DEV_ERR_NO_DEVICE; } mtpDev_->needZLP = ZLP_NO_NEED; if ((needXferCount & (mtpDev_->dataInPipe.maxPacketSize - 1)) == 0) { mtpDev_->needZLP = ZLP_NEED; } - int32_t ret = UsbMtpPortSendFileEx(); if (ret != HDF_SUCCESS) { HDF_LOGE("%{public}s: failed: sendfile %{public}d", __func__, ret); @@ -1511,7 +1493,7 @@ int32_t UsbfnMtpImpl::SendEvent(const std::vector &eventData) return HDF_FAILURE; } if (mtpDev_->mtpState == MTP_STATE_OFFLINE) { - HDF_LOGE("%{public}s: device offline", __func__); + HDF_LOGE("%{public}s: device disconnect", __func__); return HDF_DEV_ERR_NO_DEVICE; } struct UsbFnRequest *req = mtpDev_->notifyReq; diff --git a/usb/hdi_service/src/usbd_function.cpp b/usb/hdi_service/src/usbd_function.cpp index d38fab0b43..af4ae77fb7 100644 --- a/usb/hdi_service/src/usbd_function.cpp +++ b/usb/hdi_service/src/usbd_function.cpp @@ -87,16 +87,16 @@ int32_t UsbdFunction::SendCmdToService(const char *name, int32_t cmd, unsigned c int32_t UsbdFunction::InitMtp() { - auto serviceImpl = UsbfnMtpImpl::Get(true); - if (serviceImpl == nullptr) { - HDF_LOGE("%{public}s: failed to get of implement service", __func__); - return HDF_FAILURE; - } int32_t ret = UsbdRegisterDevice(MTP_PTP_SERVICE_NAME); if (ret != HDF_SUCCESS) { HDF_LOGE("%{public}s: register mtp device failed: %{public}d", __func__, ret); return ret; } + auto serviceImpl = UsbfnMtpImpl::Get(true); + if (serviceImpl == nullptr) { + HDF_LOGE("%{public}s: failed to get of implement service", __func__); + return HDF_FAILURE; + } ret = serviceImpl->Init(); if (ret != HDF_SUCCESS) { HDF_LOGE("%{public}s: init mtp device failed: %{public}d", __func__, ret); diff --git a/usb/test/unittest/hal/BUILD.gn b/usb/test/unittest/hal/BUILD.gn index eb8a92822e..2b75da3264 100644 --- a/usb/test/unittest/hal/BUILD.gn +++ b/usb/test/unittest/hal/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Copyright (c) 2021-2023 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 @@ -14,7 +14,7 @@ import("//build/test.gni") import("//drivers/peripheral/usb/usb.gni") -module_output_path = "hdf/usb" +module_output_path = "drivers_peripheral_usb/usb" config("module_private_config") { visibility = [ ":*" ] @@ -98,6 +98,7 @@ ohos_unittest("test_function") { "c_utils:utils", "drivers_interface_usb:libusb_proxy_1.0", "eventhandler:libeventhandler", + "hdf_core:libhdf_host", "hdf_core:libhdf_utils", "hiviewdfx_hilog_native:libhilog", "ipc:ipc_single", @@ -136,6 +137,31 @@ ohos_unittest("test_request") { module_out_path = module_output_path } +ohos_unittest("test_usbfnmtp") { + sources = [ "src/usbfn_mtp_test.cpp" ] + + configs = [ ":module_private_config" ] + + deps = [ + "${usb_driver_path}/ddk:libusb_core", + "${usb_driver_path}/gadget/function/mtp:libusbfn_mtp_interface_service_1.0", + "${usb_driver_path}/hdi_service:libusb_interface_service_1.0", + "//third_party/googletest:gtest_main", + ] + + external_deps = [ + "c_utils:utils", + "drivers_interface_usb:libusb_proxy_1.0", + "drivers_interface_usb:libusbfn_mtp_proxy_1.0", + "eventhandler:libeventhandler", + "hdf_core:libhdf_host", + "hdf_core:libhdf_utils", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_single", + ] + module_out_path = module_output_path +} + group("hal_test") { testonly = true deps = [] diff --git a/usb/test/unittest/hal/include/usbfn_mtp_test.h b/usb/test/unittest/hal/include/usbfn_mtp_test.h new file mode 100644 index 0000000000..cb06365ff1 --- /dev/null +++ b/usb/test/unittest/hal/include/usbfn_mtp_test.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 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 USBD_MTP_TEST_H +#define USBD_MTP_TEST_H + +#include + +namespace { +class UsbfnMtpTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; +} // namespace + +#endif // USBD_MTP_TEST_H diff --git a/usb/test/unittest/hal/src/usbfn_mtp_test.cpp b/usb/test/unittest/hal/src/usbfn_mtp_test.cpp new file mode 100644 index 0000000000..8e3aa7eef7 --- /dev/null +++ b/usb/test/unittest/hal/src/usbfn_mtp_test.cpp @@ -0,0 +1,1040 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "usbfn_mtp_test.h" + +#include +#include +#include +#include +#include + +#include "directory_ex.h" +#include "file_ex.h" +#include "hdf_log.h" +#include "securec.h" +#include "usbd_function.h" +#include "usbd_port.h" +#include "v1_0/iusb_interface.h" +#include "v1_0/iusbfn_mtp_interface.h" +#include "v1_0/usb_types.h" +#include "v1_0/usbfn_mtp_types.h" + +#define HDF_LOG_TAG usbfn_mtp_ut + +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::HDI::Usb::V1_0; +using namespace std; +using namespace OHOS::HDI::Usb::Gadget::Mtp::V1_0; + +namespace { +constexpr int32_t SLEEP_TIME = 3; +constexpr int32_t MTP_EVENT_PACKET_MAX_BYTES = 28; +constexpr int32_t MTP_EVENT_PACKET_VALID_LEN = 20; +constexpr int32_t MTP_EVENT_PACKET_INVALID_LEN = 29; +constexpr uint16_t CMD_CODE_GET_DEVICE_INFO = 0x1001; +constexpr uint32_t TRANSACTION_ID_RANDOM = 0xF00D; +/* mtp packet head defined as [struct UsbMtpDataHeader] in usbfn_mtp_impl.h */ +constexpr uint32_t MTP_PACKET_HEADER_SIZE = 12; +constexpr uint32_t BULK_OUT_ONCE_MAX_SIZE = 1024; +constexpr uint32_t BULK_OUT_LESS_THEN_ONCE = 23; +constexpr uint32_t BULK_OUT_MORE_THEN_ONCE = 1025; +constexpr uint32_t BULK_IN_ONCE_MAX_SIZE = 1024; +constexpr uint32_t BULK_IN_LESS_THEN_ONCE = 45; +constexpr uint32_t BULK_IN_MORE_THEN_ONCE = 2023; +constexpr uint32_t MTP_FILE_SIZE_ONE_REQ = 1024; +constexpr uint32_t MTP_FILE_SIZE_REUSE_REQ = 12 * 1024; +/* 0xFFFFFFFFLL is 4 * 1024 * 1024 * 1024 - 1 = 4GB - 1 */ +constexpr int64_t MTP_MAX_FILE_SIZE = 0xFFFFFFFFLL; +constexpr int64_t GEN_FILE_BUF_SIZE = 1024; +constexpr int64_t GEN_FILE_LIMIT_512MB = 512 * 1024 * 1024; +constexpr int32_t PRINT_VECTOR_MAX_LENGTH = 30; +constexpr const char *WORKED_UT_PATH = "/data/local/tmp/"; +constexpr const char *MTP_TEST_SEND_FILE = "/data/local/tmp/sampleFile.mtp"; +constexpr const char *MTP_TEST_RECV_FILE = "/data/local/tmp/sampleFile.mtp"; + +sptr g_usbfnMtpInterface = nullptr; +sptr g_usbInterface = nullptr; +int32_t g_currentFunc = USB_FUNCTION_NONE; +int32_t g_fileTestCount = 0; + +struct UsbFnMtpFileSlice g_mfs = { + .offset = 0, + .length = 0, + .command = 0, + .transactionId = 0, +}; + +void PrintVector(const std::string &msg, std::vector &data, bool hexFormat) +{ + size_t printLen = data.size(); + bool ignore = false; + if (printLen > static_cast(PRINT_VECTOR_MAX_LENGTH)) { + printLen = static_cast(PRINT_VECTOR_MAX_LENGTH); + ignore = true; + } + std::stringstream ss; + for (size_t i = 0; i < printLen; i++) { + if (hexFormat) { + ss << std::hex << "0x" << (0xFF & data.at(i)) << " "; + } else { + ss << data.at(i); + } + } + std::string output = msg + std::string("(") + std::to_string(printLen) + std::string("):") + ss.str(); + if (ignore) { + output += "......"; + } + HDF_LOGV("UsbfnMtpTest::PrintVector %{public}s", output.c_str()); +} + +uint64_t GetFileSize(const std::string &pathName) +{ + struct stat statbuf; + uint64_t ret = stat(pathName.c_str(), &statbuf); + if (ret != 0) { + return 0; + } + return static_cast(statbuf.st_size); +} + +bool WriteRandomDataToFile(const std::string &pathName, uint64_t fileSize) +{ + int32_t random = open("/dev/urandom", O_RDONLY); + if (random < 0) { + HDF_LOGE("UsbfnMtpTest::WriteRandomDataToFile get random data failed"); + return false; + } + FILE *opFile = std::fopen(pathName.c_str(), "w"); + if (opFile == nullptr) { + HDF_LOGE("UsbfnMtpTest::WriteRandomDataToFile create file failed: %{public}s", pathName.c_str()); + return false; + } + char buffer[GEN_FILE_BUF_SIZE]; + int64_t count = static_cast(fileSize); + while (count > 0) { + (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); + int64_t readSize = count > GEN_FILE_BUF_SIZE ? GEN_FILE_BUF_SIZE : count; + ssize_t readActual = read(random, static_cast(buffer), static_cast(readSize)); + if (readActual != static_cast(readSize)) { + HDF_LOGW("UsbfnMtpTest::WriteRandomDataToFile read random failed"); + break; + } + size_t writeActual = std::fwrite(static_cast(buffer), 1, static_cast(readSize), opFile); + if (writeActual != static_cast(readSize)) { + HDF_LOGW("UsbfnMtpTest::WriteRandomDataToFile write failed"); + break; + } + count -= readSize; + } + std::fflush(opFile); + std::fclose(opFile); + close(random); + HDF_LOGV("UsbfnMtpTest::WriteRandomDataToFile file %{public}s: %{public}" PRIu64 "/%{public}" PRIu64 "", + pathName.c_str(), GetFileSize(pathName), fileSize); + return count > 0 ? false : true; +} + +bool GenerateFile(const std::string &pathName, int64_t fileSize) +{ + if (GetFileSize(pathName) == static_cast(fileSize)) { + HDF_LOGW("UsbfnMtpTest::GenerateFile file already exist"); + return true; + } + if (fileSize > GEN_FILE_LIMIT_512MB) { + int32_t ret = truncate(pathName.c_str(), static_cast(fileSize)); + if (ret != 0) { + HDF_LOGE("UsbfnMtpTest::GenerateFile fail to truncate file to size: %{public}" PRId64 "", fileSize); + return false; + } + HDF_LOGV("UsbfnMtpTest::GenerateFile truncate %{public}s %{public}" PRId64 "", pathName.c_str(), fileSize); + return true; + } + return WriteRandomDataToFile(pathName, static_cast(fileSize)); +} + +void UsbfnMtpTest::SetUpTestCase(void) +{ + // Selinux config this UT only works in directory WORKED_UT_PATH for open/read/write file for case send/recvfile. + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + std::cout << "===>please connect to PC use USB 3.0 interface, press enter to continue set function to mtp" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + g_usbInterface = IUsbInterface::Get(); + ASSERT_TRUE(g_usbInterface != nullptr); + auto ret = g_usbInterface->SetPortRole(DEFAULT_PORT_ID, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + sleep(SLEEP_TIME); + ASSERT_EQ(0, ret); + ret = g_usbInterface->GetCurrentFunctions(g_currentFunc); + ASSERT_EQ(0, ret); + std::cout << "===>current function=" << g_currentFunc << ", set function to mtp, please wait" << std::endl; + ret = g_usbInterface->SetCurrentFunctions(USB_FUNCTION_MTP); + ASSERT_EQ(0, ret); + + g_usbfnMtpInterface = IUsbfnMtpInterface::Get(); + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ret = g_usbfnMtpInterface->Start(); + ASSERT_EQ(0, ret); +} + +void UsbfnMtpTest::TearDownTestCase(void) +{ + HDF_LOGV("UsbfnMtpTest::TearDownTestCase"); + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + auto ret = g_usbfnMtpInterface->Stop(); + ASSERT_EQ(0, ret); + ASSERT_TRUE(g_usbInterface != nullptr); + ret = g_usbInterface->SetCurrentFunctions(g_currentFunc); + ASSERT_EQ(0, ret); + if (g_fileTestCount == 0) { + return; + } + /* 1 means single test, run with '--gtest_filter=' option */ + if (g_fileTestCount == 1) { + std::cout << "===>please delete temporary test file if needed: sendfile=" << MTP_TEST_SEND_FILE + << " recvfile=" << MTP_TEST_RECV_FILE << std::endl; + return; + } + if (FileExists(std::string(MTP_TEST_SEND_FILE))) { + if (remove(MTP_TEST_SEND_FILE) != 0) { + std::cout << "[-] remove send file failed: " << MTP_TEST_SEND_FILE << std::endl; + } + } + if (FileExists(std::string(MTP_TEST_RECV_FILE))) { + if (remove(MTP_TEST_RECV_FILE) != 0) { + std::cout << "[-] remove recv file failed: " << MTP_TEST_RECV_FILE << std::endl; + } + } +} + +void UsbfnMtpTest::SetUp(void) {} + +void UsbfnMtpTest::TearDown(void) {} + +/** + * @tc.name: UsbfnMtpRead001 + * @tc.desc: Test functions to Read + * @tc.desc: int32_t Read(std::vector& data); + * @tc.desc: Positive test: parameters correctly, read length less then one packet size + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpRead001, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpRead001 Case Start"); + std::vector devData; + + std::cout << "UsbfnMtpRead001===>use libusb in PC launch bulk-out transfer(size=" << BULK_OUT_LESS_THEN_ONCE + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + int32_t ret = g_usbfnMtpInterface->Read(devData); + ASSERT_EQ(ret, 0); + ASSERT_EQ(devData.size(), static_cast(BULK_OUT_LESS_THEN_ONCE)); +} + +/** + * @tc.name: UsbfnMtpRead002 + * @tc.desc: Test functions to Read + * @tc.desc: int32_t Read(std::vector& data); + * @tc.desc: Positive test: parameters correctly, read length exactly one packet size + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpRead002, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpRead002 Case Start"); + std::vector devData; + + std::cout << "UsbfnMtpRead002===>use libusb in PC launch bulk-out transfer(size=" << BULK_OUT_ONCE_MAX_SIZE + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + int32_t ret = g_usbfnMtpInterface->Read(devData); + ASSERT_EQ(ret, 0); + ASSERT_EQ(devData.size(), static_cast(BULK_OUT_ONCE_MAX_SIZE)); +} + +/** + * @tc.name: UsbfnMtpRead003 + * @tc.desc: Test functions to Read + * @tc.desc: int32_t Read(std::vector& data); + * @tc.desc: Positive test: parameters correctly, read length more then one packet size, please read again + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpRead003, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpRead003 Case Start"); + std::vector devData; + + std::cout << "UsbfnMtpRead003===>use libusb in PC launch bulk-out transfer(size=" << BULK_OUT_MORE_THEN_ONCE + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + int32_t ret = g_usbfnMtpInterface->Read(devData); + ASSERT_EQ(ret, 0); + ASSERT_EQ(devData.size(), static_cast(BULK_OUT_ONCE_MAX_SIZE)); + devData.clear(); + ret = g_usbfnMtpInterface->Read(devData); + ASSERT_EQ(ret, 0); + ASSERT_EQ(devData.size(), static_cast(BULK_OUT_MORE_THEN_ONCE - BULK_OUT_ONCE_MAX_SIZE)); +} + +/** + * @tc.name: UsbfnMtpRead004 + * @tc.desc: Test functions to Read + * @tc.desc: int32_t Read(std::vector& data) + * @tc.desc: Positive test: parameters correctly, no specific read size + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpRead004, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpRead004 Case Start"); + std::vector devData; + + std::cout + << "UsbfnMtpRead004===>use libusb in PC launch bulk-out transfer(size in [0, 1024]), press enter to continue" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->Read(devData); + ASSERT_EQ(ret, 0); + ASSERT_GE(devData.size(), 0); +} + +/** + * @tc.name: UsbfnMtpRead005 + * @tc.desc: Test functions to Read + * @tc.desc: int32_t Read(std::vector& data) + * @tc.desc: Positive test: parameters correctly, check read content + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpRead005, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpRead005 Case Start"); + std::vector devData; + // hex value of string "read005" + std::vector expectData = {0x72, 0x65, 0x61, 0x64, 0x30, 0x30, 0x35}; + + std::cout << "UsbfnMtpRead005===>use libusb in PC launch bulk-out transfer(string=read005), press enter to continue" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->Read(devData); + ASSERT_EQ(ret, 0); + ASSERT_EQ(devData, expectData); + PrintVector("read005", devData, true); +} + +/** + * @tc.name: UsbfnMtpWrite001 + * @tc.desc: Test functions to Write + * @tc.desc: int32_t Write(const std::vector& data) + * @tc.desc: Positive test: parameters correctly + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpWrite001, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpWrite001 Case Start"); + uint32_t length = BULK_IN_LESS_THEN_ONCE; + std::vector devData; + devData.assign(length, 'w'); + + std::cout << "UsbfnMtpWrite001===>use libusb in PC launch bulk-in transfer(expect=" << length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->Write(devData); + ASSERT_EQ(ret, 0); +} + +/** + * @tc.name: UsbfnMtpWrite002 + * @tc.desc: Test functions to Write + * @tc.desc: int32_t Write(const std::vector& data) + * @tc.desc: Positive test: parameters correctly + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpWrite002, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpWrite002 Case Start"); + uint32_t length = BULK_IN_ONCE_MAX_SIZE; + std::vector devData; + devData.assign(length, 'w'); + std::cout << "UsbfnMtpWrite002===>use libusb in PC launch bulk-in transfer(expect=" << length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->Write(devData); + ASSERT_EQ(ret, 0); +} + +/** + * @tc.name: UsbfnMtpWrite003 + * @tc.desc: Test functions to Write + * @tc.desc: int32_t Write(const std::vector& data) + * @tc.desc: Positive test: parameters correctly + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpWrite003, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpWrite003 Case Start"); + uint32_t length = BULK_IN_MORE_THEN_ONCE; + std::vector devData; + devData.assign(length, 'w'); + std::cout << "UsbfnMtpWrite003===>use libusb in PC launch bulk-in transfer(expect=" << length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->Write(devData); + ASSERT_EQ(ret, 0); +} + +/** + * @tc.name: UsbfnMtpWrite004 + * @tc.desc: Test functions to Write + * @tc.desc: int32_t Write(const std::vector& data) + * @tc.desc: Positive test: parameters correctly, write empty data + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpWrite004, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpWrite004 Case Start"); + std::vector devData; + auto ret = g_usbfnMtpInterface->Write(devData); + ASSERT_EQ(ret, 0); +} + +/** + * @tc.name: UsbfnMtpWrite005 + * @tc.desc: Test functions to Write + * @tc.desc: int32_t Write(const std::vector& data) + * @tc.desc: Positive test: parameters correctly, write specific data + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpWrite005, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpWrite005 Case Start"); + // hex value of string "write005" + std::vector devData = {0x77, 0x72, 0x69, 0x74, 0x65, 0x30, 0x30, 0x35}; + std::cout << "UsbfnMtpWrite005===>use libusb in PC launch bulk-in transfer(expect string=write005), press enter " + "to continue" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->Write(devData); + ASSERT_EQ(ret, 0); + PrintVector("write005", devData, true); +} + +/** + * @tc.name: UsbfnMtpSendEvent001 + * @tc.desc: Test functions to SendEvent + * @tc.desc: int32_t SendEvent(const std::vector &eventData); + * @tc.desc: Positive test: parameters correctly, valid length + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpSendEvent001, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpSendEvent001 Case Start"); + std::vector devData; + devData.assign(MTP_EVENT_PACKET_VALID_LEN, 'e'); + std::cout << "UsbfnMtpSendEvent001===>use libusb in PC launch intr-in transfer(expect=" << devData.size() + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->SendEvent(devData); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpSendEvent002 + * @tc.desc: Test functions to SendEvent + * @tc.desc: int32_t SendEvent(const std::vector &eventData); + * @tc.desc: Positive test: parameters correctly, max length + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpSendEvent002, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpSendEvent002 Case Start"); + std::vector devData; + devData.assign(MTP_EVENT_PACKET_MAX_BYTES, 'e'); + std::cout << "UsbfnMtpSendEvent002===>use libusb in PC launch intr-in transfer(expect=" << devData.size() + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + auto ret = g_usbfnMtpInterface->SendEvent(devData); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpSendEvent003 + * @tc.desc: Test functions to SendEvent + * @tc.desc: int32_t SendEvent(const std::vector &eventData); + * @tc.desc: Negative test: parameters exception, size overflow + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpSendEvent003, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpSendEvent003 Case Start"); + std::vector devData; + devData.assign(MTP_EVENT_PACKET_INVALID_LEN, 'e'); + std::cout << "UsbfnMtpSendEvent003===>use libusb in PC launch intr-in transfer(expect=no data, or error), press " + "enter to continue" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + auto ret = g_usbfnMtpInterface->SendEvent(devData); + ASSERT_NE(0, ret); + std::cout << "UsbfnMtpSendEvent003===>make sure transfer timeout in PC, then start next test " << std::endl; +} + +/** + * @tc.name: UsbfnMtpSendEvent004 + * @tc.desc: Test functions to SendEvent + * @tc.desc: int32_t SendEvent(const std::vector &eventData); + * @tc.desc: Positive test: parameters correctly, max length, check content + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpSendEvent004, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpSendEvent004 Case Start"); + // hex value of string "event004" + std::vector devData = {0x65, 0x76, 0x65, 0x6E, 0x74, 0x30, 0x30, 0x34}; + std::cout << "UsbfnMtpSendEvent004===>use libusb in PC launch intr-in transfer(expect string=event004), press " + "enter to continue" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + auto ret = g_usbfnMtpInterface->SendEvent(devData); + ASSERT_EQ(0, ret); + PrintVector("event004", devData, true); +} + +/** + * @tc.name: UsbfnMtpFileReceive001 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, one packet enough + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive001, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive001 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = BULK_OUT_LESS_THEN_ONCE; + std::cout << "UsbfnMtpFileReceive001===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive002 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, zero length + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive002, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive002 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = 0; + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive003 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, one normal packet + short packet + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive003, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive003 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = BULK_OUT_MORE_THEN_ONCE; + std::cout << "UsbfnMtpFileReceive003===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive004 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: mfs.length set to max, 12 packet + ZLP + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive004, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive004 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_FILE_SIZE_REUSE_REQ; + std::cout << "UsbfnMtpFileReceive004===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive005 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, command and transactionId ignored + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive005, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive005 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = BULK_OUT_LESS_THEN_ONCE; + mfs.command = CMD_CODE_GET_DEVICE_INFO; + mfs.transactionId = TRANSACTION_ID_RANDOM; + std::cout << "UsbfnMtpFileReceive005===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive006 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: mfs.length set to max, recv actual file size depend on xfer count + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive006, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive006 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE; + std::cout + << "UsbfnMtpFileReceive006===>use libusb in PC launch bulk-out transfer(size = any), press enter to continue" + << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_GE(GetFileSize(filePathName), 0); +} + +/** + * @tc.name: UsbfnMtpFileReceive007 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: mfs.length set to max - 1: 4GB - 2 + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive007, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive007 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE - 1; + std::cout << "UsbfnMtpFileReceive007===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive008 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: mfs.length set to max + 1: 4GB + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive008, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive008 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE + 1; + std::cout << "UsbfnMtpFileReceive008===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileReceive009 + * @tc.desc: Test functions to ReceiveFile + * @tc.desc: int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: mfs.length set to max + 2: 4GB + 1 + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileReceive009, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileReceive009 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE + 2; + std::cout << "UsbfnMtpFileReceive009===>use libusb in PC launch bulk-out transfer(size = " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + std::string filePathName = MTP_TEST_RECV_FILE; + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->ReceiveFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); + ASSERT_EQ(GetFileSize(filePathName), static_cast(mfs.length)); +} + +/** + * @tc.name: UsbfnMtpFileSend001 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, length in one packet + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend001, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend001 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = BULK_IN_LESS_THEN_ONCE; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend001===>use libusb in PC launch bulk-in transfer(expect " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(ret, 0); +} + +/** + * @tc.name: UsbfnMtpFileSend002 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, send header + data in one packet + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend002, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend002 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = BULK_IN_LESS_THEN_ONCE; + mfs.command = CMD_CODE_GET_DEVICE_INFO; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend002===>use libusb in PC launch bulk-in transfer(expect " + << mfs.length + MTP_PACKET_HEADER_SIZE << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpFileSend003 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, zero length + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend003, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend003 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = 0; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpFileSend004 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, send header + data in two packet: normal + short + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend004, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend004 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_FILE_SIZE_ONE_REQ; + mfs.command = CMD_CODE_GET_DEVICE_INFO; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend004===>use libusb in PC launch bulk-in transfer(expect " + << mfs.length + MTP_PACKET_HEADER_SIZE << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpFileSend005 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, mfs.length set to max + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend005, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend005 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_FILE_SIZE_REUSE_REQ; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend005===>use libusb in PC launch bulk-in transfer(speed, expect " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpFileSend006 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, mfs.length set to max: 4GB - 1 + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend006, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend006 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend006===>use libusb in PC launch bulk-in transfer(speed, expect " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpFileSend007 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, mfs.length set to max + 1: 4GB + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend007, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend007 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE + 1; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend007===>use libusb in PC launch bulk-in transfer(speed, expect " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +/** + * @tc.name: UsbfnMtpFileSend008 + * @tc.desc: Test functions to SendFile + * @tc.desc: int32_t SendFile(const UsbFnMtpFileSlice &mfs); + * @tc.desc: Positive test: parameters correctly, mfs.length set to max + 1: 4GB + 1 + * @tc.type: FUNC + */ +HWTEST_F(UsbfnMtpTest, UsbfnMtpFileSend008, TestSize.Level1) +{ + ASSERT_TRUE(g_usbfnMtpInterface != nullptr); + ASSERT_TRUE(GetCurrentProcPath() == std::string(WORKED_UT_PATH)); + HDF_LOGI("UsbfnMtpTest::UsbfnMtpFileSend008 Case Start"); + g_fileTestCount++; + struct UsbFnMtpFileSlice mfs = g_mfs; + mfs.length = MTP_MAX_FILE_SIZE + 2; + std::string filePathName = MTP_TEST_SEND_FILE; + EXPECT_TRUE(GenerateFile(filePathName, mfs.length)); + std::cout << "UsbfnMtpFileSend008===>use libusb in PC launch bulk-in transfer(speed, expect " << mfs.length + << "), press enter to continue" << std::endl; + int32_t c; + while ((c = getchar()) != '\n' && c != EOF) {} + + mfs.fd = open(filePathName.c_str(), O_CREAT | O_RDONLY); + ASSERT_GT(mfs.fd, 0); + auto ret = g_usbfnMtpInterface->SendFile(mfs); + close(mfs.fd); + ASSERT_EQ(0, ret); +} + +} // namespace