int gnrc_gomach_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt, netopt_enable_t csma_enable) { assert(netif != NULL); assert(pkt != NULL); /* Enable/disable CSMA according to the input. */ netif->dev->driver->set(netif->dev, NETOPT_CSMA, &csma_enable, sizeof(netopt_enable_t)); gnrc_gomach_set_tx_finish(netif, false); gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_UNDEF); return _gnrc_gomach_transmit(netif, pkt); }
/** * @brief Function called by the device driver on device events * * @param[in] event type of event * @param[in] data optional parameter */ static void _lwmac_event_cb(netdev_t *dev, netdev_event_t event) { gnrc_netif_t *netif = (gnrc_netif_t *) dev->context; if (event == NETDEV_EVENT_ISR) { msg_t msg; msg.type = NETDEV_MSG_TYPE_EVENT; msg.content.ptr = (void *) netif; if (msg_send(&msg, netif->pid) <= 0) { LOG_WARNING("WARNING: [LWMAC] gnrc_netdev: possibly lost interrupt.\n"); } } else { DEBUG("gnrc_netdev: event triggered -> %i\n", event); switch (event) { case NETDEV_EVENT_RX_STARTED: { LOG_DEBUG("[LWMAC] NETDEV_EVENT_RX_STARTED\n"); gnrc_netif_set_rx_started(netif, true); break; } case NETDEV_EVENT_RX_COMPLETE: { LOG_DEBUG("[LWMAC] NETDEV_EVENT_RX_COMPLETE\n"); gnrc_pktsnip_t *pkt = netif->ops->recv(netif); /* Prevent packet corruption when a packet is sent before the previous * received packet has been downloaded. This happens e.g. when a timeout * expires that causes the tx state machine to send a packet. When a * packet arrives after the timeout, the notification is queued but the * tx state machine continues to send and then destroys the received * packet in the frame buffer. After completion, the queued notification * will be handled a corrupted packet will be downloaded. Therefore * keep track that RX_STARTED is followed by RX_COMPLETE. * * TODO: transceivers might have 2 frame buffers, so make this optional */ if (pkt == NULL) { gnrc_netif_set_rx_started(netif, false); break; } gnrc_netif_set_rx_started(netif, false); if (!gnrc_mac_queue_rx_packet(&netif->mac.rx, 0, pkt)) { LOG_ERROR("ERROR: [LWMAC] Can't push RX packet @ %p, memory full?\n", pkt); gnrc_pktbuf_release(pkt); break; } lwmac_schedule_update(netif); break; } case NETDEV_EVENT_TX_STARTED: { gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_UNDEF); gnrc_netif_set_rx_started(netif, false); break; } case NETDEV_EVENT_TX_COMPLETE: { gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_SUCCESS); gnrc_netif_set_rx_started(netif, false); lwmac_schedule_update(netif); break; } case NETDEV_EVENT_TX_NOACK: { gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_NOACK); gnrc_netif_set_rx_started(netif, false); lwmac_schedule_update(netif); break; } case NETDEV_EVENT_TX_MEDIUM_BUSY: { gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_BUSY); gnrc_netif_set_rx_started(netif, false); lwmac_schedule_update(netif); break; } default: LOG_WARNING("WARNING: [LWMAC] Unhandled netdev event: %u\n", event); } } /* Execute main state machine because something just happend*/ while (gnrc_lwmac_get_reschedule(netif)) { lwmac_update(netif); } }