Permalink
Browse files

Add support for serial devices as socket streams on unix.

  • Loading branch information...
1 parent 7840674 commit ed892af39ee334bcd732a8ca9dd8cad267fc15aa @sam-github sam-github committed Sep 27, 2011
Showing with 200 additions and 1 deletion.
  1. +1 −0 config
  2. +1 −0 makefile
  3. +17 −1 src/makefile
  4. +181 −0 src/serial.c
View
1 config
@@ -11,6 +11,7 @@ MIME_V=1.0.2
SOCKET_SO=socket.$(EXT).$(SOCKET_V)
MIME_SO=mime.$(EXT).$(MIME_V)
UNIX_SO=unix.$(EXT)
+SERIAL_SO=serial.$(EXT)
#------
# Lua includes and libraries
View
@@ -48,6 +48,7 @@ install: all
install-unix: install all-unix
cd src; $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_LIB)/$(UNIX_SO)
+ cd src; $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_LIB)/$(SERIAL_SO)
#------
# End of makefile
View
@@ -47,6 +47,17 @@ UNIX_OBJS:=\
usocket.o \
unix.o
+#------
+# Modules belonging to serial (device streams)
+#
+SERIAL_OBJS:=\
+ buffer.o \
+ auxiliar.o \
+ timeout.o \
+ io.o \
+ usocket.o \
+ serial.o
+
all: $(SOCKET_SO) $(MIME_SO)
$(SOCKET_SO): $(SOCKET_OBJS)
@@ -55,11 +66,14 @@ $(SOCKET_SO): $(SOCKET_OBJS)
$(MIME_SO): $(MIME_OBJS)
$(LD) $(LDFLAGS) -o $@ $(MIME_OBJS)
-all-unix: all $(UNIX_SO)
+all-unix: all $(UNIX_SO) $(SERIAL_SO)
$(UNIX_SO): $(UNIX_OBJS)
$(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS)
+$(SERIAL_SO): $(SERIAL_OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(SERIAL_OBJS)
+
#------
# List of dependencies
#
@@ -74,6 +88,8 @@ mime.o: mime.c mime.h
options.o: options.c auxiliar.h options.h socket.h io.h timeout.h \
usocket.h inet.h
select.o: select.c socket.h io.h timeout.h usocket.h select.h
+serial.o: serial.c auxiliar.h socket.h io.h timeout.h usocket.h \
+ unix.h buffer.h
tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h inet.h \
options.h tcp.h buffer.h
timeout.o: timeout.c auxiliar.h timeout.h
View
@@ -0,0 +1,181 @@
+/*=========================================================================*\
+* Serial stream
+* LuaSocket toolkit
+\*=========================================================================*/
+#include <string.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "auxiliar.h"
+#include "socket.h"
+#include "options.h"
+#include "unix.h"
+#include <sys/un.h>
+
+/*
+Reuses userdata definition from unix.h, since it is useful for all
+stream-like objects.
+
+If we stored the serial path for use in error messages or userdata
+printing, we might need our own userdata definition.
+
+Group usage is semi-inherited from unix.c, but unnecessary since we
+have only one object type.
+*/
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int global_create(lua_State *L);
+static int meth_send(lua_State *L);
+static int meth_receive(lua_State *L);
+static int meth_close(lua_State *L);
+static int meth_settimeout(lua_State *L);
+static int meth_getfd(lua_State *L);
+static int meth_setfd(lua_State *L);
+static int meth_dirty(lua_State *L);
+static int meth_getstats(lua_State *L);
+static int meth_setstats(lua_State *L);
+
+/* serial object methods */
+static luaL_reg un[] = {
+ {"__gc", meth_close},
+ {"__tostring", auxiliar_tostring},
+ {"close", meth_close},
+ {"dirty", meth_dirty},
+ {"getfd", meth_getfd},
+ {"getstats", meth_getstats},
+ {"setstats", meth_setstats},
+ {"receive", meth_receive},
+ {"send", meth_send},
+ {"setfd", meth_setfd},
+ {"settimeout", meth_settimeout},
+ {NULL, NULL}
+};
+
+/* our socket creation function */
+static luaL_reg func[] = {
+ {"serial", global_create},
+ {NULL, NULL}
+};
+
+
+/*-------------------------------------------------------------------------*\
+* Initializes module
+\*-------------------------------------------------------------------------*/
+int luaopen_socket_serial(lua_State *L) {
+ /* create classes */
+ auxiliar_newclass(L, "serial{client}", un);
+ /* create class groups */
+ auxiliar_add2group(L, "serial{client}", "serial{any}");
+ /* make sure the function ends up in the package table */
+ luaL_openlib(L, "socket", func, 0);
+ /* return the function instead of the 'socket' table */
+ lua_pushstring(L, "serial");
+ lua_gettable(L, -2);
+ return 1;
+}
+
+/*=========================================================================*\
+* Lua methods
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Just call buffered IO methods
+\*-------------------------------------------------------------------------*/
+static int meth_send(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
+ return buffer_meth_send(L, &un->buf);
+}
+
+static int meth_receive(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
+ return buffer_meth_receive(L, &un->buf);
+}
+
+static int meth_getstats(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
+ return buffer_meth_getstats(L, &un->buf);
+}
+
+static int meth_setstats(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
+ return buffer_meth_setstats(L, &un->buf);
+}
+
+/*-------------------------------------------------------------------------*\
+* Select support methods
+\*-------------------------------------------------------------------------*/
+static int meth_getfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
+ lua_pushnumber(L, (int) un->sock);
+ return 1;
+}
+
+/* this is very dangerous, but can be handy for those that are brave enough */
+static int meth_setfd(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
+ un->sock = (t_socket) luaL_checknumber(L, 2);
+ return 0;
+}
+
+static int meth_dirty(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
+ lua_pushboolean(L, !buffer_isempty(&un->buf));
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*\
+* Closes socket used by object
+\*-------------------------------------------------------------------------*/
+static int meth_close(lua_State *L)
+{
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
+ socket_destroy(&un->sock);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------------*\
+* Just call tm methods
+\*-------------------------------------------------------------------------*/
+static int meth_settimeout(lua_State *L) {
+ p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
+ return timeout_meth_settimeout(L, &un->tm);
+}
+
+/*=========================================================================*\
+* Library functions
+\*=========================================================================*/
+/*-------------------------------------------------------------------------*\
+* Creates a serial object
+\*-------------------------------------------------------------------------*/
+static int global_create(lua_State *L) {
+ const char* path = luaL_checkstring(L, 1);
+
+ /* allocate unix object */
+ p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
+
+ /* open serial device */
+ t_socket sock = open(path, O_NOCTTY|O_RDWR);
+
+ /*printf("open %s on %d\n", path, sock);*/
+
+ if (sock < 0) {
+ lua_pushnil(L);
+ lua_pushstring(L, socket_strerror(errno));
+ lua_pushnumber(L, errno);
+ return 3;
+ }
+ /* set its type as client object */
+ auxiliar_setclass(L, "serial{client}", -1);
+ /* initialize remaining structure fields */
+ socket_setnonblocking(&sock);
+ un->sock = sock;
+ io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
+ (p_error) socket_ioerror, &un->sock);
+ timeout_init(&un->tm, -1, -1);
+ buffer_init(&un->buf, &un->io, &un->tm);
+ return 1;
+}

0 comments on commit ed892af

Please sign in to comment.