drivers: modem: ublox-sara-r4: Rework offloading mechanism

Switch to `NET_SOCKET_REGISTER` mechanism over the offloaded API
registration.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
diff --git a/drivers/modem/modem_socket.c b/drivers/modem/modem_socket.c
index 6d54e05..aa26402 100644
--- a/drivers/modem/modem_socket.c
+++ b/drivers/modem/modem_socket.c
@@ -11,7 +11,6 @@
  */
 
 #include <kernel.h>
-#include <net/socket_offload.h>
 #include <sys/fdtable.h>
 
 #include "modem_socket.h"
@@ -107,34 +106,6 @@
 }
 
 /*
- * VTable OPS
- */
-
-static ssize_t modem_socket_read_op(void *obj, void *buf, size_t sz)
-{
-	/* TODO: NOT IMPLEMENTED */
-	return -ENOTSUP;
-}
-
-static ssize_t modem_socket_write_op(void *obj, const void *buf, size_t sz)
-{
-	/* TODO: NOT IMPLEMENTED */
-	return -ENOTSUP;
-}
-
-static int modem_socket_ioctl_op(void *obj, unsigned int request, va_list args)
-{
-	/* TODO: NOT IMPLEMENTED */
-	return -ENOTSUP;
-}
-
-static const struct fd_op_vtable modem_sock_fd_vtable = {
-	.read = modem_socket_read_op,
-	.write = modem_socket_write_op,
-	.ioctl = modem_socket_ioctl_op,
-};
-
-/*
  * Socket Support Functions
  */
 
@@ -164,7 +135,8 @@
 	cfg->sockets[i].ip_proto = proto;
 	/* socket # needs assigning */
 	cfg->sockets[i].id = cfg->sockets_len + 1;
-	z_finalize_fd(cfg->sockets[i].sock_fd, cfg, &modem_sock_fd_vtable);
+	z_finalize_fd(cfg->sockets[i].sock_fd, &cfg->sockets[i],
+		      (const struct fd_op_vtable *)cfg->vtable);
 
 	return cfg->sockets[i].sock_fd;
 }
@@ -290,7 +262,8 @@
 	return found_count;
 }
 
-int modem_socket_init(struct modem_socket_config *cfg)
+int modem_socket_init(struct modem_socket_config *cfg,
+		      const struct socket_op_vtable *vtable)
 {
 	int i;
 
@@ -300,5 +273,7 @@
 		cfg->sockets[i].id = cfg->base_socket_num - 1;
 	}
 
+	cfg->vtable = vtable;
+
 	return 0;
 }
diff --git a/drivers/modem/modem_socket.h b/drivers/modem/modem_socket.h
index 5080367..2516dbb 100644
--- a/drivers/modem/modem_socket.h
+++ b/drivers/modem/modem_socket.h
@@ -15,6 +15,9 @@
 
 #include <kernel.h>
 #include <net/net_ip.h>
+#include <net/socket.h>
+
+#include "sockets_internal.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -50,6 +53,8 @@
 	/* beginning socket id (modems can set this to 0 or 1 as needed) */
 	int base_socket_num;
 	struct k_sem sem_poll;
+
+	const struct socket_op_vtable *vtable;
 };
 
 /* return total size of remaining packets */
@@ -65,7 +70,8 @@
 void modem_socket_put(struct modem_socket_config *cfg, int sock_fd);
 int modem_socket_poll(struct modem_socket_config *cfg,
 		      struct pollfd *fds, int nfds, int msecs);
-int modem_socket_init(struct modem_socket_config *cfg);
+int modem_socket_init(struct modem_socket_config *cfg,
+		      const struct socket_op_vtable *vtable);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/modem/ublox-sara-r4.c b/drivers/modem/ublox-sara-r4.c
index 7b739d3..2b4b87e 100644
--- a/drivers/modem/ublox-sara-r4.c
+++ b/drivers/modem/ublox-sara-r4.c
@@ -18,7 +18,6 @@
 #include <net/net_if.h>
 #include <net/net_offload.h>
 #include <net/socket_offload.h>
-#include <net/socket_offload_ops.h>
 
 #include "modem_context.h"
 #include "modem_socket.h"
@@ -923,24 +922,19 @@
  * Socket Offload OPS
  */
 
+static const struct socket_op_vtable offload_socket_fd_op_vtable;
+
 static int offload_socket(int family, int type, int proto)
 {
 	/* defer modem's socket create call to bind() */
 	return modem_socket_get(&mdata.socket_config, family, type, proto);
 }
 
