Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of webserverBlinky by
main.cpp@6:fba4c2e817b8, 2016-12-29 (annotated)
- Committer:
- nixnax
- Date:
- Thu Dec 29 10:48:57 2016 +0000
- Revision:
- 6:fba4c2e817b8
- Parent:
- 5:27624c02189f
- Child:
- 7:ab147f5e97ac
More IP progress
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 | 4:a469050d5b80 | 129 | void sendFrame(){ |
nixnax | 4:a469050d5b80 | 130 | crcReset(); for(int i=0;i<ppp.pkt.len-2;i++) crcDo(ppp.pkt.buf[i]); |
nixnax | 6:fba4c2e817b8 | 131 | ppp.pkt.buf[ ppp.pkt.len-2 ] = ((~crcG)>>0); // build crc lo |
nixnax | 6:fba4c2e817b8 | 132 | ppp.pkt.buf[ ppp.pkt.len-1 ] = ((~crcG)>>8); // build crc hi |
nixnax | 6:fba4c2e817b8 | 133 | pc.putc(0x7e); // start of frame |
nixnax | 4:a469050d5b80 | 134 | for(int i=0;i<ppp.pkt.len;i++) { |
nixnax | 4:a469050d5b80 | 135 | unsigned int cc = (unsigned int)ppp.pkt.buf[i]; |
nixnax | 6:fba4c2e817b8 | 136 | if (cc>32) pc.putc(cc); else {pc.putc(0x7d);pc.putc(cc+32);} |
nixnax | 4:a469050d5b80 | 137 | } |
nixnax | 6:fba4c2e817b8 | 138 | pc.putc(0x7e); // end of frame |
nixnax | 4:a469050d5b80 | 139 | } |
nixnax | 4:a469050d5b80 | 140 | |
nixnax | 6:fba4c2e817b8 | 141 | |
nixnax | 6:fba4c2e817b8 | 142 | |
nixnax | 4:a469050d5b80 | 143 | void LCPrequestFrame() { |
nixnax | 5:27624c02189f | 144 | ppp.pkt.buf[4]=2; // change to an ACK packet |
nixnax | 5:27624c02189f | 145 | sendFrame(); // acknowledge their request |
nixnax | 5:27624c02189f | 146 | // this is the right time to send our LCP setup request to them |
nixnax | 5:27624c02189f | 147 | ppp.pkt.buf[4]=1; // change back to a request |
nixnax | 5:27624c02189f | 148 | ppp.pkt.buf[5] = ppp.pkt.buf[5]+1; // take the next id |
nixnax | 5:27624c02189f | 149 | ppp.pkt.buf[16] = ppp.pkt.buf[16] ^ 0x33; // modify magic number |
nixnax | 5:27624c02189f | 150 | ppp.pkt.buf[17] = ppp.pkt.buf[16] ^ 0x33; // modify magic number |
nixnax | 5:27624c02189f | 151 | sendFrame(); // send our request |
nixnax | 5:27624c02189f | 152 | |
nixnax | 4:a469050d5b80 | 153 | } |
nixnax | 4:a469050d5b80 | 154 | |
nixnax | 4:a469050d5b80 | 155 | void LCPackFrame() { |
nixnax | 4:a469050d5b80 | 156 | xx.printf("== PPP is up ==\n"); |
nixnax | 5:27624c02189f | 157 | } |
nixnax | 4:a469050d5b80 | 158 | |
nixnax | 4:a469050d5b80 | 159 | void generalFrame() { |
nixnax | 4:a469050d5b80 | 160 | xx.printf("== General Frame ==\n"); |
nixnax | 4:a469050d5b80 | 161 | for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]); |
nixnax | 4:a469050d5b80 | 162 | xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len); |
nixnax | 4:a469050d5b80 | 163 | } |
nixnax | 4:a469050d5b80 | 164 | |
nixnax | 6:fba4c2e817b8 | 165 | void rejectIPcompression() { |
nixnax | 6:fba4c2e817b8 | 166 | xx.printf("== IP Compression Reject Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 167 | generalFrame(); |
nixnax | 6:fba4c2e817b8 | 168 | 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 | 169 | // 128/33=IPCP 4=Rej 0=id 0=sizeHigh 10=sizeLow 2,6,0,45,1=RejectCcompression |
nixnax | 6:fba4c2e817b8 | 170 | ppp.pkt.len=sizeof( rejectCompression ); |
nixnax | 6:fba4c2e817b8 | 171 | memcpy( rejectCompression, ppp.pkt.buf, ppp.pkt.len); |
nixnax | 6:fba4c2e817b8 | 172 | ppp.pkt.buf[3]=ppp.pkt.id; |
nixnax | 6:fba4c2e817b8 | 173 | sendFrame(); |
nixnax | 6:fba4c2e817b8 | 174 | } |
nixnax | 6:fba4c2e817b8 | 175 | |
nixnax | 6:fba4c2e817b8 | 176 | void ipRequestHandler(){ |
nixnax | 6:fba4c2e817b8 | 177 | xx.printf("== IP Request Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 178 | //static char compressRequest[] = {2,6,0,45,15,1}; |
nixnax | 6:fba4c2e817b8 | 179 | //if(0==memcmp(ppp.pkt.buf+6, compressRequest, 6)) rejectIPcompression(); |
nixnax | 6:fba4c2e817b8 | 180 | generalFrame(); |
nixnax | 6:fba4c2e817b8 | 181 | ppp.pkt.buf[2]=2; // ACK |
nixnax | 6:fba4c2e817b8 | 182 | sendFrame(); // acknowledge |
nixnax | 6:fba4c2e817b8 | 183 | |
nixnax | 6:fba4c2e817b8 | 184 | ppp.pkt.buf[2]=1; // request |
nixnax | 6:fba4c2e817b8 | 185 | ppp.pkt.buf[3]++; // next sequence |
nixnax | 6:fba4c2e817b8 | 186 | sendFrame(); // now WE do a request |
nixnax | 6:fba4c2e817b8 | 187 | |
nixnax | 6:fba4c2e817b8 | 188 | } |
nixnax | 6:fba4c2e817b8 | 189 | |
nixnax | 6:fba4c2e817b8 | 190 | void ipAckHandler(){ |
nixnax | 6:fba4c2e817b8 | 191 | xx.printf("== IP Ack Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 192 | } |
nixnax | 6:fba4c2e817b8 | 193 | |
nixnax | 6:fba4c2e817b8 | 194 | void ipNackHandler(){ |
nixnax | 6:fba4c2e817b8 | 195 | xx.printf("== IP Nack Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 196 | } |
nixnax | 6:fba4c2e817b8 | 197 | |
nixnax | 6:fba4c2e817b8 | 198 | void ipDefaultHandler(){ |
nixnax | 6:fba4c2e817b8 | 199 | xx.printf("== IP Unknown Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 200 | } |
nixnax | 6:fba4c2e817b8 | 201 | |
nixnax | 6:fba4c2e817b8 | 202 | void LCPgeneralFrame(){ |
nixnax | 6:fba4c2e817b8 | 203 | xx.printf("== LCP General Handler ==\n"); |
nixnax | 6:fba4c2e817b8 | 204 | generalFrame(); |
nixnax | 6:fba4c2e817b8 | 205 | } |
nixnax | 6:fba4c2e817b8 | 206 | |
nixnax | 6:fba4c2e817b8 | 207 | |
nixnax | 6:fba4c2e817b8 | 208 | void LCPhandler(){ |
nixnax | 6:fba4c2e817b8 | 209 | xx.printf("== LCP Handler ==\n"); |
nixnax | 6:fba4c2e817b8 | 210 | int action = ppp.pkt.buf[4]; |
nixnax | 6:fba4c2e817b8 | 211 | if(0); |
nixnax | 6:fba4c2e817b8 | 212 | else if ( action == 1 ) LCPrequestFrame(); |
nixnax | 6:fba4c2e817b8 | 213 | else if ( action == 2 ) LCPackFrame(); |
nixnax | 6:fba4c2e817b8 | 214 | else LCPgeneralFrame(); |
nixnax | 6:fba4c2e817b8 | 215 | } |
nixnax | 6:fba4c2e817b8 | 216 | |
nixnax | 6:fba4c2e817b8 | 217 | void IPFrame() { |
nixnax | 4:a469050d5b80 | 218 | led1 = ppp.pkt.buf[3] & 1; // This is the sequence number so the led blinks on packets |
nixnax | 6:fba4c2e817b8 | 219 | ppp.pkt.len = (((unsigned int)ppp.pkt.buf[4])<<8) + (((unsigned int)ppp.pkt.buf[5])<<0); |
nixnax | 6:fba4c2e817b8 | 220 | ppp.pkt.id = ppp.pkt.buf[3]; // remember the sequence number |
nixnax | 6:fba4c2e817b8 | 221 | int action = ppp.pkt.buf[2]; // packet type is here |
nixnax | 6:fba4c2e817b8 | 222 | if(0); |
nixnax | 6:fba4c2e817b8 | 223 | else if ( action == 1 ) ipRequestHandler(); |
nixnax | 6:fba4c2e817b8 | 224 | else if ( action == 2 ) ipAckHandler(); |
nixnax | 6:fba4c2e817b8 | 225 | else if ( action == 3 ) ipNackHandler(); |
nixnax | 6:fba4c2e817b8 | 226 | else ipDefaultHandler(); |
nixnax | 4:a469050d5b80 | 227 | } |
nixnax | 4:a469050d5b80 | 228 | |
nixnax | 4:a469050d5b80 | 229 | void determinePacketType() { |
nixnax | 6:fba4c2e817b8 | 230 | static char pktLCPReqType [] = { 0xff, 3, 0xc0, 0x21 }; // LCP requeswt packet |
nixnax | 6:fba4c2e817b8 | 231 | static char pktIPCPtype [] = { 0x80, 0x21, 1 }; // ip control packet |
nixnax | 6:fba4c2e817b8 | 232 | |
nixnax | 4:a469050d5b80 | 233 | if(0); |
nixnax | 6:fba4c2e817b8 | 234 | else if (0==memcmp( ppp.pkt.buf,pktLCPReqType,4)) LCPhandler(); |
nixnax | 6:fba4c2e817b8 | 235 | else if (0==memcmp( ppp.pkt.buf,pktIPCPtype, 3)) IPFrame(); |
nixnax | 4:a469050d5b80 | 236 | else generalFrame(); // default handler |
nixnax | 4:a469050d5b80 | 237 | } |
nixnax | 4:a469050d5b80 | 238 | |
nixnax | 4:a469050d5b80 | 239 | void scanForConnectString(){ |
nixnax | 4:a469050d5b80 | 240 | char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string |
nixnax | 4:a469050d5b80 | 241 | if( clientFound ) { |
nixnax | 4:a469050d5b80 | 242 | strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated |
nixnax | 4:a469050d5b80 | 243 | pc.printf("CLIENTSERVER"); // respond to PC |
nixnax | 4:a469050d5b80 | 244 | } |
nixnax | 4:a469050d5b80 | 245 | } |