~aleteoryx/muditaos

ref: caa4ecec76c52a68ad542c692338414975b9aee9 muditaos/module-bsp/board/linux/usb_cdc/usb_cdc.cpp -rw-r--r-- 4.0 KiB
caa4ecec — Mateusz Grzegorzek Revert "[EGD-4532] Implement dumping logs to a file for RT1051 (#1114)" (#1197) 5 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "bsp/usb/usb.hpp"
#include <termios.h>
#include <fcntl.h>
#include <fstream>

namespace bsp
{
    int fd;
    xQueueHandle USBReceiveQueue;
    constexpr auto ptsFileName = "/tmp/purephone_pts_name";

    void usbDeviceTask(void *ptr)
    {
        usbCDCReceive(ptr);
    }

    int usbCDCReceive(void *)
    {
        LOG_INFO("[ServiceDesktop:BSP_Driver] Start reading on fd:%d", fd);
        uint8_t inputData[SERIAL_BUFFER_LEN];
        static std::string receiveMsg;

        while (1) {
            if (uxQueueSpacesAvailable(USBReceiveQueue) != 0) {
                ssize_t length = read(fd, &inputData[0], SERIAL_BUFFER_LEN);
                if (length > 0) {
                    receiveMsg = std::string(inputData, inputData + length);
                    LOG_DEBUG("[ServiceDesktop:BSP_Driver] Received: %d signs", static_cast<int>(length));
                    xQueueSend(USBReceiveQueue, &receiveMsg, portMAX_DELAY);
                }
                else {
                    // yielding task because nothing in a buffer
                    vTaskDelay(10);
                }
            }
            else {
                LOG_DEBUG("[ServiceDesktop:BSP_Driver] USB receive Queue is full, yielding task");
                vTaskDelay(1000);
            }
        }
    }

    int usbCDCSend(std::string *sendMsg)
    {
        ssize_t t = write(fd, (*sendMsg).c_str(), (*sendMsg).length());
        delete sendMsg;

        if (t >= 0) {
            LOG_DEBUG("[ServiceDesktop:BSP_Driver] Send: %d signs", static_cast<int>(t));
            return 0;
        }
        else {
            LOG_ERROR("[ServiceDesktop:BSP_Driver] Writing to PTY failed with code: %d", errno);
            return -1;
        }
    }

    void writePtsToFile(const char *pts_name)
    {
        std::ofstream ptsNameFile;
        ptsNameFile.open(ptsFileName, std::ios::out | std::ios::trunc);
        ptsNameFile << pts_name;
    }

    void usbDeinit()
    {
        LOG_INFO("usbDeinit removing file %s", ptsFileName);
        std::remove(ptsFileName);
    }

    int usbInit(xQueueHandle receiveQueue, USBDeviceListener *)
    {

        fd = 0;
        fd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
        if (fd == -1) {
            LOG_ERROR("bsp::usbInit Failed to open /dev/ptmx, can't allocate new pseudo terminal");
            return -1;
        }

        grantpt(fd);
        unlockpt(fd);

        char *pts_name = ptsname(fd);
        if (pts_name == nullptr) {
            LOG_ERROR("bsp::usbInit ptsname returned NULL, no pseudo terminal allocated");
            return -1;
        }

        writePtsToFile(pts_name);
        LOG_INFO("bsp::usbInit linux ptsname: %s", pts_name);
        struct termios newtio;
        memset(&newtio, 0, sizeof(newtio));
        struct termios oldtio;
        tcgetattr(fd, &oldtio);

        newtio             = oldtio;
        newtio.c_cflag     = SERIAL_BAUDRATE | CS8 | CLOCAL | CREAD;
        newtio.c_iflag     = 0;
        newtio.c_oflag     = 0;
        newtio.c_lflag     = 0;
        newtio.c_cc[VMIN]  = 1;
        newtio.c_cc[VTIME] = 0;
        tcflush(fd, TCIFLUSH);

        cfsetispeed(&newtio, SERIAL_BAUDRATE);
        cfsetospeed(&newtio, SERIAL_BAUDRATE);
        tcsetattr(fd, TCSANOW, &newtio);

        xTaskHandle taskHandleReceive;
        USBReceiveQueue = receiveQueue;

        BaseType_t task_error = xTaskCreate(&bsp::usbDeviceTask,
                                            "USBLinuxReceive",
                                            SERIAL_BUFFER_LEN * 8,
                                            nullptr,
                                            tskIDLE_PRIORITY,
                                            &taskHandleReceive);

        if (task_error != pdPASS) {
            LOG_ERROR("bsp::usbInit Failed to start freertos USB_Linux_Receive");
            return -1;
        }

        return 0;
    }
} // namespace bsp