Annotation of sbbs/src/sbbs3/js_com.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.