• 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 
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