#include #include #include #include SRCFILE(__FILE__) long BytesToTerm; long BytesFromTerm; #undef PROTODEBUG # ifdef PROTODEBUG char *ProtoName(int p){ char *s = 0; char buf[32]; switch( p&0xFF ){ case P_UCHAR : s = "P_UCHAR"; break; case P_SHORT : s = "P_SHORT"; break; case P_LONG : s = "P_LONG"; break; case P_CACHEOP : s = "P_CACHEOP"; break; case P_I_DEFINE : s = "P_I_DEFINE"; break; case P_I_CACHE : s = "P_I_CACHE"; break; case P_C_DEFINE : s = "P_C_DEFINE"; break; case P_C_CACHE : s = "P_C_CACHE"; break; case P_STRING : s = "P_STRING"; break; case P_INDEX : s = "P_INDEX"; break; case P_PADDEF : s = "P_PADDEF"; break; case P_ATTRIBUTE : s = "P_ATTRIBUTE"; break; case P_BANNER : s = "P_BANNER"; break; case P_CARTE : s = "P_CARTE"; break; case P_LINES : s = "P_LINES"; break; case P_NAME : s = "P_NAME"; break; case P_TABS : s = "P_TABS"; break; case P_HELPCARTE : s = "P_HELPCARTE"; break; case P_PADOP : s = "P_PADOP"; break; case P_ACTION : s = "P_ACTION"; break; case P_ALARM : s = "P_ALARM"; break; case P_CLEAR : s = "P_CLEAR"; break; case P_CYCLE : s = "P_CYCLE"; break; case P_DELETE : s = "P_DELETE"; break; case P_KBDSTR : s = "P_KBDSTR"; break; case P_LINE : s = "P_LINE"; break; case P_LINEREQ : s = "P_LINEREQ"; break; case P_MAKECURRENT : s = "P_MAKECURRENT"; break; case P_MAKEGAP : s = "P_MAKEGAP"; break; case P_NEXTLINE : s = "P_NEXTLINE"; break; case P_NUMERIC : s = "P_NUMERIC"; break; case P_USERCLOSE : s = "P_USERCLOSE"; break; case P_CREATELINE : s = "P_CREATELINE"; break; case P_REMOVELINE : s = "P_REMOVELINE"; break; case P_HOSTSTATE : s = "P_HOSTSTATE"; break; case P_BUSY : s = "P_BUSY"; break; case P_IDLE : s = "P_IDLE"; break; case P_USERCUT : s = "P_USERCUT"; break; case P_PICK : s = "P_PICK"; break; case P_HELPSTR : s = "P_HELPSTR"; break; case P_SHELL : s = "P_SHELL"; break; case P_VERSION : s = "P_VERSION"; break; case P_QUIT : s = "P_QUIT"; break; case P_ERROR : s = "P_ERROR"; break; default: sprintf(buf, "%X", p); s = buf; } return s; } # endif void Remote::checkproto(int p){ if( get()!=p ) err("Pads library: protocol error: checkproto"); } void Remote::proto(int p) { put( p ); } long Remote::rcvlong() { return (long) shiftin( P_LONG ); } short Remote::rcvshort() { return (short) shiftin( P_SHORT ); } uchar Remote::rcvuchar() { return (uchar) shiftin(P_UCHAR); } void Remote::sendlong(long x) { shiftout( P_LONG, x ); } void Remote::sendshort(short x) { shiftout( P_SHORT, (long) x ); } void Remote::senduchar(unsigned char x) { shiftout( P_UCHAR, (long) x ); } void Remote::pktstart(char c) { put(c); } void Remote::pktflush() { writesize = 0; pktend(); } void Remote::put(char c){ writebuffer[pktsize++] = c; if (pktsize == sizeof(writebuffer)) pktflush(); } void Remote::sendobj(PadRcv *o){ sendlong((long)o); } PadRcv *Remote::rcvobj(){ PadRcv *obj = (PadRcv*)rcvlong(); short oid = rcvshort(); if (obj && obj->oid != oid) obj = 0; trace("rcvobj(0x%08x)",obj); return obj; } void Remote::err(const char *e){ if( !e ) e = StrDup("Pads library: protocol error"); PadsError(e); } Remote::Remote(int opened){ if(opened){ ifd = 0; ofd = 1; pktsize = writesize = 0; } } Remote::Remote(const char *dev){ ifd = ofd = open(dev, 2); pktsize = writesize = 0; } void Remote::share(){ trace( "%d.share()", this ); } long Remote::shiftin( int bytes ){ long shifter = 0; checkproto( bytes ); while( bytes-- ) shifter = (shifter<<8) + (get()&0xFF); return shifter; } void Remote::shiftout( int bytes, long shifter ){ proto( bytes ); do { put( (char)(shifter>>( (--bytes)*8 )) ); } while( bytes ); } void Remote::pktend(){ if (pktsize > writesize) { if (write(ofd, (char*)writebuffer, pktsize) != pktsize) abort(); BytesToTerm += pktsize; pktsize = 0; writesize = sizeof(writebuffer); } } char *Remote::rcvstring( char *s0 ){ char *s = s0; unsigned char len; checkproto( P_STRING ); len = rcvuchar(); if( !s0 ) s = s0 = new char [len+1]; while( len-->0 ) *s++ = get(); *s = '\0'; return s0; } void Remote::sendstring(const char *s){ int len; proto( P_STRING ); len = strlen(s); if( len > 255 ) len = 255; senduchar( len ); while( len-- ) put(*s++); } int Remote::get(){ static uchar buf[64]; static int i, nleft = 0; if (pktsize) { err("Remote::get: pktsize"); return 0; } if( nleft <= 0 ){ again: if( (nleft = read(ifd, (char *)buf, sizeof buf)) < 0 ){ if(errno == EINTR) /* why are we getting EINTR? */ goto again; err(strerror(errno)); return 0; } i = 0; } --nleft; ++BytesFromTerm; return (int)buf[i++]; }