blob: 0aa1881730265e636dded5ae26bb569a61149a28 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdlib.h>
#include <string.h>
#define _ALL_SOURCE
#include <threads.h>
#include <ddk/binding.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <wlan/protocol/if-impl.h>
#include <zircon/types.h>
wlanif_impl_ifc_t wlanif_ifc = {};
void* wlanif_cookie = NULL;
zx_device_t* global_device;
uint64_t scan_txn_id;
zx_status_t wlanif_start(void* ctx, wlanif_impl_ifc_t* ifc, void* cookie) {
printf("***** wlanif_start called\n");
memcpy(&wlanif_ifc, ifc, sizeof(wlanif_ifc));
wlanif_cookie = cookie;
return ZX_OK;
}
void wlanif_stop(void* ctx) {}
#define MAX_SSID_LEN 100
wlanif_bss_description_t scan_results[] = {
{.bssid = {11, 22, 33, 44, 55, 66},
.ssid.data = {'F', 'a', 'k', 'e', ' ', 'A', 'P', ' ', '1'},
.ssid.len = 9,
.bss_type = WLAN_BSS_TYPE_INFRASTRUCTURE,
.beacon_period = 1,
.dtim_period = 1,
.timestamp = 0,
.local_time = 0,
.num_rates = 12,
.rates = {128 + 2, 128 + 4, 128 + 11, 128 + 22, 12, 18, 24, 36, 48, 72, 96, 108},
.rsne_len = 0,
.chan = {.primary = 4, .cbw = CBW20, .secondary80 = 0}}};
#define NUM_SCAN_RESULTS countof(scan_results)
int fake_scan_results(void* arg) {
printf("***** faking scan results!\n");
for (unsigned int iter = 0; iter < NUM_SCAN_RESULTS; iter++) {
zx_nanosleep(zx_deadline_after(ZX_MSEC(200)));
wlanif_scan_result_t scan_result;
scan_result.txn_id = scan_txn_id;
scan_result.bss = scan_results[iter];
wlanif_ifc.on_scan_result(wlanif_cookie, &scan_result);
}
zx_nanosleep(zx_deadline_after(ZX_MSEC(200)));
wlanif_scan_end_t scan_end = {.txn_id = scan_txn_id, .code = WLAN_SCAN_RESULT_SUCCESS};
wlanif_ifc.on_scan_end(wlanif_cookie, &scan_end);
return 0;
}
void wlanif_start_scan(void* ctx, wlanif_scan_req_t* req) {
printf("***** starting scan (txn_id = %lu)!!!\n", req->txn_id);
scan_txn_id = req->txn_id;
thrd_t scan_thrd;
thrd_create_with_name(&scan_thrd, fake_scan_results, NULL, "wlanif-test-fake-scan");
return;
}
void wlanif_join_req(void* ctx, wlanif_join_req_t* req) {
printf("***** join_req\n");
wlanif_join_confirm_t conf = {.result_code = WLAN_JOIN_RESULT_SUCCESS};
wlanif_ifc.join_conf(wlanif_cookie, &conf);
}
void wlanif_auth_req(void* ctx, wlanif_auth_req_t* req) {
printf("***** auth_req\n");
wlanif_auth_confirm_t conf;
memcpy(conf.peer_sta_address, req->peer_sta_address, ETH_ALEN);
conf.auth_type = req->auth_type;
conf.result_code = WLAN_AUTH_RESULT_SUCCESS;
wlanif_ifc.auth_conf(wlanif_cookie, &conf);
}
void wlanif_auth_resp(void* ctx, wlanif_auth_resp_t* ind) {
printf("***** auth_ind\n");
}
void wlanif_deauth_req(void* ctx, wlanif_deauth_req_t* req) {
printf("***** deauth_req\n");
}
void wlanif_assoc_req(void* ctx, wlanif_assoc_req_t* req) {
printf("***** assoc_req\n");
wlanif_assoc_confirm_t conf;
conf.result_code = WLAN_ASSOC_RESULT_SUCCESS;
conf.association_id = 0;
wlanif_ifc.assoc_conf(wlanif_cookie, &conf);
}
void wlanif_assoc_resp(void* ctx, wlanif_assoc_resp_t* ind) {
printf("***** assoc_ind\n");
}
void wlanif_disassoc_req(void* ctx, wlanif_disassoc_req_t* req) {
printf("***** disassoc_req\n");
}
void wlanif_reset_req(void* ctx, wlanif_reset_req_t* req) {
printf("***** reset_req\n");
}
void wlanif_start_req(void* ctx, wlanif_start_req_t* req) {
printf("***** start_req\n");
}
void wlanif_stop_req(void* ctx, wlanif_stop_req_t* req) {
printf("***** stop_req\n");
}
void wlanif_set_keys_req(void* ctx, wlanif_set_keys_req_t* req) {
printf("***** set_keys_req\n");
}
void wlanif_del_keys_req(void* ctx, wlanif_del_keys_req_t* req) {
printf("***** del_keys_req\n");
}
void wlanif_eapol_req(void* ctx, wlanif_eapol_req_t* req) {
printf("***** eapol_req\n");
}
void wlanif_query(void* ctx, wlanif_query_info_t* info) {
printf("***** query\n");
memset(info, 0, sizeof(*info));
// mac_addr
uint8_t mac_addr[ETH_ALEN] = {1, 2, 3, 4, 5, 6};
memcpy(info->mac_addr, mac_addr, ETH_ALEN);
// role
info->role = WLAN_MAC_ROLE_CLIENT;
// features
info->features = 0;
// num_bands
info->num_bands = 1;
// basic_rates
const uint16_t basic_rates[] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
static_assert(countof(basic_rates) <= WLAN_BASIC_RATES_MAX_LEN, "too many basic rates");
size_t num_rates = countof(basic_rates);
info->bands[0].num_basic_rates = num_rates;
memcpy(info->bands[0].basic_rates, basic_rates, sizeof(basic_rates));
// base_frequency
info->bands[0].base_frequency = 2407;
// channels
const uint8_t channels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
static_assert(countof(channels) <= WLAN_CHANNELS_MAX_LEN, "too many channels");
size_t num_channels = countof(channels);
info->bands[0].num_channels = num_channels;
memcpy(info->bands[0].channels, channels, sizeof(channels));
}
zx_status_t wlanif_data_queue_tx(void* ctx, uint32_t options, ethmac_netbuf_t* netbuf) {
printf("***** data_queue_tx\n");
return ZX_OK;
}
wlanif_impl_protocol_ops_t wlanif_impl_ops = {
.start = wlanif_start,
.stop = wlanif_stop,
.query = wlanif_query,
.start_scan = wlanif_start_scan,
.join_req = wlanif_join_req,
.auth_req = wlanif_auth_req,
.auth_resp = wlanif_auth_resp,
.deauth_req = wlanif_deauth_req,
.assoc_req = wlanif_assoc_req,
.assoc_resp = wlanif_assoc_resp,
.disassoc_req = wlanif_disassoc_req,
.reset_req = wlanif_reset_req,
.start_req = wlanif_start_req,
.stop_req = wlanif_stop_req,
.set_keys_req = wlanif_set_keys_req,
.del_keys_req = wlanif_del_keys_req,
.eapol_req = wlanif_eapol_req,
.data_queue_tx = wlanif_data_queue_tx,
};
static zx_protocol_device_t device_ops = {
.version = DEVICE_OPS_VERSION,
};
zx_status_t dev_bind(void* ctx, zx_device_t* device) {
static bool first = true;
if (!first) { return ZX_ERR_ALREADY_BOUND; }
first = false;
static device_add_args_t args = {
.version = DEVICE_ADD_ARGS_VERSION,
.name = "wlanif-test",
.ctx = NULL,
.ops = &device_ops,
.proto_id = ZX_PROTOCOL_WLANIF_IMPL,
.proto_ops = &wlanif_impl_ops,
};
return device_add(device, &args, &global_device);
}
zx_status_t dev_init(void** out_ctx) {
return ZX_OK;
}
void dev_release(void* ctx) {}
static zx_driver_ops_t wlanif_test_driver_ops = {
.version = DRIVER_OPS_VERSION,
.init = dev_init,
.bind = dev_bind,
.release = dev_release,
};
// clang-format off
ZIRCON_DRIVER_BEGIN(wlanif-test, wlanif_test_driver_ops, "fuchsia", "0.1", 1)
BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_TEST_PARENT),
ZIRCON_DRIVER_END(wlanif-test)
// clang-format on