luars232.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /*
  2. * Copyright (c) 2011 Petr Stetiar <ynezz@true.cz>, Gaben Ltd.
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use,
  8. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following
  11. * conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. * OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #include <lauxlib.h>
  26. #include <lua.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include "librs232/rs232.h"
  30. #define MODULE_TIMESTAMP __DATE__ " " __TIME__
  31. #define MODULE_NAMESPACE "luars232"
  32. #define MODULE_VERSION "1.0.3"
  33. #define MODULE_BUILD "$Id: luars232.c 15 2011-02-23 09:02:20Z sp $"
  34. #define MODULE_COPYRIGHT "Copyright (c) 2011 Petr Stetiar <ynezz@true.cz>, Gaben Ltd."
  35. #ifndef luaL_reg
  36. #define luaL_reg luaL_Reg
  37. #endif
  38. static struct {
  39. const char *name;
  40. unsigned long value;
  41. } luars232_ulong_consts[] = {
  42. /* baudrates */
  43. { "RS232_BAUD_300", RS232_BAUD_300 },
  44. { "RS232_BAUD_2400", RS232_BAUD_2400 },
  45. { "RS232_BAUD_4800", RS232_BAUD_4800 },
  46. { "RS232_BAUD_9600", RS232_BAUD_9600 },
  47. { "RS232_BAUD_19200", RS232_BAUD_19200 },
  48. { "RS232_BAUD_38400", RS232_BAUD_38400 },
  49. { "RS232_BAUD_57600", RS232_BAUD_57600 },
  50. { "RS232_BAUD_115200", RS232_BAUD_115200 },
  51. { "RS232_BAUD_460800", RS232_BAUD_460800 },
  52. /* databits */
  53. { "RS232_DATA_5", RS232_DATA_5 },
  54. { "RS232_DATA_6", RS232_DATA_6 },
  55. { "RS232_DATA_7", RS232_DATA_7 },
  56. { "RS232_DATA_8", RS232_DATA_8 },
  57. /* stop bits */
  58. { "RS232_STOP_1", RS232_STOP_1 },
  59. { "RS232_STOP_2", RS232_STOP_2 },
  60. /* parity */
  61. { "RS232_PARITY_NONE", RS232_PARITY_NONE },
  62. { "RS232_PARITY_ODD", RS232_PARITY_ODD },
  63. { "RS232_PARITY_EVEN", RS232_PARITY_EVEN },
  64. /* flow */
  65. { "RS232_FLOW_OFF", RS232_FLOW_OFF },
  66. { "RS232_FLOW_HW", RS232_FLOW_HW },
  67. { "RS232_FLOW_XON_XOFF", RS232_FLOW_XON_XOFF },
  68. /* DTR and RTS */
  69. { "RS232_DTR_ON", RS232_DTR_ON },
  70. { "RS232_DTR_OFF", RS232_DTR_OFF },
  71. { "RS232_RTS_ON", RS232_RTS_ON },
  72. { "RS232_RTS_OFF", RS232_RTS_OFF },
  73. /* errors */
  74. { "RS232_ERR_NOERROR", RS232_ERR_NOERROR },
  75. { "RS232_ERR_UNKNOWN", RS232_ERR_UNKNOWN },
  76. { "RS232_ERR_OPEN", RS232_ERR_OPEN },
  77. { "RS232_ERR_CLOSE", RS232_ERR_CLOSE },
  78. { "RS232_ERR_FLUSH", RS232_ERR_FLUSH },
  79. { "RS232_ERR_CONFIG", RS232_ERR_CONFIG },
  80. { "RS232_ERR_READ", RS232_ERR_READ },
  81. { "RS232_ERR_WRITE", RS232_ERR_WRITE },
  82. { "RS232_ERR_SELECT", RS232_ERR_SELECT },
  83. { "RS232_ERR_TIMEOUT", RS232_ERR_TIMEOUT },
  84. { "RS232_ERR_IOCTL", RS232_ERR_IOCTL },
  85. { "RS232_ERR_PORT_CLOSED", RS232_ERR_PORT_CLOSED },
  86. { "RS232_ERR_BREAK", RS232_ERR_BREAK },
  87. { "RS232_ERR_FRAME", RS232_ERR_FRAME },
  88. { "RS232_ERR_PARITY", RS232_ERR_PARITY },
  89. { "RS232_ERR_RXOVERFLOW", RS232_ERR_RXOVERFLOW },
  90. { "RS232_ERR_OVERRUN", RS232_ERR_OVERRUN },
  91. { NULL, 0 }
  92. };
  93. #ifdef WIN32
  94. BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  95. {
  96. return TRUE;
  97. }
  98. #endif
  99. /*
  100. * rs232 = require("luars232")
  101. * error, port = rs232.open(device)
  102. * error, port = rs232.open("/dev/ttyUSB0")
  103. */
  104. static int lua_port_open(lua_State *L)
  105. {
  106. int ret = 0;
  107. struct rs232_port_t *p = NULL;
  108. struct rs232_port_t **ud = NULL;
  109. const char *dev = luaL_checkstring(L, 1);
  110. p = rs232_init();
  111. if (p == NULL) {
  112. lua_pushinteger(L, RS232_ERR_CONFIG);
  113. lua_pushnil(L);
  114. return 2;
  115. }
  116. DBG("p=%p \n", (void *)p);
  117. rs232_set_device(p, dev);
  118. ret = rs232_open(p);
  119. if (ret > RS232_ERR_NOERROR) {
  120. free(p->pt);
  121. free(p);
  122. lua_pushinteger(L, ret);
  123. lua_pushnil(L);
  124. return 2;
  125. }
  126. lua_pushinteger(L, RS232_ERR_NOERROR);
  127. ud = lua_newuserdata(L, sizeof(struct rs232_port_t *));
  128. *ud = p;
  129. luaL_getmetatable(L, MODULE_NAMESPACE);
  130. lua_setmetatable(L, -2);
  131. return 2;
  132. }
  133. /*
  134. * error, data, read_len = port:read(max_read_len [[, timeout_ms], forced])
  135. *
  136. * if forced > 0 then read() blocks until 'timeout_ms' or there's 'max_read_len'
  137. * bytes available
  138. */
  139. static int lua_port_read(lua_State *L)
  140. {
  141. int ret = 0;
  142. int argc = 0;
  143. int forced = 0;
  144. unsigned int timeout = 0;
  145. unsigned int len = 0;
  146. unsigned int bytes_read = 0;
  147. unsigned char tmp[128];
  148. unsigned char *data = tmp;
  149. struct rs232_port_t *p = NULL;
  150. p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  151. lua_remove(L, 1);
  152. if (p == NULL || !rs232_port_open(p)) {
  153. lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
  154. lua_pushnil(L);
  155. lua_pushinteger(L, 0);
  156. return 3;
  157. }
  158. argc = lua_gettop(L);
  159. len = (unsigned int) luaL_checkinteger(L, 1);
  160. if(len > sizeof(tmp)){
  161. data = (unsigned char*) malloc(len);
  162. memset(data, 0, len);
  163. }
  164. switch (argc) {
  165. case 1:
  166. ret = rs232_read(p, data, len, &bytes_read);
  167. break;
  168. case 2:
  169. case 3:
  170. timeout = (unsigned int) luaL_checknumber(L, 2);
  171. if(lua_isnumber(L, 3))
  172. forced = (lua_tointeger(L, 3) > 0) ? 1 : 0;
  173. else if (!lua_isnoneornil(L, 3)) {
  174. luaL_checktype(L, 3, LUA_TBOOLEAN);
  175. forced = lua_toboolean(L, 3);
  176. }
  177. if (forced > 0)
  178. ret = rs232_read_timeout_forced(p, data, len, &bytes_read, timeout);
  179. else
  180. ret = rs232_read_timeout(p, data, len, &bytes_read, timeout);
  181. break;
  182. default:
  183. lua_pushinteger(L, RS232_ERR_UNKNOWN);
  184. lua_pushnil(L);
  185. lua_pushinteger(L, 0);
  186. return 3;
  187. }
  188. DBG("ret=%d hex='%s' bytes_read=%d\n",
  189. ret, rs232_hex_dump(data, bytes_read), bytes_read);
  190. lua_pushinteger(L, ret);
  191. if (bytes_read > 0)
  192. lua_pushlstring(L, (char *) data, bytes_read);
  193. else
  194. lua_pushnil(L);
  195. if (data != tmp)
  196. free(data);
  197. lua_pushinteger(L, bytes_read);
  198. return 3;
  199. }
  200. /*
  201. * error, bytes = port:in_queue()
  202. */
  203. static int lua_port_in_queue(lua_State *L)
  204. {
  205. int ret = 0;
  206. struct rs232_port_t *p = NULL;
  207. unsigned int in_bytes = 0;
  208. p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  209. lua_remove(L, 1);
  210. if (p == NULL || !rs232_port_open(p)) {
  211. lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
  212. lua_pushinteger(L, 0);
  213. return 2;
  214. }
  215. ret = rs232_in_queue(p, &in_bytes);
  216. lua_pushinteger(L, ret);
  217. lua_pushinteger(L, in_bytes);
  218. return 2;
  219. }
  220. /*
  221. * error = port:in_queue_clear()
  222. */
  223. static int lua_port_in_queue_clear(lua_State *L)
  224. {
  225. struct rs232_port_t *p = NULL;
  226. p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  227. lua_remove(L, 1);
  228. if (p == NULL || !rs232_port_open(p)) {
  229. lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
  230. return 1;
  231. }
  232. rs232_in_queue_clear(p);
  233. lua_pushinteger(L, RS232_ERR_NOERROR);
  234. return 1;
  235. }
  236. /*
  237. * error, written_len = port:write(data [, timeout_ms])
  238. */
  239. static int lua_port_write(lua_State *L)
  240. {
  241. int ret = 0;
  242. int argc = 0;
  243. unsigned int timeout = 0;
  244. unsigned int wlen = 0;
  245. size_t len = 0;
  246. const char *data;
  247. struct rs232_port_t *p = NULL;
  248. p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  249. lua_remove(L, 1);
  250. if (p == NULL || !rs232_port_open(p)) {
  251. lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
  252. lua_pushinteger(L, 0);
  253. return 2;
  254. }
  255. argc = lua_gettop(L);
  256. switch (argc) {
  257. case 1: {
  258. data = luaL_checklstring(L, 1, &len);
  259. ret = rs232_write(p, (unsigned char*) data, (unsigned int) len, &wlen);
  260. break;
  261. }
  262. case 2:
  263. data = luaL_checklstring(L, 1, &len);
  264. timeout = (unsigned int) luaL_checknumber(L, 2);
  265. ret = rs232_write_timeout(p, (unsigned char*) data, (unsigned int) len, &wlen, timeout);
  266. break;
  267. default:
  268. lua_pushinteger(L, RS232_ERR_CONFIG);
  269. lua_pushinteger(L, 0);
  270. return 2;
  271. }
  272. lua_pushinteger(L, ret);
  273. lua_pushinteger(L, wlen);
  274. return 2;
  275. }
  276. /* error = port:close() */
  277. static int lua_port_close(lua_State *L)
  278. {
  279. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  280. if (p == NULL || !rs232_port_open(p)) {
  281. lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
  282. return 1;
  283. }
  284. lua_pushinteger(L, rs232_close(p));
  285. return 1;
  286. }
  287. /* __gc */
  288. static int lua_port_gc(lua_State *L)
  289. {
  290. struct rs232_port_t **p = (struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  291. if (*p != NULL) {
  292. rs232_end(*p);
  293. *p = NULL;
  294. }
  295. return 1;
  296. }
  297. /* error = port:flush() */
  298. static int lua_port_flush(lua_State *L)
  299. {
  300. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  301. if (p == NULL || !rs232_port_open(p)) {
  302. lua_pushinteger(L, RS232_ERR_PORT_CLOSED);
  303. return 1;
  304. }
  305. lua_pushinteger(L, rs232_flush(p));
  306. return 1;
  307. }
  308. /* __tostring metamethod */
  309. static int lua_port_tostring(lua_State *L)
  310. {
  311. const char *ret;
  312. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  313. if (p == NULL) {
  314. lua_pushnil(L);
  315. return 1;
  316. }
  317. ret = rs232_to_string(p);
  318. if (ret == NULL)
  319. lua_pushnil(L);
  320. else
  321. lua_pushstring(L, ret);
  322. return 1;
  323. }
  324. static int lua_port_device(lua_State *L)
  325. {
  326. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  327. const char *ret = rs232_get_device(p);
  328. if (ret == NULL)
  329. lua_pushnil(L);
  330. else
  331. lua_pushstring(L, ret);
  332. return 1;
  333. }
  334. static int lua_port_fd(lua_State *L)
  335. {
  336. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE);
  337. lua_pushinteger(L, rs232_fd(p));
  338. return 1;
  339. }
  340. /*
  341. * print(port:error_tostring(error))
  342. */
  343. static int lua_port_strerror(lua_State *L)
  344. {
  345. const char *ret = rs232_strerror((unsigned int) luaL_checkinteger(L, 1));
  346. if (ret == NULL)
  347. lua_pushnil(L);
  348. else
  349. lua_pushstring(L, ret);
  350. return 1;
  351. }
  352. #define FN_SET_PORT(type) \
  353. static int lua_port_set_##type(lua_State *L) \
  354. { \
  355. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE); \
  356. lua_pushinteger(L, rs232_set_##type(p, (unsigned int) luaL_checknumber(L, 2))); \
  357. return 1; \
  358. } \
  359. #define FN_GET_PORT(type) \
  360. static int lua_port_get_##type(lua_State *L) \
  361. { \
  362. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE); \
  363. lua_pushinteger(L, rs232_get_##type(p)); \
  364. return 1; \
  365. }
  366. #define FN_GET_PORT_STRING(type) \
  367. static int lua_port_get_str##type(lua_State *L) \
  368. { \
  369. struct rs232_port_t *p = *(struct rs232_port_t**) luaL_checkudata(L, 1, MODULE_NAMESPACE); \
  370. int param = (int) luaL_optinteger(L, 2, -1); \
  371. const char *ret = rs232_str##type(param == -1 ? rs232_get_##type(p) : (unsigned int) param); \
  372. if (ret == NULL) { \
  373. lua_pushnil(L); \
  374. } else { \
  375. lua_pushstring(L, ret); \
  376. } \
  377. return 1; \
  378. }
  379. FN_SET_PORT(baud)
  380. FN_SET_PORT(data)
  381. FN_SET_PORT(stop)
  382. FN_SET_PORT(parity)
  383. FN_SET_PORT(flow)
  384. FN_SET_PORT(dtr)
  385. FN_SET_PORT(rts)
  386. FN_GET_PORT(baud)
  387. FN_GET_PORT(data)
  388. FN_GET_PORT(stop)
  389. FN_GET_PORT(parity)
  390. FN_GET_PORT(flow)
  391. FN_GET_PORT(dtr)
  392. FN_GET_PORT(rts)
  393. FN_GET_PORT_STRING(baud)
  394. FN_GET_PORT_STRING(data)
  395. FN_GET_PORT_STRING(stop)
  396. FN_GET_PORT_STRING(parity)
  397. FN_GET_PORT_STRING(flow)
  398. FN_GET_PORT_STRING(dtr)
  399. FN_GET_PORT_STRING(rts)
  400. static luaL_reg port_methods[] = {
  401. { "__tostring", lua_port_tostring },
  402. { "__gc", lua_port_gc },
  403. { "read", lua_port_read },
  404. { "write", lua_port_write },
  405. { "close", lua_port_close },
  406. { "flush", lua_port_flush },
  407. { "device", lua_port_device },
  408. { "fd", lua_port_fd },
  409. { "in_queue", lua_port_in_queue },
  410. { "in_queue_clear", lua_port_in_queue_clear },
  411. /* baud */
  412. { "baud_rate", lua_port_get_baud },
  413. { "baud_rate_tostring", lua_port_get_strbaud },
  414. { "set_baud_rate", lua_port_set_baud },
  415. /* data */
  416. { "data_bits", lua_port_get_data },
  417. { "data_bits_tostring", lua_port_get_strdata },
  418. { "set_data_bits", lua_port_set_data },
  419. /* stop */
  420. { "stop_bits", lua_port_get_stop },
  421. { "stop_bits_tostring", lua_port_get_strstop },
  422. { "set_stop_bits", lua_port_set_stop },
  423. /* parity */
  424. { "parity", lua_port_get_parity },
  425. { "parity_tostring", lua_port_get_strparity },
  426. { "set_parity", lua_port_set_parity },
  427. /* flow */
  428. { "flow_control", lua_port_get_flow },
  429. { "flow_control_tostring", lua_port_get_strflow },
  430. { "set_flow_control", lua_port_set_flow },
  431. /* dtr */
  432. { "dtr", lua_port_get_dtr },
  433. { "dtr_tostring", lua_port_get_strdtr },
  434. { "set_dtr", lua_port_set_dtr },
  435. /* rts */
  436. { "rts", lua_port_get_rts },
  437. { "rts_tostring", lua_port_get_strrts },
  438. { "set_rts", lua_port_set_rts },
  439. { NULL, NULL }
  440. };
  441. static luaL_reg port_functions[] = {
  442. { "open", lua_port_open },
  443. { "error_tostring", lua_port_strerror },
  444. { NULL, NULL }
  445. };
  446. static void create_metatables(lua_State *L, const char *name, const luaL_reg *methods)
  447. {
  448. luaL_newmetatable(L, name);
  449. lua_pushvalue(L, -1);
  450. lua_setfield(L, -2, "__index");
  451. #if LUA_VERSION_NUM < 502
  452. luaL_register(L, NULL, methods);
  453. #else
  454. luaL_setfuncs(L, methods, 0);
  455. #endif
  456. }
  457. RS232_LIB int luaopen_luars232(lua_State *L)
  458. {
  459. int i;
  460. create_metatables(L, MODULE_NAMESPACE, port_methods);
  461. #if LUA_VERSION_NUM < 502
  462. luaL_register(L, MODULE_NAMESPACE, port_functions);
  463. #else
  464. luaL_newlib(L, port_functions);
  465. #endif
  466. for (i = 0; luars232_ulong_consts[i].name != NULL; i++) {
  467. lua_pushstring(L, luars232_ulong_consts[i].name);
  468. lua_pushnumber(L, luars232_ulong_consts[i].value);
  469. lua_settable(L, -3);
  470. }
  471. lua_pushstring(L, MODULE_VERSION);
  472. lua_setfield(L, -2, "_VERSION");
  473. lua_pushstring(L, MODULE_BUILD);
  474. lua_setfield(L, -2, "_BUILD");
  475. lua_pushstring(L, MODULE_TIMESTAMP);
  476. lua_setfield(L, -2, "_TIMESTAMP");
  477. lua_pushstring(L, MODULE_COPYRIGHT);
  478. lua_setfield(L, -2, "_COPYRIGHT");
  479. DBG("[*] luaopen_luars232(Version: '%s' Build: '%s' TimeStamp: '%s')\n",
  480. MODULE_VERSION, MODULE_BUILD, MODULE_TIMESTAMP);
  481. return 1;
  482. }
  483. RS232_LIB int luaopen_rs232_core(lua_State *L){
  484. return luaopen_luars232(L);
  485. }