X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=vw-nm.c;h=329f95e4b38fa8a52db1476faf67915afbca0aca;hb=df725c1e1086d45aebe9d78df0d156e618d61986;hp=c8439026fbef7ba03ec1aab073f012bfd7e309e7;hpb=6357000d97517389e2b15f8a7b01c4e83ef0d96f;p=revag-nm.git diff --git a/vw-nm.c b/vw-nm.c index c843902..329f95e 100644 --- a/vw-nm.c +++ b/vw-nm.c @@ -30,7 +30,8 @@ -static void nm_update_my_next_id(struct NM_Main *nm) { +static void nm_update_my_next_id(struct NM_Main *nm) +{ unsigned id = nm->my_id; do { @@ -49,15 +50,28 @@ static void nm_update_my_next_id(struct NM_Main *nm) { break; } } while (id != nm->my_id); +} + - if (nm->nodes[nm->my_id].next == nm->my_id) { - /* Uh oh, we're the only one left. */ - /* TODO */ - nm->nodes[nm->my_id].state = NM_MAIN_LOGIN; - /* TODO: Timeout 140ms (RCD 310) */ +static unsigned nm_num_active_nodes(struct NM_Main *nm) +{ + unsigned id = 0; + unsigned active = 0; + + for (id = 0; id < nm->max_nodes; id++) { + NM_State state; + + state = nm->nodes[id].state & NM_MAIN_MASK; + + if (state == NM_MAIN_ON || state == NM_MAIN_LOGIN) { + /* We skip limp home nodes */ + active++; + } } + + return active; } @@ -87,6 +101,15 @@ static void nm_handle_can_frame(struct NM_Main *nm, struct can_frame *frame) return; } + /* If we're currently stuck in Limp Home mode, and we can see + * someone else's messages: reset counters, reset NM, re-login. + */ + if ((nm->nodes[nm->my_id].state & NM_MAIN_MASK) + == NM_MAIN_LIMPHOME) { + nm_initreset(nm); + return; + } + nm->nodes[sender].next = next; nm->nodes[sender].state = state; @@ -152,9 +175,19 @@ static void nm_handle_can_frame(struct NM_Main *nm, struct can_frame *frame) * round. */ + /* HACK: + * Special case: The Media-In's NM implementation + * doesn't auto-switch to NM_ON. Let's say hello, + * even if it ends up being a little late. + */ + if (nm_num_active_nodes(nm) >= 2) { + nm_set_timer_normal(nm); + } + /* Nothing else to do. */ break; case NM_MAIN_LIMPHOME: + /* Nothing we can do. Poor guy. */ break; } @@ -181,23 +214,35 @@ static void nm_timeout_callback(struct NM_Main *nm, struct can_frame *frame) { switch(nm->timer_reason) { case NM_TIMER_NOW: + /* We're due to log in */ + nm_buildframe(nm, frame); + + if ((nm->nodes[nm->my_id].state & NM_MAIN_MASK) + != NM_MAIN_LOGIN) { + + printf("BUG: TIMER_NOW expired in non-ON state %u\n", + nm->nodes[nm->my_id].state & NM_MAIN_MASK); + } + + /* We're going to be ready, let's + * change state (RCD 310 behavior) + */ + nm->nodes[nm->my_id].state = NM_MAIN_ON; + + nm_set_timer_normal(nm); + break; case NM_TIMER_NORMAL: /* We're due to send our own ring message */ - switch(nm->nodes[nm->my_id].state & NM_MAIN_MASK) { - case NM_MAIN_ON: - break; - case NM_MAIN_LOGIN: - /* We're going to be ready, let's - * change state (RCD 310 behavior) - */ - nm->nodes[nm->my_id].state = NM_MAIN_ON; - break; - default: - printf("BUG: TIMER_NORMAL expired in unknown NM_MAIN state\n"); - break; + nm_buildframe(nm, frame); + + if ((nm->nodes[nm->my_id].state & NM_MAIN_MASK) + != NM_MAIN_ON) { + + printf("BUG: TIMER_NORMAL expired in non-ON state %u\n", + nm->nodes[nm->my_id].state & NM_MAIN_MASK); } + nm_set_timer_awol(nm); - nm_buildframe(nm, frame); break; case NM_TIMER_AWOL: /* The network is silent because a node disappeared @@ -205,13 +250,15 @@ static void nm_timeout_callback(struct NM_Main *nm, struct can_frame *frame) * Reset everything and start over. */ nm_reset(nm); + nm_buildframe(nm, frame); break; case NM_TIMER_LIMPHOME: - /* TODO */ + printf("Limp home timer expired again :(\n"); + + nm_buildframe(nm, frame); + nm_set_timer_limphome(nm); break; } - - nm_buildframe(nm, frame); } @@ -284,14 +331,6 @@ int main(int argc, char **argv) s = net_init(argv[1]); - /* Stir up the hornet's nest */ - if (1) { - struct can_frame frame; - - nm_buildframe(nm, &frame); - can_tx(s, &frame); - } - while (1) { int retval;