RS232_LIB unsigned int rs232_set_rts(struct rs232_port_t *p, enum rs232_rts_e state) { DCB pdcb; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p rts=%d (rts control %s)\n", (void *)p, p->pt, state, rs232_strrts(state)); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_STATE(wx->fd, &pdcb); switch (state) { case RS232_DTR_OFF: pdcb.fRtsControl = RTS_CONTROL_DISABLE; break; case RS232_DTR_ON: pdcb.fRtsControl = RTS_CONTROL_ENABLE; break; default: return RS232_ERR_UNKNOWN; } SET_PORT_STATE(wx->fd, &pdcb); p->rts = state; return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_set_parity(struct rs232_port_t *p, enum rs232_parity_e parity) { DCB pdcb; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p parity=%d (parity %s)\n", (void *)p, p->pt, parity, rs232_strparity(parity)); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_STATE(wx->fd, &pdcb); switch (parity) { case RS232_PARITY_NONE: pdcb.Parity = NOPARITY; break; case RS232_PARITY_ODD: pdcb.Parity = ODDPARITY; break; case RS232_PARITY_EVEN: pdcb.Parity = EVENPARITY; break; default: return RS232_ERR_UNKNOWN; } SET_PORT_STATE(wx->fd, &pdcb); p->parity = parity; return RS232_ERR_NOERROR; }
RS232_LIB void rs232_end(struct rs232_port_t *p) { struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p\n", (void *)p, p->pt); if (!rs232_port_open(p)) { free(p->pt); free(p); return; } rs232_flush(p); if (!SetCommState(wx->fd, &wx->old_dcb)) { DBG("SetCommState() %s\n", last_error()); return; } if (!SetCommTimeouts(wx->fd, &wx->old_tm)) { DBG("SetCommTimeouts() %s\n", last_error()); return; } rs232_close(p); free(p->pt); free(p); }
RS232_LIB unsigned int rs232_set_stop(struct rs232_port_t *p, enum rs232_stop_e stop) { DCB pdcb; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p stop=%d (%s stop bits)\n", (void *)p, p->pt, stop, rs232_strstop(stop)); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_STATE(wx->fd, &pdcb); switch (stop) { case RS232_STOP_1: pdcb.StopBits = ONESTOPBIT; break; case RS232_STOP_2: pdcb.StopBits = TWOSTOPBITS; break; default: return RS232_ERR_UNKNOWN; } SET_PORT_STATE(wx->fd, &pdcb); p->stop = stop; return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_read_timeout(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len, unsigned int *read_len, unsigned int timeout) { unsigned int r = 0; struct rs232_windows_t *wx = p->pt; unsigned int rt = wx->r_timeout; DBG("p=%p p->pt=%p buf_len: %d timeout: %d\n", (void *)p, p->pt, buf_len, timeout); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; *read_len = 0; if (port_timeout(p, timeout, wx->w_timeout)) return RS232_ERR_UNKNOWN; if (!ReadFile(wx->fd, buf, buf_len, &r, NULL)) { *read_len = 0; DBG("ReadFile() %s\n", last_error()); return RS232_ERR_READ; } if (port_timeout(p, rt, wx->w_timeout)) return RS232_ERR_UNKNOWN; *read_len = r; DBG("read_len=%d hex='%s' ascii='%s'\n", r, rs232_hex_dump(buf, r), rs232_ascii_dump(buf, r)); return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_write_timeout(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len, unsigned int *write_len, unsigned int timeout) { unsigned int w = 0; struct rs232_windows_t *wx = p->pt; unsigned int wt = wx->w_timeout; DBG("p=%p p->pt=%p buf_len:%d\n", (void *)p, p->pt, buf_len); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; if (port_timeout(p, wx->r_timeout, timeout)) return RS232_ERR_UNKNOWN; if (!WriteFile(wx->fd, buf, buf_len, &w, NULL)) { *write_len = 0; DBG("WriteFile() %s\n", last_error()); return RS232_ERR_WRITE; } if (port_timeout(p, wx->r_timeout, wt)) return RS232_ERR_UNKNOWN; *write_len = w; DBG("write_len=%d hex='%s' ascii='%s'\n", w, rs232_hex_dump(buf, w), rs232_ascii_dump(buf, w)); return RS232_ERR_NOERROR; }
/* error = port:flush() */ static int lua_port_flush(lua_State *L) { struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE); if (p == NULL || !rs232_port_open(p)) { lua_pushinteger(L, RS232_ERR_PORT_CLOSED); return 1; } lua_pushinteger(L, rs232_flush(p)); return 1; }
RS232_LIB unsigned int rs232_set_baud(struct rs232_port_t *p, enum rs232_baud_e baud) { DCB pdcb; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p baud=%d (%s bauds)\n", (void *)p, p->pt, baud, rs232_strbaud(baud)); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_STATE(wx->fd, &pdcb); switch (baud) { case RS232_BAUD_300: pdcb.BaudRate = CBR_300; break; case RS232_BAUD_2400: pdcb.BaudRate = CBR_2400; break; case RS232_BAUD_4800: pdcb.BaudRate = CBR_4800; break; case RS232_BAUD_9600: pdcb.BaudRate = CBR_9600; break; case RS232_BAUD_19200: pdcb.BaudRate = CBR_19200; break; case RS232_BAUD_38400: pdcb.BaudRate = CBR_38400; break; case RS232_BAUD_57600: pdcb.BaudRate = CBR_57600; break; case RS232_BAUD_115200: pdcb.BaudRate = CBR_115200; break; case RS232_BAUD_460800: pdcb.BaudRate = CBR_460800; break; default: return RS232_ERR_UNKNOWN; } SET_PORT_STATE(wx->fd, &pdcb); p->baud = baud; return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_close(struct rs232_port_t *p) { int ret; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p\n", (void *)p, p->pt); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; ret = CloseHandle(wx->fd); if (ret == 0) { DBG("PurgeComm() %s\n", last_error()); return RS232_ERR_CLOSE; } return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_set_flow(struct rs232_port_t *p, enum rs232_flow_e flow) { DCB pdcb; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p flow=%d (flow control %s)\n", (void *)p, p->pt, flow, rs232_strflow(flow)); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_STATE(wx->fd, &pdcb); switch (flow) { case RS232_FLOW_OFF: pdcb.fOutxCtsFlow = FALSE; pdcb.fRtsControl = RTS_CONTROL_DISABLE; pdcb.fInX = FALSE; pdcb.fOutX = FALSE; break; case RS232_FLOW_HW: pdcb.fOutxCtsFlow = TRUE; pdcb.fRtsControl = RTS_CONTROL_HANDSHAKE; pdcb.fInX = FALSE; pdcb.fOutX = FALSE; break; case RS232_FLOW_XON_XOFF: pdcb.fOutxCtsFlow = FALSE; pdcb.fRtsControl = RTS_CONTROL_DISABLE; pdcb.fInX = TRUE; pdcb.fOutX = TRUE; break; default: return RS232_ERR_UNKNOWN; } SET_PORT_STATE(wx->fd, &pdcb); p->flow = flow; return RS232_ERR_NOERROR; }
static unsigned int port_buffers(struct rs232_port_t *p, unsigned int rb, unsigned int wb) { struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p rb=%d wb=%d\n", (void *)p, p->pt, rb, wb); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; if (!SetupComm(wx->fd, rb, wb)) { DBG("SetupComm() %s\n", last_error()); return RS232_ERR_UNKNOWN; } wx->r_buffer = rb; wx->w_buffer = wb; return RS232_ERR_NOERROR; }
/* * error, written_len = port:write(data [, timeout_ms]) */ static int lua_port_write(lua_State *L) { int ret = 0; int argc = 0; unsigned int timeout = 0; unsigned int wlen = 0; size_t len = 0; const char *data; struct rs232_port_t *p = NULL; p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE); lua_remove(L, 1); if (p == NULL || !rs232_port_open(p)) { lua_pushinteger(L, RS232_ERR_PORT_CLOSED); lua_pushinteger(L, 0); return 2; } argc = lua_gettop(L); switch (argc) { case 1: { data = luaL_checklstring(L, 1, &len); ret = rs232_write(p, (unsigned char*) data, (unsigned int) len, &wlen); break; } case 2: data = luaL_checklstring(L, 1, &len); timeout = (unsigned int) luaL_checknumber(L, 2); ret = rs232_write_timeout(p, (unsigned char*) data, (unsigned int) len, &wlen, timeout); break; default: lua_pushinteger(L, RS232_ERR_CONFIG); lua_pushinteger(L, 0); return 2; } lua_pushinteger(L, ret); lua_pushinteger(L, wlen); return 2; }
RS232_LIB unsigned int rs232_in_qeue(struct rs232_port_t *p, unsigned int *in_bytes) { COMSTAT cs; unsigned long errmask = 0; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p\n", (void *)p, p->pt); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; if (!ClearCommError(wx->fd, &errmask, &cs)) { DBG("ClearCommError() %s\n", last_error()); return RS232_ERR_IOCTL; } *in_bytes = cs.cbInQue; DBG("in_bytes=%d\n", cs.cbInQue); return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_flush(struct rs232_port_t *p) { struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p\n", (void *)p, p->pt); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; if (!FlushFileBuffers(wx->fd)) { DBG("FlushFileBuffers() %s\n", last_error()); return RS232_ERR_FLUSH; } if (!PurgeComm(wx->fd, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) { DBG("PurgeComm() %s\n", last_error()); return RS232_ERR_FLUSH; } return RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_read_timeout(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len, unsigned int *read_len, unsigned int timeout) { unsigned int r = 0; struct rs232_windows_t *wx = p->pt; unsigned int rt = wx->r_timeout; DBG("p=%p p->pt=%p buf_len: %d timeout: %d\n", (void *)p, p->pt, buf_len, timeout); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; *read_len = 0; if (port_timeout(p, timeout, wx->w_timeout)) return RS232_ERR_UNKNOWN; if (!ReadFile(wx->fd, buf, buf_len, &r, NULL)) { *read_len = 0; DBG("ReadFile() %s\n", last_error()); return RS232_ERR_READ; } if (port_timeout(p, rt, wx->w_timeout)) return RS232_ERR_UNKNOWN; *read_len = r; DBG("read_len=%d hex='%s' ascii='%s'\n", r, rs232_hex_dump(buf, r), rs232_ascii_dump(buf, r)); /* TODO - This is lame, since we rely on the fact, that if we read 0 bytes, * that the read probably timeouted. So we should rather measure the reading * interval or rework it using overlapped I/O */ return *read_len == 0 ? RS232_ERR_TIMEOUT : RS232_ERR_NOERROR; }
RS232_LIB unsigned int rs232_set_data(struct rs232_port_t *p, enum rs232_data_e data) { DCB pdcb; struct rs232_windows_t *wx = p->pt; DBG("p=%p p->pt=%p data=%d (%s data bits)\n", (void *)p, p->pt, data, rs232_strdata(data)); if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_STATE(wx->fd, &pdcb); switch (data) { case RS232_DATA_5: pdcb.ByteSize = 5; break; case RS232_DATA_6: pdcb.ByteSize = 6; break; case RS232_DATA_7: pdcb.ByteSize = 7; break; case RS232_DATA_8: pdcb.ByteSize = 8; break; default: return RS232_ERR_UNKNOWN; } SET_PORT_STATE(wx->fd, &pdcb); p->data = data; return RS232_ERR_NOERROR; }
static unsigned int port_timeout(struct rs232_port_t *p, unsigned int rt, unsigned int wt) { struct rs232_windows_t *wx = p->pt; COMMTIMEOUTS t; if (!rs232_port_open(p)) return RS232_ERR_PORT_CLOSED; GET_PORT_TIMEOUTS(wx->fd, &t); t.ReadIntervalTimeout = 0; t.ReadTotalTimeoutMultiplier = 0; t.ReadTotalTimeoutConstant = rt; t.WriteTotalTimeoutMultiplier = 0; t.WriteTotalTimeoutConstant = wt; SET_PORT_TIMEOUTS(wx->fd, &t); wx->w_timeout = wt; wx->r_timeout = rt; return RS232_ERR_NOERROR; }
/* * error, data, read_len = port:read(max_read_len [[, timeout_ms], forced]) * * if forced > 0 then read() blocks until 'timeout_ms' or there's 'max_read_len' * bytes available */ static int lua_port_read(lua_State *L) { int ret = 0; int argc = 0; int forced = 0; unsigned int timeout = 0; unsigned int len = 0; unsigned int bytes_read = 0; unsigned char *data = NULL; struct rs232_port_t *p = NULL; p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE); lua_remove(L, 1); if (p == NULL || !rs232_port_open(p)) { lua_pushinteger(L, RS232_ERR_PORT_CLOSED); lua_pushnil(L); lua_pushinteger(L, 0); return 3; } argc = lua_gettop(L); switch (argc) { case 1: len = (unsigned int) luaL_checkinteger(L, 1); data = (unsigned char*) malloc(len * sizeof(unsigned char *)); memset(data, 0, len); ret = rs232_read(p, data, len, &bytes_read); break; case 2: case 3: len = (unsigned int) luaL_checknumber(L, 1); data = (unsigned char*) malloc(len * sizeof(unsigned char *)); memset(data, 0, len); timeout = (unsigned int) luaL_checknumber(L, 2); forced = luaL_optint(L, 3, 0); if (forced > 0) ret = rs232_read_timeout_forced(p, data, len, &bytes_read, timeout); else ret = rs232_read_timeout(p, data, len, &bytes_read, timeout); break; default: lua_pushinteger(L, RS232_ERR_UNKNOWN); lua_pushnil(L); lua_pushinteger(L, 0); return 3; } DBG("ret=%d hex='%s' bytes_read=%d\n", ret, rs232_hex_dump(data, bytes_read), bytes_read); lua_pushinteger(L, ret); if (bytes_read > 0) lua_pushlstring(L, (char *) data, bytes_read); else lua_pushnil(L); if (data) free(data); lua_pushinteger(L, bytes_read); return 3; }