-
Notifications
You must be signed in to change notification settings - Fork 2k
How to implement a `ng_netdev` enabled device
The following sections describe how to implement a ng_netdev
enabled device.
-
(implementation of
driver.add_event_callback
) -
the implementation is pretty much always the same:
if ((dev == NULL) || (dev->driver != &ng_tapnet_driver)) { return -ENODEV; } if (dev->event_cb != NULL) { return -ENOBUFS; } dev->event_cb = cb; return 0;
-
(implementation of
driver.rem_event_callback
) -
the implementation is pretty much always the same:
if ((dev == NULL) || (dev->driver != &ng_tapnet_driver)) { return -ENODEV; } if (dev->event_cb != NULL) { return -ENOBUFS; } dev->event_cb = cb; return 0;
-
in interrupt handler of driver:
-
determine event type
event_type
- value can be chosen by driver
- not necessarily bound to
ng_netdev_event_t
-
determine device
dev
-
send message
msg
todev->mac_pid
(event handler thread) withmsg.type == NG_NETDEV_MSG_TYPE_EVENT msg.content.value = event_type msg_send(&msg, dev->mac_pid);
-
-
in thread
dev->mac_pid
(dev
is known by event handler thread):msg_receive(&msg); switch (msg.type) { case NG_NETDEV_MSG_TYPE_EVENT: dev->driver->isr_event(dev, msg.content.value); break; /* ... */ }
-
in
driver.isr_event(dev, event_type)
:- check
dev
(dev != NULL
anddev->driver == &driver
) - call event handlers
_event_<event_type>()
for event according to event
- check
-
FAQ:
- TODO
TODO
-
read received data
data
(of lengthdata_len
) from device -
add
ng_netif_hdr_t
with both sourcel2src
(of lengthl2src_len
) and destination addressl2_dest
(of lengthl2dst_len
) tong_pktbuf
ng_pktsnip_t *hdr_snip = ng_pktbuf_add(NULL, NULL, sizeof(ng_netif_hdr_t) + l2src_len + l2dst_len, NG_NETTYPE_UNDEF); if (hdr_snip == NULL) { DEBUG("Packet buffer full.\n"); return; } ng_netif_hdr_t *hdr = hdr_snip->data; ng_netif_hdr_init(hdr, l2src_len, l2dst_len); ng_netif_hdr_set_src_addr(hdr, l2src, l2src_len); ng_netif_hdr_set_src_addr(hdr, l2dst, l2dst_len); hdr->if_pid = thread_getpid(); hdr->rssi = l2rssi; hdr->lqi = l2lqi;
-
determine demultiplexing type
demux_type
(e.g. via Ethertype with Ethernet devices) if available -
otherwise
demux_type
can be a fixed value (e.g.NG_NETTYPE_SIXLOWPAN
for IEEE 802.15.4 devices) -
copy payload of received packet into packet buffer
ng_nettype_t demux_type = NG_NETTYPE_UNDEF; switch (ether_type) { #ifdef MODULE_NG_IPV6 case ETHER_TYPE_IPV6: demux_type = NG_NETTYPE_IPV6; break; #endif default: break; } pkt = ng_pktbuf_add(pkt, data + L2_HDR_LEN, data_len, demux_type); if (pkt == NULL) { DEBUG("Packet buffer full.\n"); ng_pktbuf_release(hdr_snip); return; }
-
call callback event handler with
pkt
as argument if available:if (dev->event_cb) { dev->event_cb(NETDEV_EVENT_RX_COMPLETE, pkt); } else { ng_pktbuf_release(pkt); }
-
release packet also in other error case, no one else will clean-up your mess 😉
-
FAQ:
- TODO
TODO
TODO
-
(implementation of
driver.send_data
) -
check if
pkt != NULL
, return-EFAULT
on failure -
check
dev
(dev != NULL
anddev->driver == &driver
)- on failure: release
pkt
return-ENODEV
- on failure: release
-
build device header from
netif_hdr
(is first header inpkt
) -
put device header in out buffer
-
put rest of
pkt
out bufferout_buf
(may also be SPI buffer or similar)ng_pktsnip_t *ptr = pkt->next; int nwrite = L2_HDR_LEN; while (ptr) { memcpy(out_buf + nwrite, ptr->data, ptr->size); if (nwrite > OUT_BUF_SIZE) { ng_pktbuf_release(pkt); return -ENOBUFS; } ptr = ptr->next; } ng_pktbuf_release(pkt);
-
send content of out buffer
-
release packet also in other error case, no one else will clean-up your mess 😉
-
FAQ:
- TODO
- (implementation of
driver.get
) - check
dev
(dev != NULL
anddev->driver == &driver
), return -ENODEV on failure - check if getting of
opt
is supported, return-ENOSUP
on failure - check if
*value_len
is appropriate foropt
, return -EOVERFLOW on failure- use
*value_len < sizeof(option_type)
for array like options (like addresses) - use
*value_len != sizeof(option_type)
for primitive types
- use
- set
*value_len
tosizeof(option_type)
- copy
option_value
intovalue
- return length of parameter on success
-
FAQ:
- TODO
- (implementation of
driver.get
) - check
dev
(dev != NULL
anddev->driver == &driver
), return -ENODEV on failure - check if setting of
opt
is supported, return-ENOSUP
on failure - check if
*value_len
is appropriate foropt
, return -EOVERFLOW on failure- use
*value_len < sizeof(option_type)
for array like options (like addresses) - use
*value_len != sizeof(option_type)
for primitive types
- use
- set
*value_len
tosizeof(option_type)
- copy
option_value
intovalue
- return length of parameter on success
-
FAQ:
- TODO