|
|
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.