159 lines
3.7 KiB
C
159 lines
3.7 KiB
C
#include "lupi.h"
|
|
#include <lua.h>
|
|
#include <lualib.h>
|
|
#include <lauxlib.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <dirent.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <termios.h>
|
|
#include <sys/stat.h>
|
|
|
|
int s_listports(lua_State * L) {
|
|
DIR * d = opendir("/sys/class/tty");
|
|
struct dirent * ent = NULL;
|
|
struct stat statbuf;
|
|
char path[255];
|
|
char linkpath[255];
|
|
lua_newtable(L);
|
|
size_t index = 1;
|
|
while ((ent = readdir(d)) != NULL) {
|
|
sprintf(path, "/sys/class/tty/%s/device", ent->d_name);
|
|
if (stat(path, &statbuf) == 0) {
|
|
readlink(path, linkpath, 255);
|
|
if (strstr(linkpath, "serial8250") == NULL) {
|
|
// We have a serial port
|
|
lua_pushinteger(L, index);
|
|
lua_pushstring(L, ent->d_name);
|
|
lua_settable(L, -3);
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
struct baudrate {
|
|
uint32_t baud;
|
|
tcflag_t flags;
|
|
};
|
|
|
|
// taken from here: https://man7.org/linux/man-pages/man3/termios.3.html
|
|
struct baudrate baudrates[] = {
|
|
{0, B0},
|
|
{50, B50},
|
|
{75, B75},
|
|
{110, B110},
|
|
{134, B134},
|
|
{150, B150},
|
|
{200, B200},
|
|
{300, B300},
|
|
{600, B600},
|
|
{1200, B1200},
|
|
{1800, B1800},
|
|
{2400, B2400},
|
|
{4800, B4800},
|
|
{9600, B9600},
|
|
{19200, B19200},
|
|
{38400, B38400},
|
|
{57600, B57600},
|
|
{115200, B115200},
|
|
{230400, B230400}
|
|
};
|
|
|
|
struct baudrate * getbaud(uint32_t baud) {
|
|
for (size_t i=0; i<sizeof(baudrates)/sizeof(struct baudrate); ++i) {
|
|
if (baudrates[i].baud == baud) {
|
|
return &baudrates[i];
|
|
} else if (baudrates[i].baud > baud) {
|
|
return &baudrates[i-1];
|
|
}
|
|
}
|
|
return getbaud(230400);
|
|
}
|
|
|
|
struct sport {
|
|
uint32_t baudrate;
|
|
int fd;
|
|
struct termios options;
|
|
};
|
|
|
|
int s_openport(lua_State * L) {
|
|
char * path = luaL_checkstring(L, 1);
|
|
struct sport * port = lua_newuserdata(L, sizeof(struct sport));
|
|
port->baudrate = 9600;
|
|
char rpath[255];
|
|
sprintf(rpath, "/dev/%s", path);
|
|
port->fd = open(rpath, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
|
if (port->fd == -1)
|
|
luaL_error(L, "unable to open port %s: ", path, strerror(errno));
|
|
tcgetattr(port->fd, &port->options);
|
|
cfsetispeed(&port->options, B9600);
|
|
cfsetospeed(&port->options, B9600);
|
|
tcsetattr(port->fd, TCSANOW, &port->options);
|
|
return 1;
|
|
}
|
|
|
|
int s_setbaudrate(lua_State * L) {
|
|
struct sport * port = lua_touserdata(L, 1);
|
|
long raw_br = luaL_checkinteger(L, 2);
|
|
struct baudrate * br = getbaud(raw_br & 0xFFFFFFFF);
|
|
//port->options.c_cflag &= ~(CBAUD);
|
|
//port->options.c_cflag |= br->flags;
|
|
cfsetispeed(&port->options, br->flags);
|
|
cfsetospeed(&port->options, br->flags);
|
|
port->baudrate = br->baud;
|
|
lua_pushinteger(L, br->baud);
|
|
port->options.c_cflag &= ~PARENB;
|
|
port->options.c_cflag &= ~CSTOPB;
|
|
port->options.c_cflag &= ~CSIZE;
|
|
port->options.c_cflag |= CS8;
|
|
tcsetattr(port->fd, TCSANOW, &port->options);
|
|
return 1;
|
|
}
|
|
|
|
int s_getbaudrate(lua_State * L) {
|
|
struct sport * port = lua_touserdata(L, 1);
|
|
lua_pushinteger(L, port->baudrate);
|
|
return 1;
|
|
}
|
|
|
|
int s_write(lua_State * L) {
|
|
struct sport * port = lua_touserdata(L, 1);
|
|
size_t len = 0;
|
|
char * data = luaL_checklstring(L, 2, &len);
|
|
size_t ioc = 0;
|
|
if ((ioc = write(port->fd, data, len)) != len) {
|
|
luaL_error(L, "io error! %llu != %llu", ioc, len);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int s_read(lua_State * L) {
|
|
struct sport * port = lua_touserdata(L, 1);
|
|
char buffer[2048]; // Max packet size
|
|
long size = luaL_checkinteger(L, 2);
|
|
size_t ioc = read(port->fd, buffer, size);
|
|
if (ioc != size && ioc != 0) {
|
|
luaL_error(L, "io error! %llu != %llu or 0", ioc, size);
|
|
} else if (ioc != 0) {
|
|
lua_pushlstring(L, buffer, size);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void serial_start(lua_State * L) {
|
|
struct luaL_Reg seriallib[] = {
|
|
{"open", s_openport},
|
|
{"list", s_listports},
|
|
{"write", s_write},
|
|
{"read", s_read},
|
|
{"setbaud", s_setbaudrate},
|
|
{"getbaud", s_getbaudrate},
|
|
{NULL, NULL}
|
|
};
|
|
luaL_openlib(L, "serial", seriallib, 0);
|
|
} |