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 */ 58 enum 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 82 struct 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 89 struct UsbMtpPipe { 90 uint8_t id; 91 uint16_t maxPacketSize; 92 struct UsbFnInterface *ctrlIface; 93 }; 94 95 struct UsbMtpInterface { 96 struct UsbFnInterface *fn; 97 UsbFnInterfaceHandle handle; 98 }; 99 100 struct 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 118 struct 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 149 struct CtrlInfo { 150 uint8_t request; 151 struct UsbMtpDevice *mtpDev; 152 }; 153 154 namespace OHOS { 155 namespace HDI { 156 namespace Usb { 157 namespace Gadget { 158 namespace Mtp { 159 namespace V1_0 { 160 class UsbfnMtpImpl : public IUsbfnMtpInterface { 161 public: 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 185 private: 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