• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "serial_sysfs_device.h"
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <cinttypes>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <regex.h>
24 #include <hdf_base.h>
25 
26 #include "hdf_log.h"
27 #include "securec.h"
28 #include "usbd_wrapper.h"
29 
30 #define SEIAL_NUMBER_NAME "serial"
31 #define SYSFS_PATH_LEN   128
32 #define PROPERTY_MAX_LEN 128
33 #define HDF_LOG_TAG      usb_ddk_sysfs_dev
34 
35 namespace OHOS {
36 namespace HDI {
37 namespace Usb {
38 namespace Serial {
39 namespace V1_0 {
40 
41 const int32_t DEC_BASE = 10;
42 const int32_t HEX_BASE = 16;
43 const uint64_t MOVE_NUM = 32;
44 
SerialGetBase(const char * propName)45 static inline int32_t SerialGetBase(const char *propName)
46 {
47     if (strcmp(propName, "idProduct") == 0 || strcmp(propName, "idVendor") == 0 ||
48         strcmp(propName, "bInterfaceNumber") == 0 || strcmp(propName, "bInterfaceProtocol") == 0 ||
49         strcmp(propName, "bInterfaceClass") == 0 || strcmp(propName, "bInterfaceSubClass") == 0) {
50         return HEX_BASE;
51     }
52     return DEC_BASE;
53 }
54 
SerialMakeDevAddr(uint32_t busNum,uint32_t devNum)55 inline uint64_t SerialMakeDevAddr(uint32_t busNum, uint32_t devNum)
56 {
57     return ((static_cast<uint64_t>(busNum) << MOVE_NUM) | devNum);
58 }
59 
SerialReadProperty(const char * deviceDir,const char * propName,int64_t * value,uint64_t maxVal)60 static int32_t SerialReadProperty(const char *deviceDir, const char *propName, int64_t *value, uint64_t maxVal)
61 {
62     char pathTmp[SYSFS_PATH_LEN] = {0};
63     int32_t num = 0;
64     num = sprintf_s(pathTmp, SYSFS_PATH_LEN, "%s/%s", deviceDir, propName);
65     if (num <= 0) {
66         HDF_LOGE("%{public}s: sprintf_s error deviceDir:%{public}s, propName:%{public}s",
67             __func__, deviceDir, propName);
68         return HDF_FAILURE;
69     }
70     // read string from file
71     char path[PATH_MAX] = {'\0'};
72     if (realpath(pathTmp, path) == nullptr) {
73         HDF_LOGE("file %{public}s is invalid", pathTmp);
74         return HDF_FAILURE;
75     }
76     int32_t fd = open(path, O_RDONLY | O_CLOEXEC);
77     if (fd == -1) {
78         HDF_LOGE("%{public}s: open file failed path:%{public}s, errno:%{public}d", __func__, path, errno);
79         return HDF_ERR_IO;
80     }
81     int32_t ret = HDF_SUCCESS;
82     do {
83         char buf[PROPERTY_MAX_LEN] = {0};
84         ssize_t numRead = read(fd, buf, PROPERTY_MAX_LEN);
85         if (numRead <= 0) {
86             HDF_LOGE("%{public}s: read prop failed path:%{public}s, errno:%{public}d", __func__, path, errno);
87             ret = HDF_ERR_IO;
88             break;
89         }
90         // convert string to int64_t
91         if (buf[numRead - 1] != '\n') {
92             HDF_LOGE("%{public}s: prop is not end with newline path:%{public}s", __func__, path);
93             ret = HDF_ERR_INVALID_PARAM;
94             break;
95         }
96         buf[numRead - 1] = '\0';
97         int64_t res = strtoll(buf, nullptr, SerialGetBase(propName));
98         if (res == LLONG_MAX || res == LLONG_MIN || res > (int64_t)maxVal) {
99             HDF_LOGE("%{public}s: convert failed path:%{public}s, res:%{public}" PRId64 "", __func__, path, res);
100             ret = HDF_ERR_INVALID_PARAM;
101             break;
102         }
103         *value = res;
104     } while (0);
105 
106     close(fd);
107     return ret;
108 }
109 
SerialGetSerialNo(const char * deviceDir)110 static std::string SerialGetSerialNo(const char *deviceDir)
111 {
112     std::string serialNo;
113     char pathTmp[SYSFS_PATH_LEN] = {0};
114     int32_t num = sprintf_s(pathTmp, SYSFS_PATH_LEN, "%s/%s", deviceDir, SEIAL_NUMBER_NAME);
115     if (num <= 0) {
116         HDF_LOGE("%{public}s: sprintf_s error deviceDir:%{public}s, propName:%{public}s",
117             __func__, deviceDir, SEIAL_NUMBER_NAME);
118         return serialNo;
119     }
120     char path[PATH_MAX] = {'\0'};
121     if (realpath(pathTmp, path) == nullptr) {
122         HDF_LOGE("file %{public}s is invalid", pathTmp);
123         return serialNo;
124     }
125     int32_t fd = open(path, O_RDONLY | O_CLOEXEC);
126     if (fd == -1) {
127         HDF_LOGE("%{public}s: open file failed path:%{public}s, errno:%{public}d", __func__, path, errno);
128         return serialNo;
129     }
130     char buf[PROPERTY_MAX_LEN] = {0};
131     do {
132         ssize_t numRead = read(fd, buf, PROPERTY_MAX_LEN);
133         if (numRead <= 0) {
134             HDF_LOGE("%{public}s: read prop failed path:%{public}s, errno:%{public}d", __func__, path, errno);
135             break;
136         }
137         if (buf[numRead - 1] != '\n') {
138             HDF_LOGE("%{public}s: prop is not end with newline path:%{public}s", __func__, path);
139             break;
140         }
141         buf[numRead - 1] = '\0';
142         serialNo = std::string(buf);
143     } while (0);
144 
145     close(fd);
146     return serialNo;
147 }
148 
SerialGetDevice(const char * deviceDir,struct UsbPnpNotifyMatchInfoTable * device)149 int32_t SerialGetDevice(const char *deviceDir, struct UsbPnpNotifyMatchInfoTable *device)
150 {
151     int64_t value = 0;
152     int32_t ret = SerialReadProperty(deviceDir, "devnum", &value, INT32_MAX);
153     device->devNum = static_cast<int32_t>(value);
154     ret += SerialReadProperty(deviceDir, "busnum", &value, INT32_MAX);
155     device->busNum = static_cast<int32_t>(value);
156     ret += SerialReadProperty(deviceDir, "bNumInterfaces", &value, UINT8_MAX);
157     device->numInfos = static_cast<uint8_t>(value);
158 
159     struct UsbPnpNotifyDeviceInfo *devInfo = &device->deviceInfo;
160     ret += SerialReadProperty(deviceDir, "idVendor", &value, UINT16_MAX);
161     devInfo->vendorId = static_cast<uint16_t>(value);
162     ret += SerialReadProperty(deviceDir, "idProduct", &value, UINT16_MAX);
163     devInfo->productId = static_cast<uint16_t>(value);
164     ret += SerialReadProperty(deviceDir, "bcdDevice", &value, UINT16_MAX);
165     devInfo->bcdDeviceLow = static_cast<uint16_t>(value);
166     devInfo->bcdDeviceHigh = devInfo->bcdDeviceLow;
167     ret += SerialReadProperty(deviceDir, "bDeviceClass", &value, UINT8_MAX);
168     devInfo->deviceClass = static_cast<uint8_t>(value);
169     ret += SerialReadProperty(deviceDir, "bDeviceSubClass", &value, UINT8_MAX);
170     devInfo->deviceSubClass = static_cast<uint8_t>(value);
171     ret += SerialReadProperty(deviceDir, "bDeviceProtocol", &value, UINT8_MAX);
172     devInfo->deviceProtocol = static_cast<uint8_t>(value);
173     devInfo->serialNo = SerialGetSerialNo(deviceDir);
174     if (ret != HDF_SUCCESS) {
175         HDF_LOGE("%{public}s: get property failed:%{public}d", __func__, ret);
176         return ret;
177     }
178     return HDF_SUCCESS;
179 }
180 
181 } // V1_0
182 } // Serial
183 } // Usb
184 } // HDI
185 } // OHOS