Skip to content
main.c 3.34 KiB
Newer Older
#include <mutek/printk.h>
#include <mutek/startup.h>
#include <device/resources.h>
#include <device/device.h>
#include <device/driver.h>
#include <device/irq.h>
#include <hexo/endian.h>

#include <device/class/gpio.h>
#include <device/class/net.h>
#include <net/layer.h>
#include <net/layer/ethernet.h>
#include <inet/layer/ipv4.h>
#include <inet/layer/icmp.h>
#include <inet/protocol/ip.h>
#include <net/scheduler.h>
#define MTU 128

struct app_s
{
  struct device_net_s net;
  struct net_scheduler_s scheduler;
  struct buffer_pool_s packet_pool;
  struct net_layer_s *eth;
  struct net_layer_s *ipv4;
  struct net_layer_s *icmp;
};

static
void eth_link_changed(void *delegate, struct net_layer_s *layer, bool_t connected)
  struct app_s *app = delegate;

  printk("Ethernet link now %s\n", connected ? "up" : "down");
}
static
void eth_destroyed(void *delegate, struct net_layer_s *layer)
{
  struct app_s *app = delegate;
  printk("%s\n", __FUNCTION__);
  assert(app->eth == layer);
  app->eth = NULL;
static
void ipv4_destroyed(void *delegate, struct net_layer_s *layer)
  struct app_s *app = delegate;

  printk("%s\n", __FUNCTION__);

  assert(app->ipv4 == layer);
  app->ipv4 = NULL;
static
void icmp_destroyed(void *delegate, struct net_layer_s *layer)
  struct app_s *app = delegate;

  printk("%s\n", __FUNCTION__);

  assert(app->icmp == layer);
  app->icmp = NULL;
static
SLAB_GROW(packet_pool_grow)
    return 5;
}

static const struct net_ethernet_delegate_vtable_s eth_delegate_vtable = {
  .base.release = eth_destroyed,
  .link_changed = eth_link_changed,
};
static const struct net_layer_delegate_vtable_s ipv4_delegate_vtable = {
  .release = ipv4_destroyed,
};

static const struct net_layer_delegate_vtable_s icmp_delegate_vtable = {
  .release = icmp_destroyed,
};

void app_start()
{
  error_t err;
  struct app_s *app;

  app = mem_alloc(sizeof(*app), mem_scope_sys);
  if (!app) {
    printk("Failed to create app context\n");
    return;
  }

  err = device_get_accessor_by_path(&app->net.base, NULL, "eth*", DRIVER_CLASS_NET);
  if (err) {
    printk("Failed to get Ethernet device\n");
    return;
  }

  buffer_pool_init(&app->packet_pool, MTU, packet_pool_grow, mem_scope_sys);

  err = net_scheduler_init(&app->scheduler, &app->packet_pool, "timer* rtc*");
  if (err) {
    printk("Error while initializing net scheduler: %d\n", err);
    return;
  }

  err = DEVICE_OP(&app->net, layer_create, &app->scheduler,
                  NET_LAYER_ETHERNET, NULL,
                  app, &eth_delegate_vtable.base,
                  &app->eth);
  if (err) {
    printk("Error while creating Ethernet layer: %d\n", err);
    return;
  }

  err = inet_ipv4_create(&app->scheduler, app, &ipv4_delegate_vtable, &app->ipv4);
  if (err) {
    printk("Error while creating ipv4 layer: %d\n", err);
    return;
  }

  err = net_layer_bind(app->eth, NULL, app->ipv4);
  if (err) {
    printk("Unable to bind ipv4 layer above ethernet: %d\n", err);
    return;
  }

  net_layer_refdec(app->ipv4);

  err = inet_icmp_create(&app->scheduler, app, &icmp_delegate_vtable, &app->icmp);
  if (err) {
    printk("Error while creating icmp layer: %d\n", err);
    return;
  }

  err = net_layer_bind(app->ipv4, (const uint8_t[]){ INET_IP_PROTO_ICMP }, app->icmp);
  if (err) {
    printk("Unable to bind icmp layer above ethernet: %d\n", err);
    return;
  }

  net_layer_refdec(app->icmp);