/*
dload - Dot command for downloading files on the Spectrum Next
Copyright (C) 2025 Ian Cowburn (ianc@noddybox.co.uk)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
--------------------------------------------------------------------------
Wifi interface
*/
#include
#include
#include
#include
#include "wifi.h"
#define MAX_PROTOCOL_LEN 10
#define MAX_HOSTNAME_LEN 255
#define MAX_PATH_LEN 255
/* ---------------------------------------- PRIVATE ROUTINES
*/
static WifiStatus SendToModem(const char *buffer, size_t len)
{
while(len)
{
WifiStatus status;
if ((status = SendByte(*buffer)) != eWifiOK)
{
return status;
}
buffer++;
len--;
}
return eWifiOK;
}
static WifiStatus ConnectToModem(void)
{
return eWifiTimeout;
}
static void Copy(const char *from, const char *to, char *buff, size_t maxlen)
{
while(maxlen && ((to && from != to) || (!to && *from)))
{
*buff++ = *from++;
maxlen--;
}
if (maxlen)
{
*buff = 0;
}
else
{
*--buff = 0;
}
}
static int ParseURL(const char *url,
char *hostname,
char *path,
int *port,
int *ssl)
{
char protocol[MAX_PROTOCOL_LEN];
const char *double_slash;
const char *colon;
const char *slash;
double_slash = strstr(url, "//");
if (double_slash && double_slash != url)
{
Copy(url, double_slash - 1, protocol, MAX_PROTOCOL_LEN);
}
else
{
strcpy(protocol, "http");
}
colon = strchr(double_slash ? double_slash + 2 : url, ':');
slash = strchr(double_slash ? double_slash + 2 : url, '/');
if (colon)
{
char buff[10];
Copy(colon + 1, slash, buff, 10);
*port = atoi(buff);
Copy(double_slash ? double_slash + 2 : url, colon,
hostname, MAX_HOSTNAME_LEN);
}
else
{
if (strcmp(protocol, "http") == 0)
{
*port = 80;
}
else if (strcmp(protocol, "https") == 0)
{
*port = 443;
}
else
{
return 0;
}
Copy(double_slash ? double_slash + 2 : url, slash,
hostname, MAX_HOSTNAME_LEN);
}
*ssl = (strcmp(protocol, "https") == 0);
if (slash)
{
Copy(slash, NULL, path, MAX_PATH_LEN);
}
else
{
strcpy(path, "/");
}
if (!hostname[0])
{
return 0;
}
return 1;
}
static void Chomp(char *p)
{
size_t l = strlen(p);
while(l && (p[l - 1] == '\r' || p[l - 1] == '\n'))
{
p[--l] = 0;
}
}
static WifiStatus ReadLine(char *buff, size_t maxlen)
{
size_t len = 0;
WifiStatus status;
unsigned char c;
while(len < maxlen && ((status = GetByte(&c)) == eWifiOK))
{
buff[len++] = c;
buff[len] = 0;
if (len > 1)
{
if (buff[len - 1] == '\n' && buff[len - 2] == '\r')
{
Chomp(buff);
return eWifiOK;
}
}
}
return eWifiFailedToReceive;
}
static WifiStatus SendATCommand(const char *command)
{
char line[80];
WifiStatus status;
if((status = SendToModem(command, strlen(command))) != eWifiOK)
{
return status;
}
if((status = ReadLine(line, sizeof line)) != eWifiOK)
{
return status;
}
return strcmp("OK", line) == 0 ? eWifiOK : eWifiFailedToSendCommand;
}
/* ---------------------------------------- PUBLIC ROUTINES
*/
WifiStatus WifiConnect(void)
{
return ConnectToModem();
}
WifiStatus ConnectURL(int is_post, const char *url, size_t *content_length)
{
char hostname[MAX_HOSTNAME_LEN];
char path[MAX_PATH_LEN];
int port;
int ssl;
WifiStatus status;
if (!ParseURL(url, hostname, path, &port, &ssl))
{
return eWifiInvalidURL;
}
if ((status = SendATCommand("AT+CIPMUX=0\r\n")) != eWifiOK)
{
return status;
}`
return eWifiTimeout;
}
WifiStatus SendFormatted(const char *format, ...)
{
char buff[256];
va_list va;
va_start(va, format);
vsnprintf(buff, sizeof buff, format, va);
va_end(va);
return SendToModem(buff, strlen(buff));
}
WifiStatus SendByte(unsigned char c)
{
return eWifiTimeout;
}
WifiStatus GetByte(unsigned char *c)
{
*c = 0;
return eWifiTimeout;
}
/*
vim: ai sw=4 ts=8 expandtab
*/