add: mtp hdi ut

Signed-off-by: yannikli <liyanqing18@huawei.com>
This commit is contained in:
yannikli
2023-03-17 11:53:29 +08:00
parent 9cf383e97e
commit 1b69541c08
7 changed files with 1187 additions and 269 deletions
-159
View File
@@ -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 */
@@ -17,6 +17,7 @@
#define OHOS_HDI_USB_GADGET_MTP_V1_0_USBFNMTPIMPL_H
#include <mutex>
#include <semaphore.h>
#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<uint8_t> &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<uint8_t> &vectorData);
uint32_t BufCopyFromVector(
void *buf, uint32_t bufSize, const std::vector<uint8_t> &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_;
+74 -92
View File
@@ -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<uint64_t>(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<size_t>(req->length));
if (readRet != static_cast<ssize_t>(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<int64_t>(mtpDev->dataInPipe.maxPacketSize);
uint64_t reqMax = static_cast<uint64_t>(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<int64_t>(req->length);
mtpDev->asyncSendFileExpect += static_cast<uint64_t>(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<struct UsbMtpDevice *>(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<uint8_t> &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<std::mutex> 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<uint8_t> &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<uint8_t> &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<uint8_t> &data)
std::lock_guard<std::mutex> 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<uint64_t>(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<void *>(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<void *>(mtpDev->asyncRecvWriteTempContent),
static_cast<size_t>(WRITE_FILE_TEMP_SLICE));
if (writeRet != static_cast<ssize_t>(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<uint64_t>(req->actual);
}
if (mtpDev->asyncXferFile == ASYNC_XFER_FILE_DONE) {
size_t writeRet = write(
mtpDev->xferFd, static_cast<void *>(mtpDev->asyncRecvWriteTempContent), mtpDev->asyncRecvWriteTempCount);
if (writeRet != mtpDev->asyncRecvWriteTempCount) {
ssize_t writeRet = write(mtpDev->xferFd, static_cast<void *>(mtpDev->asyncRecvWriteTempContent),
static_cast<size_t>(mtpDev->asyncRecvWriteTempCount));
if (writeRet != static_cast<ssize_t>(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<int64_t>(mtpDev->dataOutPipe.maxPacketSize);
uint64_t reqMax = static_cast<uint64_t>(mtpDev->dataOutPipe.maxPacketSize);
if (mtpDev->asyncRecvFileExpect + reqMax < mtpDev->xferFileLength) {
req->length = static_cast<uint32_t>(mtpDev->dataOutPipe.maxPacketSize);
} else {
@@ -1271,7 +1257,7 @@ int32_t UsbfnMtpImpl::UsbMtpPortStartSubmitRxReq(struct UsbMtpPort *mtpPort, boo
return ret;
}
mtpPort->readStarted++;
mtpDev->asyncRecvFileExpect += static_cast<int64_t>(req->length);
mtpDev->asyncRecvFileExpect += static_cast<uint64_t>(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<std::mutex> 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<uint64_t>(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<int64_t>((mtpDev_->xferSendHeader == 1) ? sizeof(struct UsbMtpDataHeader) : 0);
int64_t needXferCount = mtpDev_->xferFileLength + static_cast<int64_t>(hdrSize);
int64_t reqMax = static_cast<int64_t>(mtpDev_->dataInPipe.maxPacketSize);
uint64_t hdrSize = static_cast<uint64_t>((mtpDev_->xferSendHeader == 1) ? sizeof(struct UsbMtpDataHeader) : 0);
uint64_t needXferCount = mtpDev_->xferFileLength + hdrSize;
uint64_t reqMax = static_cast<uint64_t>(mtpDev_->dataInPipe.maxPacketSize);
req->length = (reqMax > needXferCount) ? static_cast<uint32_t>(needXferCount) : static_cast<uint32_t>(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<uint8_t *>(req->buf) + hdrSize;
oneReqLeft = (hdrSize + mtpDev_->xferFileLength < reqMax) ? mtpDev_->xferFileLength : reqMax - hdrSize;
ssize_t readRet = read(mtpDev_->xferFd, static_cast<void *>(bufOffset), oneReqLeft);
ssize_t readRet = read(mtpDev_->xferFd, static_cast<void *>(bufOffset), static_cast<size_t>(oneReqLeft));
if (readRet != static_cast<ssize_t>(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<std::mutex> guard(mtpRunning_);
mtpDev_->xferFd = mfs.fd;
mtpDev_->xferFileOffset = mfs.offset;
mtpDev_->xferFileLength = mfs.length;
mtpDev_->xferFileOffset = static_cast<uint64_t>(mfs.offset);
mtpDev_->xferFileLength = static_cast<uint64_t>(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<int64_t>(hdrSize);
uint64_t hdrSize = (mtpDev_->xferSendHeader == 1) ? static_cast<uint64_t>(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<uint8_t> &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;
+5 -5
View File
@@ -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);
+28 -2
View File
@@ -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 = []
@@ -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 <gtest/gtest.h>
namespace {
class UsbfnMtpTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
void SetUp();
void TearDown();
};
} // namespace
#endif // USBD_MTP_TEST_H
File diff suppressed because it is too large Load Diff