RealtimeCompLab2
Dependencies: mbed
Fork of PPP-Blinky by
main.cpp@7:ab147f5e97ac, 2016-12-29 (annotated)
- Committer:
- nixnax
- Date:
- Thu Dec 29 16:31:48 2016 +0000
- Revision:
- 7:ab147f5e97ac
- Parent:
- 6:fba4c2e817b8
- Child:
- 8:48e40f1ff316
Fairly close on IP setup - one IPCP Conf Req is troublesome. PC won't Ack it.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
nixnax | 0:2cf4880c312a | 1 | #include "mbed.h" |
nixnax | 0:2cf4880c312a | 2 | |
nixnax | 0:2cf4880c312a | 3 | // Proof-of-concept for TCP/IP using Windows 7/8/10 Dial Up Networking over MBED USB Virtual COM Port |
nixnax | 0:2cf4880c312a | 4 | |
nixnax | 4:a469050d5b80 | 5 | // Toggles LED1 every time the PC sends an IP packet over the PPP link |
nixnax | 4:a469050d5b80 | 6 | |
nixnax | 4:a469050d5b80 | 7 | // Note - turn off all authentication, passwords, compression etc. Simplest link possible. |
nixnax | 0:2cf4880c312a | 8 | |
nixnax | 6:fba4c2e817b8 | 9 | // Nice links |
nixnax | 6:fba4c2e817b8 | 10 | // http://atari.kensclassics.org/wcomlog.htm |
nixnax | 6:fba4c2e817b8 | 11 | // https://technet.microsoft.com/en-us/library/cc957992.aspx |
nixnax | 6:fba4c2e817b8 | 12 | // http://www.sunshine2k.de/coding/javascript/crc/crc_js.html |
nixnax | 6:fba4c2e817b8 | 13 | |
nixnax | 6:fba4c2e817b8 | 14 | Serial pc(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem on your pc |
nixnax | 4:a469050d5b80 | 15 | Serial xx(PC_10, PC_11); // debug port - use a second USB serial port to monitor |
nixnax | 0:2cf4880c312a | 16 | |
nixnax | 4:a469050d5b80 | 17 | DigitalOut led1(LED1); |
nixnax | 4:a469050d5b80 | 18 | |
nixnax | 4:a469050d5b80 | 19 | #define FRAME_7E (0x7e) |
nixnax | 4:a469050d5b80 | 20 | #define BUFLEN (1<<14) |
nixnax | 4:a469050d5b80 | 21 | char rxbuf[BUFLEN]; |
nixnax | 4:a469050d5b80 | 22 | char frbuf[3000]; // buffer for ppp frame |
nixnax | 0:2cf4880c312a | 23 | |
nixnax | 4:a469050d5b80 | 24 | struct { |
nixnax | 4:a469050d5b80 | 25 | int online; |
nixnax | 4:a469050d5b80 | 26 | struct { |
nixnax | 4:a469050d5b80 | 27 | char * buf; |
nixnax | 4:a469050d5b80 | 28 | int head; |
nixnax | 4:a469050d5b80 | 29 | int tail; |
nixnax | 4:a469050d5b80 | 30 | } rx; // serial port buffer |
nixnax | 4:a469050d5b80 | 31 | struct { |
nixnax | 6:fba4c2e817b8 | 32 | int id; |
nixnax | 4:a469050d5b80 | 33 | int len; |
nixnax | 4:a469050d5b80 | 34 | int crc; |
nixnax | 4:a469050d5b80 | 35 | char * buf; |
nixnax | 4:a469050d5b80 | 36 | } pkt; // ppp buffer |
nixnax | 4:a469050d5b80 | 37 | } ppp; |
nixnax | 0:2cf4880c312a | 38 | |
nixnax | 4:a469050d5b80 | 39 | 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;} |
nixnax | 4:a469050d5b80 | 40 | |
nixnax | 4:a469050d5b80 | 41 | int crcG; // frame check sequence (CRC) holder |
nixnax | 4:a469050d5b80 | 42 | 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 |
nixnax | 4:a469050d5b80 | 43 | void crcReset(){crcG=0xffff;} // crc restart |
nixnax | 0:2cf4880c312a | 44 | |
nixnax | 0:2cf4880c312a | 45 | void rxHandler() // serial port receive interrupt handler |
nixnax | 0:2cf4880c312a | 46 | { |
nixnax | 4:a469050d5b80 | 47 | ppp.rx.buf[ppp.rx.head]=pc.getc(); // insert in buffer |
nixnax | 0:2cf4880c312a | 48 | __disable_irq(); |
nixnax | 4:a469050d5b80 | 49 | ppp.rx.head=(ppp.rx.head+1)&(BUFLEN-1); |
nixnax | 0:2cf4880c312a | 50 | __enable_irq(); |
nixnax | 0:2cf4880c312a | 51 | } |
nixnax | 0:2cf4880c312a | 52 | |
nixnax | 0:2cf4880c312a | 53 | int pc_readable() // check if buffer has data |
nixnax | 0:2cf4880c312a | 54 | { |
nixnax | 4:a469050d5b80 | 55 | return (ppp.rx.head==ppp.rx.tail) ? 0 : 1 ; |
nixnax | 0:2cf4880c312a | 56 | } |
nixnax | 0:2cf4880c312a | 57 | |
nixnax | 0:2cf4880c312a | 58 | int pc_getBuf() // get one character from the buffer |
nixnax | 0:2cf4880c312a | 59 | { |
nixnax | 0:2cf4880c312a | 60 | if (pc_readable()) { |
nixnax | 4:a469050d5b80 | 61 | int x = ppp.rx.buf[ ppp.rx.tail ]; |
nixnax | 4:a469050d5b80 | 62 | ppp.rx.tail=(ppp.rx.tail+1)&(BUFLEN-1); |
nixnax | 0:2cf4880c312a | 63 | return x; |
nixnax | 0:2cf4880c312a | 64 | } |
nixnax | 0:2cf4880c312a | 65 | return -1; |
nixnax | 0:2cf4880c312a | 66 | } |
nixnax | 0:2cf4880c312a | 67 | |
nixnax | 4:a469050d5b80 | 68 | void scanForConnectString(); // scan for connect attempts from pc |
nixnax | 1:9e03798d4367 | 69 | |
nixnax | 0:2cf4880c312a | 70 | int main() |
nixnax | 0:2cf4880c312a | 71 | { |
nixnax | 6:fba4c2e817b8 | 72 | pc.baud(19200); |
nixnax | 4:a469050d5b80 | 73 | xx.baud(115200); |
nixnax | 4:a469050d5b80 | 74 | xx.puts("\x1b[2J\x1b[H"); // VT100 terminal control code for screen clear/home |
nixnax | 4:a469050d5b80 | 75 | |
nixnax | 4:a469050d5b80 | 76 | pppInitStruct(); // structure containing all the PPP stuff |
nixnax | 4:a469050d5b80 | 77 | |
nixnax | 0:2cf4880c312a | 78 | pc.attach(&rxHandler,Serial::RxIrq); // activate the receive interrupt handler |
nixnax | 4:a469050d5b80 | 79 | |
nixnax | 4:a469050d5b80 | 80 | int frameStartIndex, frameEndIndex; |
nixnax | 4:a469050d5b80 | 81 | int frameBusy=0; |
nixnax | 4:a469050d5b80 | 82 | |
nixnax | 0:2cf4880c312a | 83 | while(1) { |
nixnax | 0:2cf4880c312a | 84 | while ( pc_readable() ) { |
nixnax | 1:9e03798d4367 | 85 | int rx = pc_getBuf(); |
nixnax | 4:a469050d5b80 | 86 | if (frameBusy) { |
nixnax | 4:a469050d5b80 | 87 | if (rx==FRAME_7E) { |
nixnax | 4:a469050d5b80 | 88 | frameBusy=0; // done gathering frame |
nixnax | 4:a469050d5b80 | 89 | frameEndIndex=ppp.rx.tail-1; // remember where frame ends |
nixnax | 4:a469050d5b80 | 90 | void processFrame(int start, int end); // process a received frame |
nixnax | 4:a469050d5b80 | 91 | processFrame(frameStartIndex, frameEndIndex); |
nixnax | 4:a469050d5b80 | 92 | } |
nixnax | 4:a469050d5b80 | 93 | } |
nixnax | 4:a469050d5b80 | 94 | else { |
nixnax | 4:a469050d5b80 | 95 | if (rx==FRAME_7E) { |
nixnax | 4:a469050d5b80 | 96 | frameBusy=1; // start gathering frame |
nixnax | 4:a469050d5b80 | 97 | frameStartIndex=ppp.rx.tail; // remember where frame starts |
nixnax | 4:a469050d5b80 | 98 | } |
nixnax | 0:2cf4880c312a | 99 | } |
nixnax | 4:a469050d5b80 | 100 | } |
nixnax | 4:a469050d5b80 | 101 | if (ppp.online==0) scanForConnectString(); // try to connect |
nixnax | 4:a469050d5b80 | 102 | } |
nixnax | 4:a469050d5b80 | 103 | } |
nixnax | 4:a469050d5b80 | 104 | |
nixnax | 4:a469050d5b80 | 105 | void processFrame(int start, int end) { |
nixnax | 4:a469050d5b80 | 106 | crcReset(); |
nixnax | 4:a469050d5b80 | 107 | char * dest = ppp.pkt.buf; |
nixnax | 4:a469050d5b80 | 108 | ppp.pkt.len=0; |
nixnax | 4:a469050d5b80 | 109 | int special=0; |
nixnax | 4:a469050d5b80 | 110 | for (int i=start; i<end; i++) { |
nixnax | 4:a469050d5b80 | 111 | if (special==0) { |
nixnax | 4:a469050d5b80 | 112 | if (rxbuf[i]==0x7d) special=1; |
nixnax | 4:a469050d5b80 | 113 | else { *dest++ = rxbuf[i]; ppp.pkt.len++; crcDo(rxbuf[i]);} |
nixnax | 4:a469050d5b80 | 114 | } else { |
nixnax | 4:a469050d5b80 | 115 | *dest++ = rxbuf[i]-32; ppp.pkt.len++; crcDo(rxbuf[i]-32); |
nixnax | 4:a469050d5b80 | 116 | special=0; |
nixnax | 0:2cf4880c312a | 117 | } |
nixnax | 0:2cf4880c312a | 118 | } |
nixnax | 4:a469050d5b80 | 119 | ppp.rx.head=0; // reuse rxbuf |
nixnax | 4:a469050d5b80 | 120 | ppp.rx.tail=0; // reuse rxbuf |
nixnax | 6:fba4c2e817b8 | 121 | ppp.pkt.crc = crcG; |
nixnax | 6:fba4c2e817b8 | 122 | if (crcG == 0xf0b8) { // check for good CRC |
nixnax | 6:fba4c2e817b8 | 123 | void determinePacketType(); // declare early |
nixnax | 6:fba4c2e817b8 | 124 | determinePacketType(); |
nixnax | 6:fba4c2e817b8 | 125 | } |
nixnax | 0:2cf4880c312a | 126 | } |
nixnax | 4:a469050d5b80 | 127 | |
nixnax | 6:fba4c2e817b8 | 128 | |
nixnax | 7:ab147f5e97ac | 129 | void generalFrame() { |
nixnax | 7:ab147f5e97ac | 130 | xx.printf("== General Frame ==\n"); |
nixnax | 7:ab147f5e97ac | 131 | for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]); |
nixnax | 7:ab147f5e97ac | 132 | xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len); |
nixnax | 7:ab147f5e97ac | 133 | } |
nixnax | 7:ab147f5e97ac | 134 | |
nixnax | 7:ab147f5e97ac | 135 | |
nixnax | 4:a469050d5b80 | 136 | void sendFrame(){ |
nixnax | 4:a469050d5b80 | 137 | crcReset(); for(int i=0;i<ppp.pkt.len-2;i++) crcDo(ppp.pkt.buf[i]); |
nixnax | 6:fba4c2e817b8 | 138 | ppp.pkt.buf[ ppp.pkt.len-2 ] = ((~crcG)>>0); // build crc lo |
nixnax | 6:fba4c2e817b8 | 139 | ppp.pkt.buf[ ppp.pkt.len-1 ] = ((~crcG)>>8); // build crc hi |
nixnax | 6:fba4c2e817b8 | 140 | pc.putc(0x7e); // start of frame |
nixnax | 4:a469050d5b80 | 141 | for(int i=0;i<ppp.pkt.len;i++) { |
nixnax | 4:a469050d5b80 | 142 | unsigned int cc = (unsigned int)ppp.pkt.buf[i]; |
nixnax | 6:fba4c2e817b8 | 143 | if (cc>32) pc.putc(cc); else {pc.putc(0x7d);pc.putc(cc+32);} |
nixnax | 4:a469050d5b80 | 144 | } |
nixnax | 6:fba4c2e817b8 | 145 | pc.putc(0x7e); // end of frame |
nixnax | 4:a469050d5b80 | 146 | } |
nixnax | 4:a469050d5b80 | 147 | |
nixnax | 6:fba4c2e817b8 | 148 | |
nixnax | 6:fba4c2e817b8 | 149 | |
nixnax | 4:a469050d5b80 | 150 | void LCPrequestFrame() { |
nixnax | 7:ab147f5e97ac | 151 | xx.printf("== LCP Request ==\n"); |
nixnax | 7:ab147f5e97ac | 152 | if (ppp.pkt.buf[7] != 4) { |
nixnax | 7:ab147f5e97ac | 153 | ppp.pkt.buf[4]=4; // nack everything until zero len |
nixnax | 7:ab147f5e97ac | 154 | sendFrame(); |
nixnax | 7:ab147f5e97ac | 155 | } else { |
nixnax | 7:ab147f5e97ac | 156 | ppp.pkt.buf[4]=2; // ack zero conf |
nixnax | 7:ab147f5e97ac | 157 | sendFrame(); |
nixnax | 7:ab147f5e97ac | 158 | // send our config request - also all zeros |
nixnax | 7:ab147f5e97ac | 159 | ppp.pkt.buf[4]=1; // request zero conf |
nixnax | 7:ab147f5e97ac | 160 | sendFrame(); |
nixnax | 7:ab147f5e97ac | 161 | } |
nixnax | 7:ab147f5e97ac | 162 | } |
nixnax | 5:27624c02189f | 163 | |
nixnax | 7:ab147f5e97ac | 164 | |
nixnax | 7:ab147f5e97ac | 165 | |
nixnax | 4:a469050d5b80 | 166 | |
nixnax | 4:a469050d5b80 | 167 | void LCPackFrame() { |
nixnax | 7:ab147f5e97ac | 168 | xx.printf("== Saw Ack - PPP is up ==\n"); |
nixnax | 5:27624c02189f | 169 | } |
nixnax | 4:a469050d5b80 | 170 | |
nixnax | 4:a469050d5b80 | 171 | |
nixnax | 6:fba4c2e817b8 | 172 | void rejectIPcompression() { |
nixnax | 6:fba4c2e817b8 | 173 | xx.printf("== IP Compression Reject Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 174 | generalFrame(); |
nixnax | 6:fba4c2e817b8 | 175 | static char rejectCompression [] = {0x80,0x21,4,0,0,10,2,6,0,45,15,1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
nixnax | 6:fba4c2e817b8 | 176 | // 128/33=IPCP 4=Rej 0=id 0=sizeHigh 10=sizeLow 2,6,0,45,1=RejectCcompression |
nixnax | 6:fba4c2e817b8 | 177 | ppp.pkt.len=sizeof( rejectCompression ); |
nixnax | 6:fba4c2e817b8 | 178 | memcpy( rejectCompression, ppp.pkt.buf, ppp.pkt.len); |
nixnax | 6:fba4c2e817b8 | 179 | ppp.pkt.buf[3]=ppp.pkt.id; |
nixnax | 6:fba4c2e817b8 | 180 | sendFrame(); |
nixnax | 6:fba4c2e817b8 | 181 | } |
nixnax | 6:fba4c2e817b8 | 182 | |
nixnax | 6:fba4c2e817b8 | 183 | void ipRequestHandler(){ |
nixnax | 6:fba4c2e817b8 | 184 | xx.printf("== IP Request Frame ==\n"); |
nixnax | 7:ab147f5e97ac | 185 | if( ppp.pkt.buf[7] != 10 ) { |
nixnax | 7:ab147f5e97ac | 186 | ppp.pkt.buf[4]=4; // Nack |
nixnax | 7:ab147f5e97ac | 187 | sendFrame(); // we want minimum config |
nixnax | 7:ab147f5e97ac | 188 | } else { |
nixnax | 7:ab147f5e97ac | 189 | ppp.pkt.buf[4]=2; // ack the minimum |
nixnax | 7:ab147f5e97ac | 190 | ppp.pkt.buf[10]=10; // ip addr 1 |
nixnax | 7:ab147f5e97ac | 191 | ppp.pkt.buf[11]=10; // ip addr 2 |
nixnax | 7:ab147f5e97ac | 192 | ppp.pkt.buf[12]=10; // ip addr 3 |
nixnax | 7:ab147f5e97ac | 193 | ppp.pkt.buf[13]=10; // ip addr 4 |
nixnax | 7:ab147f5e97ac | 194 | sendFrame(); // acknowledge |
nixnax | 7:ab147f5e97ac | 195 | xx.printf("zeroconf ack\n"); |
nixnax | 7:ab147f5e97ac | 196 | // send our own request now |
nixnax | 7:ab147f5e97ac | 197 | ppp.pkt.buf[4]=1; // request the minimum |
nixnax | 7:ab147f5e97ac | 198 | ppp.pkt.buf[5]++; // next sequence |
nixnax | 7:ab147f5e97ac | 199 | sendFrame(); // this is our request |
nixnax | 7:ab147f5e97ac | 200 | } |
nixnax | 6:fba4c2e817b8 | 201 | } |
nixnax | 6:fba4c2e817b8 | 202 | |
nixnax | 6:fba4c2e817b8 | 203 | void ipAckHandler(){ |
nixnax | 6:fba4c2e817b8 | 204 | xx.printf("== IP Ack Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 205 | } |
nixnax | 6:fba4c2e817b8 | 206 | |
nixnax | 6:fba4c2e817b8 | 207 | void ipNackHandler(){ |
nixnax | 6:fba4c2e817b8 | 208 | xx.printf("== IP Nack Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 209 | } |
nixnax | 6:fba4c2e817b8 | 210 | |
nixnax | 6:fba4c2e817b8 | 211 | void ipDefaultHandler(){ |
nixnax | 6:fba4c2e817b8 | 212 | xx.printf("== IP Unknown Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 213 | } |
nixnax | 6:fba4c2e817b8 | 214 | |
nixnax | 6:fba4c2e817b8 | 215 | void LCPgeneralFrame(){ |
nixnax | 6:fba4c2e817b8 | 216 | xx.printf("== LCP General Handler ==\n"); |
nixnax | 6:fba4c2e817b8 | 217 | generalFrame(); |
nixnax | 6:fba4c2e817b8 | 218 | } |
nixnax | 6:fba4c2e817b8 | 219 | |
nixnax | 6:fba4c2e817b8 | 220 | |
nixnax | 6:fba4c2e817b8 | 221 | void LCPhandler(){ |
nixnax | 6:fba4c2e817b8 | 222 | int action = ppp.pkt.buf[4]; |
nixnax | 6:fba4c2e817b8 | 223 | if(0); |
nixnax | 6:fba4c2e817b8 | 224 | else if ( action == 1 ) LCPrequestFrame(); |
nixnax | 6:fba4c2e817b8 | 225 | else if ( action == 2 ) LCPackFrame(); |
nixnax | 6:fba4c2e817b8 | 226 | else LCPgeneralFrame(); |
nixnax | 6:fba4c2e817b8 | 227 | } |
nixnax | 6:fba4c2e817b8 | 228 | |
nixnax | 6:fba4c2e817b8 | 229 | void IPFrame() { |
nixnax | 7:ab147f5e97ac | 230 | led1 = ppp.pkt.buf[5] & 1; // This is the sequence number so the led blinks on packets |
nixnax | 7:ab147f5e97ac | 231 | //ppp.pkt.len = (((unsigned int)ppp.pkt.buf[4])<<8) + (((unsigned int)ppp.pkt.buf[5])<<0); |
nixnax | 7:ab147f5e97ac | 232 | ppp.pkt.id = ppp.pkt.buf[5]; // remember the sequence number |
nixnax | 7:ab147f5e97ac | 233 | int action = ppp.pkt.buf[4]; // packet type is here |
nixnax | 6:fba4c2e817b8 | 234 | if(0); |
nixnax | 6:fba4c2e817b8 | 235 | else if ( action == 1 ) ipRequestHandler(); |
nixnax | 6:fba4c2e817b8 | 236 | else if ( action == 2 ) ipAckHandler(); |
nixnax | 6:fba4c2e817b8 | 237 | else if ( action == 3 ) ipNackHandler(); |
nixnax | 6:fba4c2e817b8 | 238 | else ipDefaultHandler(); |
nixnax | 4:a469050d5b80 | 239 | } |
nixnax | 4:a469050d5b80 | 240 | |
nixnax | 4:a469050d5b80 | 241 | void determinePacketType() { |
nixnax | 7:ab147f5e97ac | 242 | static char pktLCPReqType [] = { 0xff, 3, 0xc0, 0x21 }; // LCP packet |
nixnax | 7:ab147f5e97ac | 243 | static char pktIPCPtype [] = { 0xff, 3, 0x80, 0x21, }; // IP packet |
nixnax | 6:fba4c2e817b8 | 244 | |
nixnax | 4:a469050d5b80 | 245 | if(0); |
nixnax | 6:fba4c2e817b8 | 246 | else if (0==memcmp( ppp.pkt.buf,pktLCPReqType,4)) LCPhandler(); |
nixnax | 7:ab147f5e97ac | 247 | else if (0==memcmp( ppp.pkt.buf,pktIPCPtype, 4)) IPFrame(); |
nixnax | 4:a469050d5b80 | 248 | else generalFrame(); // default handler |
nixnax | 4:a469050d5b80 | 249 | } |
nixnax | 4:a469050d5b80 | 250 | |
nixnax | 4:a469050d5b80 | 251 | void scanForConnectString(){ |
nixnax | 4:a469050d5b80 | 252 | char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string |
nixnax | 4:a469050d5b80 | 253 | if( clientFound ) { |
nixnax | 4:a469050d5b80 | 254 | strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated |
nixnax | 4:a469050d5b80 | 255 | pc.printf("CLIENTSERVER"); // respond to PC |
nixnax | 4:a469050d5b80 | 256 | } |
nixnax | 4:a469050d5b80 | 257 | } |