1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef OHOS_HDI_USB_GADGET_MTP_V1_0_USBFNMTPIMPL_H 17#define OHOS_HDI_USB_GADGET_MTP_V1_0_USBFNMTPIMPL_H 18 19#include <semaphore.h> 20#include <mutex> 21#include <semaphore.h> 22 23#include "data_fifo.h" 24#include "hdf_base.h" 25#include "hdf_device_desc.h" 26#include "usbfn_device.h" 27#include "usbfn_interface.h" 28#include "usbfn_request.h" 29#include "v1_0/iusbfn_mtp_interface.h" 30 31// MTP interface descriptor 32#define USB_MTP_DEVICE_CLASS USB_DDK_CLASS_VENDOR_SPEC 33#define USB_MTP_DEVICE_SUBCLASS USB_DDK_SUBCLASS_VENDOR_SPEC 34#define USB_MTP_DEVICE_PROTOCOL 0 35 36// PTP interface descriptor 37#define USB_PTP_DEVICE_CLASS USB_DDK_CLASS_STILL_IMAGE 38#define USB_PTP_DEVICE_SUBCLASS 1 39#define USB_PTP_DEVICE_PROTOCOL 1 40#define MTP_CONTROL_XFER_BYTECOUNT 512 41 42/* req count for control xfer */ 43#define MTP_CTRL_REQUEST_NUM 2 44 45/* req count for bulk-out xfer */ 46#define READ_QUEUE_SIZE 8 47 48/* req count for bulk-in xfer */ 49#define WRITE_QUEUE_SIZE 8 50#define BULK_WRITE_BUF_SIZE 8192 51#define BULK_READ_BUF_SIZE 8192 52#define USB_HS_INTR_PACKET_MAX_BYTES 1024 53 54/* MTP event packet max length */ 55#define MTP_EVENT_PACKET_MAX_BYTES 28 56 57/* values for UsbMtpDevice.mtpState */ 58enum UsbMtpDeviceState { 59 MTP_STATE_OFFLINE = 0, /* initial state, disconnected */ 60 MTP_STATE_READY, /* ready for userspace calls */ 61 MTP_STATE_BUSY, /* processing userspace calls */ 62 MTP_STATE_CANCELED, /* transaction canceled by host */ 63 MTP_STATE_ERROR, /* error from completion routine */ 64}; 65 66/* Compatible: ID for Microsoft MTP OS String */ 67#define USB_MTP_OS_STRING_ID 0xEE 68#define USB_MTP_BMS_VENDORCODE 0x01 69#define USB_MTP_EXTENDED_COMPAT_ID 0x0004 70#define USB_MTP_EXTENDED_PROPERTIES 0x0005 71 72/* MTP class reqeusts */ 73#define USB_MTP_REQ_CANCEL 0x64 74#define USB_MTP_REQ_GET_EXT_EVENT_DATA 0x65 75#define USB_MTP_REQ_RESET 0x66 76#define USB_MTP_REQ_GET_DEVICE_STATUS 0x67 77 78/* constants for device status */ 79#define MTP_RESPONSE_OK 0x2001 80#define MTP_RESPONSE_DEVICE_BUSY 0x2019 81 82struct UsbMtpDataHeader { 83 uint32_t length; 84 uint16_t type; /* defined mtp data type */ 85 uint16_t cmdCode; /* Operation, Response or Event Code in mtp */ 86 uint32_t transactionId; 87}; 88 89struct UsbMtpPipe { 90 uint8_t id; 91 uint16_t maxPacketSize; 92 struct UsbFnInterface *ctrlIface; 93}; 94 95struct UsbMtpInterface { 96 struct UsbFnInterface *fn; 97 UsbFnInterfaceHandle handle; 98}; 99 100struct UsbMtpPort { 101 struct UsbMtpDevice *mtpDev; 102 struct DListHead readPool; /* ready/idle read(bulk-out) req */ 103 struct DListHead readQueue; /* working async read(bulk-out) req */ 104 int32_t readStarted; 105 int32_t readAllocated; 106 struct DataFifo readFifo; 107 struct DListHead writePool; /* ready/idle write(bulk-in) req */ 108 struct DListHead writeQueue; /* working async write(bulk-in) req */ 109 int32_t writeStarted; 110 int32_t writeAllocated; 111 struct DataFifo writeFifo; 112 bool writeBusy; 113 bool suspended; 114 bool startDelayed; 115 int32_t refCount; 116}; 117 118struct UsbMtpDevice { 119 struct UsbFnDevice *fnDev; 120 struct UsbMtpInterface ctrlIface; 121 struct UsbMtpInterface intrIface; 122 struct UsbMtpInterface dataIface; 123 struct UsbMtpPipe notifyPipe; /* intr-in */ 124 struct UsbMtpPipe dataInPipe; /* bulk-in */ 125 struct UsbMtpPipe dataOutPipe; /* bulk-out */ 126 struct DListHead ctrlPool; 127 int32_t ctrlReqNum; 128 struct UsbFnRequest *notifyReq; 129 struct UsbMtpPort *mtpPort; 130 const char *udcName; 131 uint64_t asyncRecvFileActual; 132 uint64_t asyncRecvFileExpect; 133 uint64_t asyncSendFileActual; /* already send actual */ 134 uint64_t asyncSendFileExpect; /* already send expect */ 135 uint8_t asyncXferFile; 136 uint8_t needZLP; 137 uint32_t asyncRecvWriteTempCount; 138 uint8_t *asyncRecvWriteTempContent; 139 bool initFlag; 140 uint8_t mtpState; /* record mtp state, example: MTP_STATE_OFFLINE */ 141 uint8_t xferSendHeader; /* two value: 0 1 */ 142 uint16_t xferCommand; /* refer to struct UsbMtpFileRange.command */ 143 uint32_t xferTransactionId; /* refer to struct UsbMtpFileRange.transactionId */ 144 int32_t xferFd; 145 uint64_t xferFileOffset; 146 uint64_t xferFileLength; 147}; 148 149struct CtrlInfo { 150 uint8_t request; 151 struct UsbMtpDevice *mtpDev; 152}; 153 154namespace OHOS { 155namespace HDI { 156namespace Usb { 157namespace Gadget { 158namespace Mtp { 159namespace V1_0 { 160class UsbfnMtpImpl : public IUsbfnMtpInterface { 161public: 162 UsbfnMtpImpl(); 163 virtual ~UsbfnMtpImpl() = default; 164 165 HdfDeviceObject *deviceObject_; 166 167 /* Return 0 if operation is successful */ 168 int32_t Start() override; 169 /* Return 0 if operation is successful */ 170 int32_t Stop() override; 171 /* Return 0 if operation is successful */ 172 int32_t Read(std::vector<uint8_t> &data) override; 173 /* Return 0 if operation is successful */ 174 int32_t Write(const std::vector<uint8_t> &data) override; 175 /* Return 0 if send/receive is successful */ 176 int32_t ReceiveFile(const UsbFnMtpFileSlice &mfs) override; 177 /* Return 0 if send/receive is successful */ 178 int32_t SendFile(const UsbFnMtpFileSlice &mfs) override; 179 /* Return 0 if send/receive is successful */ 180 int32_t SendEvent(const std::vector<uint8_t> &eventData) override; 181 182 int32_t Init() override; 183 int32_t Release() override; 184 185private: 186 static void UsbFnRequestReadComplete(uint8_t pipe, struct UsbFnRequest *req); 187 static void UsbFnRequestWriteComplete(uint8_t pipe, struct UsbFnRequest *req); 188 static void UsbFnRequestNotifyComplete(uint8_t pipe, struct UsbFnRequest *req); 189 static void UsbFnRequestCtrlComplete(uint8_t pipe, struct UsbFnRequest *req); 190 191 static int32_t UsbMtpPortTxReqCheck(struct UsbMtpPort *mtpPort, struct UsbFnRequest *req); 192 static int32_t UsbMtpPortProcessLastTxPacket(struct UsbMtpPort *mtpPort, struct UsbFnRequest *req); 193 static int32_t UsbMtpPortSubmitAsyncTxReq(struct UsbMtpPort *mtpPort, struct UsbFnRequest *req); 194 static int32_t UsbMtpPortStartTxAsync(struct UsbMtpPort *mtpPort, bool callByComplete); 195 static int32_t UsbMtpPortProcessAsyncRxDone(struct UsbMtpPort *mtpPort); 196 static int32_t UsbMtpPortRxPush(struct UsbMtpPort *mtpPort, struct UsbFnRequest *req); 197 static int32_t UsbMtpPortStartSubmitRxReq(struct UsbMtpPort *mtpPort, bool needZLP); 198 static int32_t UsbMtpPortStartRxAsync(struct UsbMtpPort *mtpPort); 199 static int32_t UsbMtpPortRxCheckReq(struct UsbMtpPort *mtpPort, struct UsbFnRequest *req, bool &writeToFile); 200 201 static int32_t UsbMtpPortCancelAndFreeReq( 202 struct DListHead *queueHead, struct DListHead *poolHead, int32_t &allocated, bool freeReq); 203 static int32_t UsbMtpPortCancelPlusFreeIo(struct UsbMtpPort *mtpPort, bool freeReq); 204 static struct UsbFnRequest *UsbMtpDeviceGetCtrlReq(struct UsbMtpDevice *mtpDev); 205 static int32_t UsbMtpDeviceStandardRequest( 206 struct UsbMtpDevice *mtpDev, struct UsbFnCtrlRequest *setup, struct UsbFnRequest *req); 207 static int32_t UsbMtpDeviceClassRequest( 208 struct UsbMtpDevice *mtpDev, struct UsbFnCtrlRequest *setup, struct UsbFnRequest *req); 209 static int32_t UsbMtpDeviceVendorRequest( 210 struct UsbMtpDevice *mtpDev, struct UsbFnCtrlRequest *setup, struct UsbFnRequest *req); 211 static int32_t UsbMtpDeviceSetup(struct UsbMtpDevice *mtpDev, struct UsbFnCtrlRequest *setup); 212 static void UsbMtpDeviceSuspend(struct UsbMtpDevice *mtpDev); 213 static void UsbMtpDeviceResume(struct UsbMtpDevice *mtpDev); 214 static int32_t UsbMtpDeviceEnable(struct UsbMtpDevice *mtpDev); 215 static int32_t UsbMtpDeviceDisable(struct UsbMtpDevice *mtpDev); 216 static void UsbMtpDeviceEp0EventDispatch(struct UsbFnEvent *event); 217 218 int32_t UsbMtpDeviceAllocCtrlRequests(int32_t num); 219 void UsbMtpDeviceFreeCtrlRequests(); 220 void UsbMtpPortFreeRequests(struct DListHead *head, int32_t &allocated); 221 int32_t UsbMtpPortAllocReadWriteRequests(int32_t readSize, int32_t writeSize); 222 int32_t UsbMtpPortInitIo(); 223 int32_t UsbMtpPortReleaseIo(); 224 int32_t UsbMtpDeviceParseEachPipe(struct UsbMtpInterface &iface); 225 int32_t UsbMtpDeviceParseMtpIface(struct UsbFnInterface *fnIface); 226 bool UsbFnInterfaceIsUsbMtpPtpDevice(struct UsbFnInterface *iface); 227 int32_t UsbMtpDeviceParseEachIface(struct UsbFnDevice *fnDev); 228 int32_t UsbMtpDeviceCreateFuncDevice(); 229 int32_t UsbMtpDeviceReleaseFuncDevice(); 230 int32_t UsbMtpDeviceAlloc(); 231 int32_t UsbMtpDeviceFree(); 232 int32_t UsbMtpDeviceAllocNotifyRequest(); 233 void UsbMtpDeviceFreeNotifyRequest(); 234 235 int32_t WriteEx(const std::vector<uint8_t> &data, uint8_t sendZLP, uint32_t &xferActual); 236 int32_t UsbMtpPortSendFileFillFirstReq(struct UsbFnRequest *req, uint64_t &oneReqLeft); 237 int32_t UsbMtpPortSendFileEx(); 238 int32_t UsbMtpPortSendFileLeftAsync(uint64_t oneReqLeft); 239 int32_t ReceiveFileEx(); 240 241 uint32_t BufCopyToVector(void *buf, uint32_t bufSize, std::vector<uint8_t> &vectorData); 242 uint32_t BufCopyFromVector( 243 void *buf, uint32_t bufSize, const std::vector<uint8_t> &vectorData, uint32_t vectorOffset); 244 245 static struct UsbMtpDevice *mtpDev_; 246 static struct UsbMtpPort *mtpPort_; 247 static std::mutex mtpRunning_; 248 static std::mutex asyncMutex_; 249 static sem_t asyncReq_; 250}; 251} // namespace V1_0 252} // namespace Mtp 253} // namespace Gadget 254} // namespace Usb 255} // namespace HDI 256} // namespace OHOS 257 258#endif // OHOS_HDI_USB_GADGET_MTP_V1_0_USBFNMTPIMPL_H 259