1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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 "usb_accessory_uevent_handle.h"
17 #include "hdf_base.h"
18 #include "hdf_log.h"
19 #include "usbd_wrapper.h"
20 #include "ddk_pnp_listener_mgr.h"
21 
22 #define HDF_LOG_TAG usb_accessory_uevent
23 
24 char *g_usbAccessoryUeventPath = "invalid_path";
25 
26 struct UsbAccessoryUeventInfo {
27     const char *devPath;
28     const char *subSystem;
29     const char *accessory;
30     const char *devName;
31 };
32 
UsbAccessoryDispatchUevent(const struct UsbAccessoryUeventInfo * info)33 static void UsbAccessoryDispatchUevent(const struct UsbAccessoryUeventInfo *info)
34 {
35     HDF_LOGD("%{public}s: devPath: %{public}s, accessory: %{public}s", __func__, info->devPath, info->accessory);
36     if (strcmp(info->devPath, g_usbAccessoryUeventPath) != 0) {
37         return;
38     }
39     if (strcmp(info->accessory, "START") == 0) {
40         DdkListenerMgrNotifyAll(NULL, USB_ACCESSORY_START);
41     } else if (strcmp(info->accessory, "SEND") == 0) {
42         DdkListenerMgrNotifyAll(NULL, USB_ACCESSORY_SEND);
43     }
44 }
45 
UsbAccessoryUeventHandle(const char msg[],ssize_t rcvLen)46 void UsbAccessoryUeventHandle(const char msg[], ssize_t rcvLen)
47 {
48     HDF_LOGD("%{public}s: msg: %{public}s, len: %{public}zd", __func__, msg, rcvLen);
49     char fullMsg[rcvLen + 1];
50     for (int i = 0; i < rcvLen; i++) {
51         if (msg[i] == '\0') {
52             fullMsg[i] = ' ';
53         } else {
54             fullMsg[i] = msg[i];
55         }
56     }
57     fullMsg[rcvLen] = '\0';
58     HDF_LOGD("%{public}s:Full message: %{public}s", __func__, fullMsg);
59 
60     struct UsbAccessoryUeventInfo info = {
61         .devPath = "",
62         .subSystem = "",
63         .accessory = "",
64         .devName = ""
65     };
66     const char *msgTmp = msg;
67     while (*msgTmp && (msgTmp - msg < rcvLen)) {
68         if (strncmp(msgTmp, "DEVPATH=", strlen("DEVPATH=")) == 0) {
69             msgTmp += strlen("DEVPATH=");
70             info.devPath = msgTmp;
71         } else if (strncmp(msgTmp, "SUBSYSTEM=", strlen("SUBSYSTEM=")) == 0 &&
72             strlen(info.subSystem) == 0) { // some uevent has more than one SUBSYSTEM property
73             msgTmp += strlen("SUBSYSTEM=");
74             info.subSystem = msgTmp;
75         } else if (strncmp(msgTmp, "ACCESSORY=", strlen("ACCESSORY=")) == 0) {
76             msgTmp += strlen("ACCESSORY=");
77             info.accessory = msgTmp;
78         } else if (strncmp(msgTmp, "DEVNAME=", strlen("DEVNAME=")) == 0) {
79             msgTmp += strlen("DEVNAME=");
80             info.devName = msgTmp;
81         }
82         msgTmp += strlen(msgTmp) + 1; // 1 is a skip character '\0'
83     }
84 
85     UsbAccessoryDispatchUevent(&info);
86 }
87 
UsbAccessoryUeventInit(const char * ueventPath)88 int32_t UsbAccessoryUeventInit(const char *ueventPath)
89 {
90     if (ueventPath == NULL) {
91         HDF_LOGE("%{public}s invalid param", __func__);
92         return HDF_ERR_INVALID_PARAM;
93     }
94     HDF_LOGD("%{public}s: enter, ueventPath: %{public}s", __func__, ueventPath);
95 
96     g_usbAccessoryUeventPath = (char *)ueventPath;
97     return HDF_SUCCESS;
98 }
99