00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00103 #include <avr/eeprom.h>
00104 #include <inttypes.h>
00105 #include <stddef.h>
00106 #include <string.h>
00107 #include "net/network.h"
00108 #include "net/transport.h"
00109 #include "utils.h"
00110 #include "net.h"
00111
00112
00113 uint8_t ee_group_size[TSP_MAX_GROUPS] EEPROM;
00114 uint8_t ee_segment_size EEPROM;
00115
00116
00117 #define TPDU_MASK 0x30
00118 #define SEQU_MASK 0x0f
00119
00120
00121 #define TPDU_ACKED_MSG 0x00
00122 #define TPDU_UACKED_MSG 0x01
00123 #define TPDU_ACK 0x02
00124 #define TPDU_REMINDER 0x03
00125
00126
00133 struct cache_entry_t {
00134 net_addr_t addr;
00135 uint8_t sequ;
00136 uint8_t got_ack;
00137 };
00138
00142 struct reply_entry_t {
00143 uint8_t header;
00144 net_requ_t requ;
00145 net_buf_t *buf;
00146 uint8_t local_fin;
00147 };
00148
00149 static struct cache_entry_t cache[TSP_CACHE_SIZE];
00150 static struct reply_entry_t reply_buffer[TSP_REPLY_SIZE];
00151 static uint8_t reply_rd, reply_wr;
00152
00153
00154 static net_buf_t buffer_info;
00156 static struct tsp_int_buf {
00157 uint8_t header[12];
00158 uint8_t ack[2];
00159 uint8_t reminder[8];
00160 uint8_t dummy[2];
00161 } buffer;
00162
00163 static uint8_t tnr;
00164 static uint8_t timeout;
00165 static uint8_t tries;
00166 static uint8_t remaining;
00167 static struct reply_entry_t current;
00168
00169
00170 extern net_buf_t *tsp_ind(uint8_t *buf, uint8_t len, uint8_t session);
00171 extern void tsp_con(uint8_t *buf, uint8_t len);
00172 extern void tsp_con_fin(uint8_t status);
00173
00174 static inline void timeout_start(void)
00175 {
00176 timeout = TSP_TIMEOUT;
00177 }
00178
00179 static inline void timeout_restart(void)
00180 {
00181 timeout = TSP_TIMEOUT;
00182 }
00183
00184 static inline void timeout_stop(void)
00185 {
00186 timeout = 0;
00187 }
00188
00201 static void cache_refresh(const net_addr_t *from)
00202 {
00203 uint8_t i;
00204 struct cache_entry_t tmp;
00205
00206
00207 i = 0;
00208 while (i < TSP_CACHE_SIZE) {
00209 if (net_compare_src_addr(from, &cache[i].addr)) goto match;
00210 i++;
00211 }
00212
00213
00214 for (i=TSP_CACHE_SIZE-1;i>0;i--) cache[i] = cache[i-1];
00215 cache[0].addr = *from;
00216 cache[0].sequ = 0xff;
00217 cache[0].got_ack = 0;
00218 return;
00219
00220 match:
00221
00222 tmp = cache[i];
00223 while (i>0) {
00224 cache[i] = cache[i-1];
00225 i--;
00226 }
00227 cache[0] = tmp;
00228 return;
00229 }
00230
00237 static uint8_t cache_got_reply(uint8_t sequ)
00238 {
00239 if (cache[0].sequ != sequ) return 0;
00240 return cache[0].got_ack;
00241 }
00242
00251 static void queue_reply(const net_ind_t *ind, net_buf_t *buf, uint8_t sequ)
00252 {
00253 reply_wr = (reply_wr+1) & (TSP_REPLY_SIZE-1);
00254 reply_buffer[reply_wr].header = (TPDU_ACK << 4)|sequ;
00255 reply_buffer[reply_wr].requ.dest = ind->src;
00256 reply_buffer[reply_wr].requ.src = ind->rat;
00257 reply_buffer[reply_wr].requ.pdu = ind->pdu;
00258 reply_buffer[reply_wr].requ.backlog = 0;
00259 reply_buffer[reply_wr].buf = buf;
00260 }
00261
00269 static uint8_t calc_backlog(net_addr_t *addr)
00270 {
00271 switch (addr->format) {
00272 case NAF_LOGIC:
00273 return 1;
00274 case NAF_GROUP:
00275 return eeprom_read_byte(&ee_group_size[addr->addr[0]]);
00276 case NAF_PHYSIC:
00277 return 1;
00278 case NAF_BROADCAST:
00279 return eeprom_read_byte(&ee_segment_size);
00280 }
00281 return 0;
00282 }
00283
00284
00285
00286
00287
00296 void net_ind(uint8_t *buf, uint8_t len, const net_ind_t *ind)
00297 {
00298 uint8_t sequ, id;
00299 net_buf_t *tmp;
00300
00301
00302 if (ind->pdu == NPDU_SINGLE) {
00303 tsp_ind(buf, len, 0);
00304 return;
00305 }
00306
00307
00308 switch (buf[0] & TPDU_MASK) {
00309 case TPDU_ACKED_MSG<<4:
00310 cache_refresh(&ind->src);
00311 sequ = buf[0]&SEQU_MASK;
00312 if (cache_got_reply(sequ)) return;
00313 if (ind->pdu == NPDU_SESSION) {
00314
00315 tmp = tsp_ind(buf+1, len-1, (cache[0].sequ != sequ)?1:2);
00316 if (tmp != NULL) queue_reply(ind, tmp, sequ);
00317 } else {
00318
00319 queue_reply(ind, NULL, sequ);
00320
00321 if (cache[0].sequ != sequ) tsp_ind(buf+1, len-1, 0);
00322 }
00323 cache[0].sequ = sequ;
00324 break;
00325
00326 case TPDU_UACKED_MSG<<4:
00327 cache_refresh(&ind->src);
00328 sequ = buf[0]&SEQU_MASK;
00329 if (cache[0].sequ != sequ) {
00330 tsp_ind(buf+1, len-1, 0);
00331 cache[0].sequ = sequ;
00332 }
00333 break;
00334
00335 case TPDU_ACK<<4:
00336
00337 if (remaining == 0) break;
00338
00339
00340
00341 if ((buf[0]&SEQU_MASK) == (current.header&SEQU_MASK)) {
00342
00343 if (ind->pdu == NPDU_SESSION) tsp_con(buf+1, len-1);
00344
00345 if (ind->src.format == NAF_GROUP) {
00346 id = ind->src.addr[1];
00347
00348 if ((buffer.reminder[id>>3] & (1<<(id&0x07))) == 0) {
00349 buffer.reminder[id>>3] |= 1<<(id&0x07);
00350 remaining--;
00351 }
00352 } else {
00353
00354 remaining = 0;
00355 }
00356
00357 if (remaining == 0) {
00358 timeout_stop();
00359 tsp_con_fin(1);
00360 }
00361 }
00362 break;
00363
00364 case TPDU_REMINDER<<4:
00365 cache_refresh(&ind->src);
00366
00367 if (cache[0].sequ != (buf[0]&SEQU_MASK)) return;
00368
00369 id = net_get_local_member_id(ind->rat);
00370 if (buf[(id>>3)+1] & (1 << (id&0x07))) cache[0].got_ack = 1;
00371 break;
00372 }
00373 }
00374
00380 void net_con(void)
00381 {
00382 if (reply_buffer[reply_rd].local_fin) tsp_con_fin(1);
00383 }
00384
00385
00386
00387
00388
00389
00398 void tsp_process(void)
00399 {
00400 net_buf_t *buf;
00401
00402
00403 if (!net_clear_to_send()) return;
00404
00405
00406 if (reply_rd != reply_wr) {
00407 reply_rd = (reply_rd+1) & (TSP_REPLY_SIZE-1);
00408
00409
00410 buf = reply_buffer[reply_rd].buf;
00411 if (reply_buffer[reply_rd].requ.pdu == NPDU_SINGLE) {
00412
00413 buffer_info = *buf;
00414 } else {
00415
00416 switch (reply_buffer[reply_rd].header&TPDU_MASK) {
00417 case TPDU_ACK<<4:
00418 if (buf == NULL) {
00419
00420 buf_init(buffer_info, &buffer.ack, 0);
00421 } else {
00422 buffer_info = *buf;
00425 reply_buffer[reply_rd].local_fin = 1;
00426 }
00427 break;
00428 case TPDU_REMINDER<<4:
00429 buf_init(buffer_info, &buffer.reminder, 1+sizeof(buffer.reminder));
00430 break;
00431 default:
00432 buffer_info = *buf;
00433 }
00434 buf_prep_char(&buffer_info, reply_buffer[reply_rd].header);
00435 }
00436
00437 if (!net_requ(&buffer_info, &reply_buffer[reply_rd].requ)) {
00438 reply_rd = (reply_rd-1) & (TSP_REPLY_SIZE-1);
00439 }
00440 }
00441 }
00442
00451 void tsp_check_timeout(void)
00452 {
00453 if (remaining == 0) return;
00454 if (timeout == 0) return;
00455
00456 timeout--;
00457 if (timeout == 0) {
00458 if (tries > 0) {
00459
00460 tries--;
00461
00462 if (current.requ.dest.format == NAF_GROUP) {
00463 reply_buffer[reply_wr] = current;
00464 reply_buffer[reply_wr].header = (reply_buffer[reply_wr].header&SEQU_MASK) | (TPDU_REMINDER<<4);
00465 reply_buffer[reply_wr].requ.backlog = 0;
00466 reply_wr = (reply_wr+1) & (TSP_REPLY_SIZE-1);
00467 }
00468 reply_wr = (reply_wr+1) & (TSP_REPLY_SIZE-1);
00469 reply_buffer[reply_wr] = current;
00470 reply_buffer[reply_wr].requ.backlog = remaining;
00471 timeout = TSP_TIMEOUT;
00472 } else {
00473
00474 remaining = 0;
00475 tsp_con_fin(0);
00476 }
00477 }
00478 }
00479
00492 int8_t tsp_requ(net_buf_t *buf, net_addr_t *dest, enum tsp_service_e service)
00493 {
00494 uint8_t i;
00495
00496
00497 if (remaining != 0) return 0;
00498
00499
00500 i = 1;
00501 current.requ.dest = *dest;
00502 current.requ.src = AT_LOGIC;
00503 current.buf = buf;
00504 current.local_fin = 0;
00505 switch (service) {
00506 case S_DGRAM:
00507 current.requ.pdu = NPDU_SINGLE;
00508 current.requ.backlog = 0;
00509 break;
00510 case S_REPEATED:
00511 current.header = (TPDU_UACKED_MSG<<4)|(tnr&SEQU_MASK);
00512 current.requ.pdu = NPDU_TRANSACTION;
00513 current.requ.backlog = 0;
00514 tnr++;
00515 i = 4;
00516 break;
00517 case S_ACKED:
00518 current.header = (TPDU_ACKED_MSG<<4)|(tnr&SEQU_MASK);
00519 current.requ.pdu = NPDU_TRANSACTION;
00520 current.requ.backlog = calc_backlog(dest);
00521 timeout_start();
00522 tnr++;
00523 break;
00524 case S_REQUEST:
00525 current.requ.pdu = NPDU_SESSION;
00526 current.header = (TPDU_ACKED_MSG<<4)|(tnr&SEQU_MASK);
00527 current.requ.backlog = calc_backlog(dest);
00528 timeout_start();
00529 tnr++;
00530 break;
00531 default:
00532 return -1;
00533 }
00534
00535
00536 memset(&buffer.reminder, 0, sizeof(buffer.reminder));
00537
00538
00539 remaining = current.requ.backlog;
00540 tries = 3;
00541 while (i > 0) {
00542
00543 if ((i==1) && (service <= S_REPEATED)) current.local_fin = 1;
00544 reply_wr = (reply_wr+1) & (TSP_REPLY_SIZE-1);
00545 reply_buffer[reply_wr] = current;
00546 i--;
00547 }
00548
00549 return 1;
00550 }
00551
00555 uint8_t tsp_clear_to_send(void)
00556 {
00557 return remaining == 0;
00558 }
00559
00565 void tsp_set_segment_size(uint8_t size)
00566 {
00567 eeprom_write_byte(&ee_segment_size, size);
00568 }
00569
00575 uint8_t tsp_get_segment_size(void)
00576 {
00577 return eeprom_read_byte(&ee_segment_size);
00578 }
00579
00586 void tsp_set_group_size(uint8_t group, uint8_t size)
00587 {
00588 eeprom_write_byte(&ee_group_size[group], size);
00589 }
00590
00597 uint8_t tsp_get_group_size(uint8_t group)
00598 {
00599 return eeprom_read_byte(&ee_group_size[group]);
00600 }