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