drivers: wifi: simplelink: Implement offloaded getaddrinfo()
This offloads the getaddrinfo() socket operation to the simplelink WiFi driver, via a socket_offload hook. This was validated using http_get on cc3220sf_launchxl. Also implements freeaddrinfo(). Signed-off-by: Gil Pitney <gil.pitney@linaro.org>
This commit is contained in:
parent
5a42292a9e
commit
1022b85c0f
3 changed files with 114 additions and 7 deletions
|
@ -229,6 +229,7 @@ static void simplelink_iface_init(struct net_if *iface)
|
|||
#ifdef CONFIG_NET_SOCKETS_OFFLOAD
|
||||
/* Direct socket offload: */
|
||||
socket_offload_register(&simplelink_ops);
|
||||
simplelink_sockets_init();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "simplelink_log.h"
|
||||
LOG_MODULE_DECLARE(LOG_MODULE_NAME);
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
/* Define sockaddr, etc, before simplelink.h */
|
||||
#include <net/socket_offload.h>
|
||||
|
@ -15,6 +18,9 @@ LOG_MODULE_DECLARE(LOG_MODULE_NAME);
|
|||
#include <ti/drivers/net/wifi/source/driver.h>
|
||||
#include "simplelink_support.h"
|
||||
|
||||
/* Mutex for getaddrinfo() calls: */
|
||||
K_MUTEX_DEFINE(ga_mutex);
|
||||
|
||||
static int simplelink_socket(int family, int type, int proto)
|
||||
{
|
||||
int retval;
|
||||
|
@ -509,22 +515,121 @@ exit:
|
|||
return _SlDrvSetErrno(retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Later SimpleLink SDK versions implement the full getaddrinfo semantics,
|
||||
* returning potentially multiple IP addresses.
|
||||
* This version implements a simple gethostbyname() API.
|
||||
*/
|
||||
static int simplelink_getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
ARG_UNUSED(node);
|
||||
ARG_UNUSED(service);
|
||||
ARG_UNUSED(hints);
|
||||
ARG_UNUSED(res);
|
||||
_u8 sl_family = SL_AF_INET;
|
||||
unsigned long port = 0;
|
||||
int socktype = SOCK_STREAM;
|
||||
int proto = IPPROTO_TCP;
|
||||
struct addrinfo *ai;
|
||||
struct sockaddr *ai_addr;
|
||||
_i16 retval;
|
||||
_u32 ipaddr[4];
|
||||
|
||||
errno = ENOTSUP;
|
||||
return EAI_SYSTEM;
|
||||
/* Check args: */
|
||||
if (!node && !service) {
|
||||
retval = EAI_NONAME;
|
||||
goto exit;
|
||||
}
|
||||
if (service) {
|
||||
port = strtol(service, NULL, 10);
|
||||
if (port < 1 || port > USHRT_MAX) {
|
||||
retval = EAI_SERVICE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
retval = EAI_NONAME;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* See if any hints for family; otherwise, default to AF_INET. */
|
||||
if (hints) {
|
||||
/* Note: SimpleLink SDK doesn't support AF_UNSPEC: */
|
||||
sl_family = (hints->ai_family == AF_INET6 ?
|
||||
SL_AF_INET6 : SL_AF_INET);
|
||||
}
|
||||
|
||||
/* Now, try to resolve host name: */
|
||||
k_mutex_lock(&ga_mutex, K_FOREVER);
|
||||
retval = sl_NetAppDnsGetHostByName((signed char *)node, strlen(node),
|
||||
ipaddr, sl_family);
|
||||
k_mutex_unlock(&ga_mutex);
|
||||
|
||||
if (retval < 0) {
|
||||
LOG_ERR("Could not resolve name: %s, retval: %d",
|
||||
node, retval);
|
||||
retval = EAI_NONAME;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Allocate out res (addrinfo) struct. Just one. */
|
||||
*res = calloc(1, sizeof(struct addrinfo));
|
||||
ai = *res;
|
||||
if (!ai) {
|
||||
retval = EAI_MEMORY;
|
||||
goto exit;
|
||||
} else {
|
||||
/* Now, alloc the embedded sockaddr struct: */
|
||||
ai_addr = calloc(1, sizeof(struct sockaddr));
|
||||
if (!ai_addr) {
|
||||
retval = EAI_MEMORY;
|
||||
free(*res);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, fill in the fields of res (addrinfo struct): */
|
||||
ai->ai_family = (sl_family == SL_AF_INET6 ? AF_INET6 : AF_INET);
|
||||
if (hints) {
|
||||
socktype = hints->ai_socktype;
|
||||
}
|
||||
ai->ai_socktype = socktype;
|
||||
|
||||
if (socktype == SOCK_DGRAM) {
|
||||
proto = IPPROTO_UDP;
|
||||
}
|
||||
ai->ai_protocol = proto;
|
||||
|
||||
/* Fill sockaddr struct fields based on family: */
|
||||
if (ai->ai_family == AF_INET) {
|
||||
net_sin(ai_addr)->sin_family = ai->ai_family;
|
||||
net_sin(ai_addr)->sin_addr.s_addr = htonl(ipaddr[0]);
|
||||
net_sin(ai_addr)->sin_port = htons(port);
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
} else {
|
||||
net_sin6(ai_addr)->sin6_family = ai->ai_family;
|
||||
net_sin6(ai_addr)->sin6_addr.s6_addr32[0] = htonl(ipaddr[0]);
|
||||
net_sin6(ai_addr)->sin6_addr.s6_addr32[1] = htonl(ipaddr[1]);
|
||||
net_sin6(ai_addr)->sin6_addr.s6_addr32[2] = htonl(ipaddr[2]);
|
||||
net_sin6(ai_addr)->sin6_addr.s6_addr32[3] = htonl(ipaddr[3]);
|
||||
net_sin6(ai_addr)->sin6_port = htons(port);
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
ai->ai_addr = ai_addr;
|
||||
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void simplelink_freeaddrinfo(struct addrinfo *res)
|
||||
{
|
||||
ARG_UNUSED(res);
|
||||
__ASSERT_NO_MSG(res);
|
||||
|
||||
free(res->ai_addr);
|
||||
free(res);
|
||||
}
|
||||
|
||||
void simplelink_sockets_init(void)
|
||||
{
|
||||
k_mutex_init(&ga_mutex);
|
||||
}
|
||||
|
||||
const struct socket_offload simplelink_ops = {
|
||||
|
|
|
@ -12,6 +12,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
extern const struct socket_offload simplelink_ops;
|
||||
extern void simplelink_sockets_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue