1/*
2 * Copyright (c) 2021-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#include "cstdio"
17#include "usb_common_test.h"
18#include "usb_srv_client.h"
19#include "cJSON.h"
20#include "common_event_manager.h"
21#include "common_event_support.h"
22
23using namespace std;
24using namespace OHOS;
25using namespace OHOS::USB;
26using namespace OHOS::USB::Common;
27using namespace OHOS::EventFwk;
28static constexpr int32_t DEFAULT_PORT_ID = 1;
29static constexpr int32_t DEFAULT_ROLE_HOST = 1;
30static constexpr int32_t DEFAULT_ROLE_DEVICE = 2;
31static constexpr int32_t MIN_ARG_NUM = 3;
32static constexpr uint32_t CMD_INDEX = 1;
33static constexpr uint32_t PARAM_INDEX = 2;
34
35static constexpr int32_t HOST_MODE = 2;
36
37static UsbSrvClient &g_usbClient = UsbSrvClient::GetInstance();
38
39static void PrintHelp()
40{
41    printf("2 args\n");
42    printf("-p 0: Query Port\n");
43    printf("-p 1: Switch to host\n");
44    printf("-p 2: Switch to device:\n");
45    printf("-f 0: Query function\n");
46    printf("-f 1: Switch to function:acm\n");
47    printf("-f 2: Switch to function:ecm\n");
48    printf("-f 3: Switch to function:acm&ecm\n");
49    printf("-f 4: Switch to function:hdc\n");
50    printf("-f 5: Switch to function:acm&hdc\n");
51    printf("-f 6: Switch to function:ecm&hdc\n");
52    printf("-f 8: Switch to function:mtp\n");
53    printf("-f 16: Switch to function:ptp\n");
54    printf("-f 32: Switch to function:rndis\n");
55    printf("-f 512: Switch to function:storage\n");
56    printf("-f 36: Switch to function:rndis&hdc\n");
57    printf("-f 516: Switch to function:storage&hdc\n");
58    printf("-c 1: Switch to recv braodcast\n");
59    printf("-s 0: Get devicespeed\n");
60    printf("-s 1: Get interface actived\n");
61    printf("-r 0: Reset proxy\n");
62}
63
64class UsbSubscriberTest : public CommonEventSubscriber {
65public:
66    explicit UsbSubscriberTest(const CommonEventSubscribeInfo &sp) : CommonEventSubscriber(sp) {}
67
68    void OnReceiveEvent(const CommonEventData &data) override
69    {
70        USB_HILOGI(MODULE_USB_SERVICE, "recv event ok");
71        eventData_ = data;
72        std::string deviceStr = eventData_.GetData();
73        USB_HILOGI(MODULE_USB_SERVICE, "recv broadcast: %{public}s", deviceStr.c_str());
74
75        cJSON* pDevice =  cJSON_Parse(deviceStr.c_str());
76        UsbDevice device(pDevice);
77        std::string strConfig = "null";
78        if (device.GetConfigCount() > 0) {
79            USBConfig config;
80            device.GetConfig(0, config);
81            strConfig = config.ToString();
82        }
83        USB_HILOGI(MODULE_USB_SERVICE, "recv broadcast:Name: %{public}s, config size: %{public}d, config0: %{public}s",
84            device.GetName().c_str(), device.GetConfigCount(), strConfig.c_str());
85    }
86
87    static CommonEventData eventData_;
88};
89
90CommonEventData UsbSubscriberTest::eventData_ {};
91std::shared_ptr<UsbSubscriberTest> subscriber = nullptr;
92static void AddCommonEvent()
93{
94    MatchingSkills matchingSkills;
95    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USB_DEVICE_DETACHED);
96    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USB_DEVICE_ATTACHED);
97    matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USB_STATE);
98    CommonEventSubscribeInfo subscriberInfo(matchingSkills);
99    subscriber = std::make_shared<UsbSubscriberTest>(subscriberInfo);
100    bool ret = CommonEventManager::SubscribeCommonEvent(subscriber);
101    if (!ret) {
102        USB_HILOGW(MODULE_USB_SERVICE, "subscriber event for failed: %{public}d", ret);
103    }
104}
105
106static void StopSubscriberCommonEvent(int32_t signo)
107{
108    (void) signo;
109    if (subscriber != nullptr) {
110        CommonEventManager::UnSubscribeCommonEvent(subscriber);
111    }
112    std::cout << "stop recv broadcast."<< std::endl;
113    USB_HILOGI(MODULE_USB_SERVICE, "stop recv broadcast.");
114}
115
116static void GetCurrentFunctionInfo()
117{
118    int32_t funcs = 0;
119    string strFun = "";
120    int32_t ret = g_usbClient.GetCurrentFunctions(funcs);
121    if (ret) {
122        printf("%s:%d error exit\n", __func__, __LINE__);
123        return;
124    }
125    strFun = g_usbClient.UsbFunctionsToString(funcs);
126    printf("%s:%d get current function: %s\n", __func__, __LINE__, strFun.c_str());
127}
128
129static void FunctionSwitch(UsbSrvClient &g_usbClient, int32_t mode)
130{
131    switch (mode) {
132        case 0:
133            GetCurrentFunctionInfo();
134            break;
135        default:
136            int32_t ret = g_usbClient.SetCurrentFunctions(mode);
137            if (ret) {
138                printf("%s:%d error exit\n", __func__, __LINE__);
139                break;
140            }
141            GetCurrentFunctionInfo();
142            break;
143    }
144}
145
146static void GetPortsInfo()
147{
148    std::vector<UsbPort> usbports;
149    int32_t ret = g_usbClient.GetPorts(usbports);
150    if (ret) {
151        printf("%s:%d error exit\n", __func__, __LINE__);
152        return;
153    }
154
155    if (usbports[0].usbPortStatus.currentMode == HOST_MODE) {
156        printf("get current port %d: host\n", usbports[0].usbPortStatus.currentMode);
157    } else {
158        printf("get current port %d: device\n", usbports[0].usbPortStatus.currentMode);
159    }
160}
161
162static void PortSwitch(UsbSrvClient &g_usbClient, int32_t mode)
163{
164    switch (mode) {
165        case 0:
166            GetPortsInfo();
167            break;
168        case DEFAULT_ROLE_HOST:
169            g_usbClient.SetPortRole(DEFAULT_PORT_ID, DEFAULT_ROLE_HOST, DEFAULT_ROLE_HOST);
170            GetPortsInfo();
171            break;
172        case DEFAULT_ROLE_DEVICE:
173            g_usbClient.SetPortRole(DEFAULT_PORT_ID, DEFAULT_ROLE_DEVICE, DEFAULT_ROLE_DEVICE);
174            GetPortsInfo();
175            break;
176        default:
177            printf("%s:%d port param error\n", __func__, __LINE__);
178            break;
179    }
180}
181
182static void DeviceSpeed(UsbSrvClient &g_usbClient, int32_t &sp)
183{
184    vector<UsbDevice> devi;
185    g_usbClient.GetDevices(devi);
186    USBDevicePipe pipe;
187    UsbDevice device = devi.front();
188    g_usbClient.OpenDevice(device, pipe);
189    uint8_t speed = -1;
190    g_usbClient.GetDeviceSpeed(pipe, speed);
191    sp = speed;
192    return;
193}
194
195static void InterfaceStatus(UsbSrvClient &g_usbClient, int32_t &ds)
196{
197    vector<UsbDevice> devi;
198    g_usbClient.GetDevices(devi);
199    USBDevicePipe pipe;
200    UsbDevice device = devi.front();
201    g_usbClient.OpenDevice(device, pipe);
202    UsbInterface interface = device.GetConfigs().front().GetInterfaces().at(0);
203    bool unactivated = false;
204    g_usbClient.GetInterfaceActiveStatus(pipe, interface, unactivated);
205    unactivated ? ds = 1 : ds = 0;
206    return;
207}
208
209static void ResetProxy(UsbSrvClient &g_usbClient, int32_t &sp)
210{
211    vector<UsbDevice> devi;
212    g_usbClient.GetDevices(devi);
213    USBDevicePipe pipe;
214    UsbDevice device = devi.front();
215    g_usbClient.OpenDevice(device, pipe);
216    std::cout << "please kill service, press enter to continue" << std::endl;
217    int32_t ch = 0;
218    while (ch != EOF) {
219        if ((ch = getchar()) == '\n') {
220            break;
221        }
222    }
223    uint8_t speed = -1;
224    g_usbClient.GetDeviceSpeed(pipe, speed);
225    sp = speed;
226    return;
227}
228
229static void DeviceStatus(UsbSrvClient &g_usbClient, int32_t mode)
230{
231    switch (mode) {
232        case 0:
233            int32_t sp;
234            DeviceSpeed(g_usbClient, sp);
235            printf("%s:%d device speed=%d\n", __func__, __LINE__, sp);
236            break;
237        case 1:
238            int32_t ds;
239            InterfaceStatus(g_usbClient, ds);
240            printf("%s:%d interface status=%d\n", __func__, __LINE__, ds);
241            break;
242        default:
243            printf("%s:%d port param error\n", __func__, __LINE__);
244            break;
245    }
246}
247
248static void SetProxy(UsbSrvClient &g_usbClient, int32_t mode)
249{
250    switch (mode) {
251        case 0:
252            int32_t sp;
253            ResetProxy(g_usbClient, sp);
254            if (sp > 0) {
255                printf("%s:%d ResetProxy Okay\n", __func__, __LINE__);
256            } else {
257                printf("%s:%d ResetProxy failed\n", __func__, __LINE__);
258            }
259            break;
260        default:
261            printf("%s:%d port param error\n", __func__, __LINE__);
262            break;
263    }
264}
265
266static inline bool isNumber(string_view strv)
267{
268    return (strv.find_first_not_of("0123456789") == strv.npos);
269}
270
271int32_t main(int32_t argc, char *argv[])
272{
273    UsbCommonTest::GrantPermissionSysNative();
274
275    if (argc < MIN_ARG_NUM) {
276        PrintHelp();
277        return 0;
278    }
279
280    if (!isNumber(argv[PARAM_INDEX])) {
281        PrintHelp();
282        return 0;
283    }
284
285    uint32_t mode;
286    if ((!strcmp(argv[CMD_INDEX], "-f"))) {
287        mode = stoi(argv[PARAM_INDEX]);
288        FunctionSwitch(g_usbClient, mode);
289    } else if (!strcmp(argv[CMD_INDEX], "-p")) {
290        mode = stoi(argv[PARAM_INDEX]);
291        PortSwitch(g_usbClient, mode);
292    } else if (!strcmp(argv[CMD_INDEX], "-s")) {
293        mode = stoi(argv[PARAM_INDEX]);
294        DeviceStatus(g_usbClient, mode);
295    } else if (!strcmp(argv[CMD_INDEX], "-r")) {
296        mode = stoi(argv[PARAM_INDEX]);
297        SetProxy(g_usbClient, mode);
298    } else if (!strcmp(argv[CMD_INDEX], "-c")) {
299        AddCommonEvent();
300        printf("Press input c to exit.\n");
301        char ch = getchar();
302        while (ch != 'c') {
303            ch = getchar();
304            if (ch == 'c') {
305                StopSubscriberCommonEvent(0);
306                break;
307            }
308            sleep(1);
309        }
310        printf("show boac exit.\n");
311    } else {
312        printf("param incorrect: please input -h for help\n");
313    }
314    return 0;
315}
316