/* plSerial.c August, 1998 * Kevin Scott kcscott@cc.gatech.edu * FCE Lab, GaTEch * * Library functions for accessing Intellon powerline modem and * Rhino boards */ #include "plSerial.h" /************************************************************ * Open and configure the serial port * for Intellon PowerLine Modem - SGI O2 settings */ int plOpen(char *port) { char s[12]; char temp = 0x00; struct termios opts; plSetDefaults(); /* Attempt to open the serial port */ if ((plModem = open(port, O_RDWR | O_NOCTTY | O_NDELAY)) == -1) { printf("\nSerial port could not be opened. Exiting\n"); exit(0); } tcgetattr(plModem, &opts); opts.c_lflag &= ~(ICANON | ECHO | ISIG); opts.c_cflag |= (CLOCAL | CREAD); cfsetispeed(&opts,B9600); opts.c_cflag &= ~CNEW_RTSCTS; opts.c_iflag |= (INPCK | ISTRIP); opts.c_iflag |= (IXON | IXOFF | IXANY); opts.c_cflag &= ~CSIZE; opts.c_cflag |= CS8; opts.c_oflag &= ~OPOST; opts.c_cc[VMIN] = 1; opts.c_cc[VTIME] = 0; tcsetattr(plModem, TCSANOW, &opts); plClearSerialPort(); /* send control packet */ packet.type = 'C'; /* control packet follows */ packet.message[0] = 'C'; /* request standard device configuration */ packet.mLen = 1; plSend(); /* if the CEMonitor returns a status packet... */ if (plReceive(1)) { printf("\nCEMonitor ready\n"); } else { printf("\nCEMonitor not found.\n"); plClose(); exit(0); } return 1; } /* end plOpen */ /************************************************************ * Close the serial port */ void plClose() { close(plModem); } /************************************************************ * Gather packet from serial port buffer */ int plReceive(int dt) { int len, count, i; for (i = 0; i < 50; i++) { incoming.message[i] = '\0'; } if (waitForStart(dt) != 1) { printf("\n"); return 0; } recvBuf[1] = 0x00; while(recvBuf[1] == 0x00) /* read length byte */ { read(plModem, &recvBuf[1], 1); } len = recvBuf[1]; count = 0; i = 2; while (count < len) /* read type, message */ { if(read(plModem, &recvBuf[i], 1) == 1) { i++; count++; } } incoming.start = recvBuf[0]; incoming.length = recvBuf[1]; incoming.type = recvBuf[2]; incoming.mLen = len - 1; /* subtract one byte for TYPE */ memcpy(incoming.message, &recvBuf[3], incoming.mLen); incoming.chksum = 0x00; /* note: in my experience, the CEMonitor does not send a checksum, * but it does expect one... */ return 1; } /* end plReceive */ /*********************************************************** * Assemble packet to send */ int plSend() { int i, j; if (packet.mLen == 0) { printf("\nRemember to assemble your message first.\n"); return(FALSE); } packet.start = PL_START_BYTE; packet.length = 0x01 + packet.mLen; sendBuf[0] = packet.start; sendBuf[1] = packet.length; sendBuf[2] = packet.type; memcpy(&sendBuf[3], packet.message, packet.mLen); plPacketChecksum(); j = packet.mLen + 3; sendBuf[j] = packet.chksum; j++; if ((write(plModem, sendBuf, j)) != j) { return 0; } else { return 1; } } /* end plSend */ /*********************************************************** * Calculate the type + message checksum */ int plPacketChecksum() { char comp; int i; comp = 0x00; comp += packet.type; for(i = 0; i < packet.mLen; i++) { comp += packet.message[i]; } comp = ~comp; comp += 0x01; packet.chksum = comp; return 1; } /*********************************************************** * debug dump for send and receive buffers */ void plPacketDump(int which) { int i; if (which == IN) { printf("\nIncoming: %x %x %x ", incoming.start, incoming.length, incoming.type); for(i = 0; i < incoming.mLen; i++) { printf("%x ", incoming.message[i]); } /* printf("%x\n", incoming.chksum); */ printf("\n"); } else { printf("\nPacket: %x %x %x ", packet.start, packet.length, packet.type); for(i = 0; i < packet.mLen; i++) { printf("%x ", packet.message[i]); } /* printf("%x\n", packet.chksum); */ printf("\n"); } } /* end packetDump */ /*********************************************************** * Clear all the stuff in the serial input/output buffer */ void plClearSerialPort() { tcflush(plModem, TCIOFLUSH); } /*********************************************************** * configure default values */ void plSetDefaults() { DA[0] = 0x09; /* LSB */ DA[1] = 0x00; /* MSB */ DH[0] = 0x01; DH[1] = 0x00; SA[0] = 0x01; SA[1] = 0x00; SH[0] = 0x01; SH[1] = 0x00; LPDU = PL_LPDU_HEADER_BYTE; } /*********************************************************** * send configuration packet */ int plSendConfiguration() { printf("\nConfiguring CEMonitor\n"); packet.type = 'C'; packet.message[0] = 'U'; /* set source address */ packet.message[1] = SA[0]; packet.message[2] = SA[1]; packet.message[3] = 'H'; /* set source house code */ packet.message[4] = SH[0]; packet.message[5] = SH[1]; packet.mLen = 6; if (plSend() != 1) printf("\nConfig sending error.\n"); /* if status ok, return 1 */ return 1; } /*********************************************************** * send message to Rhino */ int plSendMessage(char info) { packet.type = 'T'; packet.message[0] = LPDU; packet.message[1] = DA[0]; packet.message[2] = DA[1]; packet.message[3] = DH[0]; packet.message[4] = DH[1]; packet.message[5] = SA[0]; packet.message[6] = SA[1]; packet.message[7] = SH[0]; packet.message[8] = SH[1]; packet.message[9] = NPDU; packet.message[10] = APDU_HEADER; packet.message[11] = info; packet.mLen = 12; plSend(); plReceive(1); return 1; } /*********************************************************** * send message to Rhino */ int waitForStart(dt) { time_t start, now; int FOUND = 0; recvBuf[0] = 0x00; start = time(NULL); now = start; while (now - start < dt) { now = time(NULL); if (read(plModem, recvBuf, 1) == 1) { if (recvBuf[0] == PL_START_BYTE) { FOUND = 1; break; } } } return (FOUND); } /* end waitForStart */ /*********************************************************** * print message as text */ int plPrintMessage(int which) { int i; if (which == IN) { printf("\n%s", &incoming.message[11]); } else { printf("\n%s", &packet.message[11]); } return 1; } /*********************************************************** * set Destination Address */ int plSetDestinationAddress(char *destAddress) { destAddress[1] -= 0x30; destAddress[0] -= 0x30; DA[0] = destAddress[1]; DA[1] = destAddress[0]; return 1; }