RealtimeCompLab2
Dependencies: mbed
Fork of PPP-Blinky by
main.cpp
- Committer:
- nixnax
- Date:
- 2016-12-29
- Revision:
- 8:48e40f1ff316
- Parent:
- 7:ab147f5e97ac
- Child:
- 9:0992486d4a30
File content as of revision 8:48e40f1ff316:
#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. // Nice 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 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 DigitalOut led1(LED1); #define FRAME_7E (0x7e) #define BUFLEN (1<<14) char rxbuf[BUFLEN]; char frbuf[3000]; // buffer for ppp frame struct { int online; struct { char * buf; int head; int tail; } 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.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 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); __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 int main() { pc.baud(19200); xx.baud(115200); xx.puts("\x1b[2J\x1b[H"); // VT100 terminal control code for screen clear/home pppInitStruct(); // structure containing all the PPP stuff pc.attach(&rxHandler,Serial::RxIrq); // activate the receive interrupt handler int frameStartIndex, frameEndIndex; int frameBusy=0; while(1) { while ( pc_readable() ) { int rx = pc_getBuf(); 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 starts } } } if (ppp.online==0) scanForConnectString(); // try to connect } } void processFrame(int start, int end) { crcReset(); char * dest = ppp.pkt.buf; ppp.pkt.len=0; int special=0; for (int i=start; i<end; i++) { if (special==0) { if (rxbuf[i]==0x7d) special=1; else { *dest++ = rxbuf[i]; ppp.pkt.len++; crcDo(rxbuf[i]);} } else { *dest++ = rxbuf[i]-32; ppp.pkt.len++; crcDo(rxbuf[i]-32); special=0; } } ppp.rx.head=0; // reuse rxbuf ppp.rx.tail=0; // reuse rxbuf ppp.pkt.crc = crcG; if (crcG == 0xf0b8) { // check for good CRC void determinePacketType(); // declare early determinePacketType(); } } void generalFrame() { xx.printf("== 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(){ crcReset(); for(int i=0;i<ppp.pkt.len-2;i++) crcDo(ppp.pkt.buf[i]); ppp.pkt.buf[ ppp.pkt.len-2 ] = ((~crcG)>>0); // build crc lo ppp.pkt.buf[ ppp.pkt.len-1 ] = ((~crcG)>>8); // build crc hi pc.putc(0x7e); // start of frame 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); // end of frame } void LCPrequestFrame() { xx.printf("== LCP Request ==\n"); if (ppp.pkt.buf[7] != 4) { ppp.pkt.buf[4]=4; // nack everything until zero len sendFrame(); } else { ppp.pkt.buf[4]=2; // ack zero conf sendFrame(); // send our config request - also all zeros ppp.pkt.buf[4]=1; // request zero conf sendFrame(); } } void LCPackFrame() { xx.printf("== Saw Ack - PPP is up ==\n"); } void ipRequestHandler(){ xx.printf("== IP Request Frame ==\n"); generalFrame(); if ( ppp.pkt.buf[7] != 4 ) { ppp.pkt.buf[4]=4; // Nack sendFrame(); } else { ppp.pkt.buf[4]=2; // ack the minimum sendFrame(); // acknowledge xx.printf("zeroconf ack\n"); // send our own request now ppp.pkt.buf[4]=1; // request the minimum ppp.pkt.buf[5]++; // next sequence sendFrame(); // this is our request } } void ipAckHandler(){ xx.printf("== IP Ack Frame ==\n"); } void ipNackHandler(){ xx.printf("== IP Nack Frame ==\n"); } void ipDefaultHandler(){ xx.printf("== IP Unknown Frame ==\n"); } void LCPgeneralFrame(){ xx.printf("== LCP General Handler ==\n"); generalFrame(); } void LCPhandler(){ int action = ppp.pkt.buf[4]; if(0); else if ( action == 1 ) LCPrequestFrame(); else if ( action == 2 ) LCPackFrame(); else LCPgeneralFrame(); } void IPFrame() { 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 action = ppp.pkt.buf[4]; // packet type is here if(0); else if ( action == 1 ) ipRequestHandler(); else if ( action == 2 ) ipAckHandler(); else if ( action == 3 ) ipNackHandler(); else ipDefaultHandler(); } void determinePacketType() { static char pktLCPReqType [] = { 0xff, 3, 0xc0, 0x21 }; // LCP packet static char pktIPCPtype [] = { 0xff, 3, 0x80, 0x21, }; // IP packet if(0); else if (0==memcmp( ppp.pkt.buf,pktLCPReqType,4)) LCPhandler(); else if (0==memcmp( ppp.pkt.buf,pktIPCPtype, 4)) IPFrame(); else generalFrame(); // default handler } void scanForConnectString(){ 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 } }