slip.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdio.h>
00037 #include <string.h>
00038
00039 #include "contiki.h"
00040
00041 #include "net/uip.h"
00042 #include "net/uip-fw.h"
00043 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00044
00045 #include "dev/slip.h"
00046
00047 #define SLIP_END 0300
00048 #define SLIP_ESC 0333
00049 #define SLIP_ESC_END 0334
00050 #define SLIP_ESC_ESC 0335
00051
00052 PROCESS(slip_process, "SLIP driver");
00053
00054 u8_t slip_active;
00055
00056 #if 1
00057 #define SLIP_STATISTICS(statement)
00058 #else
00059 u16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop;
00060 #define SLIP_STATISTICS(statement) statement
00061 #endif
00062
00063
00064 #define RX_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN + 16)
00065
00066 enum {
00067 STATE_TWOPACKETS = 0,
00068 STATE_OK = 1,
00069 STATE_ESC = 2,
00070 STATE_RUBBISH = 3,
00071 };
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 static u8_t state = STATE_TWOPACKETS;
00085 static u16_t begin, end;
00086 static u8_t rxbuf[RX_BUFSIZE];
00087 static u16_t pkt_end;
00088
00089 static void (* input_callback)(void) = NULL;
00090
00091 void
00092 slip_set_input_callback(void (*c)(void))
00093 {
00094 input_callback = c;
00095 }
00096
00097
00098
00099
00100
00101 u8_t
00102 slip_send(void)
00103 {
00104 u16_t i;
00105 u8_t *ptr;
00106 u8_t c;
00107
00108 slip_arch_writeb(SLIP_END);
00109
00110 ptr = &uip_buf[UIP_LLH_LEN];
00111 for(i = 0; i < uip_len; ++i) {
00112 if(i == UIP_TCPIP_HLEN) {
00113 ptr = (u8_t *)uip_appdata;
00114 }
00115 c = *ptr++;
00116 if(c == SLIP_END) {
00117 slip_arch_writeb(SLIP_ESC);
00118 c = SLIP_ESC_END;
00119 } else if(c == SLIP_ESC) {
00120 slip_arch_writeb(SLIP_ESC);
00121 c = SLIP_ESC_ESC;
00122 }
00123 slip_arch_writeb(c);
00124 }
00125 slip_arch_writeb(SLIP_END);
00126
00127 return UIP_FW_OK;
00128 }
00129
00130
00131 u8_t
00132 slip_write(const void *_ptr, int len)
00133 {
00134 const u8_t *ptr = _ptr;
00135 u16_t i;
00136 u8_t c;
00137
00138 slip_arch_writeb(SLIP_END);
00139
00140 for(i = 0; i < len; ++i) {
00141 c = *ptr++;
00142 if(c == SLIP_END) {
00143 slip_arch_writeb(SLIP_ESC);
00144 c = SLIP_ESC_END;
00145 } else if(c == SLIP_ESC) {
00146 slip_arch_writeb(SLIP_ESC);
00147 c = SLIP_ESC_ESC;
00148 }
00149 slip_arch_writeb(c);
00150 }
00151 slip_arch_writeb(SLIP_END);
00152
00153 return len;
00154 }
00155
00156 static void
00157 rxbuf_init(void)
00158 {
00159 begin = end = pkt_end = 0;
00160 state = STATE_OK;
00161 }
00162
00163
00164 static u16_t
00165 slip_poll_handler(u8_t *outbuf, u16_t blen)
00166 {
00167
00168 if(rxbuf[begin] == 'C') {
00169 int i;
00170 if(begin < end && (end - begin) >= 6
00171 && memcmp(&rxbuf[begin], "CLIENT", 6) == 0) {
00172 state = STATE_TWOPACKETS;
00173 memset(&rxbuf[begin], 0x0, 6);
00174
00175 rxbuf_init();
00176
00177 for(i = 0; i < 13; i++) {
00178 slip_arch_writeb("CLIENTSERVER\300"[i]);
00179 }
00180 return 0;
00181 }
00182 }
00183 #ifdef SLIP_CONF_ANSWER_MAC_REQUEST
00184 else if(rxbuf[begin] == '?') {
00185
00186 int i, j;
00187 char* hexchar = "0123456789abcdef";
00188 if(begin < end && (end - begin) >= 2
00189 && rxbuf[begin + 1] == 'M') {
00190 state = STATE_TWOPACKETS;
00191 rxbuf[begin] = 0;
00192 rxbuf[begin + 1] = 0;
00193
00194 rxbuf_init();
00195
00196 rimeaddr_t addr = get_mac_addr();
00197
00198 slip_arch_writeb('!');
00199 slip_arch_writeb('M');
00200 for(j = 0; j < 8; j++) {
00201 slip_arch_writeb(hexchar[addr.u8[j] >> 4]);
00202 slip_arch_writeb(hexchar[addr.u8[j] & 15]);
00203 }
00204 slip_arch_writeb(SLIP_END);
00205 return 0;
00206 }
00207 }
00208 #endif
00209
00210
00211
00212
00213
00214 if(begin != pkt_end) {
00215 u16_t len;
00216
00217 if(begin < pkt_end) {
00218 len = pkt_end - begin;
00219 if(len > blen) {
00220 len = 0;
00221 } else {
00222 memcpy(outbuf, &rxbuf[begin], len);
00223 }
00224 } else {
00225 len = (RX_BUFSIZE - begin) + (pkt_end - 0);
00226 if(len > blen) {
00227 len = 0;
00228 } else {
00229 unsigned i;
00230 for(i = begin; i < RX_BUFSIZE; i++) {
00231 *outbuf++ = rxbuf[i];
00232 }
00233 for(i = 0; i < pkt_end; i++) {
00234 *outbuf++ = rxbuf[i];
00235 }
00236 }
00237 }
00238
00239
00240 begin = pkt_end;
00241 if(state == STATE_TWOPACKETS) {
00242 pkt_end = end;
00243 state = STATE_OK;
00244
00245
00246 process_poll(&slip_process);
00247 }
00248 return len;
00249 }
00250
00251 return 0;
00252 }
00253
00254 PROCESS_THREAD(slip_process, ev, data)
00255 {
00256 PROCESS_BEGIN();
00257
00258 rxbuf_init();
00259
00260 while(1) {
00261 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
00262
00263 slip_active = 1;
00264
00265
00266 uip_len = slip_poll_handler(&uip_buf[UIP_LLH_LEN],
00267 UIP_BUFSIZE - UIP_LLH_LEN);
00268 #if !UIP_CONF_IPV6
00269 if(uip_len == 4 && strncmp((char*)&uip_buf[UIP_LLH_LEN], "?IPA", 4) == 0) {
00270 char buf[8];
00271 memcpy(&buf[0], "=IPA", 4);
00272 memcpy(&buf[4], &uip_hostaddr, 4);
00273 if(input_callback) {
00274 input_callback();
00275 }
00276 slip_write(buf, 8);
00277 } else if(uip_len > 0
00278 && uip_len == (((u16_t)(BUF->len[0]) << 8) + BUF->len[1])
00279 && uip_ipchksum() == 0xffff) {
00280 #define IP_DF 0x40
00281 if(BUF->ipid[0] == 0 && BUF->ipid[1] == 0 && BUF->ipoffset[0] & IP_DF) {
00282 static u16_t ip_id;
00283 u16_t nid = ip_id++;
00284 BUF->ipid[0] = nid >> 8;
00285 BUF->ipid[1] = nid;
00286 nid = uip_htons(nid);
00287 nid = ~nid;
00288 BUF->ipchksum += nid;
00289 if(BUF->ipchksum < nid) {
00290 BUF->ipchksum++;
00291 }
00292 }
00293 #ifdef SLIP_CONF_TCPIP_INPUT
00294 SLIP_CONF_TCPIP_INPUT();
00295 #else
00296 tcpip_input();
00297 #endif
00298 } else {
00299 uip_len = 0;
00300 SLIP_STATISTICS(slip_ip_drop++);
00301 }
00302 #else
00303 if(uip_len > 0) {
00304 if(input_callback) {
00305 input_callback();
00306 }
00307 #ifdef SLIP_CONF_TCPIP_INPUT
00308 SLIP_CONF_TCPIP_INPUT();
00309 #else
00310 tcpip_input();
00311 #endif
00312 }
00313 #endif
00314 }
00315
00316 PROCESS_END();
00317 }
00318
00319 int
00320 slip_input_byte(unsigned char c)
00321 {
00322 switch(state) {
00323 case STATE_RUBBISH:
00324 if(c == SLIP_END) {
00325 state = STATE_OK;
00326 }
00327 return 0;
00328
00329 case STATE_TWOPACKETS:
00330 return 0;
00331
00332 case STATE_ESC:
00333 if(c == SLIP_ESC_END) {
00334 c = SLIP_END;
00335 } else if(c == SLIP_ESC_ESC) {
00336 c = SLIP_ESC;
00337 } else {
00338 state = STATE_RUBBISH;
00339 SLIP_STATISTICS(slip_rubbish++);
00340 end = pkt_end;
00341 return 0;
00342 }
00343 state = STATE_OK;
00344 break;
00345
00346 case STATE_OK:
00347 if(c == SLIP_ESC) {
00348 state = STATE_ESC;
00349 return 0;
00350 } else if(c == SLIP_END) {
00351
00352
00353
00354
00355
00356 if(end != pkt_end) {
00357 if(begin == pkt_end) {
00358 pkt_end = end;
00359 } else {
00360 state = STATE_TWOPACKETS;
00361 SLIP_STATISTICS(slip_twopackets++);
00362 }
00363 process_poll(&slip_process);
00364 return 1;
00365 }
00366 return 0;
00367 }
00368 break;
00369 }
00370
00371
00372 {
00373 unsigned next;
00374 next = end + 1;
00375 if(next == RX_BUFSIZE) {
00376 next = 0;
00377 }
00378 if(next == begin) {
00379 state = STATE_RUBBISH;
00380 SLIP_STATISTICS(slip_overflow++);
00381 end = pkt_end;
00382 return 0;
00383 }
00384 rxbuf[end] = c;
00385 end = next;
00386 }
00387
00388
00389 if(c == 'T' && rxbuf[begin] == 'C') {
00390 process_poll(&slip_process);
00391 return 1;
00392 }
00393
00394 return 0;
00395 }
00396