_modbus_rt_tcp.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. /**
  2. * @file _modbus_rt.c
  3. * @brief modbus_rt的pika层的API实现
  4. * @author SenySunny (senysunny@163.com)
  5. * @date 2023-05-14
  6. *
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright (c) 2022 Ma Longwei.
  10. * All rights reserved.</center></h2>
  11. *
  12. */
  13. #include "PikaObj.h"
  14. #include "PikaStdData_List.h"
  15. #include "TinyObj.h"
  16. #include "_modbus_rt__tcp.h"
  17. #include "modbus_tcp.h"
  18. #if MODBUS_P2P_ENABLE
  19. #include "modbus_p2p.h"
  20. #endif
  21. void _modbus_rt__tcp___del__(PikaObj *self) {
  22. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  23. pika_platform_printf("modbus tcp is not activated.\n");
  24. return ;
  25. #else
  26. int ret = 0;
  27. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  28. if(NULL == dev) {
  29. pika_platform_printf("modbus_tcp_del error, dev is NULL.\n");
  30. return ;
  31. }
  32. ret = modbus_tcp_destroy(&dev);
  33. if(MODBUS_RT_EOK != ret){
  34. pika_platform_printf("modbus_tcp_destroy error, code:%d.\n", ret);
  35. return ;
  36. }
  37. obj_setPtr(self, "dev", NULL);
  38. #endif
  39. }
  40. void _modbus_rt__tcp__init(PikaObj *self, int mode) {
  41. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  42. pika_platform_printf("modbus tcp is not activated.\n");
  43. #else
  44. tcp_modbus_device_t dev = modbus_tcp((modbus_mode_type)mode);
  45. if(NULL == dev) {
  46. pika_platform_printf("modbus_tcp create error.\n");
  47. }
  48. obj_setInt(self, "mode", mode);
  49. obj_setPtr(self, "dev", dev);
  50. #endif
  51. }
  52. int _modbus_rt__tcp__set_net(PikaObj *self, char* ip, int port, int type) {
  53. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  54. pika_platform_printf("modbus tcp is not activated.\n");
  55. return 0;
  56. #else
  57. int ret = 0;
  58. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  59. if(NULL == dev) {
  60. pika_platform_printf("modbus_tcp_set_net error, dev is NULL.\n");
  61. return 0;
  62. }
  63. if(0 != dev->status) {
  64. pika_platform_printf("modbus_tcp_set_net error, dev is opened.\n");
  65. return 0;
  66. }
  67. if(0 == strlen(ip)) {
  68. ip = NULL;
  69. }
  70. ret = modbus_tcp_set_net(dev, ip, port, type);
  71. if(MODBUS_RT_EOK != ret){
  72. pika_platform_printf("modbus_tcp_set_net error, code:%d.\n", ret);
  73. return 0;
  74. }
  75. return 1;
  76. #endif
  77. }
  78. int _modbus_rt__tcp__set_ip(PikaObj *self, char* ip) {
  79. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  80. pika_platform_printf("modbus tcp is not activated.\n");
  81. return 0;
  82. #else
  83. int ret = 0;
  84. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  85. if(NULL == dev) {
  86. pika_platform_printf("modbus_tcp_set_ip error, dev is NULL.\n");
  87. return 0;
  88. }
  89. if(0 != dev->status) {
  90. pika_platform_printf("modbus_tcp_set_ip error, dev is opened.\n");
  91. return 0;
  92. }
  93. if(0 == strlen(ip)) {
  94. ip = NULL;
  95. }
  96. ret = modbus_tcp_set_ip(dev, ip);
  97. if(MODBUS_RT_EOK != ret){
  98. pika_platform_printf("modbus_tcp_set_ip error, code:%d.\n", ret);
  99. return 0;
  100. }
  101. return 1;
  102. #endif
  103. }
  104. int _modbus_rt__tcp__set_port(PikaObj *self, int port) {
  105. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  106. pika_platform_printf("modbus tcp is not activated.\n");
  107. return 0;
  108. #else
  109. int ret = 0;
  110. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  111. if(NULL == dev) {
  112. pika_platform_printf("modbus_tcp_set_port error, dev is NULL.\n");
  113. return 0;
  114. }
  115. if(0 != dev->status) {
  116. pika_platform_printf("modbus_tcp_set_port error, dev is opened.\n");
  117. return 0;
  118. }
  119. ret = modbus_tcp_set_port(dev, port);
  120. if(MODBUS_RT_EOK != ret){
  121. pika_platform_printf("modbus_tcp_set_port error, code:%d.\n", ret);
  122. return 0;
  123. }
  124. return 1;
  125. #endif
  126. }
  127. int _modbus_rt__tcp__set_type(PikaObj *self, int type) {
  128. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  129. pika_platform_printf("modbus tcp is not activated.\n");
  130. return 0;
  131. #else
  132. int ret = 0;
  133. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  134. if(NULL == dev) {
  135. pika_platform_printf("modbus_tcp_set_type error, dev is NULL.\n");
  136. return 0;
  137. }
  138. if(0 != dev->status) {
  139. pika_platform_printf("modbus_tcp_set_type error, dev is opened.\n");
  140. return 0;
  141. }
  142. ret = modbus_tcp_set_type(dev, type);
  143. if(MODBUS_RT_EOK != ret){
  144. pika_platform_printf("modbus_tcp_set_type error, code:%d.\n", ret);
  145. return 0;
  146. }
  147. return 1;
  148. #endif
  149. }
  150. int _modbus_rt__tcp__set_p2p(PikaObj *self, int p2p_flag) {
  151. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  152. pika_platform_printf("modbus tcp is not activated.\n");
  153. return 0;
  154. #elif (!MODBUS_P2P_ENABLE)
  155. pika_platform_printf("MODBUS_P2P_ENABLE is not enabled.\n");
  156. return 0;
  157. #else
  158. int ret = 0;
  159. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  160. if(NULL == dev) {
  161. pika_platform_printf("modbus_tcp_set_p2p error, dev is NULL.\n");
  162. return 0;
  163. }
  164. if(0 != dev->status) {
  165. pika_platform_printf("modbus_tcp_set_p2p error, dev is opened.\n");
  166. return 0;
  167. }
  168. ret = modbus_tcp_set_p2p_flag(dev, p2p_flag);
  169. if(MODBUS_RT_EOK != ret){
  170. pika_platform_printf("modbus_tcp_set_p2p error, code:%d.\n", ret);
  171. return 0;
  172. }
  173. return 1;
  174. #endif
  175. }
  176. int _modbus_rt__tcp__open(PikaObj *self) {
  177. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  178. pika_platform_printf("modbus tcp is not activated.\n");
  179. return 0;
  180. #else
  181. int ret = 0;
  182. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  183. if(NULL == dev) {
  184. pika_platform_printf("modbus_tcp_open error, dev is NULL.\n");
  185. return 0;
  186. }
  187. if(0 != dev->status) {
  188. pika_platform_printf("modbus_tcp_open error, dev is opened.\n");
  189. return 0;
  190. }
  191. ret = modbus_tcp_open(dev);
  192. if(MODBUS_RT_EOK != ret){
  193. pika_platform_printf("modbus_tcp_open error, code: %d.\n", ret);
  194. return 0;
  195. }
  196. return 1;
  197. #endif
  198. }
  199. int _modbus_rt__tcp__isopen(PikaObj *self) {
  200. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  201. pika_platform_printf("modbus tcp is not activated.\n");
  202. return 0;
  203. #else
  204. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  205. if(NULL == dev) {
  206. pika_platform_printf("modbus_tcp_isopen error, dev is NULL.\n");
  207. return 0;
  208. }
  209. return modbus_tcp_isopen(dev);
  210. #endif
  211. }
  212. int _modbus_rt__tcp__close(PikaObj *self) {
  213. #if (!MODBUS_TCP_SLAVE_ENABLE) && (!MODBUS_TCP_MASTER_ENABLE)
  214. pika_platform_printf("modbus tcp is not activated.\n");
  215. return 0;
  216. #else
  217. int ret = 0;
  218. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  219. if(NULL == dev) {
  220. pika_platform_printf("modbus_tcp_close error, dev is NULL.\n");
  221. return 0;
  222. }
  223. if(0 == dev->status) {
  224. pika_platform_printf("modbus_tcp_close error, dev is closed.\n");
  225. return 0;
  226. }
  227. ret = modbus_tcp_close(dev);
  228. if(MODBUS_RT_EOK != ret){
  229. pika_platform_printf("modbus_tcp_close error, code: %d.\n", ret);
  230. return 0;
  231. }
  232. return 1;
  233. #endif
  234. }
  235. int _modbus_rt__tcp__slave_set_addr(PikaObj *self, int addr) {
  236. #if (!MODBUS_TCP_SLAVE_ENABLE)
  237. pika_platform_printf("modbus tcp slave is not activated.\n");
  238. return 0;
  239. #else
  240. int ret = 0;
  241. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  242. if(NULL == dev) {
  243. pika_platform_printf("modbus_tcp_set_addr error, dev is NULL.\n");
  244. return 0;
  245. }
  246. if(MODBUS_SLAVE != dev->mode){
  247. pika_platform_printf("modbus_tcp_set_addr is only for slave.\n");
  248. return 0;
  249. }
  250. if(0 != dev->status) {
  251. pika_platform_printf("modbus_tcp_set_addr error, dev is opened.\n");
  252. return 0;
  253. }
  254. ret = modbus_tcp_set_addr(dev,addr);
  255. if(MODBUS_RT_EOK != ret){
  256. pika_platform_printf("modbus_tcp_set_addr error, code: %d.\n", ret);
  257. return 0;
  258. }
  259. return 1;
  260. #endif
  261. }
  262. int _modbus_rt__tcp__slave_set_strict(PikaObj *self, int strict) {
  263. #if (!MODBUS_TCP_SLAVE_ENABLE)
  264. pika_platform_printf("modbus tcp slave is not activated.\n");
  265. return 0;
  266. #else
  267. int ret = 0;
  268. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  269. if(NULL == dev) {
  270. pika_platform_printf("modbus_tcp_set_strict error, dev is NULL.\n");
  271. return 0;
  272. }
  273. if(MODBUS_SLAVE != dev->mode){
  274. pika_platform_printf("modbus_tcp_set_strict is only for slave.\n");
  275. return 0;
  276. }
  277. if(0 != dev->status) {
  278. pika_platform_printf("modbus_tcp_set_strict error, dev is opened.\n");
  279. return 0;
  280. }
  281. ret = modbus_tcp_set_strict(dev,strict);
  282. if(MODBUS_RT_EOK != ret){
  283. pika_platform_printf("modbus_tcp_set_strict error, code: %d.\n", ret);
  284. return 0;
  285. }
  286. return 1;
  287. #endif
  288. }
  289. int _modbus_rt__tcp__slave_add_block(PikaObj *self, char* name, int type, int addr, int nums) {
  290. #if (!MODBUS_TCP_SLAVE_ENABLE)
  291. pika_platform_printf("modbus tcp slave is not activated.\n");
  292. return 0;
  293. #else
  294. int ret = 0;
  295. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  296. if(NULL == dev) {
  297. pika_platform_printf("modbus_tcp_add_block error, dev is NULL.\n");
  298. return 0;
  299. }
  300. if(MODBUS_SLAVE != dev->mode){
  301. pika_platform_printf("modbus_tcp_add_block is only for slave.\n");
  302. return 0;
  303. }
  304. if(0 != dev->status) {
  305. pika_platform_printf("modbus_tcp_add_block error, dev is opened.\n");
  306. return 0;
  307. }
  308. if((0 >= strlen(name)) || (0 > type) || (4 < type)){
  309. pika_platform_printf("modbus_tcp_add_block: the para is error.\n");
  310. return 0;
  311. }
  312. int len = 0;
  313. if((CIOLS == type) || (INPUTS == type)) {
  314. len = nums;
  315. } else if((INPUT_REGISTERS == type) || (REGISTERS == type)) {
  316. len = nums * 2;
  317. }
  318. obj_setBytes(self, name, NULL, len);
  319. uint8_t* block = obj_getBytes(self, name);
  320. ret = modbus_tcp_add_block(dev,type, addr, block, nums);
  321. if(MODBUS_RT_EOK != ret){
  322. pika_platform_printf("modbus_tcp_add_block error, code: %d.\n", ret);
  323. return 0;
  324. }
  325. return 1;
  326. #endif
  327. }
  328. int _modbus_rt__tcp__slave_regs_binding(PikaObj *self, Arg* regs, int type, int addr, int nums) {
  329. #if (!MODBUS_TCP_SLAVE_ENABLE)
  330. pika_platform_printf("modbus tcp slave is not activated.\n");
  331. return 0;
  332. #else
  333. int ret = 0;
  334. ArgType t = arg_getType(regs);
  335. if (ARG_TYPE_BYTES != t) {
  336. pika_platform_printf("modbus_tcp_regs_binding: the regs buf type is only for bytes.\n");
  337. return 0;
  338. }
  339. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  340. if(NULL == dev) {
  341. pika_platform_printf("modbus_tcp_regs_binding error, dev is NULL.\n");
  342. return 0;
  343. }
  344. if(MODBUS_SLAVE != dev->mode){
  345. pika_platform_printf("modbus_tcp_regs_binding is only for slave.\n");
  346. return 0;
  347. }
  348. if(0 != dev->status) {
  349. pika_platform_printf("modbus_tcp_regs_binding error, dev is opened.\n");
  350. return 0;
  351. }
  352. size_t regs_size = arg_getBytesSize(regs);
  353. if((CIOLS == type) || (INPUTS == type)) {
  354. if(regs_size < nums) {
  355. pika_platform_printf("modbus_tcp_regs_binding: For CIOLS and INPUTS, the length of regs buf must be greater than nums.\n");
  356. return 0;
  357. }
  358. } else if((INPUT_REGISTERS == type) || (REGISTERS == type)) {
  359. if(regs_size < nums) {
  360. pika_platform_printf("modbus_tcp_regs_binding: For INPUT_REGISTERS and REGISTERS, the length of regs buf must be greater than 2 * nums.\n");
  361. return 0;
  362. }
  363. }
  364. uint8_t* block = arg_getBytes(regs);
  365. ret = modbus_tcp_add_block(dev, type, addr, block, nums);
  366. if(MODBUS_RT_EOK != ret){
  367. pika_platform_printf("modbus_tcp_regs_binding error, code: %d.\n", ret);
  368. return 0;
  369. }
  370. return 1;
  371. #endif
  372. return 0;
  373. }
  374. #if (MODBUS_TCP_SLAVE_ENABLE) || (MODBUS_TCP_MASTER_ENABLE)
  375. PikaEventListener* g_modbus_rt_tcp_event_listener = NULL;
  376. #endif
  377. int _modbus_rt__tcp__slave_pre_ans_handler(agile_modbus_t *ctx, int slave, int function,int addr, int quantity) {
  378. #if (!MODBUS_TCP_SLAVE_ENABLE)
  379. pika_platform_printf("modbus tcp slave is not activated.\n");
  380. return 0;
  381. #else
  382. char hash_str[32] = {0};
  383. memset(hash_str, 0, sizeof(hash_str));
  384. sprintf(hash_str, "pre_ans%p", ctx);
  385. uint32_t eventId = hash_time33(hash_str);
  386. Arg* evt_obj_arg = arg_newDirectObj(New_TinyObj);
  387. PikaObj* evt_obj = arg_getPtr(evt_obj_arg);
  388. obj_setInt(evt_obj, "slave", slave);
  389. obj_setInt(evt_obj, "function", function);
  390. obj_setInt(evt_obj, "addr", addr);
  391. obj_setInt(evt_obj, "quantity", quantity);
  392. pika_eventListener_send(g_modbus_rt_tcp_event_listener, eventId, evt_obj_arg);
  393. return 1;
  394. #endif
  395. }
  396. int _modbus_rt__tcp__slave_set_pre_ans_callback(PikaObj *self, Arg* cb) {
  397. #if (!MODBUS_TCP_SLAVE_ENABLE)
  398. pika_platform_printf("modbus tcp slave is not activated.\n");
  399. return 0;
  400. #else
  401. int ret = 0;
  402. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  403. if(NULL == dev) {
  404. pika_platform_printf("modbus_tcp_set_pre_ans_callback error, dev is NULL.\n");
  405. return 0;
  406. }
  407. if(MODBUS_SLAVE != dev->mode){
  408. pika_platform_printf("modbus_tcp_set_pre_ans_callback is only for slave.\n");
  409. return 0;
  410. }
  411. if(0 != dev->status) {
  412. pika_platform_printf("modbus_tcp_set_pre_ans_callback error, dev is opened.\n");
  413. return 0;
  414. }
  415. if(NULL == cb) {
  416. pika_platform_printf("modbus_tcp_set_pre_ans_callback error, cb is NULL.\n");
  417. return 0;
  418. }
  419. ret = modbus_tcp_set_pre_ans_callback(dev,_modbus_rt__tcp__slave_pre_ans_handler);
  420. if(MODBUS_RT_EOK != ret){
  421. pika_platform_printf("modbus_rtu_set_pre_ans_callback error, code: %d.\n", ret);
  422. return 0;
  423. }
  424. if (NULL == g_modbus_rt_tcp_event_listener) {
  425. pika_eventListener_init(&g_modbus_rt_tcp_event_listener);
  426. }
  427. char hash_str[32] = {0};
  428. memset(hash_str, 0, sizeof(hash_str));
  429. sprintf(hash_str, "pre_ans%p", dev->ctx);
  430. uint32_t eventId = hash_time33(hash_str);
  431. pika_eventListener_registEventCallback(g_modbus_rt_tcp_event_listener, eventId, cb);
  432. return 1;
  433. #endif
  434. }
  435. int _modbus_rt__tcp__slave_done_handler(agile_modbus_t *ctx, int slave, int function,int addr, int quantity) {
  436. #if (!MODBUS_TCP_SLAVE_ENABLE)
  437. pika_platform_printf("modbus tcp slave is not activated.\n");
  438. return 0;
  439. #else
  440. char hash_str[32] = {0};
  441. memset(hash_str, 0, sizeof(hash_str));
  442. sprintf(hash_str, "done%p", ctx);
  443. uint32_t eventId = hash_time33(hash_str);
  444. Arg* evt_obj_arg = arg_newDirectObj(New_TinyObj);
  445. PikaObj* evt_obj = arg_getPtr(evt_obj_arg);
  446. obj_setInt(evt_obj, "slave", slave);
  447. obj_setInt(evt_obj, "function", function);
  448. obj_setInt(evt_obj, "addr", addr);
  449. obj_setInt(evt_obj, "quantity", quantity);
  450. pika_eventListener_send(g_modbus_rt_tcp_event_listener, eventId, evt_obj_arg);
  451. return 1;
  452. #endif
  453. }
  454. int _modbus_rt__tcp__slave_set_done_callback(PikaObj *self, Arg* cb) {
  455. #if (!MODBUS_TCP_SLAVE_ENABLE)
  456. pika_platform_printf("modbus tcp slave is not activated.\n");
  457. return 0;
  458. #else
  459. int ret = 0;
  460. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  461. if(NULL == dev) {
  462. pika_platform_printf("modbus_tcp_set_done_callback error, dev is NULL.\n");
  463. return 0;
  464. }
  465. if(MODBUS_SLAVE != dev->mode){
  466. pika_platform_printf("modbus_tcp_set_done_callback is only for slave.\n");
  467. return 0;
  468. }
  469. if(0 != dev->status) {
  470. pika_platform_printf("modbus_tcp_set_done_callback error, dev is opened.\n");
  471. return 0;
  472. }
  473. if(NULL == cb) {
  474. pika_platform_printf("modbus_tcp_set_done_callback error, cb is NULL.\n");
  475. return 0;
  476. }
  477. ret = modbus_tcp_set_done_callback(dev,_modbus_rt__tcp__slave_done_handler);
  478. if(MODBUS_RT_EOK != ret){
  479. pika_platform_printf("modbus_tcp_set_done_callback error, code: %d.\n", ret);
  480. return 0;
  481. }
  482. if (NULL == g_modbus_rt_tcp_event_listener) {
  483. pika_eventListener_init(&g_modbus_rt_tcp_event_listener);
  484. }
  485. char hash_str[32] = {0};
  486. memset(hash_str, 0, sizeof(hash_str));
  487. sprintf(hash_str, "done%p", dev->ctx);
  488. uint32_t eventId = hash_time33(hash_str);
  489. pika_eventListener_registEventCallback(g_modbus_rt_tcp_event_listener, eventId, cb);
  490. return 1;
  491. #endif
  492. }
  493. int _modbus_rt__tcp__slave_set_dev_binding(PikaObj *self, int flag) {
  494. #if (!MODBUS_TCP_SLAVE_ENABLE)
  495. pika_platform_printf("modbus tcp slave is not activated.\n");
  496. return 0;
  497. #elif (!SLAVE_DATA_DEVICE_BINDING)
  498. pika_platform_printf("SLAVE_DATA_DEVICE_BINDING is not activated.\n");
  499. return 0;
  500. #else
  501. int ret = 0;
  502. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  503. if(NULL == dev) {
  504. pika_platform_printf("modbus_tcp_set_dev_binding error, dev is NULL.\n");
  505. return 0;
  506. }
  507. if(MODBUS_SLAVE != dev->mode){
  508. pika_platform_printf("modbus_tcp_set_dev_binding is only for slave.\n");
  509. return 0;
  510. }
  511. if(0 != dev->status) {
  512. pika_platform_printf("modbus_tcp_set_dev_binding error, dev is opened.\n");
  513. return 0;
  514. }
  515. ret = modbus_tcp_set_dev_binding(dev,flag);
  516. if(MODBUS_RT_EOK != ret){
  517. pika_platform_printf("modbus_tcp_set_dev_binding error, code: %d.\n", ret);
  518. return 0;
  519. }
  520. return 1;
  521. #endif
  522. }
  523. int _modbus_rt__tcp__master_set_server(PikaObj *self, char* saddr, int sport) {
  524. #if (!MODBUS_TCP_MASTER_ENABLE)
  525. pika_platform_printf("modbus tcp master is not activated.\n");
  526. return 0;
  527. #else
  528. int ret = 0;
  529. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  530. if(NULL == dev) {
  531. pika_platform_printf("modbus_tcp_set_server error, dev is NULL.\n");
  532. return 0;
  533. }
  534. if(MODBUS_MASTER != dev->mode){
  535. pika_platform_printf("modbus_tcp_set_server is only for master.\n");
  536. return 0;
  537. }
  538. ret = modbus_tcp_set_server(dev, saddr, sport);
  539. if(MODBUS_RT_EOK != ret){
  540. pika_platform_printf("modbus_tcp_set_server error, code: %d.\n", ret);
  541. return 0;
  542. }
  543. return 1;
  544. #endif
  545. }
  546. char* _modbus_rt__tcp__master_get_saddr(PikaObj *self) {
  547. #if (!MODBUS_TCP_MASTER_ENABLE)
  548. pika_platform_printf("modbus tcp master is not activated.\n");
  549. return NULL;
  550. #else
  551. int ret = 0;
  552. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  553. if(NULL == dev) {
  554. pika_platform_printf("modbus_tcp_get_saddr error, dev is NULL.\n");
  555. return NULL;
  556. }
  557. if((MODBUS_MASTER != dev->mode)){
  558. pika_platform_printf("modbus_tcp_get_saddr is only for master.\n");
  559. return NULL;
  560. }
  561. char saddr[INET_ADDRSTRLEN];
  562. ret = modbus_tcp_get_saddr(dev, saddr);
  563. if(MODBUS_RT_EOK != ret){
  564. pika_platform_printf("modbus_tcp_get_saddr error, code: %d.\n", ret);
  565. return NULL;
  566. }
  567. char* str = obj_cacheStr(self, saddr);
  568. return str;
  569. #endif
  570. }
  571. PikaObj* _modbus_rt__tcp__slave_read_regs(PikaObj *self, int type, int addr, PikaTuple* val){
  572. #if (!MODBUS_TCP_SLAVE_ENABLE)
  573. pika_platform_printf("modbus tcp slave is not activated.\n");
  574. return NULL;
  575. #else
  576. int ret = 0;
  577. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  578. if(NULL == dev) {
  579. pika_platform_printf("modbus_tcp_read_regs error, dev is NULL.\n");
  580. return NULL;
  581. }
  582. if(MODBUS_SLAVE != dev->mode){
  583. pika_platform_printf("modbus_tcp_read_regs is only for slave.\n");
  584. return NULL;
  585. }
  586. if(0 == dev->status) {
  587. pika_platform_printf("modbus_tcp_read_regs error, dev is not opened.\n");
  588. return 0;
  589. }
  590. uint8_t *dest = NULL;
  591. /* 确保参数正确,且值无误*/
  592. if(1 != pikaTuple_getSize(val)) {
  593. pika_platform_printf("modbus_tcp_read_regs: the para num of func is error.\n");
  594. return NULL;
  595. }
  596. Arg* arg_0 = pikaTuple_getArg(val, 0);
  597. ArgType t = arg_getType(arg_0);
  598. if (ARG_TYPE_INT != t) {
  599. pika_platform_printf("modbus_tcp_read_regs: the para type of func is error.\n");
  600. return NULL;
  601. }
  602. int quantity = arg_getInt(arg_0);
  603. if(0 >= quantity) {
  604. pika_platform_printf("modbus_tcp_read_regs: quantity can not be zero or negative.\n");
  605. return NULL;
  606. }
  607. if((CIOLS == type) || (INPUTS == type)) {
  608. dest = modbus_rt_calloc(1,quantity);
  609. if(dest == NULL) {
  610. pika_platform_printf("modbus_tcp_read_regs: mem is not enough.\n");
  611. return NULL;
  612. }
  613. } else if((INPUT_REGISTERS == type) || (REGISTERS == type)) {
  614. dest = modbus_rt_calloc(1,quantity * 2);
  615. if(dest == NULL) {
  616. pika_platform_printf("modbus_tcp_read_regs: mem is not enough.\n");
  617. return NULL;
  618. }
  619. }
  620. pika_GIL_EXIT();
  621. ret = modbus_tcp_excuse(dev, MODBUS_READ, type, addr, quantity, dest);
  622. pika_GIL_ENTER();
  623. if(MODBUS_RT_EOK != ret) {
  624. modbus_rt_free(dest);
  625. pika_platform_printf("modbus_tcp_read_regs: modbus_tcp_excuse error, code: %d.\n", ret);
  626. return NULL;
  627. }
  628. uint16_t *dest_r = (uint16_t *)dest;
  629. PikaList* list = New_PikaList();
  630. for(int i = 0; i < quantity; i++ ) {
  631. if((CIOLS == type) || (INPUTS == type)) {
  632. pikaList_append(list, arg_newInt(dest[i]));
  633. } else if((INPUT_REGISTERS == type) || (REGISTERS == type)) {
  634. pikaList_append(list, arg_newInt(dest_r[i]));
  635. }
  636. }
  637. modbus_rt_free(dest);
  638. return list;
  639. #endif
  640. }
  641. int _modbus_rt__tcp__slave_write_regs(PikaObj *self, int type, int addr, PikaTuple* val) {
  642. #if (!MODBUS_TCP_SLAVE_ENABLE)
  643. pika_platform_printf("modbus tcp slave is not activated.\n");
  644. return 0;
  645. #else
  646. int ret = 0;
  647. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  648. if(NULL == dev) {
  649. pika_platform_printf("modbus_tcp_write_regs error, dev is NULL.\n");
  650. return 0;
  651. }
  652. if(MODBUS_SLAVE != dev->mode){
  653. pika_platform_printf("modbus_tcp_write_regs is only for master.\n");
  654. return 0;
  655. }
  656. if(0 == dev->status) {
  657. pika_platform_printf("modbus_tcp_write_regs error, dev is not opened.\n");
  658. return 0;
  659. }
  660. uint8_t *dest = NULL;
  661. /* 确保参数正确,且值无误*/
  662. if(2 != pikaTuple_getSize(val)) {
  663. pika_platform_printf("modbus_tcp_write_regs: the para num of func is error.\n");
  664. return 0;
  665. }
  666. Arg* arg_0 = pikaTuple_getArg(val, 0);
  667. ArgType t = arg_getType(arg_0);
  668. if (ARG_TYPE_INT != t) {
  669. pika_platform_printf("modbus_tcp_write_regs: the para0 type of func is error.\n");
  670. return 0;
  671. }
  672. int quantity = arg_getInt(arg_0);
  673. if((CIOLS == type) || (INPUTS == type)) {
  674. dest = modbus_rt_calloc(1,quantity);
  675. if(dest == NULL) {
  676. pika_platform_printf("modbus_tcp_write_regs: mem is not enough.\n");
  677. return 0;
  678. }
  679. memset(dest,0,quantity);
  680. } else if((INPUT_REGISTERS == type) || (REGISTERS == type)) {
  681. dest = modbus_rt_calloc(1,quantity * 2);
  682. if(dest == NULL) {
  683. pika_platform_printf("modbus_tcp_write_regs: mem is not enough.\n");
  684. return 0;
  685. }
  686. memset(dest,0,quantity * 2);
  687. }
  688. Arg* arg_1 = pikaTuple_getArg(val, 1);
  689. t = arg_getType(arg_1);
  690. if (ARG_TYPE_OBJECT != t) {
  691. pika_platform_printf("modbus_tcp_write_regs: the para1 type of func is error.\n");
  692. return 0;
  693. }
  694. PikaObj* _list = arg_getPtr(arg_1);
  695. int len_list = pikaList_getSize(_list);
  696. if(len_list > quantity) {
  697. len_list = quantity;
  698. }
  699. if((CIOLS == type) || (INPUTS == type)) {
  700. for(int i = 0; i < len_list; i++) {
  701. dest[i] = pikaList_getInt(_list, i);
  702. }
  703. pika_GIL_EXIT();
  704. ret = modbus_tcp_excuse(dev, MODBUS_WRITE, type, addr, quantity, dest);
  705. pika_GIL_ENTER();
  706. if(MODBUS_RT_EOK != ret) {
  707. modbus_rt_free(dest);
  708. pika_platform_printf("modbus_tcp_write_regs: modbus_tcp_excuse error, code: %d.\n", ret);
  709. return 0;
  710. }
  711. } else if((INPUT_REGISTERS == type) || (REGISTERS == type)) {
  712. uint16_t *dest_r = (uint16_t *)dest;
  713. for(int i = 0; i < len_list; i++){
  714. dest_r[i] = pikaList_getInt(_list, i);
  715. }
  716. pika_GIL_EXIT();
  717. ret = modbus_tcp_excuse(dev, MODBUS_WRITE, type, addr, quantity, dest_r);
  718. pika_GIL_ENTER();
  719. if(MODBUS_RT_EOK != ret) {
  720. modbus_rt_free(dest);
  721. pika_platform_printf("modbus_tcp_write_regs: modbus_tcp_excuse error, code: %d.\n", ret);
  722. return 0;
  723. }
  724. }
  725. modbus_rt_free(dest);
  726. return 1;
  727. #endif
  728. }
  729. PikaObj* _modbus_rt__tcp__master_read_list(PikaObj *self, int slave, int fuction, int addr, PikaTuple* val) {
  730. #if (!MODBUS_TCP_MASTER_ENABLE)
  731. pika_platform_printf("modbus tcp master is not activated.\n");
  732. return NULL;
  733. #else
  734. int ret = 0;
  735. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  736. if(NULL == dev) {
  737. pika_platform_printf("modbus_tcp_read_list error, dev is NULL.\n");
  738. return NULL;
  739. }
  740. if(MODBUS_MASTER != dev->mode){
  741. pika_platform_printf("modbus_tcp_read_list is only for master.\n");
  742. return NULL;
  743. }
  744. if(0 == dev->status) {
  745. pika_platform_printf("modbus_tcp_read_list error, dev is not opened.\n");
  746. return 0;
  747. }
  748. uint8_t *dest = NULL;
  749. /* 确保参数正确,且值无误*/
  750. if(1 != pikaTuple_getSize(val)) {
  751. pika_platform_printf("modbus_tcp_read_list: the para num of func is error.\n");
  752. return NULL;
  753. }
  754. Arg* arg_0 = pikaTuple_getArg(val, 0);
  755. ArgType t = arg_getType(arg_0);
  756. if (ARG_TYPE_INT != t) {
  757. pika_platform_printf("modbus_tcp_read_list: the para type of func is error.\n");
  758. return NULL;
  759. }
  760. int quantity = arg_getInt(arg_0);
  761. if(0 >= quantity) {
  762. pika_platform_printf("modbus_tcp_read_list: quantity can not be zero or negative.\n");
  763. return NULL;
  764. }
  765. if((AGILE_MODBUS_FC_READ_COILS == fuction) ||(AGILE_MODBUS_FC_READ_DISCRETE_INPUTS == fuction)) {
  766. dest = modbus_rt_calloc(1,quantity);
  767. if(dest == NULL) {
  768. pika_platform_printf("modbus_tcp_read_list: mem is not enough.\n");
  769. return NULL;
  770. }
  771. } else if((AGILE_MODBUS_FC_READ_HOLDING_REGISTERS == fuction) ||(AGILE_MODBUS_FC_READ_INPUT_REGISTERS == fuction)) {
  772. dest = modbus_rt_calloc(1,quantity * 2);
  773. if(dest == NULL) {
  774. pika_platform_printf("modbus_tcp_read_list: mem is not enough.\n");
  775. return NULL;
  776. }
  777. }
  778. pika_GIL_EXIT();
  779. ret = modbus_tcp_excuse(dev, slave, fuction, addr, quantity, dest);
  780. pika_GIL_ENTER();
  781. if(MODBUS_RT_EOK != ret) {
  782. modbus_rt_free(dest);
  783. pika_platform_printf("modbus_tcp_read_list: modbus_tcp_excuse error, code: %d.\n", ret);
  784. return NULL;
  785. }
  786. uint16_t *dest_r = (uint16_t *)dest;
  787. PikaList* list = New_PikaList();
  788. for(int i = 0; i < quantity; i++ ) {
  789. if((AGILE_MODBUS_FC_READ_COILS == fuction) ||(AGILE_MODBUS_FC_READ_DISCRETE_INPUTS == fuction)) {
  790. pikaList_append(list, arg_newInt(dest[i]));
  791. } else if((AGILE_MODBUS_FC_READ_HOLDING_REGISTERS == fuction) ||(AGILE_MODBUS_FC_READ_INPUT_REGISTERS == fuction)) {
  792. pikaList_append(list, arg_newInt(dest_r[i]));
  793. }
  794. }
  795. modbus_rt_free(dest);
  796. return list;
  797. #endif
  798. }
  799. int _modbus_rt__tcp__master_write_int(PikaObj *self, int slave, int fuction, int addr, PikaTuple* val) {
  800. #if (!MODBUS_TCP_MASTER_ENABLE)
  801. pika_platform_printf("modbus tcp master is not activated.\n");
  802. return 0;
  803. #else
  804. int ret = 0;
  805. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  806. if(NULL == dev) {
  807. pika_platform_printf("modbus_tcp_write_int error, dev is NULL.\n");
  808. return 0;
  809. }
  810. if(MODBUS_MASTER != dev->mode){
  811. pika_platform_printf("modbus_tcp_write_int is only for master.\n");
  812. return 0;
  813. }
  814. if(0 == dev->status) {
  815. pika_platform_printf("modbus_tcp_write_int error, dev is not opened.\n");
  816. return 0;
  817. }
  818. /* 确保参数正确,且值无误*/
  819. if(1 != pikaTuple_getSize(val)) {
  820. pika_platform_printf("modbus_tcp_write_int: the para num of func is error.\n");
  821. return 0;
  822. }
  823. Arg* arg_0 = pikaTuple_getArg(val, 0);
  824. ArgType t = arg_getType(arg_0);
  825. if (ARG_TYPE_INT != t) {
  826. pika_platform_printf("modbus_tcp_write_int: the para type of func is error.\n");
  827. return 0;
  828. }
  829. int value = arg_getInt(arg_0);
  830. pika_GIL_EXIT();
  831. ret = modbus_tcp_excuse(dev, slave, fuction, addr, 1, &value);
  832. pika_GIL_ENTER();
  833. if(MODBUS_RT_EOK != ret) {
  834. pika_platform_printf("modbus_tcp_write_int: modbus_tcp_excuse error, code: %d.\n", ret);
  835. return 0;
  836. }
  837. return 1;
  838. #endif
  839. }
  840. int _modbus_rt__tcp__master_write_list(PikaObj *self, int slave, int fuction, int addr, PikaTuple* val) {
  841. #if (!MODBUS_TCP_MASTER_ENABLE)
  842. pika_platform_printf("modbus tcp master is not activated.\n");
  843. return 0;
  844. #else
  845. int ret = 0;
  846. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  847. if(NULL == dev) {
  848. pika_platform_printf("modbus_tcp_write_int error, dev is NULL.\n");
  849. return 0;
  850. }
  851. if(MODBUS_MASTER != dev->mode){
  852. pika_platform_printf("modbus_tcp_write_int is only for master.\n");
  853. return 0;
  854. }
  855. if(0 == dev->status) {
  856. pika_platform_printf("modbus_tcp_write_int error, dev is not opened.\n");
  857. return 0;
  858. }
  859. uint8_t *dest = NULL;
  860. /* 确保参数正确,且值无误*/
  861. if(2 != pikaTuple_getSize(val)) {
  862. pika_platform_printf("modbus_tcp_write_int: the para num of func is error.\n");
  863. return 0;
  864. }
  865. Arg* arg_0 = pikaTuple_getArg(val, 0);
  866. ArgType t = arg_getType(arg_0);
  867. if (ARG_TYPE_INT != t) {
  868. pika_platform_printf("modbus_tcp_write_int: the para0 type of func is error.\n");
  869. return 0;
  870. }
  871. int quantity = arg_getInt(arg_0);
  872. if(fuction == AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS) {
  873. dest = modbus_rt_calloc(1,quantity);
  874. if(dest == NULL) {
  875. pika_platform_printf("modbus_tcp_write_int: mem is not enough.\n");
  876. return 0;
  877. }
  878. memset(dest,0,quantity);
  879. } else if(fuction == AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS) {
  880. dest = modbus_rt_calloc(1,quantity * 2);
  881. if(dest == NULL) {
  882. pika_platform_printf("modbus_tcp_write_int: mem is not enough.\n");
  883. return 0;
  884. }
  885. memset(dest,0,quantity * 2);
  886. }
  887. Arg* arg_1 = pikaTuple_getArg(val, 1);
  888. t = arg_getType(arg_1);
  889. if (ARG_TYPE_OBJECT != t) {
  890. pika_platform_printf("modbus_tcp_write_int: the para1 type of func is error.\n");
  891. return 0;
  892. }
  893. PikaObj* _list = arg_getPtr(arg_1);
  894. int len_list = pikaList_getSize(_list);
  895. if(len_list > quantity) {
  896. len_list = quantity;
  897. }
  898. if(fuction == AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS) {
  899. for(int i = 0; i < len_list; i++) {
  900. dest[i] = pikaList_getInt(_list, i);
  901. }
  902. pika_GIL_EXIT();
  903. ret = modbus_tcp_excuse(dev, slave, fuction, addr, quantity, dest);
  904. pika_GIL_ENTER();
  905. if(MODBUS_RT_EOK != ret) {
  906. modbus_rt_free(dest);
  907. pika_platform_printf("modbus_tcp_write_int: modbus_tcp_excuse error, code: %d.\n", ret);
  908. return 0;
  909. }
  910. } else if(fuction == AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS) {
  911. uint16_t *dest_r = (uint16_t *)dest;
  912. for(int i = 0; i < len_list; i++){
  913. dest_r[i] = pikaList_getInt(_list, i);
  914. }
  915. pika_GIL_EXIT();
  916. ret = modbus_tcp_excuse(dev, slave, fuction, addr, quantity, dest_r);
  917. pika_GIL_ENTER();
  918. if(MODBUS_RT_EOK != ret) {
  919. modbus_rt_free(dest);
  920. pika_platform_printf("modbus_tcp_write_int: modbus_tcp_excuse error, code: %d.\n", ret);
  921. return 0;
  922. }
  923. }
  924. modbus_rt_free(dest);
  925. return 1;
  926. #endif
  927. }
  928. int _modbus_rt__tcp__master_download(PikaObj *self, int slave, char* file_dev, char* file_master) {
  929. #if (!MODBUS_TCP_MASTER_ENABLE)
  930. pika_platform_printf("modbus tcp master is not activated.\n");
  931. return 0;
  932. #elif (!MODBUS_P2P_ENABLE) || (!MODBUS_P2P_MASTER_ENABLE)
  933. pika_platform_printf("MODBUS_P2P_ENABLE and MODBUS_P2P_MASTER_ENABLE is not enabled.\n");
  934. return 0;
  935. #else
  936. int ret = 0;
  937. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  938. if(NULL == dev) {
  939. pika_platform_printf("modbus_tcp_download error, dev is NULL.\n");
  940. return 0;
  941. }
  942. if(MODBUS_MASTER != dev->mode){
  943. pika_platform_printf("modbus_tcp_download is only for master.\n");
  944. return 0;
  945. }
  946. if(0 == dev->status) {
  947. pika_platform_printf("modbus_tcp_download error, dev is not opened.\n");
  948. return 0;
  949. }
  950. if(0 == dev->p2p_flag) {
  951. pika_platform_printf("modbus_tcp_download error, p2p_flag is not seted.\n");
  952. return 0;
  953. }
  954. ret = modbus_tcp_excuse_file(dev, slave, MODBUS_WRITE, file_dev, file_master);
  955. if(MODBUS_RT_EOK != ret) {
  956. pika_platform_printf("modbus_tcp_download error, code: %d.\n", ret);
  957. return 0;
  958. }
  959. return 1;
  960. #endif
  961. }
  962. int _modbus_rt__tcp__master_upload(PikaObj *self, int slave, char* file_dev, char* file_master) {
  963. #if (!MODBUS_TCP_MASTER_ENABLE)
  964. pika_platform_printf("modbus tcp master is not activated.\n");
  965. return 0;
  966. #elif (!MODBUS_P2P_ENABLE) || (!MODBUS_P2P_MASTER_ENABLE)
  967. pika_platform_printf("MODBUS_P2P_ENABLE and MODBUS_P2P_MASTER_ENABLE is not enabled.\n");
  968. return 0;
  969. #else
  970. int ret = 0;
  971. tcp_modbus_device_t dev = (tcp_modbus_device_t)obj_getPtr(self, "dev");
  972. if(NULL == dev) {
  973. pika_platform_printf("modbus_tcp_upload error, dev is NULL.\n");
  974. return 0;
  975. }
  976. if(MODBUS_MASTER != dev->mode){
  977. pika_platform_printf("modbus_tcp_upload is only for master.\n");
  978. return 0;
  979. }
  980. if(0 == dev->status) {
  981. pika_platform_printf("modbus_tcp_upload error, dev is not opened.\n");
  982. return 0;
  983. }
  984. if(0 == dev->p2p_flag) {
  985. pika_platform_printf("modbus_tcp_upload error, p2p_flag is not seted.\n");
  986. return 0;
  987. }
  988. ret = modbus_tcp_excuse_file(dev, slave, MODBUS_READ, file_dev, file_master);
  989. if(MODBUS_RT_EOK != ret) {
  990. pika_platform_printf("modbus_tcp_upload error, code: %d.\n", ret);
  991. return 0;
  992. }
  993. return 1;
  994. #endif
  995. }