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