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@8:48e40f1ff316, 2016-12-29 (annotated)
- Committer:
- nixnax
- Date:
- Thu Dec 29 17:25:16 2016 +0000
- Revision:
- 8:48e40f1ff316
- Parent:
- 7:ab147f5e97ac
- Child:
- 9:0992486d4a30
Wow - the link is fully up. The code is a bit spaghetti but it's working for the first time.
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 | 4:a469050d5b80 | 164 | void LCPackFrame() { |
nixnax | 7:ab147f5e97ac | 165 | xx.printf("== Saw Ack - PPP is up ==\n"); |
nixnax | 5:27624c02189f | 166 | } |
nixnax | 4:a469050d5b80 | 167 | |
nixnax | 4:a469050d5b80 | 168 | |
nixnax | 6:fba4c2e817b8 | 169 | void ipRequestHandler(){ |
nixnax | 6:fba4c2e817b8 | 170 | xx.printf("== IP Request Frame ==\n"); |
nixnax | 8:48e40f1ff316 | 171 | generalFrame(); |
nixnax | 8:48e40f1ff316 | 172 | if ( ppp.pkt.buf[7] != 4 ) { |
nixnax | 7:ab147f5e97ac | 173 | ppp.pkt.buf[4]=4; // Nack |
nixnax | 8:48e40f1ff316 | 174 | sendFrame(); |
nixnax | 7:ab147f5e97ac | 175 | } else { |
nixnax | 7:ab147f5e97ac | 176 | ppp.pkt.buf[4]=2; // ack the minimum |
nixnax | 7:ab147f5e97ac | 177 | sendFrame(); // acknowledge |
nixnax | 7:ab147f5e97ac | 178 | xx.printf("zeroconf ack\n"); |
nixnax | 7:ab147f5e97ac | 179 | // send our own request now |
nixnax | 7:ab147f5e97ac | 180 | ppp.pkt.buf[4]=1; // request the minimum |
nixnax | 7:ab147f5e97ac | 181 | ppp.pkt.buf[5]++; // next sequence |
nixnax | 7:ab147f5e97ac | 182 | sendFrame(); // this is our request |
nixnax | 7:ab147f5e97ac | 183 | } |
nixnax | 6:fba4c2e817b8 | 184 | } |
nixnax | 6:fba4c2e817b8 | 185 | |
nixnax | 6:fba4c2e817b8 | 186 | void ipAckHandler(){ |
nixnax | 6:fba4c2e817b8 | 187 | xx.printf("== IP Ack Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 188 | } |
nixnax | 6:fba4c2e817b8 | 189 | |
nixnax | 6:fba4c2e817b8 | 190 | void ipNackHandler(){ |
nixnax | 6:fba4c2e817b8 | 191 | xx.printf("== IP Nack Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 192 | } |
nixnax | 6:fba4c2e817b8 | 193 | |
nixnax | 6:fba4c2e817b8 | 194 | void ipDefaultHandler(){ |
nixnax | 6:fba4c2e817b8 | 195 | xx.printf("== IP Unknown Frame ==\n"); |
nixnax | 6:fba4c2e817b8 | 196 | } |
nixnax | 6:fba4c2e817b8 | 197 | |
nixnax | 6:fba4c2e817b8 | 198 | void LCPgeneralFrame(){ |
nixnax | 6:fba4c2e817b8 | 199 | xx.printf("== LCP General Handler ==\n"); |
nixnax | 6:fba4c2e817b8 | 200 | generalFrame(); |
nixnax | 6:fba4c2e817b8 | 201 | } |
nixnax | 6:fba4c2e817b8 | 202 | |
nixnax | 6:fba4c2e817b8 | 203 | |
nixnax | 6:fba4c2e817b8 | 204 | void LCPhandler(){ |
nixnax | 6:fba4c2e817b8 | 205 | int action = ppp.pkt.buf[4]; |
nixnax | 6:fba4c2e817b8 | 206 | if(0); |
nixnax | 6:fba4c2e817b8 | 207 | else if ( action == 1 ) LCPrequestFrame(); |
nixnax | 6:fba4c2e817b8 | 208 | else if ( action == 2 ) LCPackFrame(); |
nixnax | 6:fba4c2e817b8 | 209 | else LCPgeneralFrame(); |
nixnax | 6:fba4c2e817b8 | 210 | } |
nixnax | 6:fba4c2e817b8 | 211 | |
nixnax | 6:fba4c2e817b8 | 212 | void IPFrame() { |
nixnax | 7:ab147f5e97ac | 213 | led1 = ppp.pkt.buf[5] & 1; // This is the sequence number so the led blinks on packets |
nixnax | 7:ab147f5e97ac | 214 | ppp.pkt.id = ppp.pkt.buf[5]; // remember the sequence number |
nixnax | 7:ab147f5e97ac | 215 | int action = ppp.pkt.buf[4]; // packet type is here |
nixnax | 6:fba4c2e817b8 | 216 | if(0); |
nixnax | 6:fba4c2e817b8 | 217 | else if ( action == 1 ) ipRequestHandler(); |
nixnax | 6:fba4c2e817b8 | 218 | else if ( action == 2 ) ipAckHandler(); |
nixnax | 6:fba4c2e817b8 | 219 | else if ( action == 3 ) ipNackHandler(); |
nixnax | 6:fba4c2e817b8 | 220 | else ipDefaultHandler(); |
nixnax | 4:a469050d5b80 | 221 | } |
nixnax | 4:a469050d5b80 | 222 | |
nixnax | 4:a469050d5b80 | 223 | void determinePacketType() { |
nixnax | 7:ab147f5e97ac | 224 | static char pktLCPReqType [] = { 0xff, 3, 0xc0, 0x21 }; // LCP packet |
nixnax | 7:ab147f5e97ac | 225 | static char pktIPCPtype [] = { 0xff, 3, 0x80, 0x21, }; // IP packet |
nixnax | 6:fba4c2e817b8 | 226 | |
nixnax | 4:a469050d5b80 | 227 | if(0); |
nixnax | 6:fba4c2e817b8 | 228 | else if (0==memcmp( ppp.pkt.buf,pktLCPReqType,4)) LCPhandler(); |
nixnax | 7:ab147f5e97ac | 229 | else if (0==memcmp( ppp.pkt.buf,pktIPCPtype, 4)) IPFrame(); |
nixnax | 4:a469050d5b80 | 230 | else generalFrame(); // default handler |
nixnax | 4:a469050d5b80 | 231 | } |
nixnax | 4:a469050d5b80 | 232 | |
nixnax | 4:a469050d5b80 | 233 | void scanForConnectString(){ |
nixnax | 4:a469050d5b80 | 234 | char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string |
nixnax | 4:a469050d5b80 | 235 | if( clientFound ) { |
nixnax | 4:a469050d5b80 | 236 | strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated |
nixnax | 4:a469050d5b80 | 237 | pc.printf("CLIENTSERVER"); // respond to PC |
nixnax | 4:a469050d5b80 | 238 | } |
nixnax | 4:a469050d5b80 | 239 | } |