esp_netif_driver.rst 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. ESP-NETIF Custom I/O Driver
  2. ===========================
  3. This section outlines implementing a new I/O driver with esp-netif connection capabilities.
  4. By convention the I/O driver has to register itself as an esp-netif driver and thus holds a dependency on esp-netif component
  5. and is responsible for providing data path functions, post-attach callback and in most cases also default event handlers to define network interface
  6. actions based on driver's lifecycle transitions.
  7. Packet input/output
  8. ^^^^^^^^^^^^^^^^^^^
  9. As shown in the diagram, the following three API functions for the packet data path must be defined for connecting with esp-netif:
  10. * :cpp:func:`esp_netif_transmit()`
  11. * :cpp:func:`esp_netif_free_rx_buffer()`
  12. * :cpp:func:`esp_netif_receive()`
  13. The first two functions for transmitting and freeing the rx buffer are provided as callbacks, i.e. they get called from
  14. esp-netif (and its underlying TCP/IP stack) and I/O driver provides their implementation.
  15. The receiving function on the other hand gets called from the I/O driver, so that the driver's code simply calls :cpp:func:`esp_netif_receive()`
  16. on a new data received event.
  17. Post attach callback
  18. ^^^^^^^^^^^^^^^^^^^^
  19. A final part of the network interface initialization consists of attaching the esp-netif instance to the I/O driver, by means
  20. of calling the following API:
  21. .. code:: c
  22. esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle);
  23. It is assumed that the ``esp_netif_iodriver_handle`` is a pointer to driver's object, a struct derived from ``struct esp_netif_driver_base_s``,
  24. so that the first member of I/O driver structure must be this base structure with pointers to
  25. * post-attach function callback
  26. * related esp-netif instance
  27. As a consequence the I/O driver has to create an instance of the struct per below:
  28. .. code:: c
  29. typedef struct my_netif_driver_s {
  30. esp_netif_driver_base_t base; /*!< base structure reserved as esp-netif driver */
  31. driver_impl *h; /*!< handle of driver implementation */
  32. } my_netif_driver_t;
  33. with actual values of ``my_netif_driver_t::base.post_attach`` and the actual drivers handle ``my_netif_driver_t::h``.
  34. So when the :cpp:func:`esp_netif_attach()` gets called from the initialization code, the post-attach callback from I/O driver's code
  35. gets executed to mutually register callbacks between esp-netif and I/O driver instances. Typically the driver is started
  36. as well in the post-attach callback. An example of a simple post-attach callback is outlined below:
  37. .. code:: c
  38. static esp_err_t my_post_attach_start(esp_netif_t * esp_netif, void * args)
  39. {
  40. my_netif_driver_t *driver = args;
  41. const esp_netif_driver_ifconfig_t driver_ifconfig = {
  42. .driver_free_rx_buffer = my_free_rx_buf,
  43. .transmit = my_transmit,
  44. .handle = driver->driver_impl
  45. };
  46. driver->base.netif = esp_netif;
  47. ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
  48. my_driver_start(driver->driver_impl);
  49. return ESP_OK;
  50. }
  51. Default handlers
  52. ^^^^^^^^^^^^^^^^
  53. I/O drivers also typically provide default definitions of lifecycle behaviour of related network interfaces based
  54. on state transitions of I/O drivers. For example *driver start* ``->`` *network start*, etc.
  55. An example of such a default handler is provided below:
  56. .. code:: c
  57. esp_err_t my_driver_netif_set_default_handlers(my_netif_driver_t *driver, esp_netif_t * esp_netif)
  58. {
  59. driver_set_event_handler(driver->driver_impl, esp_netif_action_start, MY_DRV_EVENT_START, esp_netif);
  60. driver_set_event_handler(driver->driver_impl, esp_netif_action_stop, MY_DRV_EVENT_STOP, esp_netif);
  61. return ESP_OK;
  62. }
  63. Network stack connection
  64. ------------------------
  65. The packet data path functions for transmitting and freeing the rx buffer (defined in the I/O driver) are called from
  66. the esp-netif, specifically from its TCP/IP stack connecting layer.
  67. Note, that IDF provides several network stack configurations for the most common network interfaces, such as for the WiFi station or Ethernet.
  68. These configurations are defined in :component_file:`esp_netif/include/esp_netif_defaults.h` and should be sufficient for most network drivers.
  69. (In rare cases, expert users might want to define custom lwIP based interface layers; it is possible, but an explicit dependency to lwIP needs to be set)
  70. The following API reference outlines these network stack interaction with the esp-netif:
  71. .. include-build-file:: inc/esp_netif_net_stack.inc