-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 {
+
+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;
+}
+
+
+
static void nm_handle_can_frame(struct NM_Main *nm, struct can_frame *frame)
{
NM_ID sender, next;
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;
* 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;
}
{
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
* 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);
}
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;