/* * @file linux_cellular.cpp * @author Mateusz Piesta (mateusz.piesta@mudita.com) * @date 14.06.19 * @brief * @copyright Copyright (C) 2019 mudita.com * @details */ #include "linux_cellular.hpp" #include #include #include "log/log.hpp" #include "mutex.hpp" #include #include #include #include #include #include #include #include #define _LINUX_UART_DEBUG 0 namespace bsp { std::map PortSpeeds_text = {{9600U, B9600}, {19200U, B19200}, {38400U, B38400}, {57600U, B57600}, {115200U, B115200}, {230400U, B230400}, {460800U, B460800}}; LinuxCellular::LinuxCellular(const char *term, uint32_t portSpeed) { if (strcmp(term, "0") == 0) { fd = 0; } else { // open serial port fd = open(term, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { LOG_FATAL("Failed to open serial port"); return; } struct termios t; memset(&t, 0, sizeof(t)); tcgetattr(fd, &t); cfmakeraw(&t); t.c_cflag |= CLOCAL; // if(ctsrts == 1) // t.c_cflag |= CRTSCTS; //enable the flow control on dev board // else t.c_cflag &= ~(CRTSCTS); // disable the flow control on dev board speed_t speed = PortSpeeds_text[portSpeed]; // B115200; cfsetispeed(&t, speed); cfsetospeed(&t, speed); tcsetattr(fd, TCSANOW, &t); int status = TIOCM_DTR | TIOCM_RTS; ioctl(fd, TIOCMBIS, &status); } epoll_fd = epoll_create1(0); if (epoll_fd == -1) { LOG_FATAL("Failed to create epoll file descriptor"); } struct epoll_event event; event.events = EPOLLIN; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) { LOG_FATAL("Failed to add file descriptor to epoll"); } isInitialized = true; } LinuxCellular::~LinuxCellular() { if (fd >= 0) { close(fd); } if (epoll_fd >= 0) { close(epoll_fd); } } void LinuxCellular::PowerUp() {} void LinuxCellular::PowerDown() {} void LinuxCellular::Restart() {} ssize_t LinuxCellular::Read(void *buf, size_t nbytes) { cpp_freertos::LockGuard lock(serOutMutex); retry: auto ret = read(fd, buf, nbytes); if ((ret == -1) && (errno == EINTR)) { goto retry; } #if _LINUX_UART_DEBUG if (ret > 0) { LOG_PRINTF("[RX] "); uint8_t *ptr = (uint8_t *)buf; for (size_t i = 0; i < ret; i++) LOG_PRINTF("%02X ", (uint8_t)*ptr++); LOG_PRINTF("\n"); } #endif return ret; } ssize_t LinuxCellular::Write(void *buf, size_t nbytes) { cpp_freertos::LockGuard lock(serOutMutex); #if _LINUX_UART_DEBUG LOG_PRINTF("[TX] "); uint8_t *ptr = (uint8_t *)buf; for (size_t i = 0; i < nbytes; i++) LOG_PRINTF("%02X ", (uint8_t)*ptr++); LOG_PRINTF("\n"); #endif retry: auto ret = write(fd, buf, nbytes); if ((ret == -1) && (errno == EINTR)) { goto retry; } return ret; } void LinuxCellular::InformModemHostAsleep(void) {} void LinuxCellular::InformModemHostWakeup(void) {} void LinuxCellular::EnterSleep() {} void LinuxCellular::ExitSleep() {} uint32_t LinuxCellular::Wait(uint32_t timeout) { uint32_t currentTime = cpp_freertos::Ticks::GetTicks(); uint32_t timeoutNeeded = timeout == UINT32_MAX ? UINT32_MAX : currentTime + timeout; uint32_t timeElapsed = currentTime; retry: if (timeElapsed >= timeoutNeeded) { return 0; // timeout } auto event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, timeoutNeeded - timeElapsed); timeElapsed = cpp_freertos::Ticks::GetTicks(); if (event_count == 0) { return 0; // timeout } else if ((event_count == -1) && (errno == EINTR)) { goto retry; } else { return 1; } } void LinuxCellular::SetSpeed(uint32_t portSpeed) { struct termios t; memset(&t, 0, sizeof(t)); tcgetattr(fd, &t); cfmakeraw(&t); t.c_cflag |= CLOCAL; // if(ctsrts == 1) // t.c_cflag |= CRTSCTS; //enable the flow control on dev board // else t.c_cflag &= ~(CRTSCTS); // disable the flow control on dev board speed_t speed = PortSpeeds_text[portSpeed]; // B115200; cfsetispeed(&t, speed); cfsetospeed(&t, speed); tcsetattr(fd, TCSANOW, &t); int status = TIOCM_DTR | TIOCM_RTS; ioctl(fd, TIOCMBIS, &status); } void LinuxCellular::SelectAntenna(uint8_t antenna) {} uint8_t LinuxCellular::GetAntenna() { return 0; } namespace cellular { auto init(QueueHandle_t qHandle) -> int { return 0; } namespace status { bsp::cellular::status::value getStatus() { return bsp::cellular::status::value::ACTIVE; } BaseType_t statusIRQhandler() { return pdFALSE; } } namespace sim { auto trayIRQ_handler() -> BaseType_t { return BaseType_t(); } auto getTray() -> Store::GSM::Tray { return Store::GSM::Tray::IN; } void hotswap_trigger() {} void sim_sel() {} } // namespace sim } // namespace cellular } // namespace bsp