diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 30909237c..79919b917 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -2522,3 +2522,8 @@ * include/nuttx/arch.h, configs/stm3240g-eval/src/up_cxxinitialize.c, and configs/stm3240g-eval/src/up_cxxinitialize.c: Add support for C++ static initializers. + * net/setsockopt.c, net/getsockopt.c, net/bind.c, net/socket.c: Add more + low level, thread-independent socket interfaces for use within the OS. + Some of these are currently used by the FTP controlling terminal. More will + be used to support the NFS file system currenly underwork. + diff --git a/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c b/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c index 1ed9c29bc..97ccceb68 100644 --- a/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c +++ b/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c @@ -300,7 +300,6 @@ # define bdtdbg(x...) # define bdtvdbg(x...) -# define pic32mx_ep0bdtdump(msg) #endif @@ -467,9 +466,6 @@ static inline void static inline bool pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno); static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv); -#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG -static void pic32mx_ep0bdtdump(const char *msg); -#endif /* Endpoint operations ******************************************************/ @@ -504,6 +500,7 @@ static int pic32mx_selfpowered(struct usbdev_s *dev, bool selfpowered); static void pic32mx_reset(struct pic32mx_usbdev_s *priv); static void pic32mx_attach(struct pic32mx_usbdev_s *priv); static void pic32mx_detach(struct pic32mx_usbdev_s *priv); +static void pic32mx_swreset(struct pic32mx_usbdev_s *priv); static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv); static void pic32mx_stateinit(struct pic32mx_usbdev_s *priv); static void pic32mx_hwshutdown(struct pic32mx_usbdev_s *priv); @@ -2292,21 +2289,22 @@ static int pic32mx_interrupt(int irq, void *context) { usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_RESET), usbir); - /* Reset interrupt received. Restore our power-up state */ + /* Reset interrupt received. Restore our initial state. NOTE: the + * hardware automatically resets the USB address, so we just need + * reset any existing configuration/transfer states. + */ -#warning "Broken Logic" -#if 0 /* If there is no pull-up, then this will just cause another reset */ - pic32mx_reset(priv); - pic32mx_attach(priv); -#endif + pic32mx_swreset(priv); priv->devstate = DEVSTATE_DEFAULT; #ifdef CONFIG_USBOTG /* Disable and deactivate HNP */ #warning Missing Logic #endif - pic32mx_putreg(USB_INT_URST, PIC32MX_USB_IR); - goto interrupt_exit; + /* Acknowlege the reset interrupt */ + + pic32mx_putreg(USB_INT_URST, PIC32MX_USB_IR); + goto interrupt_exit; } /* Service IDLE interrupts */ @@ -2630,28 +2628,6 @@ static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv) bdt->addr = 0; } -/**************************************************************************** - * Name: pic32mx_ep0bdtdump - ****************************************************************************/ - -#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG -static void pic32mx_ep0bdtdump(const char *msg) -{ - volatile struct usbotg_bdtentry_s *bdt; - - bdtdbg("EP0 BDT: %s\n", msg); - - bdt = &g_bdt[EP0_OUT_EVEN] ; - bdtdbg(" OUT EVEN [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr); - bdt = &g_bdt[EP0_OUT_ODD]; - bdtdbg(" OUT ODD [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr); - bdt = &g_bdt[EP0_IN_EVEN]; - bdtdbg(" IN EVEN [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr); - bdt = &g_bdt[EP0_IN_ODD]; - bdtdbg(" IN ODD [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr); -} -#endif - /**************************************************************************** * Endpoint operations ****************************************************************************/ @@ -3372,44 +3348,9 @@ static int pic32mx_selfpowered(struct usbdev_s *dev, bool selfpowered) static void pic32mx_reset(struct pic32mx_usbdev_s *priv) { - int epno; + /* Reset the software configuration */ - /* Tell the class driver that we are disconnected. The class driver - * should then accept any new configurations. - */ - - if (priv->driver) - { - CLASS_DISCONNECT(priv->driver, &priv->usbdev); - } - - /* Reset the device state structure */ - - priv->ctrlstate = CTRLSTATE_WAITSETUP; - - /* Reset endpoints */ - - for (epno = 0; epno < PIC32MX_NENDPOINTS; epno++) - { - struct pic32mx_ep_s *privep = &priv->eplist[epno]; - - /* Cancel any queued requests. Since they are canceled - * with status -ESHUTDOWN, then will not be requeued - * until the configuration is reset. NOTE: This should - * not be necessary... the CLASS_DISCONNECT above should - * result in the class implementation calling pic32mx_epdisable - * for each of its configured endpoints. - */ - - pic32mx_cancelrequests(privep); - - /* Reset endpoint status */ - - privep->stalled = false; - privep->halted = false; - privep->txbusy = false; - privep->txnullpkt = false; - } + pic32mx_swreset(priv); /* Re-configure the USB controller in its initial, unconnected state */ @@ -3450,7 +3391,6 @@ static void pic32mx_attach(struct pic32mx_usbdev_s *priv) /* Configure EP0 */ pic32mx_ep0configure(priv); - pic32mx_ep0bdtdump("Attached"); /* Flush any pending transactions */ @@ -3554,6 +3494,65 @@ static void pic32mx_detach(struct pic32mx_usbdev_s *priv) #endif } +/**************************************************************************** + * Name: pic32mx_swreset + ****************************************************************************/ + +static void pic32mx_swreset(struct pic32mx_usbdev_s *priv) +{ + int epno; + + /* Tell the class driver that we are disconnected. The class driver + * should then accept any new configurations. + */ + + if (priv->driver) + { + CLASS_DISCONNECT(priv->driver, &priv->usbdev); + } + + /* Flush and reset endpoint states (except EP0) */ + + for (epno = 1; epno < PIC32MX_NENDPOINTS; epno++) + { + struct pic32mx_ep_s *privep = &priv->eplist[epno]; + + /* Cancel any queued requests. Since they are canceled + * with status -ESHUTDOWN, then will not be requeued + * until the configuration is reset. NOTE: This should + * not be necessary... the CLASS_DISCONNECT above should + * result in the class implementation calling pic32mx_epdisable + * for each of its configured endpoints. + */ + + pic32mx_cancelrequests(privep); + + /* Reset endpoint status */ + + privep->stalled = false; + privep->halted = false; + privep->txbusy = false; + privep->txnullpkt = false; + } + + /* Reset to the default address */ + + pic32mx_putreg(0, PIC32MX_USB_ADDR); + + /* Unconfigure each endpoint by clearing the endpoint control registers + * (except EP0) + */ + + for (epno = 1; epno < PIC32MX_NENDPOINTS; epno++) + { + pic32mx_putreg(0, PIC32MX_USB_EP(epno)); + } + + /* Reset the control state */ + + priv->ctrlstate = CTRLSTATE_WAITSETUP; +} + /**************************************************************************** * Name: pic32mx_hwreset ****************************************************************************/ @@ -3562,7 +3561,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv) { uint32_t physaddr; uint16_t regval; - int i; /* Power down the USB module. This will reset all USB registers. */ @@ -3578,12 +3576,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv) regval |= USB_PWRC_USBPWR; pic32mx_putreg(regval, PIC32MX_USB_PWRC); - /* Reset configuration and disable interrrupts at the USB controller */ - - pic32mx_putreg(0, PIC32MX_USB_CNFG1); - pic32mx_putreg(0, PIC32MX_USB_EIE); - pic32mx_putreg(0, PIC32MX_USB_IE); - /* Set the address of the buffer descriptor table (BDT) * * BDTP1: Bit 1-7: Bits 9-15 of the BDT base address @@ -3596,17 +3588,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv) pic32mx_putreg((uint16_t)((physaddr >> 16) & USB_BDTP2_MASK), PIC32MX_USB_BDTP2); pic32mx_putreg((uint16_t)((physaddr >> 8) & USB_BDTP1_MASK), PIC32MX_USB_BDTP1); - /* Reset to then default address */ - - pic32mx_putreg(0, PIC32MX_USB_ADDR); - - /* Clear all of the endpoint control registers */ - - for (i = 0; i < PIC32MX_NENDPOINTS; i++) - { - pic32mx_putreg(0, PIC32MX_USB_EP(i)); - } - /* Assert reset request to all of the Ping Pong buffer pointers. This * will reset all Even/Odd buffer pointers to the EVEN BD banks. */ @@ -3860,7 +3841,7 @@ int usbdev_register(struct usbdevclass_driver_s *driver) /* Setup the USB controller in it initial unconnected state */ DEBUGASSERT(priv->devstate == DEVSTATE_DETACHED); - pic32mx_hwreset(priv); + pic32mx_reset(priv); /* We do not know the order in which the user will call APIs. If * pic32mx_attach() were called before we got here, the the attach diff --git a/nuttx/include/nuttx/net.h b/nuttx/include/nuttx/net.h index 64d9cdc56..bcbcd627b 100644 --- a/nuttx/include/nuttx/net.h +++ b/nuttx/include/nuttx/net.h @@ -150,6 +150,12 @@ EXTERN int net_releaselist(FAR struct socketlist *list); EXTERN FAR struct socket *sockfd_socket(int sockfd); +/* socket.c ******************************************************************/ +/* socket using underlying socket structure */ + +EXTERN int psock_socket(int domain, int type, int protocol, + FAR struct socket *psock); + /* net_close.c ***************************************************************/ /* The standard close() operation redirects operations on socket descriptors * to this function. @@ -161,6 +167,12 @@ EXTERN int net_close(int sockfd); EXTERN int psock_close(FAR struct socket *psock); +/* net_close.c ***************************************************************/ +/* Performs the bind operation of a socket instance */ + +EXTERN int psock_bind(FAR struct socket *psock, const struct sockaddr *addr, + socklen_t addrlen); + /* send.c ********************************************************************/ /* Send using underlying socket structure */ @@ -185,6 +197,18 @@ EXTERN ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, #define psock_recv(psock,buf,len,flags) psock_recvfrom(psock,buf,len,flags,NULL,0) +/* getsockopt.c **************************************************************/ +/* getsockopt using the underlying socket structure */ + +EXTERN int psock_getsockopt(FAR struct socket *psock, int level, int option, + FAR void *value, FAR socklen_t *value_len); + +/* setsockopt.c **************************************************************/ +/* setsockopt using the underlying socket structure */ + +EXTERN int psock_setsockopt(FAR struct socket *psock, int level, int option, + FAR const void *value, socklen_t value_len); + /* net_ioctl.c ***************************************************************/ /* The standard ioctl() operation redirects operations on socket descriptors * to this function. diff --git a/nuttx/net/bind.c b/nuttx/net/bind.c index e0e9676dd..da912e017 100644 --- a/nuttx/net/bind.c +++ b/nuttx/net/bind.c @@ -1,8 +1,8 @@ /**************************************************************************** * net/bind.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,16 +51,16 @@ ****************************************************************************/ /**************************************************************************** - * Function: bind + * Function: psock_bind * * Description: - * bind() gives the socket 'sockfd' the local address 'addr'. 'addr' is + * bind() gives the socket 'psock' the local address 'addr'. 'addr' is * 'addrlen' bytes long. Traditionally, this is called "assigning a name to * a socket." When a socket is created with socket, it exists in a name * space (address family) but has no name assigned. * * Parameters: - * sockfd Socket descriptor from socket + * psock Socket structure of the socket to bind * addr Socket local address * addrlen Length of 'addr' * @@ -71,21 +71,18 @@ * The address is protected, and the user is not the superuser. * EADDRINUSE * The given address is already in use. - * EBADF - * sockfd is not a valid descriptor. * EINVAL * The socket is already bound to an address. * ENOTSOCK - * sockfd is a descriptor for a file, not a socket. + * psock is a descriptor for a file, not a socket. * * Assumptions: * ****************************************************************************/ -int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +int psock_bind(FAR struct socket *psock, const struct sockaddr *addr, + socklen_t addrlen) { - FAR struct socket *psock = sockfd_socket(sockfd); - #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) #ifdef CONFIG_NET_IPv6 FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; @@ -97,11 +94,11 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int err; int ret; - /* Verify that the sockfd corresponds to valid, allocated socket */ + /* Verify that the psock corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { - err = EBADF; + err = ENOTSOCK; goto errout; } @@ -154,4 +151,47 @@ errout: return ERROR; } +/**************************************************************************** + * Function: bind + * + * Description: + * bind() gives the socket 'sockfd' the local address 'addr'. 'addr' is + * 'addrlen' bytes long. Traditionally, this is called "assigning a name to + * a socket." When a socket is created with socket, it exists in a name + * space (address family) but has no name assigned. + * + * Parameters: + * sockfd Socket descriptor of the socket to bind + * addr Socket local address + * addrlen Length of 'addr' + * + * Returned Value: + * 0 on success; -1 on error with errno set appropriately + * + * EACCES + * The address is protected, and the user is not the superuser. + * EADDRINUSE + * The given address is already in use. + * EBADF + * sockfd is not a valid descriptor. + * EINVAL + * The socket is already bound to an address. + * ENOTSOCK + * sockfd is a descriptor for a file, not a socket. + * + * Assumptions: + * + ****************************************************************************/ + +int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) +{ + /* Make the socket descriptor to the underlying socket structure */ + + FAR struct socket *psock = sockfd_socket(sockfd); + + /* Then let psock_bind do all of the work */ + + return psock_bind(psock, addr, addrlen); +} + #endif /* CONFIG_NET */ diff --git a/nuttx/net/getsockopt.c b/nuttx/net/getsockopt.c index 94cfb5ec7..c3afb29c9 100644 --- a/nuttx/net/getsockopt.c +++ b/nuttx/net/getsockopt.c @@ -1,8 +1,8 @@ /**************************************************************************** * net/getsockopt.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,11 +51,11 @@ ****************************************************************************/ /**************************************************************************** - * Function: getsockopt + * Function: psock_getsockopt * * Description: * getsockopt() retrieve thse value for the option specified by the - * 'option' argument for the socket specified by the 'sockfd' argument. If + * 'option' argument for the socket specified by the 'psock' argument. If * the size of the option value is greater than 'value_len', the value * stored in the object pointed to by the 'value' argument will be silently * truncated. Otherwise, the length pointed to by the 'value_len' argument @@ -68,7 +68,7 @@ * See a complete list of values for the 'option' argument. * * Parameters: - * sockfd Socket descriptor of socket + * psock Socket structure of the socket to query * level Protocol level to set the option * option identifies the option to get * value Points to the argument value @@ -76,15 +76,13 @@ * * Returned Value: * - * EBADF - * The 'sockfd' argument is not a valid socket descriptor. * EINVAL * The specified option is invalid at the specified socket 'level' or the * socket has been shutdown. * ENOPROTOOPT * The 'option' is not supported by the protocol. * ENOTSOCK - * The 'sockfd' argument does not refer to a socket. + * The 'psock' argument does not refer to a socket. * ENOBUFS * Insufficient resources are available in the system to complete the * call. @@ -93,21 +91,11 @@ * ****************************************************************************/ -int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len) +int psock_getsockopt(FAR struct socket *psock, int level, int option, + FAR void *value, FAR socklen_t *value_len) { - FAR struct socket *psock; int err; - /* Get the underlying socket structure */ - /* Verify that the sockfd corresponds to valid, allocated socket */ - - psock = sockfd_socket(sockfd); - if (!psock || psock->s_crefs <= 0) - { - err = EBADF; - goto errout; - } - /* Verify that the socket option if valid (but might not be supported ) */ if (!_SO_GETVALID(option) || !value || !value_len) @@ -117,6 +105,7 @@ int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_ } /* Process the option */ + switch (option) { /* The following options take a point to an integer boolean value. @@ -231,8 +220,70 @@ int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_ return OK; errout: - *get_errno_ptr() = err; + set_errno(err); return ERROR; } +/**************************************************************************** + * Function: getsockopt + * + * Description: + * getsockopt() retrieve thse value for the option specified by the + * 'option' argument for the socket specified by the 'sockfd' argument. If + * the size of the option value is greater than 'value_len', the value + * stored in the object pointed to by the 'value' argument will be silently + * truncated. Otherwise, the length pointed to by the 'value_len' argument + * will be modified to indicate the actual length of the'value'. + * + * The 'level' argument specifies the protocol level of the option. To + * retrieve options at the socket level, specify the level argument as + * SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Parameters: + * sockfd Socket descriptor of socket + * level Protocol level to set the option + * option identifies the option to get + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * + * EBADF + * The 'sockfd' argument is not a valid socket descriptor. + * EINVAL + * The specified option is invalid at the specified socket 'level' or the + * socket has been shutdown. + * ENOPROTOOPT + * The 'option' is not supported by the protocol. + * ENOTSOCK + * The 'sockfd' argument does not refer to a socket. + * ENOBUFS + * Insufficient resources are available in the system to complete the + * call. + * + * Assumptions: + * + ****************************************************************************/ + +int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len) +{ + FAR struct socket *psock; + + /* Get the underlying socket structure */ + /* Verify that the sockfd corresponds to valid, allocated socket */ + + psock = sockfd_socket(sockfd); + if (!psock || psock->s_crefs <= 0) + { + set_errno(EBADF); + return ERROR; + } + + /* Then let psock_getsockopt() do all of the work */ + + return psock_getsockopt(psock, level, option, value, value_len); +} + #endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */ diff --git a/nuttx/net/net_sockets.c b/nuttx/net/net_sockets.c index 0ff4b57ad..05363167c 100644 --- a/nuttx/net/net_sockets.c +++ b/nuttx/net/net_sockets.c @@ -242,6 +242,7 @@ int sockfd_allocate(int minsd) } _net_semgive(list); } + return ERROR; } diff --git a/nuttx/net/setsockopt.c b/nuttx/net/setsockopt.c index f8de93cff..ad52ff53d 100644 --- a/nuttx/net/setsockopt.c +++ b/nuttx/net/setsockopt.c @@ -1,8 +1,8 @@ /**************************************************************************** * net/setsockopt.c * - * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -52,13 +52,12 @@ ****************************************************************************/ /**************************************************************************** - * Function: setsockopt + * Function: psock_setsockopt * * Description: - * setsockopt() sets the option specified by the 'option' argument, + * psock_setsockopt() sets the option specified by the 'option' argument, * at the protocol level specified by the 'level' argument, to the value - * pointed to by the 'value' argument for the socket associated with the - * file descriptor specified by the 'sockfd' argument. + * pointed to by the 'value' argument for the socket on the 'psock' argument. * * The 'level' argument specifies the protocol level of the option. To set * options at the socket level, specify the level argument as SOL_SOCKET. @@ -66,7 +65,7 @@ * See a complete list of values for the 'option' argument. * * Parameters: - * sockfd Socket descriptor of socket + * psock Socket structure of socket to operate on * level Protocol level to set the option * option identifies the option to set * value Points to the argument value @@ -75,8 +74,6 @@ * Returned Value: * 0 on success; -1 on failure * - * EBADF - * The 'sockfd' argument is not a valid socket descriptor. * EDOM * The send and receive timeout values are too big to fit into the * timeout fields in the socket structure. @@ -100,22 +97,12 @@ * ****************************************************************************/ -int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len) +int psock_setsockopt(FAR struct socket *psock, int level, int option, + FAR const void *value, socklen_t value_len) { - FAR struct socket *psock; uip_lock_t flags; int err; - /* Get the underlying socket structure */ - /* Verify that the sockfd corresponds to valid, allocated socket */ - - psock = sockfd_socket(sockfd); - if (!psock || psock->s_crefs <= 0) - { - err = EBADF; - goto errout; - } - /* Verify that the socket option if valid (but might not be supported ) */ if (!_SO_SETVALID(option) || !value) @@ -242,8 +229,76 @@ int setsockopt(int sockfd, int level, int option, const void *value, socklen_t v return OK; errout: - *get_errno_ptr() = err; + set_errno(err); return ERROR; } +/**************************************************************************** + * Function: setsockopt + * + * Description: + * setsockopt() sets the option specified by the 'option' argument, + * at the protocol level specified by the 'level' argument, to the value + * pointed to by the 'value' argument for the socket associated with the + * file descriptor specified by the 'sockfd' argument. + * + * The 'level' argument specifies the protocol level of the option. To set + * options at the socket level, specify the level argument as SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Parameters: + * sockfd Socket descriptor of socket + * level Protocol level to set the option + * option identifies the option to set + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * 0 on success; -1 on failure + * + * EBADF + * The 'sockfd' argument is not a valid socket descriptor. + * EDOM + * The send and receive timeout values are too big to fit into the + * timeout fields in the socket structure. + * EINVAL + * The specified option is invalid at the specified socket 'level' or the + * socket has been shut down. + * EISCONN + * The socket is already connected, and a specified option cannot be set + * while the socket is connected. + * ENOPROTOOPT + * The 'option' is not supported by the protocol. + * ENOTSOCK + * The 'sockfd' argument does not refer to a socket. + * ENOMEM + * There was insufficient memory available for the operation to complete. + * ENOBUFS + * Insufficient resources are available in the system to complete the + * call. + * + * Assumptions: + * + ****************************************************************************/ + +int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len) +{ + FAR struct socket *psock; + + /* Get the underlying socket structure */ + /* Verify that the sockfd corresponds to valid, allocated socket */ + + psock = sockfd_socket(sockfd); + if (!psock || psock->s_crefs <= 0) + { + set_errno(EBADF); + return ERROR; + } + + /* Then let psock_setockopt() do all of the work */ + + return psock_setsockopt(psock, level, option, value, value_len); +} + #endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */ diff --git a/nuttx/net/socket.c b/nuttx/net/socket.c index 3bbdd848c..a6befc5d7 100644 --- a/nuttx/net/socket.c +++ b/nuttx/net/socket.c @@ -1,8 +1,8 @@ /**************************************************************************** * net/socket.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -52,15 +52,17 @@ ****************************************************************************/ /**************************************************************************** - * Function: socket + * Function: psock_socket * * Description: - * socket() creates an endpoint for communication and returns a descriptor. + * socket() creates an endpoint for communication and returns a socket + * structure. * * Parameters: * domain (see sys/socket.h) * type (see sys/socket.h) * protocol (see sys/socket.h) + * psock A pointer to a user allocated socket structure to be initialized. * * Returned Value: * 0 on success; -1 on error with errno set appropriately @@ -87,10 +89,8 @@ * ****************************************************************************/ -int socket(int domain, int type, int protocol) +int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) { - FAR struct socket *psock; - int sockfd; int err = ENFILE; /* Only PF_INET or PF_INET6 domains supported */ @@ -123,23 +123,7 @@ int socket(int domain, int type, int protocol) goto errout; } - /* Everything looks good. Allocate a socket descriptor */ - - sockfd = sockfd_allocate(0); - if (sockfd < 0) - { - goto errout; /* with err == ENFILE */ - } - - /* Initialize the socket structure */ - - psock = sockfd_socket(sockfd); - if (!psock) - { - err = ENOSYS; /* should not happen */ - goto errout; - } - + /* Everything looks good. Initialize the socket structure */ /* Save the protocol type */ psock->s_type = type; @@ -209,17 +193,94 @@ int socket(int domain, int type, int protocol) { /* Failed to reserve a connection structure */ - sockfd_release(sockfd); goto errout; /* With err == ENFILE or ENOMEM */ } - return sockfd; + return OK; errout: errno = err; return ERROR; } +/**************************************************************************** + * Function: socket + * + * Description: + * socket() creates an endpoint for communication and returns a descriptor. + * + * Parameters: + * domain (see sys/socket.h) + * type (see sys/socket.h) + * protocol (see sys/socket.h) + * + * Returned Value: + * A non-negative socket descriptor on success; -1 on error with errno set + * appropriately. + * + * EACCES + * Permission to create a socket of the specified type and/or protocol + * is denied. + * EAFNOSUPPORT + * The implementation does not support the specified address family. + * EINVAL + * Unknown protocol, or protocol family not available. + * EMFILE + * Process file table overflow. + * ENFILE + * The system limit on the total number of open files has been reached. + * ENOBUFS or ENOMEM + * Insufficient memory is available. The socket cannot be created until + * sufficient resources are freed. + * EPROTONOSUPPORT + * The protocol type or the specified protocol is not supported within + * this domain. + * + * Assumptions: + * + ****************************************************************************/ + +int socket(int domain, int type, int protocol) +{ + FAR struct socket *psock; + int sockfd; + int ret; + + /* Allocate a socket descriptor */ + + sockfd = sockfd_allocate(0); + if (sockfd < 0) + { + set_errno(ENFILE); + return ERROR; + } + + /* Get the underlying socket structure */ + + psock = sockfd_socket(sockfd); + if (!psock) + { + set_errno(ENOSYS); /* should not happen */ + goto errout; + } + + /* Initialize the socket structure */ + + ret = psock_socket(domain, type, protocol, psock); + if (ret < 0) + { + /* Error already set by psock_socket() */ + + goto errout; + } + + return sockfd; + +errout: + sockfd_release(sockfd); + return ERROR; +} + #endif /* CONFIG_NET */