void tool_app_t::cmac(const netlist::factory::element_t *e) { auto v = plib::psplit(e->param_desc(), ","); pstring vs; for (auto s : v) vs += ", p" + s.replace_all("+", "").replace_all(".", "_"); mac_out("#define " + e->name() + "(name" + vs + ")"); mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)"); for (auto s : v) { pstring r(s.replace_all("+", "").replace_all(".", "_")); if (s.startsWith("+")) mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")"); else mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")"); } mac_out("", false); }
/* * This function is an intermediate function that processes * any options before transmitting the actual frame. It parses * the frame's tx options and if its an indirect transfer, will * send it to the indirect queue. If the frame also requires an * ACK, it will buffer it in the retry queue so that the frame * can be re-sent in the case that the ack doesn't come. */ void mac_tx_handler(buffer_t *buf, address_t *addr, bool indir, bool ack_req, U8 dsn, U8 handle) { if (indir) { mac_indir_add(buf, addr, ack_req, dsn, handle); return; } if (ack_req) mac_retry_add(buf, dsn, handle); mac_out(buf, ack_req, dsn, handle); }
void tool_app_t::header_entry(const netlist::factory::element_t *e) { auto v = plib::psplit(e->param_desc(), ","); pstring vs; for (const auto &s : v) if (!plib::startsWith(s, "@")) vs += ", p" + plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"); mac_out("#define " + e->name() + "(name" + vs + ")"); mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)"); for (const auto &s : v) { pstring r(plib::replace_all(plib::replace_all(plib::replace_all(s, "+", ""), ".", "_"), "@","")); if (plib::startsWith(s, "+")) mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")"); else if (plib::startsWith(s, "@")) mac_out("\tNET_CONNECT(name, " + r + ", " + r + ")"); else mac_out("\tNETDEV_PARAMI(name, " + r + ", p" + r + ")"); } mac_out("", false); }
/* * Handle the rx events from the mac process. If the driver * receives a valid frame, it will send an event to the mac * process. The mac process will then call the event handler * which retrieves the frame from the rx queue and parses it. * Once parsed, it will be handled according to the frame type. * If its a command frame, it gets sent to the command handler, * a data frame gets sent to the next higher layer, etc... */ static void mac_eventhandler(process_event_t event) { buffer_t *buf, *buf_out; mac_hdr_t hdr; mac_cmd_t cmd; bool frm_pend; mac_pcb_t *pcb = mac_pcb_get(); mac_pib_t *pib = mac_pib_get(); if (event == event_mac_rx) { DBG_PRINT("MAC_EVENTHANDLER: Rx event occurred.\n"); buf = mac_queue_buf_pop(); if (buf) { DBG_PRINT_RAW("\n<INCOMING>"); debug_dump_buf(buf->dptr, buf->len); /* decode the packet */ mac_parse_hdr(buf, &hdr); debug_dump_mac_hdr(&hdr); /* * check if an ack is needed. if so, then generate * an ack and queue it for transmission. the frm * pending bit will be set for any frame coming from * an address that has an indirect frame for it. this * is against the spec, but it will speed up the ack * transmission. * NOTE: the ack response section may change due to the * tight ack timing requirements. */ if (hdr.mac_frm_ctrl.ack_req) { BUF_ALLOC(buf_out, TX); DBG_PRINT("MAC: ACK Required.\n"); frm_pend = mac_indir_frm_pend(&hdr.src_addr); mac_gen_ack(buf_out, frm_pend, hdr.dsn); mac_out(buf_out, false, hdr.dsn, 0); } /* * process accordingly. if a scan is in progress, * all frames except for beacon frames will be * discarded. */ switch(hdr.mac_frm_ctrl.frame_type) { case MAC_COMMAND: if (pcb->mac_state != MLME_SCAN) { /* * need to handle the case that this is an indirect * transfer, which means that we need to stop the * poll timer and send a status to the poll confirm. */ if ((pcb->mac_state == MLME_DATA_REQ) && (hdr.src_addr.mode == SHORT_ADDR) && (hdr.src_addr.short_addr == pib->coord_addr.short_addr)) { ctimer_stop(&pcb->mlme_tmr); mac_poll_conf(MAC_SUCCESS); } mac_parse_cmd(buf, &cmd); mac_cmd_handler(&cmd, &hdr); } buf_free(buf); break; case MAC_BEACON: /* discard the beacon if we're not doing a scan */ if (pcb->mac_state == MLME_SCAN) { mac_parse_beacon(buf, &hdr); mac_beacon_notify_ind(buf, mac_scan_descr_find_addr(&hdr.src_addr)); } buf_free(buf); break; case MAC_ACK: mac_retry_ack_handler(hdr.dsn); /* * we need to do some special ops depending on the * state we're in if we get an ACK. */ if (pcb->mac_state == MLME_ASSOC_REQ) { if (pcb->assoc_req_dsn == hdr.dsn) ctimer_set(&pcb->mlme_tmr, pib->resp_wait_time, mac_poll_req, NULL); } else if (pcb->mac_state == MLME_DATA_REQ) { if (hdr.mac_frm_ctrl.frame_pending) ctimer_set(&pcb->mlme_tmr, aMacMaxFrameTotalWaitTime, mac_poll_timeout, NULL); } buf_free(buf); break; case MAC_DATA: if (pcb->mac_state != MLME_SCAN) { /* * need to handle the case that this is an indirect * transfer, which means that we need to stop the poll * timer and send a status to the poll confirm. */ if ((pcb->mac_state == MLME_DATA_REQ) && (hdr.src_addr.mode == SHORT_ADDR) && (hdr.src_addr.short_addr == pib->coord_addr.short_addr)) { ctimer_stop(&pcb->mlme_tmr); mac_poll_conf(MAC_SUCCESS); } mac_data_ind(buf, &hdr); } else buf_free(buf); break; default: /* TODO: Add a statistic here to capture an error'd rx */ break; } } /* * there's a possibility that more than one frame is in the * buffer. if they came in before this function gets executed. * So process until the queue is empty. */ if (!mac_queue_is_empty()) { while (process_post(&mac_process, event_mac_rx, NULL) != PROCESS_ERR_OK) { ; } } } }