-static int offload_close(int sock_fd)
+static int offload_close(struct modem_socket *sock)
 {
-	struct modem_socket *sock;
 	char buf[sizeof("AT+USOCL=#\r")];
 	int ret;
 
-	sock = modem_socket_from_fd(&mdata.socket_config, sock_fd);
-	if (!sock) {
-		/* socket was already closed?  Exit quietly here. */
-		return 0;
-	}
-
 	/* make sure we assigned an id */
 	if (sock->id < mdata.socket_config.base_socket_num) {
 		return 0;
@@ -955,20 +949,14 @@
 		LOG_ERR("%s ret:%d", log_strdup(buf), ret);
 	}
 
-	modem_socket_put(&mdata.socket_config, sock_fd);
+	modem_socket_put(&mdata.socket_config, sock->sock_fd);
 	return 0;
 }
 
-static int offload_bind(int sock_fd, const struct sockaddr *addr,
+static int offload_bind(void *obj, const struct sockaddr *addr,
 			socklen_t addrlen)
 {
-	struct modem_socket *sock = NULL;
-
-	sock = modem_socket_from_fd(&mdata.socket_config, sock_fd);
-	if (!sock) {
-		LOG_ERR("Can't locate socket from fd:%d", sock_fd);
-		return -EINVAL;
-	}
+	struct modem_socket *sock = (struct modem_socket *)obj;
 
 	/* save bind address information */
 	memcpy(&sock->src, addr, sizeof(*addr));
@@ -981,10 +969,10 @@
 	return 0;
 }
 
-static int offload_connect(int sock_fd, const struct sockaddr *addr,
+static int offload_connect(void *obj, const struct sockaddr *addr,
 			   socklen_t addrlen)
 {
-	struct modem_socket *sock;
+	struct modem_socket *sock = (struct modem_socket *)obj;
 	int ret;
 	char buf[sizeof("AT+USOCO=#,!###.###.###.###!,#####,#\r")];
 	u16_t dst_port = 0U;
@@ -993,15 +981,9 @@
 		return -EINVAL;
 	}
 
-	sock = modem_socket_from_fd(&mdata.socket_config, sock_fd);
-	if (!sock) {
-		LOG_ERR("Can't locate socket from fd:%d", sock_fd);
-		return -EINVAL;
-	}
-
 	if (sock->id < mdata.socket_config.base_socket_num - 1) {
 		LOG_ERR("Invalid socket_id(%d) from fd:%d",
-			sock->id, sock_fd);
+			sock->id, sock->sock_fd);
 		return -EINVAL;
 	}
 
@@ -1042,8 +1024,26 @@
 /* support for POLLIN only for now. */
 static int offload_poll(struct pollfd *fds, int nfds, int msecs)
 {
-	int ret = modem_socket_poll(&mdata.socket_config, fds, nfds, msecs);
+	int ret, i;
+	void *obj;
 
+	/* Only accept modem sockets. */
+	for (i = 0; i < nfds; i++) {
+		if (fds[i].fd < 0) {
+			continue;
+		}
+
+		/* If vtable matches, then it's modem socket. */
+		obj = z_get_fd_obj(fds[i].fd,
+				   (const struct fd_op_vtable *)
+						&offload_socket_fd_op_vtable,
+				   EINVAL);
+		if (obj == NULL) {
+			return -1;
+		}
+	}
+
+	ret = modem_socket_poll(&mdata.socket_config, fds, nfds, msecs);
 	if (ret < 0) {
 		LOG_ERR("ret:%d errno:%d", ret, errno);
 	}
@@ -1051,11 +1051,11 @@
 	return ret;
 }
 
-static ssize_t offload_recvfrom(int sock_fd, void *buf, short int len,
-				short int flags, struct sockaddr *from,
+static ssize_t offload_recvfrom(void *obj, void *buf, size_t len,
+				int flags, struct sockaddr *from,
 				socklen_t *fromlen)
 {
-	struct modem_socket *sock;
+	struct modem_socket *sock = (struct modem_socket *)obj;
 	int ret;
 	struct modem_cmd cmd[] = {
 		MODEM_CMD("+USORF: ", on_cmd_sockreadfrom, 4U, ","),
@@ -1068,12 +1068,6 @@
 		return -EINVAL;
 	}
 
-	sock = modem_socket_from_fd(&mdata.socket_config, sock_fd);
-	if (!sock) {
-		LOG_ERR("Can't locate socket from fd:%d", sock_fd);
-		return -EINVAL;
-	}
-
 	if (flags & MSG_PEEK) {
 		return -ENOTSUP;
 	} else if (flags & MSG_DONTWAIT && !sock->packet_sizes[0]) {
@@ -1119,17 +1113,11 @@
 	return ret;
 }
 
-static ssize_t offload_recv(int sock_fd, void *buf, size_t max_len, int flags)
-{
-	return offload_recvfrom(sock_fd, buf, (short int)max_len, flags,
-				NULL, NULL);
-}
-
-static ssize_t offload_sendto(int sock_fd, const void *buf, size_t len,
+static ssize_t offload_sendto(void *obj, const void *buf, size_t len,
 			      int flags, const struct sockaddr *to,
 			      socklen_t tolen)
 {
-	struct modem_socket *sock;
+	struct modem_socket *sock = (struct modem_socket *)obj;
 	struct modem_cmd cmd[] = {
 		MODEM_CMD("+USOST: ", on_cmd_sockwrite, 2U, ","),
 		MODEM_CMD("+USOWR: ", on_cmd_sockwrite, 2U, ","),
@@ -1139,12 +1127,6 @@
 		return -EINVAL;
 	}
 
-	sock = modem_socket_from_fd(&mdata.socket_config, sock_fd);
-	if (!sock) {
-		LOG_ERR("Can't locate socket from fd:%d", sock_fd);
-		return -EINVAL;
-	}
-
 	if (!to && sock->ip_proto == IPPROTO_UDP) {
 		to = &sock->dst;
 	}
@@ -1153,23 +1135,73 @@
 				buf, len, MDM_CMD_TIMEOUT);
 }
 
-static ssize_t offload_send(int sock_fd, const void *buf, size_t len, int flags)
+static int offload_ioctl(void *obj, unsigned int request, va_list args)
 {
-	return offload_sendto(sock_fd, buf, len, flags, NULL, 0U);
+	switch (request) {
+	/* Handle close specifically. */
+	case ZFD_IOCTL_CLOSE:
+		return offload_close((struct modem_socket *)obj);
+
+	case ZFD_IOCTL_POLL_PREPARE:
+		return -EXDEV;
+
+	case ZFD_IOCTL_POLL_UPDATE:
+		return -EOPNOTSUPP;
+
+	case ZFD_IOCTL_POLL_OFFLOAD: {
+		struct zsock_pollfd *fds;
+		int nfds;
+		int timeout;
+
+		fds = va_arg(args, struct zsock_pollfd *);
+		nfds = va_arg(args, int);
+		timeout = va_arg(args, int);
+
+		return offload_poll(fds, nfds, timeout);
+	}
+
+	default:
+		errno = EINVAL;
+		return -1;
+	}
 }
 
-static const struct socket_offload modem_socket_offload = {
-	.socket = offload_socket,
-	.close = offload_close,
+static ssize_t offload_read(void *obj, void *buffer, size_t count)
+{
+	return offload_recvfrom(obj, buffer, count, 0, NULL, 0);
+}
+
+static ssize_t offload_write(void *obj, const void *buffer, size_t count)
+{
+	return offload_sendto(obj, buffer, count, 0, NULL, 0);
+}
+
+static const struct socket_op_vtable offload_socket_fd_op_vtable = {
+	.fd_vtable = {
+		.read = offload_read,
+		.write = offload_write,
+		.ioctl = offload_ioctl,
+	},
 	.bind = offload_bind,
 	.connect = offload_connect,
-	.poll = offload_poll,
-	.recv = offload_recv,
-	.recvfrom = offload_recvfrom,
-	.send = offload_send,
 	.sendto = offload_sendto,
+	.recvfrom = offload_recvfrom,
+	.listen = NULL,
+	.accept = NULL,
+	.sendmsg = NULL,
+	.getsockopt = NULL,
+	.setsockopt = NULL,
 };
 
+static bool offload_is_supported(int family, int type, int proto)
+{
+	/* TODO offloading always enabled for now. */
+	return true;
+}
+
+NET_SOCKET_REGISTER(ublox_sara_r4, AF_UNSPEC, offload_is_supported,
+		    offload_socket);
+
 static int net_offload_dummy_get(sa_family_t family,
 				 enum net_sock_type type,
 				 enum net_ip_protocol ip_proto,
@@ -1225,7 +1257,6 @@
 	net_if_set_link_addr(iface, modem_get_mac(dev),
 			     sizeof(data->mac_addr),
 			     NET_LINK_ETHERNET);
-	socket_offload_register(&modem_socket_offload);
 	data->net_iface = iface;
 }
 
@@ -1264,7 +1295,8 @@
 	mdata.socket_config.sockets = &mdata.sockets[0];
 	mdata.socket_config.sockets_len = ARRAY_SIZE(mdata.sockets);
 	mdata.socket_config.base_socket_num = MDM_BASE_SOCKET_NUM;
-	ret = modem_socket_init(&mdata.socket_config);
+	ret = modem_socket_init(&mdata.socket_config,
+				&offload_socket_fd_op_vtable);
 	if (ret < 0) {
 		goto error;
 	}