• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include "linux_serial.h"
16 #include <hdf_base.h>
17 #include <hdf_log.h>
18 #include <unistd.h>
19 #include <cstdlib>
20 #include <fcntl.h>
21 #include <cstring>
22 #include <cerrno>
23 #include <cstdio>
24 #include <cctype>
25 #include <sys/un.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #include <sys/select.h>
30 #include "usbd_wrapper.h"
31 #include "securec.h"
32 
33 #define UEVENT_BUFFER_SIZE 2048
34 #define CMSPAR 010000000000
35 #define BUFF_SIZE 50
36 #define SYSFS_PATH_LEN   128
37 #define RETRY_NUM 5
38 
39 #define ERR_CODE_IOEXCEPTION (-5)
40 #define ERR_CODE_DEVICENOTOPEN (-6)
41 #define ERR_CODE_TIMEOUT (-7)
42 
43 namespace OHOS {
44 namespace HDI {
45 namespace Usb {
46 namespace Serial {
47 namespace V1_0 {
48 
49 static const std::string SERIAL_TYPE_NAME = "ttyUSB";
50 static const int32_t ERR_NO = -1;
51 typedef std::pair<int32_t, int32_t> BaudratePair;
52 
53 BaudratePair g_baudratePairs[] = {
54     {BAUDRATE_50, B50},
55     {BAUDRATE_75, B75},
56     {BAUDRATE_110, B110},
57     {BAUDRATE_134, B134},
58     {BAUDRATE_150, B150},
59     {BAUDRATE_200, B200},
60     {BAUDRATE_300, B300},
61     {BAUDRATE_600, B600},
62     {BAUDRATE_1200, B1200},
63     {BAUDRATE_1800, B1800},
64     {BAUDRATE_2400, B2400},
65     {BAUDRATE_4800, B4800},
66     {BAUDRATE_9600, B9600},
67     {BAUDRATE_19200, B19200},
68     {BAUDRATE_38400, B38400},
69     {BAUDRATE_57600, B57600},
70     {BAUDRATE_115200, B115200},
71     {BAUDRATE_230400, B230400},
72     {BAUDRATE_460800, B460800},
73     {BAUDRATE_500000, B500000},
74     {BAUDRATE_576000, B576000},
75     {BAUDRATE_921600, B921600},
76     {BAUDRATE_1000000, B1000000},
77     {BAUDRATE_1152000, B1152000},
78     {BAUDRATE_1500000, B1500000},
79     {BAUDRATE_2000000, B2000000},
80     {BAUDRATE_2500000, B2500000},
81     {BAUDRATE_3000000, B3000000},
82     {BAUDRATE_3500000, B3500000},
83     {BAUDRATE_4000000, B4000000},
84 };
85 
LinuxSerial()86 LinuxSerial::LinuxSerial()
87 {
88 }
89 
~LinuxSerial()90 LinuxSerial::~LinuxSerial()
91 {
92 }
93 
GetInstance()94 LinuxSerial &LinuxSerial::GetInstance()
95 {
96     static LinuxSerial instance;
97     return instance;
98 }
99 
GetBaudrate(unsigned int baudrate)100 int32_t LinuxSerial::GetBaudrate(unsigned int baudrate)
101 {
102     for (const auto& pair : g_baudratePairs) {
103         if (pair.first == baudrate) {
104             return pair.second;
105         }
106     }
107     return HDF_FAILURE;
108 }
109 
GetDatabits(unsigned char dataBits)110 tcflag_t LinuxSerial::GetDatabits(unsigned char dataBits)
111 {
112     tcflag_t bit_temp;
113     switch (dataBits) {
114         case USB_ATTR_DATABIT_4:
115             HDF_LOGE("%{public}s: Not Supported 4 data bits.", __func__);
116             return HDF_FAILURE;
117         case USB_ATTR_DATABIT_5:
118             bit_temp = CS5;
119             break;
120         case USB_ATTR_DATABIT_6:
121             bit_temp = CS6;
122             break;
123         case USB_ATTR_DATABIT_7:
124             bit_temp = CS7;
125             break;
126         case USB_ATTR_DATABIT_8:
127             bit_temp = CS8;
128             break;
129         default:
130             return HDF_FAILURE;
131         }
132         return bit_temp;
133 }
134 
GetParity(tcflag_t c_cflag,unsigned char parity)135 tcflag_t LinuxSerial::GetParity(tcflag_t c_cflag, unsigned char parity)
136 {
137     c_cflag &= ~(PARENB | PARODD);
138     c_cflag |= PARENB;
139     if (parity == USB_ATTR_PARITY_NONE) {
140         c_cflag &= ~PARENB;
141     } else if (parity == USB_ATTR_PARITY_ODD) {
142         c_cflag |= PARODD;
143     } else if (parity == USB_ATTR_PARITY_EVEN) {
144         c_cflag &= ~PARODD;
145     } else if (parity == USB_ATTR_PARITY_MARK || parity == USB_ATTR_PARITY_SPACE) {
146         HDF_LOGE("%{public}s: Not Supported Mark and Space.", __func__);
147         return HDF_FAILURE;
148     } else {
149         HDF_LOGE("%{public}s: Parity not exist!", __func__);
150         return HDF_FAILURE;
151     }
152     return c_cflag;
153 }
154 
GetStopbits(tcflag_t c_cflag,unsigned char stopBits)155 tcflag_t LinuxSerial::GetStopbits(tcflag_t c_cflag, unsigned char stopBits)
156 {
157     if (stopBits == USB_ATTR_STOPBIT_1) {
158         c_cflag &= ~CSTOPB;
159     } else if (stopBits == USB_ATTR_STOPBIT_1P5) {
160         HDF_LOGE("%{public}s: Not Supported 1.5.", __func__);
161         return HDF_FAILURE;
162     } else if (stopBits == USB_ATTR_STOPBIT_2) {
163         c_cflag |= CSTOPB;
164     } else {
165         return HDF_FAILURE;
166     }
167     return c_cflag;
168 }
169 
GetFdByPortId(int32_t portId)170 int32_t LinuxSerial::GetFdByPortId(int32_t portId)
171 {
172     size_t index = 0;
173     bool isFound = false;
174     std::lock_guard<std::mutex> lock(portMutex_);
175     for (index = 0; index < serialPortList_.size(); index++) {
176         if (portId == serialPortList_[index].portId) {
177             isFound = true;
178             break;
179         }
180     }
181     if (!isFound) {
182         HDF_LOGE("%{public}s: not find portId.", __func__);
183         return HDF_FAILURE;
184     }
185     if (ERR_NO == serialPortList_[index].fd) {
186         HDF_LOGE("%{public}s: fd not exist.", __func__);
187         return HDF_FAILURE;
188     }
189     return serialPortList_[index].fd;
190 }
191 
SerialOpen(int32_t portId)192 int32_t LinuxSerial::SerialOpen(int32_t portId)
193 {
194     std::lock_guard<std::mutex> lock(portMutex_);
195     size_t index = 0;
196     bool isFound = false;
197     char path[BUFF_SIZE] = {'\0'};
198     for (index = 0; index < serialPortList_.size(); index++) {
199         if (portId == serialPortList_[index].portId) {
200             isFound = true;
201             break;
202         }
203     }
204     if (!isFound) {
205         HDF_LOGE("%{public}s: not find portId.", __func__);
206         return HDF_FAILURE;
207     }
208     if (ERR_NO != serialPortList_[index].fd) {
209         HDF_LOGE("%{public}s: device has been opened,fd=%{public}d", __func__, serialPortList_[index].fd);
210         return HDF_FAILURE;
211     }
212     int32_t ret = 0;
213     ret = snprintf_s(path, sizeof(path), sizeof(path)-1, "/dev/ttyUSB%d", portId);
214     if (ret < 0) {
215         HDF_LOGE("%{public}s: sprintf_s path failed, ret:%{public}d", __func__, ret);
216         return ret;
217     }
218     serialPortList_[index].fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
219     if (serialPortList_[index].fd <= 0) {
220         HDF_LOGE("%{public}s: Unable to open serial port.", __func__);
221         return HDF_FAILURE;
222     }
223 
224     tcgetattr(serialPortList_[index].fd, &options_);
225     options_.c_lflag &= ~ICANON;
226     options_.c_lflag &= ~ECHO;
227     tcsetattr(serialPortList_[index].fd, TCSANOW, &options_);
228 
229     return HDF_SUCCESS;
230 }
231 
SerialClose(int32_t portId)232 int32_t LinuxSerial::SerialClose(int32_t portId)
233 {
234     std::lock_guard<std::mutex> lock(portMutex_);
235     size_t index = 0;
236     bool isFound = false;
237     for (index = 0; index < serialPortList_.size(); index++) {
238         if (portId == serialPortList_[index].portId) {
239             isFound = true;
240             break;
241         }
242     }
243     if (!isFound) {
244         HDF_LOGE("%{public}s: not find portId.", __func__);
245         return HDF_FAILURE;
246     }
247     if (ERR_NO == serialPortList_[index].fd) {
248         HDF_LOGE("%{public}s: fd not exist.", __func__);
249         return HDF_FAILURE;
250     }
251     close(serialPortList_[index].fd);
252     serialPortList_[index].fd = -1;
253     return HDF_SUCCESS;
254 }
255 
SerialRead(int32_t portId,std::vector<uint8_t> & data,uint32_t size,uint32_t timeout)256 int32_t LinuxSerial::SerialRead(int32_t portId, std::vector<uint8_t>& data, uint32_t size, uint32_t timeout)
257 {
258     int32_t fd = -1;
259     if (size <= 0) {
260         return HDF_FAILURE;
261     }
262     fd = GetFdByPortId(portId);
263     if (fd < 0) {
264         return ERR_CODE_DEVICENOTOPEN;
265     }
266 
267     fd_set readfds;
268     FD_ZERO(&readfds);
269     FD_SET(fd, &readfds);
270 
271     struct timeval readTimeout;
272     readTimeout.tv_sec = 0;
273     readTimeout.tv_usec = timeout;
274 
275     int32_t status = select(fd + 1, &readfds, nullptr, nullptr, &readTimeout);
276     if (status == -1) {
277         return HDF_FAILURE;
278     } else if (status == 0) {
279         return ERR_CODE_TIMEOUT;
280     } else {
281         int32_t bytesRead = read(fd, data.data(), size);
282         if (bytesRead < 0) {
283             HDF_LOGE("%{public}s: read fail.", __func__);
284             return ERR_CODE_IOEXCEPTION;
285         }
286     }
287     return HDF_SUCCESS;
288 }
289 
SerialWrite(int32_t portId,const std::vector<uint8_t> & data,uint32_t size,uint32_t timeout)290 int32_t LinuxSerial::SerialWrite(int32_t portId, const std::vector<uint8_t>& data, uint32_t size, uint32_t timeout)
291 {
292     int32_t fd;
293     int32_t bytesWritten;
294     fd = GetFdByPortId(portId);
295     if (fd < 0) {
296         return ERR_CODE_DEVICENOTOPEN;
297     }
298     if (data.empty()) {
299         HDF_LOGE("%{public}s: data is empty!", __func__);
300         return HDF_FAILURE;
301     }
302 
303     bytesWritten = write(fd, data.data(), data.size());
304     if (bytesWritten == ERR_NO) {
305         HDF_LOGE("%{public}s: write fail.", __func__);
306         return ERR_CODE_IOEXCEPTION;
307     }
308     return HDF_SUCCESS;
309 }
310 
SerialGetAttribute(int32_t portId,SerialAttribute & attribute)311 int32_t LinuxSerial::SerialGetAttribute(int32_t portId, SerialAttribute& attribute)
312 {
313     HDF_LOGI("%{public}s: enter get attribute.", __func__);
314     int32_t fd = GetFdByPortId(portId);
315     if (fd < 0) {
316         return ERR_CODE_DEVICENOTOPEN;
317     }
318     tcgetattr(fd, &options_);
319 
320     for (const auto& pair : g_baudratePairs) {
321         if (pair.second == cfgetispeed(&options_)) {
322             attribute.baudrate = pair.first;
323         }
324     }
325 
326     int databits = options_.c_cflag & CSIZE;
327     switch (databits) {
328         case CS5:
329             attribute.dataBits = USB_ATTR_DATABIT_5;
330             break;
331         case CS6:
332             attribute.dataBits = USB_ATTR_DATABIT_6;
333             break;
334         case CS7:
335             attribute.dataBits = USB_ATTR_DATABIT_7;
336             break;
337         case CS8:
338             attribute.dataBits = USB_ATTR_DATABIT_8;
339             break;
340         default:
341             HDF_LOGE("%{public}s: Unknown data bits setting", __func__);
342             return HDF_FAILURE;
343     }
344 
345     if (options_.c_cflag & PARENB) {
346         attribute.parity = (options_.c_cflag & PARODD) ? USB_ATTR_PARITY_ODD : USB_ATTR_PARITY_EVEN;
347     } else {
348         attribute.parity = USB_ATTR_PARITY_NONE;
349     }
350 
351     attribute.stopBits = (options_.c_cflag & CSTOPB) ? USB_ATTR_STOPBIT_2 : USB_ATTR_STOPBIT_1;
352     return HDF_SUCCESS;
353 }
354 
SerialSetAttribute(int32_t portId,const SerialAttribute & attribute)355 int32_t LinuxSerial::SerialSetAttribute(int32_t portId, const SerialAttribute& attribute)
356 {
357     HDF_LOGI("%{public}s: enter set attribute.", __func__);
358     int32_t fd;
359     int retry = RETRY_NUM;
360     fd = GetFdByPortId(portId);
361     if (fd < 0) {
362         return ERR_CODE_DEVICENOTOPEN;
363     }
364     tcgetattr(fd, &options_);
365     if (GetStopbits(options_.c_cflag, attribute.stopBits) < 0) {
366         HDF_LOGE("%{public}s: stopBits set fail.", __func__);
367         return GetStopbits(options_.c_cflag, attribute.stopBits);
368     }
369     options_.c_cflag |= (CLOCAL | CREAD);
370     if (GetBaudrate(attribute.baudrate) < 0) {
371         HDF_LOGE("%{public}s: baudrate set fail.", __func__);
372         return HDF_FAILURE;
373     }
374     cfsetispeed(&options_, GetBaudrate(attribute.baudrate));
375     cfsetospeed(&options_, GetBaudrate(attribute.baudrate));
376     options_.c_cflag &= ~CSIZE;
377     if (GetDatabits(attribute.dataBits) < 0) {
378         HDF_LOGE("%{public}s: dataBits set fail.", __func__);
379         return GetDatabits(attribute.dataBits);
380     }
381     options_.c_cflag |= GetDatabits(attribute.dataBits);
382     if (GetParity(options_.c_cflag, attribute.parity)< 0) {
383         HDF_LOGE("%{public}s:parity set fail.", __func__);
384         return GetParity(options_.c_cflag, attribute.parity);
385     }
386     options_.c_cflag = GetParity(options_.c_cflag, attribute.parity);
387     options_.c_cflag = GetStopbits(options_.c_cflag, attribute.stopBits);
388     options_.c_cc[VMIN] = 1;
389     options_.c_cc[VTIME] = 0;
390     while (retry-- > 0) {
391         if (tcsetattr(fd, TCSANOW, &options_) == 0) {
392             break;
393         } else if (errno != EINTR) {
394             HDF_LOGE("%{public}s: tcsetattr failed.", __func__);
395         }
396     }
397     if (retry <= 0) {
398         HDF_LOGE("%{public}s: Failed to set attributes after multiple attempts.", __func__);
399         return ERR_CODE_IOEXCEPTION;
400     }
401     return HDF_SUCCESS;
402 }
403 
HandleDevListEntry(struct UsbPnpNotifyMatchInfoTable * device,std::vector<SerialPort> & portIds)404 void LinuxSerial::HandleDevListEntry(struct UsbPnpNotifyMatchInfoTable *device, std::vector<SerialPort>& portIds)
405 {
406     SerialPort serialPort;
407     Serialfd serialPortId;
408     struct UsbPnpNotifyDeviceInfo *devInfo = &device->deviceInfo;
409     HDF_LOGI("%{public}s: device: devNum = %{public}d, busNum = %{public}d, numInfos = %{public}d",
410         __func__, device->devNum, device->busNum, device->numInfos);
411     HDF_LOGI("%{public}s: device info: vendorId = %{public}d, productId = %{public}d, deviceClass = %{public}d",
412         __func__, devInfo->vendorId, devInfo->productId, devInfo->deviceClass);
413 
414     char nodePath[SYSFS_PATH_LEN] = { 0x00 };
415     DevInterfaceInfo interfaceInfo;
416     interfaceInfo.busNum = device->busNum;
417     interfaceInfo.devNum = device->devNum;
418     interfaceInfo.intfNum = 0;
419     int32_t ret = DdkSysfsGetDevNodePath(&interfaceInfo, SERIAL_TYPE_NAME.c_str(), nodePath, sizeof(nodePath));
420     if (ret != HDF_SUCCESS) {
421         HDF_LOGE("%{public}s: Get device node path failed.", __func__);
422         return;
423     }
424     HDF_LOGI("%{public}s: Device node path: %{public}s", __func__, nodePath);
425     std::string devnameStr(nodePath);
426     int32_t pos = devnameStr.find(SERIAL_TYPE_NAME);
427     if (pos != std::string::npos) {
428         std::string numStr = devnameStr.substr(pos + SERIAL_TYPE_NAME.length());
429         int num = atoi(numStr.c_str());
430         serialPort.portId = num;
431         serialPortId.portId = num;
432         serialPortId.fd = -1;
433     }
434     serialPort.deviceInfo.busNum = static_cast<uint8_t>(device->busNum);
435     serialPort.deviceInfo.devAddr = static_cast<uint8_t>(device->devNum);
436     serialPort.deviceInfo.vid = static_cast<int32_t>(devInfo->vendorId);
437     serialPort.deviceInfo.pid = static_cast<int32_t>(devInfo->productId);
438     // serialPort.deviceInfo.serialNum = "";
439     auto it = std::find_if(serialPortList_.begin(), serialPortList_.end(), [&](const Serialfd& tempSerial) {
440         return tempSerial.portId == serialPortId.portId;
441     });
442     if (it == serialPortList_.end()) {
443         serialPortList_.push_back(serialPortId);
444     }
445     portIds.push_back(serialPort);
446 }
447 
DdkDevMgrInitDevice(struct UsbDdkDeviceInfo * deviceInfo)448 static int32_t DdkDevMgrInitDevice(struct UsbDdkDeviceInfo *deviceInfo)
449 {
450     (void)memset_s(deviceInfo, sizeof(struct UsbDdkDeviceInfo), 0, sizeof(struct UsbDdkDeviceInfo));
451     int32_t ret = OsalMutexInit(&deviceInfo->deviceMutex);
452     if (ret != HDF_SUCCESS) {
453         HDF_LOGE("%{public}s: init mutex failed", __func__);
454         return HDF_FAILURE;
455     }
456     DListHeadInit(&deviceInfo->list);
457 
458     return HDF_SUCCESS;
459 }
460 
SerialGetPortList(std::vector<SerialPort> & portIds)461 int32_t LinuxSerial::SerialGetPortList(std::vector<SerialPort>& portIds)
462 {
463     DIR *dir = opendir(SYSFS_DEVICES_DIR);
464     if (dir == NULL) {
465         HDF_LOGE("%{public}s: opendir failed sysfsDevDir:%{public}s", __func__, SYSFS_DEVICES_DIR);
466         return HDF_FAILURE;
467     }
468 
469     struct UsbDdkDeviceInfo *device = (struct UsbDdkDeviceInfo *)OsalMemCalloc(sizeof(struct UsbDdkDeviceInfo));
470     if (device == NULL) {
471         HDF_LOGE("%{public}s: init device failed", __func__);
472         return HDF_FAILURE;
473     }
474     int32_t status = HDF_SUCCESS;
475     struct dirent *devHandle;
476     while ((devHandle = readdir(dir))) {
477         if (devHandle->d_name[0] > '9' || devHandle->d_name[0] < '0' || strchr(devHandle->d_name, ':')) {
478             continue;
479         }
480         status = DdkDevMgrInitDevice(device);
481         if (status != HDF_SUCCESS) {
482             HDF_LOGE("%{public}s: init device failed:%{public}d", __func__, status);
483             break;
484         }
485         status = DdkSysfsGetDevice(devHandle->d_name, &device->info);
486         if (status != HDF_SUCCESS) {
487             HDF_LOGE("%{public}s: sysfs get device failed:%{public}d", __func__, status);
488             break;
489         }
490         HandleDevListEntry(&device->info, portIds);
491     }
492 
493     OsalMemFree(device);
494     closedir(dir);
495     return HDF_SUCCESS;
496 }
497 } // V1_0
498 } // Serial
499 } // Usb
500 } // HDI
501 } // OHOS
502