summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-11-29 10:53:22 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-11-29 10:53:22 -0600
commit6fa66b5a77300b73f40dbaae2bb831d92eaa8fe6 (patch)
tree64046c058f5f6e86d9f59dee44f9b6faba15d4cf /nuttx
parent7773304d911066ca3345eb295a944d949fd220c4 (diff)
downloadnuttx-6fa66b5a77300b73f40dbaae2bb831d92eaa8fe6.tar.gz
nuttx-6fa66b5a77300b73f40dbaae2bb831d92eaa8fe6.tar.bz2
nuttx-6fa66b5a77300b73f40dbaae2bb831d92eaa8fe6.zip
Add support for a variadic ioctl() function. The ioctl() interface is a non-standard, Unix interface. NuttX has always used the older, three-parameter version. Most contemporary systems now, however, use a variadic form of the ioctl() function. Added an option to insert a shim layer to adapt the three-parameter ioctl() to use the variadic interface form. Internally, the ioctl handling is the same three-parameter logic. The only real complexity to the shim is in how the system calls must be handled.
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/TODO42
-rw-r--r--nuttx/fs/vfs/fs_ioctl.c6
-rw-r--r--nuttx/include/nuttx/fs/fs.h34
-rw-r--r--nuttx/include/sys/ioctl.h49
-rw-r--r--nuttx/include/sys/syscall.h6
-rw-r--r--nuttx/libc/Kconfig26
-rw-r--r--nuttx/libc/misc/Make.defs10
-rw-r--r--nuttx/libc/misc/lib_ioctl.c101
-rw-r--r--nuttx/syscall/syscall.csv3
-rw-r--r--nuttx/syscall/syscall_lookup.h4
-rw-r--r--nuttx/syscall/syscall_stublookup.c5
11 files changed, 233 insertions, 53 deletions
diff --git a/nuttx/TODO b/nuttx/TODO
index 56f555da3..8ec8533ef 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated November 27, 2014)
+NuttX TODO List (Last updated November 29, 2014)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -18,7 +18,7 @@ nuttx/
(13) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
(10) Libraries (libc/, )
- (12) File system/Generic drivers (fs/, drivers/)
+ (11) File system/Generic drivers (fs/, drivers/)
(8) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/)
(1) Documentation (Documentation/)
@@ -1172,44 +1172,6 @@ o File system / Generic drivers (fs/, drivers/)
Status: Open
Priority: Medium
- Title: IOCTL() IS NO LONGER STANDARD
- Description: The function prototype for ioctl() is no longer standard. It
- was more-or-less standard at one time. The NuttX ioctl is the
- historic System 7 Unix, three-parameter version.
-
- int ioctl(int fd, int req, unsigned long arg);
-
- Current definitions now allow for the third parameter to be
- optional (and, I suppose, could accept additional arguments).
- For example, OpenGroup
- (http://pubs.opengroup.org/onlinepubs/009695399/functions/ioctl.html):
-
- int ioctl(int fildes, int request, ... /* arg */);
-
- Linux man page:
-
- int ioctl(int d, unsigned long request, ...);
-
- FreeBSD:
-
- int ioctl(int fd, unsigned long request, ...);
-
- I imagine that making the thread argument variadic, the logic
- is rescued for the case with modern 64-bit computers where
- sizeof(long) < sizeof(pointer).
-
- Since NuttX relies on OpenGroup for interface definitions, the
- current NuttX definition is incompatible with the standard in
- any event.
-
- Unfortunately, the change would be very extensive. If the
- type of the argument depends on the 'request', then the third
- argument would have to be decoded by every device device
- driver. That would be an enormous job and will not happen soon.
- Status: Open
- Priority: Very low until I run into a machine with sizeof(long) <
- sizeof(pointer)
-
o Graphics subsystem (graphics/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/fs/vfs/fs_ioctl.c b/nuttx/fs/vfs/fs_ioctl.c
index c0165cf7b..d96d95889 100644
--- a/nuttx/fs/vfs/fs_ioctl.c
+++ b/nuttx/fs/vfs/fs_ioctl.c
@@ -57,7 +57,7 @@
****************************************************************************/
/****************************************************************************
- * Name: ioctl
+ * Name: ioctl/fs_ioctl
*
* Description:
* Perform device specific operations.
@@ -85,7 +85,11 @@
*
****************************************************************************/
+#ifdef CONFIG_LIBC_IOCTL_VARIADIC
+int fs_ioctl(int fd, int req, unsigned long arg)
+#else
int ioctl(int fd, int req, unsigned long arg)
+#endif
{
int err;
#if CONFIG_NFILE_DESCRIPTORS > 0
diff --git a/nuttx/include/nuttx/fs/fs.h b/nuttx/include/nuttx/fs/fs.h
index 68d3a3725..1baa91cee 100644
--- a/nuttx/include/nuttx/fs/fs.h
+++ b/nuttx/include/nuttx/fs/fs.h
@@ -624,6 +624,40 @@ int open_blockdriver(FAR const char *pathname, int mountflags,
int close_blockdriver(FAR struct inode *inode);
#endif
+/* fs/vfs/fs_ioctl.c ********************************************************/
+/****************************************************************************
+ * Name: fs_ioctl
+ *
+ * Description:
+ * Perform device specific operations.
+ *
+ * Parameters:
+ * fd File/socket descriptor of device
+ * req The ioctl command
+ * arg The argument of the ioctl cmd
+ *
+ * Return:
+ * >=0 on success (positive non-zero values are cmd-specific)
+ * -1 on failure withi errno set properly:
+ *
+ * EBADF
+ * 'fd' is not a valid descriptor.
+ * EFAULT
+ * 'arg' references an inaccessible memory area.
+ * EINVAL
+ * 'cmd' or 'arg' is not valid.
+ * ENOTTY
+ * 'fd' is not associated with a character special device.
+ * ENOTTY
+ * The specified request does not apply to the kind of object that the
+ * descriptor 'fd' references.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_LIBC_IOCTL_VARIADIC
+int fs_ioctl(int fd, int req, unsigned long arg);
+#endif
+
/* fs_fdopen.c **************************************************************/
/****************************************************************************
* Name: fs_fdopen
diff --git a/nuttx/include/sys/ioctl.h b/nuttx/include/sys/ioctl.h
index 69aed10f5..edc916808 100644
--- a/nuttx/include/sys/ioctl.h
+++ b/nuttx/include/sys/ioctl.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/sys/ioctl.h
*
- * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008, 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -55,14 +55,6 @@
* Pre-Processor Definitions
****************************************************************************/
-/****************************************************************************
- * Type Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
@@ -72,9 +64,46 @@ extern "C"
#define EXTERN extern
#endif
-/* ioctl() is a non-standard UNIX-like API */
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+/****************************************************************************
+ * Name: ioctl/fs_ioctl
+ *
+ * Description:
+ * Perform device specific operations.
+ *
+ * ioctl() is a non-standard UNIX-like API
+ *
+ * Parameters:
+ * fd File/socket descriptor of device
+ * req The ioctl command
+ * arg The argument of the ioctl cmd
+ *
+ * Return:
+ * >=0 on success (positive non-zero values are cmd-specific)
+ * -1 on failure withi errno set properly:
+ *
+ * EBADF
+ * 'fd' is not a valid descriptor.
+ * EFAULT
+ * 'arg' references an inaccessible memory area.
+ * EINVAL
+ * 'cmd' or 'arg' is not valid.
+ * ENOTTY
+ * 'fd' is not associated with a character special device.
+ * ENOTTY
+ * The specified request does not apply to the kind of object that the
+ * descriptor 'fd' references.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_LIBC_IOCTL_VARIADIC
+int ioctl(int fd, int req, ...);
+#else
int ioctl(int fd, int req, unsigned long arg);
+#endif
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/sys/syscall.h b/nuttx/include/sys/syscall.h
index 755162a74..c0d163452 100644
--- a/nuttx/include/sys/syscall.h
+++ b/nuttx/include/sys/syscall.h
@@ -229,7 +229,11 @@
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
# define SYS_close (__SYS_descriptors+0)
-# define SYS_ioctl (__SYS_descriptors+1)
+# ifdef CONFIG_LIBC_IOCTL_VARIADIC
+# define SYS_fs_ioctl (__SYS_descriptors+1)
+# else
+# define SYS_ioctl (__SYS_descriptors+1)
+# endif
# define SYS_read (__SYS_descriptors+2)
# define SYS_write (__SYS_descriptors+3)
# define SYS_pread (__SYS_descriptors+4)
diff --git a/nuttx/libc/Kconfig b/nuttx/libc/Kconfig
index 138793aad..2c31a1983 100644
--- a/nuttx/libc/Kconfig
+++ b/nuttx/libc/Kconfig
@@ -48,6 +48,32 @@ config LIBC_FLOATINGPOINT
By default, floating point
support in printf, sscanf, etc. is disabled.
+config LIBC_IOCTL_VARIADIC
+ bool "Enable variadic ioctl()"
+ default n
+ ---help---
+ By default, NuttX implements the "old style," three-parameter,
+ ioctl() interface with this function prototype:
+
+ int ioctl(int fd, int req, unsigned long arg);
+
+ That function is implemented as part of the VFS. If
+ LIBC_IOCTL_VARIADIC is selected, then an additional compatibility
+ layer will be provided in the C library. The enabled, then function
+ prototype will become:
+
+ int ioctl(int fd, int req, ...);
+
+ The ioctl() is not controlled by any standard so it is really
+ arbitrary which format you used. You may select the variadic
+ function prototype with this option. That will slightly increase
+ code size and ioctl() processing time. It will not support a
+ variable number of arguments and it still always expects to see a
+ third argument of type 'unsigned long'. The only benefit of this
+ alternative function signature is that it may provide greater
+ compatibility if you are porting code from other platforms that use
+ the variadic ioctl() function.
+
config LIB_RAND_ORDER
int "Order of the random number generate"
default 1
diff --git a/nuttx/libc/misc/Make.defs b/nuttx/libc/misc/Make.defs
index c09e78331..1e7a6ae05 100644
--- a/nuttx/libc/misc/Make.defs
+++ b/nuttx/libc/misc/Make.defs
@@ -42,18 +42,28 @@ CSRCS += lib_stream.c lib_filesem.c
ifneq ($(CONFIG_NFILE_DESCRIPTORS),0)
CSRCS += lib_sendfile.c
+
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += lib_streamsem.c
endif
+ifeq ($(CONFIG_LIBC_IOCTL_VARIADIC),y)
+CSRCS += lib_ioctl.c
+endif
+
else
ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
CSRCS += lib_sendfile.c
+
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += lib_streamsem.c
endif
+ifeq ($(CONFIG_LIBC_IOCTL_VARIADIC),y)
+CSRCS += lib_ioctl.c
+endif
+
endif
endif
diff --git a/nuttx/libc/misc/lib_ioctl.c b/nuttx/libc/misc/lib_ioctl.c
new file mode 100644
index 000000000..9ef09fcd9
--- /dev/null
+++ b/nuttx/libc/misc/lib_ioctl.c
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * libc/misc/lib_ioctl.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/ioctl.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include <nuttx/fs/fs.h>
+
+#include "lib_internal.h"
+
+#if defined(CONFIG_LIBC_IOCTL_VARIADIC) && CONFIG_NFILE_DESCRIPTORS > 0
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ioctl/fs_ioctl
+ *
+ * Description:
+ * Perform device specific operations.
+ *
+ * Parameters:
+ * fd File/socket descriptor of device
+ * req The ioctl command
+ * ... One argument of type unsigned long is expected
+ *
+ * Return:
+ * >=0 on success (positive non-zero values are cmd-specific)
+ * -1 on failure withi errno set properly:
+ *
+ * EBADF
+ * 'fd' is not a valid descriptor.
+ * EFAULT
+ * 'arg' references an inaccessible memory area.
+ * EINVAL
+ * 'cmd' or 'arg' is not valid.
+ * ENOTTY
+ * 'fd' is not associated with a character special device.
+ * ENOTTY
+ * The specified request does not apply to the kind of object that the
+ * descriptor 'fd' references.
+ *
+ ****************************************************************************/
+
+int ioctl(int fd, int req, ...)
+{
+ va_list ap;
+ unsigned long arg;
+
+ /* Get the unsigned long argument */
+
+ va_start(ap, req);
+ arg = va_arg(ap, unsigned long );
+ va_end(ap);
+
+ /* Then let fs_ioctl() to the real work */
+
+ return fs_ioctl(fd, req, arg);
+}
+
+#endif /* CONFIG_LIBC_IOCTL_VARIADIC && CONFIG_NFILE_DESCRIPTORS > 0 */
diff --git a/nuttx/syscall/syscall.csv b/nuttx/syscall/syscall.csv
index 1831c652c..708a6aafb 100644
--- a/nuttx/syscall/syscall.csv
+++ b/nuttx/syscall/syscall.csv
@@ -20,13 +20,14 @@
"exit","stdlib.h","","void","int"
"fcntl","fcntl.h","CONFIG_NFILE_DESCRIPTORS > 0","int","int","int","..."
"fs_fdopen","nuttx/fs/fs.h","CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0","FAR struct file_struct*","int","int","FAR struct tcb_s*"
+"fs_ioctl","nuttx/fs/fs.h","defined(CONFIG_LIBC_IOCTL_VARIADIC) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","int","int","unsigned long"
"fsync","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","int"
"get_errno","errno.h","","int"
"getenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char*","FAR const char*"
"getpid","unistd.h","","pid_t"
"getsockopt","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int","int","FAR void*","FAR socklen_t*"
"gettimeofday","sys/time.h","","int","struct timeval*","FAR void*"
-"ioctl","sys/ioctl.h","CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0","int","int","int","unsigned long"
+"ioctl","sys/ioctl.h","!defined(CONFIG_LIBC_IOCTL_VARIADIC) && (CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0)","int","int","int","unsigned long"
"kill","signal.h","!defined(CONFIG_DISABLE_SIGNALS)","int","pid_t","int"
"listen","sys/socket.h","CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET)","int","int","int"
"lseek","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0","off_t","int","off_t","int"
diff --git a/nuttx/syscall/syscall_lookup.h b/nuttx/syscall/syscall_lookup.h
index 1c640d0b3..11cdb92e1 100644
--- a/nuttx/syscall/syscall_lookup.h
+++ b/nuttx/syscall/syscall_lookup.h
@@ -160,7 +160,11 @@ SYSCALL_LOOKUP(up_assert, 2, STUB_up_assert)
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
SYSCALL_LOOKUP(close, 1, STUB_close)
+# ifdef CONFIG_LIBC_IOCTL_VARIADIC
+ SYSCALL_LOOKUP(fs_ioctl, 3, STUB_fs_ioctl)
+# else
SYSCALL_LOOKUP(ioctl, 3, STUB_ioctl)
+# endif
SYSCALL_LOOKUP(read, 3, STUB_read)
SYSCALL_LOOKUP(write, 3, STUB_write)
SYSCALL_LOOKUP(pread, 4, STUB_pread)
diff --git a/nuttx/syscall/syscall_stublookup.c b/nuttx/syscall/syscall_stublookup.c
index 6068021b7..1a32ab687 100644
--- a/nuttx/syscall/syscall_stublookup.c
+++ b/nuttx/syscall/syscall_stublookup.c
@@ -161,8 +161,13 @@ uintptr_t STUB_timer_settime(int nbr, uintptr_t parm1, uintptr_t parm2,
*/
uintptr_t STUB_close(int nbr, uintptr_t parm1);
+#ifdef CONFIG_LIBC_IOCTL_VARIADIC
+uintptr_t STUB_fs_ioctl(int nbr, uintptr_t parm1, uintptr_t parm2,
+ uintptr_t parm3);
+#else
uintptr_t STUB_ioctl(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t parm3);
+#endif
uintptr_t STUB_read(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t parm3);
uintptr_t STUB_write(int nbr, uintptr_t parm1, uintptr_t parm2,