1 static char* nm_main_to_string(NM_State state)
3 switch(state & NM_MAIN_MASK) {
10 case NM_MAIN_LIMPHOME:
17 static char* nm_sleep_to_string(NM_State state)
19 switch(state & NM_SLEEP_MASK) {
22 case NM_SLEEP_REQUEST:
25 return "Acknowledged";
33 static void nm_dump_all(struct NM_Main *nm)
38 printf(" Node | next | Main | Sleep\n");
39 printf("----------------------------------------\n");
41 for (id = 0; id < nm->max_nodes; id++) {
42 struct NM_Node *node = &nm->nodes[id];
44 if (node->state & NM_MAIN_MASK) {
45 printf(" %02x %02x %9s %s\n",
48 nm_main_to_string(node->state),
49 nm_sleep_to_string(node->state));
62 static void can_tx(int socket, struct can_frame *frame)
66 ret = write(socket, frame, sizeof(*frame));
67 if (ret != sizeof(*frame)) {
68 perror("write to CAN socket");
79 static int nm_is_rx_frame_valid(struct NM_Main *nm, struct can_frame *frame)
81 if (frame->can_dlc < 2) {
82 printf("Skipping short frame from CAN ID %03x\n", frame->can_id);
86 if ((frame->can_id & ~(nm->max_nodes - 1)) != nm->can_base) {
87 printf("Skipping non-NM from CAN ID %03x\n", frame->can_id);
103 static void nm_set_timer_now(struct NM_Main *nm)
107 nm->timer_reason = NM_TIMER_NOW;
110 static void nm_set_timer_normal(struct NM_Main *nm)
113 nm->tv.tv_usec = NM_USECS_NORMAL_TURN;
114 nm->timer_reason = NM_TIMER_NORMAL;
117 static void nm_set_timer_awol(struct NM_Main *nm)
120 nm->tv.tv_usec = NM_USECS_NODE_AWOL;
121 nm->timer_reason = NM_TIMER_AWOL;
124 static void nm_set_timer_limphome(struct NM_Main *nm)
127 nm->tv.tv_usec = NM_USECS_LIMPHOME;
128 nm->timer_reason = NM_TIMER_LIMPHOME;
136 static void nm_reset(struct NM_Main *nm)
140 if (nm->nodes[nm->my_id].next == nm->my_id) {
144 for (id = 0; id < nm->max_nodes; id++) {
145 nm->nodes[id].next = 0xff;
146 nm->nodes[id].state = NM_MAIN_OFF;
149 nm->nodes[nm->my_id].next = nm->my_id;
150 if (nm->lonely_resets >= 5) {
151 printf("Limp home detected :(\n");
153 nm->nodes[nm->my_id].state = NM_MAIN_LIMPHOME;
154 nm_set_timer_limphome(nm);
156 nm->nodes[nm->my_id].state = NM_MAIN_LOGIN;
157 nm_set_timer_now(nm);
162 static void nm_initreset(struct NM_Main *nm)
166 nm->lonely_resets = 0;
172 static struct NM_Main* nm_alloc(unsigned node_bits, NM_ID my_id, canid_t can_base)
176 if (node_bits < 1 || node_bits > 6) {
180 nm = malloc(sizeof(*nm));
185 nm->max_nodes = 1 << node_bits;
186 nm->nodes = malloc(nm->max_nodes * sizeof(*nm->nodes));
193 nm->can_base = can_base;
203 static void nm_free(struct NM_Main *nm)