-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
network: Add SCSI ethernet support, emulating a Dayna SCSI/Link
Add SCSI commands to start a WiFi scan, check status, and get SSID list For some reason trying to use command IDs in the vendor range (0xc0-0xf0) result in errors on the bus
- Loading branch information
Showing
11 changed files
with
881 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
283 changes: 283 additions & 0 deletions
283
lib/BlueSCSI_platform_RP2040/BlueSCSI_platform_network.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
/* | ||
* Copyright (c) 2023 joshua stein <jcs@jcs.org> | ||
* | ||
* Permission to use, copy, modify, and distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
|
||
#include "BlueSCSI_platform.h" | ||
#include "BlueSCSI_log.h" | ||
#include "BlueSCSI_config.h" | ||
#include <scsi.h> | ||
#include <network.h> | ||
|
||
extern "C" { | ||
|
||
#include <cyw43.h> | ||
#include <pico/cyw43_arch.h> | ||
|
||
#ifndef CYW43_IOCTL_GET_RSSI | ||
#define CYW43_IOCTL_GET_RSSI (0xfe) | ||
#endif | ||
|
||
// A default DaynaPort-compatible MAC | ||
static const char defaultMAC[] = { 0x00, 0x80, 0x19, 0xc0, 0xff, 0xee }; | ||
|
||
static bool network_in_use = false; | ||
|
||
bool platform_network_supported() | ||
{ | ||
/* from cores/rp2040/RP2040Support.h */ | ||
#if !defined(ARDUINO_RASPBERRY_PI_PICO_W) | ||
return false; | ||
#else | ||
extern bool __isPicoW; | ||
return __isPicoW; | ||
#endif | ||
} | ||
|
||
int platform_network_init(char *mac, char *ssid, char *password) | ||
{ | ||
uint8_t tmac[6]; | ||
int ret; | ||
|
||
if (!platform_network_supported()) | ||
return -1; | ||
|
||
memset(wifi_network_list, 0, sizeof(wifi_network_list)); | ||
|
||
cyw43_deinit(&cyw43_state); | ||
|
||
if (mac == NULL || (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0)) { | ||
mac = (char *)&defaultMAC; | ||
memcpy(scsiDev.boardCfg.wifiMACAddress, mac, sizeof(scsiDev.boardCfg.wifiMACAddress)); | ||
} | ||
|
||
// XXX: this requires libpico to be compiled with CYW43_USE_OTP_MAC=0 | ||
memcpy(cyw43_state.mac, mac, sizeof(cyw43_state.mac)); | ||
|
||
cyw43_arch_enable_sta_mode(); | ||
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, (uint8_t *)&tmac); | ||
|
||
log(" "); | ||
log("=== Network Initialization"); | ||
|
||
log_f("WiFi MAC is %02X:%02X:%02X:%02X:%02X:%02X", tmac[0], tmac[1], tmac[2], tmac[3], tmac[4], tmac[5]); | ||
if (memcmp(mac, tmac, sizeof(tmac)) != 0) | ||
log("WARNING: WiFi MAC is not what was requested, is libpico not compiled with CYW43_USE_OTP_MAC=0?"); | ||
|
||
#if 0 | ||
platform_network_wifi_start_scan(); | ||
while (!platform_network_wifi_scan_finished()) | ||
{ | ||
platform_network_poll(); | ||
} | ||
platform_network_wifi_dump_scan_list(); | ||
#endif | ||
|
||
if (password == NULL || password[0] == 0) | ||
{ | ||
log("Connecting to WiFi SSID \"", ssid, "\" with no authentication"); | ||
ret = cyw43_arch_wifi_connect_async(ssid, NULL, CYW43_AUTH_OPEN); | ||
} | ||
else | ||
{ | ||
log("Connecting to WiFi SSID \"", ssid, "\" with WPA/WPA2 PSK"); | ||
ret = cyw43_arch_wifi_connect_async(ssid, password, CYW43_AUTH_WPA2_MIXED_PSK); | ||
} | ||
if (ret != 0) | ||
log_f("WiFi connection failed: %d", ret); | ||
|
||
network_in_use = true; | ||
|
||
return 0; | ||
} | ||
|
||
void platform_network_poll() | ||
{ | ||
if (network_in_use) | ||
cyw43_arch_poll(); | ||
} | ||
|
||
int platform_network_send(uint8_t *buf, size_t len) | ||
{ | ||
int ret = cyw43_send_ethernet(&cyw43_state, 0, len, buf, 0); | ||
if (ret != 0) | ||
log_f("cyw43_send_ethernet failed: %d", ret); | ||
|
||
return ret; | ||
} | ||
|
||
static int platform_network_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result) | ||
{ | ||
struct wifi_network_entry *entry = NULL; | ||
|
||
if (!result || !result->ssid_len || !result->ssid[0]) | ||
return 0; | ||
|
||
for (int i = 0; i < WIFI_NETWORK_LIST_ENTRY_COUNT; i++) | ||
{ | ||
// take first available | ||
if (wifi_network_list[i].ssid[0] == '\0') | ||
{ | ||
entry = &wifi_network_list[i]; | ||
break; | ||
} | ||
// or if we've seen this network before, use this slot | ||
else if (strcmp((char *)result->ssid, wifi_network_list[i].ssid) == 0) | ||
{ | ||
entry = &wifi_network_list[i]; | ||
break; | ||
} | ||
} | ||
|
||
if (!entry) { | ||
// no available slots, insert according to our RSSI | ||
for (int i = 0; i < WIFI_NETWORK_LIST_ENTRY_COUNT; i++) | ||
{ | ||
if (result->rssi > wifi_network_list[i].rssi) | ||
{ | ||
// shift everything else down | ||
for (int j = WIFI_NETWORK_LIST_ENTRY_COUNT - 1; j > i; j--) | ||
wifi_network_list[j] = wifi_network_list[j - 1]; | ||
|
||
entry = &wifi_network_list[i]; | ||
memset(entry, 0, sizeof(struct wifi_network_entry)); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (entry == NULL) | ||
return 0; | ||
|
||
if (entry->rssi == 0 || result->rssi > entry->rssi) | ||
{ | ||
entry->channel = result->channel; | ||
entry->rssi = result->rssi; | ||
} | ||
if (result->auth_mode & 7) | ||
entry->flags = WIFI_NETWORK_FLAGS_AUTH; | ||
strncpy(entry->ssid, (const char *)result->ssid, sizeof(entry->ssid)); | ||
entry->ssid[sizeof(entry->ssid) - 1] = '\0'; | ||
memcpy(entry->bssid, result->bssid, sizeof(entry->bssid)); | ||
|
||
return 0; | ||
} | ||
|
||
int platform_network_wifi_start_scan() | ||
{ | ||
if (cyw43_wifi_scan_active(&cyw43_state)) | ||
return -1; | ||
|
||
cyw43_wifi_scan_options_t scan_options = { 0 }; | ||
memset(wifi_network_list, 0, sizeof(wifi_network_list)); | ||
return cyw43_wifi_scan(&cyw43_state, &scan_options, NULL, platform_network_wifi_scan_result); | ||
} | ||
|
||
int platform_network_wifi_scan_finished() | ||
{ | ||
return !cyw43_wifi_scan_active(&cyw43_state); | ||
} | ||
|
||
void platform_network_wifi_dump_scan_list() | ||
{ | ||
struct wifi_network_entry *entry = NULL; | ||
|
||
for (int i = 0; i < WIFI_NETWORK_LIST_ENTRY_COUNT; i++) | ||
{ | ||
entry = &wifi_network_list[i]; | ||
|
||
if (entry->ssid[0] == '\0') | ||
break; | ||
|
||
log_f("wifi[%d] = %s, channel %d, rssi %d, bssid %02x:%02x:%02x:%02x:%02x:%02x, flags %d", | ||
i, entry->ssid, entry->channel, entry->rssi, | ||
entry->bssid[0], entry->bssid[1], entry->bssid[2], | ||
entry->bssid[3], entry->bssid[4], entry->bssid[5], | ||
entry->flags); | ||
} | ||
} | ||
|
||
int platform_network_wifi_rssi() | ||
{ | ||
int32_t rssi = 0; | ||
|
||
cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_RSSI, sizeof(rssi), (uint8_t *)&rssi, CYW43_ITF_STA); | ||
return rssi; | ||
} | ||
|
||
char * platform_network_wifi_ssid() | ||
{ | ||
struct ssid_t { | ||
uint32_t ssid_len; | ||
uint8_t ssid[32 + 1]; | ||
} ssid; | ||
static char cur_ssid[32 + 1]; | ||
|
||
memset(cur_ssid, 0, sizeof(cur_ssid)); | ||
|
||
int ret = cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_SSID, sizeof(ssid), (uint8_t *)&ssid, CYW43_ITF_STA); | ||
if (ret) | ||
{ | ||
log_f("Failed getting WiFi SSID: %d", ret); | ||
return NULL; | ||
} | ||
|
||
ssid.ssid[sizeof(ssid.ssid) - 1] = '\0'; | ||
if (ssid.ssid_len < sizeof(ssid.ssid)) | ||
ssid.ssid[ssid.ssid_len] = '\0'; | ||
|
||
strlcpy(cur_ssid, (char *)ssid.ssid, sizeof(cur_ssid)); | ||
return cur_ssid; | ||
} | ||
|
||
char * platform_network_wifi_bssid() | ||
{ | ||
static char bssid[6]; | ||
|
||
memset(bssid, 0, sizeof(bssid)); | ||
|
||
/* TODO */ | ||
|
||
return bssid; | ||
} | ||
|
||
int platform_network_wifi_channel() | ||
{ | ||
int32_t channel = 0; | ||
|
||
cyw43_ioctl(&cyw43_state, CYW43_IOCTL_GET_CHANNEL, sizeof(channel), (uint8_t *)&channel, CYW43_ITF_STA); | ||
return channel; | ||
} | ||
|
||
// these override weakly-defined functions in pico-sdk | ||
|
||
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) | ||
{ | ||
scsiNetworkEnqueue(buf, len); | ||
} | ||
|
||
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) | ||
{ | ||
log_f("Disassociated from WiFi SSID %s", self->ap_ssid); | ||
} | ||
|
||
void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) | ||
{ | ||
char *ssid = platform_network_wifi_ssid(); | ||
|
||
if (ssid) | ||
log_f("Successfully connected to WiFi SSID \"%s\"", ssid); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.