| /**************************************************************************** |
| * apps/wireless/gs2200m/gs2200m_main.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <stdint.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <debug.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <poll.h> |
| #include <unistd.h> |
| |
| #include <sys/param.h> |
| #include <sys/socket.h> |
| #include <sys/ioctl.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <net/if.h> |
| |
| #include <nuttx/net/usrsock.h> |
| #include <nuttx/wireless/wireless.h> |
| #include <nuttx/wireless/gs2200m.h> |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| /* #define GS2200M_TRACE */ |
| |
| #ifdef GS2200M_TRACE |
| # define gs2200m_printf(v, ...) printf(v, ##__VA_ARGS__) |
| #else |
| # define gs2200m_printf(v, ...) |
| #endif |
| |
| #define SOCKET_BASE 10000 |
| #define SOCKET_COUNT 16 |
| |
| /**************************************************************************** |
| * Private Data Types |
| ****************************************************************************/ |
| |
| enum sock_state_e |
| { |
| CLOSED, |
| OPENED, |
| BOUND, |
| CONNECTED, |
| }; |
| |
| struct usock_s |
| { |
| int8_t type; |
| char cid; |
| enum sock_state_e state; |
| uint16_t lport; /* local port */ |
| struct sockaddr_in raddr; /* remote addr */ |
| }; |
| |
| struct gs2200m_s |
| { |
| char *ssid; |
| char *key; |
| uint8_t mode; |
| uint8_t ch; |
| int gsfd; |
| struct usock_s sockets[SOCKET_COUNT]; |
| }; |
| |
| union usrsock_request_u |
| { |
| struct usrsock_request_socket_s socket; |
| struct usrsock_request_close_s close; |
| struct usrsock_request_connect_s connect; |
| struct usrsock_request_sendto_s sendto; |
| struct usrsock_request_recvfrom_s recvfrom; |
| struct usrsock_request_setsockopt_s setsockopt; |
| struct usrsock_request_getsockopt_s getsockopt; |
| struct usrsock_request_getsockname_s getsockname; |
| struct usrsock_request_getpeername_s getpeername; |
| struct usrsock_request_bind_s bind; |
| struct usrsock_request_listen_s listen; |
| struct usrsock_request_accept_s accept; |
| struct usrsock_request_ioctl_s ioctl; |
| }; |
| |
| /**************************************************************************** |
| * Private Function Prototypes |
| ****************************************************************************/ |
| |
| static int socket_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int close_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int connect_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int sendto_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int recvfrom_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int setsockopt_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int getsockopt_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int getsockname_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int getpeername_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int ioctl_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int bind_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int listen_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| static int accept_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf); |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| static const struct usrsock_req_handler_s |
| { |
| uint32_t hdrlen; |
| int (CODE *fn)(int fd, FAR struct gs2200m_s *priv, FAR void *req); |
| } |
| handlers[USRSOCK_REQUEST__MAX] = |
| { |
| { |
| sizeof(struct usrsock_request_socket_s), |
| socket_request, |
| }, |
| { |
| sizeof(struct usrsock_request_close_s), |
| close_request, |
| }, |
| { |
| sizeof(struct usrsock_request_connect_s), |
| connect_request, |
| }, |
| { |
| sizeof(struct usrsock_request_sendto_s), |
| sendto_request, |
| }, |
| { |
| sizeof(struct usrsock_request_recvfrom_s), |
| recvfrom_request, |
| }, |
| { |
| sizeof(struct usrsock_request_setsockopt_s), |
| setsockopt_request, |
| }, |
| { |
| sizeof(struct usrsock_request_getsockopt_s), |
| getsockopt_request, |
| }, |
| { |
| sizeof(struct usrsock_request_getsockname_s), |
| getsockname_request, |
| }, |
| { |
| sizeof(struct usrsock_request_getpeername_s), |
| getpeername_request, |
| }, |
| { |
| sizeof(struct usrsock_request_bind_s), |
| bind_request, |
| }, |
| { |
| sizeof(struct usrsock_request_listen_s), |
| listen_request, |
| }, |
| { |
| sizeof(struct usrsock_request_accept_s), |
| accept_request, |
| }, |
| { |
| sizeof(struct usrsock_request_ioctl_s), |
| ioctl_request, |
| }, |
| }; |
| |
| static struct gs2200m_s *_daemon; |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: _write_to_usock |
| ****************************************************************************/ |
| |
| static int _write_to_usock(int fd, void *buf, size_t count) |
| { |
| ssize_t wlen; |
| |
| wlen = write(fd, buf, count); |
| |
| if (wlen < 0) |
| { |
| return -errno; |
| } |
| |
| if (wlen != count) |
| { |
| return -ENOSPC; |
| } |
| |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: _send_ack_common |
| ****************************************************************************/ |
| |
| static int _send_ack_common(int fd, |
| uint16_t events, |
| uint32_t xid, |
| FAR struct usrsock_message_req_ack_s *resp) |
| { |
| resp->head.msgid = USRSOCK_MESSAGE_RESPONSE_ACK; |
| resp->head.flags = 0; |
| resp->head.events = events; |
| resp->xid = xid; |
| |
| /* Send ACK response. */ |
| |
| return _write_to_usock(fd, resp, sizeof(*resp)); |
| } |
| |
| /**************************************************************************** |
| * Name: gs2200m_socket_alloc |
| ****************************************************************************/ |
| |
| static int16_t gs2200m_socket_alloc(FAR struct gs2200m_s *priv, int type) |
| { |
| FAR struct usock_s *usock; |
| int16_t i; |
| |
| for (i = 0; i < SOCKET_COUNT; i++) |
| { |
| usock = &priv->sockets[i]; |
| |
| if (CLOSED == usock->state) |
| { |
| memset(usock, 0, sizeof(*usock)); |
| usock->cid = 'z'; /* Invalidate cid */ |
| usock->state = OPENED; |
| usock->type = type; |
| return i + SOCKET_BASE; |
| } |
| } |
| |
| return -1; |
| } |
| |
| /**************************************************************************** |
| * Name: gs2200m_socket_get |
| ****************************************************************************/ |
| |
| static FAR struct usock_s *gs2200m_socket_get(FAR struct gs2200m_s *priv, |
| int sockid) |
| { |
| if (sockid < SOCKET_BASE) |
| { |
| return NULL; |
| } |
| |
| sockid -= SOCKET_BASE; |
| |
| if (sockid >= SOCKET_COUNT) |
| { |
| return NULL; |
| } |
| |
| return &priv->sockets[sockid]; |
| } |
| |
| /**************************************************************************** |
| * Name: gs2200m_find_socket_by_cid |
| ****************************************************************************/ |
| |
| static FAR struct usock_s * |
| gs2200m_find_socket_by_cid(FAR struct gs2200m_s *priv, |
| char cid) |
| { |
| FAR struct usock_s *ret = NULL; |
| int i; |
| |
| for (i = 0; i < SOCKET_COUNT; i++) |
| { |
| if (priv->sockets[i].cid == cid) |
| { |
| ret = &priv->sockets[i]; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: gs2200m_socket_free |
| ****************************************************************************/ |
| |
| static int gs2200m_socket_free(FAR struct gs2200m_s *priv, int sockid) |
| { |
| FAR struct usock_s *usock = gs2200m_socket_get(priv, sockid); |
| |
| if (!usock) |
| { |
| return -EBADFD; |
| } |
| |
| if (CLOSED == usock->state) |
| { |
| return -EFAULT; |
| } |
| |
| usock->state = CLOSED; |
| usock->cid = 'z'; /* invalid */ |
| |
| return 0; |
| } |
| |
| /**************************************************************************** |
| * Name: read_req |
| ****************************************************************************/ |
| |
| static ssize_t |
| read_req(int fd, FAR const struct usrsock_request_common_s *com_hdr, |
| FAR void *req, size_t reqsize) |
| { |
| ssize_t rlen; |
| |
| rlen = read(fd, (uint8_t *)req + sizeof(*com_hdr), |
| reqsize - sizeof(*com_hdr)); |
| |
| if (rlen < 0) |
| { |
| return -errno; |
| } |
| |
| if (rlen + sizeof(*com_hdr) != reqsize) |
| { |
| return -EMSGSIZE; |
| } |
| |
| return rlen; |
| } |
| |
| /**************************************************************************** |
| * Name: usrsock_handle_request |
| ****************************************************************************/ |
| |
| static int usrsock_handle_request(int fd, FAR struct gs2200m_s *priv) |
| { |
| FAR struct usrsock_request_common_s *com_hdr; |
| union usrsock_request_u req; |
| ssize_t rlen; |
| |
| com_hdr = (FAR void *)&req; |
| rlen = read(fd, com_hdr, sizeof(*com_hdr)); |
| |
| if (rlen < 0) |
| { |
| return -errno; |
| } |
| |
| if (rlen != sizeof(*com_hdr)) |
| { |
| return -EMSGSIZE; |
| } |
| |
| if (com_hdr->reqid >= USRSOCK_REQUEST__MAX || |
| !handlers[com_hdr->reqid].fn) |
| { |
| ASSERT(false); |
| return -EIO; |
| } |
| |
| assert(handlers[com_hdr->reqid].hdrlen <= sizeof(req)); |
| |
| rlen = read_req(fd, com_hdr, &req, |
| handlers[com_hdr->reqid].hdrlen); |
| |
| if (rlen < 0) |
| { |
| return rlen; |
| } |
| |
| return handlers[com_hdr->reqid].fn(fd, priv, &req); |
| } |
| |
| /**************************************************************************** |
| * Name: usock_send_event |
| ****************************************************************************/ |
| |
| static int usock_send_event(int fd, FAR struct gs2200m_s *priv, |
| FAR struct usock_s *usock, int events) |
| { |
| FAR struct usrsock_message_socket_event_s event; |
| int i; |
| |
| memset(&event, 0, sizeof(event)); |
| event.head.flags = USRSOCK_MESSAGE_FLAG_EVENT; |
| event.head.msgid = USRSOCK_MESSAGE_SOCKET_EVENT; |
| |
| for (i = 0; i < SOCKET_COUNT; i++) |
| { |
| if (usock == &priv->sockets[i]) |
| { |
| break; |
| } |
| } |
| |
| if (i == SOCKET_COUNT) |
| { |
| return -EINVAL; |
| } |
| |
| event.usockid = i + SOCKET_BASE; |
| event.head.events = events; |
| |
| return _write_to_usock(fd, &event, sizeof(event)); |
| } |
| |
| /**************************************************************************** |
| * Name: usock_sendevent_toall |
| ****************************************************************************/ |
| |
| static void usock_sendevent_toall(FAR struct gs2200m_s *priv, int fd) |
| { |
| int i; |
| |
| for (i = 0; i < SOCKET_COUNT; i++) |
| { |
| if (priv->sockets[i].state != CLOSED) |
| { |
| usock_send_event(fd, priv, &priv->sockets[i], |
| USRSOCK_EVENT_RECVFROM_AVAIL); |
| } |
| } |
| } |
| |
| /**************************************************************************** |
| * Name: socket_request |
| ****************************************************************************/ |
| |
| static int socket_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_socket_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| uint16_t events = 0; |
| int16_t usockid; |
| int ret; |
| |
| gs2200m_printf("%s: start type=%d\n", |
| __func__, req->type); |
| |
| /* Check domain requested */ |
| |
| if (req->domain != AF_INET) |
| { |
| usockid = -EAFNOSUPPORT; |
| } |
| else |
| { |
| /* Allocate socket. */ |
| |
| usockid = gs2200m_socket_alloc(priv, req->type); |
| ASSERT(0 < usockid); |
| } |
| |
| /* Send ACK response */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = usockid; |
| if (req->type == SOCK_DGRAM) |
| { |
| events = USRSOCK_EVENT_SENDTO_READY; |
| } |
| |
| ret = _send_ack_common(fd, events, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| |
| gs2200m_printf("%s: end\n", __func__); |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: close_request |
| ****************************************************************************/ |
| |
| static int close_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_close_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| struct gs2200m_close_msg clmsg; |
| FAR struct usock_s *usock; |
| char cid; |
| int ret = 0; |
| |
| gs2200m_printf("%s: start\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| cid = usock->cid; |
| |
| if ((BOUND != usock->state) && (CONNECTED != usock->state)) |
| { |
| ret = -EBADFD; |
| goto errout; |
| } |
| |
| memset(&clmsg, 0, sizeof(clmsg)); |
| clmsg.cid = cid; |
| ioctl(priv->gsfd, GS2200M_IOC_CLOSE, (unsigned long)&clmsg); |
| |
| errout: |
| |
| /* Send ACK response */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| |
| /* Free socket */ |
| |
| ret = gs2200m_socket_free(priv, req->usockid); |
| |
| gs2200m_printf("%s: end\n", __func__); |
| |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: connect_request |
| ****************************************************************************/ |
| |
| static int connect_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_connect_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| struct gs2200m_connect_msg cmsg; |
| struct sockaddr_in addr; |
| FAR struct usock_s *usock; |
| int events; |
| ssize_t wlen; |
| ssize_t rlen; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: start\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| /* Check if this socket is already connected. */ |
| |
| if (CONNECTED == usock->state) |
| { |
| ret = -EISCONN; |
| goto prepare; |
| } |
| |
| memset(&cmsg, 0, sizeof(cmsg)); |
| |
| /* Check if this socket is already connected. */ |
| |
| if (BOUND == usock->state) |
| { |
| if (usock->type == SOCK_STREAM) |
| { |
| ret = -EISCONN; |
| goto prepare; |
| } |
| else |
| { |
| /* Firstly, close the socket */ |
| |
| struct gs2200m_close_msg clmsg; |
| memset(&clmsg, 0, sizeof(clmsg)); |
| clmsg.cid = usock->cid; |
| |
| ioctl(priv->gsfd, GS2200M_IOC_CLOSE, (unsigned long)&clmsg); |
| |
| /* Copy the local port info */ |
| |
| cmsg.lport = usock->lport; |
| |
| usock->state = OPENED; |
| } |
| } |
| |
| /* Check if address size ok. */ |
| |
| if (req->addrlen > sizeof(addr)) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| |
| /* Read address. */ |
| |
| rlen = read(fd, &addr, sizeof(addr)); |
| |
| if (rlen < 0 || rlen < req->addrlen) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| |
| /* Check address family. */ |
| |
| if (addr.sin_family != AF_INET) |
| { |
| ret = -EAFNOSUPPORT; |
| goto prepare; |
| } |
| |
| snprintf(cmsg.addr, sizeof(cmsg.addr), "%s", |
| inet_ntoa(addr.sin_addr)); |
| snprintf(cmsg.port, sizeof(cmsg.port), "%d", |
| ntohs(addr.sin_port)); |
| |
| cmsg.cid = 'z'; /* set to invalid */ |
| cmsg.type = usock->type; |
| |
| ret = ioctl(priv->gsfd, GS2200M_IOC_CONNECT, |
| (unsigned long)&cmsg); |
| |
| if (0 == ret) |
| { |
| usock->cid = cmsg.cid; |
| usock->state = CONNECTED; |
| usock->raddr = addr; |
| } |
| else |
| { |
| ret = -errno; |
| } |
| |
| prepare: |
| |
| /* Send ACK response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| |
| events = USRSOCK_EVENT_SENDTO_READY; |
| wlen = usock_send_event(fd, priv, usock, events); |
| |
| if (wlen < 0) |
| { |
| return wlen; |
| } |
| |
| gs2200m_printf("%s: end\n", __func__); |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: sendto_request |
| ****************************************************************************/ |
| |
| static int sendto_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_sendto_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| struct gs2200m_send_msg smsg; |
| FAR struct usock_s *usock; |
| uint8_t *sendbuf = NULL; |
| ssize_t wlen; |
| ssize_t rlen; |
| int nret; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: start (buflen=%d)\n", |
| __func__, req->buflen); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| /* Check if this socket is connected. */ |
| |
| if (SOCK_STREAM == usock->type && CONNECTED != usock->state) |
| { |
| ret = -ENOTCONN; |
| goto prepare; |
| } |
| |
| /* Check if the address size is non-zero. |
| * connection-mode socket does not accept address |
| */ |
| |
| if (usock->type == SOCK_STREAM && req->addrlen > 0) |
| { |
| ret = -EISCONN; |
| goto prepare; |
| } |
| |
| memset(&smsg, 0, sizeof(smsg)); |
| |
| smsg.is_tcp = (usock->type == SOCK_STREAM) ? true : false; |
| |
| /* For UDP, addlen must be provided */ |
| |
| if (usock->type == SOCK_DGRAM) |
| { |
| if (CONNECTED != usock->state) |
| { |
| if (req->addrlen == 0) |
| { |
| ret = -EINVAL; |
| goto prepare; |
| } |
| |
| /* In UDP case, read the address. */ |
| |
| rlen = read(fd, &smsg.addr, sizeof(smsg.addr)); |
| |
| if (rlen < 0 || rlen < req->addrlen) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| } |
| else if (CONNECTED == usock->state) |
| { |
| /* Copy remote address */ |
| |
| smsg.addr = usock->raddr; |
| } |
| else |
| { |
| ASSERT(false); |
| } |
| |
| gs2200m_printf("%s: addr: %s:%d", |
| __func__, |
| inet_ntoa(smsg.addr.sin_addr), |
| ntohs(smsg.addr.sin_port)); |
| } |
| |
| /* Check if the request has data. */ |
| |
| if (req->buflen > 0) |
| { |
| sendbuf = calloc(1, req->buflen); |
| ASSERT(sendbuf); |
| |
| /* Read data from usrsock. */ |
| |
| rlen = read(fd, sendbuf, req->buflen); |
| |
| if (rlen < 0 || rlen < req->buflen) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| |
| smsg.cid = usock->cid; |
| smsg.buf = sendbuf; |
| smsg.len = req->buflen; |
| |
| nret = ioctl(priv->gsfd, GS2200M_IOC_SEND, |
| (unsigned long)&smsg); |
| |
| if (usock->cid != smsg.cid) |
| { |
| /* cid is newly assigned (bound) */ |
| |
| usock->cid = smsg.cid; |
| usock->state = BOUND; |
| } |
| |
| if (0 != nret) |
| { |
| ret = -errno; |
| goto prepare; |
| } |
| |
| /* return length which gs2200m sent */ |
| |
| ret = smsg.len; |
| } |
| |
| prepare: |
| if (sendbuf) |
| { |
| free(sendbuf); |
| } |
| |
| /* Send ACK response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| |
| /* Let kernel-side know that there is space for more send data. */ |
| |
| wlen = usock_send_event(fd, priv, usock, |
| USRSOCK_EVENT_SENDTO_READY); |
| |
| if (wlen < 0) |
| { |
| return wlen; |
| } |
| |
| gs2200m_printf("%s: end\n", __func__); |
| |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: recvfrom_request |
| ****************************************************************************/ |
| |
| static int recvfrom_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_recvfrom_s *req = hdrbuf; |
| struct usrsock_message_datareq_ack_s resp; |
| struct usrsock_message_req_ack_s resp1; |
| struct gs2200m_recv_msg rmsg; |
| FAR struct usock_s *usock; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: start (req->max_buflen=%d)\n", |
| __func__, req->max_buflen); |
| |
| memset(&rmsg, 0, sizeof(rmsg)); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| /* Check if this socket is connected. */ |
| |
| if (SOCK_STREAM == usock->type && CONNECTED != usock->state) |
| { |
| ret = -ENOTCONN; |
| goto prepare; |
| } |
| |
| rmsg.cid = usock->cid; |
| rmsg.reqlen = req->max_buflen; |
| rmsg.is_tcp = (usock->type == SOCK_STREAM) ? true : false; |
| rmsg.flags = req->flags; |
| |
| if (0 < req->max_buflen) |
| { |
| rmsg.buf = calloc(1, req->max_buflen); |
| ASSERT(rmsg.buf); |
| |
| ret = ioctl(priv->gsfd, GS2200M_IOC_RECV, |
| (unsigned long)&rmsg); |
| } |
| |
| if (0 == ret) |
| { |
| ret = rmsg.len; |
| } |
| else |
| { |
| ret = -errno; |
| } |
| |
| if (!rmsg.is_tcp) |
| { |
| gs2200m_printf("%s: from (%s:%d)\n", |
| __func__, |
| inet_ntoa(rmsg.addr.sin_addr), |
| ntohs(rmsg.addr.sin_port)); |
| } |
| |
| prepare: |
| |
| /* Prepare response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.reqack.result = ret; |
| resp.reqack.xid = req->head.xid; |
| resp.reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK; |
| resp.reqack.head.flags = 0; |
| resp.reqack.head.events = 0; |
| |
| if (0 <= ret) |
| { |
| resp.valuelen_nontrunc = sizeof(rmsg.addr); |
| resp.valuelen = MIN(resp.valuelen_nontrunc, |
| req->max_addrlen); |
| |
| if ((0 == rmsg.len) && (0 != rmsg.reqlen)) |
| { |
| usock_send_event(fd, priv, usock, |
| USRSOCK_EVENT_REMOTE_CLOSED |
| ); |
| |
| /* Send ack only */ |
| |
| memset(&resp1, 0, sizeof(resp1)); |
| resp1.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp1); |
| |
| goto err_out; |
| } |
| } |
| |
| /* Send response. */ |
| |
| ret = _write_to_usock(fd, &resp, sizeof(resp)); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| |
| if (0 < resp.valuelen) |
| { |
| /* Send address (value) */ |
| |
| ret = _write_to_usock(fd, &rmsg.addr, resp.valuelen); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| } |
| |
| if (resp.reqack.result > 0) |
| { |
| /* Send buffer */ |
| |
| ret = _write_to_usock(fd, rmsg.buf, resp.reqack.result); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| } |
| |
| err_out: |
| gs2200m_printf("%s: *** end ret=%d\n", __func__, ret); |
| |
| if (rmsg.buf) |
| { |
| free(rmsg.buf); |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: bind_request |
| ****************************************************************************/ |
| |
| static int bind_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_bind_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| struct gs2200m_bind_msg bmsg; |
| FAR struct usock_s *usock; |
| struct sockaddr_in addr; |
| ssize_t rlen; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: called ****\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| /* Check if address size ok. */ |
| |
| if (req->addrlen > sizeof(addr)) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| |
| /* Read address. */ |
| |
| rlen = read(fd, &addr, sizeof(addr)); |
| |
| if (rlen < 0 || rlen < req->addrlen) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| |
| /* Check address family. */ |
| |
| if (addr.sin_family != AF_INET) |
| { |
| ret = -EAFNOSUPPORT; |
| goto prepare; |
| } |
| |
| snprintf(bmsg.port, sizeof(bmsg.port), "%d", ntohs(addr.sin_port)); |
| bmsg.cid = 'z'; /* set to invalid */ |
| bmsg.is_tcp = (usock->type == SOCK_STREAM) ? true : false; |
| |
| ret = ioctl(priv->gsfd, GS2200M_IOC_BIND, (unsigned long)&bmsg); |
| |
| if (0 == ret) |
| { |
| usock->cid = bmsg.cid; |
| usock->lport = ntohs(addr.sin_port); |
| usock->state = BOUND; |
| } |
| |
| prepare: |
| |
| /* Send ACK response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| |
| gs2200m_printf("%s: end\n", __func__); |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: listen_request |
| ****************************************************************************/ |
| |
| static int listen_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_listen_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| FAR struct usock_s *usock; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: called ****\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| } |
| |
| /* Send ACK response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| |
| gs2200m_printf("%s: end\n", __func__); |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: accept_request |
| ****************************************************************************/ |
| |
| static int accept_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_accept_s *req = hdrbuf; |
| struct usrsock_message_datareq_ack_s resp; |
| struct gs2200m_accept_msg amsg; |
| FAR struct usock_s *usock; |
| FAR struct usock_s *new_usock = NULL; |
| int ret = 0; |
| int16_t usockid; /* usockid for new client */ |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: called ****\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| /* TODO: need to check if specified socket exists */ |
| |
| /* Call gs2200m driver to obtain new cid for client */ |
| |
| amsg.cid = usock->cid; /* Set server cid */ |
| ret = ioctl(priv->gsfd, GS2200M_IOC_ACCEPT, (unsigned long)&amsg); |
| |
| if (-1 == ret) |
| { |
| goto prepare; |
| } |
| |
| /* allocate socket. */ |
| |
| usockid = gs2200m_socket_alloc(priv, SOCK_STREAM); |
| ASSERT(0 < usockid); |
| new_usock = gs2200m_socket_get(priv, usockid); |
| |
| /* Set cid for the new_usock to be used in gs2200m driver */ |
| |
| new_usock->cid = amsg.cid; |
| new_usock->state = CONNECTED; |
| new_usock->raddr = amsg.addr; |
| |
| prepare: |
| |
| /* Prepare response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.reqack.xid = req->head.xid; |
| resp.reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK; |
| resp.reqack.head.flags = 0; |
| resp.reqack.head.events = 0; |
| |
| if (0 == ret) |
| { |
| resp.reqack.result = 2; /* new_usock->raddr + usock */ |
| resp.valuelen_nontrunc = sizeof(new_usock->raddr); |
| resp.valuelen = resp.valuelen_nontrunc; |
| } |
| else |
| { |
| resp.reqack.result = ret; |
| resp.valuelen = 0; |
| } |
| |
| /* Send response. */ |
| |
| ret = _write_to_usock(fd, &resp, sizeof(resp)); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| |
| if (resp.valuelen > 0) |
| { |
| /* Send address (value) */ |
| |
| ret = _write_to_usock(fd, &new_usock->raddr, resp.valuelen); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| |
| /* Send new usockid info */ |
| |
| ret = _write_to_usock(fd, &usockid, sizeof(usockid)); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| |
| /* Set events ofr new_usock */ |
| |
| usock_send_event(fd, priv, new_usock, |
| USRSOCK_EVENT_SENDTO_READY |
| ); |
| } |
| |
| err_out: |
| gs2200m_printf("%s: end\n", __func__); |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: setsockopt_request |
| ****************************************************************************/ |
| |
| static int setsockopt_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_setsockopt_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| FAR struct usock_s *usock; |
| ssize_t rlen; |
| int ret = 0; |
| int value; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: called ****\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| if (req->level != SOL_SOCKET) |
| { |
| gs2200m_printf("setsockopt: level=%d not supported\n", |
| __func__, req->level); |
| ret = -ENOPROTOOPT; |
| goto prepare; |
| } |
| |
| if (req->option != SO_REUSEADDR) |
| { |
| gs2200m_printf("setsockopt: option=%d not supported\n", |
| __func__, req->option); |
| ret = -ENOPROTOOPT; |
| goto prepare; |
| } |
| |
| if (req->valuelen < sizeof(value)) |
| { |
| ret = -EINVAL; |
| goto prepare; |
| } |
| |
| /* Read value. */ |
| |
| rlen = read(fd, &value, sizeof(value)); |
| |
| if (rlen < 0 || rlen < sizeof(value)) |
| { |
| ret = -EFAULT; |
| goto prepare; |
| } |
| |
| /* Debug print */ |
| |
| gs2200m_printf("setsockopt: option=%d value=%d\n", |
| __func__, req->option, value); |
| |
| ret = OK; |
| |
| prepare: |
| |
| /* Send ACK response */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| gs2200m_printf("%s: end (ret=%d)\n", __func__, ret); |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: getsockopt_request |
| ****************************************************************************/ |
| |
| static int getsockopt_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| DEBUGASSERT(false); |
| return -ENOSYS; |
| } |
| |
| /**************************************************************************** |
| * Name: getsockname_request |
| ****************************************************************************/ |
| |
| static int getsockname_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_getsockname_s *req = hdrbuf; |
| struct usrsock_message_datareq_ack_s resp; |
| struct gs2200m_name_msg nmsg; |
| FAR struct usock_s *usock; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: called ****\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| memset(&nmsg, 0, sizeof(nmsg)); |
| nmsg.cid = usock->cid; |
| nmsg.local = true; /* Obtain local address & port */ |
| |
| ret = ioctl(priv->gsfd, GS2200M_IOC_NAME, (unsigned long)&nmsg); |
| |
| prepare: |
| |
| /* Prepare response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.reqack.xid = req->head.xid; |
| resp.reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK; |
| resp.reqack.head.flags = 0; |
| resp.reqack.head.events = 0; |
| resp.reqack.result = ret; |
| |
| if (0 == ret) |
| { |
| resp.valuelen_nontrunc = sizeof(nmsg.addr); |
| resp.valuelen = resp.valuelen_nontrunc; |
| |
| if (resp.valuelen > req->max_addrlen) |
| { |
| resp.valuelen = req->max_addrlen; |
| } |
| } |
| else |
| { |
| resp.valuelen_nontrunc = 0; |
| resp.valuelen = 0; |
| } |
| |
| /* Send response. */ |
| |
| ret = _write_to_usock(fd, &resp, sizeof(resp)); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| |
| if (resp.valuelen > 0) |
| { |
| /* Send address (value) */ |
| |
| ret = _write_to_usock(fd, &nmsg.addr, resp.valuelen); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| } |
| |
| err_out: |
| gs2200m_printf("%s: end\n", __func__); |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: getpeername_request |
| ****************************************************************************/ |
| |
| static int getpeername_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_getpeername_s *req = hdrbuf; |
| struct usrsock_message_datareq_ack_s resp; |
| FAR struct usock_s *usock; |
| int ret = 0; |
| |
| DEBUGASSERT(priv); |
| DEBUGASSERT(req); |
| |
| gs2200m_printf("%s: called ****\n", __func__); |
| |
| /* Check if this socket exists. */ |
| |
| usock = gs2200m_socket_get(priv, req->usockid); |
| |
| if (!usock) |
| { |
| ret = -EBADFD; |
| goto prepare; |
| } |
| |
| if (CONNECTED != usock->state) |
| { |
| ret = -ENOTCONN; |
| } |
| |
| prepare: |
| |
| /* Prepare response. */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.reqack.xid = req->head.xid; |
| resp.reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK; |
| resp.reqack.head.flags = 0; |
| resp.reqack.head.events = 0; |
| resp.reqack.result = ret; |
| |
| if (0 == ret) |
| { |
| resp.valuelen_nontrunc = sizeof(usock->raddr); |
| resp.valuelen = resp.valuelen_nontrunc; |
| |
| if (resp.valuelen > req->max_addrlen) |
| { |
| resp.valuelen = req->max_addrlen; |
| } |
| } |
| else |
| { |
| resp.valuelen_nontrunc = 0; |
| resp.valuelen = 0; |
| } |
| |
| /* Send response. */ |
| |
| ret = _write_to_usock(fd, &resp, sizeof(resp)); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| |
| if (resp.valuelen > 0) |
| { |
| /* Send address (value) */ |
| |
| ret = _write_to_usock(fd, &usock->raddr, resp.valuelen); |
| |
| if (0 > ret) |
| { |
| goto err_out; |
| } |
| } |
| |
| err_out: |
| gs2200m_printf("%s: end\n", __func__); |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: ioctl_request |
| ****************************************************************************/ |
| |
| static int ioctl_request(int fd, FAR struct gs2200m_s *priv, |
| FAR void *hdrbuf) |
| { |
| FAR struct usrsock_request_ioctl_s *req = hdrbuf; |
| struct usrsock_message_req_ack_s resp; |
| struct usrsock_message_datareq_ack_s resp2; |
| struct gs2200m_ifreq_msg imsg; |
| bool getreq = false; |
| int ret = -EINVAL; |
| |
| memset(&imsg.ifr, 0, sizeof(imsg.ifr)); |
| |
| switch (req->cmd) |
| { |
| case SIOCGIFADDR: |
| case SIOCGIFFLAGS: |
| case SIOCGIFHWADDR: |
| case SIOCGIWNWID: |
| case SIOCGIWFREQ: |
| case SIOCGIWSENS: |
| getreq = true; |
| break; |
| |
| case SIOCSIFADDR: |
| case SIOCSIFDSTADDR: |
| case SIOCSIFNETMASK: |
| |
| read(fd, &imsg.ifr, sizeof(imsg.ifr)); |
| break; |
| |
| default: |
| break; |
| } |
| |
| imsg.cmd = req->cmd; |
| ret = ioctl(priv->gsfd, GS2200M_IOC_IFREQ, (unsigned long)&imsg); |
| |
| if (!getreq) |
| { |
| /* Send ACK response */ |
| |
| memset(&resp, 0, sizeof(resp)); |
| resp.result = ret; |
| ret = _send_ack_common(fd, 0, req->head.xid, &resp); |
| |
| if (0 > ret) |
| { |
| return ret; |
| } |
| } |
| |
| if (getreq) |
| { |
| resp2.reqack.result = ret; |
| resp2.reqack.xid = req->head.xid; |
| resp2.reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK; |
| resp2.reqack.head.flags = 0; |
| resp2.reqack.head.events = 0; |
| resp2.valuelen_nontrunc = sizeof(imsg.ifr); |
| resp2.valuelen = sizeof(imsg.ifr); |
| |
| _write_to_usock(fd, &resp2, sizeof(resp2)); |
| |
| /* Return struct ifreq address */ |
| |
| _write_to_usock(fd, &imsg.ifr, resp2.valuelen); |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: gs2200m_loop |
| ****************************************************************************/ |
| |
| static int gs2200m_loop(FAR struct gs2200m_s *priv) |
| { |
| struct gs2200m_assoc_msg amsg; |
| FAR struct usock_s *usock; |
| struct pollfd fds[2]; |
| int fd[2]; |
| char cid; |
| int ret; |
| |
| fd[0] = open("/dev/usrsock", O_RDWR); |
| ASSERT(0 <= fd[0]); |
| |
| fd[1] = open("/dev/gs2200m", O_RDWR); |
| ASSERT(0 <= fd[1]); |
| priv->gsfd = fd[1]; |
| |
| amsg.ssid = priv->ssid; |
| amsg.key = priv->key; |
| amsg.mode = priv->mode; |
| amsg.ch = priv->ch; |
| while (true) |
| { |
| ret = ioctl(priv->gsfd, GS2200M_IOC_ASSOC, (unsigned long)&amsg); |
| |
| if (0 == ret) |
| { |
| break; |
| } |
| |
| fprintf(stderr, "association failed : retrying\n"); |
| } |
| |
| while (true) |
| { |
| memset(fds, 0, sizeof(fds)); |
| |
| /* Check events from usrsock and gs2200m */ |
| |
| fds[0].fd = fd[0]; |
| fds[0].events = POLLIN; |
| fds[1].fd = fd[1]; |
| fds[1].events = POLLIN; |
| |
| ret = poll(fds, 2, -1); |
| ASSERT(0 < ret); |
| |
| if (fds[0].revents & POLLIN) |
| { |
| ret = usrsock_handle_request(fd[0], priv); |
| ASSERT(0 == ret); |
| } |
| |
| if (fds[1].revents & POLLIN) |
| { |
| gs2200m_printf("=== %s: event from /dev/gs2200m\n", |
| __func__); |
| |
| /* retrieve cid from gs2200m driver */ |
| |
| cid = 'z'; |
| ret = read(fd[1], &cid, sizeof(cid)); |
| ASSERT(ret == sizeof(cid)); |
| |
| /* Check if all socket destroy or not */ |
| |
| if (cid == DISASSOCIATION_CID) |
| { |
| gs2200m_printf("=== %s: Disassocitaion event\n", |
| __func__); |
| |
| /* To release sockets blocking in user-sock, |
| * send event to all opened sockets. |
| */ |
| |
| usock_sendevent_toall(priv, fd[0]); |
| } |
| else |
| { |
| /* find usock by the cid */ |
| |
| usock = gs2200m_find_socket_by_cid(priv, cid); |
| |
| if (NULL == usock) |
| { |
| gs2200m_printf("=== %s: cid=%c not found (ignored)\n", |
| __func__, cid); |
| } |
| else |
| { |
| /* send event to call xxxx_request() */ |
| |
| usock_send_event(fd[0], priv, usock, |
| USRSOCK_EVENT_RECVFROM_AVAIL); |
| } |
| } |
| } |
| } |
| |
| close(fd[1]); |
| close(fd[0]); |
| |
| gs2200m_printf("finished: ret=%d\n", __func__, ret); |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * Name: _show_usage |
| ****************************************************************************/ |
| |
| static void _show_usage(FAR char *cmd) |
| { |
| fprintf(stderr, |
| "Usage: %s [-a [ch]] ssid passphrase(key) \n\n", cmd); |
| fprintf(stderr, |
| "AP mode : specify -a option (optionally with channel) with ssid\n" |
| " and 8 to 63 ascii passphrase for WPA2-PSK\n" |
| " or 10 hex digits key for WEP\n"); |
| fprintf(stderr, |
| "STA mode: specify ssid and passphrase for WPA/WPA2 PSK\n"); |
| } |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| int main(int argc, FAR char *argv[]) |
| { |
| int option; |
| int ret; |
| bool ap_mode = false; |
| |
| if (_daemon) |
| { |
| fprintf(stderr, "%s is already running!\n", argv[0]); |
| return -1; |
| } |
| |
| _daemon = calloc(sizeof(struct gs2200m_s), 1); |
| ASSERT(_daemon); |
| |
| _daemon->mode = 0; /* default mode = 0 (station) */ |
| |
| while ((option = getopt(argc, argv, "a:")) != ERROR) |
| { |
| switch (option) |
| { |
| case 'a': |
| _daemon->mode = 1; /* ap mode */ |
| _daemon->ch = 1; |
| |
| if (5 == argc) |
| { |
| _daemon->ch = (int)atoi(optarg); |
| } |
| |
| ap_mode = true; |
| break; |
| } |
| } |
| |
| if ((ap_mode && (4 != argc) && (5 != argc)) |
| || (!ap_mode && 3 != argc)) |
| { |
| _show_usage(argv[0]); |
| ret = ERROR; |
| goto errout; |
| } |
| |
| _daemon->ssid = argv[argc - 2]; |
| _daemon->key = argv[argc - 1]; |
| |
| ret = gs2200m_loop(_daemon); |
| |
| errout: |
| if (_daemon) |
| { |
| free(_daemon); |
| _daemon = NULL; |
| } |
| |
| return ret; |
| } |