RealtimeCompLab2
Dependencies: mbed
Fork of PPP-Blinky by
main.cpp
- Committer:
- nixnax
- Date:
- 2016-12-30
- Revision:
- 9:0992486d4a30
- Parent:
- 8:48e40f1ff316
- Child:
- 10:74f8233f72c0
File content as of revision 9:0992486d4a30:
#include "mbed.h" // Proof-of-concept for TCP/IP using Windows 7/8/10 Dial Up Networking over MBED USB Virtual COM Port // Toggles LED1 every time the PC sends an IP packet over the PPP link // Note - turn off all authentication, passwords, compression etc. Simplest link possible. // Handy links // http://atari.kensclassics.org/wcomlog.htm // https://technet.microsoft.com/en-us/library/cc957992.aspx // http://www.sunshine2k.de/coding/javascript/crc/crc_js.html // https://en.wikibooks.org/wiki/Serial_Programming/IP_Over_Serial_Connections Serial pc(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem on your pc Serial xx(PC_10, PC_11); // debug port - use a second USB serial port to monitor #define debug(x) xx.printf( x ) DigitalOut led1(LED1); #define FRAME_7E (0x7e) #define BUFLEN (1<<12) char rxbuf[BUFLEN]; char frbuf[3000]; // buffer for ppp frame struct { int online; struct { char * buf; int head; int tail; int total; } rx; // serial port buffer struct { int id; int len; int crc; char * buf; } pkt; // ppp buffer } ppp; void pppInitStruct(){ ppp.online=0; ppp.rx.buf=rxbuf; ppp.rx.tail=0; ppp.rx.head=0; ppp.rx.total=0; ppp.pkt.buf=frbuf; ppp.pkt.len=0;} int crcG; // frame check sequence (CRC) holder void crcDo(int x){for (int i=0;i<8;i++){crcG=((crcG&1)^(x&1))?(crcG>>1)^0x8408:crcG>>1;x>>=1;}} // crc calculator void crcReset(){crcG=0xffff;} // crc restart int crcBuf(char * buf, int size){crcReset();for(int i=0;i<size;i++)crcDo(*buf++);return crcG;} // crc on a block of memory void rxHandler() // serial port receive interrupt handler { ppp.rx.buf[ppp.rx.head]=pc.getc(); // insert in buffer __disable_irq(); ppp.rx.head=(ppp.rx.head+1)&(BUFLEN-1); ppp.rx.total++; __enable_irq(); } int pc_readable() // check if buffer has data { return (ppp.rx.head==ppp.rx.tail) ? 0 : 1 ; } int pc_getBuf() // get one character from the buffer { if (pc_readable()) { int x = ppp.rx.buf[ ppp.rx.tail ]; ppp.rx.tail=(ppp.rx.tail+1)&(BUFLEN-1); return x; } return -1; } void scanForConnectString(); // scan for connect attempts from pc void processFrame(int start, int end) { // process received frame if(start==end) { xx.printf("Null Frame c=%d\n",ppp.rx.total); pc.putc(0x7e); return; } crcReset(); char * dest = ppp.pkt.buf; ppp.pkt.len=0; int unstuff=0; for (int i=start; i<end; i++) { if (unstuff==0) { if (rxbuf[i]==0x7d) unstuff=1; else { *dest++ = rxbuf[i]; ppp.pkt.len++; crcDo(rxbuf[i]);} } else { *dest++ = rxbuf[i]^0x20; ppp.pkt.len++; crcDo((int)rxbuf[i]^0x20); unstuff=0; } } ppp.pkt.crc = crcG & 0xffff; if (ppp.pkt.crc == 0xf0b8) { // check for good CRC void determinePacketType(); // declare early determinePacketType(); } else { xx.printf("CRC was %x \n",ppp.pkt.crc); for(int i=0;i<ppp.pkt.len;i++)xx.printf("%02x ", ppp.pkt.buf[i]); xx.printf("\nLen = %d\n", ppp.pkt.len); } } void generalFrame() { debug("== General Frame ==\n"); for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]); xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len); } void sendFrame(){ int crc = crcBuf(ppp.pkt.buf, ppp.pkt.len-2); // get crc ppp.pkt.buf[ ppp.pkt.len-2 ] = (~crc>>0); // fcs lo ppp.pkt.buf[ ppp.pkt.len-1 ] = (~crc>>8); // fcs hi pc.putc(0x7e); // frame flag for(int i=0;i<ppp.pkt.len;i++) { unsigned int cc = (unsigned int)ppp.pkt.buf[i]; if (cc>32) pc.putc(cc); else {pc.putc(0x7d); pc.putc(cc+32);} } pc.putc(0x7e); // frame flag } void ipRequestHandler(){ debug("IPCP Conf "); if ( ppp.pkt.buf[7] != 4 ) { debug("Rej\n"); // reject if any options are requested ppp.pkt.buf[4]=4; sendFrame(); } else { debug("Ack\n"); ppp.pkt.buf[4]=2; // ack the minimum sendFrame(); // acknowledge // send our own request now debug("IPCP Ask\n"); ppp.pkt.buf[4]=1; // request the minimum ppp.pkt.buf[5]++; // next sequence sendFrame(); // this is our request } } void ipAckHandler(){ debug("IPCP Grant\n"); } void ipNackHandler(){ debug("IPCP Nack\n"); } void ipDefaultHandler(){ debug("IPCP Other\n"); } void IPCPframe() { led1 = ppp.pkt.buf[5] & 1; // This is the sequence number so the led blinks on packets //ppp.pkt.id = ppp.pkt.buf[5]; // remember the sequence number int code = ppp.pkt.buf[4]; // packet type is here switch (code) { case 1: ipRequestHandler(); break; case 2: ipAckHandler(); break; case 3: ipNackHandler(); break; default: ipDefaultHandler(); } } void IPframe() { xx.printf("IP frame proto %3d len %4d %d.%d.%d.%d %d.%d.%d.%d\n", ppp.pkt.buf[13],(ppp.pkt.buf[6]<<8)+ppp.pkt.buf[7],ppp.pkt.buf[16],ppp.pkt.buf[17],ppp.pkt.buf[18],ppp.pkt.buf[19],ppp.pkt.buf[20],ppp.pkt.buf[21],ppp.pkt.buf[22],ppp.pkt.buf[23] ); } void LCPconfReq() { debug("LCP Conf "); if (ppp.pkt.buf[7] != 4) { ppp.pkt.buf[4]=4; // allow only minimal requests debug("Rej\n"); sendFrame(); } else { ppp.pkt.buf[4]=2; // ack zero conf debug("Ack\n"); sendFrame(); debug("LCP ask\n"); ppp.pkt.buf[4]=1; // request zero conf sendFrame(); } } void LCPconfAck() { debug("LCP Ack\n"); } void LCPend(){ debug("LCP End\n"); ppp.online=0; ppp.pkt.buf[4]=6; sendFrame(); } void LCPother(){ debug("LCP Other\n"); generalFrame(); } void LCPframe(){ int code = ppp.pkt.buf[4]; switch (code) { case 1: LCPconfReq(); break; case 2: LCPconfAck(); break; case 5: LCPend(); break; default: LCPother(); } } void xx21frame() { debug("Unknown frame type ff 03 xx 21\n"); } void determinePacketType() { if ( ppp.pkt.buf[0] != 0xff ) {debug("byte0 != ff\n"); return;} if ( ppp.pkt.buf[1] != 3 ) {debug("byte1 != 3\n"); return;} if ( ppp.pkt.buf[3] != 0x21 ) {debug("byte2 != 21\n"); return;} int packetType = ppp.pkt.buf[2]; switch (packetType) { case 0xc0: LCPframe(); break; case 0x80: IPCPframe(); break; case 0x00: IPframe(); break; default: xx21frame(); break; } } void scanForConnectString() { if ( ppp.online==0 ) { char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string if( clientFound ) { strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated pc.printf("CLIENTSERVER"); // respond to PC ppp.online=1; // we can stop looking for the string debug("Connect string found\n"); } } } int main() { pc.baud(9600); xx.baud(115200); xx.puts("\x1b[2J\x1b[HReady\n"); // VT100 code for clear screen & home pppInitStruct(); // initialize all the PPP properties pc.attach(&rxHandler,Serial::RxIrq); // start the receive handler int frameStartIndex, frameEndIndex; int frameBusy=0; while(1) { if ( ppp.online==0 ) scanForConnectString(); // try to connect while ( pc_readable() ) { int rx = pc_getBuf(); wait(0.001); if (frameBusy) { if (rx==FRAME_7E) { frameBusy=0; // done gathering frame frameEndIndex=ppp.rx.tail-1; // remember where frame ends void processFrame(int start, int end); // process a received frame processFrame(frameStartIndex, frameEndIndex); } } else { if (rx==FRAME_7E) { frameBusy=1; // start gathering frame frameStartIndex=ppp.rx.tail; // remember where frame started } } } } }