diff --git a/kernel-src/include/kernel/net.h b/kernel-src/include/kernel/net.h index 6be9bb8a..4d52a571 100644 --- a/kernel-src/include/kernel/net.h +++ b/kernel-src/include/kernel/net.h @@ -33,6 +33,7 @@ typedef struct { #define NETDEV_FLAGS_DEBUG 0x4 #define NETDEV_FLAGS_LOOPBACK 0x8 #define NETDEV_FLAGS_RUNNING 0x40 +#define NETDEV_FLAGS_WLAN 0x80 typedef struct netdev_t { mac_t mac; diff --git a/kernel-src/include/kernel/wlan.h b/kernel-src/include/kernel/wlan.h new file mode 100644 index 00000000..a6195606 --- /dev/null +++ b/kernel-src/include/kernel/wlan.h @@ -0,0 +1,8 @@ +#ifndef _WLAN_H +#define _WLAN_H + +#include + +int wlan_register(void *handle, const u80211_drv_device_metadata_t *metadata, const u80211_drv_device_ops_t *ops, u80211_drv_network_device_handle_t *network_device); + +#endif diff --git a/kernel-src/io/net/u80211_drv/kernel_interface.c b/kernel-src/io/net/u80211_drv/kernel_interface.c index 2e6c8c38..c4b4622f 100644 --- a/kernel-src/io/net/u80211_drv/kernel_interface.c +++ b/kernel-src/io/net/u80211_drv/kernel_interface.c @@ -253,8 +253,7 @@ int u80211_drv_kernel_submit_bulk_xfer_and_wait(u80211_drv_device_handle_t opaqu } int u80211_drv_device_ready(void *device, const u80211_drv_device_metadata_t *metadata, const u80211_drv_device_ops_t *ops, u80211_drv_network_device_handle_t *network_device) { - printf("device ready\n"); - return 0; + return wlan_register(device, metadata, ops, network_device) ? U80211_DRV_STATUS_UNKNOWN_ERROR : U80211_DRV_STATUS_SUCCESS; } void u80211_drv_packet_received(u80211_drv_network_device_handle_t device, void *packet, size_t packet_size) { diff --git a/kernel-src/io/net/wlan.c b/kernel-src/io/net/wlan.c new file mode 100644 index 00000000..7f72c6e5 --- /dev/null +++ b/kernel-src/io/net/wlan.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include + +typedef struct { + netdev_t netdev; + void *driver_handle; + u80211_device_t *u80211_device; + const u80211_drv_device_ops_t *ops; + int id; +} wlan_device_t; + +// TODO: in u80211, change the device ops to take a (void *) handle +// TODO: general netdev cleanup: +// - use struct ops instead of having function pointers in netdev struct +// - proper initialize() function +// - proper destroy() function + +static uint64_t id_bitmap; +static int allocate_id(void) { + for (;;) { + uint64_t snapshot = __atomic_load_n(&id_bitmap, __ATOMIC_RELAXED); + if (snapshot == UINT64_MAX) + return -1; + + int id = __builtin_ctz(~snapshot); + uint64_t mask = 1lu << id; + if (__atomic_fetch_or(&id_bitmap, mask, __ATOMIC_RELAXED) & mask) + continue; + + return id; + } +} + +static void free_id(int id) { + __atomic_fetch_and(&id_bitmap, ~(1lu << id), __ATOMIC_RELAXED); +} + + +static int allocate_tx_buffer(u80211_device_t *device, size_t size, u80211_tx_buffer_descriptor_t *buffer_descriptor) { + wlan_device_t *wlan = device->driver_data; +} + +static int free_tx_buffer(u80211_device_t *device, u80211_tx_buffer_descriptor_t *buffer_descriptor) { + wlan_device_t *wlan = device->driver_data; +} + +static int transmit(u80211_device_t *device, u80211_tx_buffer_descriptor_t *buffer_descriptor, const u80211_transmit_options_t *options) { + wlan_device_t *wlan = device->driver_data; + +} + +static int set_channel(u80211_device_t *device, int channel) { + wlan_device_t *wlan = device->driver_data; + +} + +static int set_key(u80211_device_t *device, const u80211_key_t *key) { + wlan_device_t *wlan = device->driver_data; + +} + +static int del_key(u80211_device_t *device, uint8_t index, const u80211_mac_address_t *peer, uint32_t flags) { + wlan_device_t *wlan = device->driver_data; + +} + +static u80211_device_ops_t ops = { + .allocate_tx_buffer = allocate_tx_buffer, + .free_tx_buffer = free_tx_buffer, + .transmit = transmit, + .set_channel = set_channel, + .set_key = set_key, + .del_key = del_key +}; + +static int wlan_alloc_desc(netdev_t *netdev, size_t requestedsize, netdesc_t *desc) { + +} + +static int wlan_free_desc(netdev_t *netdev, netdesc_t *desc) { + +} + +static int wlan_send_packet(netdev_t *_internal, netdesc_t desc, mac_t targetmac, int proto) { + +} + +int wlan_register(void *handle, const u80211_drv_device_metadata_t *drv_metadata, const u80211_drv_device_ops_t *drv_ops, u80211_drv_network_device_handle_t *network_device) { + wlan_device_t *wlan = alloc(sizeof(wlan_device_t)); + if (wlan == NULL) + return ENOMEM; + + wlan->driver_handle = handle; + wlan->ops = drv_ops; + + wlan->netdev.mtu = 1500; + wlan->netdev.sendpacket = wlan_send_packet; + wlan->netdev.allocdesc = wlan_alloc_desc; + wlan->netdev.freedesc = wlan_free_desc; + wlan->netdev.flags = NETDEV_FLAGS_WLAN; + memcpy(&wlan->netdev.mac, &drv_metadata->mac_address, 6); + if (hashtable_init(&wlan->netdev.arpcache, 30)) { + free(wlan); + return ENOMEM; + } + + wlan->id = allocate_id(); + if (wlan->id == -1) { + hashtable_destroy(&wlan->netdev.arpcache); + free(wlan); + return EAGAIN; + } + + u80211_device_metadata_t metadata; + memcpy(&metadata.mac_address, &drv_metadata->mac_address, sizeof(metadata.mac_address)); + memcpy(&metadata.rate_bitmap, &drv_metadata->rate_bitmap, sizeof(metadata.rate_bitmap)); + + int status = u80211_register_device(&metadata, &ops, wlan, &wlan->u80211_device); + if (status != U80211_STATUS_SUCCESS) { + free_id(wlan->id); + hashtable_destroy(&wlan->netdev.arpcache); + free(wlan); + return EINVAL; + } + + char name[10]; + snprintf(name, 10, "wlan%d", wlan->id); + int error = netdev_register(&wlan->netdev, name); + if (error) { + u80211_unregister_device(wlan->u80211_device); + free_id(wlan->id); + hashtable_destroy(&wlan->netdev.arpcache); + free(wlan); + } + return error; +}