|
|
1.1 root 1: /* js_com.c */
2:
3: /* Synchronet JavaScript "COM" Object */
4:
5: /* $Id: js_com.c,v 1.4 2011/09/09 19:58:33 deuce Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "comio.h"
40: #include "js_request.h"
41:
42: #ifdef JAVASCRIPT
43:
44: typedef struct
45: {
46: COM_HANDLE com;
47: BOOL external; /* externally created, don't close */
48: BOOL is_open;
49: BOOL network_byte_order;
50: BOOL debug;
51: BOOL dtr;
52: long baud_rate;
53: int last_error;
54: char *dev;
55:
56: } private_t;
57:
58: static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";
59:
60: static void dbprintf(BOOL error, private_t* p, char* fmt, ...)
61: {
62: va_list argptr;
63: char sbuf[1024];
64:
65: if(p==NULL || (!p->debug /*&& !error */))
66: return;
67:
68: va_start(argptr,fmt);
69: vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
70: sbuf[sizeof(sbuf)-1]=0;
71: va_end(argptr);
72:
73: lprintf(LOG_DEBUG,"%s %s%s",p->dev,error ? "ERROR: ":"",sbuf);
74: }
75:
76: /* COM Destructor */
77:
78: static void js_finalize_com(JSContext *cx, JSObject *obj)
79: {
80: private_t* p;
81:
82: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL)
83: return;
84:
85: if(p->external==FALSE && p->com!=COM_HANDLE_INVALID) {
86: comClose(p->com);
87: dbprintf(FALSE, p, "closed");
88: }
89:
90: if(p->dev)
91: free(p->dev);
92: free(p);
93:
94: JS_SetPrivate(cx, obj, NULL);
95: }
96:
97:
98: /* COM Object Methods */
99:
100: static JSBool
101: js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
102: {
103: private_t* p;
104: jsrefcount rc;
105:
106: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
107: JS_ReportError(cx,getprivate_failure,WHERE);
108: return(JS_FALSE);
109: }
110:
111: if(p->com==COM_HANDLE_INVALID)
112: return(JS_TRUE);
113:
114: rc=JS_SUSPENDREQUEST(cx);
115: comClose(p->com);
116:
117: p->last_error = ERROR_VALUE;
118:
119: dbprintf(FALSE, p, "closed");
120:
121: p->com = COM_HANDLE_INVALID;
122: p->is_open = FALSE;
123: JS_RESUMEREQUEST(cx, rc);
124:
125: return(JS_TRUE);
126: }
127:
128: static JSBool
129: js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
130: {
131: private_t* p;
132: jsrefcount rc;
133:
134: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
135: JS_ReportError(cx,getprivate_failure,WHERE);
136: return(JS_FALSE);
137: }
138:
139: rc=JS_SUSPENDREQUEST(cx);
140: dbprintf(FALSE, p, "opening port %s", p->dev);
141:
142: p->com=comOpen(p->dev);
143:
144: if(p->com==COM_HANDLE_INVALID) {
145: p->last_error=ERROR_VALUE;
146: dbprintf(TRUE, p, "connect failed with error %d",ERROR_VALUE);
147: *rval = JSVAL_FALSE;
148: JS_RESUMEREQUEST(cx, rc);
149: return(JS_TRUE);
150: }
151:
152: comSetBaudRate(p->com, p->baud_rate);
153:
154: p->is_open = TRUE;
155: *rval = JSVAL_TRUE;
156: dbprintf(FALSE, p, "connected to port %s", p->dev);
157: JS_RESUMEREQUEST(cx, rc);
158:
159: return(JS_TRUE);
160: }
161:
162: static JSBool
163: js_send(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
164: {
165: char* cp;
166: int len;
167: JSString* str;
168: private_t* p;
169: jsrefcount rc;
170:
171: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
172: JS_ReportError(cx,getprivate_failure,WHERE);
173: return(JS_FALSE);
174: }
175:
176: *rval = JSVAL_FALSE;
177:
178: str = JS_ValueToString(cx, argv[0]);
179: cp = JS_GetStringBytes(str);
180: len = JS_GetStringLength(str);
181:
182: rc=JS_SUSPENDREQUEST(cx);
183: if(comWriteBuf(p->com,cp,len)==len) {
184: dbprintf(FALSE, p, "sent %u bytes",len);
185: *rval = JSVAL_TRUE;
186: } else {
187: p->last_error=ERROR_VALUE;
188: dbprintf(TRUE, p, "send of %u bytes failed",len);
189: }
190: JS_RESUMEREQUEST(cx, rc);
191:
192: return(JS_TRUE);
193: }
194:
195: static JSBool
196: js_sendfile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
197: {
198: long len;
199: int file;
200: char* fname;
201: JSString* str;
202: private_t* p;
203: jsrefcount rc;
204: char *buf;
205:
206: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
207: JS_ReportError(cx,getprivate_failure,WHERE);
208: return(JS_FALSE);
209: }
210:
211: *rval = JSVAL_FALSE;
212:
213: if((str = JS_ValueToString(cx, argv[0]))==NULL
214: || (fname=JS_GetStringBytes(str))==NULL) {
215: JS_ReportError(cx,"Failure reading filename");
216: return(JS_FALSE);
217: }
218:
219: rc=JS_SUSPENDREQUEST(cx);
220: if((file=nopen(fname,O_RDONLY|O_BINARY))==-1) {
221: JS_RESUMEREQUEST(cx, rc);
222: return(JS_TRUE);
223: }
224:
225: len=filelength(file);
226: if((buf=malloc(len))==NULL) {
227: close(file);
228: return(JS_TRUE);
229: }
230: if(read(file,buf,len)!=len) {
231: free(buf);
232: close(file);
233: return(JS_TRUE);
234: }
235: close(file);
236:
237: if(comWriteBuf(p->com,buf,len)==len) {
238: dbprintf(FALSE, p, "sent %u bytes",len);
239: *rval = JSVAL_TRUE;
240: } else {
241: p->last_error=ERROR_VALUE;
242: dbprintf(TRUE, p, "send of %u bytes failed",len);
243: }
244: free(buf);
245:
246: JS_RESUMEREQUEST(cx, rc);
247: return(JS_TRUE);
248: }
249:
250: static JSBool
251: js_sendbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
252: {
253: BYTE b;
254: WORD w;
255: DWORD l;
256: int32 val=0;
257: size_t wr=0;
258: size_t size=sizeof(DWORD);
259: private_t* p;
260: jsrefcount rc;
261:
262: *rval = JSVAL_FALSE;
263:
264: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
265: JS_ReportError(cx,getprivate_failure,WHERE);
266: return(JS_FALSE);
267: }
268:
269: if(argv[0]!=JSVAL_VOID)
270: JS_ValueToInt32(cx,argv[0],&val);
271: if(argc>1 && argv[1]!=JSVAL_VOID)
272: JS_ValueToInt32(cx,argv[1],(int32*)&size);
273:
274: rc=JS_SUSPENDREQUEST(cx);
275: switch(size) {
276: case sizeof(BYTE):
277: b = (BYTE)val;
278: wr=comWriteBuf(p->com,&b,size);
279: break;
280: case sizeof(WORD):
281: w = (WORD)val;
282: if(p->network_byte_order)
283: w=htons(w);
284: wr=comWriteBuf(p->com,(BYTE*)&w,size);
285: break;
286: case sizeof(DWORD):
287: l = val;
288: if(p->network_byte_order)
289: l=htonl(l);
290: wr=comWriteBuf(p->com,(BYTE*)&l,size);
291: break;
292: default:
293: /* unknown size */
294: dbprintf(TRUE, p, "unsupported binary write size: %d",size);
295: break;
296: }
297: if(wr==size) {
298: dbprintf(FALSE, p, "sent %u bytes (binary)",size);
299: *rval = JSVAL_TRUE;
300: } else {
301: p->last_error=ERROR_VALUE;
302: dbprintf(TRUE, p, "send of %u bytes (binary) failed",size);
303: }
304:
305: JS_RESUMEREQUEST(cx, rc);
306: return(JS_TRUE);
307: }
308:
309:
310: static JSBool
311: js_recv(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
312: {
313: char* buf;
314: int32 len=512;
315: JSString* str;
316: jsrefcount rc;
317: int32 timeout=30; /* seconds */
318:
319: private_t* p;
320:
321: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
322: JS_ReportError(cx,getprivate_failure,WHERE);
323: return(JS_FALSE);
324: }
325:
326: if(argc && argv[0]!=JSVAL_VOID)
327: JS_ValueToInt32(cx,argv[0],&len);
328:
329: if(argc>1 && argv[1]!=JSVAL_VOID)
330: JS_ValueToInt32(cx,argv[1],&timeout);
331:
332: if((buf=(char*)alloca(len+1))==NULL) {
333: JS_ReportError(cx,"Error allocating %u bytes",len+1);
334: return(JS_FALSE);
335: }
336:
337: rc=JS_SUSPENDREQUEST(cx);
338: len = comReadBuf(p->com,buf,len,NULL,timeout);
339: JS_RESUMEREQUEST(cx, rc);
340: if(len<0) {
341: p->last_error=ERROR_VALUE;
342: *rval = JSVAL_NULL;
343: return(JS_TRUE);
344: }
345: buf[len]=0;
346:
347: str = JS_NewStringCopyN(cx, buf, len);
348: if(str==NULL)
349: return(JS_FALSE);
350:
351: *rval = STRING_TO_JSVAL(str);
352: rc=JS_SUSPENDREQUEST(cx);
353: dbprintf(FALSE, p, "received %u bytes",len);
354: JS_RESUMEREQUEST(cx, rc);
355:
356: return(JS_TRUE);
357: }
358:
359: static JSBool
360: js_recvline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
361: {
362: char* buf;
363: int i;
364: int32 len=512;
365: int32 timeout=30; /* seconds */
366: JSString* str;
367: private_t* p;
368: jsrefcount rc;
369:
370: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
371: JS_ReportError(cx,getprivate_failure,WHERE);
372: return(JS_FALSE);
373: }
374:
375: if(argc && argv[0]!=JSVAL_VOID)
376: JS_ValueToInt32(cx,argv[0],&len);
377:
378: if((buf=(char*)alloca(len+1))==NULL) {
379: JS_ReportError(cx,"Error allocating %u bytes",len+1);
380: return(JS_FALSE);
381: }
382:
383: if(argc>1 && argv[1]!=JSVAL_VOID)
384: JS_ValueToInt32(cx,argv[1],&timeout);
385:
386: rc=JS_SUSPENDREQUEST(cx);
387:
388: i=comReadLine(p->com, buf, len+1, timeout);
389:
390: if(i>0 && buf[i-1]=='\r')
391: buf[i-1]=0;
392: else
393: buf[i]=0;
394:
395: JS_RESUMEREQUEST(cx, rc);
396: str = JS_NewStringCopyZ(cx, buf);
397: if(str==NULL)
398: return(JS_FALSE);
399:
400: *rval = STRING_TO_JSVAL(str);
401: rc=JS_SUSPENDREQUEST(cx);
402: dbprintf(FALSE, p, "received %u bytes (recvline) lasterror=%d"
403: ,i,ERROR_VALUE);
404: JS_RESUMEREQUEST(cx, rc);
405:
406: return(JS_TRUE);
407: }
408:
409: static JSBool
410: js_recvbin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
411: {
412: BYTE b;
413: WORD w;
414: DWORD l;
415: int size=sizeof(DWORD);
416: int rd=0;
417: private_t* p;
418: jsrefcount rc;
419: int32 timeout=30; /* seconds */
420:
421: *rval = INT_TO_JSVAL(-1);
422:
423: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
424: JS_ReportError(cx,getprivate_failure,WHERE);
425: return(JS_FALSE);
426: }
427:
428: if(argc && argv[0]!=JSVAL_VOID)
429: JS_ValueToInt32(cx,argv[0],(int32*)&size);
430:
431: if(argc>1 && argv[1]!=JSVAL_VOID)
432: JS_ValueToInt32(cx,argv[1],&timeout);
433:
434: rc=JS_SUSPENDREQUEST(cx);
435: switch(size) {
436: case sizeof(BYTE):
437: if((rd=comReadBuf(p->com,(BYTE*)&b,size,NULL,timeout))==size)
438: *rval = INT_TO_JSVAL(b);
439: break;
440: case sizeof(WORD):
441: if((rd=comReadBuf(p->com,(BYTE*)&w,size,NULL,timeout))==size) {
442: if(p->network_byte_order)
443: w=ntohs(w);
444: *rval = INT_TO_JSVAL(w);
445: }
446: break;
447: case sizeof(DWORD):
448: if((rd=comReadBuf(p->com,(BYTE*)&l,size,NULL,timeout))==size) {
449: if(p->network_byte_order)
450: l=ntohl(l);
451: JS_RESUMEREQUEST(cx, rc);
452: JS_NewNumberValue(cx,l,rval);
453: rc=JS_SUSPENDREQUEST(cx);
454: }
455: break;
456: }
457:
458: if(rd!=size)
459: p->last_error=ERROR_VALUE;
460:
461: JS_RESUMEREQUEST(cx, rc);
462: return(JS_TRUE);
463: }
464:
465: /* COM Object Properites */
466: enum {
467: COM_PROP_LAST_ERROR
468: ,COM_PROP_IS_OPEN
469: ,COM_PROP_DEBUG
470: ,COM_PROP_DESCRIPTOR
471: ,COM_PROP_NETWORK_ORDER
472: ,COM_PROP_BAUD_RATE
473: ,COM_PROP_DEVICE
474: ,COM_PROP_DTR
475: ,COM_PROP_CTS
476: ,COM_PROP_DSR
477: ,COM_PROP_RING
478: ,COM_PROP_DCD
479:
480: };
481:
482: #ifdef BUILD_JSDOCS
483: static char* com_prop_desc[] = {
484: "error status for the last COM operation that failed - <small>READ ONLY</small>"
485: ,"<i>true</i> if port is in a connected state - <small>READ ONLY</small>"
486: ,"enable debug logging"
487: ,"COM handle (advanced uses only)"
488: ,"<i>true</i> if binary data is to be sent in Network Byte Order (big end first), default is <i>true</i>"
489: ,"COM port Baud rate"
490: ,"Device name"
491: ,"Data Terminal Ready"
492: ,"Clear To Send"
493: ,"Data Set Ready"
494: ,"Ring Indicator"
495: ,"Data Carrier Detect"
496: ,NULL
497: };
498: #endif
499:
500: static JSBool js_com_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
501: {
502: jsint tiny;
503: private_t* p;
504: jsrefcount rc;
505: double d;
506:
507: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
508: // Prototype access
509: return(JS_TRUE);
510: }
511:
512: tiny = JSVAL_TO_INT(id);
513:
514: rc=JS_SUSPENDREQUEST(cx);
515: dbprintf(FALSE, p, "setting property %d",tiny);
516: JS_RESUMEREQUEST(cx, rc);
517:
518: switch(tiny) {
519: case COM_PROP_DEBUG:
520: JS_ValueToBoolean(cx,*vp,&(p->debug));
521: break;
522: case COM_PROP_DESCRIPTOR:
523: JS_ValueToInt32(cx,*vp,(int32*)&(p->com));
524: p->is_open=TRUE;
525: break;
526: case COM_PROP_LAST_ERROR:
527: JS_ValueToInt32(cx,*vp,(int32*)&(p->last_error));
528: break;
529: case COM_PROP_BAUD_RATE:
530: JS_ValueToNumber(cx,*vp,&d);
531: p->baud_rate=(long)d;
532: rc=JS_SUSPENDREQUEST(cx);
533: if(p->is_open)
534: comSetBaudRate(p->com, p->baud_rate);
535: JS_RESUMEREQUEST(cx, rc);
536: break;
537: case COM_PROP_NETWORK_ORDER:
538: JS_ValueToBoolean(cx,*vp,&(p->network_byte_order));
539: break;
540: case COM_PROP_DTR:
541: JS_ValueToBoolean(cx,*vp,&(p->dtr));
542: if(p->is_open) {
543: if(p->dtr)
544: comRaiseDTR(p->com);
545: else
546: comLowerDTR(p->com);
547: }
548: else
549: p->dtr=FALSE;
550: break;
551:
552: }
553:
554: return(JS_TRUE);
555: }
556:
557: static JSBool js_com_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
558: {
559: jsint tiny;
560: private_t* p;
561: JSString* js_str;
562: jsrefcount rc;
563: long baud_rate;
564: int ms;
565:
566: if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
567: // Protoype access
568: return(JS_TRUE);
569: }
570:
571: tiny = JSVAL_TO_INT(id);
572:
573: rc=JS_SUSPENDREQUEST(cx);
574: #if 0 /* just too much */
575: dbprintf(FALSE, p, "getting property %d",tiny);
576: #endif
577:
578: switch(tiny) {
579: case COM_PROP_LAST_ERROR:
580: *vp = INT_TO_JSVAL(p->last_error);
581: break;
582: case COM_PROP_IS_OPEN:
583: if(p->is_open)
584: *vp = JSVAL_TRUE;
585: else
586: *vp = JSVAL_FALSE;
587: break;
588: case COM_PROP_DEBUG:
589: *vp = BOOLEAN_TO_JSVAL(p->debug);
590: break;
591: case COM_PROP_DESCRIPTOR:
592: *vp = INT_TO_JSVAL(p->com);
593: //p->is_open = TRUE;
594: break;
595: case COM_PROP_NETWORK_ORDER:
596: *vp = BOOLEAN_TO_JSVAL(p->network_byte_order);
597: break;
598: case COM_PROP_BAUD_RATE:
599: baud_rate=comGetBaudRate(p->com);
600: JS_RESUMEREQUEST(cx, rc);
601: JS_NewNumberValue(cx,baud_rate,vp);
602: rc=JS_SUSPENDREQUEST(cx);
603: break;
604: case COM_PROP_DEVICE:
605: JS_RESUMEREQUEST(cx, rc);
606: if((js_str=JS_NewStringCopyZ(cx,p->dev))==NULL)
607: return(JS_FALSE);
608: *vp = STRING_TO_JSVAL(js_str);
609: rc=JS_SUSPENDREQUEST(cx);
610: break;
611: case COM_PROP_DTR:
612: *vp = BOOLEAN_TO_JSVAL(p->dtr);
613: break;
614: case COM_PROP_CTS:
615: ms=comGetModemStatus(p->com);
616: *vp = BOOLEAN_TO_JSVAL(ms & COM_CTS);
617: break;
618: case COM_PROP_DSR:
619: ms=comGetModemStatus(p->com);
620: *vp = BOOLEAN_TO_JSVAL(ms & COM_DSR);
621: break;
622: case COM_PROP_RING:
623: ms=comGetModemStatus(p->com);
624: *vp = BOOLEAN_TO_JSVAL(ms & COM_RING);
625: break;
626: case COM_PROP_DCD:
627: ms=comGetModemStatus(p->com);
628: *vp = BOOLEAN_TO_JSVAL(ms & COM_DCD);
629: break;
630:
631: }
632:
633: JS_RESUMEREQUEST(cx, rc);
634: return(TRUE);
635: }
636:
637: #define COM_PROP_FLAGS JSPROP_ENUMERATE|JSPROP_READONLY
638:
639: static jsSyncPropertySpec js_com_properties[] = {
640: /* name ,tinyid ,flags, ver */
641:
642: { "error" ,COM_PROP_LAST_ERROR ,COM_PROP_FLAGS, 315 },
643: { "last_error" ,COM_PROP_LAST_ERROR ,JSPROP_READONLY, 315 }, /* alias */
644: { "is_open" ,COM_PROP_IS_OPEN ,COM_PROP_FLAGS, 315 },
645: { "debug" ,COM_PROP_DEBUG ,JSPROP_ENUMERATE, 315 },
646: { "descriptor" ,COM_PROP_DESCRIPTOR ,JSPROP_ENUMERATE, 315 },
647: { "network_byte_order",COM_PROP_NETWORK_ORDER ,JSPROP_ENUMERATE, 315 },
648: { "baud_rate" ,COM_PROP_BAUD_RATE ,JSPROP_ENUMERATE, 315 },
649: { "device" ,COM_PROP_DEVICE ,COM_PROP_FLAGS, 315 },
650: { "dtr" ,COM_PROP_DTR ,JSPROP_ENUMERATE, 315 },
651: { "cts" ,COM_PROP_CTS ,COM_PROP_FLAGS, 315 },
652: { "dsr" ,COM_PROP_DSR ,COM_PROP_FLAGS, 315 },
653: { "ring" ,COM_PROP_RING ,COM_PROP_FLAGS, 315 },
654: { "dcd" ,COM_PROP_DCD ,COM_PROP_FLAGS, 315 },
655: {0}
656: };
657:
658: static jsSyncMethodSpec js_com_functions[] = {
659: {"close", js_close, 0, JSTYPE_VOID, ""
660: ,JSDOCSTR("close the port immediately")
661: ,315
662: },
663: {"open", js_open, 2, JSTYPE_BOOLEAN, JSDOCSTR("")
664: ,JSDOCSTR("connect to a COM port")
665: ,315
666: },
667: {"write", js_send, 1, JSTYPE_ALIAS },
668: {"send", js_send, 1, JSTYPE_BOOLEAN, JSDOCSTR("data")
669: ,JSDOCSTR("send a string (AKA write)")
670: ,315
671: },
672: {"sendfile", js_sendfile, 1, JSTYPE_BOOLEAN, JSDOCSTR("path/filename")
673: ,JSDOCSTR("send an entire file over the port")
674: ,315
675: },
676: {"writeBin", js_sendbin, 1, JSTYPE_ALIAS },
677: {"sendBin", js_sendbin, 1, JSTYPE_BOOLEAN, JSDOCSTR("value [,bytes=<tt>4</tt>]")
678: ,JSDOCSTR("send a binary integer over the port, default number of bytes is 4 (32-bits)")
679: ,315
680: },
681: {"read", js_recv, 1, JSTYPE_ALIAS },
682: {"recv", js_recv, 1, JSTYPE_STRING, JSDOCSTR("[maxlen=<tt>512</tt> [,timeout=<tt>30</tt>]]")
683: ,JSDOCSTR("receive a string, default maxlen is 512 characters, default timeout is 30 seconds (AKA read)")
684: ,315
685: },
686: {"readline", js_recvline, 0, JSTYPE_ALIAS },
687: {"readln", js_recvline, 0, JSTYPE_ALIAS },
688: {"recvline", js_recvline, 0, JSTYPE_STRING, JSDOCSTR("[maxlen=<tt>512</tt>] [,timeout=<tt>30.0</tt>]")
689: ,JSDOCSTR("receive a line-feed terminated string, default maxlen is 512 characters, default timeout is 30 seconds (AKA readline and readln)")
690: ,315
691: },
692: {"readBin", js_recvbin, 0, JSTYPE_ALIAS },
693: {"recvBin", js_recvbin, 0, JSTYPE_NUMBER, JSDOCSTR("[bytes=<tt>4</tt> [,timeout=<tt>30</tt>]")
694: ,JSDOCSTR("receive a binary integer from the port, default number of bytes is 4 (32-bits), default timeout is 30 seconds")
695: ,315
696: },
697: {0}
698: };
699:
700: static JSBool js_com_resolve(JSContext *cx, JSObject *obj, jsval id)
701: {
702: char* name=NULL;
703:
704: if(id != JSVAL_NULL)
705: name=JS_GetStringBytes(JSVAL_TO_STRING(id));
706:
707: return(js_SyncResolve(cx, obj, name, js_com_properties, js_com_functions, NULL, 0));
708: }
709:
710: static JSBool js_com_enumerate(JSContext *cx, JSObject *obj)
711: {
712: return(js_com_resolve(cx, obj, JSVAL_NULL));
713: }
714:
715: static JSClass js_com_class = {
716: "COM" /* name */
717: ,JSCLASS_HAS_PRIVATE /* flags */
718: ,JS_PropertyStub /* addProperty */
719: ,JS_PropertyStub /* delProperty */
720: ,js_com_get /* getProperty */
721: ,js_com_set /* setProperty */
722: ,js_com_enumerate /* enumerate */
723: ,js_com_resolve /* resolve */
724: ,JS_ConvertStub /* convert */
725: ,js_finalize_com /* finalize */
726: };
727:
728: /* COM Constructor (creates COM descriptor) */
729:
730: static JSBool
731: js_com_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
732: {
733: private_t* p;
734: char* protocol=NULL;
735: char* fname;
736: JSString* str;
737:
738: if(argc==0 || (str = JS_ValueToString(cx, argv[0]))==NULL
739: || (fname=JS_GetStringBytes(str))==NULL) {
740: JS_ReportError(cx,"Failure reading port name");
741: return(JS_FALSE);
742: }
743:
744: if((p=(private_t*)malloc(sizeof(private_t)))==NULL) {
745: JS_ReportError(cx,"malloc failed");
746: return(JS_FALSE);
747: }
748: memset(p,0,sizeof(private_t));
749:
750: p->dev=strdup(fname);
751: p->network_byte_order = TRUE;
752: p->baud_rate = 9600;
753: p->com = COM_HANDLE_INVALID;
754:
755: if(!JS_SetPrivate(cx, obj, p)) {
756: JS_ReportError(cx,"JS_SetPrivate failed");
757: return(JS_FALSE);
758: }
759:
760: #ifdef BUILD_JSDOCS
761: js_DescribeSyncObject(cx,obj,"Class used for serial port communications",31501);
762: js_DescribeSyncConstructor(cx,obj,"To create a new COM object: "
763: "var c = new COM('<i>device</i>')</tt><br>"
764: "where <i>device</i> = <tt>COMx</tt> (e.g. COM1) for Win32 or <tt>/dev/ttyXY</tt> for *nix (e.g. /dev/ttyu0)"
765: );
766: js_CreateArrayOfStrings(cx, obj, "_property_desc_list", com_prop_desc, JSPROP_READONLY);
767: #endif
768:
769: dbprintf(FALSE, p, "object constructed");
770: return(JS_TRUE);
771: }
772:
773: JSObject* DLLCALL js_CreateCOMClass(JSContext* cx, JSObject* parent)
774: {
775: JSObject* comobj;
776:
777: comobj = JS_InitClass(cx, parent, NULL
778: ,&js_com_class
779: ,js_com_constructor
780: ,0 /* number of constructor args */
781: ,NULL /* props, specified in constructor */
782: ,NULL /* funcs, specified in constructor */
783: ,NULL,NULL);
784:
785: return(comobj);
786: }
787:
788: JSObject* DLLCALL js_CreateCOMObject(JSContext* cx, JSObject* parent, const char *name, COM_HANDLE com)
789: {
790: JSObject* obj;
791: private_t* p;
792:
793: obj = JS_DefineObject(cx, parent, name, &js_com_class, NULL
794: ,JSPROP_ENUMERATE|JSPROP_READONLY);
795:
796: if(obj==NULL)
797: return(NULL);
798:
799: if((p=(private_t*)malloc(sizeof(private_t)))==NULL)
800: return(NULL);
801: memset(p,0,sizeof(private_t));
802:
803: p->com = com;
804: p->external = TRUE;
805: p->network_byte_order = TRUE;
806:
807: if(!JS_SetPrivate(cx, obj, p)) {
808: dbprintf(TRUE, p, "JS_SetPrivate failed");
809: return(NULL);
810: }
811:
812: dbprintf(FALSE, p, "object created");
813:
814: return(obj);
815: }
816:
817: #endif /* JAVSCRIPT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.