aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpx4dev <px4@purgatory.org>2013-01-17 01:00:46 -0800
committerpx4dev <px4@purgatory.org>2013-01-17 01:00:46 -0800
commit1a532d16dd3a90f20c3668b00ea4f3a86ea32c49 (patch)
treea770db1fe91e5a3c08e4cb03b216ac36c6f7684d
parent7d7c352fb44b718cb96096a624a19b5225e39f92 (diff)
parentcaeef71797019505fd450b1a0ae573ac5e490c6e (diff)
downloadpx4-firmware-1a532d16dd3a90f20c3668b00ea4f3a86ea32c49.tar.gz
px4-firmware-1a532d16dd3a90f20c3668b00ea4f3a86ea32c49.tar.bz2
px4-firmware-1a532d16dd3a90f20c3668b00ea4f3a86ea32c49.zip
Merge NuttX r5527
-rw-r--r--apps/ChangeLog.txt50
-rw-r--r--apps/Kconfig4
-rw-r--r--apps/Make.defs15
-rw-r--r--apps/Makefile42
-rw-r--r--apps/README.txt146
-rw-r--r--apps/builtin/Kconfig17
-rw-r--r--apps/builtin/Make.defs (renamed from apps/namedapp/Make.defs)6
-rw-r--r--apps/builtin/Makefile (renamed from apps/namedapp/Makefile)64
-rw-r--r--apps/builtin/builtin.c (renamed from apps/namedapp/namedapp.c)15
-rw-r--r--apps/builtin/exec_builtin.c423
-rw-r--r--apps/builtin/registry/Makefile61
-rw-r--r--apps/examples/Kconfig2
-rw-r--r--apps/examples/Make.defs8
-rw-r--r--apps/examples/Makefile16
-rw-r--r--apps/examples/README.txt104
-rw-r--r--apps/examples/adc/Makefile9
-rw-r--r--apps/examples/buttons/Makefile9
-rw-r--r--apps/examples/can/Makefile9
-rw-r--r--apps/examples/cdcacm/Makefile11
-rw-r--r--apps/examples/hello/Makefile11
-rw-r--r--apps/examples/helloxx/Makefile9
-rw-r--r--apps/examples/ostest/Makefile17
-rw-r--r--apps/examples/ostest/ostest.h46
-rw-r--r--apps/examples/ostest/ostest_main.c14
-rw-r--r--apps/examples/ostest/sighand.c63
-rw-r--r--apps/examples/ostest/vfork.c103
-rw-r--r--apps/examples/ostest/waitpid.c269
-rw-r--r--apps/examples/posix_spawn/Kconfig29
-rw-r--r--apps/examples/posix_spawn/Makefile130
-rw-r--r--apps/examples/posix_spawn/filesystem/Makefile88
-rw-r--r--apps/examples/posix_spawn/filesystem/hello/hello.c78
-rwxr-xr-xapps/examples/posix_spawn/filesystem/mksymtab.sh51
-rw-r--r--apps/examples/posix_spawn/filesystem/redirect/redirect.c63
-rw-r--r--apps/examples/posix_spawn/filesystem/testdata.txt2
-rw-r--r--apps/examples/posix_spawn/spawn_main.c460
-rw-r--r--apps/examples/pwm/Makefile9
-rw-r--r--apps/examples/qencoder/Makefile9
-rw-r--r--apps/examples/watchdog/Makefile9
-rw-r--r--apps/include/builtin.h111
-rw-r--r--apps/interpreters/Makefile2
-rw-r--r--apps/interpreters/ficl/Makefile1
-rw-r--r--apps/namedapp/Kconfig15
-rw-r--r--apps/nshlib/Kconfig8
-rw-r--r--apps/nshlib/Makefile3
-rw-r--r--apps/nshlib/README.txt2
-rw-r--r--apps/nshlib/nsh.h3
-rw-r--r--apps/nshlib/nsh_builtin.c (renamed from apps/nshlib/nsh_apps.c)31
-rw-r--r--apps/nshlib/nsh_codeccmd.c538
-rw-r--r--apps/nshlib/nsh_mntcmds.c77
-rw-r--r--apps/nshlib/nsh_netcmds.c1
-rw-r--r--apps/nshlib/nsh_parse.c103
-rw-r--r--apps/system/Makefile2
-rw-r--r--apps/system/free/Makefile10
-rw-r--r--apps/system/i2c/Makefile12
-rw-r--r--apps/system/install/Makefile10
-rw-r--r--apps/system/readline/Makefile1
-rw-r--r--nuttx/ChangeLog171
-rw-r--r--nuttx/Makefile.unix6
-rw-r--r--nuttx/Makefile.win19
-rw-r--r--nuttx/README.txt284
-rw-r--r--nuttx/TODO224
-rw-r--r--nuttx/arch/Kconfig23
-rw-r--r--nuttx/arch/README.txt12
-rw-r--r--nuttx/arch/arm/Kconfig11
-rw-r--r--nuttx/arch/arm/src/armv7-m/Kconfig8
-rw-r--r--nuttx/arch/arm/src/armv7-m/Toolchain.defs19
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_doirq.c8
-rw-r--r--nuttx/arch/arm/src/armv7-m/vfork.S142
-rw-r--r--nuttx/arch/arm/src/common/up_internal.h4
-rw-r--r--nuttx/arch/arm/src/common/up_vfork.c233
-rw-r--r--nuttx/arch/arm/src/common/up_vfork.h88
-rw-r--r--nuttx/arch/arm/src/stm32/Make.defs9
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_flash.c37
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_serial.c108
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_uart.h7
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c56
-rw-r--r--nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c11
-rw-r--r--nuttx/binfmt/Kconfig14
-rw-r--r--nuttx/binfmt/Makefile3
-rw-r--r--nuttx/binfmt/binfmt_exec.c9
-rw-r--r--nuttx/binfmt/binfmt_execmodule.c20
-rw-r--r--nuttx/binfmt/binfmt_loadmodule.c43
-rw-r--r--nuttx/binfmt/builtin.c196
-rw-r--r--nuttx/binfmt/elf.c2
-rw-r--r--nuttx/binfmt/libbuiltin/Kconfig4
-rw-r--r--nuttx/binfmt/libbuiltin/Make.defs52
-rw-r--r--nuttx/binfmt/libbuiltin/libbuiltin_getname.c92
-rw-r--r--nuttx/binfmt/libbuiltin/libbuiltin_isavail.c (renamed from apps/namedapp/exec_namedapp.c)119
-rw-r--r--nuttx/configs/README.txt63
-rw-r--r--nuttx/drivers/Kconfig3
-rw-r--r--nuttx/drivers/input/Kconfig19
-rw-r--r--nuttx/drivers/lcd/Make.defs4
-rw-r--r--nuttx/drivers/lcd/ug-2864ambag01.c8
-rw-r--r--nuttx/drivers/lcd/ug-2864hsweg01.c1218
-rw-r--r--nuttx/drivers/mmcsd/Kconfig4
-rw-r--r--nuttx/drivers/mtd/Make.defs3
-rw-r--r--nuttx/drivers/usbdev/composite.c4
-rw-r--r--nuttx/drivers/usbdev/pl2303.c20
-rw-r--r--nuttx/drivers/usbhost/Kconfig64
-rw-r--r--nuttx/drivers/usbhost/usbhost_hidkbd.c405
-rw-r--r--nuttx/fs/Kconfig3
-rw-r--r--nuttx/fs/Makefile15
-rw-r--r--nuttx/fs/binfs/Kconfig19
-rw-r--r--nuttx/fs/binfs/Make.defs48
-rw-r--r--nuttx/fs/binfs/fs_binfs.c (renamed from apps/namedapp/binfs.c)344
-rw-r--r--nuttx/fs/fat/Make.defs9
-rw-r--r--nuttx/fs/fat/fs_fat32.c171
-rw-r--r--nuttx/fs/fat/fs_fat32.h1
-rw-r--r--nuttx/fs/fat/fs_fat32util.c10
-rw-r--r--nuttx/fs/fs_files.c18
-rw-r--r--nuttx/fs/fs_mount.c15
-rw-r--r--nuttx/fs/mmap/Make.defs9
-rw-r--r--nuttx/fs/nfs/Make.defs9
-rw-r--r--nuttx/fs/nfs/nfs_node.h3
-rw-r--r--nuttx/fs/nfs/nfs_util.c9
-rw-r--r--nuttx/fs/nfs/nfs_vfsops.c163
-rw-r--r--nuttx/fs/nfs/rpc_clnt.c28
-rw-r--r--nuttx/fs/nxffs/Make.defs9
-rw-r--r--nuttx/fs/nxffs/nxffs.h41
-rw-r--r--nuttx/fs/nxffs/nxffs_initialize.c4
-rw-r--r--nuttx/fs/nxffs/nxffs_open.c65
-rw-r--r--nuttx/fs/romfs/Make.defs9
-rw-r--r--nuttx/fs/romfs/fs_romfs.c258
-rw-r--r--nuttx/fs/romfs/fs_romfs.h1
-rw-r--r--nuttx/fs/romfs/fs_romfsutil.c12
-rw-r--r--nuttx/graphics/Kconfig6
-rw-r--r--nuttx/graphics/Makefile3
-rw-r--r--nuttx/graphics/nxfonts/Make.defs6
-rw-r--r--nuttx/graphics/nxfonts/Makefile.sources7
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_bitmaps.c2
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_getfont.c12
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_mono5x8.h815
-rw-r--r--nuttx/include/nuttx/arch.h2
-rw-r--r--nuttx/include/nuttx/binfmt/binfmt.h8
-rw-r--r--nuttx/include/nuttx/binfmt/builtin.h (renamed from apps/include/apps.h)87
-rw-r--r--nuttx/include/nuttx/clock.h2
-rw-r--r--nuttx/include/nuttx/fs/binfs.h83
-rw-r--r--nuttx/include/nuttx/fs/dirent.h6
-rw-r--r--nuttx/include/nuttx/fs/fs.h3
-rw-r--r--nuttx/include/nuttx/fs/ioctl.h5
-rw-r--r--nuttx/include/nuttx/input/kbd_codec.h347
-rw-r--r--nuttx/include/nuttx/lcd/ug-2864hsweg01.h245
-rw-r--r--nuttx/include/nuttx/net/mii.h168
-rw-r--r--nuttx/include/nuttx/nx/nxfonts.h11
-rw-r--r--nuttx/include/nuttx/progmem.h4
-rw-r--r--nuttx/include/nuttx/sched.h34
-rw-r--r--nuttx/include/nuttx/usb/hid.h2
-rw-r--r--nuttx/include/nuttx/wqueue.h2
-rw-r--r--nuttx/include/pthread.h152
-rw-r--r--nuttx/include/semaphore.h10
-rw-r--r--nuttx/include/signal.h68
-rw-r--r--nuttx/include/spawn.h198
-rw-r--r--nuttx/include/stdbool.h4
-rw-r--r--nuttx/include/sys/types.h4
-rw-r--r--nuttx/include/sys/wait.h10
-rw-r--r--nuttx/include/unistd.h16
-rw-r--r--nuttx/libc/Kconfig89
-rw-r--r--nuttx/libc/Makefile1
-rw-r--r--nuttx/libc/math/Kconfig2
-rw-r--r--nuttx/libc/misc/Make.defs6
-rw-r--r--nuttx/libc/misc/lib_filesem.c16
-rw-r--r--nuttx/libc/misc/lib_kbddecode.c267
-rw-r--r--nuttx/libc/misc/lib_kbdencode.c151
-rw-r--r--nuttx/libc/misc/lib_streamsem.c2
-rw-r--r--nuttx/libc/spawn/Make.defs65
-rw-r--r--nuttx/libc/spawn/lib_ps.c623
-rw-r--r--nuttx/libc/spawn/lib_psa_dump.c127
-rw-r--r--nuttx/libc/spawn/lib_psa_getflags.c72
-rw-r--r--nuttx/libc/spawn/lib_psa_getschedparam.c74
-rw-r--r--nuttx/libc/spawn/lib_psa_getschedpolicy.c73
-rw-r--r--nuttx/libc/spawn/lib_psa_getsigmask.c78
-rw-r--r--nuttx/libc/spawn/lib_psa_init.c93
-rw-r--r--nuttx/libc/spawn/lib_psa_setflags.c71
-rw-r--r--nuttx/libc/spawn/lib_psa_setschedparam.c74
-rw-r--r--nuttx/libc/spawn/lib_psa_setschedpolicy.c72
-rw-r--r--nuttx/libc/spawn/lib_psa_setsigmask.c79
-rw-r--r--nuttx/libc/spawn/lib_psfa_addaction.c91
-rw-r--r--nuttx/libc/spawn/lib_psfa_addclose.c100
-rw-r--r--nuttx/libc/spawn/lib_psfa_adddup2.c104
-rw-r--r--nuttx/libc/spawn/lib_psfa_addopen.c119
-rw-r--r--nuttx/libc/spawn/lib_psfa_destroy.c96
-rw-r--r--nuttx/libc/spawn/lib_psfa_dump.c129
-rw-r--r--nuttx/libc/spawn/lib_psfa_init.c70
-rw-r--r--nuttx/libc/spawn/spawn.h121
-rw-r--r--nuttx/libc/stdio/lib_libfread.c3
-rw-r--r--nuttx/libc/string/lib_strndup.c11
-rw-r--r--nuttx/libc/unistd/Make.defs4
-rw-r--r--nuttx/libc/unistd/lib_execl.c146
-rw-r--r--nuttx/libc/unistd/lib_execsymtab.c147
-rw-r--r--nuttx/libc/unistd/lib_execv.c151
-rw-r--r--nuttx/sched/Kconfig77
-rw-r--r--nuttx/sched/Makefile7
-rw-r--r--nuttx/sched/clock_time2ticks.c42
-rw-r--r--nuttx/sched/mq_initialize.c4
-rw-r--r--nuttx/sched/os_bringup.c22
-rw-r--r--nuttx/sched/os_internal.h6
-rw-r--r--nuttx/sched/sched_addprioritized.c2
-rw-r--r--nuttx/sched/sched_addreadytorun.c8
-rw-r--r--nuttx/sched/sched_setuptaskfiles.c3
-rw-r--r--nuttx/sched/sched_unlock.c1
-rw-r--r--nuttx/sched/sched_wait.c90
-rw-r--r--nuttx/sched/sched_waitid.c256
-rw-r--r--nuttx/sched/sched_waitpid.c192
-rw-r--r--nuttx/sched/sig_kill.c7
-rw-r--r--nuttx/sched/sig_mqnotempty.c7
-rw-r--r--nuttx/sched/sig_queue.c13
-rw-r--r--nuttx/sched/sig_timedwait.c29
-rw-r--r--nuttx/sched/task_create.c2
-rw-r--r--nuttx/sched/task_deletecurrent.c20
-rw-r--r--nuttx/sched/task_exithook.c71
-rw-r--r--nuttx/sched/task_setup.c43
-rw-r--r--nuttx/sched/task_vfork.c338
-rw-r--r--nuttx/sched/timer_settime.c4
-rw-r--r--nuttx/tools/Makefile.host53
-rw-r--r--nuttx/tools/README.txt61
-rw-r--r--nuttx/tools/bdf-converter.c1
-rw-r--r--nuttx/tools/cfgdefine.c323
-rw-r--r--nuttx/tools/cfgdefine.h (renamed from apps/namedapp/namedapp.h)40
-rw-r--r--nuttx/tools/cfgparser.c162
-rw-r--r--nuttx/tools/cfgparser.h15
-rw-r--r--nuttx/tools/cmpconfig.c161
-rw-r--r--nuttx/tools/configure.bat127
-rw-r--r--nuttx/tools/configure.c890
-rwxr-xr-xnuttx/tools/configure.sh21
-rwxr-xr-xnuttx/tools/kconfig.bat131
-rw-r--r--nuttx/tools/mkconfig.c10
-rw-r--r--nuttx/tools/mksyscall.c6
-rw-r--r--nuttx/tools/mkversion.c4
228 files changed, 15510 insertions, 1911 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 0695747f8..14eb78950 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -435,3 +435,53 @@
logic to find the absolute path to the program using the PATH variable.
6.25 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
+
+ * Makefiles: Removed dependency of distclean on clean in most top-level
+ files. It makes sense for 'leaf' Makefiles to have this dependency,
+ but it does not make sense for upper-level Makefiles.
+ * apps/namedapp/: Renamed to builtins in preparation for another change.
+ * .context: Removed the .context kludge. This caused lots of problems
+ when changing configurations because there is no easy way to get the
+ system to rebuild the context. Now, the context will be rebuilt
+ whenever there is a change in either .config or the Makefile.
+ * apps/builtin/registry: Updated new built-in registration logic to handle
+ cases where (1) old apps/.config is used, and (2) applications ared
+ removed, not just added.
+ * apps/examples/nettest/Makefile: Fix an error that crept in during
+ some of the recent, massive build system changes.
+ * apps/builtin/Makefile: Need to have auto-generated header files
+ in place early in the dependency generation phase to avoid warnings.
+ It is not important if they are only stubbed out header files at
+ this build phase.
+ * apps/examples/hidbkd: Now supports decoding of encoded special keys
+ if CONFIG_EXAMPLES_HIDKBD_ENCODED is defined.
+ * apps/examples/hidbkd: Add support for decoding key release events
+ as well. However, the USB HID keyboard drier has not yet been
+ updated to detect key release events. That is kind of tricky in
+ the USB HID keyboard report data.
+ * apps/examples/wlan: Remove non-functional example.
+ * apps/examples/ostest/vfork.c: Added a test of vfork().
+ * apps/exampes/posix_spawn: Added a test of poxis_spawn().
+ * apps/examples/ostest: Extend signal handler test to catch
+ death-of-child signals (SIGCHLD).
+ * apps/examples/ostest/waitpid.c: Add a test for waitpid(), waitid(),
+ and wait().
+ * builtin/binfs.c: Add hooks for dup() method (not implemented).
+ * builtin/exec_builtin.c, nshlib/nsh_parse.c, and nshlib/nsh_builtin.c:
+ NSH now supports re-direction of I/O to files (but still not from).
+ * builtin/binfs.c: Greatly simplified (it is going to need to be
+ very lightweight). Now supports open, close, and a new ioctl to recover
+ the builtin filename. The latter will be needed to support a binfs
+ binfmt.
+ * builtin/binfs.c: Move apps/builtin/binfs.c to fs/binfs/fs_binfs.c
+ CONFIG_APPS_BINDIR rename CONFIG_FS_BINFS
+ * apps/include/builtin.h: Some of the content of
+ apps/include/apps.h moved to include/nuttx/binfmt/builtin.h.
+ apps/include/apps.h renamed builtin.h
+ * apps/builtin/exec_builtins.c: Move utility builtin
+ utility functions from apps/builtin/exec_builtins.c to
+ binfmt/libbuiltin/libbuiltin_utils.c
+ * apps/nshlib/nsh_mountcmds.c: The block driver/source
+ argument is now optional. Many files systems do not need
+ a source and it is really stupid to have to enter a bogus
+ source parameter.
diff --git a/apps/Kconfig b/apps/Kconfig
index ea9bd2d31..68c36f5a5 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -3,8 +3,8 @@
# see misc/tools/kconfig-language.txt.
#
-menu "Named Applications"
-source "$APPSDIR/namedapp/Kconfig"
+menu "Built-In Applications"
+source "$APPSDIR/builtin/Kconfig"
endmenu
menu "Examples"
diff --git a/apps/Make.defs b/apps/Make.defs
index 53ac7f8be..f7e6aa08d 100644
--- a/apps/Make.defs
+++ b/apps/Make.defs
@@ -34,8 +34,17 @@
#
############################################################################
+BUILTIN_REGISTRY = $(APPDIR)$(DELIM)builtin$(DELIM)registry
+
+ifeq ($(CONFIG_NUTTX_NEWCONFIG),y)
+DEPCONFIG = $(TOPDIR)$(DELIM).config
+else
+DEPCONFIG = $(TOPDIR)$(DELIM).config $(APPDIR)$(DELIM).config
+endif
+
define REGISTER
- @echo "Register: $1"
- @echo "{ \"$1\", $2, $3, $4 }," >> "$(APPDIR)/namedapp/namedapp_list.h"
- @echo "EXTERN int $4(int argc, char *argv[]);" >> "$(APPDIR)/namedapp/namedapp_proto.h"
+ $(Q) echo "Register: $1"
+ $(Q) echo "{ \"$1\", $2, $3, $4 }," > "$(BUILTIN_REGISTRY)$(DELIM)$4.bdat"
+ $(Q) echo "int $4(int argc, char *argv[]);" > "$(BUILTIN_REGISTRY)$(DELIM)$4.pdat"
+ $(Q) touch "$(BUILTIN_REGISTRY)$(DELIM).updated"
endef
diff --git a/apps/Makefile b/apps/Makefile
index f0de58e25..d0cc23a5f 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -45,14 +45,11 @@ APPDIR = ${shell pwd}
# action. It is created by the configured appconfig file (a copy of which
# appears in this directory as .config)
# SUBDIRS is the list of all directories containing Makefiles. It is used
-# only for cleaning. namedapp must always be the first in the list. This
+# only for cleaning. builtin must always be the first in the list. This
# list can be extended by the .config file as well.
CONFIGURED_APPS =
-#SUBDIRS = examples graphics interpreters modbus namedapp nshlib netutils system
-ALL_SUBDIRS = $(dir $(shell /usr/bin/find . -name Makefile))
-SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS))
-
+SUBDIRS = examples graphics interpreters modbus builtin nshlib netutils system
# There are two different mechanisms for obtaining the list of configured
# directories:
@@ -73,20 +70,20 @@ SUBDIRS = namedapp/ $(filter-out ./ ./namedapp/ ./examples/,$(ALL_SUBDIRS))
ifeq ($(CONFIG_NUTTX_NEWCONFIG),y)
-# namedapp/Make.defs must be included first
+# builtin/Make.defs must be included first
--include namedapp/Make.defs
--include examples/Make.defs
--include graphics/Make.defs
--include interpreters/Make.defs
--include modbus/Make.defs
--include netutils/Make.defs
--include nshlib/Make.defs
--include system/Make.defs
+include builtin/Make.defs
+include examples/Make.defs
+include graphics/Make.defs
+include interpreters/Make.defs
+include modbus/Make.defs
+include netutils/Make.defs
+include nshlib/Make.defs
+include system/Make.defs
# INSTALLED_APPS is the list of currently available application directories. It
# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent
-# application directory. namedapp is always in the list of applications to be
+# application directory. builtin is always in the list of applications to be
# built.
INSTALLED_APPS =
@@ -98,10 +95,10 @@ else
# INSTALLED_APPS is the list of currently available application directories. It
# is the same as CONFIGURED_APPS, but filtered to exclude any non-existent
-# application directory. namedapp is always in the list of applications to be
+# application directory. builtin is always in the list of applications to be
# built.
-INSTALLED_APPS = namedapp
+INSTALLED_APPS = builtin
endif
# Create the list of available applications (INSTALLED_APPS)
@@ -139,21 +136,16 @@ $(INSTALLED_APPS):
$(BIN): $(INSTALLED_APPS)
-.context:
+context:
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
$(Q) for %%G in ($(INSTALLED_APPS)) do ( \
- if exist %%G\.context del /f /q %%G\.context \
$(MAKE) -C %%G TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" context \
)
else
$(Q) for dir in $(INSTALLED_APPS) ; do \
- rm -f $$dir/.context ; \
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" context ; \
done
endif
- $(Q) touch $@
-
-context: .context
.depend: context Makefile $(SRCS)
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
@@ -184,13 +176,12 @@ endif
$(call DELFILE, $(BIN))
$(call CLEAN)
-distclean: # clean
+distclean:
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
$(Q) for %%G in ($(SUBDIRS)) do ( \
$(MAKE) -C %%G distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" \
)
$(call DELFILE, .config)
- $(call DELFILE, .context)
$(call DELFILE, .depend)
$(Q) ( if exist external ( \
echo ********************************************************" \
@@ -202,7 +193,6 @@ else
$(MAKE) -C $$dir distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"; \
done
$(call DELFILE, .config)
- $(call DELFILE, .context)
$(call DELFILE, .depend)
$(Q) ( if [ -e external ]; then \
echo "********************************************************"; \
diff --git a/apps/README.txt b/apps/README.txt
index 7a379254e..55accfcf6 100644
--- a/apps/README.txt
+++ b/apps/README.txt
@@ -6,26 +6,25 @@ Contents
General
Directory Location
- Named Applications
- Named Startup main() function
+ Built-In Applications
NuttShell (NSH) Built-In Commands
Synchronous Built-In Commands
Application Configuration File
- Example Named Application
+ Example Built-In Application
Building NuttX with Board-Specific Pieces Outside the Source Tree
General
-------
This folder provides various applications found in sub-directories. These
-applications are not inherently a part of NuttX but are provided you help
+applications are not inherently a part of NuttX but are provided to help
you develop your own applications. The apps/ directory is a "break away"
-part of the configuration that you may chose to use or not.
+part of the configuration that you may choose to use or not.
Directory Location
------------------
The default application directory used by the NuttX build should be named
apps/ (or apps-x.y/ where x.y is the NuttX version number). This apps/
-directoy should appear in the directory tree at the same level as the
+directory should appear in the directory tree at the same level as the
NuttX directory. Like:
.
@@ -47,14 +46,14 @@ ways to do that:
path to the application directory on the configuration command line
like: ./configure.sh -a <app-dir> <board-name>/<config-name>
-Named Applications
-------------------
+Built-In Applications
+---------------------
NuttX also supports applications that can be started using a name string.
In this case, application entry points with their requirements are gathered
together in two files:
- - namedapp/namedapp_proto.h Entry points, prototype function
- - namedapp/namedapp_list.h Application specific information and requirements
+ - builtin/builtin_proto.h Entry points, prototype function
+ - builtin/builtin_list.h Application specific information and requirements
The build occurs in several phases as different build targets are executed:
(1) context, (2) depend, and (3) default (all). Application information is
@@ -62,18 +61,18 @@ collected during the make context build phase.
To execute an application function:
- exec_namedapp() is defined in the nuttx/include/apps/apps.h
+ exec_builtin() is defined in the nuttx/include/apps/builtin.h
NuttShell (NSH) Built-In Commands
---------------------------------
-One use of named applications is to provide a way of invoking your custom
+One use of builtin applications is to provide a way of invoking your custom
application through the NuttShell (NSH) command line. NSH will support
a seamless method invoking the applications, when the following option is
enabled in the NuttX configuration file:
CONFIG_NSH_BUILTIN_APPS=y
-Applications registered in the apps/namedapp/namedapp_list.h file will then
+Applications registered in the apps/builtin/builtin_list.h file will then
be accessible from the NSH command line. If you type 'help' at the NSH
prompt, you will see a list of the registered commands.
@@ -96,11 +95,11 @@ after the NSH command.
Application Configuration File
------------------------------
-A special configuration file is used to configure which applications
-are to be included in the build. The source for this file is
-configs/<board>/<configuration>/appconfig. The existence of the appconfig
-file in the board configuration directory is sufficient to enable building
-of applications.
+The old-style NuttX configuration uses a special configuration file is
+used to configure which applications are to be included in the build.
+The source for this file is configs/<board>/<configuration>/appconfig.
+The existence of the appconfig file in the board configuration directory\
+is sufficient to enable building of applications.
The appconfig file is copied into the apps/ directory as .config when
NuttX is configured. .config is included in the toplevel apps/Makefile.
@@ -109,38 +108,101 @@ CONFIGURED_APPS list like:
CONFIGURED_APPS += examples/hello system/poweroff
-Named Start-Up main() function
-------------------------------
-A named application can even be used as the main, start-up entry point
-into your embedded software. When the user defines this option in
-the NuttX configuration file:
+The new NuttX configuration uses kconfig-frontends tools and only the
+NuttX .config file. The new configuration is indicated by the existence
+of the definition CONFIG_NUTTX_NEWCONFIG=y in the NuttX .config file.
+If CONFIG_NUTTX_NEWCONFIG is defined, then the Makefile will:
+
+- Assume that there is no apps/.config file and will instead
+- Include Make.defs files from each of the subdirectories.
+
+When an application is enabled using the kconfig-frontends tool, then
+a new definition is added to the NuttX .config file. For example, if
+you want to enable apps/examples/hello then the old apps/.config would
+have had:
+
+ CONFIGURED_APPS += examples/hello
+
+But in the new configuration there will be no apps/.config file and,
+instead, the NuttX .config will have:
+
+ CONFIG_EXAMPLES_HELLO=y
- CONFIG_BUILTIN_APP_START=<application name>
-
-that application shall be invoked immediately after system starts
-*instead* of the default "user_start" entry point.
-Note that <application name> must be provided as: "hello",
-will call:
+This will select the apps/examples/hello in the following way:
- int hello_main(int argc, char *argv[])
+- The top-level make will include examples/Make.defs
+- examples/Make.defs will set CONFIGURED_APPS += examples/hello
+ like this:
-Example Named Application
--------------------------
+ ifeq ($(CONFIG_EXAMPLES_HELLO),y)
+ CONFIGURED_APPS += examples/hello
+ endif
+
+Thus accomplishing the same thing with no apps/.config file.
+
+Example Built-In Application
+----------------------------
An example application skeleton can be found under the examples/hello
-sub-directory. This example shows how a named application can be added
+sub-directory. This example shows how a builtin application can be added
to the project. One must define:
- 1. create sub-directory as: appname
- 2. provide entry point: appname_main()
- 3. set the requirements in the file: Makefile, specially the lines:
+Old configuration method:
+
+ 1. Create sub-directory as: appname
+
+ 2. In this directory there should be:
+
+ - A Makefile, and
+ - The application source code.
+
+ 3. The application source code should provide the entry point:
+ appname_main()
+
+ 4. Set the requirements in the file: Makefile, specially the lines:
+
+ APPNAME = appname
+ PRIORITY = SCHED_PRIORITY_DEFAULT
+ STACKSIZE = 768
+ ASRCS = asm source file list as a.asm b.asm ...
+ CSRCS = C source file list as foo1.c foo2.c ..
+
+ Look at some of the other Makefiles for examples. Note the
+ special registration logic needed for the context: target
+
+ 5. Add the to the application to the CONFIGIURED_APPS in the
+ apps/.config file:
+
+ CONFIGURED_APPS += appname
+
+New Configuration Method:
+
+ 1. Create sub-directory as: appname
+
+ 2. In this directory there should be:
+
+ - A Make.defs file that would be included by the apps/Makefile
+ - A Kconfig file that would be used by the configuration tool (see
+ misc/tools/kconfig-language.txt). This Kconfig file should be
+ included by the apps/Kconfig file
+ - A Makefile, and
+ - The application source code.
+
+ 3. The application source code should provide the entry point:
+ appname_main()
+
+ 4. Set the requirements in the file: Makefile, specially the lines:
+
+ APPNAME = appname
+ PRIORITY = SCHED_PRIORITY_DEFAULT
+ STACKSIZE = 768
+ ASRCS = asm source file list as a.asm b.asm ...
+ CSRCS = C source file list as foo1.c foo2.c ..
- APPNAME = appname
- PRIORITY = SCHED_PRIORITY_DEFAULT
- STACKSIZE = 768
- ASRCS = asm source file list as a.asm b.asm ...
- CSRCS = C source file list as foo1.c foo2.c ..
+ 4b. The Make.defs file should include a line like:
- 4. add application in the apps/.config
+ ifeq ($(CONFIG_APPNAME),y)
+ CONFIGURED_APPS += appname
+ endif
Building NuttX with Board-Specific Pieces Outside the Source Tree
-----------------------------------------------------------------
diff --git a/apps/builtin/Kconfig b/apps/builtin/Kconfig
new file mode 100644
index 000000000..c3371d708
--- /dev/null
+++ b/apps/builtin/Kconfig
@@ -0,0 +1,17 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+if BUILTIN
+
+config BUILTIN_PROXY_STACKSIZE
+ int "Builtin Proxy Stack Size"
+ default 1024
+ ---help---
+ If exec_builtin uses I/O redirection options, then it will require
+ an intermediary/proxy task to muck with the file descriptors. This
+ configuration item specifies the stack size used for the proxy. Default:
+ 1024 bytes.
+
+endif
diff --git a/apps/namedapp/Make.defs b/apps/builtin/Make.defs
index 399fefee8..ab6292cc3 100644
--- a/apps/namedapp/Make.defs
+++ b/apps/builtin/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# apps/namedapps/Make.defs
+# apps/builtin/Make.defs
# Adds selected applications to apps/ build
#
# Copyright (C) 2012 Gregory Nutt. All rights reserved.
@@ -34,7 +34,7 @@
#
############################################################################
-ifeq ($(CONFIG_NAMEDAPP),y)
-CONFIGURED_APPS += namedapp
+ifeq ($(CONFIG_BUILTIN),y)
+CONFIGURED_APPS += builtin
endif
diff --git a/apps/namedapp/Makefile b/apps/builtin/Makefile
index a88c73567..d77054f41 100644
--- a/apps/namedapp/Makefile
+++ b/apps/builtin/Makefile
@@ -1,5 +1,5 @@
############################################################################
-# apps/nshlib/Makefile
+# apps/builtin/Makefile
#
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
@@ -33,20 +33,13 @@
#
############################################################################
--include $(TOPDIR)/.config
-include $(TOPDIR)/Make.defs
include $(APPDIR)/Make.defs
-# NSH Library
-
# Source and object files
ASRCS =
-CSRCS = namedapp.c exec_namedapp.c
-
-ifeq ($(CONFIG_APPS_BINDIR),y)
-CSRCS += binfs.c
-endif
+CSRCS = builtin.c exec_builtin.c
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
@@ -70,7 +63,7 @@ VPATH =
# Build Targets
all: .built
-.PHONY: .context context depend clean distclean
+.PHONY: context depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
@@ -78,33 +71,60 @@ $(AOBJS): %$(OBJEXT): %.S
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
-.built: $(OBJS)
+registry$(DELIM).updated:
+ $(V) $(MAKE) -C registry .updated TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
+
+builtin_list.h: registry$(DELIM).updated
+ $(call DELFILE, builtin_list.h)
+ $(Q) touch builtin_list.h
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ $(Q) for /f %%G in ('dir /b registry\*.bdat`) do ( type registry\%%G >> builtin_list.h )
+else
+ $(Q) ( \
+ filelist=`ls registry/*.bdat 2>/dev/null || echo ""`; \
+ for file in $$filelist; \
+ do cat $$file >> builtin_list.h; \
+ done; \
+ )
+endif
+
+builtin_proto.h: registry$(DELIM).updated
+ $(call DELFILE, builtin_proto.h)
+ $(Q) touch builtin_proto.h
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ $(Q) for /f %%G in ('dir /b registry\*.pdat`) do ( type registry\%%G >> builtin_proto.h )
+else
+ $(Q) ( \
+ filelist=`ls registry/*.pdat 2>/dev/null || echo ""`; \
+ for file in $$filelist; \
+ do cat $$file >> builtin_proto.h; \
+ done; \
+ )
+endif
+
+.built: builtin_list.h builtin_proto.h $(OBJS)
$(call ARCHIVE, $(BIN), $(OBJS))
$(Q) touch .built
-.context:
- @echo "/* List of application requirements, generated during make context. */" > namedapp_list.h
- @echo "/* List of application entry points, generated during make context. */" > namedapp_proto.h
- $(Q) touch $@
-
-context: .context
+context:
+ $(Q) $(MAKE) -C registry context TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
-.depend: Makefile $(SRCS)
+.depend: Makefile $(SRCS) builtin_list.h builtin_proto.h
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
depend: .depend
clean:
+ $(Q) $(MAKE) -C registry clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
$(call DELFILE, .built)
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
+ $(Q) $(MAKE) -C registry distclean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)"
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
- $(call DELFILE, namedapp_list.h)
- $(call DELFILE, namedapp_proto.h)
+ $(call DELFILE, builtin_list.h)
+ $(call DELFILE, builtin_proto.h)
-include Make.dep
-
diff --git a/apps/namedapp/namedapp.c b/apps/builtin/builtin.c
index d59ce6e3b..7655a531d 100644
--- a/apps/namedapp/namedapp.c
+++ b/apps/builtin/builtin.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * apps/namedaps/namedapp.c
+ * apps/builtin/builtin.c
*
* Copyright (C) 2011 Uros Platise. All rights reserved.
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
@@ -40,7 +40,8 @@
****************************************************************************/
#include <nuttx/config.h>
-#include <apps/apps.h>
+
+#include <nuttx/binfmt/builtin.h>
/****************************************************************************
* Private Types
@@ -62,11 +63,11 @@ extern "C" {
#define EXTERN extern
#endif
-#include "namedapp_proto.h"
+#include "builtin_proto.h"
-const struct namedapp_s namedapps[] =
+const struct builtin_s g_builtins[] =
{
-# include "namedapp_list.h"
+# include "builtin_list.h"
{ NULL, 0, 0, 0 }
};
@@ -88,9 +89,9 @@ const struct namedapp_s namedapps[] =
* Public Functions
****************************************************************************/
-int number_namedapps(void)
+int number_builtins(void)
{
- return sizeof(namedapps)/sizeof(struct namedapp_s) - 1;
+ return sizeof(g_builtins)/sizeof(struct builtin_s) - 1;
}
diff --git a/apps/builtin/exec_builtin.c b/apps/builtin/exec_builtin.c
new file mode 100644
index 000000000..05648590d
--- /dev/null
+++ b/apps/builtin/exec_builtin.c
@@ -0,0 +1,423 @@
+/****************************************************************************
+ * apps/builtin/exec_builtin.c
+ *
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 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 <sched.h>
+#include <string.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/builtin.h>
+#include <apps/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_BUILTIN_PROXY_STACKSIZE
+# define CONFIG_BUILTIN_PROXY_STACKSIZE 1024
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct builtin_parms_s
+{
+ /* Input values */
+
+ FAR const char *redirfile;
+ FAR const char **argv;
+ int oflags;
+ int index;
+
+ /* Returned values */
+
+ pid_t result;
+ int errcode;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_builtin_parmsem = SEM_INITIALIZER(1);
+static sem_t g_builtin_execsem = SEM_INITIALIZER(0);
+static struct builtin_parms_s g_builtin_parms;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bultin_semtake and builtin_semgive
+ *
+ * Description:
+ * Give and take semaphores
+ *
+ * Input Parameters:
+ *
+ * sem - The semaphore to act on.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void bultin_semtake(FAR sem_t *sem)
+{
+ int ret;
+
+ do
+ {
+ ret = sem_wait(sem);
+ ASSERT(ret == 0 || errno == EINTR);
+ }
+ while (ret != 0);
+}
+
+#define builtin_semgive(sem) sem_post(sem)
+
+/****************************************************************************
+ * Name: builtin_taskcreate
+ *
+ * Description:
+ * Execute the builtin task
+ *
+ * Returned Value:
+ * On success, the task ID of the builtin task is returned; On failure, -1
+ * (ERROR) is returned and the errno is set appropriately.
+ *
+ ****************************************************************************/
+
+static int builtin_taskcreate(int index, FAR const char **argv)
+{
+ int ret;
+
+ /* Disable pre-emption. This means that although we start the builtin
+ * application here, it will not actually run until pre-emption is
+ * re-enabled below.
+ */
+
+ sched_lock();
+
+ /* Start the builtin application task */
+
+ ret = TASK_CREATE(g_builtins[index].name, g_builtins[index].priority,
+ g_builtins[index].stacksize, g_builtins[index].main,
+ (argv) ? &argv[1] : (FAR const char **)NULL);
+
+ /* If robin robin scheduling is enabled, then set the scheduling policy
+ * of the new task to SCHED_RR before it has a chance to run.
+ */
+
+#if CONFIG_RR_INTERVAL > 0
+ if (ret > 0)
+ {
+ struct sched_param param;
+
+ /* Pre-emption is disabled so the task creation and the
+ * following operation will be atomic. The priority of the
+ * new task cannot yet have changed from its initial value.
+ */
+
+ param.sched_priority = g_builtins[index].priority;
+ (void)sched_setscheduler(ret, SCHED_RR, &param);
+ }
+#endif
+
+ /* Now let the builtin application run */
+
+ sched_unlock();
+
+ /* Return the task ID of the new task if the task was sucessfully
+ * started. Otherwise, ret will be ERROR (and the errno value will
+ * be set appropriately).
+ */
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: builtin_proxy
+ *
+ * Description:
+ * Perform output redirection, then execute the builtin task.
+ *
+ * Input Parameters:
+ * Standard task start-up parameters
+ *
+ * Returned Value:
+ * Standard task return value.
+ *
+ ****************************************************************************/
+
+static int builtin_proxy(int argc, char *argv[])
+{
+ int fd;
+ int ret = ERROR;
+
+ /* Open the output file for redirection */
+
+ svdbg("Open'ing redirfile=%s oflags=%04x mode=0644\n",
+ g_builtin_parms.redirfile, g_builtin_parms.oflags);
+
+ fd = open(g_builtin_parms.redirfile, g_builtin_parms.oflags, 0644);
+ if (fd < 0)
+ {
+ /* Remember the errno value. ret is already set to ERROR */
+
+ g_builtin_parms.errcode = errno;
+ sdbg("ERROR: open of %s failed: %d\n",
+ g_builtin_parms.redirfile, g_builtin_parms.errcode);
+ }
+
+ /* Does the return file descriptor happen to match the required file
+ * desciptor number?
+ */
+
+ else if (fd != 1)
+ {
+ /* No.. dup2 to get the correct file number */
+
+ svdbg("Dup'ing %d->1\n", fd);
+
+ ret = dup2(fd, 1);
+ if (ret < 0)
+ {
+ g_builtin_parms.errcode = errno;
+ sdbg("ERROR: dup2 failed: %d\n", g_builtin_parms.errcode);
+ }
+
+ svdbg("Closing fd=%d\n", fd);
+ close(fd);
+ }
+
+ /* Was the setup successful? */
+
+ if (ret == OK)
+ {
+ /* Yes.. Start the task. On success, the task ID of the builtin task
+ * is returned; On failure, -1 (ERROR) is returned and the errno
+ * is set appropriately.
+ */
+
+ ret = builtin_taskcreate(g_builtin_parms.index, g_builtin_parms.argv);
+ if (ret < 0)
+ {
+ g_builtin_parms.errcode = errno;
+ sdbg("ERROR: builtin_taskcreate failed: %d\n",
+ g_builtin_parms.errcode);
+ }
+ }
+
+ /* Post the semaphore to inform the parent task that we have completed
+ * what we need to do.
+ */
+
+ g_builtin_parms.result = ret;
+ builtin_semgive(&g_builtin_execsem);
+ return 0;
+}
+
+/****************************************************************************
+ * Name: builtin_startproxy
+ *
+ * Description:
+ * Perform output redirection, then execute the builtin task.
+ *
+ * Input Parameters:
+ * Standard task start-up parameters
+ *
+ * Returned Value:
+ * On success, the task ID of the builtin task is returned; On failure, -1
+ * (ERROR) is returned and the errno is set appropriately.
+ *
+ ****************************************************************************/
+
+static inline int builtin_startproxy(int index, FAR const char **argv,
+ FAR const char *redirfile, int oflags)
+{
+ struct sched_param param;
+ pid_t proxy;
+ int errcode;
+ int ret;
+
+ DEBUGASSERT(path);
+
+ svdbg("index=%d argv=%p redirfile=%s oflags=%04x\n",
+ index, argv, redirfile, oflags);
+
+ /* We will have to go through an intermediary/proxy task in order to
+ * perform the I/O redirection. This would be a natural place to fork().
+ * However, true fork() behavior requires an MMU and most implementations
+ * of vfork() are not capable of these operations.
+ *
+ * Even without fork(), we can still do the job, but parameter passing is
+ * messier. Unfortunately, there is no (clean) way to pass binary values
+ * as a task parameter, so we will use a semaphore-protected global
+ * structure.
+ */
+
+ /* Get exclusive access to the global parameter structure */
+
+ bultin_semtake(&g_builtin_parmsem);
+
+ /* Populate the parameter structure */
+
+ g_builtin_parms.redirfile = redirfile;
+ g_builtin_parms.argv = argv;
+ g_builtin_parms.result = ERROR;
+ g_builtin_parms.oflags = oflags;
+ g_builtin_parms.index = index;
+
+ /* Get the priority of this (parent) task */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ errcode = errno;
+ sdbg("ERROR: sched_getparam failed: %d\n", errcode);
+ goto errout;
+ }
+
+ /* Start the intermediary/proxy task at the same priority as the parent task. */
+
+ proxy = TASK_CREATE("builtin_proxy", param.sched_priority,
+ CONFIG_BUILTIN_PROXY_STACKSIZE, (main_t)builtin_proxy,
+ (FAR const char **)NULL);
+ if (proxy < 0)
+ {
+ errcode = errno;
+ sdbg("ERROR: Failed to start builtin_proxy: %d\n", errcode);
+ goto errout;
+ }
+
+ /* Wait for the proxy to complete its job. We could use waitpid()
+ * for this.
+ */
+
+ bultin_semtake(&g_builtin_execsem);
+
+ /* Get the result and relinquish our access to the parameter structure */
+
+ set_errno(g_builtin_parms.errcode);
+ builtin_semgive(&g_builtin_parmsem);
+ return g_builtin_parms.result;
+
+errout:
+ set_errno(errcode);
+ builtin_semgive(&g_builtin_parmsem);
+ return ERROR;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exec_builtin
+ *
+ * Description:
+ * Executes builtin applications registered during 'make context' time.
+ * New application is run in a separate task context (and thread).
+ *
+ * Input Parameter:
+ * filename - Name of the linked-in binary to be started.
+ * argv - Argument list
+ * redirfile - If output if redirected, this parameter will be non-NULL
+ * and will provide the full path to the file.
+ * oflags - If output is redirected, this parameter will provide the
+ * open flags to use. This will support file replacement
+ * of appending to an existing file.
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * Returns the PID of the exec'ed module. On failure, it.returns
+ * -1 (ERROR) and sets errno appropriately.
+ *
+ ****************************************************************************/
+
+int exec_builtin(FAR const char *appname, FAR const char **argv,
+ FAR const char *redirfile, int oflags)
+{
+ int index;
+ int ret = ERROR;
+
+ /* Verify that an application with this name exists */
+
+ index = builtin_isavail(appname);
+ if (index >= 0)
+ {
+ /* Is output being redirected? */
+
+ if (redirfile)
+ {
+ ret = builtin_startproxy(index, argv, redirfile, oflags);
+ }
+ else
+ {
+ /* Start the builtin application task */
+
+ ret = builtin_taskcreate(index, argv);
+ }
+ }
+
+
+ /* Return the task ID of the new task if the task was sucessfully
+ * started. Otherwise, ret will be ERROR (and the errno value will
+ * be set appropriately).
+ */
+
+ return ret;
+}
diff --git a/apps/builtin/registry/Makefile b/apps/builtin/registry/Makefile
new file mode 100644
index 000000000..4ecd5da9f
--- /dev/null
+++ b/apps/builtin/registry/Makefile
@@ -0,0 +1,61 @@
+############################################################################
+# apps/builtin/registry/Makefile
+#
+# Copyright (C) 2012 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.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# NSH Library
+
+all:
+.PHONY: context depend clean distclean
+
+.updated: $(DEPCONFIG)
+ $(call DELFILE, *.bdat)
+ $(call DELFILE, *.pdat)
+ $(Q) touch .updated
+
+# This must run before any other context target
+
+context: .updated
+
+depend:
+
+clean:
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, *.bdat)
+ $(call DELFILE, *.pdat)
+ $(call DELFILE, .updated)
diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig
index ae5f0a61a..ec0a97dd4 100644
--- a/apps/examples/Kconfig
+++ b/apps/examples/Kconfig
@@ -39,6 +39,7 @@ source "$APPSDIR/examples/pashello/Kconfig"
source "$APPSDIR/examples/pipe/Kconfig"
source "$APPSDIR/examples/poll/Kconfig"
source "$APPSDIR/examples/pwm/Kconfig"
+source "$APPSDIR/examples/posix_spawn/Kconfig"
source "$APPSDIR/examples/qencoder/Kconfig"
source "$APPSDIR/examples/relays/Kconfig"
source "$APPSDIR/examples/rgmp/Kconfig"
@@ -58,5 +59,4 @@ source "$APPSDIR/examples/usbterm/Kconfig"
source "$APPSDIR/examples/watchdog/Kconfig"
source "$APPSDIR/examples/wget/Kconfig"
source "$APPSDIR/examples/wgetjson/Kconfig"
-source "$APPSDIR/examples/wlan/Kconfig"
source "$APPSDIR/examples/xmlrpc/Kconfig"
diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs
index 91f1331df..68d4d4340 100644
--- a/apps/examples/Make.defs
+++ b/apps/examples/Make.defs
@@ -182,6 +182,10 @@ ifeq ($(CONFIG_EXAMPLES_PWM),y)
CONFIGURED_APPS += examples/pwm
endif
+ifeq ($(CONFIG_EXAMPLES_POSIXSPAWN),y)
+CONFIGURED_APPS += examples/posix_spawn
+endif
+
ifeq ($(CONFIG_EXAMPLES_QENCODER),y)
CONFIGURED_APPS += examples/qencoder
endif
@@ -254,10 +258,6 @@ ifeq ($(CONFIG_EXAMPLES_WGETJSON),y)
CONFIGURED_APPS += examples/wgetjson
endif
-ifeq ($(CONFIG_EXAMPLES_WLAN),y)
-CONFIGURED_APPS += examples/wlan
-endif
-
ifeq ($(CONFIG_EXAMPLES_XMLRPC),y)
CONFIGURED_APPS += examples/xmlrpc
endif
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index bdbfd4de8..939748075 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -40,9 +40,9 @@
SUBDIRS = adc buttons can cdcacm composite cxxtest dhcpd discover elf ftpc
SUBDIRS += ftpd hello helloxx hidkbd igmp json keypadtest lcdrw mm modbus mount
SUBDIRS += nettest nsh null nx nxconsole nxffs nxflat nxhello nximage
-SUBDIRS += nxlines nxtext ostest pashello pipe poll pwm qencoder relays
-SUBDIRS += rgmp romfs serloop telnetd thttpd tiff touchscreen udp uip
-SUBDIRS += usbserial sendmail usbstorage usbterm watchdog wget wgetjson wlan
+SUBDIRS += nxlines nxtext ostest pashello pipe poll pwm posix_spawn qencoder
+SUBDIRS += relays rgmp romfs serloop telnetd thttpd tiff touchscreen udp uip
+SUBDIRS += usbserial sendmail usbstorage usbterm watchdog wget wgetjson
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
@@ -57,13 +57,11 @@ SUBDIRS += usbserial sendmail usbstorage usbterm watchdog wget wgetjson wlan
CNTXTDIRS = pwm
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
-CNTXTDIRS += adc can cdcacm composite cxxtest dhcpd discover ftpd json keypadtest
-CNTXTDIRS += modbus nettest nxlines relays qencoder telnetd watchdog wgetjson
+CNTXTDIRS += adc can cdcacm composite cxxtest dhcpd discover ftpd hello json
+CNTXTDIRS += keypadtestmodbus nettest nxlines relays qencoder telnetd watchdog
+CNTXTDIRS += wgetjson
endif
-ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y)
-CNTXTDIRS += hello
-endif
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)
CNTXTDIRS += helloxx
endif
@@ -120,7 +118,7 @@ depend: $(foreach SDIR, $(SUBDIRS), $(SDIR)_depend)
clean: $(foreach SDIR, $(SUBDIRS), $(SDIR)_clean)
-distclean: clean $(foreach SDIR, $(SUBDIRS), $(SDIR)_distclean)
+distclean: $(foreach SDIR, $(SUBDIRS), $(SDIR)_distclean)
-include Make.dep
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index e40a63be9..5996cbb70 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -329,10 +329,10 @@ examples/elf
each program in the ROMFS file system is executed. Requires CONFIG_ELF.
Other configuration options:
- CONFIG_EXAMPLES_ELF_DEVMINOR - The minor device number of the ROMFS block.
- For example, the N in /dev/ramN. Used for registering the RAM block driver
- that will hold the ROMFS file system containing the ELF executables to be
- tested. Default: 0
+ CONFIG_EXAMPLES_ELF_DEVMINOR - The minor device number of the ROMFS block
+ driver. For example, the N in /dev/ramN. Used for registering the RAM
+ block driver that will hold the ROMFS file system containing the ELF
+ executables to be tested. Default: 0
CONFIG_EXAMPLES_ELF_DEVPATH - The path to the ROMFS block driver device. This
must match EXAMPLES_ELF_DEVMINOR. Used for registering the RAM block driver
@@ -348,7 +348,7 @@ examples/elf
Similarly for C++ flags which must be provided in CXXELFFLAGS.
- 2. Your top-level nuttx/Make.defs file must alos include an approproate definition,
+ 2. Your top-level nuttx/Make.defs file must also include an approproate definition,
LDELFFLAGS, to generate a relocatable ELF object. With GNU LD, this should
include '-r' and '-e main' (or _main on some platforms).
@@ -491,7 +491,7 @@ examples/hello
than examples/null with a single printf statement. Really useful only
for bringing up new NuttX architectures.
- * CONFIG_EXAMPLES_HELLO_BUILTIN
+ * CONFIG_NSH_BUILTIN_APPS
Build the "Hello, World" example as an NSH built-in application.
examples/helloxx
@@ -540,9 +540,21 @@ examples/hidkbd
This is a simple test to debug/verify the USB host HID keyboard class
driver.
- CONFIG_EXAMPLES_HIDKBD_DEFPRIO - Priority of "waiter" thread.
- CONFIG_EXAMPLES_HIDKBD_STACKSIZE - Stacksize of "waiter" thread.
-
+ CONFIG_EXAMPLES_HIDKBD_DEFPRIO - Priority of "waiter" thread. Default:
+ 50
+ CONFIG_EXAMPLES_HIDKBD_STACKSIZE - Stacksize of "waiter" thread. Default
+ 1024
+ CONFIG_EXAMPLES_HIDKBD_DEVNAME - Name of keyboard device to be used.
+ Default: "/dev/kbda"
+ CONFIG_EXAMPLES_HIDKBD_ENCODED - Decode special key press events in the
+ user buffer. In this case, the example coded will use the interfaces
+ defined in include/nuttx/input/kbd_codec.h to decode the returned
+ keyboard data. These special keys include such things as up/down
+ arrows, home and end keys, etc. If this not defined, only 7-bit print-
+ able and control ASCII characters will be provided to the user.
+ Requires CONFIG_HIDKBD_ENCODED && CONFIG_LIB_KBDCODEC
+
+endif
examples/igmp
^^^^^^^^^^^^^
@@ -1190,6 +1202,80 @@ examples/poll
CONFIGURED_APPS += uiplib
+examples/posix_spawn
+^^^^^^^^^^^^^^^^^^^^
+
+ This is a simple test of the posix_spawn() API. The example derives from
+ examples/elf. As a result, these tests are built using the relocatable
+ ELF format installed in a ROMFS file system. At run time, the test program
+ in the ROMFS file system is spawned using posix_spawn().
+
+ Requires:
+
+ CONFIG_BINFMT_DISABLE=n - Don't disable the binary loader
+ CONFIG_ELF=y - Enable ELF binary loader
+ CONFIG_LIBC_EXECFUNCS=y - Enable support for posix_spawn
+ CONFIG_EXECFUNCS_SYMTAB="exports" - The name of the symbol table
+ created by the test.
+ CONFIG_EXECFUNCS_NSYMBOLS=10 - Value does not matter, it will be
+ corrected at runtime.
+ CONFIG_POSIX_SPAWN_STACKSIZE=768 - This default setting.
+
+ Test-specific configuration options:
+
+ CONFIG_EXAMPLES_POSIXSPAWN_DEVMINOR - The minor device number of the ROMFS
+ block. driver. For example, the N in /dev/ramN. Used for registering the
+ RAM block driver that will hold the ROMFS file system containing the ELF
+ executables to be tested. Default: 0
+
+ CONFIG_EXAMPLES_POSIXSPAWN_DEVPATH - The path to the ROMFS block driver
+ device. This must match EXAMPLES_POSIXSPAWN_DEVMINOR. Used for
+ registering the RAM block driver that will hold the ROMFS file system
+ containing the ELF executables to be tested. Default: "/dev/ram0"
+
+ NOTES:
+
+ 1. CFLAGS should be provided in CELFFLAGS. RAM and FLASH memory regions
+ may require long allcs. For ARM, this might be:
+
+ CELFFLAGS = $(CFLAGS) -mlong-calls
+
+ Similarly for C++ flags which must be provided in CXXELFFLAGS.
+
+ 2. Your top-level nuttx/Make.defs file must also include an approproate
+ definition, LDELFFLAGS, to generate a relocatable ELF object. With GNU
+ LD, this should include '-r' and '-e main' (or _main on some platforms).
+
+ LDELFFLAGS = -r -e main
+
+ If you use GCC to link, you make also need to include '-nostdlib' or
+ '-nostartfiles' and '-nodefaultlibs'.
+
+ 3. This example also requires genromfs. genromfs can be build as part of the
+ nuttx toolchain. Or can built from the genromfs sources that can be found
+ at misc/tools/genromfs-0.5.2.tar.gz. In any event, the PATH variable must
+ include the path to the genromfs executable.
+
+ 4. ELF size: The ELF files in this example are, be default, quite large
+ because they include a lot of "build garbage". You can greatly reduce the
+ size of the ELF binaries are using the 'objcopy --strip-unneeded' command to
+ remove un-necessary information from the ELF files.
+
+ 5. Simulator. You cannot use this example with the the NuttX simulator on
+ Cygwin. That is because the Cygwin GCC does not generate ELF file but
+ rather some Windows-native binary format.
+
+ If you really want to do this, you can create a NuttX x86 buildroot toolchain
+ and use that be build the ELF executables for the ROMFS file system.
+
+ 6. Linker scripts. You might also want to use a linker scripts to combine
+ sections better. An example linker script is at nuttx/binfmt/libelf/gnu-elf.ld.
+ That example might have to be tuned for your particular linker output to
+ position additional sections correctly. The GNU LD LDELFFLAGS then might
+ be:
+
+ LDELFFLAGS = -r -e main -T$(TOPDIR)/binfmt/libelf/gnu-elf.ld
+
examples/pwm
^^^^^^^^^^^^
diff --git a/apps/examples/adc/Makefile b/apps/examples/adc/Makefile
index 69862b383..3cbe843f6 100644
--- a/apps/examples/adc/Makefile
+++ b/apps/examples/adc/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/buttons/Makefile b/apps/examples/buttons/Makefile
index 77c1cd67d..a2e8679d4 100644
--- a/apps/examples/buttons/Makefile
+++ b/apps/examples/buttons/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/can/Makefile b/apps/examples/can/Makefile
index 8924797e3..548c6702c 100644
--- a/apps/examples/can/Makefile
+++ b/apps/examples/can/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/cdcacm/Makefile b/apps/examples/cdcacm/Makefile
index e8d03807d..2cf3a107f 100644
--- a/apps/examples/cdcacm/Makefile
+++ b/apps/examples/cdcacm/Makefile
@@ -87,12 +87,17 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME1)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME1),$(PRIORITY1),$(STACKSIZE1),$(APPNAME1)_main)
+
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME2)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME2),$(PRIORITY2),$(STACKSIZE2),$(APPNAME2)_main)
- @touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME1)_main.bdat $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME2)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/hello/Makefile b/apps/examples/hello/Makefile
index 560b0da35..c3b9744d7 100644
--- a/apps/examples/hello/Makefile
+++ b/apps/examples/hello/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
-ifeq ($(CONFIG_EXAMPLES_HELLO_BUILTIN),y)
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/helloxx/Makefile b/apps/examples/helloxx/Makefile
index 062da7d58..44d880658 100644
--- a/apps/examples/helloxx/Makefile
+++ b/apps/examples/helloxx/Makefile
@@ -100,13 +100,14 @@ $(CXXOBJS): %$(OBJEXT): %.cxx
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile
index 3e78c64e8..5a8ff7293 100644
--- a/apps/examples/ostest/Makefile
+++ b/apps/examples/ostest/Makefile
@@ -52,6 +52,10 @@ ifeq ($(CONFIG_ARCH_FPU),y)
CSRCS += fpu.c
endif
+ifeq ($(CONFIG_SCHED_WAITPID),y)
+CSRCS += waitpid.c
+endif
+
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
CSRCS += cancel.c cond.c mutex.c sem.c barrier.c
ifneq ($(CONFIG_RR_INTERVAL),0)
@@ -84,6 +88,10 @@ ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
CSRCS += posixtimer.c
endif
+ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CSRCS += vfork.c
+endif
+
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
@@ -127,13 +135,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_EXAMPLES_OSTEST_BUILTIN),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h
index a4af37f05..5217f0a0c 100644
--- a/apps/examples/ostest/ostest.h
+++ b/apps/examples/ostest/ostest.h
@@ -105,71 +105,83 @@
/* dev_null.c ***************************************************************/
-extern int dev_null(void);
+int dev_null(void);
/* fpu.c ********************************************************************/
-extern void fpu_test(void);
+void fpu_test(void);
+
+/* waitpid.c ****************************************************************/
+
+#ifdef CONFIG_SCHED_WAITPID
+int waitpid_test(void);
+#endif
/* mutex.c ******************************************************************/
-extern void mutex_test(void);
+void mutex_test(void);
/* rmutex.c ******************************************************************/
-extern void recursive_mutex_test(void);
+void recursive_mutex_test(void);
/* sem.c ********************************************************************/
-extern void sem_test(void);
+void sem_test(void);
/* cond.c *******************************************************************/
-extern void cond_test(void);
+void cond_test(void);
/* mqueue.c *****************************************************************/
-extern void mqueue_test(void);
+void mqueue_test(void);
/* timedmqueue.c ************************************************************/
-extern void timedmqueue_test(void);
+void timedmqueue_test(void);
/* cancel.c *****************************************************************/
-extern void cancel_test(void);
+void cancel_test(void);
/* timedwait.c **************************************************************/
-extern void timedwait_test(void);
+void timedwait_test(void);
/* sighand.c ****************************************************************/
-extern void sighand_test(void);
+void sighand_test(void);
/* posixtimers.c ************************************************************/
-extern void timer_test(void);
+void timer_test(void);
/* roundrobin.c *************************************************************/
-extern void rr_test(void);
+void rr_test(void);
/* barrier.c ****************************************************************/
-extern void barrier_test(void);
+void barrier_test(void);
/* prioinherit.c ************************************************************/
-extern void priority_inheritance(void);
+void priority_inheritance(void);
+
+/* vfork.c ******************************************************************/
+
+#ifdef CONFIG_ARCH_HAVE_VFORK
+int vfork_test(void);
+#endif
/* APIs exported (conditionally) by the OS specifically for testing of
* priority inheritance
*/
#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG)
-extern void sem_enumholders(FAR sem_t *sem);
-extern int sem_nfreeholders(void);
+void sem_enumholders(FAR sem_t *sem);
+int sem_nfreeholders(void);
#else
# define sem_enumholders(sem)
# define sem_nfreeholders()
diff --git a/apps/examples/ostest/ostest_main.c b/apps/examples/ostest/ostest_main.c
index 46726d515..aab1ff045 100644
--- a/apps/examples/ostest/ostest_main.c
+++ b/apps/examples/ostest/ostest_main.c
@@ -301,6 +301,14 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif
+#ifdef CONFIG_SCHED_WAITPID
+ /* Check waitpid() and friends */
+
+ printf("\nuser_main: waitpid test\n");
+ waitpid_test();
+ check_test_memory_usage();
+#endif
+
#ifndef CONFIG_DISABLE_PTHREAD
/* Verify pthreads and pthread mutex */
@@ -409,6 +417,11 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */
+#ifdef CONFIG_ARCH_HAVE_VFORK
+ printf("\nuser_main: vfork() test\n");
+ vfork_test();
+#endif
+
/* Compare memory usage at time ostest_main started until
* user_main exits. These should not be identical, but should
* be similar enough that we can detect any serious OS memory
@@ -428,6 +441,7 @@ static int user_main(int argc, char *argv[])
show_memory_usage(&g_mmbefore, &g_mmafter);
#endif
}
+
printf("user_main: Exitting\n");
return 0;
}
diff --git a/apps/examples/ostest/sighand.c b/apps/examples/ostest/sighand.c
index eabfe5646..32b182c21 100644
--- a/apps/examples/ostest/sighand.c
+++ b/apps/examples/ostest/sighand.c
@@ -54,12 +54,37 @@ static sem_t sem;
static bool sigreceived = false;
static bool threadexited = false;
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static void death_of_child(int signo, siginfo_t *info, void *ucontext)
+{
+ /* Use of printf in a signal handler is NOT safe! It can cause deadlocks!
+ * Also, signals are not queued by NuttX. As a consequence, some
+ * notifications will get lost (or the info data can be overwrittedn)!
+ * Because POSIX does not require signals to be queued, I do not think
+ * that this is a bug (the overwriting is a bug, however).
+ */
+
+ if (info)
+ {
+ printf("death_of_child: PID %d received signal=%d code=%d pid=%d status=%d\n",
+ getpid(), signo, info->si_code, info->si_pid, info->si_status);
+ }
+ else
+ {
+ printf("death_of_child: PID %d received signal=%d (no info?)\n",
+ getpid(), signo);
+ }
+}
+#endif
+
static void wakeup_action(int signo, siginfo_t *info, void *ucontext)
{
sigset_t oldset;
sigset_t allsigs;
int status;
+ /* Use of printf in a signal handler is NOT safe! It can cause deadlocks! */
+
printf("wakeup_action: Received signal %d\n" , signo);
sigreceived = true;
@@ -186,6 +211,11 @@ static int waiter_main(int argc, char *argv[])
void sighand_test(void)
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ struct sigaction act;
+ struct sigaction oact;
+ sigset_t sigset;
+#endif
struct sched_param param;
union sigval sigvalue;
pid_t waiterpid;
@@ -195,6 +225,32 @@ void sighand_test(void)
printf("sighand_test: Initializing semaphore to 0\n" );
sem_init(&sem, 0, 0);
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ printf("sighand_test: Unmasking SIGCHLD\n");
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+ status = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ if (status != OK)
+ {
+ printf("sighand_test: ERROR sigprocmask failed, status=%d\n",
+ status);
+ }
+
+ printf("sighand_test: Registering SIGCHLD handler\n" );
+ act.sa_sigaction = death_of_child;
+ act.sa_flags = SA_SIGINFO;
+
+ (void)sigfillset(&act.sa_mask);
+ (void)sigdelset(&act.sa_mask, SIGCHLD);
+
+ status = sigaction(SIGCHLD, &act, &oact);
+ if (status != OK)
+ {
+ printf("waiter_main: ERROR sigaction failed, status=%d\n" , status);
+ }
+#endif
+
/* Start waiter thread */
printf("sighand_test: Starting waiter task\n" );
@@ -262,6 +318,13 @@ void sighand_test(void)
printf("sighand_test: ERROR signal handler did not run\n" );
}
+ /* Detach the signal handler */
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ act.sa_sigaction = SIG_DFL;
+ status = sigaction(SIGCHLD, &act, &oact);
+#endif
+
printf("sighand_test: done\n" );
FFLUSH();
}
diff --git a/apps/examples/ostest/vfork.c b/apps/examples/ostest/vfork.c
new file mode 100644
index 000000000..4e1b8c892
--- /dev/null
+++ b/apps/examples/ostest/vfork.c
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * examples/ostest/vfork.c
+ *
+ * Copyright (C) 2013 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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if defined(CONFIG_ARCH_HAVE_VFORK) && !defined(CONFIG_DISABLE_SIGNALS)
+static volatile bool g_vforkchild;
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int vfork_test(void)
+{
+#if defined(CONFIG_ARCH_HAVE_VFORK) && !defined(CONFIG_DISABLE_SIGNALS)
+ pid_t pid;
+
+ g_vforkchild = false;
+ pid = vfork();
+ if (pid == 0)
+ {
+ /* There is not very much that the child is permitted to do. Perhaps
+ * it can just set g_vforkchild.
+ */
+
+ g_vforkchild = true;
+ exit(0);
+ }
+ else if (pid < 0)
+ {
+ printf("vfork_test: vfork() failed: %d\n", errno);
+ return -1;
+ }
+ else
+ {
+ sleep(1);
+ if (g_vforkchild)
+ {
+ printf("vfork_test: Child %d ran successfully\n", pid);
+ }
+ else
+ {
+ printf("vfork_test: ERROR Child %d did not run\n", pid);
+ return -1;
+ }
+ }
+#endif
+
+ return 0;
+}
diff --git a/apps/examples/ostest/waitpid.c b/apps/examples/ostest/waitpid.c
new file mode 100644
index 000000000..e53b49213
--- /dev/null
+++ b/apps/examples/ostest/waitpid.c
@@ -0,0 +1,269 @@
+/****************************************************************************
+ * examples/ostest/waitpid.c
+ *
+ * Copyright (C) 2013 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/wait.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+#ifdef CONFIG_SCHED_WAITPID
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RETURN_STATUS 14
+#define NCHILDREN 3
+#define PRIORITY 100
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static int g_waitpids[NCHILDREN];
+
+/****************************************************************************
+ * Priviate Functions
+ ****************************************************************************/
+
+static int waitpid_main(int argc, char *argv[])
+{
+ pid_t me = getpid();
+
+ printf("waitpid_main: PID %d Started\n", me);
+ sleep(3);
+ printf("waitpid_main: PID %d exitting with result=%d\n", me, RETURN_STATUS);
+ return RETURN_STATUS;
+}
+
+static void waitpid_start_children(void)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < NCHILDREN; i++)
+ {
+ ret = TASK_CREATE("waitpid", PRIORITY, STACKSIZE, waitpid_main, NULL);
+ if (ret < 0)
+ {
+ printf("waitpid_start_child: ERROR Failed to start user_main\n");
+ }
+ else
+ {
+ printf("waitpid_start_child: Started waitpid_main at PID=%d\n", ret);
+ }
+
+ g_waitpids[i] = ret;
+ }
+}
+
+static void waitpid_last(void)
+{
+ int stat_loc;
+ int ret;
+
+ printf("waitpid_last: Waiting for PID=%d with waitpid()\n",
+ g_waitpids[NCHILDREN-1]);
+
+ ret = (int)waitpid(g_waitpids[NCHILDREN-1], &stat_loc, 0);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_last: ERROR: PID %d waitpid failed: %d\n",
+ g_waitpids[NCHILDREN-1], errcode);
+ }
+ else if (stat_loc != RETURN_STATUS)
+ {
+ printf("waitpid_last: ERROR: PID %d return status is %d, expected %d\n",
+ g_waitpids[NCHILDREN-1], stat_loc, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_last: PID %d waitpid succeeded with stat_loc=%d\n",
+ g_waitpids[NCHILDREN-1], stat_loc);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int waitpid_test(void)
+{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ siginfo_t info;
+#endif
+ int stat_loc;
+ int ret;
+
+ /* Start the children and wait for first one to complete */
+
+ printf("\nTest waitpid()\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for PID=%d with waitpid()\n", g_waitpids[0]);
+ ret = (int)waitpid(g_waitpids[0], &stat_loc, 0);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: PID %d waitpid failed: %d\n",
+ g_waitpids[0], errcode);
+ }
+ else if (ret != g_waitpids[0])
+ {
+ printf("waitpid_test: ERROR: PID %d wait returned PID %d\n",
+ g_waitpids[0], ret);
+ }
+ else if (stat_loc != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ g_waitpids[0], stat_loc, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: PID %d waitpid succeeded with stat_loc=%d\n",
+ g_waitpids[0], stat_loc);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ /* Start the children and wait for first one to complete */
+
+ printf("\nTest waitid(P_PID)\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for PID=%d with waitid()\n", g_waitpids[0]);
+ ret = waitid(P_PID, (id_t)g_waitpids[0], &info, WEXITED);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: PID %d waitid failed: %d\n",
+ g_waitpids[0], errcode);
+ }
+ else if (info.si_pid != g_waitpids[0])
+ {
+ printf("waitpid_test: ERROR: PID %d waitid returned PID %d\n",
+ g_waitpids[0], info.si_pid);
+ }
+ else if (info.si_status != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ info.si_pid, info.si_status, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: waitid PID %d succeeded with si_status=%d\n",
+ info.si_pid, info.si_status);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+
+ /* Start the children and wait for any one to complete */
+
+ printf("\nTest waitid(P_ALL)\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for any child with waitid()\n");
+ ret = waitid(P_ALL, 0, &info, WEXITED);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: waitid failed: %d\n", errcode);
+ }
+ else if (info.si_status != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ info.si_pid, info.si_status, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: PID %d waitid succeeded with si_status=%d\n",
+ info.si_pid, info.si_status);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+
+ /* Start the children and wait for first one to complete */
+
+ printf("\nTest wait()\n");
+ waitpid_start_children();
+
+ printf("waitpid_test: Waiting for any child with wait()\n");
+ ret = (int)wait(&stat_loc);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("waitpid_test: ERROR: wait failed: %d\n", errcode);
+ }
+ else if (stat_loc != RETURN_STATUS)
+ {
+ printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
+ ret, stat_loc, RETURN_STATUS);
+ }
+ else
+ {
+ printf("waitpid_test: PID %d wait succeeded with stat_loc=%d\n",
+ ret, stat_loc);
+ }
+
+ /* Wait a big to make sure that the other threads complete */
+
+ waitpid_last();
+ sleep(1);
+#endif
+
+ return 0;
+}
+
+#endif /* CONFIG_SCHED_WAITPID */
diff --git a/apps/examples/posix_spawn/Kconfig b/apps/examples/posix_spawn/Kconfig
new file mode 100644
index 000000000..508065913
--- /dev/null
+++ b/apps/examples/posix_spawn/Kconfig
@@ -0,0 +1,29 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config EXAMPLES_POSIXSPAWN
+ bool "posix_spawn Unit Test"
+ default n
+ ---help---
+ Enable the posix_spawn() unit test
+
+if EXAMPLES_POSIXSPAWN
+config EXAMPLES_POSIXSPAWN_DEVMINOR
+ int "ROMFS Minor Device Number"
+ default 0
+ ---help---
+ The minor device number of the ROMFS block. For example, the N in /dev/ramN.
+ Used for registering the RAM block driver that will hold the ROMFS file system
+ containing the ELF executables to be tested. Default: 0
+
+config EXAMPLES_POSIXSPAWN_DEVPATH
+ string "ROMFS Devie Path"
+ default "/dev/ram0"
+ ---help---
+ The path to the ROMFS block driver device. This must match EXAMPLES_POSIXSPAWN_DEVMINOR.
+ Used for registering the RAM block driver that will hold the ROMFS file system
+ containing the ELF executables to be tested. Default: "/dev/ram0"
+
+endif
diff --git a/apps/examples/posix_spawn/Makefile b/apps/examples/posix_spawn/Makefile
new file mode 100644
index 000000000..0bfa36e55
--- /dev/null
+++ b/apps/examples/posix_spawn/Makefile
@@ -0,0 +1,130 @@
+############################################################################
+# apps/examples/posix_spawn/Makefile
+#
+# Copyright (C) 2013 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.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# ELF Example
+
+ASRCS =
+CSRCS = spawn_main.c symtab.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ BIN = ..\..\libapps$(LIBEXT)
+else
+ifeq ($(WINTOOL),y)
+ BIN = ..\\..\\libapps$(LIBEXT)
+else
+ BIN = ../../libapps$(LIBEXT)
+endif
+endif
+
+ROOTDEPPATH = --dep-path . --dep-path filesystem
+
+# Build targets
+
+VPATH = filesystem
+
+all: build
+.PHONY: build clean_filesystem clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+# This is a little messy. The build is broken into two pieces: (1) the
+# filesystem/ subdir build that auto-generates several files, and (2) the library
+# build. This is done because we need a fresh build context after auto-
+# generating the source files.
+
+build_lib: $(OBJS)
+ $(call ARCHIVE, $(BIN), $(OBJS))
+
+build:
+ @$(MAKE) -C filesystem TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV)
+ @$(MAKE) TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" build_lib
+
+context:
+
+# We can't make dependencies in this directory because the required
+# header files may not yet exist.
+
+.depend:
+ @touch $@
+
+depend: .depend
+
+clean_filesystem:
+ @$(MAKE) -C filesystem TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) clean
+
+clean: clean_filesystem
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, Make.dep)
+ $(call DELFILE, .depend)
+
+# There are no dependencies in this directory. Some of more important
+# and more obvious dependencies are hard-coded here:
+
+spawn_main.o: spawn_main.c \
+ $(TOPDIR)/include/nuttx/config.h \
+ $(TOPDIR)/include/nuttx/compiler.h \
+ $(TOPDIR)/include/sys/mount.h \
+ $(TOPDIR)/include/stdio.h \
+ $(TOPDIR)/include/stdlib.h \
+ $(TOPDIR)/include/unistd.h \
+ $(TOPDIR)/include/string.h \
+ $(TOPDIR)/include/fcntl.h \
+ $(TOPDIR)/include/spawn.h \
+ $(TOPDIR)/include/debug.h \
+ $(TOPDIR)/include/errno.h \
+ $(TOPDIR)/include/nuttx/ramdisk.h \
+ $(TOPDIR)/include/nuttx/binfmt/elf.h \
+ $(TOPDIR)/include/nuttx/binfmt/symtab.h \
+ filesystem/romfs.h
+
+symtab.o: filesystem/symtab.c \
+ $(TOPDIR)/include/nuttx/compiler.h \
+ $(TOPDIR)/include/nuttx/binfmt/symtab.h
diff --git a/apps/examples/posix_spawn/filesystem/Makefile b/apps/examples/posix_spawn/filesystem/Makefile
new file mode 100644
index 000000000..26897426c
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/Makefile
@@ -0,0 +1,88 @@
+############################################################################
+# apps/examples/posix_spawn/filesystem/Makefile
+#
+# Copyright (C) 2013 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.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)$(DELIM)Make.defs
+
+SPAWN_DIR = $(APPDIR)$(DELIM)examples$(DELIM)posix_spawn
+FILESYSTEM_DIR = $(SPAWN_DIR)$(DELIM)filesystem
+ROMFS_DIR = $(FILESYSTEM_DIR)$(DELIM)romfs
+ROMFS_IMG = $(FILESYSTEM_DIR)$(DELIM)romfs.img
+ROMFS_HDR = $(FILESYSTEM_DIR)$(DELIM)romfs.h
+SYMTAB_SRC = $(FILESYSTEM_DIR)$(DELIM)symtab.c
+
+all: $(ROMFS_HDR) $(SYMTAB_SRC)
+.PHONY: all hello/hello redirect/redirect clean populate
+
+# Create the romfs directory
+
+$(ROMFS_DIR):
+ $(Q) mkdir $(ROMFS_DIR)
+
+# Build the hello test program
+
+hello/hello:
+ $(Q) $(MAKE) -C hello hello TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+
+# Build the redirection test program
+
+redirect/redirect:
+ $(Q) $(MAKE) -C redirect redirect TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+
+# Create the romfs.img file from the romfs directory
+
+$(ROMFS_IMG): hello/hello redirect/redirect testdata.txt $(ROMFS_DIR)
+ $(Q) $(MAKE) -C hello install TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) $(MAKE) -C redirect install TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) install --mode=0644 testdata.txt $(ROMFS_DIR)/testdata.txt
+ $(Q) genromfs -f $@ -d $(ROMFS_DIR) -V "POSIXSPAWN"
+
+# Create the romfs.h header file from the romfs.img file
+
+$(ROMFS_HDR) : $(ROMFS_IMG)
+ $(Q) (cd $(FILESYSTEM_DIR); xxd -i romfs.img | sed -e "s/^unsigned/static const unsigned/g" >$@)
+
+# Create the exported symbol table
+
+$(SYMTAB_SRC): $(ROMFS_DIR)/hello $(ROMFS_DIR)/redirect $(ROMFS_DIR)/testdata.txt
+ $(Q) $(FILESYSTEM_DIR)$(DELIM)mksymtab.sh $(ROMFS_DIR) >$@
+
+# Clean each subdirectory
+
+clean:
+ $(Q) $(MAKE) -C hello clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) $(MAKE) -C redirect clean TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)"
+ $(Q) rm -f $(ROMFS_HDR) $(ROMFS_IMG) $(SYMTAB_SRC)
+ $(Q) rm -rf $(ROMFS_DIR)
diff --git a/apps/examples/posix_spawn/filesystem/hello/hello.c b/apps/examples/posix_spawn/filesystem/hello/hello.c
new file mode 100644
index 000000000..1b269d85f
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/hello/hello.c
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * examples/posix_spawn/filesystem/hello/hello.c
+ *
+ * Copyright (C) 2013 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 <stdio.h>
+#include <stdlib.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ /* Mandatory "Hello, world!" */
+
+ puts("Getting ready to say \"Hello, world\"\n");
+ printf("Hello, world!\n");
+ puts("It has been said.\n");
+
+ /* Print arguments */
+
+ printf("argc\t= %d\n", argc);
+ printf("argv\t= 0x%p\n", argv);
+
+ for (i = 0; i < argc; i++)
+ {
+ printf("argv[%d]\t= ", i);
+ if (argv[i])
+ {
+ printf("(0x%p) \"%s\"\n", argv[i], argv[i]);
+ }
+ else
+ {
+ printf("NULL?\n");
+ }
+ }
+
+ printf("argv[%d]\t= 0x%p\n", argc, argv[argc]);
+ printf("Goodbye, world!\n");
+ return 0;
+}
diff --git a/apps/examples/posix_spawn/filesystem/mksymtab.sh b/apps/examples/posix_spawn/filesystem/mksymtab.sh
new file mode 100755
index 000000000..51408a89c
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/mksymtab.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+usage="Usage: $0 <test-dir-path>"
+
+# Check for the required ROMFS directory path
+
+dir=$1
+if [ -z "$dir" ]; then
+ echo "ERROR: Missing <test-dir-path>"
+ echo ""
+ echo $usage
+ exit 1
+fi
+
+if [ ! -d "$dir" ]; then
+ echo "ERROR: Directory $dir does not exist"
+ echo ""
+ echo $usage
+ exit 1
+fi
+
+# Extract all of the undefined symbols from the ELF files and create a
+# list of sorted, unique undefined variable names.
+
+varlist=`find ${dir} -executable -type f | xargs nm | fgrep ' U ' | sed -e "s/^[ ]*//g" | cut -d' ' -f2 | sort | uniq`
+
+# Now output the symbol table as a structure in a C source file. All
+# undefined symbols are declared as void* types. If the toolchain does
+# any kind of checking for function vs. data objects, then this could
+# faile
+
+echo "#include <nuttx/compiler.h>"
+echo "#include <nuttx/binfmt/symtab.h>"
+echo ""
+
+for var in $varlist; do
+ echo "extern void *${var};"
+done
+
+echo ""
+echo "const struct symtab_s exports[] = "
+echo "{"
+
+for var in $varlist; do
+ echo " {\"${var}\", &${var}},"
+done
+
+echo "};"
+echo ""
+echo "const int nexports = sizeof(exports) / sizeof(struct symtab_s);"
+
diff --git a/apps/examples/posix_spawn/filesystem/redirect/redirect.c b/apps/examples/posix_spawn/filesystem/redirect/redirect.c
new file mode 100644
index 000000000..61638df79
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/redirect/redirect.c
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * examples/posix_spawn/filesystem/redirect/redirect.c
+ *
+ * Copyright (C) 2013 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 <stdio.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int ch;
+
+ printf("Entering the stdin redirection test\n");
+
+ /* stdin should have been redirected to testdata.txt. Read and print until
+ * we hit the end of file.
+ */
+
+ while ((ch = getchar()) != EOF)
+ {
+ putchar(ch);
+ }
+
+ printf("Exit-ing the stdin redirection test\n");
+ return 0;
+}
diff --git a/apps/examples/posix_spawn/filesystem/testdata.txt b/apps/examples/posix_spawn/filesystem/testdata.txt
new file mode 100644
index 000000000..bb581fbb5
--- /dev/null
+++ b/apps/examples/posix_spawn/filesystem/testdata.txt
@@ -0,0 +1,2 @@
+Now is the time for all good men to come to the aid of their party.
+
diff --git a/apps/examples/posix_spawn/spawn_main.c b/apps/examples/posix_spawn/spawn_main.c
new file mode 100644
index 000000000..0ca5f9107
--- /dev/null
+++ b/apps/examples/posix_spawn/spawn_main.c
@@ -0,0 +1,460 @@
+/****************************************************************************
+ * examples/posix_spawn/spawn_main.c
+ *
+ * Copyright (C) 2013 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 <nuttx/compiler.h>
+
+#include <sys/mount.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/ramdisk.h>
+#include <nuttx/binfmt/elf.h>
+#include <nuttx/binfmt/symtab.h>
+
+#include "filesystem/romfs.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Check configuration. This is not all of the configuration settings that
+ * are required -- only the more obvious.
+ */
+
+#if CONFIG_NFILE_DESCRIPTORS < 1
+# error "You must provide file descriptors via CONFIG_NFILE_DESCRIPTORS in your configuration file"
+#endif
+
+#ifdef CONFIG_BINFMT_DISABLE
+# error "The binary loader is disabled (CONFIG_BINFMT_DISABLE)!"
+#endif
+
+#ifndef CONFIG_ELF
+# error "You must select CONFIG_ELF in your configuration file"
+#endif
+
+#ifndef CONFIG_FS_ROMFS
+# error "You must select CONFIG_FS_ROMFS in your configuration file"
+#endif
+
+#ifdef CONFIG_DISABLE_MOUNTPOINT
+# error "You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file"
+#endif
+
+#ifdef CONFIG_BINFMT_DISABLE
+# error "You must not disable loadable modules via CONFIG_BINFMT_DISABLE in your configuration file"
+#endif
+
+/* Describe the ROMFS file system */
+
+#define SECTORSIZE 512
+#define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE)
+#define MOUNTPT "/mnt/romfs"
+
+#ifndef CONFIG_EXAMPLES_ELF_DEVMINOR
+# define CONFIG_EXAMPLES_ELF_DEVMINOR 0
+#endif
+
+#ifndef CONFIG_EXAMPLES_ELF_DEVPATH
+# define CONFIG_EXAMPLES_ELF_DEVPATH "/dev/ram0"
+#endif
+
+/* If CONFIG_DEBUG is enabled, use dbg instead of printf so that the
+ * output will be synchronous with the debug output.
+ */
+
+#ifdef CONFIG_CPP_HAVE_VARARGS
+# ifdef CONFIG_DEBUG
+# define message(format, arg...) dbg(format, ##arg)
+# define err(format, arg...) dbg(format, ##arg)
+# else
+# define message(format, arg...) printf(format, ##arg)
+# define err(format, arg...) fprintf(stderr, format, ##arg)
+# endif
+#else
+# ifdef CONFIG_DEBUG
+# define message dbg
+# define err dbg
+# else
+# define message printf
+# define err printf
+# endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static unsigned int g_mminitial; /* Initial memory usage */
+static unsigned int g_mmstep; /* Memory Usage at beginning of test step */
+
+static const char delimiter[] =
+ "****************************************************************************";
+static const char g_redirect[] = "redirect";
+static const char g_hello[] = "hello";
+static const char g_data[] = "testdata.txt";
+
+static char fullpath[128];
+
+static char * const g_argv[4] =
+ { "Argument 1", "Argument 2", "Argument 3", NULL };
+
+/****************************************************************************
+ * Symbols from Auto-Generated Code
+ ****************************************************************************/
+
+extern const struct symtab_s exports[];
+extern const int nexports;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mm_update
+ ****************************************************************************/
+
+static void mm_update(FAR unsigned int *previous, FAR const char *msg)
+{
+ struct mallinfo mmcurrent;
+
+ /* Get the current memory usage */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mmcurrent = mallinfo();
+#else
+ (void)mallinfo(&mmcurrent);
+#endif
+
+ /* Show the change from the previous time */
+
+ printf("\nMemory Usage %s:\n", msg);
+ printf(" Before: %8u After: %8u Change: %8d\n",
+ *previous, mmcurrent.uordblks, (int)mmcurrent.uordblks - (int)*previous);
+
+ /* Set up for the next test */
+
+ *previous = mmcurrent.uordblks;
+}
+
+/****************************************************************************
+ * Name: mm_initmonitor
+ ****************************************************************************/
+
+static void mm_initmonitor(void)
+{
+ struct mallinfo mmcurrent;
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mmcurrent = mallinfo();
+#else
+ (void)mallinfo(&mmcurrent);
+#endif
+
+ g_mminitial = mmcurrent.uordblks;
+ g_mmstep = mmcurrent.uordblks;
+
+ printf("Initial memory usage: %d\n", mmcurrent.uordblks);
+}
+
+/****************************************************************************
+ * Name: testheader
+ ****************************************************************************/
+
+static inline void testheader(FAR const char *progname)
+{
+ message("\n%s\n* Executing %s\n%s\n\n", delimiter, progname, delimiter);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spawn_main
+ ****************************************************************************/
+
+int spawn_main(int argc, char *argv[])
+{
+ posix_spawn_file_actions_t file_actions;
+ posix_spawnattr_t attr;
+ FAR const char *filepath;
+ pid_t pid;
+ int ret;
+
+ /* Initialize the memory monitor */
+
+ mm_initmonitor();
+
+ /* Initialize the ELF binary loader */
+
+ message("Initializing the ELF binary loader\n");
+ ret = elf_initialize();
+ if (ret < 0)
+ {
+ err("ERROR: Initialization of the ELF loader failed: %d\n", ret);
+ exit(1);
+ }
+
+ mm_update(&g_mmstep, "after elf_initialize");
+
+ /* Create a ROM disk for the ROMFS filesystem */
+
+ message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR);
+ ret = romdisk_register(CONFIG_EXAMPLES_ELF_DEVMINOR, (FAR uint8_t *)romfs_img,
+ NSECTORS(romfs_img_len), SECTORSIZE);
+ if (ret < 0)
+ {
+ err("ERROR: romdisk_register failed: %d\n", ret);
+ elf_uninitialize();
+ exit(1);
+ }
+
+ mm_update(&g_mmstep, "after romdisk_register");
+
+ /* Mount the file system */
+
+ message("Mounting ROMFS filesystem at target=%s with source=%s\n",
+ MOUNTPT, CONFIG_EXAMPLES_ELF_DEVPATH);
+
+ ret = mount(CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, "romfs", MS_RDONLY, NULL);
+ if (ret < 0)
+ {
+ err("ERROR: mount(%s,%s,romfs) failed: %s\n",
+ CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, errno);
+ elf_uninitialize();
+ }
+
+ mm_update(&g_mmstep, "after mount");
+
+ /* Does the system support the PATH variable? Has the PATH variable
+ * already been set? If YES and NO, then set the PATH variable to
+ * the ROMFS mountpoint.
+ */
+
+#if defined(CONFIG_BINFMT_EXEPATH) && !defined(CONFIG_PATH_INITIAL)
+ (void)setenv("PATH", MOUNTPT, 1);
+#endif
+
+ /* Make sure that we are using our symbol take */
+
+ exec_setsymtab(exports, nexports);
+
+ /*************************************************************************
+ * Case 1: Simple program with arguments
+ *************************************************************************/
+
+ /* Output a seperated so that we can clearly discriminate the output of
+ * this program from the others.
+ */
+
+ testheader(g_hello);
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_init failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_init failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr init");
+
+ /* If the binary loader does not support the PATH variable, then
+ * create the full path to the executable program. Otherwise,
+ * use the relative path so that the binary loader will have to
+ * search the PATH variable to find the executable.
+ */
+
+#ifdef CONFIG_BINFMT_EXEPATH
+ filepath = g_hello;
+#else
+ snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_hello);
+ filepath = fullpath;
+#endif
+
+ /* Execute the program */
+
+ mm_update(&g_mmstep, "before posix_spawn");
+
+ ret = posix_spawn(&pid, filepath, &file_actions, &attr, NULL, (FAR char * const*)&g_argv);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn failed: %d\n", ret);
+ }
+
+ sleep(4);
+ mm_update(&g_mmstep, "after posix_spawn");
+
+ /* Free attibutes and file actions */
+
+ ret = posix_spawn_file_actions_destroy(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_destroy failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_destroy(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_destroy failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr destruction");
+
+ /*************************************************************************
+ * Case 2: Simple program with redirection of stdin to a file input
+ *************************************************************************/
+
+ /* Output a seperated so that we can clearly discriminate the output of
+ * this program from the others.
+ */
+
+ testheader(g_redirect);
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_init failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_init failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr init");
+
+ /* Set up to close stdin (0) and open testdata.txt as the program input */
+
+ ret = posix_spawn_file_actions_addclose(&file_actions, 0);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_addclose failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_data);
+ ret = posix_spawn_file_actions_addopen(&file_actions, 0, fullpath, O_RDONLY, 0644);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_addopen failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ mm_update(&g_mmstep, "after adding file_actions");
+
+ /* If the binary loader does not support the PATH variable, then
+ * create the full path to the executable program. Otherwise,
+ * use the relative path so that the binary loader will have to
+ * search the PATH variable to find the executable.
+ */
+
+#ifdef CONFIG_BINFMT_EXEPATH
+ filepath = g_redirect;
+#else
+ snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_redirect);
+ filepath = fullpath;
+#endif
+
+ /* Execute the program */
+
+ mm_update(&g_mmstep, "before posix_spawn");
+
+ ret = posix_spawn(&pid, filepath, &file_actions, &attr, NULL, NULL);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn failed: %d\n", ret);
+ }
+
+ sleep(2);
+ mm_update(&g_mmstep, "after posix_spawn");
+
+ /* Free attibutes and file actions */
+
+ ret = posix_spawn_file_actions_destroy(&file_actions);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawn_file_actions_destroy failed: %d\n", ret);
+ }
+ posix_spawn_file_actions_dump(&file_actions);
+
+ ret = posix_spawnattr_destroy(&attr);
+ if (ret != 0)
+ {
+ err("ERROR: posix_spawnattr_destroy failed: %d\n", ret);
+ }
+ posix_spawnattr_dump(&attr);
+
+ mm_update(&g_mmstep, "after file_action/attr destruction");
+
+ /* Clean-up */
+
+ elf_uninitialize();
+
+ mm_update(&g_mmstep, "End-of-Test");
+ return 0;
+}
diff --git a/apps/examples/pwm/Makefile b/apps/examples/pwm/Makefile
index 3a6f2520a..ece901a99 100644
--- a/apps/examples/pwm/Makefile
+++ b/apps/examples/pwm/Makefile
@@ -83,11 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/qencoder/Makefile b/apps/examples/qencoder/Makefile
index 7d2427c6b..9668796e6 100644
--- a/apps/examples/qencoder/Makefile
+++ b/apps/examples/qencoder/Makefile
@@ -83,13 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-endif
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/examples/watchdog/Makefile b/apps/examples/watchdog/Makefile
index 9890959fb..076272fe3 100644
--- a/apps/examples/watchdog/Makefile
+++ b/apps/examples/watchdog/Makefile
@@ -83,11 +83,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
@touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
diff --git a/apps/include/builtin.h b/apps/include/builtin.h
new file mode 100644
index 000000000..24cf204fa
--- /dev/null
+++ b/apps/include/builtin.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * apps/include/builtin.h
+ *
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 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.
+ *
+ ****************************************************************************/
+
+#ifndef __APPS_INCLUDE_BUILTIN_H
+#define __APPS_INCLUDE_BUILTIN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exec_builtin
+ *
+ * Description:
+ * Executes builtin applications registered during 'make context' time.
+ * New application is run in a separate task context (and thread).
+ *
+ * Input Parameter:
+ * filename - Name of the linked-in binary to be started.
+ * argv - Argument list
+ * redirfile - If output if redirected, this parameter will be non-NULL
+ * and will provide the full path to the file.
+ * oflags - If output is redirected, this parameter will provide the
+ * open flags to use. This will support file replacement
+ * of appending to an existing file.
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * Returns the PID of the exec'ed module. On failure, it.returns
+ * -1 (ERROR) and sets errno appropriately.
+ *
+ ****************************************************************************/
+
+EXTERN int exec_builtin(FAR const char *appname, FAR const char **argv,
+ FAR const char *redirfile, int oflags);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __APPS_INCLUDE_BUILTIN_H */
diff --git a/apps/interpreters/Makefile b/apps/interpreters/Makefile
index 867d45f99..f78528714 100644
--- a/apps/interpreters/Makefile
+++ b/apps/interpreters/Makefile
@@ -73,4 +73,4 @@ depend: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_depend)
clean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_clean)
-distclean: clean $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
+distclean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
diff --git a/apps/interpreters/ficl/Makefile b/apps/interpreters/ficl/Makefile
index 990630fb8..3b2dc7ab9 100644
--- a/apps/interpreters/ficl/Makefile
+++ b/apps/interpreters/ficl/Makefile
@@ -108,7 +108,6 @@ context:
depend: .depend
clean:
- $(call DELFILE, .context)
$(call DELFILE, .built)
$(call CLEAN)
diff --git a/apps/namedapp/Kconfig b/apps/namedapp/Kconfig
deleted file mode 100644
index 8d8f03421..000000000
--- a/apps/namedapp/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see misc/tools/kconfig-language.txt.
-#
-
-config NAMEDAPP
- bool "Support named applications"
- default n
- ---help---
- Enable support for named applications. This features assigns a string
- name to an application. This feature is also the underlying requirement
- to support built-in applications in the NuttShell (NSH).
-
-if NAMEDAPP
-endif
diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig
index 17b107b8f..e60e9c480 100644
--- a/apps/nshlib/Kconfig
+++ b/apps/nshlib/Kconfig
@@ -15,12 +15,12 @@ if NSH_LIBRARY
config NSH_BUILTIN_APPS
bool "Enable built-in applications"
default y
- depends on NAMEDAPP
+ depends on BUILTIN
---help---
- Support external registered, "named" applications that can be
+ Support external registered, "built-in" applications that can be
executed from the NSH command line (see apps/README.txt for
- more information). This options requires support for named applications
- (NAMEDAPP).
+ more information). This options requires support for builtin
+ applications (BUILTIN).
menu "Disable Individual commands"
diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile
index 73325e899..5c5269685 100644
--- a/apps/nshlib/Makefile
+++ b/apps/nshlib/Makefile
@@ -44,7 +44,7 @@ CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_fscmds.c nsh_ddcmd.c \
nsh_proccmds.c nsh_mmcmds.c nsh_envcmds.c nsh_dbgcmds.c
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
-CSRCS += nsh_apps.c
+CSRCS += nsh_builtin.c
endif
ifeq ($(CONFIG_NSH_ROMFSETC),y)
@@ -130,7 +130,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/nshlib/README.txt b/apps/nshlib/README.txt
index bc626e699..006839628 100644
--- a/apps/nshlib/README.txt
+++ b/apps/nshlib/README.txt
@@ -945,7 +945,7 @@ NSH-Specific Configuration Settings
the configs/<board-name>/defconfig file:
* CONFIG_NSH_BUILTIN_APPS
- Support external registered, "named" applications that can be
+ Support external registered, "builtin" applications that can be
executed from the NSH command line (see apps/README.txt for
more information).
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index a046a384f..253a803f8 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -491,7 +491,8 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline);
/* Application interface */
#ifdef CONFIG_NSH_BUILTIN_APPS
-int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, FAR char **argv);
+int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags);
#endif
/* Working directory support */
diff --git a/apps/nshlib/nsh_apps.c b/apps/nshlib/nsh_builtin.c
index 7dbaf9ba8..ba39e8dfe 100644
--- a/apps/nshlib/nsh_apps.c
+++ b/apps/nshlib/nsh_builtin.c
@@ -1,10 +1,16 @@
/****************************************************************************
- * apps/nshlib/nsh_apps.c
+ * apps/nshlib/nsh_builtin.c
+ *
+ * Originally by:
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2011-2013 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:
@@ -48,7 +54,8 @@
#include <errno.h>
#include <string.h>
-#include <apps/apps.h>
+#include <nuttx/binfmt/builtin.h>
+#include <apps/builtin.h>
#include "nsh.h"
#include "nsh_console.h"
@@ -84,13 +91,13 @@
****************************************************************************/
/****************************************************************************
- * Name: nsh_execapp
+ * Name: nsh_builtin
*
* Description:
* Attempt to execute the application task whose name is 'cmd'
*
* Returned Value:
- * <0 If exec_namedapp() fails, then the negated errno value
+ * <0 If exec_builtin() fails, then the negated errno value
* is returned.
* -1 (ERROR) if the application task corresponding to 'cmd' could not
* be started (possibly because it doesn not exist).
@@ -104,8 +111,8 @@
*
****************************************************************************/
-int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
- FAR char **argv)
+int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags)
{
int ret = OK;
@@ -119,7 +126,7 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
* applications.
*/
- ret = exec_namedapp(cmd, (FAR const char **)argv);
+ ret = exec_builtin(cmd, (FAR const char **)argv, redirfile, oflags);
if (ret >= 0)
{
/* The application was successfully started (but still blocked because
@@ -191,7 +198,7 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
#if !defined(CONFIG_SCHED_WAITPID) || !defined(CONFIG_NSH_DISABLEBG)
{
struct sched_param param;
- sched_getparam(0, &param);
+ sched_getparam(ret, &param);
nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
/* Backgrounded commands always 'succeed' as long as we can start
@@ -205,13 +212,13 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
sched_unlock();
- /* If exec_namedapp() or waitpid() failed, then return the negated errno
- * value.
+ /* If exec_builtin() or waitpid() failed, then return -1 (ERROR) with the
+ * errno value set appropriately.
*/
if (ret < 0)
{
- return -errno;
+ return ERROR;
}
return ret;
diff --git a/apps/nshlib/nsh_codeccmd.c b/apps/nshlib/nsh_codeccmd.c
new file mode 100644
index 000000000..779fc5ecd
--- /dev/null
+++ b/apps/nshlib/nsh_codeccmd.c
@@ -0,0 +1,538 @@
+/****************************************************************************
+ * apps/nshlib/nsh_codeccmd.c
+ *
+ * This file is part of NuttX, contributed by Darcy Gong
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Darcy Gong 2012-10-30
+ *
+ * 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>
+#ifdef CONFIG_NETUTILS_CODECS
+
+#include <sys/stat.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <errno.h>
+#include <debug.h>
+
+#if defined(CONFIG_NSH_DISABLE_URLENCODE) && defined(CONFIG_NSH_DISABLE_URLDECODE)
+# undef CONFIG_CODECS_URLCODE
+#endif
+
+#ifdef CONFIG_CODECS_URLCODE
+#include <apps/netutils/urldecode.h>
+#endif
+
+#if defined(CONFIG_NSH_DISABLE_BASE64ENC) && defined(CONFIG_NSH_DISABLE_BASE64ENC)
+# undef CONFIG_CODECS_BASE64
+#endif
+
+#ifdef CONFIG_CODECS_BASE64
+#include <apps/netutils/base64.h>
+#endif
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+#include <apps/netutils/md5.h>
+#endif
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_CODECS_BUFSIZE
+# define CONFIG_NSH_CODECS_BUFSIZE 128
+#endif
+
+#define CODEC_MODE_URLENCODE 1
+#define CODEC_MODE_URLDECODE 2
+#define CODEC_MODE_BASE64ENC 3
+#define CODEC_MODE_BASE64DEC 4
+#define CODEC_MODE_HASH_MD5 5
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef void (*codec_callback_t)(FAR char *src_buff, int src_buff_len,
+ FAR char *dst_buff, FAR int *dst_buff_len,
+ int mode);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: urlencode_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLENCODE)
+static void urlencode_cb(FAR char *src_buff, int src_buff_len,
+ FAR char *dst_buff, FAR int *dst_buff_len, int mode)
+{
+ urlencode(src_buff,src_buff_len,dst_buff,dst_buff_len);
+}
+#endif
+
+/****************************************************************************
+ * Name: urldecode_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
+static void urldecode_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ urldecode(src_buff,src_buff_len,dst_buff,dst_buff_len);
+}
+#endif
+
+/****************************************************************************
+ * Name: b64enc_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
+static void b64enc_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ if (mode == 0)
+ {
+ //dst_buff =
+ base64_encode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff, (size_t *)dst_buff_len);
+ }
+ else
+ {
+ //dst_buff =
+ base64w_encode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff, (size_t *)dst_buff_len);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: b64dec_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64DEC)
+static void b64dec_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ if (mode == 0)
+ {
+ //dst_buff =
+ base64_decode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff, (size_t *)dst_buff_len);
+ }
+ else
+ {
+ //dst_buff =
+ base64w_decode((unsigned char *)src_buff, src_buff_len,
+ (unsigned char *)dst_buff,(size_t *)dst_buff_len);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: md5_cb
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+static void md5_cb(FAR char *src_buff, int src_buff_len, FAR char *dst_buff,
+ FAR int *dst_buff_len, int mode)
+{
+ MD5Update((MD5_CTX *)dst_buff, (unsigned char *)src_buff, src_buff_len);
+}
+#endif
+
+/****************************************************************************
+ * Name: calc_codec_buffsize
+ ****************************************************************************/
+
+static int calc_codec_buffsize(int src_buffsize, uint8_t mode)
+{
+ switch (mode)
+ {
+ case CODEC_MODE_URLENCODE:
+ return src_buffsize*3+1;
+ case CODEC_MODE_URLDECODE:
+ return src_buffsize+1;
+ case CODEC_MODE_BASE64ENC:
+ return ((src_buffsize + 2)/ 3 * 4)+1;
+ case CODEC_MODE_BASE64DEC:
+ return (src_buffsize / 4 * 3 + 2)+1;
+ case CODEC_MODE_HASH_MD5:
+ return 32+1;
+ default:
+ return src_buffsize+1;
+ }
+}
+
+/****************************************************************************
+ * Name: cmd_codecs_proc
+ ****************************************************************************/
+
+static int cmd_codecs_proc(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv,
+ uint8_t mode, codec_callback_t func)
+{
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ static const unsigned char hex_chars[] = "0123456789abcdef";
+ MD5_CTX ctx;
+ unsigned char mac[16];
+ char *pSrc;
+ char *pDest;
+#endif
+
+ char *localfile = NULL;
+ char *src_buffer = NULL;
+ char *buffer = NULL;
+ char *fullpath = NULL;
+ const char *fmt;
+ char *s_data;
+ bool badarg = false;
+ bool is_file = false;
+ bool is_websafe=false;
+ int option;
+ int fd = -1;
+ int buff_len = 0;
+ int src_buff_len = 0;
+ int i = 0;
+ int ret = OK;
+
+ /* Get the command options */
+
+ while ((option = getopt(argc, argv, ":fw")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'f':
+ is_file = true;
+ break;
+
+#ifdef CONFIG_CODECS_BASE64
+ case 'w':
+ is_websafe = true;
+
+ if (!(mode == CODEC_MODE_BASE64ENC || mode == CODEC_MODE_BASE64DEC))
+ {
+ badarg = true;
+ }
+ break;
+#endif
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ badarg = true;
+ break;
+ }
+ }
+
+ /* If a bad argument was encountered, then return without processing the command */
+
+ if (badarg)
+ {
+ return ERROR;
+ }
+
+ /* There should be exactly on parameter left on the command-line */
+
+ if (optind == argc-1)
+ {
+ s_data = argv[optind];
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ MD5Init(&ctx);
+ }
+#endif
+
+ if (is_file)
+ {
+ /* Get the local file name */
+
+ localfile = s_data;
+
+ /* Get the full path to the local file */
+
+ fullpath = nsh_getfullpath(vtbl, localfile);
+
+ /* Open the local file for writing */
+
+ fd = open(fullpath, O_RDONLY|O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ ret = ERROR;
+ goto exit;
+ }
+
+ src_buffer = malloc(CONFIG_NSH_CODECS_BUFSIZE+2);
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
+ if (mode == CODEC_MODE_BASE64ENC)
+ {
+ src_buff_len = CONFIG_NSH_CODECS_BUFSIZE / 3 * 3;
+ }
+ else
+#endif
+ {
+ src_buff_len = CONFIG_NSH_CODECS_BUFSIZE;
+ }
+
+ buff_len = calc_codec_buffsize(src_buff_len+2, mode);
+ buffer = malloc(buff_len);
+ while(true)
+ {
+ memset(src_buffer, 0, src_buff_len+2);
+ ret=read(fd, src_buffer, src_buff_len);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
+ ret = ERROR;
+ goto exit;
+ }
+ else if(ret==0)
+ {
+ break;
+ }
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
+ if (mode == CODEC_MODE_URLDECODE)
+ {
+ if (src_buffer[src_buff_len-1]=='%')
+ {
+ ret += read(fd,&src_buffer[src_buff_len],2);
+ }
+ else if (src_buffer[src_buff_len-2]=='%')
+ {
+ ret += read(fd,&src_buffer[src_buff_len],1);
+ }
+ }
+#endif
+ memset(buffer, 0, buff_len);
+ if (func)
+ {
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ func(src_buffer, ret, (char *)&ctx, &buff_len,0);
+ }
+ else
+#endif
+ {
+ func(src_buffer, ret, buffer, &buff_len,(is_websafe)?1:0);
+ nsh_output(vtbl, "%s", buffer);
+ }
+ }
+
+ buff_len = calc_codec_buffsize(src_buff_len+2, mode);
+ }
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ MD5Final(mac, &ctx);
+ pSrc = (char *)&mac;
+ pDest = buffer;
+ for(i=0;i<16;i++,pSrc++)
+ {
+ *pDest++ = hex_chars[(*pSrc) >> 4];
+ *pDest++ = hex_chars[(*pSrc) & 0x0f];
+ }
+
+ *pDest='\0';
+ nsh_output(vtbl, "%s\n", buffer);
+ }
+#endif
+ ret = OK;
+ goto exit;
+ }
+ else
+ {
+ src_buffer = s_data;
+ src_buff_len = strlen(s_data);
+ buff_len = calc_codec_buffsize(src_buff_len, mode);
+ buffer = malloc(buff_len);
+ buffer[0]=0;
+ if (!buffer)
+ {
+ fmt = g_fmtcmdoutofmemory;
+ goto errout;
+ }
+
+ memset(buffer, 0, buff_len);
+ if (func)
+ {
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+ if (mode == CODEC_MODE_HASH_MD5)
+ {
+ func(src_buffer, src_buff_len, (char *)&ctx, &buff_len, 0);
+ MD5Final(mac, &ctx);
+ pSrc = (char *)&mac;
+ pDest = buffer;
+ for(i=0;i<16;i++,pSrc++)
+ {
+ *pDest++ = hex_chars[(*pSrc) >> 4];
+ *pDest++ = hex_chars[(*pSrc) & 0x0f];
+ }
+
+ *pDest='\0';
+ }
+ else
+#endif
+ {
+ func(src_buffer, src_buff_len, buffer, &buff_len,(is_websafe)?1:0);
+ }
+ }
+
+ nsh_output(vtbl, "%s\n",buffer);
+ src_buffer = NULL;
+ goto exit;
+ }
+
+exit:
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+
+ if (fullpath)
+ {
+ free(fullpath);
+ }
+
+ if (src_buffer)
+ {
+ free(src_buffer);
+ }
+
+ if (buffer)
+ {
+ free(buffer);
+ }
+
+ return ret;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ ret = ERROR;
+ goto exit;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_urlencode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLENCODE)
+int cmd_urlencode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_URLENCODE, urlencode_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_urldecode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
+int cmd_urldecode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_URLDECODE, urldecode_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_base64encode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
+int cmd_base64encode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_BASE64ENC, b64enc_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_base64decode
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64DEC)
+int cmd_base64decode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_BASE64DEC, b64dec_cb);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_md5
+ ****************************************************************************/
+
+#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
+int cmd_md5(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cmd_codecs_proc(vtbl,argc,argv,CODEC_MODE_HASH_MD5,md5_cb);
+}
+#endif
+
+#endif /* CONFIG_NETUTILS_CODECS */
diff --git a/apps/nshlib/nsh_mntcmds.c b/apps/nshlib/nsh_mntcmds.c
index 690d027ca..f8e3a142a 100644
--- a/apps/nshlib/nsh_mntcmds.c
+++ b/apps/nshlib/nsh_mntcmds.c
@@ -45,10 +45,13 @@
#include <stdint.h>
#include <stdbool.h>
+#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <debug.h>
+#include <nuttx/fs/nfs.h>
+
#include "nsh.h"
#include "nsh_console.h"
@@ -128,9 +131,9 @@ static int mount_handler(FAR const char *mountpoint,
break;
#endif
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
case BINFS_MAGIC:
- fstype = "bindir";
+ fstype = "binfs";
break;
#endif
@@ -195,9 +198,11 @@ int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT)
int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- FAR char *source;
- FAR char *target;
- FAR char *filesystem = NULL;
+ FAR const char *source;
+ FAR char *fullsource;
+ FAR const char *target;
+ FAR char *fulltarget;
+ FAR const char *filesystem = NULL;
bool badarg = false;
int option;
int ret;
@@ -245,19 +250,32 @@ int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
return ERROR;
}
- /* There are two required arguments after the options: the source and target
- * paths.
+ /* There may be one or two required arguments after the options: the source
+ * and target paths. Some file systems do not require the source parameter
+ * so if there is only one parameter left, it must be the target.
*/
- if (optind + 2 < argc)
+ if (optind >= argc)
{
- nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
return ERROR;
}
- else if (optind + 2 > argc)
+
+ source = NULL;
+ target = argv[optind];
+ optind++;
+
+ if (optind < argc)
{
- nsh_output(vtbl, g_fmtargrequired, argv[0]);
- return ERROR;
+ source = target;
+ target = argv[optind];
+ optind++;
+
+ if (optind < argc)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ return ERROR;
+ }
}
/* While the above parsing for the -t argument looks nice, the -t argument
@@ -274,29 +292,44 @@ int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* working directory.
*/
- source = nsh_getfullpath(vtbl, argv[optind]);
- if (!source)
+ fullsource = NULL;
+ fulltarget = NULL;
+
+ if (source)
{
- return ERROR;
+ fullsource = nsh_getfullpath(vtbl, source);
+ if (!fullsource)
+ {
+ return ERROR;
+ }
}
- target = nsh_getfullpath(vtbl, argv[optind+1]);
- if (!target)
+ fulltarget = nsh_getfullpath(vtbl, target);
+ if (!fulltarget)
{
- nsh_freefullpath(source);
- return ERROR;
+ ret = ERROR;
+ goto errout;
}
/* Perform the mount */
- ret = mount(source, target, filesystem, 0, NULL);
+ ret = mount(fullsource, fulltarget, filesystem, 0, NULL);
if (ret < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
}
- nsh_freefullpath(source);
- nsh_freefullpath(target);
+errout:
+ if (fullsource)
+ {
+ nsh_freefullpath(fullsource);
+ }
+
+ if (fulltarget)
+ {
+ nsh_freefullpath(fulltarget);
+ }
+
return ret;
}
#endif
diff --git a/apps/nshlib/nsh_netcmds.c b/apps/nshlib/nsh_netcmds.c
index 371d30460..506950e14 100644
--- a/apps/nshlib/nsh_netcmds.c
+++ b/apps/nshlib/nsh_netcmds.c
@@ -67,6 +67,7 @@
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
!defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
# include <apps/netutils/uiplib.h>
+# include <apps/netutils/resolv.h>
#endif
#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index 27068acff..ef4125a63 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/nshlib/nsh_parse.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -59,7 +59,7 @@
#endif
#ifdef CONFIG_NSH_BUILTIN_APPS
-# include <apps/apps.h>
+# include <nuttx/binfmt/builtin.h>
#endif
#include <apps/nsh.h>
@@ -72,7 +72,7 @@
/* Argument list size
*
- * argv[0]: The command name.
+ * argv[0]: The command name.
* argv[1]: The beginning of argument (up to CONFIG_NSH_MAXARGUMENTS)
* argv[argc-3]: Possibly '>' or '>>'
* argv[argc-2]: Possibly <file>
@@ -226,7 +226,7 @@ static const struct cmdmap_s g_cmdmap[] =
{ "help", cmd_help, 1, 3, "[-v] [<cmd>]" },
# endif
#endif
-
+
#if CONFIG_NFILE_DESCRIPTORS > 0
#ifndef CONFIG_NSH_DISABLE_HEXDUMP
{ "hexdump", cmd_hexdump, 2, 2, "<file or device>" },
@@ -301,7 +301,7 @@ static const struct cmdmap_s g_cmdmap[] =
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
# ifndef CONFIG_NSH_DISABLE_MOUNT
- { "mount", cmd_mount, 1, 5, "[-t <fstype> <block-device> <mount-point>]" },
+ { "mount", cmd_mount, 1, 5, "[-t <fstype> [<block-device>] <mount-point>]" },
# endif
#endif
@@ -605,7 +605,7 @@ static inline void help_builtins(FAR struct nsh_vtbl_s *vtbl)
/* List the set of available built-in commands */
nsh_output(vtbl, "\nBuiltin Apps:\n");
- for (i = 0; (name = namedapp_getname(i)) != NULL; i++)
+ for (i = 0; (name = builtin_getname(i)) != NULL; i++)
{
nsh_output(vtbl, " %s\n", name);
}
@@ -723,15 +723,11 @@ static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
* Name: nsh_execute
*
* Description:
- * Exectue the command in argv[0]
+ * Execute the command in argv[0]
*
* Returned Value:
- * <0 If exec_namedapp() fails, then the negated errno value
- * is returned.
* -1 (ERRROR) if the command was unsuccessful
* 0 (OK) if the command was successful
- * 1 if an application task was spawned successfully, but
- * returned failure exit status.
*
****************************************************************************/
@@ -751,21 +747,6 @@ static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[])
*/
cmd = argv[0];
-
- /* Try to find a command in the application library. */
-
-#ifdef CONFIG_NSH_BUILTIN_APPS
- ret = nsh_execapp(vtbl, cmd, argv);
-
- /* If the built-in application was successfully started, return OK
- * or 1 (if the application returned a non-zero exit status).
- */
-
- if (ret >= 0)
- {
- return ret;
- }
-#endif
/* See if the command is one that we understand */
@@ -1352,7 +1333,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
/* Parse all of the arguments following the command name. The form
* of argv is:
*
- * argv[0]: The command name.
+ * argv[0]: The command name.
* argv[1]: The beginning of argument (up to CONFIG_NSH_MAXARGUMENTS)
* argv[argc-3]: Possibly '>' or '>>'
* argv[argc-2]: Possibly <file>
@@ -1410,6 +1391,47 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
}
}
+ /* Check if the maximum number of arguments was exceeded */
+
+ if (argc > CONFIG_NSH_MAXARGUMENTS)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, cmd);
+ }
+
+ /* Does this command correspond to a builtin command?
+ * nsh_builtin() returns:
+ *
+ * -1 (ERROR) if the application task corresponding to 'argv[0]' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'argv[0]' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ * Note the priority if not effected by nice-ness.
+ */
+
+#ifdef CONFIG_NSH_BUILTIN_APPS
+ ret = nsh_builtin(vtbl, argv[0], argv, redirfile, oflags);
+ if (ret >= 0)
+ {
+ /* nsh_builtin() returned 0 or 1. This means that the builtin
+ * command was successfully started (although it may not have ran
+ * successfully). So certainly it is not an NSH command.
+ */
+
+ return nsh_saveresult(vtbl, ret != OK);
+ }
+
+ /* No, not a built in command (or, at least, we were unable to start a
+ * builtin command of that name). Treat it like an NSH command.
+ */
+
+#endif
+
/* Redirected output? */
if (vtbl->np.np_redirect)
@@ -1431,23 +1453,13 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
}
}
- /* Check if the maximum number of arguments was exceeded */
-
- if (argc > CONFIG_NSH_MAXARGUMENTS)
- {
- nsh_output(vtbl, g_fmttoomanyargs, cmd);
- }
-
/* Handle the case where the command is executed in background.
- * However is app is to be started as namedapp new process will
- * be created anyway, so skip this step. */
+ * However is app is to be started as builtin new process will
+ * be created anyway, so skip this step.
+ */
#ifndef CONFIG_NSH_DISABLEBG
- if (vtbl->np.np_bg
-#ifdef CONFIG_NSH_BUILTIN_APPS
- && namedapp_isavail(argv[0]) < 0
-#endif
- )
+ if (vtbl->np.np_bg)
{
struct sched_param param;
struct nsh_vtbl_s *bkgvtbl;
@@ -1514,6 +1526,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
priority = min_priority;
}
}
+
param.sched_priority = priority;
}
@@ -1553,8 +1566,6 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
*
* -1 (ERRROR) if the command was unsuccessful
* 0 (OK) if the command was successful
- * 1 if an application task was spawned successfully, but
- * returned failure exit status.
*/
ret = nsh_execute(vtbl, argc, argv);
@@ -1568,11 +1579,11 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
nsh_undirect(vtbl, save);
}
- /* Treat both errors and non-zero return codes as "errors" so that
- * it is possible to test for non-zero returns in nsh scripts.
+ /* Mark errors so that it is possible to test for non-zero return values
+ * in nsh scripts.
*/
- if (ret != OK)
+ if (ret < 0)
{
goto errout;
}
diff --git a/apps/system/Makefile b/apps/system/Makefile
index 9955a6b2c..057fbcf77 100644
--- a/apps/system/Makefile
+++ b/apps/system/Makefile
@@ -73,4 +73,4 @@ depend: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_depend)
clean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_clean)
-distclean: clean $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
+distclean: $(foreach SDIR, $(INSTALLED_DIRS), $(SDIR)_distclean)
diff --git a/apps/system/free/Makefile b/apps/system/free/Makefile
index dada00d99..58ca7956c 100644
--- a/apps/system/free/Makefile
+++ b/apps/system/free/Makefile
@@ -92,11 +92,14 @@ $(COBJS): %$(OBJEXT): %.c
# Register application
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- $(Q) touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
# Create dependencies
@@ -111,7 +114,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/system/i2c/Makefile b/apps/system/i2c/Makefile
index 029d2b6fe..1ed7a2fae 100644
--- a/apps/system/i2c/Makefile
+++ b/apps/system/i2c/Makefile
@@ -68,7 +68,7 @@ STACKSIZE = 2048
# Build targets
all: .built
-.PHONY: .context context .depend depend clean distclean
+.PHONY: context .depend depend clean distclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
@@ -80,11 +80,14 @@ $(COBJS): %$(OBJEXT): %.c
$(call ARCHIVE, $(BIN), $(OBJS))
$(Q) touch .built
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- $(Q) touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
@@ -97,7 +100,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/system/install/Makefile b/apps/system/install/Makefile
index 6a02d859f..07d42887a 100644
--- a/apps/system/install/Makefile
+++ b/apps/system/install/Makefile
@@ -93,11 +93,14 @@ $(COBJS): %$(OBJEXT): %.c
# Register application
-.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- $(Q) touch $@
-context: .context
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
# Create dependencies
@@ -112,7 +115,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/apps/system/readline/Makefile b/apps/system/readline/Makefile
index 3a48d324e..040fd2e28 100644
--- a/apps/system/readline/Makefile
+++ b/apps/system/readline/Makefile
@@ -100,7 +100,6 @@ clean:
$(call CLEAN)
distclean: clean
- $(call DELFILE, .context)
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index ed1cf39dc..6bc66ec9d 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -1452,7 +1452,7 @@
complex: 'uname -o 2>/dev/null || echo "Other"'
* drivers/usbhost/usbhost_enumerate.c: Add logic to get the VID and PID. This
is necessary in order to support vendor-specific USB devices.
- * examplex/wlan, configs/olimex-lpc1766stk/wlan, drivers/usbhost/usbhost_rtl8187.c,
+ * examples/wlan, configs/olimex-lpc1766stk/wlan, drivers/usbhost/usbhost_rtl8187.c,
Add infrastructure to support RTL18187 wireless USB.
* configs/nucleus2g: backed out USB host changes... wrong board.
* Renamed arc/hc/include/mc9s12ne64 and src/mc9s12ne64 to m9s12. That name is
@@ -1920,7 +1920,7 @@
CONFIG_FAT_LCNAMES is not selected, all filenames are strictly upper
case.
* configs/stm3210e-eval/nsh2: Console is back on UART1; Added
- examplex/nx as an NSH "built-in" command as a demonstration.
+ examples/nx as an NSH "built-in" command as a demonstration.
* fs/fat/fs_fat32dirent.c: Fix an important bug in the directory
allocation (fat_allocatedirentry()). I looks like it could be
initializing the wrong sectors! NOTE: This function was in
@@ -3801,3 +3801,170 @@
to find executables using a relative path.
6.25 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
+
+ * graphics/: Adds 5x8 monospace font. This tiny font is useful for graph
+ labels and for small bitmapped display. Contributed by Petteri
+ Aimonen.
+ * configs/stm3220g-eval/nxwm: Converted to use the kconfig-frontends
+ configuration tool.
+ * configs/sim/nxwm: Converted to use the kconfig-frontends configuration
+ tool.
+ * include/pthread.h: In sys/prctl.h because it is needed by
+ pthread_[set|get]name_np()
+ * tools/kconfig.bat: Kludge to run kconfig-frontends from a DOS shell.
+ * sched/sig_timedwait.c: Should always move the time up to the next
+ largest number of system ticks. The logic was rounding. Noted by
+ Petteri Aimonen.
+ * arch/arm/src/up_head.S: Fix backward conditional compilation. NOTE
+ there is a issue of ARM9 systems with low vectors and large memories
+ that will have to be addressed in the future.
+ * libc/misc/lib_kbdencode.c and lib_kbddecode.c: Add logic to marshal
+ and serialized "out-of-band" keyboard commands intermixed with normal
+ ASCII data (not yet hooked into anything).
+ * drivers/usbhost/usbhost_hidkbd.c: If CONFIG_HIDKBD_ENCODED is
+ defined, this driver will now use libc/misc/lib_kbdencode.c to
+ encode special function keys.
+ * configs/olimex-lpc1766stk/hidkbd: This configuration has been
+ converted to use the kconfig-frontends configuration tool.
+ * drivers/lcd/ug-2864hsweg01.c and include/nuttx/lcd/ug-2864hsweg01.h:
+ Driver for UG-2864HSWEG01 OLED contributed by Darcy Gong.
+ * configs/stm32f4discovery/src/up_ug2864hsweg01.c: Support for the
+ UG-2864HSWEG01 OLED for the STM32F4Discovery board.
+ * drivers/usbhost/usbhost_hidkbd.c: Correct a logic error in how
+ tasks waiting for read data are awakened.
+ * libc/misc/lib_kbdencode.c and lib_kbddecode.c: Now handles keypress
+ events too. However, the USB HID keyboard drier has not yet been
+ updated to detect key release events. That is kind of tricky in
+ the USB HID keyboard report data.
+ * configs/mcu123-214x/nsh: Converted to use the kconfig-frontends
+ configuration tool.
+ * configs/zp214xpa: Add basic support for the The0.net ZP213x/4xPA
+ board (with the LPC2148 and the UG_2864AMBAG01).
+ * configs/sim/nxlines: Add an nxlines configuration for the
+ simulator.
+ * configs/zp214xpa/nxlines: Add an nxlines configuration for the
+ ZP213x/4xPA (with the LPC2148 and the UG_2864AMBAG01). Working
+ as of 2012-12-30.
+ * configs/olimex-lpc1766stk/wlan: Remove non-functional
+ configuration.
+ * configs/stm32f4discovery/src and nuttx/drivers/lcd/ug-2864hsweg01.c:
+ Updates and correctinos for the UG-2864HSWEG01 from Darcy Gong.
+ * configs/lm326965-ek: All configurations converted to use the
+ kconfig-frontends configuration tool.
+ * configs/Kconfig: NSH_MMCSDSPIPORTNO should depend on MMCSD_SPI,
+ not just SPI (from Jose Pablo Carballo).
+ * arch/arm/src/arm/Kconfig and armv7m/Kconfig: Add an option for
+ buildroot toolchains: They may be EABI or OABI.
+ * include/nuttx/progmem and arch/arm/src/stm32/stm32_flash.c:
+ Fix a counting bug plus change interface to use either relative
+ or absolut FLASH addressing (from Freddie Chopin).
+ * libc/misc/Make.defs: Fix error in conditional for KBD CODEC.
+ * libc/Kconfig and configs/*/defconfig (several): The default
+ setting should be CONFIG_LIB_KBDCODEC=n
+ * tools/configure.c: configure.c can be used to build a work-alike
+ program as a replacement for configure.sh. This work-alike
+ program would be used in environments that do not support Bash
+ scripting (such as the Windows native environment).
+ * tools/configure.bat: configure.bat is a small Windows batch
+ file that can be used as a replacement for configure.sh in a
+ Windows native environment. configure.bat is actually just a
+ thin layer that execuates configure.exe if it is available. If
+ configure.exe is not available, then configure.bat will attempt
+ to build it first.
+ * arch/arm/src/lpc17xx/lpc17_syscon.h: Correct some typos in bit
+ definitions (from Rommel Marcelo).
+ * libc/string/lib_strndup.c: strndup() should use strnlen(), not
+ strlen(), to determine the size of the string.
+ * sched/os_bringup.c: Remove support for CONFIG_BUILTIN_APP_START.
+ This is not really a useful feature and creates a violation of the
+ OS layered architecture.
+ * include/unistd.h, arch/arch/src/*: Implement a simple vfork().
+ On initial checkin, this API is available only for ARM platforms.
+ * binfmt/binfmt_exec.c: exec() now sets the priority of the new task
+ to the same priority as the current task (instead of the arbirtrary
+ value of 50).
+ * libc/unisted/lib_execv.c and lib_execl.c: New, somewhat flawed,
+ implementations of execv() and execl().
+ * tools/cfgdefine.c: Strips quotes from CONFIG_EXECFUNCS_SYMTAB
+ value.
+ * arch/arm/include/lm3s/chip.h: Move chip definitions into
+ public include area for compatibility with other architectures.
+ * arch/arm/src/lm3s/chip: Move register definition header files
+ into a new chip/ sub-directory.
+ * arch/arm/src/lm3s/lm3s_internal.h: Broke up into several
+ smaller header files.
+ * arch/arm/src/lm: Rename the arch/arm/src/lm3s directory to
+ arch/arm/src/lm so that is can support other members of the
+ Stellaris family.
+ * libc/spawn: Add file action interfaces needed by posix_spawn().
+ * sched/clock_time2ticks.c: Another case where time was being
+ rounded down instead of up (from Mike Smith).
+ * libc/spawn: Implementation of posix_spawn() is complete but
+ untested and undocumented.
+ * drivers/usbdev/pl2303.c: Fix typols in the PL2303 driver
+ (from Max Holtzberg).
+ * configs/stm32f4discovery/posix_spawn: Added a configuration
+ that can be used for testing posix_spawn().
+ * arch/arm/src/stm32: Bring F1 support for general DMA and serial
+ DMA in paricular up to parity with F2/F4 (from Mike Smith).
+ * libc/stdio/lib_libfread.c: Correct some error handling when
+ lib_fread() was passed a bad stream. Needed to move the
+ releasing of a semaphore inside of some conditional logic
+ (cosmetic).
+ * include/nuttx/sched.h, sched/task_setup.c, and sched/task_exithook.c:
+ Add support for remembering the parent task and sending
+ SIGCHLD to the parent when the task exists.
+ * sched/task_exithook.c: Fixed a *critical* bug. Here is
+ the scenario: (1) sched_lock() is called increments the lockcount
+ on the current TCB (i.e., the one at the head of the ready to run
+ list), (2) sched_mergepending is called which may change the task
+ at the head of the readytorun list, then (2) sched_unlock() is called
+ which decrements the lockcount on the wrong TCB. The failure case
+ that I saw was that pre-emption got disabled in the IDLE thread,
+ locking up the whole system.
+ * sched/sched_waitpid.c: Use SIGCHLD instead of a semaphore. This
+ is a much more spec-compliant implemenation. However, there are
+ some issues with overruning signals because NuttX does not support
+ queueing of signals (POSIX does not require it). I think it may
+ need to.
+ * sched/sched_waitid.c and sched_wait.c: Add support for waitid()
+ and wait(). See issues with waitpid() above.
+ * include/nuttx/fs/fs.h and fs/fs_files.c: Add a dup() method to
+ the struct mountpt_operations. When dup'ing a file that resides
+ on a mounted volume, let the file system's dup() method do the
+ work.
+ * fs/romfs/fs_romfs.c: Implemented the dup() method for the ROMFS
+ file system.
+ * fs/fat/fs_fat32.c, fs/nxffs/nxffs_initialize, and
+ fs/nfs/nfs_vfsops.c: Add hooks for dup() method (not yet
+ implemented).
+ * fs/romfs: Remove the rf_open flag. It looks good, but actually
+ does nothing.
+ * fs/fat: Remove the ff_open flag. Same story as for the ROMFS
+ rf_open flag.
+ * fs/fat/fs_fat32.c, fs/nxffs/nxffs_initialize, and
+ fs/nfs/nfs_vfsops.c: Completed implementation of the dup() methods.
+ There is still no good test available.
+ * sched/sig_timedwait.c: sigtimedwait() would return a bad signal
+ number if the signal was already pending when the function was
+ called.
+ * configs/ubw32/scripts: All common linker scripts moved to this
+ scripts sub-directory
+ * configs/ubw32/ostest: Configuration configured to use the
+ kconfig-frontends tools.
+ * arch/mips/src/mips32/up_vfork.c, up_vfork.h, and vfork.S:
+ Implement vfork() for MIPS32 (no floating point support)
+ * configs/ubw32/ostest: Enable the vfork() test.
+ * fs/binfs: Move apps/builtin/binfs.c to fs/binfs/fs_binfs.c
+ CONFIG_APPS_BINDIR rename CONFIG_FS_BINFS
+ * include/nuttx/binfmt/builtin.h: Some of the content of
+ apps/include/apps.h moved to include/nuttx/binfmt/builtin.h
+ * binfmt/libbuiltin/libbuiltin_utils.c: Move utility builtin
+ utility functions from apps/builtin/exec_builtins.c to
+ binfmt/libbuiltin/libbuiltin_utils.c
+ * binfmt/builtin.c and binfmt/libbuiltin: Add a binary "loader"
+ that can be used to execute builtin programs from the BINFS
+ file system.
+ * configs/sim/nsh: Convert to use kconfig-frontends configuration
+ tool.
+
diff --git a/nuttx/Makefile.unix b/nuttx/Makefile.unix
index d66c06bd8..47debcccf 100644
--- a/nuttx/Makefile.unix
+++ b/nuttx/Makefile.unix
@@ -642,13 +642,13 @@ pass2dep: context tools/mkdeps$(HOSTEXEEXT)
# misc/tools/README.txt for additional information.
config:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf Kconfig
+ $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf Kconfig
oldconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf --oldconfig Kconfig
+ $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --oldconfig Kconfig
menuconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} mconf Kconfig
+ $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-mconf Kconfig
# export
#
diff --git a/nuttx/Makefile.win b/nuttx/Makefile.win
index 34da12ad0..5c4404f57 100644
--- a/nuttx/Makefile.win
+++ b/nuttx/Makefile.win
@@ -252,7 +252,7 @@ LINKLIBS = $(patsubst lib\\%,%,$(NUTTXLIBS))
BIN = nuttx$(EXEEXT)
all: $(BIN)
-.PHONY: context clean_context check_context export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
+.PHONY: context clean_context check_context configenv config oldconfig menuconfig export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
# Target used to copy include\nuttx\math.h. If CONFIG_ARCH_MATH_H is
# defined, then there is an architecture specific math.h header file
@@ -452,7 +452,7 @@ clean_context:
# check_context
#
# This target checks if NuttX has been configured. NuttX is configured using
-# the script tools\configure.sh. That script will install certain files in
+# the script tools\configure.bat. That script will install certain files in
# the top-level NuttX build directory. This target verifies that those
# configuration files have been installed and that NuttX is ready to be built.
@@ -647,14 +647,17 @@ pass2dep: context tools\mkdeps$(HOSTEXEEXT)
# location: http://ymorin.is-a-geek.org/projects/kconfig-frontends. See
# misc\tools\README.txt for additional information.
-config:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf Kconfig
+configenv:
+ $(Q) set APPSDIR=${CONFIG_APPS_DIR}
-oldconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} conf --oldconfig Kconfig
+config: configenv
+ $(Q) kconfig-conf Kconfig
-menuconfig:
- $(Q) APPSDIR=${CONFIG_APPS_DIR} mconf Kconfig
+oldconfig: configenv
+ $(Q) kconfig-conf --oldconfig Kconfig
+
+menuconfig: configenv
+ $(Q) kconfig-mconf Kconfig
# export
#
diff --git a/nuttx/README.txt b/nuttx/README.txt
index b9210277e..2ff473fa0 100644
--- a/nuttx/README.txt
+++ b/nuttx/README.txt
@@ -10,6 +10,9 @@ README
o Configuring NuttX
- Instantiating "Canned" Configurations
- NuttX Configuration Tool
+ - Incompatibilities with Older Configurations
+ - Converting Older Configurations to use the Configuration Tool
+ - NuttX Configuration Tool under DOS
o Toolchains
- Cross-Development Toolchains
- NuttX Buildroot Toolchain
@@ -38,6 +41,10 @@ Installing Cygwin
tiny setup.exe program and it does the real, internet installation
for you.
+ NOTE: NuttX can also be installed and built on a native Windows
+ system, but with some loss of tool functionality (see the
+ discussion "Native Windows Build" below).
+
Some Cygwin installation tips:
1. Install at C:\cygwin
@@ -58,8 +65,9 @@ Installing Cygwin
After installing Cygwin, you will get lots of links for installed
tools and shells. I use the RXVT native shell. It is fast and reliable
and does not require you to run the Cygwin X server (which is neither
- fast nor reliable). The rest of these instructions assume that you
- are at a bash command line prompt in either Linux or in Cygwin shell.
+ fast nor reliable). Unless otherwise noted, the rest of these
+ instructions assume that you are at a bash command line prompt in
+ either Linux or in Cygwin shell.
Download and Unpack
-------------------
@@ -235,8 +243,8 @@ additional file to the directory the NuttX application package (APPSDIR)):
The appconfig file describes the applications that need to be
built in the appliction directory (APPSDIR). Not all configurations
have an appconfig file. This file is deprecated and will not be
- used with new defconfig files produced with the mconf configuration
- tool.
+ used with new defconfig files produced with the kconfig-mconf
+ configuration tool.
General information about configuring NuttX can be found in:
@@ -249,6 +257,13 @@ easier. It is used as follows:
cd ${TOPDIR}/tools
./configure.sh <board-name>/<config-dir>
+There is an alternative Windows batch file that can be used in the
+windows native enironment like:
+
+ cd ${TOPDIR}\tools
+ configure.bat <board-name>\<config-dir>
+
+See tools/README.txt for more information about these scripts.
NuttX Configuration Tool
------------------------
@@ -292,6 +307,162 @@ NuttX Configuration Tool
install 'mconf', make certain that your PATH variable includes
a path to that installation directory.
+ The basic configuration order is "bottom-up":
+
+ - Select the build environment,
+ - Select the processor,
+ - Select the board,
+ - Select the supported peripherals
+ - Configure the device drivers,
+ - Configure the application options on top of this.
+
+ This is pretty straight forward for creating new configurations
+ but may be less intuitive for modifying existing configurations.
+
+Incompatibilities with Older Configurations
+-------------------------------------------
+
+ ***** WARNING *****
+
+ The old legacy, manual configurations and the new kconfig-frontends
+ configurations are not 100% compatible. Old legacy configurations
+ can *not* be used with the kconfig-frontends tool: If you run
+ 'make menuconfig' with a legacy configuration the resulting
+ configuration will probably not be functional.
+
+ Q: How can I tell if a configuration is a new kconfig-frontends
+ configuration or an older, manual configuration?
+
+ A: a) New kcondfig-frontends configurations will have this setting
+ within the defconfig/.config file":
+
+ CONFIG_NUTTX_NEWCONFIG=y
+
+ b) Only old, manual configurations will have an appconfig file
+
+Converting Older Configurations to use the Configuration Tool
+-------------------------------------------------------------
+
+ Q: How can I convert a older, manual configuration into a new,
+ kconfig-frontends toolchain.
+
+ A: 1) Look at the appconfig file: Each application path there
+ will now have to have an enabling setting. For example,
+ if the old appconfig file had:
+
+ CONFIGURED_APPS = examples/ostest
+
+ Then the new configuration will need:
+
+ CONFIG_EXAMPLES_OSTEST=y
+
+ The appconfig file can then be deleted because it will not
+ be needed after the conversion.
+
+ 2) Build the cmpconfig utility at tools:
+
+ cd tools
+ make -f Makefile.host cmpconfig
+
+ 3) Perform these steps repeatedly until you are convinced that
+ the configurations are the same:
+
+ a) Repeat the following until you have account for all of the differences:
+
+ cp configs/<board>/<condfiguration>/defconfig .config
+ make menuconfig (Just exit and save the new .config file)
+ tools/cmpconfig configs/<board>/<condfiguration>/defconfig .config | grep file1
+
+ The final grep will show settings in the old defconfig file that
+ do not appear in the new .config file (or have a different value
+ in the new .config file). In the new configuration, you will
+ probably have to enable certain groups of features. Such
+ hierarachical enabling options were not part of the older
+ configuration.
+
+ b) Then make sure these all make sense:
+
+ tools/cmpconfig configs/<board>/<condfiguration>/defconfig .config | grep file2
+
+ The final grep will show settings in the new .config file that
+ do not appear in the older defconfig file (or have a different value
+ in the new .config file). Here you should see only the new
+ hierarachical enabling options (such as CONFIG_SPI or CONFIG_MMCSD)
+ plus some other internal configuration settings (like CONFIG_ARCH_HAVE_UART0).
+ You will have to convince yourself that these new settings all make sense.
+
+ 4) Finally, update the configuration:
+
+ cp .config configs/<board>/<condfiguration>/defconfig
+ rm configs/<board>/<condfiguration>/appconfig
+
+ NOTE: You should comment out the line containing the CONFIG_APPS_DIR
+ in the new defconfig file. Why? Because the application directory
+ may reside at a different location when the configuration is installed
+ at some later time.
+
+ # CONFIG_APPS_DIR="../apps"
+
+ 5) The updated configuration can then be instantiated in the normal
+ fashion:
+
+ cd tools
+ ./configure.sh <board>/<condfiguration>
+
+ (or configure.bat for the case of the Windows native build).
+
+ NOTE: If CONFIG_APPS_DIR is not defined in the defconfig file,
+ the configure.sh script will find and add the new, correct path to
+ the application directory (CONFIG_APPS_DIR) when it copies the
+ defconfig file to the .config file. This is the setting that was
+ commented out in step 4.
+
+NuttX Configuration Tool under DOS
+----------------------------------
+
+ Recent versions of NuttX support building NuttX from a native Windows
+ console window (see "Native Windows Build" below). But kconfig-frontends
+ is a Linux tool. There have been some successes building a Windows
+ native version of the kconfig-frontends tool, but that is not ready
+ for prime time.
+
+ At this point, there are only a few options for the Windows user:
+
+ 1. You can run the configuration tool using Cygwin. However, the
+ Cygwin Makefile.win will complain so to do this will, you have
+ to manually edit the .config file:
+
+ a. Delete the line: CONFIG_WINDOWS_NATIVE=y
+ b. Change the apps/ directory path, CONFIG_APPS_DIR to use Unix
+ style delimiters. For example, change "..\apps" to "../apps"
+
+ And of course, after you use the configuration tool you need to
+ restore CONFIG_WINDOWS_NATIVE=y and the correct CONFIG_APPS_DIR.
+
+ 2) You can, with some effort, run the the Cygwin kconfig-mconf tool
+ directly in the Windows console window. In this case, you do not
+ have to modify the .config file, but there are other complexities:
+
+ a. You need to temporarily set the Cgywin directories in the PATH
+ variable then run kconfig-mconf manually like:
+
+ kconfig-mconf Kconfig
+
+ There is a Windows bacht file at tools/kconfig.bat that automates
+ these steps:
+
+ tools/kconfig menuconfig
+
+ b. There is an issue with accessing DOS environment variables from
+ the Cygwin kconfig-mconf running in the Windows console. The
+ following change to the top-level Kconfig file seems to work
+ around these problems:
+
+ config APPSDIR
+ string
+ - option env="APPSDIR"
+ + default "../apps"
+
TOOLCHAINS
^^^^^^^^^^
@@ -509,82 +680,93 @@ Native Windows Build
- A few extensions from GNUWin32
In this build, you cannot use a Cygwin or MSYS shell. Rather the build must
- be performed in a Windows CMD shell. Here is a better shell than than the
- standard issue, CMD shell: ConEmu which can be downloaded from:
+ be performed in a Windows console window. Here is a better terminal than the
+ standard issue, CMD.exe terminal: ConEmu which can be downloaded from:
http://code.google.com/p/conemu-maximus5/
Build Tools. The build still relies on some Unix-like commands. I use
the GNUWin32 tools that can be downloaded from http://gnuwin32.sourceforge.net/.
- Host Compiler: I use the MingGW compiler which can be downloaded from
+ Host Compiler: I use the MingGW GCC compiler which can be downloaded from
http://www.mingw.org/. If you are using GNUWin32, then it is recommended
the you not install the optional MSYS components as there may be conflicts.
+ This capability should still be considered a work in progress because:
+
+ (1) It has not been verfied on all targets and tools, and
+ (2) it still lacks some of the creature-comforts of the more mature environments
+ (like 'make menuconfig' support. See the section "NuttX Configuration Tool
+ under DOS" above).
+
+ There is an alternative to the setenv.sh script available for the Windows
+ native environment: tools/configure.bat. See tools/README.txt for additional
+ information.
+
Installing GNUWin32
-------------------
-The Windows native build will depend upon a few Unix-like tools that can be
-provided either by MSYS or GNUWin32. The GNUWin32 are available from
-http://gnuwin32.sourceforge.net/. GNUWin32 provides ports of tools with a
-GPL or similar open source license to modern MS-Windows (Microsoft Windows
-2000 / XP / 2003 / Vista / 2008 / 7). See
-http://gnuwin32.sourceforge.net/packages.html for a list of all of the tools
-available in the GNUWin32 package.
+ The Windows native build will depend upon a few Unix-like tools that can be
+ provided either by MSYS or GNUWin32. The GNUWin32 are available from
+ http://gnuwin32.sourceforge.net/. GNUWin32 provides ports of tools with a
+ GPL or similar open source license to modern MS-Windows (Microsoft Windows
+ 2000 / XP / 2003 / Vista / 2008 / 7). See
+ http://gnuwin32.sourceforge.net/packages.html for a list of all of the tools
+ available in the GNUWin32 package.
-The SourceForge project is located here:
-http://sourceforge.net/projects/gnuwin32/. The project is still being
-actively supported (although some of the Windows ports have gotten very old).
+ The SourceForge project is located here:
+ http://sourceforge.net/projects/gnuwin32/. The project is still being
+ actively supported (although some of the Windows ports have gotten very old).
-Some commercial toolchains include a subset of the GNUWin32 tools in the
-installation. My recommendation is that you download the GNUWin32 tools
-directly from the sourceforge.net website so that you will know what you are
-using and can reproduce your build environment.
+ Some commercial toolchains include a subset of the GNUWin32 tools in the
+ installation. My recommendation is that you download the GNUWin32 tools
+ directly from the sourceforge.net website so that you will know what you are
+ using and can reproduce your build environment.
-GNUWin32 Installation Steps:
+ GNUWin32 Installation Steps:
-The following steps will download and execute the GNUWin32 installer.
+ The following steps will download and execute the GNUWin32 installer.
-1. Download GetGNUWin32-x.x.x.exe from
- http://sourceforge.net/projects/getgnuwin32/files/. This is the
- installer. The current version as of this writing is 0.6.3.
+ 1. Download GetGNUWin32-x.x.x.exe from
+ http://sourceforge.net/projects/getgnuwin32/files/. This is the
+ installer. The current version as of this writing is 0.6.3.
-2. Run the installer.
+ 2. Run the installer.
-3. Accept the license.
+ 3. Accept the license.
-4. Select the installation directory. My recommendation is the
- directory that contains this README file (<this-directory>).
+ 4. Select the installation directory. My recommendation is the
+ directory that contains this README file (<this-directory>).
-5. After running GetGNUWin32-0.x.x.exe, you will have a new directory
- <this-directory>/GetGNUWin32
+ 5. After running GetGNUWin32-0.x.x.exe, you will have a new directory
+ <this-directory>/GetGNUWin32
-Note the the GNUWin32 installer didn't install GNUWin32. Instead, it
-installed another, smarter downloader. That downloader is the GNUWin32
-package management tool developed by the Open SSL project.
+ Note the the GNUWin32 installer didn't install GNUWin32. Instead, it
+ installed another, smarter downloader. That downloader is the GNUWin32
+ package management tool developed by the Open SSL project.
-The following steps probably should be performed from inside a DOS shell.
+ The following steps probably should be performed from inside a DOS shell.
-6. Change to the directory created by GetGNUWin32-x.x.x.exe
+ 6. Change to the directory created by GetGNUWin32-x.x.x.exe
- cd GetGNUWin32
+ cd GetGNUWin32
-7. Execute the download.bat script. The download.bat script will download
- about 446 packages! Enough to have a very complete Linux-like environment
- under the DOS shell. This will take awhile. This step only downloads
- the packages and the next step will install the packages.
+ 7. Execute the download.bat script. The download.bat script will download
+ about 446 packages! Enough to have a very complete Linux-like environment
+ under the DOS shell. This will take awhile. This step only downloads
+ the packages and the next step will install the packages.
- download
+ download
-8. This step will install the downloaded packages. The argument of the
- install.bat script is the installation location. C:\gnuwin32 is the
- standard install location:
+ 8. This step will install the downloaded packages. The argument of the
+ install.bat script is the installation location. C:\gnuwin32 is the
+ standard install location:
- install C:\gnuwin32
+ install C:\gnuwin32
-NOTE: This installation step will install *all* GNUWin32 packages... far
-more than you will ever need. If disc space is a problem for you, you might
-need to perform a manual installation of the individual ZIP files that you
-will find in the <this directory>/GetGNUWin32/packages directory.
+ NOTE: This installation step will install *all* GNUWin32 packages... far
+ more than you will ever need. If disc space is a problem for you, you might
+ need to perform a manual installation of the individual ZIP files that you
+ will find in the <this directory>/GetGNUWin32/packages directory.
CYGWIN BUILD PROBLEMS
^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/TODO b/nuttx/TODO
index 6c28bfd43..248d2dafa 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated November 25, 2012)
+NuttX TODO List (Last updated January 14, 2013)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -6,21 +6,20 @@ standards, things that could be improved, and ideas for enhancements.
nuttx/
- (6) Task/Scheduler (sched/)
- (1) On-demand paging (sched/)
+ (10) Task/Scheduler (sched/)
(1) Memory Managment (mm/)
- (2) Signals (sched/, arch/)
+ (3) Signals (sched/, arch/)
(2) pthreads (sched/)
(2) C++ Support
(6) Binary loaders (binfmt/)
(17) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
- (11) Libraries (libc/, )
+ (12) Libraries (libc/, )
(9) File system/Generic drivers (fs/, drivers/)
(5) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/)
(1) Documentation (Documentation/)
- (8) Build system / Toolchains
+ (7) Build system / Toolchains
(5) Linux/Cywgin simulation (arch/sim)
(6) ARM (arch/arm/)
(1) ARM/C5471 (arch/arm/src/c5471/)
@@ -31,8 +30,8 @@ nuttx/
(2) ARM/LPC313x (arch/arm/src/lpc313x/)
(0) ARM/LPC43x (arch/arm/src/lpc43xx/)
(3) ARM/STR71x (arch/arm/src/str71x/)
- (3) ARM/LM3S6918 (arch/arm/src/lm3s/)
- (4) ARM/STM32 (arch/arm/src/stm32/)
+ (3) ARM/LM3S6918 (arch/arm/src/lm/)
+ (5) ARM/STM32 (arch/arm/src/stm32/)
(3) AVR (arch/avr)
(0) Intel x86 (arch/x86)
(5) 8051 / MCS51 (arch/8051/)
@@ -56,33 +55,9 @@ o Task/Scheduler (sched/)
Title: CHILD PTHREAD TERMINATION
Description: When a tasks exits, shouldn't all of its child pthreads also be
terminated?
- Status: Open
+ Status: Closed. No, this behavior will not be implemented.
Priority: Medium, required for good emulation of process/pthread model.
- Title: MMAN.H
- Description: Implement sys/mman.h and functions
- Status: Open
- Priority: Low
-
- Title: WAIT.H
- Description: Implement sys/wait.h and functions. Consider implementing wait,
- waitpid, waitid. At present, a parent has no information about
- child tasks.
-
- Update: A simple but usable version of waitpid() has been included.
- This version is not compliant with all specifications and can be
- enabled with CONFIG_SCHED_WAITPID.
- Status: Open
- Priority: Low
-
- Title: MISSING ERRNO SETTINGS
- Description: Several APIs do not set errno. Need to review all APIs.
- Update: These are being fixed as they are encountered. There is
- no accounting of how many interfaces have this problem.
- Status: Open
- Priority: Medium, required for standard compliance (but makes the
- code bigger)
-
Title: TICKLESS OS
Description: On a side note, I have thought about a tick-less timer for the OS
for a long time. Basically we could replace the periodic system
@@ -107,18 +82,22 @@ o Task/Scheduler (sched/)
3) sched_process_timeslice(). Then there is round-robin time-slicing.
- Status: Open
+ The primary advantage of a tickless OS is that is would allow for
+ reduce power consumptions. That is because timer interrupts will
+ usually awaken CPUs from reduced power consumption states.
+ Status: Open. There will probably be no tickless OS implementation unless
+ someone gets motivated and drives the change.
Priority: Low
- Title: posix_spawn()
- Description: This would be a good interface to add to NuttX. It is really
- just a re-packaging of the existing, non-standard NuttX exec()
- function.
- Status: Open
- Priority: Medium low.
-
-o On-demand paging (sched/)
- ^^^^^^^^^^^^^^^^^^^^^^^^^
+ Title: pause() NON-COMPLIANCE
+ Description: In the POSIX description of this function is the pause() function
+ will suspend the calling thread until delivery of a signal whose
+ action is either to execute a signal-catching function or to
+ terminate the process. The current implementation only waits for
+ any non-blocked signal to be received. It should only wake up if
+ the signal is delivered to a handler.
+ Status: Open.
+ Priority: Medium Low.
Title: ON-DEMAND PAGE INCOMPLETE
Description: On-demand paging has recently been incorporated into the RTOS.
@@ -130,19 +109,16 @@ o On-demand paging (sched/)
configs/ea3131/pgnsh and locked directories). There are
some limitations of this testing so I still cannot say that
the feature is fully functional.
- Status: Open
+ Status: Open. This has been put on the shelf for some time.
Priority: Medium-Low
-o Other core OS logic
- ^^^^^^^^^^^^^^^^^^^
-
Title: GET_ENVIRON_PTR()
Description: get_environ_ptr() (sched/sched_getenvironptr.c) is not implemented.
The representation of the the environment strings selected for
NutX is not compatible with the operation. Some significant
re-design would be required to implement this funcion and that
effort is thought to be not worth the result.
- Status: Open
+ Status: Open. No change is planned.
Priority: Low -- There is no plan to implement this.
Title: TIMER_GETOVERRUN()
@@ -150,6 +126,91 @@ o Other core OS logic
Status: Open
Priority: Low -- There is no plan to implement this.
+ Title: USER-SPACE WORK QUEUES
+ Description: There has been some use of work queues that has crept into some
+ user code. I am thinking of NxWidgets::CNxTimer. That timer
+ logic was originally implemented (correctly) using POSIX timers,
+ but was re-implemented using timed work.
+
+ The issue is that NxWidgets::CNxTimer is a user-space application
+ but the work queues are an OS internal feature. This will be a
+ problem for KERNEL builds. Hooks and definitions have been added
+ in include/nuttx/wqueue.h to support a user-space work queue, but
+ the corresponding logic has not been implemented.
+
+ The work queue logic will need to be moved from sched/ to libc/wqueue/
+ Status: Open. No work will probably be done until a functional KERNEL build
+ that includes NxWisges::CNxTimer is needed.
+ Priority: Medium Low for now
+
+ Title: INCOMPATIBILITES WITH execv() AND execl()
+ Description: Simplified 'execl()' and 'execv()' functions are provided by
+ NuttX. NuttX does not support processes and hence the concept
+ of overlaying a tasks process image with a new process image
+ does not make any sense. In NuttX, these functions are
+ wrapper functions that:
+
+ 1. Call the non-standard binfmt function 'exec', and then
+ 2. exit(0).
+
+ As a result, the current implementations of 'execl()' and
+ 'execv()' suffer from some incompatibilities, the most
+ serious of these is that the exec'ed task will not have
+ the same task ID as the vfork'ed function. So the parent
+ function cannot know the ID of the exec'ed task.
+ Status: Open
+ Priority: Medium Low for now
+
+ Title: RETAINING TASK EXIT STATUS
+ Description: When a task exists, its exit status should be retained in
+ so data structure until it is reaped (via waitpid(), or
+ similar interface) or until the parent thread exists.
+
+ You would think that this should be a clone of the existing
+ pthread join logic. Howver there is no need for zombies
+ in NuttX so no need to keep the status if the parent has
+ already exit'ed. Other simplifications:
+
+ 1. Keep the array/list of return status in the parent
+ tasks TCB.
+ 2. Use a fixed size array of return status (perhaps the
+ the enire array is allocated so that that is con
+ penalty for tasks that have no childre.
+
+ At present, exit status is not retained. If waitpid()
+ is called after the child task has exit'ed it simpley
+ returns with the ECHLD error. That is not too bad, but
+ does not tell you what the exit status was.
+
+ A work-around is to:
+ 1) Call sched_lock() to disable pre-emption.
+ 2) Start the task (it cannot run because pre-emption is
+ disbled.
+ 3) Call waitpid();
+ 4) Call sched_unlock() to re-enable pre-emption.
+
+ Status: Open
+ Priority: Low
+
+ Title: IMPROVED TASK CONTROL BLOCK STRUCTURE
+ All task resources that are shared amongst threads have
+ their own "break-away", reference-counted structure. The
+ Task Control Block (TCB) of each thread holds a reference
+ to each breakaway structure (see include/nuttx/sched.h).
+ It would be more efficent to have one reference counted
+ structure that holds all of the shared resources.
+
+ These are the current shared structures:
+ - Environment varaibles (struct environ_s)
+ - PIC data space and address environments (struct dspace_s)
+ - File descriptors (struct filelist)
+ - FILE streams (struct streamlist)
+ - Sockets (struct socketlist)
+ Status: Open
+ Priority: Low. This is an enhancement. It would slight reduce
+ memory usage but would also increase coupling. These
+ resources are nicely modular now.
+
o Memory Managment (mm/)
^^^^^^^^^^^^^^^^^^^^^^
@@ -212,7 +273,7 @@ o Memory Managment (mm/)
be required to keep this memory on the correct list (or on
no list at all).
- Status: Open
+ Status: Open. No changes are planned.
Priority: Medium/Low, a good feature to prevent memory leaks but would
have negative impact on memory usage and code size.
@@ -221,8 +282,10 @@ o Signals (sched/, arch/)
Title: STANDARD SIGNALS
Description: 'Standard' signals and signal actions are not supported.
- (e.g., SIGINT, SIGCHLD, SIGSEGV, etc).
- Status: Open
+ (e.g., SIGINT, SIGSEGV, etc).
+
+ Update: SIG_CHLD is support if configured.
+ Status: Open. No changes are planned.
Priority: Low, required by standards but not so critical for an
embedded system.
@@ -234,17 +297,25 @@ o Signals (sched/, arch/)
are required by the POSIX standard.
Priority: Low for now
+ Title: SIGNAL NUMBERING
+ Description: In signal.h, the range of valid signals is listed as 0-31. However,
+ in many interfaces, 0 is not a valid signal number. The valid
+ signal number should be 1-32. The signal set operations would need
+ to map bits appropriately.
+ Status: Open
+ Priority: Low. Even if there are only 31 usable signals, that is still a lot.
+
o pthreads (sched/)
^^^^^^^^^^^^^^^^^
Title: CANCELLATION POINTS
Description: pthread_cancel(): Should implement cancellation points and
pthread_testcancel()
- Status: Open
+ Status: Open. No changes are planned.
Priority: Low, probably not that useful
Title: PTHREAD_PRIO_PROTECT
- Description: Extended pthread_mutexattr_setprotocol() suport PTHREAD_PRIO_PROTECT:
+ Description: Extended pthread_mutexattr_setprotocol() suport PTHREAD_PRIO_PROTECT:
"When a thread owns one or more mutexes initialized with the
PTHREAD_PRIO_PROTECT protocol, it shall execute at the higher of its
priority or the highest of the priority ceilings of all the mutexes
@@ -260,7 +331,7 @@ o pthreads (sched/)
PTHREAD_PRIO_PROTECT protocol attributes, it shall not be subject to
being moved to the tail of the scheduling queue at its priority in the
event that its original priority is changed."
- Status: Open
+ Status: Open. No changes planned.
Priority: Low -- about zero, probably not that useful. Priority inheritance is
already supported and is a much better solution. And it turns out
that priority protection is just about as complex as priority inheritance.
@@ -442,21 +513,25 @@ o Network (net/, drivers/net)
Title: SOCK_RAW/SOCK_PACKET
Description: Should implement SOCK_RAW, SOCK_PACKET
- Status: Open
+ Status: Open. No changes are planned.
Priority: Low
Tile: MULTIPLE NETWORK INTERFACE SUPPORT
Description: uIP polling issues / Multiple network interface support:
+
(1) Current logic will not support multiple ethernet drivers.
Each driver should poll on TCP connections connect on the
network supported by the driver; UDP polling should respond
with TX data only if the UDP packet is intended for the
the network supported by the driver.
+
(2) If there were multiple drivers, polling would occur at
double the rate. Fix by using bound IP address in TCP
connection (lipaddr) and verifying that it is in the subnet
served by the driver.
- Status: Open
+
+ Status: Open. Nothing will probably be done until I have a platform
+ with two network interfaces that I need to support.
Priority: Medium, The feature is not important, but it is important
for NuttX to resolve the architectural issues.
@@ -464,7 +539,7 @@ o Network (net/, drivers/net)
Description: sendto() and multiple network interface support:
When polled, would have to assure that the destination IP
is on the subnet served by the polling driver.
- Status: Open
+ Status: Open. This is really part of the above issue.
Priority: Medium, The feature is not important, but it is important
for NuttX to resolve the architectural issues.
@@ -472,7 +547,8 @@ o Network (net/, drivers/net)
Description: IPv6 support is incomplete. Adam Dunkels has recently announced
IPv6 support for uIP (currently only as part of Contiki). Those
changes need to be ported to NuttX.
- Status: Open
+ Status: Open. No work will probably be done until there is a specific
+ requirement for IPv6.
Priority: Medium
Title: LISTENING FOR UDP BROADCASTS
@@ -488,7 +564,7 @@ o Network (net/, drivers/net)
driver should be throttled. Perhaps the driver should disable
RX interrupts when throttled and re-anable on each poll time.
recvfrom would, of course, have to un-throttle.
- Status: Open
+ Status: Open. This is just a thought experiment. No changes are planned.
Priority: Medium
Title: STANDARDIZE ETHERNET DRIVER STATISTICS
@@ -637,6 +713,15 @@ o USB (drivers/usbdev, drivers/usbhost)
o Libraries (libc/)
^^^^^^^^^^^^^^^^^
+ Title: SIGNED time_t
+ Description: The NuttX time_t is type uint32_t. I think this is consistent
+ with all standards and with normal usage of time_t. However,
+ according to Wikipedia, time_t is usually implemented as a
+ signed 32-bit value.
+ Status: Open
+ Priority: Very low unless there is some compelling issue that I do not
+ know about.
+
Title: ENVIRON
Description: The definition of environ in stdlib.h is bogus and will not
work as it should. This is because the underlying
@@ -1002,20 +1087,6 @@ o Build system
Status: Open, there are some workarounds, but none are good.
Priority: High
- Title: configure.sh NOT AVAILABLE IN NATIVE WINDOWS BUILD
- Description: configure.sh is a Bash script and cannot be used from a Windows
- CMD.exe window. I started a configure.bat script, but I do
- not have the batch file programming skills to duplicate some
- of the more complex operations.
-
- I also considered adding a configure.c file that could be
- compiled and then executed by configure.bat (and configure.sh?).
- But I have not gone down that path yet.
-
- The current work-around is to configure under Cygwin.
- Status: Open
- Priority: High
-
o Linux/Cywgin simulation (arch/sim)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1370,7 +1441,7 @@ o ARM/STR71x (arch/arm/src/str71x/)
Status: Open
Priority: Medium -- Will be very high if you do SPI access from multiple threads.
-o ARM/LM3S6918 (arch/arm/src/lm3s/)
+o ARM/LM3S6918 (arch/arm/src/lm/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Title: I2C DRIVER
@@ -1460,6 +1531,11 @@ o ARM/STM32 (arch/arm/src/stm32/)
Status: Open
Priority: Low
+ Title: STM32 F4 USB OTG FS DEVICE-SIDE DRIVER
+ Description: This driver is reported to be buggy and to need some TLC.
+ Status: Open
+ Priority: High
+
o AVR (arch/avr)
^^^^^^^^^^^^^^
diff --git a/nuttx/arch/Kconfig b/nuttx/arch/Kconfig
index f19228143..d43137adb 100644
--- a/nuttx/arch/Kconfig
+++ b/nuttx/arch/Kconfig
@@ -16,6 +16,7 @@ config ARCH_8051
config ARCH_ARM
bool "ARM"
select ARCH_HAVE_INTERRUPTSTACK
+ select ARCH_HAVE_VFORK
---help---
The ARM architectures
@@ -108,6 +109,10 @@ config ARCH_NOINTC
bool
default n
+config ARCH_VECNOTIRQ
+ bool
+ default n
+
config ARCH_DMA
bool
default n
@@ -124,6 +129,10 @@ config ADDRENV
bool
default n
+config ARCH_HAVE_VFORK
+ bool
+ default n
+
config ARCH_STACKDUMP
bool "Dump stack on assertions"
default n
@@ -136,6 +145,20 @@ config ENDIAN_BIG
---help---
Select if architecture operates using big-endian byte ordering.
+config ARCH_HAVE_RAMFUNCS
+ bool
+ default n
+
+config ARCH_RAMFUNCS
+ bool "Copy functions to RAM on startup"
+ default n
+ depends on ARCH_HAVE_RAMFUNCS
+ ---help---
+ Copy some functions to RAM at boot time. This is done in some
+ architectures to improve performance. In other cases, it is done
+ so that FLASH can be reconfigured while the MCU executes out of
+ SRAM.
+
comment "Board Settings"
config BOARD_LOOPSPERMSEC
diff --git a/nuttx/arch/README.txt b/nuttx/arch/README.txt
index 67b99b255..14704aa76 100644
--- a/nuttx/arch/README.txt
+++ b/nuttx/arch/README.txt
@@ -170,12 +170,12 @@ arch/arm - ARM-based micro-controllers
STATUS: This port has stalled because of development tool issues. Coding
is complete on the basic port (timer, serial console, SPI).
- arch/arm/include/lm3s and arch/arm/src/lm3s
- These directories contain support for the Luminary LMS family, particularly
- for the LM3S6918. The initial, release of this port was included in NuttX version
- 0.4.6. The current port includes timer, serial console, Ethernet, SSI, and microSD
- support. There are working configurations the NuttX OS test, to run the NuttShell
- (NSH), the NuttX networking test, and the uIP web server.
+ arch/arm/include/lm and arch/arm/src/lm
+ These directories contain support for the Luminary LM3S/4F family. The
+ initial, release of this port was included in NuttX version 0.4.6. The
+ current port includes timer, serial console, Ethernet, SSI, and microSD
+ support. There are working configurations the NuttX OS test, to run the
+ NuttShell (NSH), the NuttX networking test, and the uIP web server.
arch/arm/include/lpc214x and arch/arm/src/lpc214x
These directories provide support for NXP LPC214x family of
diff --git a/nuttx/arch/arm/Kconfig b/nuttx/arch/arm/Kconfig
index 4fce8efbf..36343e319 100644
--- a/nuttx/arch/arm/Kconfig
+++ b/nuttx/arch/arm/Kconfig
@@ -47,12 +47,13 @@ config ARCH_CHIP_KINETIS
select ARCH_CORTEXM4
select ARCH_HAVE_MPU
select ARCH_IRQPRIO
+ select ARCH_HAVE_RAMFUNCS
+ select ARCH_RAMFUNCS
---help---
Freescale Kinetis Architectures (ARM Cortex-M4)
-config ARCH_CHIP_LM3S
+config ARCH_CHIP_LM
bool "TI Stellaris"
- select ARCH_CORTEXM3
select ARCH_HAVE_MPU
select ARCH_IRQPRIO
---help---
@@ -151,7 +152,7 @@ config ARCH_CHIP
default "dm320" if ARCH_CHIP_DM320
default "imx" if ARCH_CHIP_IMX
default "kinetis" if ARCH_CHIP_KINETIS
- default "lm3s" if ARCH_CHIP_LM3S
+ default "lm" if ARCH_CHIP_LM
default "lpc17xx" if ARCH_CHIP_LPC17XX
default "lpc214x" if ARCH_CHIP_LPC214X
default "lpc2378" if ARCH_CHIP_LPC2378
@@ -274,8 +275,8 @@ endif
if ARCH_CHIP_KINETIS
source arch/arm/src/kinetis/Kconfig
endif
-if ARCH_CHIP_LM3S
-source arch/arm/src/lm3s/Kconfig
+if ARCH_CHIP_LM
+source arch/arm/src/lm/Kconfig
endif
if ARCH_CHIP_LPC17XX
source arch/arm/src/lpc17xx/Kconfig
diff --git a/nuttx/arch/arm/src/armv7-m/Kconfig b/nuttx/arch/arm/src/armv7-m/Kconfig
index dc5aa3915..a154a4c5c 100644
--- a/nuttx/arch/arm/src/armv7-m/Kconfig
+++ b/nuttx/arch/arm/src/armv7-m/Kconfig
@@ -49,3 +49,11 @@ config ARMV7M_TOOLCHAIN_RAISONANCE
depends on HOST_WINDOWS
endchoice
+
+config ARMV7M_OABI_TOOLCHAIN
+ bool "OABI (vs EABI)"
+ default y
+ depends on ARMV7M_TOOLCHAIN_BUILDROOT
+ ---help---
+ Most of the older buildroot toolchains are OABI and are named arm-nuttx-elf- vs. arm-nuttx-eabi-
+
diff --git a/nuttx/arch/arm/src/armv7-m/Toolchain.defs b/nuttx/arch/arm/src/armv7-m/Toolchain.defs
index e214ce8bd..45ee9e36c 100644
--- a/nuttx/arch/arm/src/armv7-m/Toolchain.defs
+++ b/nuttx/arch/arm/src/armv7-m/Toolchain.defs
@@ -53,7 +53,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_BUILDROOT) \
- $(CONFIG_LM3S_BUILDROOT) \
+ $(CONFIG_LM_BUILDROOT) \
$(CONFIG_LPC17_BUILDROOT) \
$(CONFIG_LPC43_BUILDROOT) \
$(CONFIG_SAM3U_BUILDROOT) \
@@ -77,7 +77,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_CODESOURCERYL) \
- $(CONFIG_LM3S_CODESOURCERYL) \
+ $(CONFIG_LM_CODESOURCERYL) \
$(CONFIG_LPC17_CODESOURCERYL) \
$(CONFIG_LPC43_CODESOURCERYL) \
$(CONFIG_SAM3U_CODESOURCERYL) \
@@ -88,7 +88,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_CODESOURCERYW) \
- $(CONFIG_LM3S_CODESOURCERYW) \
+ $(CONFIG_LM_CODESOURCERYW) \
$(CONFIG_LPC17_CODESOURCERYW) \
$(CONFIG_LPC43_CODESOURCERYW) \
$(CONFIG_SAM3U_CODESOURCERYW) \
@@ -99,7 +99,7 @@ ifeq ($(filter y, \
endif
ifeq ($(filter y, \
$(CONFIG_KINETIS_DEVKITARM) \
- $(CONFIG_LM3S_DEVKITARM) \
+ $(CONFIG_LM_DEVKITARM) \
$(CONFIG_LPC17_DEVKITARM) \
$(CONFIG_LPC43_DEVKITARM) \
$(CONFIG_SAM3U_DEVKITARM) \
@@ -160,14 +160,15 @@ endif
# NuttX buildroot under Linux or Cygwin
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),BUILDROOT)
- # OABI
- # CROSSDEV = arm-nuttx-elf-
- # ARCROSSDEV = arm-nuttx-elf-
- # ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft
- # EABI
+ifeq ($(CONFIG_ARMV7M_OABI_TOOLCHAIN),y)
+ CROSSDEV = arm-nuttx-elf-
+ ARCROSSDEV = arm-nuttx-elf-
+ ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft
+else
CROSSDEV = arm-nuttx-eabi-
ARCROSSDEV = arm-nuttx-eabi-
ARCHCPUFLAGS = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft
+endif
MAXOPTIMIZATION = -Os
endif
diff --git a/nuttx/arch/arm/src/armv7-m/up_doirq.c b/nuttx/arch/arm/src/armv7-m/up_doirq.c
index 375054fba..6063f9ca1 100644
--- a/nuttx/arch/arm/src/armv7-m/up_doirq.c
+++ b/nuttx/arch/arm/src/armv7-m/up_doirq.c
@@ -79,9 +79,11 @@ uint32_t *up_doirq(int irq, uint32_t *regs)
uint32_t *savestate;
/* Nested interrupts are not supported in this implementation. If you want
- * implemented nested interrupts, you would have to (1) change the way that
- * current regs is handled and (2) the design associated with
- * CONFIG_ARCH_INTERRUPTSTACK.
+ * to implement nested interrupts, you would have to (1) change the way that
+ * current_regs is handled and (2) the design associated with
+ * CONFIG_ARCH_INTERRUPTSTACK. The savestate variable will not work for
+ * that purpose as implemented here because only the outermost nested
+ * interrupt can result in a context switch (it can probably be deleted).
*/
/* Current regs non-zero indicates that we are processing an interrupt;
diff --git a/nuttx/arch/arm/src/armv7-m/vfork.S b/nuttx/arch/arm/src/armv7-m/vfork.S
new file mode 100644
index 000000000..f36ff23aa
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/vfork.S
@@ -0,0 +1,142 @@
+/************************************************************************************
+ * arch/arm/src/armv7-m/vfork.S
+ *
+ * Copyright (C) 2013 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 "up_vfork.h"
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Symbols
+ ************************************************************************************/
+
+ .syntax unified
+ .thumb
+ .file "vfork.S"
+ .globl up_vfork
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: vfork
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the behavior is
+ * undefined if the process created by vfork() either modifies any data other than
+ * a variable of type pid_t used to store the return value from vfork(), or returns
+ * from the function in which vfork() was called, or calls any other function before
+ * successfully calling _exit() or one of the exec family of functions.
+ *
+ * This thin layer implements vfork by simply calling up_vfork() with the vfork()
+ * context as an argument. The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() collects context information and
+ * transfers control up up_vfork().
+ * 2) up_vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) up_vfork() provides any additional operating context. up_vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) up_vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * Input Paremeters:
+ * None
+ *
+ * Return:
+ * Upon successful completion, vfork() returns 0 to the child process and returns
+ * the process ID of the child process to the parent process. Otherwise, -1 is
+ * returned to the parent, no child process is created, and errno is set to
+ * indicate the error.
+ *
+ ************************************************************************************/
+
+ .thumb_func
+ .globl vfork
+ .type vfork, function
+vfork:
+ /* Create a stack frame */
+
+ mov r0, sp /* Save the value of the stack on entry */
+ sub sp, sp, #VFORK_SIZEOF /* Allocate the structure on the stack */
+
+ /* CPU registers */
+ /* Save the volatile registers */
+
+ str r4, [sp, #VFORK_R4_OFFSET]
+ str r5, [sp, #VFORK_R5_OFFSET]
+ str r6, [sp, #VFORK_R6_OFFSET]
+ str r7, [sp, #VFORK_R7_OFFSET]
+ str r8, [sp, #VFORK_R8_OFFSET]
+ str r9, [sp, #VFORK_R9_OFFSET]
+ str r10, [sp, #VFORK_R10_OFFSET]
+
+ /* Save the frame pointer, stack pointer, and return address */
+
+ str fp, [sp, #VFORK_FP_OFFSET]
+ str r0, [sp, #VFORK_SP_OFFSET]
+ str lr, [sp, #VFORK_LR_OFFSET]
+
+ /* Floating point registers (not yet) */
+
+ /* Then, call up_vfork(), passing it a pointer to the stack structure */
+
+ mov r0, sp
+ bl up_vfork
+
+ /* Release the stack data and return the value returned by up_vfork */
+
+ ldr lr, [sp, #VFORK_LR_OFFSET]
+ add sp, sp, #VFORK_SIZEOF
+ bx lr
+ .size vfork, .-vfork
+ .end
+
diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h
index 0d3c5b1f2..55071345f 100644
--- a/nuttx/arch/arm/src/common/up_internal.h
+++ b/nuttx/arch/arm/src/common/up_internal.h
@@ -188,7 +188,7 @@ extern uint32_t _ebss; /* End+1 of .bss */
* will create a function named foo that will execute from RAM.
*/
-#ifdef CONFIG_BOOT_RAMFUNCS
+#ifdef CONFIG_ARCH_RAMFUNCS
# define __ramfunc__ __attribute__ ((section(".ramfunc")))
@@ -204,7 +204,7 @@ extern const uint32_t _framfuncs; /* Copy source address in FLASH */
extern uint32_t _sramfuncs; /* Copy destination start address in RAM */
extern uint32_t _eramfuncs; /* Copy destination start address in RAM */
-#endif /* CONFIG_BOOT_RAMFUNCS */
+#endif /* CONFIG_ARCH_RAMFUNCS */
#endif /* __ASSEMBLY__ */
/****************************************************************************
diff --git a/nuttx/arch/arm/src/common/up_vfork.c b/nuttx/arch/arm/src/common/up_vfork.c
new file mode 100644
index 000000000..3b653e317
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_vfork.c
@@ -0,0 +1,233 @@
+/****************************************************************************
+ * arch/arm/src/common/up_vfork.c
+ *
+ * Copyright (C) 2013 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 <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "up_vfork.h"
+#include "os_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* ARM requires at least a 4-byte stack alignment. For use with EABI and
+ * floating point, the stack must be aligned to 8-byte addresses.
+ */
+
+#ifndef CONFIG_STACK_ALIGNMENT
+
+/* The symbol __ARM_EABI__ is defined by GCC if EABI is being used. If you
+ * are not using GCC, make sure that CONFIG_STACK_ALIGNMENT is set correctly!
+ */
+
+# ifdef __ARM_EABI__
+# define CONFIG_STACK_ALIGNMENT 8
+# else
+# define CONFIG_STACK_ALIGNMENT 4
+# endif
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_vfork
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the
+ * behavior is undefined if the process created by vfork() either modifies
+ * any data other than a variable of type pid_t used to store the return
+ * value from vfork(), or returns from the function in which vfork() was
+ * called, or calls any other function before successfully calling _exit()
+ * or one of the exec family of functions.
+ *
+ * The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() collects context information and
+ * transfers control up up_vfork().
+ * 2) up_vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) up_vfork() provides any additional operating context. up_vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) up_vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * task_vforkabort() may be called if an error occurs between steps 3 and 6.
+ *
+ * Input Paremeters:
+ * context - Caller context information saved by vfork()
+ *
+ * Return:
+ * Upon successful completion, vfork() returns 0 to the child process and
+ * returns the process ID of the child process to the parent process.
+ * Otherwise, -1 is returned to the parent, no child process is created,
+ * and errno is set to indicate the error.
+ *
+ ****************************************************************************/
+
+pid_t up_vfork(const struct vfork_s *context)
+{
+ _TCB *parent = (FAR _TCB *)g_readytorun.head;
+ _TCB *child;
+ size_t stacksize;
+ uint32_t newsp;
+ uint32_t newfp;
+ uint32_t stackutil;
+ int ret;
+
+ svdbg("r4:%08x r5:%08x r6:%08x r7:%08x\n",
+ context->r4, context->r5, context->r6, context->r7);
+ svdbg("r8:%08x r9:%08x r10:%08x\n",
+ context->r8, context->r9, context->r10);
+ svdbg("fp:%08x sp:%08x lr:%08x\n",
+ context->fp, context->sp, context->lr);
+
+ /* Allocate and initialize a TCB for the child task. */
+
+ child = task_vforksetup((start_t)(context->lr & ~1));
+ if (!child)
+ {
+ sdbg("task_vforksetup failed\n");
+ return (pid_t)ERROR;
+ }
+
+ svdbg("Parent=%p Child=%p\n", parent, child);
+
+ /* Get the size of the parent task's stack. Due to alignment operations,
+ * the adjusted stack size may be smaller than the stack size originally
+ * requrested.
+ */
+
+ stacksize = parent->adj_stack_size + CONFIG_STACK_ALIGNMENT - 1;
+
+ /* Allocate the stack for the TCB */
+
+ ret = up_create_stack(child, stacksize);
+ if (ret != OK)
+ {
+ sdbg("up_create_stack failed: %d\n", ret);
+ task_vforkabort(child, -ret);
+ return (pid_t)ERROR;
+ }
+
+ /* How much of the parent's stack was utilized? The ARM uses
+ * a push-down stack so that the current stack pointer should
+ * be lower than the initial, adjusted stack pointer. The
+ * stack usage should be the difference between those two.
+ */
+
+ DEBUGASSERT((uint32_t)parent->adj_stack_ptr > context->sp);
+ stackutil = (uint32_t)parent->adj_stack_ptr - context->sp;
+
+ svdbg("stacksize:%d stackutil:%d\n", stacksize, stackutil);
+
+ /* Make some feeble effort to perserve the stack contents. This is
+ * feeble because the stack surely contains invalid pointers and other
+ * content that will not work in the child context. However, if the
+ * user follows all of the caveats of vfor() usage, even this feeble
+ * effort is overkill.
+ */
+
+ newsp = (uint32_t)child->adj_stack_ptr - stackutil;
+ memcpy((void *)newsp, (const void *)context->sp, stackutil);
+
+ /* Was there a frame pointer in place before? */
+
+ if (context->fp <= (uint32_t)parent->adj_stack_ptr &&
+ context->fp >= (uint32_t)parent->adj_stack_ptr - stacksize)
+ {
+ uint32_t frameutil = (uint32_t)parent->adj_stack_ptr - context->fp;
+ newfp = (uint32_t)child->adj_stack_ptr - frameutil;
+ }
+ else
+ {
+ newfp = context->fp;
+ }
+
+ svdbg("Old stack base:%08x SP:%08x FP:%08x\n",
+ parent->adj_stack_ptr, context->sp, context->fp);
+ svdbg("New stack base:%08x SP:%08x FP:%08x\n",
+ child->adj_stack_ptr, newsp, newfp);
+
+ /* Update the stack pointer, frame pointer, and volatile registers. When
+ * the child TCB was initialized, all of the values were set to zero.
+ * up_initial_state() altered a few values, but the return value in R0
+ * should be cleared to zero, providing the indication to the newly started
+ * child thread.
+ */
+
+ child->xcp.regs[REG_R4] = context->r4; /* Volatile register r4 */
+ child->xcp.regs[REG_R5] = context->r5; /* Volatile register r5 */
+ child->xcp.regs[REG_R6] = context->r6; /* Volatile register r6 */
+ child->xcp.regs[REG_R7] = context->r7; /* Volatile register r7 */
+ child->xcp.regs[REG_R8] = context->r8; /* Volatile register r8 */
+ child->xcp.regs[REG_R9] = context->r9; /* Volatile register r9 */
+ child->xcp.regs[REG_R10] = context->r10; /* Volatile register r10 */
+ child->xcp.regs[REG_FP] = newfp; /* Frame pointer */
+ child->xcp.regs[REG_SP] = newsp; /* Stack pointer */
+
+ /* And, finally, start the child task. On a failure, task_vforkstart()
+ * will discard the TCB by calling task_vforkabort().
+ */
+
+ return task_vforkstart(child);
+}
diff --git a/nuttx/arch/arm/src/common/up_vfork.h b/nuttx/arch/arm/src/common/up_vfork.h
new file mode 100644
index 000000000..97edf9aaa
--- /dev/null
+++ b/nuttx/arch/arm/src/common/up_vfork.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * arch/arm/src/common/up_vfork.h
+ *
+ * Copyright (C) 2013 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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_ARM_VFORK_H
+#define __ARCH_ARM_SRC_ARM_VFORK_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define VFORK_R4_OFFSET (0*4) /* Volatile register r4 */
+#define VFORK_R5_OFFSET (1*4) /* Volatile register r5 */
+#define VFORK_R6_OFFSET (2*4) /* Volatile register r6 */
+#define VFORK_R7_OFFSET (3*4) /* Volatile register r7 */
+#define VFORK_R8_OFFSET (4*4) /* Volatile register r8 */
+#define VFORK_R9_OFFSET (5*4) /* Volatile register r9 */
+#define VFORK_R10_OFFSET (6*4) /* Volatile register r10 */
+
+#define VFORK_FP_OFFSET (7*4) /* Frame pointer */
+#define VFORK_SP_OFFSET (8*4) /* Stack pointer*/
+#define VFORK_LR_OFFSET (9*4) /* Return address*/
+
+#define VFORK_SIZEOF (10*4)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+struct vfork_s
+{
+ /* CPU registers */
+
+ uint32_t r4; /* Volatile register r4 */
+ uint32_t r5; /* Volatile register r5 */
+ uint32_t r6; /* Volatile register r6 */
+ uint32_t r7; /* Volatile register r7 */
+ uint32_t r8; /* Volatile register r8 */
+ uint32_t r9; /* Volatile register r9 */
+ uint32_t r10; /* Volatile register r10 */
+
+ uint32_t fp; /* Frame pointer */
+ uint32_t sp; /* Stack pointer*/
+ uint32_t lr; /* Return address*/
+
+ /* Floating point registers (not yet) */
+};
+#endif
+
+#endif /* __ARCH_ARM_SRC_ARM_VFORK_H */
diff --git a/nuttx/arch/arm/src/stm32/Make.defs b/nuttx/arch/arm/src/stm32/Make.defs
index baa751c7d..940ff6517 100644
--- a/nuttx/arch/arm/src/stm32/Make.defs
+++ b/nuttx/arch/arm/src/stm32/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# arch/arm/src/stm32/Make.defs
#
-# Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -39,15 +39,16 @@ else
HEAD_ASRC = stm32_vectors.S
endif
-CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S
+CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S \
+ vfork.S
CMN_CSRCS = up_assert.c up_blocktask.c up_copystate.c \
up_createstack.c up_mdelay.c up_udelay.c up_exit.c \
up_initialize.c up_initialstate.c up_interruptcontext.c \
up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \
up_releasepending.c up_releasestack.c up_reprioritizertr.c \
up_schedulesigaction.c up_sigdeliver.c up_systemreset.c \
- up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c up_svcall.c \
- up_stackcheck.c
+ up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c \
+ up_svcall.c up_stackcheck.c up_vfork.c
ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
CMN_ASRCS += up_exception.S
diff --git a/nuttx/arch/arm/src/stm32/stm32_flash.c b/nuttx/arch/arm/src/stm32/stm32_flash.c
index 83fcc6172..20b0cfe10 100644
--- a/nuttx/arch/arm/src/stm32/stm32_flash.c
+++ b/nuttx/arch/arm/src/stm32/stm32_flash.c
@@ -35,7 +35,7 @@
/* Provides standard flash access functions, to be used by the flash mtd driver.
* The interface is defined in the include/nuttx/progmem.h
- *
+ *
* Requirements during write/erase operations on FLASH:
* - HSI must be ON.
* - Low Power Modes are not permitted during write/erase
@@ -80,7 +80,7 @@ void stm32_flash_unlock(void)
if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
{
/* Unlock sequence */
-
+
putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
}
@@ -112,6 +112,11 @@ uint16_t up_progmem_pagesize(uint16_t page)
int up_progmem_getpage(uint32_t addr)
{
+ if (addr >= STM32_FLASH_BASE)
+ {
+ addr -= STM32_FLASH_BASE;
+ }
+
if (addr >= STM32_FLASH_SIZE)
{
return -EFAULT;
@@ -131,14 +136,14 @@ int up_progmem_erasepage(uint16_t page)
}
/* Get flash ready and begin erasing single page */
-
+
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
{
return -EPERM;
}
-
+
stm32_flash_unlock();
-
+
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER);
putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR);
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
@@ -146,10 +151,10 @@ int up_progmem_erasepage(uint16_t page)
while(getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste();
modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0);
-
+
/* Verify */
-
- for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
+
+ for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
count; count-=4, addr += 4)
{
if (getreg32(addr) != 0xffffffff)
@@ -173,8 +178,8 @@ int up_progmem_ispageerased(uint16_t page)
}
/* Verify */
-
- for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
+
+ for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE;
count; count--, addr++)
{
if (getreg8(addr) != 0xff)
@@ -200,6 +205,11 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count)
/* Check for valid address range */
+ if (addr >= STM32_FLASH_BASE)
+ {
+ addr -= STM32_FLASH_BASE;
+ }
+
if ((addr+count) >= STM32_FLASH_SIZE)
{
return -EFAULT;
@@ -213,10 +223,10 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count)
}
stm32_flash_unlock();
-
+
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
-
- for (addr += STM32_FLASH_BASE; count; count--, hword++, addr+=2)
+
+ for (addr += STM32_FLASH_BASE; count; count-=2, hword++, addr+=2)
{
/* Write half-word and wait to complete */
@@ -237,7 +247,6 @@ int up_progmem_write(uint32_t addr, const void *buf, size_t count)
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
return -EIO;
}
-
}
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c
index aa46a8987..bfb64b26a 100644
--- a/nuttx/arch/arm/src/stm32/stm32_serial.c
+++ b/nuttx/arch/arm/src/stm32/stm32_serial.c
@@ -79,22 +79,22 @@
#if SERIAL_HAVE_DMA
-/* Verify that DMA has been enabled an the DMA channel has been defined.
- * NOTE: These assignments may only be true for the F4.
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+/* Verify that DMA has been enabled and the DMA channel has been defined.
*/
-# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART6_RXDMA)
-# ifndef CONFIG_STM32_DMA2
-# error STM32 USART1/6 receive DMA requires CONFIG_STM32_DMA2
+# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART6_RXDMA)
+# ifndef CONFIG_STM32_DMA2
+# error STM32 USART1/6 receive DMA requires CONFIG_STM32_DMA2
+# endif
# endif
-# endif
-# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) || \
+# if defined(CONFIG_USART2_RXDMA) || defined(CONFIG_USART3_RXDMA) || \
defined(CONFIG_UART4_RXDMA) || defined(CONFIG_UART5_RXDMA)
-# ifndef CONFIG_STM32_DMA1
-# error STM32 USART2/3/4/5 receive DMA requires CONFIG_STM32_DMA1
+# ifndef CONFIG_STM32_DMA1
+# error STM32 USART2/3/4/5 receive DMA requires CONFIG_STM32_DMA1
+# endif
# endif
-# endif
/* Currently RS-485 support cannot be enabled when RXDMA is in use due to lack
* of testing - RS-485 support was developed on STM32F1x
@@ -114,28 +114,52 @@
* the following in the board.h file.
*/
-# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX)
-# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)"
-# endif
+# if defined(CONFIG_USART1_RXDMA) && !defined(DMAMAP_USART1_RX)
+# error "USART1 DMA channel not defined (DMAMAP_USART1_RX)"
+# endif
-# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX)
-# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)"
-# endif
+# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX)
+# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)"
+# endif
-# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX)
-# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)"
-# endif
+# if defined(CONFIG_USART3_RXDMA) && !defined(DMAMAP_USART3_RX)
+# error "USART3 DMA channel not defined (DMAMAP_USART3_RX)"
+# endif
-# if defined(CONFIG_UART4_RXDMA) && !defined(DMAMAP_UART4_RX)
-# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)"
-# endif
+# if defined(CONFIG_UART4_RXDMA) && !defined(DMAMAP_UART4_RX)
+# error "UART4 DMA channel not defined (DMAMAP_UART4_RX)"
+# endif
-# if defined(CONFIG_UART5_RXDMA) && !defined(DMAMAP_UART5_RX)
-# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)"
-# endif
+# if defined(CONFIG_UART5_RXDMA) && !defined(DMAMAP_UART5_RX)
+# error "UART5 DMA channel not defined (DMAMAP_UART5_RX)"
+# endif
+
+# if defined(CONFIG_USART6_RXDMA) && !defined(DMAMAP_USART6_RX)
+# error "USART6 DMA channel not defined (DMAMAP_USART6_RX)"
+# endif
+
+# elif defined(CONFIG_STM32_STM32F10XX)
+
+# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART2_RXDMA) || \
+ defined(CONFIG_USART3_RXDMA)
+# ifndef CONFIG_STM32_DMA1
+# error STM32 USART1/2/3 receive DMA requires CONFIG_STM32_DMA1
+# endif
+# endif
+
+# if defined(CONFIG_UART4_RXDMA)
+# ifndef CONFIG_STM32_DMA2
+# error STM32 USART4 receive DMA requires CONFIG_STM32_DMA2
+# endif
+# endif
+
+/* There are no optional DMA channel assignments for the F1 */
+
+# define DMAMAP_USART1_RX DMACHAN_USART1_RX
+# define DMAMAP_USART2_RX DMACHAN_USART2_RX
+# define DMAMAP_USART3_RX DMACHAN_USART3_RX
+# define DMAMAP_UART4_RX DMACHAN_USART4_RX
-# if defined(CONFIG_USART6_RXDMA) && !defined(DMAMAP_USART6_RX)
-# error "USART6 DMA channel not defined (DMAMAP_USART6_RX)"
# endif
/* The DMA buffer size when using RX DMA to emulate a FIFO.
@@ -169,6 +193,27 @@
# error "Unknown STM32 DMA"
# endif
+/* DMA control word */
+
+# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SERIAL_DMA_CONTROL_WORD \
+ (DMA_SCR_DIR_P2M | \
+ DMA_SCR_CIRC | \
+ DMA_SCR_MINC | \
+ DMA_SCR_PSIZE_8BITS | \
+ DMA_SCR_MSIZE_8BITS | \
+ CONFIG_USART_DMAPRIO | \
+ DMA_SCR_PBURST_SINGLE | \
+ DMA_SCR_MBURST_SINGLE)
+# else
+# define SERIAL_DMA_CONTROL_WORD \
+ (DMA_CCR_CIRC | \
+ DMA_CCR_MINC | \
+ DMA_CCR_PSIZE_8BITS | \
+ DMA_CCR_MSIZE_8BITS | \
+ CONFIG_USART_DMAPRIO)
+# endif
+
#endif
/* Power management definitions */
@@ -1115,14 +1160,7 @@ static int up_dma_setup(struct uart_dev_s *dev)
priv->usartbase + STM32_USART_DR_OFFSET,
(uint32_t)priv->rxfifo,
RXDMA_BUFFER_SIZE,
- DMA_SCR_DIR_P2M |
- DMA_SCR_CIRC |
- DMA_SCR_MINC |
- DMA_SCR_PSIZE_8BITS |
- DMA_SCR_MSIZE_8BITS |
- CONFIG_USART_DMAPRIO |
- DMA_SCR_PBURST_SINGLE |
- DMA_SCR_MBURST_SINGLE);
+ SERIAL_DMA_CONTROL_WORD);
/* Reset our DMA shadow pointer to match the address just
* programmed above.
diff --git a/nuttx/arch/arm/src/stm32/stm32_uart.h b/nuttx/arch/arm/src/stm32/stm32_uart.h
index 8ff6a9975..a26ea2009 100644
--- a/nuttx/arch/arm/src/stm32/stm32_uart.h
+++ b/nuttx/arch/arm/src/stm32/stm32_uart.h
@@ -140,12 +140,9 @@
# undef HAVE_CONSOLE
#endif
-/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX configuration.
- * Furthermore, DMA support is currently only implemented for the F4 (but could be
- * extended to the F1 and F2 with a little effort in the DMA code.
- */
+/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX configuration */
-#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA) || !defined(CONFIG_STM32_STM32F40XX)
+#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA)
# undef CONFIG_USART1_RXDMA
# undef CONFIG_USART2_RXDMA
# undef CONFIG_USART3_RXDMA
diff --git a/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
index 89b279bea..13324b8ac 100644
--- a/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
+++ b/nuttx/arch/arm/src/stm32/stm32f10xxx_dma.c
@@ -303,13 +303,13 @@ static int stm32_dmainterrupt(int irq, void *context)
}
dmach = &g_dma[chndx];
- /* Get the interrupt status (for this channel only) -- not currently used */
+ /* Get the interrupt status (for this channel only) */
isr = dmabase_getreg(dmach, STM32_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan);
- /* Disable the DMA channel */
+ /* Clear the interrupts we are handling */
- stm32_dmachandisable(dmach);
+ dmabase_putreg(dmach, STM32_DMA_IFCR_OFFSET, isr);
/* Invoke the callback */
@@ -528,14 +528,34 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
ccr = dmachan_getreg(dmach, STM32_DMACHAN_CCR_OFFSET);
ccr |= DMA_CCR_EN;
- /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
- * set and an interrupt is generated if the Half-Transfer Interrupt Enable
- * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
- * (TCIF) is set and an interrupt is generated if the Transfer Complete
- * Interrupt Enable bit (TCIE) is set.
+ /* In normal mode, interrupt at either half or full completion. In circular mode,
+ * always interrupt on buffer wrap, and optionally interrupt at the halfway point.
*/
- ccr |= (half ? (DMA_CCR_HTIE|DMA_CCR_TEIE) : (DMA_CCR_TCIE|DMA_CCR_TEIE));
+ if ((ccr & DMA_CCR_CIRC) == 0)
+ {
+ /* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
+ * set and an interrupt is generated if the Half-Transfer Interrupt Enable
+ * bit (HTIE) is set. At the end of the transfer, the Transfer Complete Flag
+ * (TCIF) is set and an interrupt is generated if the Transfer Complete
+ * Interrupt Enable bit (TCIE) is set.
+ */
+
+ ccr |= (half ? (DMA_CCR_HTIE|DMA_CCR_TEIE) : (DMA_CCR_TCIE|DMA_CCR_TEIE));
+
+ }
+ else
+ {
+ /* In nonstop mode, when the transfer completes it immediately resets
+ * and starts again. The transfer-complete interrupt is thus always
+ * enabled, and the half-complete interrupt can be used in circular
+ * mode to determine when the buffer is half-full, or in double-buffered
+ * mode to determine when one of the two buffers is full.
+ */
+
+ ccr |= (half ? DMA_CCR_HTIE : 0) | DMA_CCR_TCIE | DMA_CCR_TEIE;
+ }
+
dmachan_putreg(dmach, STM32_DMACHAN_CCR_OFFSET, ccr);
}
@@ -559,6 +579,24 @@ void stm32_dmastop(DMA_HANDLE handle)
}
/****************************************************************************
+ * Name: stm32_dmaresidual
+ *
+ * Description:
+ * Returns the number of bytes remaining to be transferred
+ *
+ * Assumptions:
+ * - DMA handle allocated by stm32_dmachannel()
+ *
+ ****************************************************************************/
+
+size_t stm32_dmaresidual(DMA_HANDLE handle)
+{
+ struct stm32_dma_s *dmach = (struct stm32_dma_s *)handle;
+
+ return dmachan_getreg(dmach, STM32_DMACHAN_CNDTR_OFFSET);
+}
+
+/****************************************************************************
* Name: stm32_dmasample
*
* Description:
diff --git a/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
index dcbbf1856..40fce8cb5 100644
--- a/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
+++ b/nuttx/arch/arm/src/stm32/stm32f40xxx_dma.c
@@ -94,7 +94,6 @@ struct stm32_dma_s
uint8_t irq; /* DMA stream IRQ number */
uint8_t shift; /* ISR/IFCR bit shift value */
uint8_t channel; /* DMA channel number (0-7) */
- bool nonstop; /* Stream is configured in a non-stopping mode. */
sem_t sem; /* Used to wait for DMA channel to become available */
uint32_t base; /* DMA register channel base address */
dma_callback_t callback; /* Callback invoked when the DMA completes */
@@ -728,7 +727,6 @@ void stm32_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
DMA_SCR_DBM|DMA_SCR_CIRC|
DMA_SCR_PBURST_MASK|DMA_SCR_MBURST_MASK);
regval |= scr;
- dmast->nonstop = (scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) != 0;
dmast_putreg(dmast, STM32_DMA_SCR_OFFSET, regval);
}
@@ -764,7 +762,12 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
scr = dmast_getreg(dmast, STM32_DMA_SCR_OFFSET);
scr |= DMA_SCR_EN;
- if (!dmast->nonstop)
+ /* In normal mode, interrupt at either half or full completion. In circular
+ * and double-buffered modes, always interrupt on buffer wrap, and optionally
+ * interrupt at the halfway point.
+ */
+
+ if ((scr & (DMA_SCR_DBM|DMA_SCR_CIRC)) == 0)
{
/* Once half of the bytes are transferred, the half-transfer flag (HTIF) is
* set and an interrupt is generated if the Half-Transfer Interrupt Enable
@@ -777,7 +780,7 @@ void stm32_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg, bool
}
else
{
- /* In nonstop mode, when the transfer completes it immediately resets
+ /* In non-stop modes, when the transfer completes it immediately resets
* and starts again. The transfer-complete interrupt is thus always
* enabled, and the half-complete interrupt can be used in circular
* mode to determine when the buffer is half-full, or in double-buffered
diff --git a/nuttx/binfmt/Kconfig b/nuttx/binfmt/Kconfig
index 495bd050f..8d6c0bb18 100644
--- a/nuttx/binfmt/Kconfig
+++ b/nuttx/binfmt/Kconfig
@@ -49,6 +49,20 @@ if ELF
source binfmt/libelf/Kconfig
endif
+config BUILTIN
+ bool "Support Builtin Applications"
+ default n
+ ---help---
+ Enable support for builtin applications. This features assigns a string
+ name to an application and in addition if FS_BINFS is defined, retaining
+ those names in a file system from which they can be executed. This feature
+ is also the underlying requirement to support built-in applications in the
+ NuttShell (NSH).
+
+if BUILTIN
+source binfmt/libbuiltin/Kconfig
+endif
+
endif
config PIC
diff --git a/nuttx/binfmt/Makefile b/nuttx/binfmt/Makefile
index 8ec0d877c..49dcd3d32 100644
--- a/nuttx/binfmt/Makefile
+++ b/nuttx/binfmt/Makefile
@@ -1,7 +1,7 @@
############################################################################
# nxflat/Makefile
#
-# Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -65,6 +65,7 @@ DEPPATH = --dep-path .
include libnxflat$(DELIM)Make.defs
include libelf$(DELIM)Make.defs
+include libbuiltin$(DELIM)Make.defs
BINFMT_AOBJS = $(BINFMT_ASRCS:.S=$(OBJEXT))
BINFMT_COBJS = $(BINFMT_CSRCS:.c=$(OBJEXT))
diff --git a/nuttx/binfmt/binfmt_exec.c b/nuttx/binfmt/binfmt_exec.c
index 60e8d8efd..d878c8cc5 100644
--- a/nuttx/binfmt/binfmt_exec.c
+++ b/nuttx/binfmt/binfmt_exec.c
@@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_exec.c
*
- * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,6 @@
#include <nuttx/config.h>
#include <string.h>
-#include <sched.h>
#include <debug.h>
#include <errno.h>
@@ -96,6 +95,8 @@ int exec(FAR const char *filename, FAR const char **argv,
struct binary_s bin;
int ret;
+ /* Load the module into memory */
+
memset(&bin, 0, sizeof(struct binary_s));
bin.filename = filename;
bin.exports = exports;
@@ -108,7 +109,9 @@ int exec(FAR const char *filename, FAR const char **argv,
return ERROR;
}
- ret = exec_module(&bin, 50);
+ /* Then start the module */
+
+ ret = exec_module(&bin);
if (ret < 0)
{
bdbg("ERROR: Failed to execute program '%s'\n", filename);
diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c
index 400451c40..afa445abb 100644
--- a/nuttx/binfmt/binfmt_execmodule.c
+++ b/nuttx/binfmt/binfmt_execmodule.c
@@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_execmodule.c
*
- * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
#include <errno.h>
#include <nuttx/arch.h>
+#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/binfmt.h>
#include "os_internal.h"
@@ -143,7 +144,7 @@ static inline int exec_ctors(FAR const struct binary_s *binp)
*
****************************************************************************/
-int exec_module(FAR const struct binary_s *binp, int priority)
+int exec_module(FAR const struct binary_s *binp)
{
FAR _TCB *tcb;
#ifndef CONFIG_CUSTOM_STACK
@@ -167,7 +168,7 @@ int exec_module(FAR const struct binary_s *binp, int priority)
/* Allocate a TCB for the new task. */
- tcb = (FAR _TCB*)zalloc(sizeof(_TCB));
+ tcb = (FAR _TCB*)kzalloc(sizeof(_TCB));
if (!tcb)
{
err = ENOMEM;
@@ -177,7 +178,7 @@ int exec_module(FAR const struct binary_s *binp, int priority)
/* Allocate the stack for the new task */
#ifndef CONFIG_CUSTOM_STACK
- stack = (FAR uint32_t*)malloc(binp->stacksize);
+ stack = (FAR uint32_t*)kmalloc(binp->stacksize);
if (!tcb)
{
err = ENOMEM;
@@ -186,12 +187,12 @@ int exec_module(FAR const struct binary_s *binp, int priority)
/* Initialize the task */
- ret = task_init(tcb, binp->filename, priority, stack,
+ ret = task_init(tcb, binp->filename, binp->priority, stack,
binp->stacksize, binp->entrypt, binp->argv);
#else
/* Initialize the task */
- ret = task_init(tcb, binp->filename, priority, stack,
+ ret = task_init(tcb, binp->filename, binp->priority, stack,
binp->entrypt, binp->argv);
#endif
if (ret < 0)
@@ -201,6 +202,9 @@ int exec_module(FAR const struct binary_s *binp, int priority)
goto errout_with_stack;
}
+ /* Note that tcb->flags are not modified. 0=normal task */
+ /* tcb->flags |= TCB_FLAG_TTYPE_TASK; */
+
/* Add the D-Space address as the PIC base address. By convention, this
* must be the first allocated address space.
*/
@@ -257,14 +261,14 @@ errout_with_stack:
#ifndef CONFIG_CUSTOM_STACK
tcb->stack_alloc_ptr = NULL;
sched_releasetcb(tcb);
- free(stack);
+ kfree(stack);
#else
sched_releasetcb(tcb);
#endif
goto errout;
errout_with_tcb:
- free(tcb);
+ kfree(tcb);
errout:
errno = err;
bdbg("returning errno: %d\n", err);
diff --git a/nuttx/binfmt/binfmt_loadmodule.c b/nuttx/binfmt/binfmt_loadmodule.c
index 112a6b35b..4f3dc6952 100644
--- a/nuttx/binfmt/binfmt_loadmodule.c
+++ b/nuttx/binfmt/binfmt_loadmodule.c
@@ -67,6 +67,39 @@
****************************************************************************/
/****************************************************************************
+ * Name: load_default_priority
+ *
+ * Description:
+ * Set the default priority of the module to be loaded. This may be
+ * changed (1) by the actions of the binary format's load() method if
+ * the binary format contains priority informaition, or (2) by the user
+ * between calls to load_module() and exec_module().
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success; Otherwise, -1 (ERROR) is returned and
+ * the errno variable is set appropriately.
+ *
+ ****************************************************************************/
+
+static int load_default_priority(FAR struct binary_s *bin)
+{
+ struct sched_param param;
+
+ /* Get the priority of this thread */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ bdbg("ERROR: sched_getparam failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Save that as the priority of child thread */
+
+ bin->priority = param.sched_priority;
+}
+
+/****************************************************************************
* Name: load_absmodule
*
* Description:
@@ -145,6 +178,16 @@ int load_module(FAR struct binary_s *bin)
if (bin && bin->filename)
#endif
{
+ /* Set the default priority of the new program. */
+
+ ret = load_default_priority(bin)
+ if (ret < 0)
+ {
+ /* The errno is already set in this case */
+
+ return ERROR;
+ }
+
/* Were we given a relative path? Or an absolute path to the file to
* be loaded? Absolute paths start with '/'.
*/
diff --git a/nuttx/binfmt/builtin.c b/nuttx/binfmt/builtin.c
new file mode 100644
index 000000000..d36cb6326
--- /dev/null
+++ b/nuttx/binfmt/builtin.c
@@ -0,0 +1,196 @@
+/****************************************************************************
+ * binfmt/builtin.c
+ *
+ * Copyright (C) 2012 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/types.h>
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/binfmt/binfmt.h>
+#include <nuttx/binfmt/builtin.h>
+
+#ifdef CONFIG_BUILTIN
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int builtin_loadbinary(FAR struct binary_s *binp);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct binfmt_s g_builtin_binfmt =
+{
+ NULL, /* next */
+ builtin_loadbinary, /* load */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_loadbinary
+ *
+ * Description:
+ * Verify that the file is an builtin binary.
+ *
+ ****************************************************************************/
+
+static int builtin_loadbinary(struct binary_s *binp)
+{
+ FAR const char *filename;
+ int fd;
+ int index;
+ int ret;
+
+ bvdbg("Loading file: %s\n", binp->filename);
+
+ /* Open the binary file for reading (only) */
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ int errval = errno;
+ bdbg("ERROR: Failed to open binary %s: %d\n", filename, errval);
+ return -errval;
+ }
+
+ /* If this file is a BINFS file system, then we can recover the name of
+ * the file using the FIOC_FILENAME ioctl() call.
+ */
+
+ ret = ioctl(fd, FIOC_FILENAME, (unsigned long)((uintptr_t)&filename));
+ if (ret < 0)
+ {
+ int errval = errno;
+ bdbg("ERROR: FIOC_FILENAME ioctl failed: %d\n", errval);
+ return -errval;
+ }
+
+ /* Other file systems may also support FIOC_FILENAME, so the real proof
+ * is that we can look up the index to this name in g_builtins[].
+ */
+
+ index = builtin_isavail(filename);
+ if (index < 0)
+ {
+ int errval = errno;
+ bdbg("ERROR: %s is not a builtin application\n", filename);
+ return -errval;
+
+ }
+
+ /* Return the load information. NOTE: that there is no way to configure
+ * the priority. That is a bug and needs to be fixed.
+ */
+
+ binp->entrypt = g_builtins[index].main;
+ binp->stacksize = g_builtins[index].stacksize;
+ binp->priority = g_builtins[index].priority;
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_initialize
+ *
+ * Description:
+ * Builtin support is built unconditionally. However, it order to
+ * use this binary format, this function must be called during system
+ * format in order to register the builtin binary format.
+ *
+ * Returned Value:
+ * This is a NuttX internal function so it follows the convention that
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int builtin_initialize(void)
+{
+ int ret;
+
+ /* Register ourselves as a binfmt loader */
+
+ bvdbg("Registering Builtin Loader\n");
+
+ ret = register_binfmt(&g_builtin_binfmt);
+ if (ret != 0)
+ {
+ bdbg("Failed to register binfmt: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: builtin_uninitialize
+ *
+ * Description:
+ * Unregister the builtin binary loader
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void builtin_uninitialize(void)
+{
+ unregister_binfmt(&g_builtin_binfmt);
+}
+
+#endif /* CONFIG_BUILTIN */
+
diff --git a/nuttx/binfmt/elf.c b/nuttx/binfmt/elf.c
index bcebf13ca..9dc59fbdd 100644
--- a/nuttx/binfmt/elf.c
+++ b/nuttx/binfmt/elf.c
@@ -183,7 +183,7 @@ static int elf_loadbinary(struct binary_s *binp)
bvdbg("Loading file: %s\n", binp->filename);
- /* Initialize the xflat library to load the program binary. */
+ /* Initialize the ELF library to load the program binary. */
ret = elf_init(binp->filename, &loadinfo);
elf_dumploadinfo(&loadinfo);
diff --git a/nuttx/binfmt/libbuiltin/Kconfig b/nuttx/binfmt/libbuiltin/Kconfig
new file mode 100644
index 000000000..ae2bf3130
--- /dev/null
+++ b/nuttx/binfmt/libbuiltin/Kconfig
@@ -0,0 +1,4 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
diff --git a/nuttx/binfmt/libbuiltin/Make.defs b/nuttx/binfmt/libbuiltin/Make.defs
new file mode 100644
index 000000000..5eec1acde
--- /dev/null
+++ b/nuttx/binfmt/libbuiltin/Make.defs
@@ -0,0 +1,52 @@
+############################################################################
+# binfmt/libbuiltin/Make.defs
+#
+# Copyright (C) 2013 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.
+#
+############################################################################
+
+ifeq ($(CONFIG_BUILTIN),y)
+
+# Builtin application interfaces
+
+BINFMT_CSRCS += builtin.c
+
+# Builtin library interfaces
+
+BINFMT_CSRCS += libbuiltin_getname.c libbuiltin_isavail.c
+
+# Hook the libbuiltin subdirectory into the build
+
+VPATH += libbuiltin
+SUBDIRS += libbuiltin
+DEPPATH += --dep-path libbuiltin
+
+endif
diff --git a/nuttx/binfmt/libbuiltin/libbuiltin_getname.c b/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
new file mode 100644
index 000000000..01ac024f7
--- /dev/null
+++ b/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * binfmt/libbuiltin/libbuiltin_getname.c
+ *
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 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 <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: builtin_getname
+ *
+ * Description:
+ * Return the name of the application at index in the table of builtin
+ * applications.
+ *
+ ****************************************************************************/
+
+FAR const char *builtin_getname(int index)
+{
+ if (index < 0 || index >= number_builtins())
+ {
+ return NULL;
+ }
+
+ return g_builtins[index].name;
+}
diff --git a/apps/namedapp/exec_namedapp.c b/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
index 264fca7b9..f99a4b81d 100644
--- a/apps/namedapp/exec_namedapp.c
+++ b/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
@@ -1,13 +1,15 @@
/****************************************************************************
- * apps/namedaps/exec_namedapp.c
+ * binfmt/libbuiltin/libbuiltin_isavail.c
+ *
+ * Originally by:
*
* Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
- * With updates, modifications, and general maintenance by:
+ * With subsequent updates, modifications, and general maintenance by:
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
- * Auther: Gregory Nutt <gnutt@nuttx.org>
+ * Copyright (C) 2012-2013 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
@@ -43,13 +45,16 @@
****************************************************************************/
#include <nuttx/config.h>
-#include <apps/apps.h>
-#include <sched.h>
#include <string.h>
+#include <limits.h>
#include <errno.h>
-#include "namedapp.h"
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
/****************************************************************************
* Private Types
@@ -72,26 +77,7 @@
****************************************************************************/
/****************************************************************************
- * Name: namedapp_getname
- *
- * Description:
- * Return the name of the application at index in the table of named
- * applications.
- *
- ****************************************************************************/
-
-const char *namedapp_getname(int index)
-{
- if (index < 0 || index >= number_namedapps())
- {
- return NULL;
- }
-
- return namedapps[index].name;
-}
-
-/****************************************************************************
- * Name: namedapp_isavail
+ * Name: builtin_isavail
*
* Description:
* Return the index into the table of applications for the applicaiton with
@@ -99,13 +85,13 @@ const char *namedapp_getname(int index)
*
****************************************************************************/
-int namedapp_isavail(FAR const char *appname)
+int builtin_isavail(FAR const char *appname)
{
int i;
-
- for (i = 0; namedapps[i].name; i++)
+
+ for (i = 0; g_builtins[i].name; i++)
{
- if (!strcmp(namedapps[i].name, appname))
+ if (!strncmp(g_builtins[i].name, appname, NAME_MAX))
{
return i;
}
@@ -114,74 +100,3 @@ int namedapp_isavail(FAR const char *appname)
set_errno(ENOENT);
return ERROR;
}
-
-/****************************************************************************
- * Name: namedapp_isavail
- *
- * Description:
- * Execute the application with name 'appname', providing the arguments
- * in the argv[] array.
- *
- * Returned Value:
- * On success, the task ID of the named application is returned. On
- * failure, -1 (ERROR) is returned an the errno value is set appropriately.
- *
- ****************************************************************************/
-
-int exec_namedapp(FAR const char *appname, FAR const char **argv)
-{
- pid_t pid;
- int index;
-
- /* Verify that an application with this name exists */
-
- index = namedapp_isavail(appname);
- if (index >= 0)
- {
- /* Disable pre-emption. This means that although we start the named
- * application here, it will not actually run until pre-emption is
- * re-enabled below.
- */
-
- sched_lock();
-
- /* Start the named application task */
-
- pid = TASK_CREATE(namedapps[index].name, namedapps[index].priority,
- namedapps[index].stacksize, namedapps[index].main,
- (argv) ? &argv[1] : (const char **)NULL);
-
- /* If robin robin scheduling is enabled, then set the scheduling policy
- * of the new task to SCHED_RR before it has a chance to run.
- */
-
-#if CONFIG_RR_INTERVAL > 0
- if (pid > 0)
- {
- struct sched_param param;
-
- /* Pre-emption is disabled so the task creation and the
- * following operation will be atomic. The priority of the
- * new task cannot yet have changed from its initial value.
- */
-
- param.sched_priority = namedapps[index].priority;
- sched_setscheduler(pid, SCHED_RR, &param);
- }
-#endif
- /* Now let the named application run */
-
- sched_unlock();
-
- /* Return the task ID of the new task if the task was sucessfully
- * started. Otherwise, pid will be ERROR (and the errno value will
- * be set appropriately).
- */
-
- return pid;
- }
-
- /* Return ERROR with errno set appropriately */
-
- return ERROR;
-}
diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt
index 21aace2af..babdf7330 100644
--- a/nuttx/configs/README.txt
+++ b/nuttx/configs/README.txt
@@ -334,6 +334,12 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_TASK_NAME_SIZE - Specifies that maximum size of a
task name to save in the TCB. Useful if scheduler
instrumentation is selected. Set to zero to disable.
+ CONFIG_SCHED_HAVE_PARENT - Remember the ID of the parent thread
+ when a new child thread is created. This support enables some
+ additional features (such as SIGCHLD) and modifies the behavior
+ of other interfaces. For example, it makes waitpid() more
+ standards complete by restricting the waited-for tasks to the
+ children of the caller. Default: disabled.
CONFIG_START_YEAR, CONFIG_START_MONTH, CONFIG_START_DAY -
Used to initialize the internal time logic.
CONFIG_GREGORIAN_TIME - Enables Gregorian time conversions.
@@ -400,7 +406,7 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
- the worker thread. Default: 4
+ the worker thread. Default: 17
CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
work queue is created by default. If CONFIG_SCHED_LPWORK is also defined
then an additional, lower-priority work queue will also be created. This
@@ -412,7 +418,12 @@ defconfig -- This is a configuration file similar to the Linux
checks for work in units of microseconds. Default: 50*1000 (50 MS).
CONFIG_SCHED_LPWORKSTACKSIZE - The stack size allocated for the lower
priority worker thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
- CONFIG_SCHED_WAITPID - Enables the waitpid() API
+ CONFIG_SCHED_WAITPID - Enables the waitpid() interface in a default,
+ non-standard mode (non-standard in the sense that the waited for
+ PID need not be child of the caller). If SCHED_HAVE_PARENT is
+ also defined, then this setting will modify the behavior or
+ waitpid() (making more spec compliant) and will enable the
+ waitid() and wait() interfaces as well.
CONFIG_SCHED_ATEXIT - Enables the atexit() API
CONFIG_SCHED_ATEXIT_MAX - By default if CONFIG_SCHED_ATEXIT is
selected, only a single atexit() function is supported. That number
@@ -426,6 +437,23 @@ defconfig -- This is a configuration file similar to the Linux
where 'app' is the application name. If not defined, CONFIG_USER_ENTRYPOINT
defaults to user_start.
+ Signal Numbers:
+
+ CONFIG_SIG_SIGUSR1 - Value of standard user signal 1 (SIGUSR1).
+ Default: 1
+ CONFIG_SIG_SIGUSR2 - Value of standard user signal 2 (SIGUSR2).
+ Default: 2
+ CONFIG_SIG_SIGALARM - Default the standard signal used with POSIX
+ timers (SIGALRM). Default: 3
+ CONFIG_SIG_SIGCHLD - The SIGCHLD signal is sent to the parent of a child
+ process when it exits, is interrupted (stopped), or resumes after being
+ interrupted. Default: 4
+
+ CONFIG_SIG_SIGCONDTIMEDOUT - This non-standard signal number is used in
+ the implementation of pthread_cond_timedwait(). Default 16.
+ CONFIG_SIG_SIGWORK - SIGWORK is a non-standard signal used to wake up
+ the internal NuttX worker thread. Default: 17.
+
Binary Loaders:
CONFIG_BINFMT_DISABLE - By default, support for loadable binary formats
is built.
@@ -1562,7 +1590,7 @@ defconfig -- This is a configuration file similar to the Linux
operation from FLASH but must copy initialized .data sections to RAM.
CONFIG_BOOT_COPYTORAM - Some configurations boot in FLASH
but copy themselves entirely into RAM for better performance.
- CONFIG_BOOT_RAMFUNCS - Other configurations may copy just some functions
+ CONFIG_ARCH_RAMFUNCS - Other configurations may copy just some functions
into RAM, either for better performance or for errata workarounds.
CONFIG_STACK_ALIGNMENT - Set if the your application has specific
stack alignment requirements (may not be supported
@@ -1936,6 +1964,11 @@ configs/z8f64200100kit
development kit, Z8F6423 part, and the Zilog ZDS-II Windows command line
tools. The development environment is Cygwin under WinXP.
+configs/zp214xpa
+ This port is for the NXP LPC2148 as provided on the The0.net
+ ZPA213X/4XPA development board. Includes support for the
+ UG-2864AMBAG01 OLED also from The0.net
+
Configuring NuttX
^^^^^^^^^^^^^^^^^
@@ -1955,16 +1988,24 @@ tools/configure.sh
There is a script that automates these steps. The following steps will
accomplish the same configuration:
- cd tools
- ./configure.sh <board-name>/<config-dir>
+ cd tools
+ ./configure.sh <board-name>/<config-dir>
+
+ There is an alternative Windows batch file that can be used in the
+ windows native enironment like:
+
+ cd ${TOPDIR}\tools
+ configure.bat <board-name>\<config-dir>
+
+ See tools/README.txt for more information about these scripts.
-And if configs/<board-name>/<config-dir>/appconfig exists and your
-application directory is not in the standard loction (../apps), then
-you should also specify the location of the application directory on the
-command line like:
+ And if configs/<board-name>/<config-dir>/appconfig exists and your
+ application directory is not in the standard loction (../apps), then
+ you should also specify the location of the application directory on the
+ command line like:
- cd tools
- ./configure.sh -a <app-dir> <board-name>/<config-dir>
+ cd tools
+ ./configure.sh -a <app-dir> <board-name>/<config-dir>
Building Symbol Tables
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/drivers/Kconfig b/nuttx/drivers/Kconfig
index 8302d21b7..3ced01b58 100644
--- a/nuttx/drivers/Kconfig
+++ b/nuttx/drivers/Kconfig
@@ -140,7 +140,8 @@ menuconfig SPI
bool "SPI Driver Support"
default n
---help---
- This selection enables building of the "upper-half" SPI driver.
+ This selection enables selection of common SPI options. This option
+ should be enabled by all platforms that support SPI interfaces.
See include/nuttx/spi.h for further SPI driver information.
if SPI
diff --git a/nuttx/drivers/input/Kconfig b/nuttx/drivers/input/Kconfig
index 1f345ee14..6da3a9f39 100644
--- a/nuttx/drivers/input/Kconfig
+++ b/nuttx/drivers/input/Kconfig
@@ -123,6 +123,25 @@ config STMPE811_I2C
endchoice
+config STMPE811_ACTIVELOW
+ bool "Active Low Interrupt"
+ default n
+ ---help---
+ The STMPE811 interrupt is provided by a discrete input (usually a
+ GPIO interrupt on most MCU architectures). This setting determines
+ whether the interrupt is active high (or rising edge triggered) or
+ active low (or falling edge triggered). Default: Active
+ high/rising edge.
+
+config STMPE811_EDGE
+ bool "Edge triggered Interrupt"
+ default n
+ ---help---
+ The STMPE811 interrupt is provided by a discrete input (usually a
+ GPIO interrupt on most MCU architectures). This setting determines
+ whether the interrupt is edge or level triggered. Default: Level
+ triggered.
+
config STMPE811_MULTIPLE
bool "Multiple STMPE811 Devices"
default n
diff --git a/nuttx/drivers/lcd/Make.defs b/nuttx/drivers/lcd/Make.defs
index 1b445b6a7..067f76f4e 100644
--- a/nuttx/drivers/lcd/Make.defs
+++ b/nuttx/drivers/lcd/Make.defs
@@ -51,6 +51,10 @@ ifeq ($(CONFIG_LCD_UG2864AMBAG01),y)
CSRCS += ug-2864ambag01.c
endif
+ifeq ($(CONFIG_LCD_UG2864HSWEG01),y)
+ CSRCS += ug-2864hsweg01.c
+endif
+
ifeq ($(CONFIG_LCD_UG9664HSWAG01),y)
CSRCS += ug-9664hswag01.c
endif
diff --git a/nuttx/drivers/lcd/ug-2864ambag01.c b/nuttx/drivers/lcd/ug-2864ambag01.c
index 2a47b38eb..6b3d6d5a8 100644
--- a/nuttx/drivers/lcd/ug-2864ambag01.c
+++ b/nuttx/drivers/lcd/ug-2864ambag01.c
@@ -428,7 +428,7 @@ static inline void ug2864ambag01_configspi(FAR struct spi_dev_s *spi)
SPI_SETMODE(spi, CONFIG_UG2864AMBAG01_SPIMODE);
SPI_SETBITS(spi, 8);
- SPI_SETFREQUENCY(spi, CONFIG_UG2864AMBAG01_FREQUENCY)
+ SPI_SETFREQUENCY(spi, CONFIG_UG2864AMBAG01_FREQUENCY);
}
#endif
@@ -1035,7 +1035,7 @@ FAR struct lcd_dev_s *ug2864ambag01_initialize(FAR struct spi_dev_s *spi, unsign
/* Configure the SPI */
- ug2864ambag01_configspi(spi)
+ ug2864ambag01_configspi(spi);
/* Lock and select device */
@@ -1148,8 +1148,8 @@ void ug2864ambag01_fill(FAR struct lcd_dev_s *dev, uint8_t color)
/* Transfer one page of the selected color */
- (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG2864AMBAG01_XRES],
- UG2864AMBAG01_XRES);
+ (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG2864AMBAG01_XRES],
+ UG2864AMBAG01_XRES);
}
/* De-select and unlock the device */
diff --git a/nuttx/drivers/lcd/ug-2864hsweg01.c b/nuttx/drivers/lcd/ug-2864hsweg01.c
new file mode 100644
index 000000000..02a59b104
--- /dev/null
+++ b/nuttx/drivers/lcd/ug-2864hsweg01.c
@@ -0,0 +1,1218 @@
+/**************************************************************************************
+ * drivers/lcd/ug-2864hsweg01.c
+ * Driver for Univision UG-2864HSWEG01 OLED display (wih SSD1306 controller) in SPI
+ * mode
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * References:
+ * 1. Product Specification (Preliminary), Part Name: OEL Display Module, Part ID:
+ * UG-2864HSWEG01, Doc No: SAS1-9046-B, Univision Technology Inc.
+ * 2. SSD1306, 128 X 64 Dot Matrix OLED/PLED, Preliminary Segment/Common Driver with
+ * Controller, Solomon Systech
+ *
+ * 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.
+ *
+ **************************************************************************************/
+/**************************************************************************************
+ * Device memory organization:
+ *
+ * +----------------------------+
+ * | Column |
+ * --------+----+---+---+---+-...-+-----+
+ * Page | 0 | 1 | 2 | 3 | ... | 127 |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 0 | D0 | X | | | | |
+ * | D1 | X | | | | |
+ * | D2 | X | | | | |
+ * | D3 | X | | | | |
+ * | D4 | X | | | | |
+ * | D5 | X | | | | |
+ * | D6 | X | | | | |
+ * | D7 | X | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 1 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 2 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 3 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 4 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 5 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 6 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ * Page 7 | | | | | | |
+ * --------+----+---+---+---+-...-+-----+
+ *
+ * -----------------------------------+---------------------------------------
+ * Landscape Display: | Reverse Landscape Display:
+ * --------+-----------------------+ | --------+---------------------------+
+ * | Column | | | Column |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 0 | 0 | 1 | 2 | | 127 | | Page 7 | 127 | 126 | 125 | | 0 |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 1 | V | | Page 6 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 2 | V | | Page 5 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 3 | V | | Page 4 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 4 | V | | Page 3 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 5 | V | | Page 2 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 6 | V | | Page 1 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * Page 7 | V | | Page 0 | ^ |
+ * --------+---+---+---+-...-+-----+ | --------+-----+-----+-----+-...-+---+
+ * -----------------------------------+---------------------------------------
+ *
+ * -----------------------------------+---------------------------------------
+ * Portrait Display: | Reverse Portrait Display:
+ * -----------+---------------------+ | -----------+---------------------+
+ * | Page | | | Page |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 0 | 0 | 1 | 2 | | 7 | | Column 127 | 7 | 6 | 5 | | 0 |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 1 | > > > > > | | Column 126 | |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 2 | | | Column 125 | |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * ... | | | ... | |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * Column 127 | | | Column 0 | < < < < < |
+ * -----------+---+---+---+-...-+---+ | -----------+---+---+---+-...-+---+
+ * -----------------------------------+----------------------------------------
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Included Files
+ **************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/spi.h>
+#include <nuttx/lcd/lcd.h>
+#include <nuttx/lcd/ug-2864hsweg01.h>
+
+#include <arch/irq.h>
+
+#ifdef CONFIG_LCD_UG2864HSWEG01
+
+/**************************************************************************************
+ * Pre-processor Definitions
+ **************************************************************************************/
+/* Configuration **********************************************************************/
+/* Limitations of the current configuration that I hope to fix someday */
+
+#if CONFIG_UG2864HSWEG01_NINTERFACES != 1
+# warning "This implementation supports only a single OLED device"
+# undef CONFIG_UG2864HSWEG01_NINTERFACES
+# define CONFIG_UG2864HSWEG01_NINTERFACES 1
+#endif
+
+#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT)
+# warning "No support yet for portrait modes"
+# define CONFIG_LCD_LANDSCAPE 1
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RLANDSCAPE
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_RLANDSCAPE)
+# warning "Reverse landscape mode is untested and, hence, probably buggy"
+#endif
+
+/* SSD1306 Commands *******************************************************************/
+
+#define SSD1306_SETCOLL(ad) (0x00 | ((ad) & 0x0f)) /* Set Lower Column Address: (00h - 0fh) */
+#define SSD1306_SETCOLH(ad) (0x10 | ((ad) & 0x0f)) /* Set Higher Column Address: (10h - 1fh) */
+#define SSD1306_STARTLINE(ln) (0x40 | ((ln) & 0x3f)) /* Set Display Start Line: (40h - 7fh) */
+#define SSD1306_CONTRAST_MODE (0x81) /* Set Contrast Control Register: (Double Bytes Command) */
+# define SSD1306_CONTRAST(c) (c)
+#define SSD1306_SEGREMAP(m) (0xa0 | ((m) & 0x01)) /* Set Segment Re-map: (a0h - a1h) */
+# define SSD1306_REMAPRIGHT SSD1306_SEGREMAP(0) /* Right rotation */
+# define SSD1306_REMAPPLEFT SSD1306_SEGREMAP(1) /* Left rotation */
+#define SSD1306_EDISPOFFON(s) (0xa4 | ((s) & 0x01)) /* Set Entire Display OFF/ON: (a4h - a5h) */
+# define SSD1306_EDISPOFF SSD1306_EDISPOFFON(0) /* Display off */
+# define SSD1306_EDISPON SSD1306_EDISPOFFON(1) /* Display on */
+#define SSD1306_NORMREV(s) (0xa6 | ((s) & 0x01)) /* Set Normal/Reverse Display: (a6h -a7h) */
+# define SSD1306_NORMAL SSD1306_NORMREV(0) /* Normal display */
+# define SSD1306_REVERSE SSD1306_NORMREV(1) /* Reverse display */
+#define SSD1306_MRATIO_MODE (0xa8) /* Set Multiplex Ration: (Double Bytes Command) */
+# define SSD1306_MRATIO(d) ((d) & 0x3f)
+#define SSD1306_DCDC_MODE (0xad) /* Set DC-DC OFF/ON: (Double Bytes Command) */
+# define SSD1306_DCDC_OFF (0x8a)
+# define SSD1306_DCDC_ON (0x8b)
+
+#define SSD1306_DISPOFFON(s) (0xae | ((s) & 0x01)) /* Display OFF/ON: (aeh - afh) */
+# define SSD1306_DISPOFF SSD1306_DISPOFFON(0) /* Display off */
+# define SSD1306_DISPON SSD1306_DISPOFFON(1) /* Display on */
+#define SSD1306_PAGEADDR(a) (0xb0 | ((a) & 0x0f)) /* Set Page Address: (b0h - b7h) */
+#define SSD1306_SCANDIR(d) (0xc0 | ((d) & 0x08)) /* Set Common Output Scan Direction: (c0h - c8h) */
+# define SSD1306_SCANFROMCOM0 SSD1306_SCANDIR(0x00) /* Scan from COM[0] to COM[n-1]*/
+# define SSD1306_SCANTOCOM0 SSD1306_SCANDIR(0x08) /* Scan from COM[n-1] to COM[0] */
+#define SSD1306_DISPOFFS_MODE (0xd3) /* Set Display Offset: (Double Bytes Command) */
+# define SSD1306_DISPOFFS(o) ((o) & 0x3f)
+#define SSD1306_CLKDIV_SET (0xd5) /* Set Display Clock Divide Ratio/Oscillator Frequency: (Double Bytes Command) */
+# define SSD1306_CLKDIV(f,d) ((((f) & 0x0f) << 4) | ((d) & 0x0f))
+#define SSD1306_CHRGPER_SET (0xd9) /* Set Dis-charge/Pre-charge Period: (Double Bytes Command) */
+# define SSD1306_CHRGPER(d,p) ((((d) & 0x0f) << 4) | ((p) & 0x0f))
+#define SSD1306_CMNPAD_CONFIG (0xda) /* Set Common pads hardware configuration: (Double Bytes Command) */
+# define SSD1306_CMNPAD(c) ((0x02) | ((c) & 0x10))
+#define SSD1306_VCOM_SET (0xdb) /* Set VCOM Deselect Level: (Double Bytes Command) */
+# define SSD1306_VCOM(v) (v)
+
+#define SSD1306_CHRPUMP_SET (0x8d) /* Charge Pump Setting */
+# define SSD1306_CHRPUMP_ON (0x14)
+# define SSD1306_CHRPUMP_OFF (0x10)
+
+#define SSD1306_RMWSTART (0xe0) /* Read-Modify-Write: (e0h) */
+#define SSD1306_NOP (0xe3) /* NOP: (e3h) */
+#define SSD1306_END (0xee) /* End: (eeh) */
+
+#define SSD1306_WRDATA(d) (d) /* Write Display Data */
+#define SSD1306_STATUS_BUSY (0x80) /* Read Status */
+#define SSD1306_STATUS_ONOFF (0x40)
+#define SSD1306_RDDATA(d) (d) /* Read Display Data */
+
+/* Color Properties *******************************************************************/
+/* Display Resolution
+ *
+ * The SSD1306 display controller can handle a resolution of 132x64. The UG-2864HSWEG01
+ * on the base board is 128x64.
+ */
+
+#define UG2864HSWEG01_DEV_XRES 128 /* Only 128 of 131 columns used */
+#define UG2864HSWEG01_DEV_YRES 64 /* 8 pages each 8 rows */
+#define UG2864HSWEG01_DEV_XOFFSET 2 /* Offset to logical column 0 */
+#define UG2864HSWEG01_DEV_PAGES 8 /* 8 pages */
+
+#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
+# define UG2864HSWEG01_XRES UG2864HSWEG01_DEV_XRES
+# define UG2864HSWEG01_YRES UG2864HSWEG01_DEV_YRES
+#else
+# define UG2864HSWEG01_XRES UG2864HSWEG01_DEV_YRES
+# define UG2864HSWEG01_YRES UG2864HSWEG01_DEV_XRES
+#endif
+
+/* Color depth and format */
+
+#define UG2864HSWEG01_BPP 1
+#define UG2864HSWEG01_COLORFMT FB_FMT_Y1
+
+/* Bytes per logical row and actual device row */
+
+#define UG2864HSWEG01_XSTRIDE (UG2864HSWEG01_XRES >> 3)
+#define UG2864HSWEG01_YSTRIDE (UG2864HSWEG01_YRES >> 3)
+
+/* Default contrast */
+
+#define UG2864HSWEG01_CONTRAST (128)
+
+/* The size of the shadow frame buffer or one row buffer.
+ *
+ * Frame buffer size: 128 columns x 64 rows / 8 bits-per-pixel
+ * Row size: 128 columns x 8 rows-per-page / 8 bits-per-pixel
+ */
+
+#define UG2864HSWEG01_FBSIZE (UG2864HSWEG01_XSTRIDE * UG2864HSWEG01_YRES)
+#define UG2864HSWEG01_ROWSIZE (UG2864HSWEG01_XSTRIDE)
+
+/* Bit helpers */
+
+#define LS_BIT (1 << 0)
+#define MS_BIT (1 << 7)
+
+/* Debug ******************************************************************************/
+
+#ifdef CONFIG_DEBUG_LCD
+# define lcddbg(format, arg...) dbg(format, ##arg)
+# define lcdvdbg(format, arg...) vdbg(format, ##arg)
+#else
+# define lcddbg(x...)
+# define lcdvdbg(x...)
+#endif
+
+/**************************************************************************************
+ * Private Type Definition
+ **************************************************************************************/
+
+/* This structure describes the state of this driver */
+
+struct ug2864hsweg01_dev_s
+{
+ struct lcd_dev_s dev; /* Publically visible device structure */
+
+ /* Private LCD-specific information follows */
+
+ FAR struct spi_dev_s *spi; /* Cached SPI device reference */
+ uint8_t contrast; /* Current contrast setting */
+ bool on; /* true: display is on */
+
+
+ /* The SSD1306 does not support reading from the display memory in SPI mode.
+ * Since there is 1 BPP and access is byte-by-byte, it is necessary to keep
+ * a shadow copy of the framebuffer memory. At 128x64, this amounts to 1KB.
+ */
+
+ uint8_t fb[UG2864HSWEG01_FBSIZE];
+};
+
+/**************************************************************************************
+ * Private Function Protototypes
+ **************************************************************************************/
+
+/* Low-level SPI helpers */
+
+#ifdef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_configspi(FAR struct spi_dev_s *spi);
+# define ug2864hsweg01_lock(spi)
+# define ug2864hsweg01_unlock(spi)
+#else
+# define ug2864hsweg01_configspi(spi)
+static void ug2864hsweg01_lock(FAR struct spi_dev_s *spi);
+static void ug2864hsweg01_unlock(FAR struct spi_dev_s *spi);
+#endif
+
+/* LCD Data Transfer Methods */
+
+static int ug2864hsweg01_putrun(fb_coord_t row, fb_coord_t col,
+ FAR const uint8_t *buffer, size_t npixels);
+static int ug2864hsweg01_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
+ size_t npixels);
+
+/* LCD Configuration */
+
+static int ug2864hsweg01_getvideoinfo(FAR struct lcd_dev_s *dev,
+ FAR struct fb_videoinfo_s *vinfo);
+static int ug2864hsweg01_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
+ FAR struct lcd_planeinfo_s *pinfo);
+
+/* LCD RGB Mapping */
+
+#ifdef CONFIG_FB_CMAP
+# error "RGB color mapping not supported by this driver"
+#endif
+
+/* Cursor Controls */
+
+#ifdef CONFIG_FB_HWCURSOR
+# error "Cursor control not supported by this driver"
+#endif
+
+/* LCD Specific Controls */
+
+static int ug2864hsweg01_getpower(struct lcd_dev_s *dev);
+static int ug2864hsweg01_setpower(struct lcd_dev_s *dev, int power);
+static int ug2864hsweg01_getcontrast(struct lcd_dev_s *dev);
+static int ug2864hsweg01_setcontrast(struct lcd_dev_s *dev, unsigned int contrast);
+
+/**************************************************************************************
+ * Private Data
+ **************************************************************************************/
+
+/* This is working memory allocated by the LCD driver for each LCD device
+ * and for each color plane. This memory will hold one raster line of data.
+ * The size of the allocated run buffer must therefore be at least
+ * (bpp * xres / 8). Actual alignment of the buffer must conform to the
+ * bitwidth of the underlying pixel type.
+ *
+ * If there are multiple planes, they may share the same working buffer
+ * because different planes will not be operate on concurrently. However,
+ * if there are multiple LCD devices, they must each have unique run buffers.
+ */
+
+static uint8_t g_runbuffer[UG2864HSWEG01_ROWSIZE];
+
+/* This structure describes the overall LCD video controller */
+
+static const struct fb_videoinfo_s g_videoinfo =
+{
+ .fmt = UG2864HSWEG01_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */
+ .xres = UG2864HSWEG01_XRES, /* Horizontal resolution in pixel columns */
+ .yres = UG2864HSWEG01_YRES, /* Vertical resolution in pixel rows */
+ .nplanes = 1, /* Number of color planes supported */
+};
+
+/* This is the standard, NuttX Plane information object */
+
+static const struct lcd_planeinfo_s g_planeinfo =
+{
+ .putrun = ug2864hsweg01_putrun, /* Put a run into LCD memory */
+ .getrun = ug2864hsweg01_getrun, /* Get a run from LCD memory */
+ .buffer = (uint8_t*)g_runbuffer, /* Run scratch buffer */
+ .bpp = UG2864HSWEG01_BPP, /* Bits-per-pixel */
+};
+
+/* This is the OLED driver instance (only a single device is supported for now) */
+
+static struct ug2864hsweg01_dev_s g_oleddev =
+{
+ .dev =
+ {
+ /* LCD Configuration */
+
+ .getvideoinfo = ug2864hsweg01_getvideoinfo,
+ .getplaneinfo = ug2864hsweg01_getplaneinfo,
+
+ /* LCD RGB Mapping -- Not supported */
+ /* Cursor Controls -- Not supported */
+
+ /* LCD Specific Controls */
+
+ .getpower = ug2864hsweg01_getpower,
+ .setpower = ug2864hsweg01_setpower,
+ .getcontrast = ug2864hsweg01_getcontrast,
+ .setcontrast = ug2864hsweg01_setcontrast,
+ },
+};
+
+/**************************************************************************************
+ * Private Functions
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_configspi
+ *
+ * Description:
+ * Configure the SPI for use with the UG-2864HSWEG01
+ *
+ * Input Parameters:
+ * spi - Reference to the SPI driver structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ **************************************************************************************/
+
+#ifdef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_configspi(FAR struct spi_dev_s *spi)
+{
+ lcdvdbg("Mode: %d Bits: 8 Frequency: %d\n",
+ CONFIG_UG2864HSWEG01_SPIMODE, CONFIG_UG2864HSWEG01_FREQUENCY);
+
+ /* Configure SPI for the UG-2864HSWEG01. But only if we own the SPI bus. Otherwise,
+ * don't bother because it might change.
+ */
+
+ SPI_SETMODE(spi, CONFIG_UG2864HSWEG01_SPIMODE);
+ SPI_SETBITS(spi, 8);
+ SPI_SETFREQUENCY(spi, CONFIG_UG2864HSWEG01_FREQUENCY);
+}
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_lock
+ *
+ * Description:
+ * Select the SPI, locking and re-configuring if necessary
+ *
+ * Input Parameters:
+ * spi - Reference to the SPI driver structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ **************************************************************************************/
+
+#ifndef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_lock(FAR struct spi_dev_s *spi)
+{
+ /* Lock the SPI bus if there are multiple devices competing for the SPI bus. */
+
+ SPI_LOCK(spi, true);
+
+ /* Now make sure that the SPI bus is configured for the UG-2864HSWEG01 (it
+ * might have gotten configured for a different device while unlocked)
+ */
+
+ SPI_SETMODE(spi, CONFIG_UG2864HSWEG01_SPIMODE);
+ SPI_SETBITS(spi, 8);
+ SPI_SETFREQUENCY(spi, CONFIG_UG2864HSWEG01_FREQUENCY);
+}
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_unlock
+ *
+ * Description:
+ * De-select the SPI
+ *
+ * Input Parameters:
+ * spi - Reference to the SPI driver structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ **************************************************************************************/
+
+#ifndef CONFIG_SPI_OWNBUS
+static inline void ug2864hsweg01_unlock(FAR struct spi_dev_s *spi)
+{
+ /* De-select UG-2864HSWEG01 chip and relinquish the SPI bus. */
+
+ SPI_LOCK(spi, false);
+}
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_putrun
+ *
+ * Description:
+ * This method can be used to write a partial raster line to the LCD.
+ *
+ * Input Parameters:
+ * row - Starting row to write to (range: 0 <= row < yres)
+ * col - Starting column to write to (range: 0 <= col <= xres-npixels)
+ * buffer - The buffer containing the run to be written to the LCD
+ * npixels - The number of pixels to write to the LCD
+ * (range: 0 < npixels <= xres-col)
+ *
+ **************************************************************************************/
+
+#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
+static int ug2864hsweg01_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
+ size_t npixels)
+{
+ /* Because of this line of code, we will only be able to support a single UG device */
+
+ FAR struct ug2864hsweg01_dev_s *priv = (FAR struct ug2864hsweg01_dev_s *)&g_oleddev;
+ FAR uint8_t *fbptr;
+ FAR uint8_t *ptr;
+ uint8_t devcol;
+ uint8_t fbmask;
+ uint8_t page;
+ uint8_t usrmask;
+ int pixlen;
+ uint8_t i;
+
+ lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels);
+ DEBUGASSERT(buffer);
+
+ /* Clip the run to the display */
+
+ pixlen = npixels;
+ if ((unsigned int)col + (unsigned int)pixlen > (unsigned int)UG2864HSWEG01_XRES)
+ {
+ pixlen = (int)UG2864HSWEG01_XRES - (int)col;
+ }
+
+ /* Verify that some portion of the run remains on the display */
+
+ if (pixlen <= 0 || row > UG2864HSWEG01_YRES)
+ {
+ return OK;
+ }
+
+ /* Perform coordinate conversion for reverse landscape mode */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ row = (UG2864HSWEG01_YRES-1) - row;
+ col = (UG2864HSWEG01_XRES-1) - col;
+#endif
+
+ /* Get the page number. The range of 64 lines is divided up into eight
+ * pages of 8 lines each.
+ */
+
+ page = row >> 3;
+
+ /* Update the shadow frame buffer memory. First determine the pixel
+ * position in the frame buffer memory. Pixels are organized like
+ * this:
+ *
+ * --------+---+---+---+---+-...-+-----+
+ * Segment | 0 | 1 | 2 | 3 | ... | 131 |
+ * --------+---+---+---+---+-...-+-----+
+ * D0 | | X | | | | |
+ * D1 | | X | | | | |
+ * D2 | | X | | | | |
+ * D3 | | X | | | | |
+ * D4 | | X | | | | |
+ * D5 | | X | | | | |
+ * D6 | | X | | | | |
+ * D7 | | X | | | | |
+ * --------+---+---+---+---+-...-+-----+
+ *
+ * So, in order to draw a white, horizontal line, at row 45. we
+ * would have to modify all of the bytes in page 45/8 = 5. We
+ * would have to set bit 45%8 = 5 in every byte in the page.
+ */
+
+ fbmask = 1 << (row & 7);
+ fbptr = &priv->fb[page * UG2864HSWEG01_XRES + col];
+#ifdef CONFIG_LCD_RLANDSCAPE
+ ptr = fbptr + pixlen - 1;
+#else
+ ptr = fbptr;
+#endif
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ usrmask = MS_BIT;
+#else
+ usrmask = LS_BIT;
+#endif
+
+ for (i = 0; i < pixlen; i++)
+ {
+ /* Set or clear the corresponding bit */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ if ((*buffer & usrmask) != 0)
+ {
+ *ptr-- |= fbmask;
+ }
+ else
+ {
+ *ptr-- &= ~fbmask;
+ }
+#else
+ if ((*buffer & usrmask) != 0)
+ {
+ *ptr++ |= fbmask;
+ }
+ else
+ {
+ *ptr++ &= ~fbmask;
+ }
+#endif
+
+ /* Inc/Decrement to the next source pixel */
+
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ if (usrmask == LS_BIT)
+ {
+ buffer++;
+ usrmask = MS_BIT;
+ }
+ else
+ {
+ usrmask >>= 1;
+ }
+#else
+ if (usrmask == MS_BIT)
+ {
+ buffer++;
+ usrmask = LS_BIT;
+ }
+ else
+ {
+ usrmask <<= 1;
+ }
+#endif
+ }
+
+ /* Offset the column position to account for smaller horizontal
+ * display range.
+ */
+
+ devcol = col + UG2864HSWEG01_DEV_XOFFSET;
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Select command transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Set the starting position for the run */
+ /* Set the column address to the XOFFSET value */
+
+ SPI_SEND(priv->spi, SSD1306_SETCOLL(devcol & 0x0f));
+ SPI_SEND(priv->spi, SSD1306_SETCOLH(devcol >> 4));
+
+ /* Set the page address */
+
+ SPI_SEND(priv->spi, SSD1306_PAGEADDR(page));
+
+ /* Select data transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, false);
+
+ /* Then transfer all of the data */
+
+ (void)SPI_SNDBLOCK(priv->spi, fbptr, pixlen);
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+ return OK;
+}
+#else
+# error "Configuration not implemented"
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getrun
+ *
+ * Description:
+ * This method can be used to read a partial raster line from the LCD:
+ *
+ * Description:
+ * This method can be used to write a partial raster line to the LCD.
+ *
+ * row - Starting row to read from (range: 0 <= row < yres)
+ * col - Starting column to read read (range: 0 <= col <= xres-npixels)
+ * buffer - The buffer in which to return the run read from the LCD
+ * npixels - The number of pixels to read from the LCD
+ * (range: 0 < npixels <= xres-col)
+ *
+ **************************************************************************************/
+
+#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE)
+static int ug2864hsweg01_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
+ size_t npixels)
+{
+ /* Because of this line of code, we will only be able to support a single UG device */
+
+ FAR struct ug2864hsweg01_dev_s *priv = &g_oleddev;
+ FAR uint8_t *fbptr;
+ uint8_t page;
+ uint8_t fbmask;
+ uint8_t usrmask;
+ int pixlen;
+ uint8_t i;
+
+ lcdvdbg("row: %d col: %d npixels: %d\n", row, col, npixels);
+ DEBUGASSERT(buffer);
+
+ /* Clip the run to the display */
+
+ pixlen = npixels;
+ if ((unsigned int)col + (unsigned int)pixlen > (unsigned int)UG2864HSWEG01_XRES)
+ {
+ pixlen = (int)UG2864HSWEG01_XRES - (int)col;
+ }
+
+ /* Verify that some portion of the run is actually the display */
+
+ if (pixlen <= 0 || row > UG2864HSWEG01_YRES)
+ {
+ return -EINVAL;
+ }
+
+ /* Perform coordinate conversion for reverse landscape mode */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ row = (UG2864HSWEG01_YRES-1) - row;
+ col = (UG2864HSWEG01_XRES-1) - col;
+#endif
+
+ /* Then transfer the display data from the shadow frame buffer memory */
+ /* Get the page number. The range of 64 lines is divided up into eight
+ * pages of 8 lines each.
+ */
+
+ page = row >> 3;
+
+ /* Update the shadow frame buffer memory. First determine the pixel
+ * position in the frame buffer memory. Pixels are organized like
+ * this:
+ *
+ * --------+---+---+---+---+-...-+-----+
+ * Segment | 0 | 1 | 2 | 3 | ... | 131 |
+ * --------+---+---+---+---+-...-+-----+
+ * D0 | | X | | | | |
+ * D1 | | X | | | | |
+ * D2 | | X | | | | |
+ * D3 | | X | | | | |
+ * D4 | | X | | | | |
+ * D5 | | X | | | | |
+ * D6 | | X | | | | |
+ * D7 | | X | | | | |
+ * --------+---+---+---+---+-...-+-----+
+ *
+ * So, in order to draw a white, horizontal line, at row 45. we
+ * would have to modify all of the bytes in page 45/8 = 5. We
+ * would have to set bit 45%8 = 5 in every byte in the page.
+ */
+
+ fbmask = 1 << (row & 7);
+#ifdef CONFIG_LCD_RLANDSCAPE
+ fbptr = &priv->fb[page * (UG2864HSWEG01_XRES-1) + col + pixlen];
+#else
+ fbptr = &priv->fb[page * UG2864HSWEG01_XRES + col];
+#endif
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ usrmask = MS_BIT;
+#else
+ usrmask = LS_BIT;
+#endif
+
+ *buffer = 0;
+ for (i = 0; i < pixlen; i++)
+ {
+ /* Set or clear the corresponding bit */
+
+#ifdef CONFIG_LCD_RLANDSCAPE
+ uint8_t byte = *fbptr--;
+#else
+ uint8_t byte = *fbptr++;
+#endif
+ if ((byte & fbmask) != 0)
+ {
+ *buffer |= usrmask;
+ }
+
+ /* Inc/Decrement to the next destination pixel. Hmmmm. It looks like
+ * this logic could write past the end of the user buffer. Revisit
+ * this!
+ */
+
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ if (usrmask == LS_BIT)
+ {
+ buffer++;
+ *buffer = 0;
+ usrmask = MS_BIT;
+ }
+ else
+ {
+ usrmask >>= 1;
+ }
+#else
+ if (usrmask == MS_BIT)
+ {
+ buffer++;
+ *buffer = 0;
+ usrmask = LS_BIT;
+ }
+ else
+ {
+ usrmask <<= 1;
+ }
+#endif
+ }
+
+ return OK;
+}
+#else
+# error "Configuration not implemented"
+#endif
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getvideoinfo
+ *
+ * Description:
+ * Get information about the LCD video controller configuration.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getvideoinfo(FAR struct lcd_dev_s *dev,
+ FAR struct fb_videoinfo_s *vinfo)
+{
+ DEBUGASSERT(dev && vinfo);
+ lcdvdbg("fmt: %d xres: %d yres: %d nplanes: %d\n",
+ g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes);
+ memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s));
+ return OK;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getplaneinfo
+ *
+ * Description:
+ * Get information about the configuration of each LCD color plane.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
+ FAR struct lcd_planeinfo_s *pinfo)
+{
+ DEBUGASSERT(pinfo && planeno == 0);
+ lcdvdbg("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp);
+ memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s));
+ return OK;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getpower
+ *
+ * Description:
+ * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on. On
+ * backlit LCDs, this setting may correspond to the backlight setting.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getpower(FAR struct lcd_dev_s *dev)
+{
+ FAR struct ug2864hsweg01_dev_s *priv = (FAR struct ug2864hsweg01_dev_s *)dev;
+ DEBUGASSERT(priv);
+
+ lcdvdbg("power: %s\n", priv->on ? "ON" : "OFF");
+ return priv->on ? CONFIG_LCD_MAXPOWER : 0;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_setpower
+ *
+ * Description:
+ * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On
+ * backlit LCDs, this setting may correspond to the backlight setting.
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_setpower(struct lcd_dev_s *dev, int power)
+{
+ struct ug2864hsweg01_dev_s *priv = (struct ug2864hsweg01_dev_s *)dev;
+ DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER && priv->spi);
+
+ lcdvdbg("power: %d [%d]\n", power, priv->on ? CONFIG_LCD_MAXPOWER : 0);
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ if (power <= 0)
+ {
+ /* Turn the display off */
+
+ (void)SPI_SEND(priv->spi, SSD1306_DISPOFF);
+ priv->on = false;
+ }
+ else
+ {
+ /* Turn the display on */
+
+ (void)SPI_SEND(priv->spi, SSD1306_DISPON); /* Display on, dim mode */
+ priv->on = true;
+ }
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+ return OK;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_getcontrast
+ *
+ * Description:
+ * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_getcontrast(struct lcd_dev_s *dev)
+{
+ struct ug2864hsweg01_dev_s *priv = (struct ug2864hsweg01_dev_s *)dev;
+ DEBUGASSERT(priv);
+
+ lcdvdbg("contrast: %d\n", priv->contrast);
+ return priv->contrast;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_setcontrast
+ *
+ * Description:
+ * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
+ *
+ **************************************************************************************/
+
+static int ug2864hsweg01_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
+{
+ struct ug2864hsweg01_dev_s *priv = (struct ug2864hsweg01_dev_s *)dev;
+ unsigned int scaled;
+
+ lcdvdbg("contrast: %d\n", contrast);
+ DEBUGASSERT(priv);
+
+ /* Verify the contrast value */
+
+#ifdef CONFIG_DEBUG
+ if (contrast > CONFIG_LCD_MAXCONTRAST)
+ {
+ return -EINVAL;
+ }
+#endif
+
+ /* Scale contrast: newcontrast = 255 * contrast / CONFIG_LCD_MAXCONTRAST
+ * Where contrast is in the range {1,255}
+ */
+
+#if CONFIG_LCD_MAXCONTRAST != 255
+ scaled = ((contrast << 8) - 1) / CONFIG_LCD_MAXCONTRAST;
+#else
+ scaled = contrast;
+#endif
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Select command transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Set the contrast */
+
+ (void)SPI_SEND(priv->spi, SSD1306_CONTRAST_MODE); /* Set contrast control register */
+ (void)SPI_SEND(priv->spi, SSD1306_CONTRAST(scaled)); /* Data 1: Set 1 of 256 contrast steps */
+ priv->contrast = contrast;
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+ return OK;
+}
+
+/**************************************************************************************
+ * Public Functions
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_initialize
+ *
+ * Description:
+ * Initialize the UG-2864HSWEG01 video hardware. The initial state of the
+ * OLED is fully initialized, display memory cleared, and the OLED ready
+ * to use, but with the power setting at 0 (full off == sleep mode).
+ *
+ * Input Parameters:
+ *
+ * spi - A reference to the SPI driver instance.
+ * devno - A value in the range of 0 through CONFIG_UG2864HSWEG01_NINTERFACES-1.
+ * This allows support for multiple OLED devices.
+ *
+ * Returned Value:
+ *
+ * On success, this function returns a reference to the LCD object for
+ * the specified OLED. NULL is returned on any failure.
+ *
+ **************************************************************************************/
+
+FAR struct lcd_dev_s *ug2864hsweg01_initialize(FAR struct spi_dev_s *spi, unsigned int devno)
+{
+ FAR struct ug2864hsweg01_dev_s *priv = &g_oleddev;
+
+ lcdvdbg("Initializing\n");
+ DEBUGASSERT(spi && devno == 0);
+
+ /* Save the reference to the SPI device */
+
+ priv->spi = spi;
+
+ /* Configure the SPI */
+
+ ug2864hsweg01_configspi(spi);
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(spi, SPIDEV_DISPLAY, true);
+
+ /* Select command transfer */
+
+ SPI_CMDDATA(spi, SPIDEV_DISPLAY, true);
+
+ /* Configure OLED SPI or I/O, must be delayed 1-10ms */
+
+ up_mdelay(5);
+
+ /* Configure the device */
+
+//#define OLED_WriteCmd(v) SPI_SEND(spi,v)
+//
+// /* Module manufacturers to provide initialization code Ä£¿é³§¼ÒÌṩ³õʼ»¯´úÂë */
+//
+// OLED_WriteCmd(0xAE); /* ¹Ø±ÕOLEDÃæ°åÏÔʾ(ÐÝÃß) */
+// OLED_WriteCmd(0x00); /* ÉèÖÃÁеØÖ·µÍ4bit */
+// OLED_WriteCmd(0x10); /* ÉèÖÃÁеØÖ·¸ß4bit */
+// OLED_WriteCmd(0x40); /* ÉèÖÃÆðʼÐеØÖ·£¨µÍ5bit 0-63£©£¬ Ó²¼þÏà¹Ø*/
+//
+// OLED_WriteCmd(0x81); /* ÉèÖöԱȶÈÃüÁî(Ë«×Ö½ÚÃüÁ£¬µÚ1¸ö×Ö½ÚÊÇÃüÁµÚ2¸ö×Ö½ÚÊǶԱȶȲÎÊý0-255 */
+// OLED_WriteCmd(0xCF); /* ÉèÖöԱȶȲÎÊý */
+//
+// OLED_WriteCmd(0xA1); /* A0 £ºÁеØÖ·0Ó³Éäµ½SEG0; A1 £ºÁеØÖ·127Ó³Éäµ½SEG0 */
+// OLED_WriteCmd(0xA6); /* A6 : ÉèÖÃÕý³£ÏÔʾģʽ; A7 : ÉèÖÃΪ·´ÏÔģʽ */
+//
+// OLED_WriteCmd(0xA8); /* ÉèÖÃCOM·Êý */
+// OLED_WriteCmd(0x3F); /* 1 ->£¨63+1£©Â· */
+//
+// OLED_WriteCmd(0xD3); /* ÉèÖÃÏÔʾƫÒÆ£¨Ë«×Ö½ÚÃüÁ*/
+// OLED_WriteCmd(0x00); /* ÎÞÆ«ÒÆ */
+//
+// OLED_WriteCmd(0xD5); /* ÉèÖÃÏÔʾʱÖÓ·ÖƵϵÊý/Õñµ´ÆµÂÊ */
+// OLED_WriteCmd(0x80); /* ÉèÖ÷ÖƵϵÊý,¸ß4bitÊÇ·ÖƵϵÊý£¬µÍ4bitÊÇÕñµ´ÆµÂÊ */
+//
+// OLED_WriteCmd(0xD9); /* ÉèÖÃÔ¤³äµçÖÜÆÚ */
+// OLED_WriteCmd(0xF1); /* [3:0],PHASE 1; [7:4],PHASE 2; */
+//
+// OLED_WriteCmd(0xDA); /* ÉèÖÃCOM½ÅÓ²¼þ½ÓÏß·½Ê½ */
+// OLED_WriteCmd(0x12);
+//
+// OLED_WriteCmd(0xDB); /* ÉèÖà vcomh µçѹ±¶ÂÊ */
+// OLED_WriteCmd(0x40); /* [6:4] 000 = 0.65 x VCC; 0.77 x VCC (RESET); 0.83 x VCC */
+//
+// OLED_WriteCmd(0x8D); /* ÉèÖóäµç±Ã£¨ºÍϸöÃüÁî½áºÏʹÓã© */
+// OLED_WriteCmd(0x14); /* 0x14 ʹÄܳäµç±Ã£¬ 0x10 ÊÇ¹Ø±Õ */
+// OLED_WriteCmd(0xAF); /* ´ò¿ªOLEDÃæ°å */
+
+ SPI_SEND(spi, SSD1306_DISPOFF); /* Display off 0xAE*/
+ SPI_SEND(spi, SSD1306_SETCOLL(0)); /* Set lower column address 0x00 */
+ SPI_SEND(spi, SSD1306_SETCOLH(0)); /* Set higher column address 0x10 */
+ SPI_SEND(spi, SSD1306_STARTLINE(0)); /* Set display start line 0x40*/
+ /* SPI_SEND(spi, SSD1306_PAGEADDR(0));*//* Set page address (Can ignore)*/
+ SPI_SEND(spi, SSD1306_CONTRAST_MODE); /* Contrast control 0x81*/
+ SPI_SEND(spi ,SSD1306_CONTRAST(UG2864HSWEG01_CONTRAST)); /* Default contrast 0xCF */
+ SPI_SEND(spi, SSD1306_REMAPPLEFT); /* Set segment remap left 95 to 0 | 0xA1*/
+ /* SPI_SEND(spi, SSD1306_EDISPOFF); */ /* Normal display :off 0xA4 (Can ignore)*/
+ SPI_SEND(spi, SSD1306_NORMAL); /* Normal (un-reversed) display mode 0xA6 */
+ SPI_SEND(spi, SSD1306_MRATIO_MODE); /* Multiplex ratio 0xA8*/
+ SPI_SEND(spi, SSD1306_MRATIO(0x3f)); /* Duty = 1/64 */
+ /* SPI_SEND(spi, SSD1306_SCANTOCOM0);*/ /* Com scan direction: Scan from COM[n-1] to COM[0] (Can ignore)*/
+ SPI_SEND(spi, SSD1306_DISPOFFS_MODE); /* Set display offset 0xD3 */
+ SPI_SEND(spi, SSD1306_DISPOFFS(0));
+ SPI_SEND(spi, SSD1306_CLKDIV_SET); /* Set clock divider 0xD5*/
+ SPI_SEND(spi, SSD1306_CLKDIV(8,0)); /* 0x80*/
+
+ SPI_SEND(spi, SSD1306_CHRGPER_SET); /* ++Set pre-charge period 0xD9*/
+ SPI_SEND(spi, SSD1306_CHRGPER(0x0f,1)); /* 0xf1 or 0x22£¨Enhanced mode?£© */
+
+ SPI_SEND(spi, SSD1306_CMNPAD_CONFIG); /* Set common pads / set com pins hardware configuration 0xDA*/
+ SPI_SEND(spi, SSD1306_CMNPAD(0x12)); /* 0x12 */
+
+ SPI_SEND(spi, SSD1306_VCOM_SET); /* set vcomh 0xDB*/
+ SPI_SEND(spi, SSD1306_VCOM(0x40));
+
+ SPI_SEND(spi, SSD1306_CHRPUMP_SET); /* ++Set Charge Pump enable/disable 0x8D ssd1306*/
+ SPI_SEND(spi, SSD1306_CHRPUMP_ON); /* 0x14 close 0x10 */
+
+ /*SPI_SEND(spi, SSD1306_DCDC_MODE); */ /* DC/DC control mode: on (SSD1306 Not supported) */
+ /*SPI_SEND(spi, SSD1306_DCDC_ON); */
+
+ SPI_SEND(spi, SSD1306_DISPON); /* display ON 0xAF */
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+
+ /* Clear the display */
+
+ up_mdelay(100);
+ ug2864hsweg01_fill(&priv->dev, UG_Y1_BLACK);
+ return &priv->dev;
+}
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_fill
+ *
+ * Description:
+ * This non-standard method can be used to clear the entire display by writing one
+ * color to the display. This is much faster than writing a series of runs.
+ *
+ * Input Parameters:
+ * priv - Reference to private driver structure
+ *
+ * Assumptions:
+ * Caller has selected the OLED section.
+ *
+ **************************************************************************************/
+
+void ug2864hsweg01_fill(FAR struct lcd_dev_s *dev, uint8_t color)
+{
+ FAR struct ug2864hsweg01_dev_s *priv = &g_oleddev;
+ unsigned int page;
+
+ /* Make an 8-bit version of the selected color */
+
+ if (color & 1)
+ {
+ color = 0xff;
+ }
+ else
+ {
+ color = 0;
+ }
+
+ /* Initialize the framebuffer */
+
+ memset(priv->fb, color, UG2864HSWEG01_FBSIZE);
+
+ /* Lock and select device */
+
+ ug2864hsweg01_lock(priv->spi);
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Visit each page */
+
+ for (page = 0; page < UG2864HSWEG01_DEV_PAGES; page++)
+ {
+ /* Select command transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, true);
+
+ /* Set the column address to the XOFFSET value */
+
+ SPI_SEND(priv->spi, SSD1306_SETCOLL(UG2864HSWEG01_DEV_XOFFSET));
+ SPI_SEND(priv->spi, SSD1306_SETCOLH(0));
+
+ /* Set the page address */
+
+ SPI_SEND(priv->spi, SSD1306_PAGEADDR(page));
+
+ /* Select data transfer */
+
+ SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY, false);
+
+ /* Transfer one page of the selected color */
+
+ (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG2864HSWEG01_XRES],
+ UG2864HSWEG01_XRES);
+ }
+
+ /* De-select and unlock the device */
+
+ SPI_SELECT(priv->spi, SPIDEV_DISPLAY, false);
+ ug2864hsweg01_unlock(priv->spi);
+}
+
+#endif /* CONFIG_LCD_UG2864HSWEG01 */
diff --git a/nuttx/drivers/mmcsd/Kconfig b/nuttx/drivers/mmcsd/Kconfig
index c224f220a..5cdc23bcf 100644
--- a/nuttx/drivers/mmcsd/Kconfig
+++ b/nuttx/drivers/mmcsd/Kconfig
@@ -2,6 +2,7 @@
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
+
config MMCSD_NSLOTS
int "Number of MMC/SD slots"
default 1
@@ -38,8 +39,9 @@ config MMCSD_HAVECARDDETECT
100% accurate
config MMCSD_SPI
- bool "MMC/SD spi transfer support"
+ bool "MMC/SD SPI transfer support"
default y
+ depends on SPI
config MMCSD_SPICLOCK
int "MMC/SD maximum SPI clock"
diff --git a/nuttx/drivers/mtd/Make.defs b/nuttx/drivers/mtd/Make.defs
index 7db7592d4..3102f1447 100644
--- a/nuttx/drivers/mtd/Make.defs
+++ b/nuttx/drivers/mtd/Make.defs
@@ -37,6 +37,8 @@
# Include MTD drivers
+ifeq ($(CONFIG_MTD),y)
+
CSRCS += at45db.c flash_eraseall.c ftl.c m25px.c rammtd.c ramtron.c
ifeq ($(CONFIG_MTD_AT24XX),y)
@@ -60,3 +62,4 @@ endif
DEPPATH += --dep-path mtd
VPATH += :mtd
+endif
diff --git a/nuttx/drivers/usbdev/composite.c b/nuttx/drivers/usbdev/composite.c
index 4cad8af86..530d64416 100644
--- a/nuttx/drivers/usbdev/composite.c
+++ b/nuttx/drivers/usbdev/composite.c
@@ -523,12 +523,12 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
{
/* Save the configuration and inform the constituent classes */
- ret = CLASS_SETUP(priv->dev1, dev, ctrl);
+ ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen);
dispatched = true;
if (ret >= 0)
{
- ret = CLASS_SETUP(priv->dev2, dev, ctrl);
+ ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen);
if (ret >= 0)
{
priv->config = value;
diff --git a/nuttx/drivers/usbdev/pl2303.c b/nuttx/drivers/usbdev/pl2303.c
index 95f26c185..d10539fa7 100644
--- a/nuttx/drivers/usbdev/pl2303.c
+++ b/nuttx/drivers/usbdev/pl2303.c
@@ -333,7 +333,7 @@ static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep,
/* USB class device ********************************************************/
-static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
+static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev);
static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev);
@@ -1295,7 +1295,7 @@ static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
priv->usbdev = dev;
/* Save the reference to our private data structure in EP0 so that it
- * can be recovered in ep0 completion events (Unless we are part of
+ * can be recovered in ep0 completion events (Unless we are part of
* a composite device and, in that case, the composite device owns
* EP0).
*/
@@ -1859,7 +1859,7 @@ static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
* re-enumerated.
*/
- DEV_CONNECT(dev);
+ DEV_CONNECT(dev);
}
/****************************************************************************
@@ -1878,7 +1878,7 @@ static int usbser_setup(FAR struct uart_dev_s *dev)
{
FAR struct pl2303_dev_s *priv;
- usbtrace(PL2303_CLASSASPI_SETUP, 0);
+ usbtrace(PL2303_CLASSAPI_SETUP, 0);
/* Sanity check */
@@ -1919,7 +1919,7 @@ static int usbser_setup(FAR struct uart_dev_s *dev)
static void usbser_shutdown(FAR struct uart_dev_s *dev)
{
- usbtrace(PL2303_CLASSASPI_SHUTDOWN, 0);
+ usbtrace(PL2303_CLASSAPI_SHUTDOWN, 0);
/* Sanity check */
@@ -1941,7 +1941,7 @@ static void usbser_shutdown(FAR struct uart_dev_s *dev)
static int usbser_attach(FAR struct uart_dev_s *dev)
{
- usbtrace(PL2303_CLASSASPI_ATTACH, 0);
+ usbtrace(PL2303_CLASSAPI_ATTACH, 0);
return OK;
}
@@ -1955,7 +1955,7 @@ static int usbser_attach(FAR struct uart_dev_s *dev)
static void usbser_detach(FAR struct uart_dev_s *dev)
{
- usbtrace(PL2303_CLASSASPI_DETACH, 0);
+ usbtrace(PL2303_CLASSAPI_DETACH, 0);
}
/****************************************************************************
@@ -1981,7 +1981,7 @@ static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable)
FAR uart_dev_t *serdev;
irqstate_t flags;
- usbtrace(PL2303_CLASSASPI_RXINT, (uint16_t)enable);
+ usbtrace(PL2303_CLASSAPI_RXINT, (uint16_t)enable);
/* Sanity check */
@@ -2072,7 +2072,7 @@ static void usbser_txint(FAR struct uart_dev_s *dev, bool enable)
{
FAR struct pl2303_dev_s *priv;
- usbtrace(PL2303_CLASSASPI_TXINT, (uint16_t)enable);
+ usbtrace(PL2303_CLASSAPI_TXINT, (uint16_t)enable);
/* Sanity checks */
@@ -2117,7 +2117,7 @@ static bool usbser_txempty(FAR struct uart_dev_s *dev)
{
FAR struct pl2303_dev_s *priv = (FAR struct pl2303_dev_s*)dev->priv;
- usbtrace(PL2303_CLASSASPI_TXEMPTY, 0);
+ usbtrace(PL2303_CLASSAPI_TXEMPTY, 0);
#if CONFIG_DEBUG
if (!priv)
diff --git a/nuttx/drivers/usbhost/Kconfig b/nuttx/drivers/usbhost/Kconfig
index 35695d750..531e94442 100644
--- a/nuttx/drivers/usbhost/Kconfig
+++ b/nuttx/drivers/usbhost/Kconfig
@@ -2,6 +2,7 @@
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
+
config USBHOST_NPREALLOC
int "Number of pre-allocated class instances"
default 4
@@ -29,64 +30,85 @@ config USBHOST_ISOC_DISABLE
On some architectures, selecting this setting will reduce driver size
by disabling isochronous endpoint support
+config USBHOST_MSC
+ bool "Mass Storage Class Support"
+ default n
+ depends on !BULK_DISABLE
+ ---help---
+ Enable support for the keyboard class driver. This also depends on
+ NFILE_DESCRIPTORS > 0 && SCHED_WORKQUEUE=y
+
config USBHOST_HIDKBD
- bool "HID keyboad class support"
+ bool "HID Keyboard Class Support"
default n
- depends on !USBHOST_INT_DISABLE && SCHED_WORKQUEUE && !DISABLE_SIGNALS
+ depends on !INT_DISABLE
+ ---help---
+ Enable support for the keyboard class driver. This also depends on
+ SCHED_WORKQUEUE && !DISABLE_SIGNALS
if USBHOST_HIDKBD
config HIDKBD_POLLUSEC
- bool ""
- default n
+ int "Keyboard Poll Rate (MSEC)"
+ default 100000
---help---
- Device poll rate in microseconds. Default: 100 milliseconds.
+ Device poll rate in microseconds. Default: 100,000 microseconds.
config HIDKBD_DEFPRIO
- bool ""
- default n
+ int "Polling Thread Priority"
+ default 50
---help---
Priority of the polling thread. Default: 50.
config HIDKBD_STACKSIZE
- bool ""
- default n
+ int "Polling thread stack size"
+ default 1024
---help---
Stack size for polling thread. Default: 1024
config HIDKBD_BUFSIZE
- bool ""
- default n
+ int "Scancode Buffer Size"
+ default 64
---help---
Scancode buffer size. Default: 64.
config HIDKBD_NPOLLWAITERS
- bool ""
- default n
+ int "Max Number of Waiters for Poll Event"
+ default 2
+ depends on !DISABLE_POLL
---help---
If the poll() method is enabled, this defines the maximum number
of threads that can be waiting for keyboard events. Default: 2.
config HIDKBD_RAWSCANCODES
- bool ""
+ bool "Use Raw Scan Codes"
+ default n
+ ---help---
+ If set to y no conversions will be made on the raw keyboard scan
+ codes. This option is useful during testing. Default: ASCII conversion.
+
+config HIDKBD_ENCODED
+ bool "Enocode Special Keys"
default n
+ depends on !HIDKBD_RAWSCANCODES && LIB_KBDCODEC
---help---
- If set to y no conversion will be made on the raw keyboard scan
- codes. Default: ASCII conversion.
+ Encode special key press events in the user buffer. In this case,
+ the user end must decode the encoded special key values using the
+ interfaces defined in include/nuttx/input/kbd_codec.h. These
+ special keys include such things as up/down arrows, home and end
+ keys, etc. If this not defined, only 7-bit print-able and control
+ ASCII characters will be provided to the user.
config HIDKBD_ALLSCANCODES
- bool ""
+ bool "Use All Scancodes"
default n
---help---
If set to y all 231 possible scancodes will be converted to
something. Default: 104 key US keyboard.
config HIDKBD_NODEBOUNCE
- bool ""
+ bool "Disable Debounce"
default n
---help---
If set to y normal debouncing is disabled. Default:
Debounce enabled (No repeat keys).
- USB host mass storage class driver. Requires USBHOST=y,
- config USBHOST_BULK_DISABLE=n, NFILE_DESCRIPTORS > 0,
- and SCHED_WORKQUEUE=y
endif
diff --git a/nuttx/drivers/usbhost/usbhost_hidkbd.c b/nuttx/drivers/usbhost/usbhost_hidkbd.c
index e69d68e7b..d6a9ceda3 100644
--- a/nuttx/drivers/usbhost/usbhost_hidkbd.c
+++ b/nuttx/drivers/usbhost/usbhost_hidkbd.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/usbhost/usbhost_hidkbd.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,11 @@
#include <nuttx/usb/usbhost.h>
#include <nuttx/usb/hid.h>
+#ifdef CONFIG_HIDKBD_ENCODED
+# include <nuttx/streams.h>
+# include <nuttx/input/kbd_codec.h>
+#endif
+
/* Don't compile if prerequisites are not met */
#if defined(CONFIG_USBHOST) && !defined(CONFIG_USBHOST_INT_DISABLE) && CONFIG_NFILE_DESCRIPTORS > 0
@@ -126,6 +131,22 @@
# endif
#endif
+/* We cant support encoding of special characters of unless the Keyboard
+ * CODEC is enabled.
+ */
+
+#ifndef CONFIG_LIB_KBDCODEC
+# undef CONFIG_HIDKBD_ENCODED
+#endif
+
+/* If we are using raw scancodes, then we cannot support encoding of
+ * special characters either.
+ */
+
+#ifdef CONFIG_HIDKBD_RAWSCANCODES
+# undef CONFIG_HIDKBD_ENCODED
+#endif
+
/* Driver support ***********************************************************/
/* This format is used to construct the /dev/kbd[n] device driver path. It
* defined here so that it will be used consistently in all places.
@@ -144,6 +165,23 @@
#define USBHOST_MAX_CREFS 0x7fff
+/* Debug ********************************************************************/
+/* Both CONFIG_DEBUG_INPUT and CONFIG_DEBUG_USB could apply to this file.
+ * We assume here that CONFIG_DEBUG_INPUT might be enabled separately, but
+ * CONFIG_DEBUG_USB implies both.
+ */
+
+#ifndef CONFIG_DEBUG_INPUT
+# undef idbg
+# define idbg udbg
+# undef illdbg
+# define illdbg ulldbg
+# undef ivdbg
+# define ivdbg uvdbg
+# undef illvdbg
+# define illvdbg ullvdbg
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -209,6 +247,16 @@ struct usbhost_state_s
uint8_t kbdbuffer[CONFIG_HIDKBD_BUFSIZE];
};
+/* This type is used for encoding special characters */
+
+#ifdef CONFIG_HIDKBD_ENCODED
+struct usbhost_outstream_s
+{
+ struct lib_outstream_s stream;
+ FAR struct usbhost_state_s *priv;
+};
+#endif
+
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -240,7 +288,15 @@ static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *dev
/* Keyboard polling thread */
static void usbhost_destroy(FAR void *arg);
+static void usbhost_putbuffer(FAR struct usbhost_state_s *priv, uint8_t keycode);
+#ifdef CONFIG_HIDKBD_ENCODED
+static void usbhost_putstream(FAR struct lib_outstream_s *this, int ch);
+#endif
static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier);
+#ifdef CONFIG_HIDKBD_ENCODED
+static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
+ uint8_t scancode, uint8_t modifier);
+#endif
static int usbhost_kbdpoll(int argc, char *argv[]);
/* Helpers for usbhost_connect() */
@@ -346,6 +402,121 @@ static struct usbhost_state_s *g_priv; /* Data passed to thread */
*/
#ifndef CONFIG_HIDKBD_RAWSCANCODES
+#ifdef CONFIG_HIDKBD_ENCODED
+
+/* The first and last scancode values with encode-able values */
+
+#define FIRST_ENCODING USBHID_KBDUSE_ENTER /* 0x28 Keyboard Return (ENTER) */
+#ifndef CONFIG_HIDKBD_ALLSCANCODES
+# define LAST_ENCODING USBHID_KBDUSE_POWER /* 0x66 Keyboard Power */
+#else
+# define LAST_ENCODING USBHID_KBDUSE_KPDHEXADECIMAL /* 0xdd Keypad Hexadecimal */
+#endif
+
+#define USBHID_NUMENCODINGS (LAST_ENCODING - FIRST_ENCODING + 1)
+
+static const uint8_t encoding[USBHID_NUMENCODINGS] =
+{
+ /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
+
+ KEYCODE_ENTER, 0, KEYCODE_FWDDEL, KEYCODE_BACKDEL, 0, 0, 0, 0,
+
+ /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
+
+ 0, KEYCODE_CAPSLOCK, KEYCODE_F1, KEYCODE_F2, KEYCODE_F3, KEYCODE_F4, KEYCODE_F5, KEYCODE_F6,
+
+ /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
+
+ KEYCODE_F7, KEYCODE_F8, KEYCODE_F9, KEYCODE_F10, KEYCODE_F11, KEYCODE_F12, KEYCODE_PRTSCRN, KEYCODE_SCROLLLOCK,
+
+ /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
+
+ KEYCODE_PAUSE, KEYCODE_INSERT, KEYCODE_HOME, KEYCODE_PAGEUP, KEYCODE_FWDDEL, KEYCODE_END, KEYCODE_PAGEDOWN, KEYCODE_RIGHT,
+
+ /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
+
+ KEYCODE_LEFT, KEYCODE_DOWN, KEYCODE_UP, KEYCODE_NUMLOCK, 0, 0, 0, 0,
+
+ /* 0x58-0x5f: Enter,1-7 */
+
+ KEYCODE_ENTER, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0x60-0x66: 8-9,0,.,Non-US \,Application,Power */
+
+ 0, 0, 0, 0, 0, 0, KEYCODE_POWER,
+
+#ifdef CONFIG_HIDKBD_ALLSCANCODES
+
+ 0, /* 0x67 = */
+
+ /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
+
+ KEYCODE_F13, KEYCODE_F14, KEYCODE_F15, KEYCODE_F16, KEYCODE_F17, KEYCODE_F18, KEYCODE_F19, KEYCODE_F20,
+
+ /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
+
+ KEYCODE_F21, KEYCODE_F22, KEYCODE_F23, KEYCODE_F24, KEYCODE_EXECUTE, KEYCODE_HELP, KEYCODE_MENU, KEYCODE_SELECT,
+
+ /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
+
+ KEYCODE_STOP, KEYCODE_AGAIN, KEYCODE_UNDO, KEYCODE_CUT, KEYCODE_COPY, KEYCODE_PASTE, KEYCODE_FIND, KEYCODE_MUTE,
+
+ /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
+
+ KEYCODE_VOLUP, KEYCODE_VOLDOWN, KEYCODE_LCAPSLOCK, KEYCODE_LNUMLOCK, KEYCODE_LSCROLLLOCK, 0, 0, 0,
+
+ /* 0x88-0x8f: International 2-9 */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0x90-0x97: LAN 1-8 */
+
+ KEYCODE_LANG1, KEYCODE_LANG2, KEYCODE_LANG3, KEYCODE_LANG4, KEYCODE_LANG5, KEYCODE_LANG6, KEYCODE_LANG7, KEYCODE_LANG8,
+
+ /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
+
+ 0, 0, KEYCODE_SYSREQ, KEYCODE_CANCEL, KEYCODE_CLEAR, 0, KEYCODE_ENTER, 0,
+
+ /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xa8-0xaf: (reserved) */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xb8-0xbf: {,},tab,backspace,A-D */
+
+ 0, 0, 0, KEYCODE_BACKDEL, 0, 0, 0, 0,
+
+ /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
+
+ KEYCODE_MEMSTORE, KEYCODE_MEMRECALL, KEYCODE_MEMCLEAR, KEYCODE_MEMADD, KEYCODE_MEMSUB, KEYCODE_MEMMUL, KEYCODE_MEMDIV, KEYCODE_NEGATE,
+
+ /* 0xd8-0xdd: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
+
+ KEYCODE_CLEAR, KEYCODE_CLEARENTRY, KEYCODE_BINARY, KEYCODE_OCTAL, KEYCODE_DECIMAL, KEYCODE_HEXADECIMAL
+#endif
+};
+
+#endif
+
static const uint8_t ucmap[USBHID_NUMSCANCODES] =
{
0, 0, 0, 0, 'A', 'B', 'C', 'D', /* 0x00-0x07: Reserved, errors, A-D */
@@ -354,12 +525,12 @@ static const uint8_t ucmap[USBHID_NUMSCANCODES] =
'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', /* 0x18-0x1f: U-Z,!,@ */
'#', '$', '%', '^', '&', '*', '(', ')', /* 0x20-0x27: #,$,%,^,&,*,(,) */
'\n', '\033', '\177', 0, ' ', '_', '+', '{', /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
- '}', '|', 0, ':', '"', 0, '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tidle,<,> */
+ '}', '|', 0, ':', '"', '~', '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
'?', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,sScrollLock */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
- '\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */
+ '\n', '1', '2', '3', '4', '5', '6', '7', /* 0x58-0x5f: Enter,1-7 */
'8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */
#ifdef CONFIG_HIDKBD_ALLSCANCODES
0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
@@ -368,7 +539,7 @@ static const uint8_t ucmap[USBHID_NUMSCANCODES] =
0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
- 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */
+ 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
@@ -389,12 +560,12 @@ static const uint8_t lcmap[USBHID_NUMSCANCODES] =
'u', 'v', 'w', 'x', 'y', 'z', '1', '2', /* 0x18-0x1f: u-z,1-2 */
'3', '4', '5', '6', '7', '8', '9', '0', /* 0x20-0x27: 3-9,0 */
'\n', '\033', '\177', '\t', ' ', '-', '=', '[', /* 0x28-0x2f: Enter,escape,del,tab,space,-,=,[ */
- ']', '\\', '\234', ';', '\'', 0, ',', '.', /* 0x30-0x37: ],\,Non-US pound,;,',grave accent,,,. */
+ ']', '\\', '\234', ';', '\'', '`', ',', '.', /* 0x30-0x37: ],\,Non-US pound,;,',grave accent,,,. */
'/', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
- '\n', '1', '2', '3', '4', '4', '6', '7', /* 0x58-0x5f: Enter,1-7 */
+ '\n', '1', '2', '3', '4', '5', '6', '7', /* 0x58-0x5f: Enter,1-7 */
'8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */
#ifdef CONFIG_HIDKBD_ALLSCANCODES
0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
@@ -403,7 +574,7 @@ static const uint8_t lcmap[USBHID_NUMSCANCODES] =
0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
- 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Ease,SysReq,Cancel,Clear,Prior,Return,Separator */
+ 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
@@ -638,6 +809,88 @@ static void usbhost_destroy(FAR void *arg)
}
/****************************************************************************
+ * Name: usbhost_putbuffer
+ *
+ * Description:
+ * Add one character to the user buffer.
+ *
+ * Input Parameters:
+ * priv - Driver internal state
+ * keycode - The value to add to the user buffer
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+static void usbhost_putbuffer(FAR struct usbhost_state_s *priv,
+ uint8_t keycode)
+{
+ register unsigned int head;
+ register unsigned int tail;
+
+ /* Copy the next keyboard character into the user buffer. */
+
+ head = priv->headndx;
+ priv->kbdbuffer[head] = keycode;
+
+ /* Increment the head index */
+
+ if (++head >= CONFIG_HIDKBD_BUFSIZE)
+ {
+ head = 0;
+ }
+
+ /* If the buffer is full, then increment the tail index to make space. Is
+ * it better to lose old keystrokes or new?
+ */
+
+ tail = priv->tailndx;
+ if (tail == head)
+ {
+ if (++tail >= CONFIG_HIDKBD_BUFSIZE)
+ {
+ tail = 0;
+ }
+
+ /* Save the updated tail index */
+
+ priv->tailndx = tail;
+ }
+
+ /* Save the updated head index */
+
+ priv->headndx = head;
+}
+
+/****************************************************************************
+ * Name: usbhost_putstream
+ *
+ * Description:
+ * A wrapper for usbhost_putc that is compatibile with the lib_outstream_s
+ * putc methos.
+ *
+ * Input Parameters:
+ * stream - The struct lib_outstream_s reference
+ * ch - The character to add to the user buffer
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_HIDKBD_ENCODED
+static void usbhost_putstream(FAR struct lib_outstream_s *stream, int ch)
+{
+ FAR struct usbhost_outstream_s *privstream = (FAR struct usbhost_outstream_s *)stream;
+
+ DEBUGASSERT(privstream && privstream->priv);
+ usbhost_putbuffer(privstream->priv, (uint8_t)ch);
+ stream->nput++;
+}
+#endif
+
+/****************************************************************************
* Name: usbhost_mapscancode
*
* Description:
@@ -680,6 +933,58 @@ static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier)
}
/****************************************************************************
+ * Name: usbhost_encodescancode
+ *
+ * Description:
+ * Check if the key has a special function encoding and, if it does, add
+ * the encoded value to the user buffer.
+ *
+ * Input Parameters:
+ * priv - Driver internal state
+ * scancode - Scan code to be mapped.
+ * modifier - Ctrl,Alt,Shift,GUI modifier bits
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_HIDKBD_ENCODED
+static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
+ uint8_t scancode, uint8_t modifier)
+{
+ uint8_t encoded;
+
+ /* Check if the raw scancode is in a valid range */
+
+ if (scancode >= FIRST_ENCODING && scancode <= LAST_ENCODING)
+ {
+ /* Yes the value is within range */
+
+ encoded = encoding[scancode - FIRST_ENCODING];
+ ivdbg(" scancode: %02x modifier: %02x encoded: %d\n",
+ scancode, modifier, encoded);
+
+ if (encoded)
+ {
+ struct usbhost_outstream_s usbstream;
+
+ /* And it does correspond to a special function key */
+
+ usbstream.stream.put = usbhost_putstream;
+ usbstream.stream.nput = 0;
+ usbstream.priv = priv;
+
+ /* Add the special function value to the user buffer */
+
+ kbd_specpress((enum kbd_keycode_e)encoded,
+ (FAR struct lib_outstream_s *)&usbstream);
+ }
+ }
+}
+#endif
+
+/****************************************************************************
* Name: usbhost_kbdpoll
*
* Description:
@@ -704,6 +1009,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
unsigned int npolls = 0;
#endif
unsigned int nerrors = 0;
+ bool empty = true;
+ bool newstate;
int ret;
uvdbg("Started\n");
@@ -717,17 +1024,18 @@ static int usbhost_kbdpoll(int argc, char *argv[])
* running.
*/
- priv = g_priv;
- DEBUGASSERT(priv != NULL);
+ priv = g_priv;
+ DEBUGASSERT(priv != NULL);
- priv->polling = true;
- priv->crefs++;
- usbhost_givesem(&g_syncsem);
- sleep(1);
+ priv->polling = true;
+ priv->crefs++;
+ usbhost_givesem(&g_syncsem);
+ sleep(1);
/* Loop here until the device is disconnected */
uvdbg("Entering poll loop\n");
+
while (!priv->disconnected)
{
/* Make sure that we have exclusive access to the private data
@@ -784,17 +1092,12 @@ static int usbhost_kbdpoll(int argc, char *argv[])
else if (priv->open)
{
struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)priv->tbuffer;
- unsigned int head;
- unsigned int tail;
- uint8_t ascii;
+ uint8_t keycode;
int i;
/* Add the newly received keystrokes to our internal buffer */
usbhost_takesem(&priv->exclsem);
- head = priv->headndx;
- tail = priv->tailndx;
-
for (i = 0; i < 6; i++)
{
/* Is this key pressed? But not pressed last time?
@@ -828,15 +1131,15 @@ static int usbhost_kbdpoll(int argc, char *argv[])
* or cursor controls in this version of the driver.
*/
- ascii = usbhost_mapscancode(rpt->key[i], rpt->modifier);
- uvdbg("Key %d: %02x ASCII:%c modifier: %02x\n",
- i, rpt->key[i], ascii ? ascii : ' ', rpt->modifier);
+ keycode = usbhost_mapscancode(rpt->key[i], rpt->modifier);
+ ivdbg("Key %d: %02x keycode:%c modifier: %02x\n",
+ i, rpt->key[i], keycode ? keycode : ' ', rpt->modifier);
/* Zero at this point means that the key does not map to a
* printable character.
*/
- if (ascii != 0)
+ if (keycode != 0)
{
/* Handle control characters. Zero after this means
* a valid, NUL character.
@@ -844,36 +1147,28 @@ static int usbhost_kbdpoll(int argc, char *argv[])
if ((rpt->modifier & (USBHID_MODIFER_LCTRL|USBHID_MODIFER_RCTRL)) != 0)
{
- ascii &= 0x1f;
+ keycode &= 0x1f;
}
/* Copy the next keyboard character into the user
* buffer.
*/
- priv->kbdbuffer[head] = ascii;
-
- /* Increment the head index */
-
- if (++head >= CONFIG_HIDKBD_BUFSIZE)
- {
- head = 0;
- }
+ usbhost_putbuffer(priv, keycode);
+ }
- /* If the buffer is full, then increment the tail
- * index to make space. Is it better to lose old
- * keystrokes or new?
- */
+ /* The zero might, however, map to a special keyboard action (such as a
+ * cursor movement or function key). Attempt to encode the special key.
+ */
- if (tail == head)
- {
- if (++tail >= CONFIG_HIDKBD_BUFSIZE)
- {
- tail = 0;
- }
- }
+#ifdef CONFIG_HIDKBD_ENCODED
+ else
+ {
+ usbhost_encodescancode(priv, rpt->key[i], rpt->modifier);
}
+#endif
}
+
/* Save the scancode (or lack thereof) for key debouncing on
* next keyboard report.
*/
@@ -883,9 +1178,10 @@ static int usbhost_kbdpoll(int argc, char *argv[])
#endif
}
- /* Did we just transition from no data available to data available? */
+ /* Is there data available? */
- if (head != tail && priv->headndx == priv->tailndx)
+ newstate = (priv->headndx == priv->tailndx);
+ if (!newstate)
{
/* Yes.. Is there a thread waiting for keyboard data now? */
@@ -897,15 +1193,18 @@ static int usbhost_kbdpoll(int argc, char *argv[])
priv->waiting = false;
}
- /* And wake up any threads waiting for the POLLIN event */
+ /* Did we just transition from no data available to data
+ * available? If so, wake up any threads waiting for the
+ * POLLIN event.
+ */
- usbhost_pollnotify(priv);
+ if (empty)
+ {
+ usbhost_pollnotify(priv);
+ }
}
- /* Update the head/tail indices */
-
- priv->headndx = head;
- priv->tailndx = tail;
+ empty = newstate;
usbhost_givesem(&priv->exclsem);
}
@@ -958,6 +1257,7 @@ static int usbhost_kbdpoll(int argc, char *argv[])
usbhost_givesem(&priv->exclsem);
}
+
return 0;
}
@@ -1861,6 +2161,7 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
/* Wait for data to be available */
uvdbg("Waiting...\n");
+
priv->waiting = true;
usbhost_givesem(&priv->exclsem);
usbhost_takesem(&priv->waitsem);
diff --git a/nuttx/fs/Kconfig b/nuttx/fs/Kconfig
index 1d1046735..dfbfda3fa 100644
--- a/nuttx/fs/Kconfig
+++ b/nuttx/fs/Kconfig
@@ -5,11 +5,12 @@
comment "File system configuration"
-source fs/fat/Kconfig
source fs/mmap/Kconfig
+source fs/fat/Kconfig
source fs/nfs/Kconfig
source fs/nxffs/Kconfig
source fs/romfs/Kconfig
+source fs/binfs/Kconfig
comment "System Logging"
diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile
index 6955c164b..2a1fd75a8 100644
--- a/nuttx/fs/Makefile
+++ b/nuttx/fs/Makefile
@@ -1,7 +1,7 @@
############################################################################
# fs/Makefile
#
-# Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007, 2008, 2011-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -72,6 +72,9 @@ CSRCS += fs_registerdriver.c fs_unregisterdriver.c
CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c \
fs_findblockdriver.c fs_openblockdriver.c fs_closeblockdriver.c
+DEPPATH =
+VPATH = .
+
include mmap/Make.defs
# Stream support
@@ -91,13 +94,17 @@ endif
# Additional files required is mount-able file systems are supported
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
+
CSRCS += fs_fsync.c fs_mkdir.c fs_mount.c fs_rename.c fs_rmdir.c \
fs_umount.c fs_unlink.c
CSRCS += fs_foreachmountpoint.c
+
include fat/Make.defs
include romfs/Make.defs
include nxffs/Make.defs
include nfs/Make.defs
+include binfs/Make.defs
+
endif
endif
@@ -108,8 +115,7 @@ OBJS = $(AOBJS) $(COBJS)
BIN = libfs$(LIBEXT)
-SUBDIRS = mmap fat romfs nxffs:nfs
-VPATH = mmap:fat:romfs:nxffs:nfs
+SUBDIRS = mmap fat romfs nxffs nfs binfs
all: $(BIN)
@@ -123,8 +129,7 @@ $(BIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
.depend: Makefile $(SRCS)
- $(Q) $(MKDEP) --dep-path . $(MMAPDEPPATH) $(FATDEPPATH) $(ROMFSDEPPATH) $(NXFFSDEPPATH) $(NFSDEPPATH) \
- "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
+ $(Q) $(MKDEP) --dep-path . $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@
depend: .depend
diff --git a/nuttx/fs/binfs/Kconfig b/nuttx/fs/binfs/Kconfig
new file mode 100644
index 000000000..eedbe497d
--- /dev/null
+++ b/nuttx/fs/binfs/Kconfig
@@ -0,0 +1,19 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config FS_BINFS
+ bool "BINFS File System"
+ default n
+ depends on BUILTIN
+ ---help---
+ The BINFS file system is provides access to builtin applications through
+ the NuttX file system. The BINFS may, for example, be mount at /bin.
+ Then all of the built-in applications will appear as executable files in
+ /bin. Then, for example, you list them from NSH like:
+
+ nsh> ls -l /bin
+
+ If the BINFS BINFMT loader is also enabled, then the builtin applications
+ can be executed through the normal mechanisms (posix_spawn(), exev(), etc.)
diff --git a/nuttx/fs/binfs/Make.defs b/nuttx/fs/binfs/Make.defs
new file mode 100644
index 000000000..a65b7367f
--- /dev/null
+++ b/nuttx/fs/binfs/Make.defs
@@ -0,0 +1,48 @@
+############################################################################
+# fs/binfs/Make.defs
+#
+# Copyright (C) 2013 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.
+#
+############################################################################
+
+ifeq ($(CONFIG_FS_BINFS),y)
+# Files required for BINFS file system support
+
+ASRCS +=
+CSRCS += fs_binfs.c
+
+# Include BINFS build support
+
+DEPPATH += --dep-path binfs
+VPATH += :binfs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)binfs}
+
+endif
diff --git a/apps/namedapp/binfs.c b/nuttx/fs/binfs/fs_binfs.c
index 36e3ace92..ed6326eba 100644
--- a/apps/namedapp/binfs.c
+++ b/nuttx/fs/binfs/fs_binfs.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * apps/namedapps/binfs.c
+ * fs/binfs/fs_binfs.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,6 @@
#include <stdint.h>
#include <stdbool.h>
-#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
@@ -53,49 +52,44 @@
#include <debug.h>
#include <nuttx/fs/fs.h>
+#include <nuttx/fs/binfs.h>
#include <nuttx/fs/dirent.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/binfmt/builtin.h>
-#include "namedapp.h"
-
-#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_APPS_BINDIR)
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_BINFS)
/****************************************************************************
* Private Types
****************************************************************************/
-/* This structure represents the overall mountpoint state. An instance of this
- * structure is retained as inode private data on each mountpoint that is
- * mounted with a fat32 filesystem.
- */
-
-struct binfs_state_s
-{
- sem_t bm_sem; /* Used to assume thread-safe access */
-};
-
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
-static void binfs_semtake(struct binfs_state_s *bm);
-static inline void binfs_semgive(struct binfs_state_s *bm);
static int binfs_open(FAR struct file *filep, const char *relpath,
- int oflags, mode_t mode);
+ int oflags, mode_t mode);
static int binfs_close(FAR struct file *filep);
static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int binfs_dup(FAR const struct file *oldp, FAR struct file *newp);
+
static int binfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
-static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
-static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir);
+static int binfs_readdir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
+static int binfs_rewinddir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
-static int binfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle);
-static int binfs_unbind(void *handle, FAR struct inode **blkdriver);
-static int binfs_statfs(struct inode *mountpt, struct statfs *buf);
+static int binfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
+static int binfs_unbind(FAR void *handle, FAR struct inode **blkdriver);
+static int binfs_statfs(FAR struct inode *mountpt,
+ FAR struct statfs *buf);
-static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf);
+static int binfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf);
/****************************************************************************
* Private Variables
@@ -118,7 +112,9 @@ const struct mountpt_operations binfs_operations =
NULL, /* write */
NULL, /* seek */
binfs_ioctl, /* ioctl */
+
NULL, /* sync */
+ binfs_dup, /* dup */
binfs_opendir, /* opendir */
NULL, /* closedir */
@@ -141,70 +137,41 @@ const struct mountpt_operations binfs_operations =
****************************************************************************/
/****************************************************************************
- * Name: binfs_semtake
- ****************************************************************************/
-
-static void binfs_semtake(struct binfs_state_s *bm)
-{
- /* Take the semaphore (perhaps waiting) */
-
- while (sem_wait(&bm->bm_sem) != 0)
- {
- /* The only case that an error should occur here is if
- * the wait was awakened by a signal.
- */
-
- ASSERT(errno == EINTR);
- }
-}
-
-/****************************************************************************
- * Name: binfs_semgive
- ****************************************************************************/
-
-static inline void binfs_semgive(struct binfs_state_s *bm)
-{
- sem_post(&bm->bm_sem);
-}
-
-/****************************************************************************
* Name: binfs_open
****************************************************************************/
-static int binfs_open(FAR struct file *filep, const char *relpath,
- int oflags, mode_t mode)
+static int binfs_open(FAR struct file *filep, FAR const char *relpath,
+ int oflags, mode_t mode)
{
- struct binfs_state_s *bm;
- int ret = -ENOSYS;
+ int index;
fvdbg("Open '%s'\n", relpath);
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
-
- /* mountpoint private data from the inode reference from the file
- * structure
- */
-
- bm = (struct binfs_state_s*)filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
-
/* BINFS is read-only. Any attempt to open with any kind of write
* access is not permitted.
*/
if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0)
{
- fdbg("Only O_RDONLY supported\n");
- ret = -EACCES;
+ fdbg("ERROR: Only O_RDONLY supported\n");
+ return -EACCES;
}
- /* Save open-specific state in filep->f_priv */
+ /* Check if the an entry exists with this name in the root directory.
+ * so the 'relpath' must be the name of the builtin function.
+ */
+
+ index = builtin_isavail(relpath);
+ if (index < 0)
+ {
+ fdbg("ERROR: Builting %s does not exist\n", relpath);
+ return -ENOENT;
+ }
- /* Opening of elements within the pseudo-file system is not yet supported */
+ /* Save the index as the open-specific state in filep->f_priv */
- return ret;
+ filep->f_priv = (FAR void *)index;
+ return OK;
}
/****************************************************************************
@@ -213,31 +180,8 @@ static int binfs_open(FAR struct file *filep, const char *relpath,
static int binfs_close(FAR struct file *filep)
{
- struct binfs_state_s *bm;
- int ret = -ENOSYS;
-
fvdbg("Closing\n");
-
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
-
- /* Recover the open file state from the struct file instance */
- /* bf = filep->f_priv; */
-
- /* Recover the file system state from the inode */
-
- bm = filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
-
- /* Free the open file state */
- /* free(bf); */
-
- filep->f_priv = NULL;
-
- /* Since open() is not yet supported, neither is close(). */
-
- return ret;
+ return OK;
}
/****************************************************************************
@@ -246,25 +190,10 @@ static int binfs_close(FAR struct file *filep)
static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen)
{
- struct binfs_state_s *bm;
+ /* Reading is not supported. Just return end-of-file */
fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos);
-
- /* Sanity checks */
-
- DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
-
- /* Recover the open file state data from the struct file instance */
- /* bf = filep->f_priv; */
-
- /* Recover the file system state from the inode */
-
- bm = filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
-
- /* Since open is not yet supported, neither is reading */
-
- return -ENOSYS;
+ return 0;
}
/****************************************************************************
@@ -273,25 +202,54 @@ static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen)
static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
- struct binfs_state_s *bm;
+ int ret;
fvdbg("cmd: %d arg: %08lx\n", cmd, arg);
- /* Sanity checks */
+ /* Only one IOCTL command is supported */
- DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
+ if (cmd == FIOC_FILENAME)
+ {
+ /* IN: FAR char const ** pointer
+ * OUT: Pointer to a persistent file name (Guaranteed to persist while
+ * the file is open).
+ */
- /* Recover the open file state from the struct file instance */
- /* bf = filep->f_priv; */
+ FAR const char **ptr = (FAR const char **)((uintptr_t)arg);
+ if (ptr == NULL)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ *ptr = g_builtins[(int)filep->f_priv].name;
+ ret = OK;
+ }
+ }
+ else
+ {
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
- /* Recover the file system state from the inode */
+/****************************************************************************
+ * Name: binfs_dup
+ *
+ * Description:
+ * Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
- bm = filep->f_inode->i_private;
- DEBUGASSERT(bm != NULL);
+static int binfs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ fvdbg("Dup %p->%p\n", oldp, newp);
- /* No ioctl commands yet supported */
+ /* Copy the index from the old to the new file structure */
- return -ENOTTY;
+ newp->f_priv = oldp->f_priv;
+ return OK;
}
/****************************************************************************
@@ -305,36 +263,19 @@ static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
static int binfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir)
{
- struct binfs_state_s *bm;
- int ret;
-
fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
-
- /* Recover the file system state from the inode instance */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* The requested directory must be the volume-relative "root" directory */
if (relpath && relpath[0] != '\0')
{
- ret = -ENOENT;
- goto errout_with_semaphore;
+ return -ENOENT;
}
/* Set the index to the first entry */
dir->u.binfs.fb_index = 0;
- ret = OK;
-
-errout_with_semaphore:
- binfs_semgive(bm);
- return ret;
+ return OK;
}
/****************************************************************************
@@ -346,23 +287,13 @@ errout_with_semaphore:
static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
- struct binfs_state_s *bm;
unsigned int index;
int ret;
- /* Sanity checks */
-
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
-
- /* Recover the file system state from the inode instance */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* Have we reached the end of the directory */
index = dir->u.binfs.fb_index;
- if (namedapps[index].name == NULL)
+ if (g_builtins[index].name == NULL)
{
/* We signal the end of the directory by returning the
* special error -ENOENT
@@ -375,9 +306,9 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
{
/* Save the filename and file type */
- fvdbg("Entry %d: \"%s\"\n", index, namedapps[index].name);
+ fvdbg("Entry %d: \"%s\"\n", index, g_builtins[index].name);
dir->fd_dir.d_type = DTYPE_FILE;
- strncpy(dir->fd_dir.d_name, namedapps[index].name, NAME_MAX+1);
+ strncpy(dir->fd_dir.d_name, g_builtins[index].name, NAME_MAX+1);
/* The application list is terminated by an entry with a NULL name.
* Therefore, there is at least one more entry in the list.
@@ -389,11 +320,10 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
* standard f_pos instead of our own private fb_index.
*/
- dir->u.binfs.fb_index = index;
- ret = OK;
+ dir->u.binfs.fb_index = index;
+ ret = OK;
}
- binfs_semgive(bm);
return ret;
}
@@ -406,22 +336,9 @@ static int binfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
{
- struct binfs_state_s *bm;
-
fvdbg("Entry\n");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
-
- /* Recover the file system state from the inode instance */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
- dir->u.binfs.fb_index = 0;
-
- binfs_semgive(bm);
+ dir->u.binfs.fb_index = 0;
return OK;
}
@@ -439,29 +356,7 @@ static int binfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
static int binfs_bind(FAR struct inode *blkdriver, const void *data,
void **handle)
{
- struct binfs_state_s *bm;
-
fvdbg("Entry\n");
-
- /* Create an instance of the mountpt state structure */
-
- bm = (struct binfs_state_s *)zalloc(sizeof(struct binfs_state_s));
- if (!bm)
- {
- fdbg("Failed to allocate mountpoint structure\n");
- return -ENOMEM;
- }
-
- /* Initialize the allocated mountpt state structure. The filesystem is
- * responsible for one reference ont the blkdriver inode and does not
- * have to addref() here (but does have to release in ubind().
- */
-
- sem_init(&bm->bm_sem, 0, 1); /* Initialize the semaphore that controls access */
-
- /* Mounted! */
-
- *handle = (void*)bm;
return OK;
}
@@ -475,22 +370,7 @@ static int binfs_bind(FAR struct inode *blkdriver, const void *data,
static int binfs_unbind(void *handle, FAR struct inode **blkdriver)
{
- struct binfs_state_s *bm = (struct binfs_state_s*)handle;
-
fvdbg("Entry\n");
-
-#ifdef CONFIG_DEBUG
- if (!bm)
- {
- return -EINVAL;
- }
-#endif
-
- /* Check if there are sill any files opened on the filesystem. */
-
- /* Release the mountpoint private data */
-
- sem_destroy(&bm->bm_sem);
return OK;
}
@@ -503,19 +383,8 @@ static int binfs_unbind(void *handle, FAR struct inode **blkdriver)
static int binfs_statfs(struct inode *mountpt, struct statfs *buf)
{
- struct binfs_state_s *bm;
-
fvdbg("Entry\n");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt && mountpt->i_private);
-
- /* Get the mountpoint private data from the inode structure */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* Fill in the statfs info */
memset(buf, 0, sizeof(struct statfs));
@@ -525,8 +394,6 @@ static int binfs_statfs(struct inode *mountpt, struct statfs *buf)
buf->f_bfree = 0;
buf->f_bavail = 0;
buf->f_namelen = NAME_MAX;
-
- binfs_semgive(bm);
return OK;
}
@@ -539,30 +406,17 @@ static int binfs_statfs(struct inode *mountpt, struct statfs *buf)
static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf)
{
- struct binfs_state_s *bm;
- int ret;
-
fvdbg("Entry\n");
- /* Sanity checks */
-
- DEBUGASSERT(mountpt && mountpt->i_private);
-
- /* Get the mountpoint private data from the inode structure */
-
- bm = mountpt->i_private;
- binfs_semtake(bm);
-
/* The requested directory must be the volume-relative "root" directory */
if (relpath && relpath[0] != '\0')
{
/* Check if there is a file with this name. */
- if (namedapp_isavail(relpath) < 0)
+ if (builtin_isavail(relpath) < 0)
{
- ret = -ENOENT;
- goto errout_with_semaphore;
+ return -ENOENT;
}
/* It's a execute-only file name */
@@ -578,19 +432,15 @@ static int binfs_stat(struct inode *mountpt, const char *relpath, struct stat *b
/* File/directory size, access block size */
- buf->st_size = 0;
- buf->st_blksize = 0;
- buf->st_blocks = 0;
- ret = OK;
-
-errout_with_semaphore:
- binfs_semgive(bm);
- return ret;
+ buf->st_size = 0;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
-#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_APPS_BINDIR */
+#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_BINFS */
diff --git a/nuttx/fs/fat/Make.defs b/nuttx/fs/fat/Make.defs
index 136302b86..2769ab602 100644
--- a/nuttx/fs/fat/Make.defs
+++ b/nuttx/fs/fat/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# Make.defs
#
-# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2008, 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,10 @@ CSRCS += fs_fat32.c fs_fat32dirent.c fs_fat32attrib.c fs_fat32util.c
ASRCS +=
CSRCS += fs_mkfatfs.c fs_configfat.c fs_writefat.c
-# Argument for dependency checking
+# Include FAT build support
+
+DEPPATH += --dep-path fat
+VPATH += :fat
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)fat}
-FATDEPPATH = --dep-path fat
endif
diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c
index 0c28cea67..c10c28a5c 100644
--- a/nuttx/fs/fat/fs_fat32.c
+++ b/nuttx/fs/fat/fs_fat32.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fat/fs_fat32.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
@@ -86,7 +86,9 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer,
size_t buflen);
static off_t fat_seek(FAR struct file *filep, off_t offset, int whence);
static int fat_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+
static int fat_sync(FAR struct file *filep);
+static int fat_dup(FAR const struct file *oldp, FAR struct file *newp);
static int fat_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
@@ -121,28 +123,30 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat
const struct mountpt_operations fat_operations =
{
- fat_open,
- fat_close,
- fat_read,
- fat_write,
- fat_seek,
- fat_ioctl,
- fat_sync,
-
- fat_opendir,
- NULL,
- fat_readdir,
- fat_rewinddir,
-
- fat_bind,
- fat_unbind,
- fat_statfs,
-
- fat_unlink,
- fat_mkdir,
- fat_rmdir,
- fat_rename,
- fat_stat
+ fat_open, /* open */
+ fat_close, /* close */
+ fat_read, /* read */
+ fat_write, /* write */
+ fat_seek, /* seek */
+ fat_ioctl, /* ioctl */
+
+ fat_sync, /* sync */
+ fat_dup, /* dup */
+
+ fat_opendir, /* opendir */
+ NULL, /* closedir */
+ fat_readdir, /* readdir */
+ fat_rewinddir, /* rewinddir */
+
+ fat_bind, /* bind */
+ fat_unbind, /* unbind */
+ fat_statfs, /* statfs */
+
+ fat_unlink, /* unlinke */
+ fat_mkdir, /* mkdir */
+ fat_rmdir, /* rmdir */
+ fat_rename, /* rename */
+ fat_stat /* stat */
};
/****************************************************************************
@@ -311,7 +315,6 @@ static int fat_open(FAR struct file *filep, const char *relpath,
/* Initialize the file private data (only need to initialize non-zero elements) */
- ff->ff_open = true;
ff->ff_oflags = oflags;
/* Save information that can be used later to recover the directory entry */
@@ -896,6 +899,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence)
DEBUGASSERT(fs != NULL);
/* Map the offset according to the whence option */
+
switch (whence)
{
case SEEK_SET: /* The offset is set to offset bytes. */
@@ -969,6 +973,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence)
ret = cluster;
goto errout_with_semaphore;
}
+
ff->ff_startcluster = cluster;
}
@@ -1231,6 +1236,124 @@ errout_with_semaphore:
}
/****************************************************************************
+ * Name: fat_dup
+ *
+ * Description: Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+static int fat_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ FAR struct fat_mountpt_s *fs;
+ FAR struct fat_file_s *oldff;
+ FAR struct fat_file_s *newff;
+ int ret;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(oldp->f_priv != NULL &&
+ newp->f_priv == NULL &&
+ newp->f_inode != NULL);
+
+ /* Recover our private data from the struct file instance */
+
+ fs = (struct fat_mountpt_s *)oldp->f_inode->i_private;
+ DEBUGASSERT(fs != NULL);
+
+ /* Check if the mount is still healthy */
+
+ fat_semtake(fs);
+ ret = fat_checkmount(fs);
+ if (ret != OK)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Recover the old private data from the old struct file instance */
+
+ oldff = oldp->f_priv;
+
+ /* Create a new instance of the file private date to describe the
+ * dup'ed file.
+ */
+
+ newff = (struct fat_file_s *)kmalloc(sizeof(struct fat_file_s));
+ if (!newff)
+ {
+ ret = -ENOMEM;
+ goto errout_with_semaphore;
+ }
+
+ /* Create a file buffer to support partial sector accesses */
+
+ newff->ff_buffer = (uint8_t*)fat_io_alloc(fs->fs_hwsectorsize);
+ if (!newff->ff_buffer)
+ {
+ ret = -ENOMEM;
+ goto errout_with_struct;
+ }
+
+ /* Copy the rest of the open open file state from the old file structure.
+ * There are some assumptions and potential issues here:
+ *
+ * 1) We assume that the higher level logic has copied the elements of
+ * the file structure, in particular, the file position.
+ * 2) There is a problem with ff_size if there are multiple opened
+ * file structures, each believing they know the size of the file.
+ * If one instance modifies the file length, then the new size of
+ * the opened file will be unknown to the other. That is a lurking
+ * bug!
+ *
+ * One good solution to this might be to add a refernce count to the
+ * file structure. Then, instead of dup'ing the whole structure
+ * as is done here, just increment the reference count on the
+ * structure. The would have to be integrated with open logic as
+ * well, however, so that the same file structure is re-used if the
+ * file is re-opened.
+ */
+
+ newff->ff_bflags = 0; /* File buffer flags */
+ newff->ff_oflags = oldff->ff_oflags; /* File open flags */
+ newff->ff_sectorsincluster = oldff->ff_sectorsincluster; /* Sectors remaining in cluster */
+ newff->ff_dirindex = oldff->ff_dirindex; /* Index to directory entry */
+ newff->ff_currentcluster = oldff->ff_currentcluster; /* Current cluster */
+ newff->ff_dirsector = oldff->ff_dirsector; /* Sector containing directory entry */
+ newff->ff_size = oldff->ff_size; /* Size of the file */
+ newff->ff_startcluster = oldff->ff_startcluster; /* Start cluster of file on media */
+ newff->ff_currentsector = oldff->ff_currentsector; /* Current sector */
+ newff->ff_cachesector = 0; /* Sector in file buffer */
+
+ /* Attach the private date to the struct file instance */
+
+ newp->f_priv = newff;
+
+ /* Then insert the new instance into the mountpoint structure.
+ * It needs to be there (1) to handle error conditions that effect
+ * all files, and (2) to inform the umount logic that we are busy
+ * (but a simple reference count could have done that).
+ */
+
+ newff->ff_next = fs->fs_head;
+ fs->fs_head = newff->ff_next;
+
+ fat_semgive(fs);
+ return OK;
+
+ /* Error exits -- goto's are nasty things, but they sure can make error
+ * handling a lot simpler.
+ */
+
+errout_with_struct:
+ kfree(newff);
+
+errout_with_semaphore:
+ fat_semgive(fs);
+ return ret;
+}
+
+/****************************************************************************
* Name: fat_opendir
*
* Description: Open a directory for read access
diff --git a/nuttx/fs/fat/fs_fat32.h b/nuttx/fs/fat/fs_fat32.h
index 71a21333b..81f3f4675 100644
--- a/nuttx/fs/fat/fs_fat32.h
+++ b/nuttx/fs/fat/fs_fat32.h
@@ -752,7 +752,6 @@ struct fat_mountpt_s
struct fat_file_s
{
struct fat_file_s *ff_next; /* Retained in a singly linked list */
- bool ff_open; /* true: The file is (still) open */
uint8_t ff_bflags; /* The file buffer flags */
uint8_t ff_oflags; /* Flags provided when file was opened */
uint8_t ff_sectorsincluster; /* Sectors remaining in cluster */
diff --git a/nuttx/fs/fat/fs_fat32util.c b/nuttx/fs/fat/fs_fat32util.c
index 7231456d7..9aa1d3992 100644
--- a/nuttx/fs/fat/fs_fat32util.c
+++ b/nuttx/fs/fat/fs_fat32util.c
@@ -692,8 +692,6 @@ int fat_checkmount(struct fat_mountpt_s *fs)
if (fs && fs->fs_mounted)
{
- struct fat_file_s *file;
-
/* We still think the mount is healthy. Check an see if this is
* still the case
*/
@@ -715,14 +713,8 @@ int fat_checkmount(struct fat_mountpt_s *fs)
/* If we get here, the mount is NOT healthy */
fs->fs_mounted = false;
-
- /* Make sure that this is flagged in every opened file */
-
- for (file = fs->fs_head; file; file = file->ff_next)
- {
- file->ff_open = false;
- }
}
+
return -ENODEV;
}
diff --git a/nuttx/fs/fs_files.c b/nuttx/fs/fs_files.c
index 4da2d28a5..06addb1ef 100644
--- a/nuttx/fs/fs_files.c
+++ b/nuttx/fs/fs_files.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_files.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -284,14 +284,6 @@ int files_dup(FAR struct file *filep1, FAR struct file *filep2)
goto errout;
}
-#ifndef CONFIG_DISABLE_MOUNTPOINT
- if (INODE_IS_MOUNTPT(filep1->f_inode))
- {
- err = ENOSYS; /* Not yet supported */
- goto errout;
- }
-#endif
-
list = sched_getfiles();
if (!list)
{
@@ -331,18 +323,16 @@ int files_dup(FAR struct file *filep1, FAR struct file *filep2)
if (inode->u.i_ops && inode->u.i_ops->open)
{
#ifndef CONFIG_DISABLE_MOUNTPOINT
-#if 0 /* Not implemented */
if (INODE_IS_MOUNTPT(inode))
{
- /* Open a file on the mountpoint */
+ /* Dup the open file on the in the new file structure */
- ret = inode->u.i_mops->open(filep2, ?, filep2->f_oflags, ?);
+ ret = inode->u.i_mops->dup(filep1, filep2);
}
else
#endif
-#endif
{
- /* Open the pseudo file or device driver */
+ /* (Re-)open the pseudo file or device driver */
ret = inode->u.i_ops->open(filep2);
}
diff --git a/nuttx/fs/fs_mount.c b/nuttx/fs/fs_mount.c
index 228c1fc6e..a91e7d366 100644
--- a/nuttx/fs/fs_mount.c
+++ b/nuttx/fs/fs_mount.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_mount.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -47,10 +47,6 @@
#include <nuttx/fs/fs.h>
-#ifdef CONFIG_APPS_BINDIR
-# include <apps/apps.h>
-#endif
-
#include "fs_internal.h"
/* At least one filesystem must be defined, or this file will not compile.
@@ -78,7 +74,7 @@
/* These file systems do not require block drivers */
-#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) || defined(CONFIG_NFS)
+#if defined(CONFIG_FS_NXFFS) || defined(CONFIG_FS_BINFS) || defined(CONFIG_NFS)
# define NONBDFS_SUPPORT
#endif
@@ -123,6 +119,9 @@ extern const struct mountpt_operations nxffs_operations;
#ifdef CONFIG_NFS
extern const struct mountpt_operations nfs_operations;
#endif
+#ifdef CONFIG_FS_BINFS
+extern const struct mountpt_operations binfs_operations;
+#endif
static const struct fsmap_t g_nonbdfsmap[] =
{
@@ -132,7 +131,7 @@ static const struct fsmap_t g_nonbdfsmap[] =
#ifdef CONFIG_NFS
{ "nfs", &nfs_operations },
#endif
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
{ "binfs", &binfs_operations },
#endif
{ NULL, NULL },
@@ -222,7 +221,7 @@ int mount(FAR const char *source, FAR const char *target,
/* Find the specified filesystem. Try the block driver file systems first */
#ifdef BDFS_SUPPORT
- if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
+ if (source && (mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
{
/* Make sure that a block driver argument was provided */
diff --git a/nuttx/fs/mmap/Make.defs b/nuttx/fs/mmap/Make.defs
index 59857fe9c..b85d9f60f 100644
--- a/nuttx/fs/mmap/Make.defs
+++ b/nuttx/fs/mmap/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# fs/mmap/Make.defs
#
-# Copyright (C) 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -40,4 +40,9 @@ ifeq ($(CONFIG_FS_RAMMAP),y)
CSRCS += fs_munmap.c fs_rammap.c
endif
-MMAPDEPPATH = --dep-path mmap
+# Include MMAP build support
+
+DEPPATH += --dep-path mmap
+VPATH += :mmap
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)mmap}
+
diff --git a/nuttx/fs/nfs/Make.defs b/nuttx/fs/nfs/Make.defs
index fc4682f85..ec2177fcf 100644
--- a/nuttx/fs/nfs/Make.defs
+++ b/nuttx/fs/nfs/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# Make.defs
#
-# Copyright (C) 2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,10 @@ CSRCS +=
ASRCS +=
CSRCS += rpc_clnt.c nfs_util.c nfs_vfsops.c
-# Argument for dependency checking
+# Include NFS build support
+
+DEPPATH += --dep-path nfs
+VPATH += :nfs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)nfs}
-NFSDEPPATH = --dep-path nfs
endif
diff --git a/nuttx/fs/nfs/nfs_node.h b/nuttx/fs/nfs/nfs_node.h
index 4ae9e162c..408bd1993 100644
--- a/nuttx/fs/nfs/nfs_node.h
+++ b/nuttx/fs/nfs/nfs_node.h
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_node.h
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -70,6 +70,7 @@
struct nfsnode
{
struct nfsnode *n_next; /* Retained in a singly linked list. */
+ uint8_t n_crefs; /* Reference count (for nfs_dup) */
uint8_t n_type; /* File type */
uint8_t n_fhsize; /* Size in bytes of the file handle */
uint8_t n_flags; /* Node flags */
diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c
index 73fda72a7..e7d28b3d7 100644
--- a/nuttx/fs/nfs/nfs_util.c
+++ b/nuttx/fs/nfs/nfs_util.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_util.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -213,7 +213,6 @@ int nfs_request(struct nfsmount *nmp, int procnum,
{
struct rpcclnt *clnt = nmp->nm_rpcclnt;
struct nfs_reply_header replyh;
- int trylater_delay;
int error;
tryagain:
@@ -250,12 +249,6 @@ tryagain:
if (error == EAGAIN)
{
error = 0;
- trylater_delay *= NFS_TIMEOUTMUL;
- if (trylater_delay > NFS_MAXTIMEO)
- {
- trylater_delay = NFS_MAXTIMEO;
- }
-
goto tryagain;
}
diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c
index 3cd5a47dc..2ff4ff9d3 100644
--- a/nuttx/fs/nfs/nfs_vfsops.c
+++ b/nuttx/fs/nfs/nfs_vfsops.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_vfsops.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -133,6 +133,7 @@ static int nfs_close(FAR struct file *filep);
static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
size_t buflen);
+static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int nfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
@@ -166,7 +167,9 @@ const struct mountpt_operations nfs_operations =
nfs_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
+
NULL, /* sync */
+ nfs_dup, /* dup */
nfs_opendir, /* opendir */
NULL, /* closedir */
@@ -357,7 +360,7 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
/* Save the attributes in the file data structure */
- tmp = *ptr++; /* handle_follows */
+ tmp = *ptr; /* handle_follows */
if (!tmp)
{
fdbg("WARNING: no file attributes\n");
@@ -367,7 +370,6 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np,
/* Initialize the file attributes */
nfs_attrupdate(np, (FAR struct nfs_fattr *)ptr);
- ptr += uint32_increment(sizeof(struct nfs_fattr));
}
/* Any following dir_wcc data is ignored for now */
@@ -410,7 +412,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
reqlen += (int)np->n_fhsize;
ptr += uint32_increment(np->n_fhsize);
- /* Copy the variable-length attribtes */
+ /* Copy the variable-length attributes */
*ptr++ = nfs_false; /* Don't change mode */
*ptr++ = nfs_false; /* Don't change uid */
@@ -421,7 +423,7 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp, struct nfsnode *np)
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
*ptr++ = nfs_false; /* No guard value */
- reqlen += 9*sizeof(uint32_t)
+ reqlen += 9 * sizeof(uint32_t);
/* Perform the SETATTR RPC */
@@ -551,9 +553,9 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np,
static int nfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode)
{
- struct nfsmount *nmp;
- struct nfsnode *np = NULL;
- int error;
+ struct nfsmount *nmp;
+ struct nfsnode *np;
+ int error;
/* Sanity checks */
@@ -632,6 +634,8 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath,
* non-zero elements)
*/
+ np->n_crefs = 1;
+
/* Attach the private data to the struct file instance */
filep->f_priv = np;
@@ -654,6 +658,7 @@ errout_with_semaphore:
{
kfree(np);
}
+
nfs_semgive(nmp);
return -error;
}
@@ -675,6 +680,7 @@ static int nfs_close(FAR struct file *filep)
FAR struct nfsnode *np;
FAR struct nfsnode *prev;
FAR struct nfsnode *curr;
+ int ret;
/* Sanity checks */
@@ -691,42 +697,64 @@ static int nfs_close(FAR struct file *filep)
nfs_semtake(nmp);
- /* Find our file structure in the list of file structures containted in the
- * mount structure.
+ /* Decrement the reference count. If the reference count would not
+ * decrement to zero, then that is all we have to do.
*/
- for (prev = NULL, curr = nmp->nm_head; curr; prev = curr, curr = curr->n_next)
- {
- /* Check if this node is ours */
+ if (np->n_crefs > 1)
+ {
+ np->n_crefs--;
+ ret = OK;
+ }
- if (np == curr)
- {
- /* Yes.. remove it from the list of file structures */
+ /* There are no more references to the file structure. Now we need to
+ * free up all resources associated with the open file.
+ *
+ * First, find our file structure in the list of file structures
+ * containted in the mount structure.
+ */
+
+ else
+ {
+ /* Assume file structure will not be found. This should never happen. */
+
+ ret = -EINVAL;
+
+ for (prev = NULL, curr = nmp->nm_head;
+ curr;
+ prev = curr, curr = curr->n_next)
+ {
+ /* Check if this node is ours */
- if (prev)
- {
- /* Remove from mid-list */
+ if (np == curr)
+ {
+ /* Yes.. remove it from the list of file structures */
- prev->n_next = np->n_next;
- }
- else
- {
- /* Remove from the head of the list */
+ if (prev)
+ {
+ /* Remove from mid-list */
- nmp->nm_head = np->n_next;
- }
+ prev->n_next = np->n_next;
+ }
+ else
+ {
+ /* Remove from the head of the list */
- /* Then deallocate the file structure and return success */
+ nmp->nm_head = np->n_next;
+ }
- kfree(np);
- nfs_semgive(nmp);
- return OK;
- }
- }
+ /* Then deallocate the file structure and return success */
- fdbg("ERROR: file structure not found in list: %p\n", np);
+ kfree(np);
+ ret = OK;
+ break;
+ }
+ }
+ }
+
+ filep->f_priv = NULL;
nfs_semgive(nmp);
- return EINVAL;
+ return ret;
}
/****************************************************************************
@@ -757,8 +785,8 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen)
/* Recover our private data from the struct file instance */
- nmp = (struct nfsmount*) filep->f_inode->i_private;
- np = (struct nfsnode*) filep->f_priv;
+ nmp = (struct nfsmount*)filep->f_inode->i_private;
+ np = (struct nfsnode*)filep->f_priv;
DEBUGASSERT(nmp != NULL);
@@ -1092,6 +1120,66 @@ errout_with_semaphore:
}
/****************************************************************************
+ * Name: binfs_dup
+ *
+ * Description:
+ * Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ struct nfsmount *nmp;
+ FAR struct nfsnode *np;
+ int error;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(oldp->f_priv != NULL && oldp->f_inode != NULL);
+
+ /* Recover our private data from the struct file instance */
+
+ nmp = (struct nfsmount*)oldp->f_inode->i_private;
+ np = (struct nfsnode*)oldp->f_priv;
+
+ DEBUGASSERT(nmp != NULL);
+
+ /* Check if the mount is still healthy */
+
+ nfs_semtake(nmp);
+ error = nfs_checkmount(nmp);
+ if (error != OK)
+ {
+ fdbg("ERROR: nfs_checkmount failed: %d\n", error);
+ nfs_semgive(nmp);
+ return -error;
+ }
+
+ /* Increment the reference count on the NFS node structure */
+
+ DEBUGASSERT(np->n_crefs < 0xff);
+ np->n_crefs++;
+
+ /* And save this as the file data for the new node */
+
+ newp->f_priv = np;
+
+ /* Then insert the new instance at the head of the list in the mountpoint
+ * tructure. It needs to be there (1) to handle error conditions that effect
+ * all files, and (2) to inform the umount logic that we are busy. We
+ * cannot unmount the file system if this list is not empty!
+ */
+
+ np->n_next = nmp->nm_head;
+ nmp->nm_head = np;
+
+ nfs_semgive(nmp);
+ return OK;
+}
+
+/****************************************************************************
* Name: nfs_opendir
*
* Description:
@@ -1754,12 +1842,15 @@ bad:
{
kfree(nmp->nm_so);
}
+
if (nmp->nm_rpcclnt)
{
kfree(nmp->nm_rpcclnt);
}
+
kfree(nmp);
}
+
return error;
}
diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c
index 0e2a394ba..9c2ada4f2 100644
--- a/nuttx/fs/nfs/rpc_clnt.c
+++ b/nuttx/fs/nfs/rpc_clnt.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/rpc_clnt.c
*
- * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -224,8 +224,6 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname,
static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
FAR void *reply, size_t resplen)
{
- FAR struct rpc_reply_header *replyheader;
- uint32_t rxid;
int error;
/* Get the next RPC reply from the socket */
@@ -235,22 +233,22 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
{
fdbg("ERROR: rpcclnt_receive returned: %d\n", error);
- /* If we failed because of a timeout, then try sending the CALL
- * message again.
- */
+ /* If we failed because of a timeout, then try sending the CALL
+ * message again.
+ */
- if (error == EAGAIN || error == ETIMEDOUT)
- {
- rpc->rc_timeout = true;
- }
- }
+ if (error == EAGAIN || error == ETIMEDOUT)
+ {
+ rpc->rc_timeout = true;
+ }
+ }
/* Get the xid and check that it is an RPC replysvr */
else
{
- replyheader = (FAR struct rpc_reply_header *)reply;
- rxid = replyheader->rp_xid;
+ FAR struct rpc_reply_header *replyheader =
+ (FAR struct rpc_reply_header *)reply;
if (replyheader->rp_direction != rpc_reply)
{
@@ -260,7 +258,7 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog,
}
}
- return OK;
+ return error;
}
/****************************************************************************
@@ -275,7 +273,6 @@ static uint32_t rpcclnt_newxid(void)
{
static uint32_t rpcclnt_xid = 0;
static uint32_t rpcclnt_xid_touched = 0;
- int xidp = 0;
srand(time(NULL));
if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0))
@@ -285,6 +282,7 @@ static uint32_t rpcclnt_newxid(void)
}
else
{
+ int xidp = 0;
do
{
xidp = rand();
diff --git a/nuttx/fs/nxffs/Make.defs b/nuttx/fs/nxffs/Make.defs
index b67ae4472..ccf1ba661 100644
--- a/nuttx/fs/nxffs/Make.defs
+++ b/nuttx/fs/nxffs/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# fs/nxffs/Make.defs
#
-# Copyright (C) 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,10 @@ CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c nxffs_dirent.c \
nxffs_open.c nxffs_pack.c nxffs_read.c nxffs_reformat.c \
nxffs_stat.c nxffs_unlink.c nxffs_util.c nxffs_write.c
-# Argument for dependency checking
+# Include NXFFS build support
+
+DEPPATH += --dep-path nxffs
+VPATH += :nxffs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)nxffs}
-NXFFSDEPPATH = --dep-path nxffs
endif
diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h
index 616dc7197..083e00fa7 100644
--- a/nuttx/fs/nxffs/nxffs.h
+++ b/nuttx/fs/nxffs/nxffs.h
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs.h
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -1044,6 +1044,7 @@ extern int nxffs_pack(FAR struct nxffs_volume_s *volume);
* - nxffs_read() is defined in nxffs_read.c
* - nxffs_write() is defined in nxffs_write.c
* - nxffs_ioctl() is defined in nxffs_ioctl.c
+ * - nxffs_dup() is defined in nxffs_open.c
* - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in
* nxffs_dirent.c
* - nxffs_bind() and nxffs_unbind() are defined in nxffs_initialize.c
@@ -1058,25 +1059,25 @@ struct fs_dirent_s;
struct statfs;
struct stat;
-extern int nxffs_open(FAR struct file *filep, FAR const char *relpath,
- int oflags, mode_t mode);
-extern int nxffs_close(FAR struct file *filep);
-extern ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer,
- size_t buflen);
-extern ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer,
- size_t buflen);
-extern int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
-extern int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
- FAR struct fs_dirent_s *dir);
-extern int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
-extern int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
-extern int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data,
- FAR void **handle);
-extern int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver);
-extern int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
-extern int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
- FAR struct stat *buf);
-extern int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
+int nxffs_open(FAR struct file *filep, FAR const char *relpath, int oflags,
+ mode_t mode);
+int nxffs_close(FAR struct file *filep);
+ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
+ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer,
+ size_t buflen);
+int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp);
+int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct fs_dirent_s *dir);
+int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
+int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
+int nxffs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
+int nxffs_unbind(FAR void *handle, FAR struct inode **blkdriver);
+int nxffs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
+int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf);
+int nxffs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
#endif /* __FS_NXFFS_NXFFS_H */
diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c
index 6d93a318a..4e7428c73 100644
--- a/nuttx/fs/nxffs/nxffs_initialize.c
+++ b/nuttx/fs/nxffs/nxffs_initialize.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs_initialize.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -82,7 +82,9 @@ const struct mountpt_operations nxffs_operations =
nxffs_write, /* write */
NULL, /* seek -- Use f_pos in struct file */
nxffs_ioctl, /* ioctl */
+
NULL, /* sync -- No buffered data */
+ nxffs_dup, /* dup */
nxffs_opendir, /* opendir */
NULL, /* closedir */
diff --git a/nuttx/fs/nxffs/nxffs_open.c b/nuttx/fs/nxffs/nxffs_open.c
index eb7817c57..9fa4ef2e0 100644
--- a/nuttx/fs/nxffs/nxffs_open.c
+++ b/nuttx/fs/nxffs/nxffs_open.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs_open.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -1023,7 +1023,7 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath,
#endif
/* Limitation: A file must be opened for reading or writing, but not both.
- * There is no general for extending the size of of a file. Extending the
+ * There is no general way of extending the size of a file. Extending the
* file size of possible if the file to be extended is the last in the
* sequence on FLASH, but since that case is not the general case, no file
* extension is supported.
@@ -1059,6 +1059,64 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath,
}
/****************************************************************************
+ * Name: binfs_dup
+ *
+ * Description:
+ * Duplicate open file data in the new file structure.
+ *
+ ****************************************************************************/
+
+int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+#ifdef CONFIG_DEBUG
+ FAR struct nxffs_volume_s *volume;
+#endif
+ FAR struct nxffs_ofile_s *ofile;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+#ifdef CONFIG_DEBUG
+ DEBUGASSERT(oldp->f_priv == NULL && oldp->f_inode != NULL);
+
+ /* Get the mountpoint private data from the NuttX inode reference in the
+ * file structure
+ */
+
+ volume = (FAR struct nxffs_volume_s*)oldp->f_inode->i_private;
+ DEBUGASSERT(volume != NULL);
+#endif
+
+ /* Recover the open file state from the struct file instance */
+
+ ofile = (FAR struct nxffs_ofile_s *)oldp->f_priv;
+
+ /* I do not think we need exclusive access to the volume to do this.
+ * The volume exclsem protects the open file list and, hence, would
+ * assure that the ofile is stable. However, it is assumed that the
+ * caller holds a value file descriptor associated with this ofile,
+ * so it should be stable throughout the life of this function.
+ */
+
+ /* Limitations: I do not think we have to be concerned about the
+ * usual NXFFS file limitations here: dup'ing cannot resulting
+ * in mixed reading and writing to the same file, or multiple
+ * writer to different file.
+ *
+ * I notice that nxffs_wropen will prohibit multiple opens for
+ * writing. But I do not thing that dup'ing a file already opened
+ * for writing suffers from any of these issues.
+ */
+
+ /* Just increment the reference count on the ofile */
+
+ ofile->crefs++;
+ newp->f_priv = (FAR void *)ofile;
+ return OK;
+}
+
+/****************************************************************************
* Name: nxffs_close
*
* Description:
@@ -1130,9 +1188,10 @@ int nxffs_close(FAR struct file *filep)
ofile->crefs--;
}
- filep->f_priv = NULL;
+ filep->f_priv = NULL;
sem_post(&volume->exclsem);
+
errout:
return ret;
}
diff --git a/nuttx/fs/romfs/Make.defs b/nuttx/fs/romfs/Make.defs
index 77de93c05..e87cbdf9e 100644
--- a/nuttx/fs/romfs/Make.defs
+++ b/nuttx/fs/romfs/Make.defs
@@ -1,7 +1,7 @@
############################################################################
# fs/romfs/Make.defs
#
-# Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
+# Copyright (C) 2008, 2011, 2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,10 @@ ifeq ($(CONFIG_FS_ROMFS),y)
ASRCS +=
CSRCS += fs_romfs.c fs_romfsutil.c
-# Argument for dependency checking
+# Include ROMFS build support
+
+DEPPATH += --dep-path romfs
+VPATH += :romfs
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)romfs}
-ROMFSDEPPATH = --dep-path romfs
endif
diff --git a/nuttx/fs/romfs/fs_romfs.c b/nuttx/fs/romfs/fs_romfs.c
index b95619d75..6a6fca355 100644
--- a/nuttx/fs/romfs/fs_romfs.c
+++ b/nuttx/fs/romfs/fs_romfs.c
@@ -56,6 +56,7 @@
#include <errno.h>
#include <debug.h>
+#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/fs/dirent.h>
@@ -70,24 +71,33 @@
* Private Function Prototypes
****************************************************************************/
-static int romfs_open(FAR struct file *filep, const char *relpath,
+static int romfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int romfs_close(FAR struct file *filep);
-static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen);
+static ssize_t romfs_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence);
-static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int romfs_ioctl(FAR struct file *filep, int cmd,
+ unsigned long arg);
-static int romfs_opendir(struct inode *mountpt, const char *relpath,
- struct fs_dirent_s *dir);
-static int romfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
-static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir);
+static int romfs_dup(FAR const struct file *oldp, FAR struct file *newp);
-static int romfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle);
-static int romfs_unbind(void *handle, FAR struct inode **blkdriver);
-static int romfs_statfs(struct inode *mountpt, struct statfs *buf);
+static int romfs_opendir(FAR struct inode *mountpt,
+ FAR const char *relpath,
+ FAR struct fs_dirent_s *dir);
+static int romfs_readdir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
+static int romfs_rewinddir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir);
-static int romfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf);
+static int romfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle);
+static int romfs_unbind(FAR void *handle, FAR struct inode **blkdriver);
+static int romfs_statfs(FAR struct inode *mountpt,
+ FAR struct statfs *buf);
+
+static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf);
/****************************************************************************
* Private Variables
@@ -110,7 +120,9 @@ const struct mountpt_operations romfs_operations =
NULL, /* write */
romfs_seek, /* seek */
romfs_ioctl, /* ioctl */
+
NULL, /* sync */
+ romfs_dup, /* dup */
romfs_opendir, /* opendir */
NULL, /* closedir */
@@ -136,13 +148,13 @@ const struct mountpt_operations romfs_operations =
* Name: romfs_open
****************************************************************************/
-static int romfs_open(FAR struct file *filep, const char *relpath,
- int oflags, mode_t mode)
+static int romfs_open(FAR struct file *filep, FAR const char *relpath,
+ int oflags, mode_t mode)
{
- struct romfs_dirinfo_s dirinfo;
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- int ret;
+ struct romfs_dirinfo_s dirinfo;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ int ret;
fvdbg("Open '%s'\n", relpath);
@@ -150,11 +162,11 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
- /* mountpoint private data from the inode reference from the file
+ /* Get mountpoint private data from the inode reference from the file
* structure
*/
- rm = (struct romfs_mountpt_s*)filep->f_inode->i_private;
+ rm = (FAR struct romfs_mountpt_s*)filep->f_inode->i_private;
DEBUGASSERT(rm != NULL);
@@ -214,7 +226,7 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
* file.
*/
- rf = (struct romfs_file_s *)zalloc(sizeof(struct romfs_file_s));
+ rf = (FAR struct romfs_file_s *)kzalloc(sizeof(struct romfs_file_s));
if (!rf)
{
fdbg("Failed to allocate private data\n", ret);
@@ -226,8 +238,7 @@ static int romfs_open(FAR struct file *filep, const char *relpath,
* non-zero elements)
*/
- rf->rf_open = true;
- rf->rf_size = dirinfo.rd_size;
+ rf->rf_size = dirinfo.rd_size;
/* Get the start of the file data */
@@ -277,9 +288,9 @@ errout_with_semaphore:
static int romfs_close(FAR struct file *filep)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- int ret = OK;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ int ret = OK;
fvdbg("Closing\n");
@@ -307,12 +318,12 @@ static int romfs_close(FAR struct file *filep)
if (!rm->rm_xipbase && rf->rf_buffer)
{
- free(rf->rf_buffer);
+ kfree(rf->rf_buffer);
}
/* Then free the file structure itself. */
- free(rf);
+ kfree(rf);
filep->f_priv = NULL;
return ret;
}
@@ -321,19 +332,20 @@ static int romfs_close(FAR struct file *filep)
* Name: romfs_read
****************************************************************************/
-static ssize_t romfs_read(FAR struct file *filep, char *buffer, size_t buflen)
+static ssize_t romfs_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- unsigned int bytesread;
- unsigned int readsize;
- unsigned int nsectors;
- uint32_t offset;
- size_t bytesleft;
- off_t sector;
- uint8_t *userbuffer = (uint8_t*)buffer;
- int sectorndx;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ unsigned int bytesread;
+ unsigned int readsize;
+ unsigned int nsectors;
+ uint32_t offset;
+ size_t bytesleft;
+ off_t sector;
+ FAR uint8_t *userbuffer = (FAR uint8_t*)buffer;
+ int sectorndx;
+ int ret;
fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos);
@@ -467,10 +479,10 @@ errout_with_semaphore:
static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- off_t position;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ off_t position;
+ int ret;
fvdbg("Seek to offset: %d whence: %d\n", offset, whence);
@@ -548,9 +560,9 @@ errout_with_semaphore:
static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
- struct romfs_mountpt_s *rm;
- struct romfs_file_s *rf;
- FAR void **ppv = (FAR void**)arg;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *rf;
+ FAR void **ppv = (FAR void**)arg;
fvdbg("cmd: %d arg: %08lx\n", cmd, arg);
@@ -582,6 +594,95 @@ static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
/****************************************************************************
+ * Name: romfs_dup
+ ****************************************************************************/
+
+static int romfs_dup(FAR const struct file *oldp, FAR struct file *newp)
+{
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_file_s *oldrf;
+ FAR struct romfs_file_s *newrf;
+ int ret;
+
+ fvdbg("Dup %p->%p\n", oldp, newp);
+
+ /* Sanity checks */
+
+ DEBUGASSERT(oldp->f_priv != NULL &&
+ newp->f_priv == NULL &&
+ newp->f_inode != NULL);
+
+ /* Get mountpoint private data from the inode reference from the file
+ * structure
+ */
+
+ rm = (FAR struct romfs_mountpt_s*)newp->f_inode->i_private;
+ DEBUGASSERT(rm != NULL);
+
+ /* Check if the mount is still healthy */
+
+ romfs_semtake(rm);
+ ret = romfs_checkmount(rm);
+ if (ret != OK)
+ {
+ fdbg("romfs_checkmount failed: %d\n", ret);
+ goto errout_with_semaphore;
+ }
+
+ /* Recover the old private data from the old struct file instance */
+
+ oldrf = oldp->f_priv;
+
+ /* Create an new instance of the file private data to describe the new
+ * dup'ed file.
+ */
+
+ newrf = (FAR struct romfs_file_s *)kmalloc(sizeof(struct romfs_file_s));
+ if (!newrf)
+ {
+ fdbg("Failed to allocate private data\n", ret);
+ ret = -ENOMEM;
+ goto errout_with_semaphore;
+ }
+
+ /* Copy all file private data (except for the buffer) */
+
+ newrf->rf_startoffset = oldrf->rf_startoffset;
+ newrf->rf_size = oldrf->rf_size;
+
+ /* Configure buffering to support access to this file */
+
+ ret = romfs_fileconfigure(rm, newrf);
+ if (ret < 0)
+ {
+ fdbg("Failed configure buffering: %d\n", ret);
+ goto errout_with_semaphore;
+ }
+
+ /* Attach the new private date to the new struct file instance */
+
+ newp->f_priv = newrf;
+
+ /* Then insert the new instance into the mountpoint structure.
+ * It needs to be there (1) to handle error conditions that effect
+ * all files, and (2) to inform the umount logic that we are busy
+ * (but a simple reference count could have done that).
+ */
+
+ newrf->rf_next = rm->rm_head;
+ rm->rm_head = newrf->rf_next;
+
+ romfs_semgive(rm);
+ return OK;
+
+ /* Error exits */
+
+errout_with_semaphore:
+ romfs_semgive(rm);
+ return ret;
+}
+
+/****************************************************************************
* Name: romfs_opendir
*
* Description:
@@ -589,12 +690,12 @@ static int romfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
*
****************************************************************************/
-static int romfs_opendir(struct inode *mountpt, const char *relpath,
- struct fs_dirent_s *dir)
+static int romfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct fs_dirent_s *dir)
{
- struct romfs_mountpt_s *rm;
- struct romfs_dirinfo_s dirinfo;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_dirinfo_s dirinfo;
+ int ret;
fvdbg("relpath: '%s'\n", relpath);
@@ -654,14 +755,15 @@ errout_with_semaphore:
*
****************************************************************************/
-static int romfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
+static int romfs_readdir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir)
{
- struct romfs_mountpt_s *rm;
- uint32_t linkoffset;
- uint32_t next;
- uint32_t info;
- uint32_t size;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ uint32_t linkoffset;
+ uint32_t next;
+ uint32_t info;
+ uint32_t size;
+ int ret;
fvdbg("Entry\n");
@@ -749,9 +851,10 @@ errout_with_semaphore:
*
****************************************************************************/
-static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
+static int romfs_rewinddir(FAR struct inode *mountpt,
+ FAR struct fs_dirent_s *dir)
{
- struct romfs_mountpt_s *rm;
+ FAR struct romfs_mountpt_s *rm;
int ret;
fvdbg("Entry\n");
@@ -788,8 +891,8 @@ static int romfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir)
*
****************************************************************************/
-static int romfs_bind(FAR struct inode *blkdriver, const void *data,
- void **handle)
+static int romfs_bind(FAR struct inode *blkdriver, FAR const void *data,
+ FAR void **handle)
{
struct romfs_mountpt_s *rm;
int ret;
@@ -813,7 +916,7 @@ static int romfs_bind(FAR struct inode *blkdriver, const void *data,
/* Create an instance of the mountpt state structure */
- rm = (struct romfs_mountpt_s *)zalloc(sizeof(struct romfs_mountpt_s));
+ rm = (FAR struct romfs_mountpt_s *)kzalloc(sizeof(struct romfs_mountpt_s));
if (!rm)
{
fdbg("Failed to allocate mountpoint structure\n");
@@ -857,12 +960,12 @@ static int romfs_bind(FAR struct inode *blkdriver, const void *data,
errout_with_buffer:
if (!rm->rm_xipbase)
{
- free(rm->rm_buffer);
+ kfree(rm->rm_buffer);
}
errout_with_sem:
sem_destroy(&rm->rm_sem);
- free(rm);
+ kfree(rm);
return ret;
}
@@ -874,9 +977,9 @@ errout_with_sem:
*
****************************************************************************/
-static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
+static int romfs_unbind(FAR void *handle, FAR struct inode **blkdriver)
{
- struct romfs_mountpt_s *rm = (struct romfs_mountpt_s*)handle;
+ FAR struct romfs_mountpt_s *rm = (FAR struct romfs_mountpt_s*)handle;
int ret;
fvdbg("Entry\n");
@@ -929,11 +1032,11 @@ static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
if (!rm->rm_xipbase && rm->rm_buffer)
{
- free(rm->rm_buffer);
+ kfree(rm->rm_buffer);
}
sem_destroy(&rm->rm_sem);
- free(rm);
+ kfree(rm);
return OK;
}
@@ -948,10 +1051,10 @@ static int romfs_unbind(void *handle, FAR struct inode **blkdriver)
*
****************************************************************************/
-static int romfs_statfs(struct inode *mountpt, struct statfs *buf)
+static int romfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
{
- struct romfs_mountpt_s *rm;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ int ret;
fvdbg("Entry\n");
@@ -1004,11 +1107,12 @@ errout_with_semaphore:
*
****************************************************************************/
-static int romfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf)
+static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
+ FAR struct stat *buf)
{
- struct romfs_mountpt_s *rm;
- struct romfs_dirinfo_s dirinfo;
- int ret;
+ FAR struct romfs_mountpt_s *rm;
+ FAR struct romfs_dirinfo_s dirinfo;
+ int ret;
fvdbg("Entry\n");
diff --git a/nuttx/fs/romfs/fs_romfs.h b/nuttx/fs/romfs/fs_romfs.h
index 4081517fb..6a337d2c5 100644
--- a/nuttx/fs/romfs/fs_romfs.h
+++ b/nuttx/fs/romfs/fs_romfs.h
@@ -159,7 +159,6 @@ struct romfs_mountpt_s
struct romfs_file_s
{
struct romfs_file_s *rf_next; /* Retained in a singly linked list */
- bool rf_open; /* true: The file is (still) open */
uint32_t rf_startoffset; /* Offset to the start of the file data */
uint32_t rf_size; /* Size of the file in bytes */
uint32_t rf_cachesector; /* Current sector in the rf_buffer */
diff --git a/nuttx/fs/romfs/fs_romfsutil.c b/nuttx/fs/romfs/fs_romfsutil.c
index 6ea114b5e..4857fb6d3 100644
--- a/nuttx/fs/romfs/fs_romfsutil.c
+++ b/nuttx/fs/romfs/fs_romfsutil.c
@@ -613,7 +613,7 @@ int romfs_fsconfigure(struct romfs_mountpt_s *rm)
}
/****************************************************************************
- * Name: romfs_ffileconfigure
+ * Name: romfs_fileconfigure
*
* Desciption:
* This function is called as part of the ROMFS file open operation It
@@ -649,6 +649,7 @@ int romfs_fileconfigure(struct romfs_mountpt_s *rm, struct romfs_file_s *rf)
return -ENOMEM;
}
}
+
return OK;
}
@@ -663,7 +664,6 @@ int romfs_fileconfigure(struct romfs_mountpt_s *rm, struct romfs_file_s *rf)
int romfs_checkmount(struct romfs_mountpt_s *rm)
{
- struct romfs_file_s *file;
struct inode *inode;
struct geometry geo;
int ret;
@@ -692,14 +692,8 @@ int romfs_checkmount(struct romfs_mountpt_s *rm)
/* If we get here, the mount is NOT healthy */
rm->rm_mounted = false;
-
- /* Make sure that this is flagged in every opened file */
-
- for (file = rm->rm_head; file; file = file->rf_next)
- {
- file->rf_open = false;
- }
}
+
return -ENODEV;
}
diff --git a/nuttx/graphics/Kconfig b/nuttx/graphics/Kconfig
index 18b1e1ab9..b56a6cb5c 100644
--- a/nuttx/graphics/Kconfig
+++ b/nuttx/graphics/Kconfig
@@ -178,6 +178,12 @@ config NXFONTS_CHARBITS
The number of bits in the character set. Current options are only 7 and 8.
The default is 7.
+config NXFONT_MONO5X8
+ bool "Mono 5x8"
+ default n
+ ---help---
+ Tiny mono-spaced 5x8 font (font ID FONTID_MONO5X8 = 18)
+
config NXFONT_SANS17X22
bool "Sans 17x22"
default n
diff --git a/nuttx/graphics/Makefile b/nuttx/graphics/Makefile
index 238e14df4..aa402bfa4 100644
--- a/nuttx/graphics/Makefile
+++ b/nuttx/graphics/Makefile
@@ -124,6 +124,9 @@ gen32bppsources:
$(Q) $(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_BITSPERPIXEL=32 EXTRADEFINES=$(EXTRADEFINES)
genfontsources:
+ifeq ($(CONFIG_NXFONT_MONO5X8),y)
+ @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=18 EXTRADEFINES=$(EXTRADEFINES)
+endif
ifeq ($(CONFIG_NXFONT_SANS23X27),y)
$(Q) $(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=1 EXTRADEFINES=$(EXTRADEFINES)
endif
diff --git a/nuttx/graphics/nxfonts/Make.defs b/nuttx/graphics/nxfonts/Make.defs
index bc65d7ad7..def092825 100644
--- a/nuttx/graphics/nxfonts/Make.defs
+++ b/nuttx/graphics/nxfonts/Make.defs
@@ -42,6 +42,12 @@ NXFCONV_CSRCS = nxfonts_convert_1bpp.c nxfonts_convert_2bpp.c \
NXFSET_ASRCS =
NXFSET_CSRCS =
+# Monospace fonts
+
+ifeq ($(CONFIG_NXFONT_MONO5X8),y)
+NXFSET_CSRCS += nxfonts_bitmaps_mono5x8.c
+endif
+
# Sans serif fonts
ifeq ($(CONFIG_NXFONT_SANS17X22),y)
diff --git a/nuttx/graphics/nxfonts/Makefile.sources b/nuttx/graphics/nxfonts/Makefile.sources
index 76a099dcb..2e41fc704 100644
--- a/nuttx/graphics/nxfonts/Makefile.sources
+++ b/nuttx/graphics/nxfonts/Makefile.sources
@@ -72,6 +72,13 @@ endif
ifdef NXFONTS_FONTID
+# MONO
+
+ifeq ($(NXFONTS_FONTID),18)
+NXFONTS_PREFIX := g_mono5x8_
+GEN_CSRC = nxfonts_bitmaps_mono5x8.c
+endif
+
# SANS
ifeq ($(NXFONTS_FONTID),14)
diff --git a/nuttx/graphics/nxfonts/nxfonts_bitmaps.c b/nuttx/graphics/nxfonts/nxfonts_bitmaps.c
index 2efc34b87..b089ec038 100644
--- a/nuttx/graphics/nxfonts/nxfonts_bitmaps.c
+++ b/nuttx/graphics/nxfonts/nxfonts_bitmaps.c
@@ -80,6 +80,8 @@
# include "nxfonts_sans17x23b.h"
#elif NXFONTS_FONTID == 17
# include "nxfonts_sans20x27b.h"
+#elif NXFONTS_FONTID == 18
+# include "nxfonts_mono5x8.h"
#else
# error "No font ID specified"
#endif
diff --git a/nuttx/graphics/nxfonts/nxfonts_getfont.c b/nuttx/graphics/nxfonts/nxfonts_getfont.c
index 23e5c4474..c2af977f2 100644
--- a/nuttx/graphics/nxfonts/nxfonts_getfont.c
+++ b/nuttx/graphics/nxfonts/nxfonts_getfont.c
@@ -60,6 +60,12 @@
* Private Data
****************************************************************************/
+/* MONO */
+
+#ifdef CONFIG_NXFONT_MONO5X8
+extern const struct nx_fontpackage_s g_mono5x8_package;
+#endif
+
/* SANS */
#ifdef CONFIG_NXFONT_SANS17X22
@@ -139,6 +145,12 @@ extern const struct nx_fontpackage_s g_serif38x49b_package;
static FAR const struct nx_fontpackage_s *g_fontpackages[] =
{
+/* MONO */
+
+#ifdef CONFIG_NXFONT_MONO5X8
+ &g_mono5x8_package,
+#endif
+
/* SANS */
#ifdef CONFIG_NXFONT_SANS17X22
diff --git a/nuttx/graphics/nxfonts/nxfonts_mono5x8.h b/nuttx/graphics/nxfonts/nxfonts_mono5x8.h
new file mode 100644
index 000000000..739437e62
--- /dev/null
+++ b/nuttx/graphics/nxfonts/nxfonts_mono5x8.h
@@ -0,0 +1,815 @@
+/****************************************************************************
+ * graphics/nxfonts/nxfonts_mono5x8.h
+ *
+ * Copyright (C) 2011-2012 NX Engineering, S.A., All rights reserved.
+ * Author: Petteri Aimonen <jpa@nx.mail.kapsi.fi>
+ *
+ * Based on 5x8.pcf.gz from xfonts-base. The file is marked as
+ * COPYRIGHT "Public domain font. Share and enjoy."
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __GRAPHICS_NXFONTS_NXFONTS_MONO5X8_H
+#define __GRAPHICS_NXFONTS_NXFONTS_MONO5X8_H
+
+#define NXFONT_ID FONTID_MONO5X8
+
+#define NXFONT_MIN7BIT 33
+#define NXFONT_MAX7BIT 126
+
+#define NXFONT_MIN8BIT 161
+#define NXFONT_MAX8BIT 255
+
+/* Maximum height and width of any glyph in the set */
+
+#define NXFONT_MAXHEIGHT 8
+#define NXFONT_MAXWIDTH 5
+
+/* The width of a space */
+
+#define NXFONT_SPACEWIDTH 5
+
+/* exclam (33) */
+#define NXFONT_METRICS_33 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_33 {0x0, 0x20, 0x20, 0x20, 0x20, 0x0, 0x20, 0x0}
+
+/* quotedbl (34) */
+#define NXFONT_METRICS_34 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_34 {0x0, 0x50, 0x50, 0x50, 0x0, 0x0, 0x0, 0x0}
+
+/* numbersign (35) */
+#define NXFONT_METRICS_35 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_35 {0x50, 0x50, 0xf8, 0x50, 0xf8, 0x50, 0x50, 0x0}
+
+/* dollar (36) */
+#define NXFONT_METRICS_36 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_36 {0x20, 0x70, 0xa0, 0x70, 0x28, 0x70, 0x20, 0x0}
+
+/* percent (37) */
+#define NXFONT_METRICS_37 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_37 {0x0, 0x40, 0x50, 0x20, 0x50, 0x10, 0x0, 0x0}
+
+/* ampersand (38) */
+#define NXFONT_METRICS_38 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_38 {0x40, 0xa0, 0xa0, 0x40, 0xa0, 0xa0, 0x50, 0x0}
+
+/* quotesingle (39) */
+#define NXFONT_METRICS_39 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_39 {0x0, 0x20, 0x20, 0x20, 0x0, 0x0, 0x0, 0x0}
+
+/* parenleft (40) */
+#define NXFONT_METRICS_40 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_40 {0x0, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x0}
+
+/* parenright (41) */
+#define NXFONT_METRICS_41 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_41 {0x0, 0x40, 0x20, 0x20, 0x20, 0x20, 0x40, 0x0}
+
+/* asterisk (42) */
+#define NXFONT_METRICS_42 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_42 {0x0, 0x0, 0x90, 0x60, 0xf0, 0x60, 0x90, 0x0}
+
+/* plus (43) */
+#define NXFONT_METRICS_43 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_43 {0x0, 0x0, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x0}
+
+/* comma (44) */
+#define NXFONT_METRICS_44 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_44 {0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x20, 0x40}
+
+/* hyphen (45) */
+#define NXFONT_METRICS_45 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_45 {0x0, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0}
+
+/* period (46) */
+#define NXFONT_METRICS_46 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_46 {0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x70, 0x20}
+
+/* slash (47) */
+#define NXFONT_METRICS_47 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_47 {0x0, 0x10, 0x10, 0x20, 0x40, 0x80, 0x80, 0x0}
+
+/* zero (48) */
+#define NXFONT_METRICS_48 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_48 {0x0, 0x20, 0x50, 0x50, 0x50, 0x50, 0x20, 0x0}
+
+/* one (49) */
+#define NXFONT_METRICS_49 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_49 {0x0, 0x20, 0x60, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* two (50) */
+#define NXFONT_METRICS_50 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_50 {0x0, 0x60, 0x90, 0x10, 0x60, 0x80, 0xf0, 0x0}
+
+/* three (51) */
+#define NXFONT_METRICS_51 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_51 {0x0, 0xf0, 0x20, 0x60, 0x10, 0x90, 0x60, 0x0}
+
+/* four (52) */
+#define NXFONT_METRICS_52 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_52 {0x0, 0x20, 0x60, 0xa0, 0xf0, 0x20, 0x20, 0x0}
+
+/* five (53) */
+#define NXFONT_METRICS_53 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_53 {0x0, 0xf0, 0x80, 0xe0, 0x10, 0x90, 0x60, 0x0}
+
+/* six (54) */
+#define NXFONT_METRICS_54 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_54 {0x0, 0x60, 0x80, 0xe0, 0x90, 0x90, 0x60, 0x0}
+
+/* seven (55) */
+#define NXFONT_METRICS_55 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_55 {0x0, 0xf0, 0x10, 0x20, 0x20, 0x40, 0x40, 0x0}
+
+/* eight (56) */
+#define NXFONT_METRICS_56 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_56 {0x0, 0x60, 0x90, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* nine (57) */
+#define NXFONT_METRICS_57 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_57 {0x0, 0x60, 0x90, 0x90, 0x70, 0x10, 0x60, 0x0}
+
+/* colon (58) */
+#define NXFONT_METRICS_58 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_58 {0x0, 0x0, 0x60, 0x60, 0x0, 0x60, 0x60, 0x0}
+
+/* semicolon (59) */
+#define NXFONT_METRICS_59 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_59 {0x0, 0x0, 0x30, 0x30, 0x0, 0x30, 0x20, 0x40}
+
+/* less (60) */
+#define NXFONT_METRICS_60 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_60 {0x0, 0x10, 0x20, 0x40, 0x40, 0x20, 0x10, 0x0}
+
+/* equal (61) */
+#define NXFONT_METRICS_61 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_61 {0x0, 0x0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0x0}
+
+/* greater (62) */
+#define NXFONT_METRICS_62 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_62 {0x0, 0x40, 0x20, 0x10, 0x10, 0x20, 0x40, 0x0}
+
+/* question (63) */
+#define NXFONT_METRICS_63 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_63 {0x0, 0x20, 0x50, 0x10, 0x20, 0x0, 0x20, 0x0}
+
+/* at (64) */
+#define NXFONT_METRICS_64 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_64 {0x30, 0x48, 0x98, 0xa8, 0xa8, 0x90, 0x40, 0x30}
+
+/* A (65) */
+#define NXFONT_METRICS_65 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_65 {0x0, 0x60, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* B (66) */
+#define NXFONT_METRICS_66 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_66 {0x0, 0xe0, 0x90, 0xe0, 0x90, 0x90, 0xe0, 0x0}
+
+/* C (67) */
+#define NXFONT_METRICS_67 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_67 {0x0, 0x60, 0x90, 0x80, 0x80, 0x90, 0x60, 0x0}
+
+/* D (68) */
+#define NXFONT_METRICS_68 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_68 {0x0, 0xe0, 0x90, 0x90, 0x90, 0x90, 0xe0, 0x0}
+
+/* E (69) */
+#define NXFONT_METRICS_69 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_69 {0x0, 0xf0, 0x80, 0xe0, 0x80, 0x80, 0xf0, 0x0}
+
+/* F (70) */
+#define NXFONT_METRICS_70 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_70 {0x0, 0xf0, 0x80, 0xe0, 0x80, 0x80, 0x80, 0x0}
+
+/* G (71) */
+#define NXFONT_METRICS_71 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_71 {0x0, 0x60, 0x90, 0x80, 0xb0, 0x90, 0x60, 0x0}
+
+/* H (72) */
+#define NXFONT_METRICS_72 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_72 {0x0, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x90, 0x0}
+
+/* I (73) */
+#define NXFONT_METRICS_73 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_73 {0x0, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* J (74) */
+#define NXFONT_METRICS_74 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_74 {0x0, 0x70, 0x20, 0x20, 0x20, 0xa0, 0x40, 0x0}
+
+/* K (75) */
+#define NXFONT_METRICS_75 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_75 {0x0, 0x90, 0xa0, 0xc0, 0xa0, 0xa0, 0x90, 0x0}
+
+/* L (76) */
+#define NXFONT_METRICS_76 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_76 {0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x0}
+
+/* M (77) */
+#define NXFONT_METRICS_77 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_77 {0x0, 0x90, 0xf0, 0xf0, 0x90, 0x90, 0x90, 0x0}
+
+/* N (78) */
+#define NXFONT_METRICS_78 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_78 {0x0, 0x90, 0xd0, 0xf0, 0xb0, 0xb0, 0x90, 0x0}
+
+/* O (79) */
+#define NXFONT_METRICS_79 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_79 {0x0, 0x60, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* P (80) */
+#define NXFONT_METRICS_80 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_80 {0x0, 0xe0, 0x90, 0x90, 0xe0, 0x80, 0x80, 0x0}
+
+/* Q (81) */
+#define NXFONT_METRICS_81 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_81 {0x0, 0x60, 0x90, 0x90, 0xd0, 0xb0, 0x60, 0x10}
+
+/* R (82) */
+#define NXFONT_METRICS_82 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_82 {0x0, 0xe0, 0x90, 0x90, 0xe0, 0x90, 0x90, 0x0}
+
+/* S (83) */
+#define NXFONT_METRICS_83 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_83 {0x0, 0x60, 0x90, 0x40, 0x20, 0x90, 0x60, 0x0}
+
+/* T (84) */
+#define NXFONT_METRICS_84 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_84 {0x0, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0}
+
+/* U (85) */
+#define NXFONT_METRICS_85 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_85 {0x0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* V (86) */
+#define NXFONT_METRICS_86 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_86 {0x0, 0x90, 0x90, 0x90, 0x90, 0x60, 0x60, 0x0}
+
+/* W (87) */
+#define NXFONT_METRICS_87 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_87 {0x0, 0x90, 0x90, 0x90, 0xf0, 0xf0, 0x90, 0x0}
+
+/* X (88) */
+#define NXFONT_METRICS_88 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_88 {0x0, 0x90, 0x90, 0x60, 0x60, 0x90, 0x90, 0x0}
+
+/* Y (89) */
+#define NXFONT_METRICS_89 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_89 {0x0, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x0}
+
+/* Z (90) */
+#define NXFONT_METRICS_90 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_90 {0x0, 0xf0, 0x10, 0x20, 0x40, 0x80, 0xf0, 0x0}
+
+/* bracketleft (91) */
+#define NXFONT_METRICS_91 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_91 {0x0, 0x70, 0x40, 0x40, 0x40, 0x40, 0x70, 0x0}
+
+/* backslash (92) */
+#define NXFONT_METRICS_92 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_92 {0x0, 0x80, 0x80, 0x40, 0x20, 0x10, 0x10, 0x0}
+
+/* bracketright (93) */
+#define NXFONT_METRICS_93 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_93 {0x0, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x0}
+
+/* asciicircum (94) */
+#define NXFONT_METRICS_94 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_94 {0x0, 0x20, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* underscore (95) */
+#define NXFONT_METRICS_95 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_95 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0}
+
+/* grave (96) */
+#define NXFONT_METRICS_96 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_96 {0x0, 0x40, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* a (97) */
+#define NXFONT_METRICS_97 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_97 {0x0, 0x0, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* b (98) */
+#define NXFONT_METRICS_98 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_98 {0x0, 0x80, 0x80, 0xe0, 0x90, 0x90, 0xe0, 0x0}
+
+/* c (99) */
+#define NXFONT_METRICS_99 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_99 {0x0, 0x0, 0x0, 0x30, 0x40, 0x40, 0x30, 0x0}
+
+/* d (100) */
+#define NXFONT_METRICS_100 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_100 {0x0, 0x10, 0x10, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* e (101) */
+#define NXFONT_METRICS_101 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_101 {0x0, 0x0, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* f (102) */
+#define NXFONT_METRICS_102 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_102 {0x0, 0x20, 0x50, 0x40, 0xe0, 0x40, 0x40, 0x0}
+
+/* g (103) */
+#define NXFONT_METRICS_103 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_103 {0x0, 0x0, 0x0, 0x60, 0x90, 0x70, 0x10, 0x60}
+
+/* h (104) */
+#define NXFONT_METRICS_104 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_104 {0x0, 0x80, 0x80, 0xe0, 0x90, 0x90, 0x90, 0x0}
+
+/* i (105) */
+#define NXFONT_METRICS_105 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_105 {0x0, 0x20, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* j (106) */
+#define NXFONT_METRICS_106 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_106 {0x0, 0x10, 0x0, 0x10, 0x10, 0x10, 0x50, 0x20}
+
+/* k (107) */
+#define NXFONT_METRICS_107 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_107 {0x0, 0x80, 0x80, 0x90, 0xe0, 0x90, 0x90, 0x0}
+
+/* l (108) */
+#define NXFONT_METRICS_108 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_108 {0x0, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* m (109) */
+#define NXFONT_METRICS_109 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_109 {0x0, 0x0, 0x0, 0xd0, 0xa8, 0xa8, 0xa8, 0x0}
+
+/* n (110) */
+#define NXFONT_METRICS_110 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_110 {0x0, 0x0, 0x0, 0xe0, 0x90, 0x90, 0x90, 0x0}
+
+/* o (111) */
+#define NXFONT_METRICS_111 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_111 {0x0, 0x0, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* p (112) */
+#define NXFONT_METRICS_112 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_112 {0x0, 0x0, 0x0, 0xe0, 0x90, 0xe0, 0x80, 0x80}
+
+/* q (113) */
+#define NXFONT_METRICS_113 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_113 {0x0, 0x0, 0x0, 0x70, 0x90, 0x70, 0x10, 0x10}
+
+/* r (114) */
+#define NXFONT_METRICS_114 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_114 {0x0, 0x0, 0x0, 0xa0, 0xd0, 0x80, 0x80, 0x0}
+
+/* s (115) */
+#define NXFONT_METRICS_115 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_115 {0x0, 0x0, 0x0, 0x30, 0x60, 0x10, 0x60, 0x0}
+
+/* t (116) */
+#define NXFONT_METRICS_116 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_116 {0x0, 0x40, 0x40, 0xe0, 0x40, 0x50, 0x20, 0x0}
+
+/* u (117) */
+#define NXFONT_METRICS_117 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_117 {0x0, 0x0, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* v (118) */
+#define NXFONT_METRICS_118 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_118 {0x0, 0x0, 0x0, 0x50, 0x50, 0x50, 0x20, 0x0}
+
+/* w (119) */
+#define NXFONT_METRICS_119 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_119 {0x0, 0x0, 0x0, 0x88, 0xa8, 0xa8, 0x50, 0x0}
+
+/* x (120) */
+#define NXFONT_METRICS_120 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_120 {0x0, 0x0, 0x0, 0x90, 0x60, 0x60, 0x90, 0x0}
+
+/* y (121) */
+#define NXFONT_METRICS_121 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_121 {0x0, 0x0, 0x0, 0x90, 0x90, 0x70, 0x90, 0x60}
+
+/* z (122) */
+#define NXFONT_METRICS_122 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_122 {0x0, 0x0, 0x0, 0xf0, 0x20, 0x40, 0xf0, 0x0}
+
+/* braceleft (123) */
+#define NXFONT_METRICS_123 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_123 {0x30, 0x40, 0x20, 0xc0, 0x20, 0x40, 0x30, 0x0}
+
+/* bar (124) */
+#define NXFONT_METRICS_124 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_124 {0x0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0}
+
+/* braceright (125) */
+#define NXFONT_METRICS_125 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_125 {0xc0, 0x20, 0x40, 0x30, 0x40, 0x20, 0xc0, 0x0}
+
+/* asciitilde (126) */
+#define NXFONT_METRICS_126 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_126 {0x0, 0x50, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* exclamdown (161) */
+#define NXFONT_METRICS_161 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_161 {0x0, 0x20, 0x0, 0x20, 0x20, 0x20, 0x20, 0x0}
+
+/* cent (162) */
+#define NXFONT_METRICS_162 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_162 {0x0, 0x0, 0x20, 0x70, 0xa0, 0xa0, 0x70, 0x20}
+
+/* sterling (163) */
+#define NXFONT_METRICS_163 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_163 {0x0, 0x20, 0x50, 0xe0, 0x40, 0x50, 0xa0, 0x0}
+
+/* currency (164) */
+#define NXFONT_METRICS_164 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_164 {0x0, 0x0, 0x88, 0x70, 0x50, 0x70, 0x88, 0x0}
+
+/* yen (165) */
+#define NXFONT_METRICS_165 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_165 {0x0, 0x88, 0x50, 0xf8, 0x20, 0xf8, 0x20, 0x0}
+
+/* brokenbar (166) */
+#define NXFONT_METRICS_166 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_166 {0x20, 0x20, 0x20, 0x0, 0x20, 0x20, 0x20, 0x0}
+
+/* section (167) */
+#define NXFONT_METRICS_167 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_167 {0x70, 0x80, 0xe0, 0x90, 0x70, 0x10, 0xe0, 0x0}
+
+/* dieresis (168) */
+#define NXFONT_METRICS_168 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_168 {0x0, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* copyright (169) */
+#define NXFONT_METRICS_169 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_169 {0x0, 0x70, 0xa8, 0xc8, 0xc8, 0xa8, 0x70, 0x0}
+
+/* ordfeminine (170) */
+#define NXFONT_METRICS_170 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_170 {0x30, 0x50, 0x30, 0x0, 0x70, 0x0, 0x0, 0x0}
+
+/* guillemotleft (171) */
+#define NXFONT_METRICS_171 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_171 {0x0, 0x0, 0x0, 0x50, 0xa0, 0x50, 0x0, 0x0}
+
+/* logicalnot (172) */
+#define NXFONT_METRICS_172 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_172 {0x0, 0x0, 0x0, 0x0, 0x70, 0x10, 0x10, 0x0}
+
+/* hyphen (173) */
+#define NXFONT_METRICS_173 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_173 {0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0}
+
+/* registered (174) */
+#define NXFONT_METRICS_174 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_174 {0x0, 0x70, 0xe8, 0xd8, 0xe8, 0xd8, 0x70, 0x0}
+
+/* macron (175) */
+#define NXFONT_METRICS_175 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_175 {0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* degree (176) */
+#define NXFONT_METRICS_176 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_176 {0x0, 0x20, 0x50, 0x20, 0x0, 0x0, 0x0, 0x0}
+
+/* plusminus (177) */
+#define NXFONT_METRICS_177 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_177 {0x0, 0x0, 0x20, 0x70, 0x20, 0x0, 0x70, 0x0}
+
+/* twosuperior (178) */
+#define NXFONT_METRICS_178 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_178 {0x20, 0x50, 0x10, 0x20, 0x70, 0x0, 0x0, 0x0}
+
+/* threesuperior (179) */
+#define NXFONT_METRICS_179 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_179 {0x60, 0x10, 0x60, 0x10, 0x60, 0x0, 0x0, 0x0}
+
+/* acute (180) */
+#define NXFONT_METRICS_180 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_180 {0x0, 0x20, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0}
+
+/* mu (181) */
+#define NXFONT_METRICS_181 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_181 {0x0, 0x0, 0x0, 0x90, 0x90, 0x90, 0xe0, 0x80}
+
+/* paragraph (182) */
+#define NXFONT_METRICS_182 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_182 {0x0, 0x78, 0xe8, 0xe8, 0x68, 0x28, 0x28, 0x0}
+
+/* periodcentered (183) */
+#define NXFONT_METRICS_183 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_183 {0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0}
+
+/* cedilla (184) */
+#define NXFONT_METRICS_184 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_184 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x40}
+
+/* onesuperior (185) */
+#define NXFONT_METRICS_185 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_185 {0x20, 0x60, 0x20, 0x20, 0x70, 0x0, 0x0, 0x0}
+
+/* ordmasculine (186) */
+#define NXFONT_METRICS_186 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_186 {0x20, 0x50, 0x20, 0x0, 0x70, 0x0, 0x0, 0x0}
+
+/* guillemotright (187) */
+#define NXFONT_METRICS_187 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_187 {0x0, 0x0, 0x0, 0xa0, 0x50, 0xa0, 0x0, 0x0}
+
+/* onequarter (188) */
+#define NXFONT_METRICS_188 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_188 {0x80, 0x80, 0x80, 0xa0, 0x60, 0xf0, 0x20, 0x0}
+
+/* onehalf (189) */
+#define NXFONT_METRICS_189 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_189 {0x80, 0x80, 0xa0, 0xd0, 0x10, 0x20, 0x70, 0x0}
+
+/* threequarters (190) */
+#define NXFONT_METRICS_190 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_190 {0x80, 0x40, 0x80, 0x60, 0xa0, 0xf0, 0x20, 0x0}
+
+/* questiondown (191) */
+#define NXFONT_METRICS_191 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_191 {0x0, 0x20, 0x0, 0x20, 0x40, 0x50, 0x20, 0x0}
+
+/* Agrave (192) */
+#define NXFONT_METRICS_192 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_192 {0x40, 0x20, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Aacute (193) */
+#define NXFONT_METRICS_193 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_193 {0x20, 0x40, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Acircumflex (194) */
+#define NXFONT_METRICS_194 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_194 {0x60, 0x90, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Atilde (195) */
+#define NXFONT_METRICS_195 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_195 {0x50, 0xa0, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Adieresis (196) */
+#define NXFONT_METRICS_196 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_196 {0x90, 0x0, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* Aring (197) */
+#define NXFONT_METRICS_197 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_197 {0x60, 0x90, 0x60, 0x90, 0xf0, 0x90, 0x90, 0x0}
+
+/* AE (198) */
+#define NXFONT_METRICS_198 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_198 {0x0, 0x70, 0xa0, 0xa0, 0xf0, 0xa0, 0xb0, 0x0}
+
+/* Ccedilla (199) */
+#define NXFONT_METRICS_199 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_199 {0x0, 0x60, 0x90, 0x80, 0x80, 0x90, 0x60, 0x40}
+
+/* Egrave (200) */
+#define NXFONT_METRICS_200 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_200 {0x40, 0x20, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Eacute (201) */
+#define NXFONT_METRICS_201 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_201 {0x20, 0x40, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Ecircumflex (202) */
+#define NXFONT_METRICS_202 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_202 {0x60, 0x90, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Edieresis (203) */
+#define NXFONT_METRICS_203 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_203 {0x90, 0x0, 0xf0, 0x80, 0xe0, 0x80, 0xf0, 0x0}
+
+/* Igrave (204) */
+#define NXFONT_METRICS_204 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_204 {0x40, 0x20, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Iacute (205) */
+#define NXFONT_METRICS_205 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_205 {0x10, 0x20, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Icircumflex (206) */
+#define NXFONT_METRICS_206 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_206 {0x20, 0x50, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Idieresis (207) */
+#define NXFONT_METRICS_207 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_207 {0x50, 0x0, 0x70, 0x20, 0x20, 0x20, 0x70, 0x0}
+
+/* Eth (208) */
+#define NXFONT_METRICS_208 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_208 {0x0, 0x70, 0x48, 0xe8, 0x48, 0x48, 0x70, 0x0}
+
+/* Ntilde (209) */
+#define NXFONT_METRICS_209 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_209 {0x50, 0xa0, 0x90, 0xd0, 0xb0, 0x90, 0x90, 0x0}
+
+/* Ograve (210) */
+#define NXFONT_METRICS_210 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_210 {0x40, 0x20, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Oacute (211) */
+#define NXFONT_METRICS_211 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_211 {0x20, 0x40, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Ocircumflex (212) */
+#define NXFONT_METRICS_212 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_212 {0x60, 0x90, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Otilde (213) */
+#define NXFONT_METRICS_213 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_213 {0x50, 0xa0, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Odieresis (214) */
+#define NXFONT_METRICS_214 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_214 {0x90, 0x0, 0x60, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* multiply (215) */
+#define NXFONT_METRICS_215 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_215 {0x0, 0x0, 0x0, 0x0, 0x50, 0x20, 0x50, 0x0}
+
+/* Oslash (216) */
+#define NXFONT_METRICS_216 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_216 {0x0, 0x70, 0xb0, 0xb0, 0xd0, 0xd0, 0xe0, 0x0}
+
+/* Ugrave (217) */
+#define NXFONT_METRICS_217 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_217 {0x40, 0x20, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Uacute (218) */
+#define NXFONT_METRICS_218 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_218 {0x20, 0x40, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Ucircumflex (219) */
+#define NXFONT_METRICS_219 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_219 {0x60, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Udieresis (220) */
+#define NXFONT_METRICS_220 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_220 {0x90, 0x0, 0x90, 0x90, 0x90, 0x90, 0x60, 0x0}
+
+/* Yacute (221) */
+#define NXFONT_METRICS_221 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_221 {0x10, 0x20, 0x88, 0x50, 0x20, 0x20, 0x20, 0x0}
+
+/* Thorn (222) */
+#define NXFONT_METRICS_222 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_222 {0x0, 0x80, 0xe0, 0x90, 0x90, 0xe0, 0x80, 0x0}
+
+/* germandbls (223) */
+#define NXFONT_METRICS_223 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_223 {0x0, 0x60, 0x90, 0xa0, 0xa0, 0x90, 0xa0, 0x0}
+
+/* agrave (224) */
+#define NXFONT_METRICS_224 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_224 {0x40, 0x20, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* aacute (225) */
+#define NXFONT_METRICS_225 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_225 {0x20, 0x40, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* acircumflex (226) */
+#define NXFONT_METRICS_226 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_226 {0x20, 0x50, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* atilde (227) */
+#define NXFONT_METRICS_227 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_227 {0x50, 0xa0, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* adieresis (228) */
+#define NXFONT_METRICS_228 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_228 {0x0, 0x50, 0x0, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* aring (229) */
+#define NXFONT_METRICS_229 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_229 {0x60, 0x90, 0x60, 0x70, 0x90, 0x90, 0x70, 0x0}
+
+/* ae (230) */
+#define NXFONT_METRICS_230 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_230 {0x0, 0x0, 0x0, 0xf0, 0x68, 0xb0, 0x78, 0x0}
+
+/* ccedilla (231) */
+#define NXFONT_METRICS_231 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_231 {0x0, 0x0, 0x0, 0x30, 0x40, 0x40, 0x30, 0x20}
+
+/* egrave (232) */
+#define NXFONT_METRICS_232 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_232 {0x40, 0x20, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* eacute (233) */
+#define NXFONT_METRICS_233 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_233 {0x20, 0x40, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* ecircumflex (234) */
+#define NXFONT_METRICS_234 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_234 {0x60, 0x90, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* edieresis (235) */
+#define NXFONT_METRICS_235 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_235 {0x0, 0x50, 0x0, 0x60, 0xb0, 0xc0, 0x60, 0x0}
+
+/* igrave (236) */
+#define NXFONT_METRICS_236 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_236 {0x40, 0x20, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* iacute (237) */
+#define NXFONT_METRICS_237 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_237 {0x10, 0x20, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* icircumflex (238) */
+#define NXFONT_METRICS_238 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_238 {0x20, 0x50, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* idieresis (239) */
+#define NXFONT_METRICS_239 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_239 {0x0, 0x50, 0x0, 0x60, 0x20, 0x20, 0x70, 0x0}
+
+/* eth (240) */
+#define NXFONT_METRICS_240 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_240 {0xa0, 0x40, 0xa0, 0x10, 0x70, 0x90, 0x60, 0x0}
+
+/* ntilde (241) */
+#define NXFONT_METRICS_241 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_241 {0x50, 0xa0, 0x0, 0xe0, 0x90, 0x90, 0x90, 0x0}
+
+/* ograve (242) */
+#define NXFONT_METRICS_242 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_242 {0x40, 0x20, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* oacute (243) */
+#define NXFONT_METRICS_243 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_243 {0x20, 0x40, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* ocircumflex (244) */
+#define NXFONT_METRICS_244 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_244 {0x60, 0x90, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* otilde (245) */
+#define NXFONT_METRICS_245 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_245 {0x50, 0xa0, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* odieresis (246) */
+#define NXFONT_METRICS_246 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_246 {0x0, 0x90, 0x0, 0x60, 0x90, 0x90, 0x60, 0x0}
+
+/* divide (247) */
+#define NXFONT_METRICS_247 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_247 {0x0, 0x0, 0x20, 0x0, 0x70, 0x0, 0x20, 0x0}
+
+/* oslash (248) */
+#define NXFONT_METRICS_248 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_248 {0x0, 0x0, 0x0, 0x70, 0xb0, 0xd0, 0xe0, 0x0}
+
+/* ugrave (249) */
+#define NXFONT_METRICS_249 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_249 {0x40, 0x20, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* uacute (250) */
+#define NXFONT_METRICS_250 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_250 {0x20, 0x40, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* ucircumflex (251) */
+#define NXFONT_METRICS_251 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_251 {0x60, 0x90, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* udieresis (252) */
+#define NXFONT_METRICS_252 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_252 {0x0, 0x90, 0x0, 0x90, 0x90, 0x90, 0x70, 0x0}
+
+/* yacute (253) */
+#define NXFONT_METRICS_253 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_253 {0x20, 0x40, 0x0, 0x90, 0x90, 0x70, 0x90, 0x60}
+
+/* thorn (254) */
+#define NXFONT_METRICS_254 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_254 {0x0, 0x80, 0x80, 0xe0, 0x90, 0xe0, 0x80, 0x80}
+
+/* ydieresis (255) */
+#define NXFONT_METRICS_255 {1, 5, 8, 0, 0, 0}
+#define NXFONT_BITMAP_255 {0x0, 0x90, 0x0, 0x90, 0x90, 0x70, 0x90, 0x60}
+
+#endif
diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h
index 8b4b10ade..958986472 100644
--- a/nuttx/include/nuttx/arch.h
+++ b/nuttx/include/nuttx/arch.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/arch.h
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/nuttx/include/nuttx/binfmt/binfmt.h b/nuttx/include/nuttx/binfmt/binfmt.h
index 6df5190d2..c6c7c874a 100644
--- a/nuttx/include/nuttx/binfmt/binfmt.h
+++ b/nuttx/include/nuttx/binfmt/binfmt.h
@@ -117,6 +117,12 @@ struct binary_s
#endif
size_t mapsize; /* Size of the mapped address region (needed for munmap) */
+
+ /* Start-up information that is provided by the loader, but may be modified
+ * by the caller between load_module() and exec_module() calls.
+ */
+
+ uint8_t priority; /* Task execution priority */
size_t stacksize; /* Size of the stack in bytes (unallocated) */
};
@@ -221,7 +227,7 @@ int unload_module(FAR const struct binary_s *bin);
*
****************************************************************************/
-int exec_module(FAR const struct binary_s *bin, int priority);
+int exec_module(FAR const struct binary_s *bin);
/****************************************************************************
* Name: exec
diff --git a/apps/include/apps.h b/nuttx/include/nuttx/binfmt/builtin.h
index 520128203..632f8944d 100644
--- a/apps/include/apps.h
+++ b/nuttx/include/nuttx/binfmt/builtin.h
@@ -1,9 +1,16 @@
/****************************************************************************
- * apps/include/apps.h
+ * include/nuttx/binfmt/builtin.h
*
- * Copyright(C) 2011 Uros Platise. All rights reserved.
+ * Originally by:
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
+ * With subsequent updates, modifications, and general maintenance by:
+ *
+ * Copyright (C) 2012-2013 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:
@@ -23,18 +30,18 @@
* 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,
+ * 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
+ * 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.
*
****************************************************************************/
-#ifndef __APPS_INCLUDE_APPS_H
-#define __APPS_INCLUDE_APPS_H
+#ifndef __INCLUDE_NUTTX_BINFMT_BUILTIN_H
+#define __INCLUDE_NUTTX_BINFMT_BUILTIN_H
/****************************************************************************
* Included Files
@@ -42,17 +49,12 @@
#include <nuttx/config.h>
#include <sys/types.h>
-#include <stdint.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
-struct namedapp_s
+struct builtin_s
{
const char *name; /* Invocation name and as seen under /sbin/ */
int priority; /* Use: SCHED_PRIORITY_DEFAULT */
@@ -64,20 +66,6 @@ struct namedapp_s
* Public Data
****************************************************************************/
-/* The "bindir" is file system that supports access to the named applications.
- * It is typically mounted under /bin.
- */
-
-#ifdef CONFIG_APPS_BINDIR
-struct mountpt_operations;
-extern const struct mountpt_operations binfs_operations;
-#endif
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C" {
@@ -85,8 +73,23 @@ extern "C" {
#define EXTERN extern
#endif
+/* The g_builtins[] array holds information about each builtin function. If
+ * support for builtin functions is enabled in the NuttX configuration, then
+ * this arrary (along with the number_builtins() function) must be provided
+ * by the application code.
+ */
+
+EXTERN const struct builtin_s g_builtins[];
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
/****************************************************************************
- * Name: namedapp_isavail
+ * Utility Functions Provided to Applications by binfmt/libbuiltin
+ ****************************************************************************/
+/****************************************************************************
+ * Name: builtin_isavail
*
* Description:
* Checks for availabiliy of application registerred during compile time.
@@ -101,10 +104,10 @@ extern "C" {
*
****************************************************************************/
-EXTERN int namedapp_isavail(FAR const char *appname);
+int builtin_isavail(FAR const char *appname);
/****************************************************************************
- * Name: namedapp_getname
+ * Name: builtin_getname
*
* Description:
* Returns pointer to a name of built-in application pointed by the
@@ -119,31 +122,35 @@ EXTERN int namedapp_isavail(FAR const char *appname);
*
****************************************************************************/
-EXTERN const char *namedapp_getname(int index);
+FAR const char *builtin_getname(int index);
/****************************************************************************
- * Name: exec_namedapp
+ * Data Set Access Functions Provided to Applications by binfmt/libbuiltin
+ ****************************************************************************/
+/****************************************************************************
+ * Name: number_builtins
*
* Description:
- * Executes builtin named application registered during compile time.
- * New application is run in a separate task context (and thread).
+ * Returns the number of builtin functions in the g_builtins[] array. If
+ * support for builtin functions is enabled in the NuttX configuration,
+ * then this function (along with g_builtins[]) must be provided by the
+ * application code.
*
* Input Parameter:
- * filename - Name of the linked-in binary to be started.
- * argv - Argument list
+ * None
*
* Returned Value:
- * This is an end-user function, so it follows the normal convention:
- * Returns the PID of the exec'ed module. On failure, it.returns
- * -1 (ERROR) and sets errno appropriately.
+ * The number of entries in the g_builtins[] array. This function does
+ * not return failures.
*
****************************************************************************/
-EXTERN int exec_namedapp(FAR const char *appname, FAR const char **argv);
+int number_builtins(void);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
-#endif /* __APPS_INCLUDE_APPS_H */
+#endif /* __INCLUDE_NUTTX_BINFMT_BUILTIN_H */
+
diff --git a/nuttx/include/nuttx/clock.h b/nuttx/include/nuttx/clock.h
index 952e0e5ef..e640ecd2e 100644
--- a/nuttx/include/nuttx/clock.h
+++ b/nuttx/include/nuttx/clock.h
@@ -113,7 +113,7 @@
#define USEC2TICK(usec) (((usec)+(USEC_PER_TICK/2))/USEC_PER_TICK) /* Rounds */
#define MSEC2TICK(msec) (((msec)+(MSEC_PER_TICK/2))/MSEC_PER_TICK) /* Rounds */
#define DSEC2TICK(dsec) MSEC2TICK((dsec)*MSEC_PER_DSEC)
-#define SEC2TICK(sec) MSEC2TICK((sec)*MSEC_PER_SEC)
+#define SEC2TICK(sec) MSEC2TICK((sec)*MSEC_PER_SEC) /* Exact */
#define TICK2NSEC(tick) ((tick)*NSEC_PER_TICK) /* Exact */
#define TICK2USEC(tick) ((tick)*USEC_PER_TICK) /* Exact */
diff --git a/nuttx/include/nuttx/fs/binfs.h b/nuttx/include/nuttx/fs/binfs.h
new file mode 100644
index 000000000..d967506d8
--- /dev/null
+++ b/nuttx/include/nuttx/fs/binfs.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+ * include/nuttx/fs/binfs.h
+ *
+ * Copyright (C) 2013 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_FS_BINFS_H
+#define __INCLUDE_NUTTX_FS_BINFS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_FS_BINFS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/* The "bindir" is file system that supports access to the builtin applications.
+ * It is typically mounted under /bin.
+ */
+
+EXTERN mountpt_operations;
+EXTERN const struct mountpt_operations binfs_operations;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_FS_BINFS */
+#endif /* __INCLUDE_NUTTX_FS_BINFS_H */
diff --git a/nuttx/include/nuttx/fs/dirent.h b/nuttx/include/nuttx/fs/dirent.h
index 75867c87a..f8d356850 100644
--- a/nuttx/include/nuttx/fs/dirent.h
+++ b/nuttx/include/nuttx/fs/dirent.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/dirent.h
*
- * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -102,7 +102,7 @@ struct fs_romfsdir_s
};
#endif /* CONFIG_FS_ROMFS */
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
/* The apps/ pseudo bin/ directory. The state value is simply an index */
struct fs_binfsdir_s
@@ -179,7 +179,7 @@ struct fs_dirent_s
#ifdef CONFIG_FS_ROMFS
struct fs_romfsdir_s romfs;
#endif
-#ifdef CONFIG_APPS_BINDIR
+#ifdef CONFIG_FS_BINFS
struct fs_binfsdir_s binfs;
#endif
#ifdef CONFIG_FS_NXFFS
diff --git a/nuttx/include/nuttx/fs/fs.h b/nuttx/include/nuttx/fs/fs.h
index 1759310bc..327bf37ca 100644
--- a/nuttx/include/nuttx/fs/fs.h
+++ b/nuttx/include/nuttx/fs/fs.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/fs.h
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -161,6 +161,7 @@ struct mountpt_operations
*/
int (*sync)(FAR struct file *filp);
+ int (*dup)(FAR const struct file *oldp, FAR struct file *newp);
/* Directory operations */
diff --git a/nuttx/include/nuttx/fs/ioctl.h b/nuttx/include/nuttx/fs/ioctl.h
index 6d60c2ee9..a15de03b9 100644
--- a/nuttx/include/nuttx/fs/ioctl.h
+++ b/nuttx/include/nuttx/fs/ioctl.h
@@ -105,6 +105,11 @@
#define FIOC_OPTIMIZE _FIOC(0x0003) /* IN: None
* OUT: None
*/
+#define FIOC_FILENAME _FIOC(0x0004) /* IN: FAR const char ** pointer
+ * OUT: Pointer to a persistent file name
+ * (Guaranteed to persist while the file
+ * is open).
+ */
#define FIONREAD _FIOC(0x0004) /* IN: Location to return value (int *)
* OUT: Bytes readable from this fd
diff --git a/nuttx/include/nuttx/input/kbd_codec.h b/nuttx/include/nuttx/input/kbd_codec.h
new file mode 100644
index 000000000..9a7c7c8e6
--- /dev/null
+++ b/nuttx/include/nuttx/input/kbd_codec.h
@@ -0,0 +1,347 @@
+/************************************************************************************
+ * include/nuttx/input/kbd_codec.h
+ * Serialize and marshaling keyboard data and events
+ *
+ * Copyright (C) 2012 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.
+ *
+ ************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_INPUT_KBD_CODEC_H
+#define __INCLUDE_NUTTX_INPUT_KBD_CODEC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/streams.h>
+
+#ifdef CONFIG_LIB_KBDCODEC
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* These are the special keyboard commands recognized by the CODEC. */
+
+enum kbd_keycode_e
+{
+ KEYCODE_NORMAL = 0, /* Not a special keycode */
+
+ /* Delete and Backspace keycodes (in case they may be different than the
+ * ASCII BKSP and DEL values.
+ */
+
+ KEYCODE_FWDDEL, /* DELete (forward delete) */
+ KEYCODE_BACKDEL, /* Backspace (backward delete) */
+
+ /* Cursor movement */
+
+ KEYCODE_HOME, /* Home */
+ KEYCODE_END, /* End */
+ KEYCODE_LEFT, /* Left arrow */
+ KEYCODE_RIGHT, /* Right arrow */
+ KEYCODE_UP, /* Up arrow */
+ KEYCODE_DOWN, /* Down arrow */
+ KEYCODE_PAGEUP, /* Page up */
+ KEYCODE_PAGEDOWN, /* Page down */
+
+ /* Edit commands */
+
+ KEYCODE_INSERT, /* Insert */
+ KEYCODE_AGAIN, /* Again */
+ KEYCODE_UNDO, /* Undo */
+ KEYCODE_REDO, /* Redo */
+ KEYCODE_CUT, /* Cut */
+ KEYCODE_COPY, /* Copy */
+ KEYCODE_PASTE, /* Paste */
+ KEYCODE_FIND, /* Find */
+
+ /* Selection codes */
+
+ KEYCODE_ENTER, /* Enter */
+ KEYCODE_SELECT, /* Select */
+ KEYCODE_EXECUTE, /* Execute */
+
+ /* Keyboard modes */
+
+ KEYCODE_CAPSLOCK, /* Caps Lock */
+ KEYCODE_SCROLLLOCK, /* Scroll Lock */
+ KEYCODE_NUMLOCK, /* Keypad Num Lock and Clear */
+ KEYCODE_LCAPSLOCK, /* Locking Caps Lock */
+ KEYCODE_LNUMLOCK, /* Locking Num Lock */
+ KEYCODE_LSCROLLLOCK, /* Locking Scroll Lock */
+
+ /* Misc control codes */
+
+ KEYCODE_POWER, /* Power */
+ KEYCODE_HELP, /* Help */
+ KEYCODE_MENU, /* Menu */
+ KEYCODE_STOP, /* Stop */
+ KEYCODE_PAUSE, /* Pause */
+ KEYCODE_BREAK, /* Break */
+ KEYCODE_CANCEL, /* Cancel */
+ KEYCODE_PRTSCRN, /* PrintScreen */
+ KEYCODE_SYSREQ, /* SysReq/Attention */
+
+ /* Audio */
+
+ KEYCODE_MUTE, /* Mute */
+ KEYCODE_VOLUP, /* Volume Up */
+ KEYCODE_VOLDOWN, /* Volume Down */
+
+ /* Telephone */
+
+ KEYCODE_ANSWER, /* Answer (phone) */
+ KEYCODE_HANGUP, /* Hang-up (phone) */
+
+ /* Calculator */
+
+ KEYCODE_CLEAR, /* Clear */
+ KEYCODE_CLEARENTRY, /* Clear entry */
+ KEYCODE_NEGATE, /* +/- */
+
+ KEYCODE_MEMSTORE, /* Memory store */
+ KEYCODE_MEMCLEAR, /* Memory clear */
+ KEYCODE_MEMRECALL, /* Memory recall */
+ KEYCODE_MEMADD, /* Memory add */
+ KEYCODE_MEMSUB, /* Memory substract */
+ KEYCODE_MEMMUL, /* Memory multiply */
+ KEYCODE_MEMDIV, /* Memory divide */
+
+ KEYCODE_BINARY, /* Binary mode */
+ KEYCODE_OCTAL, /* Octal mode */
+ KEYCODE_DECIMAL, /* Decimal mode */
+ KEYCODE_HEXADECIMAL, /* Hexadecimal mode */
+
+ /* Languages */
+
+ KEYCODE_LANG1, /* LANG1 */
+ KEYCODE_LANG2, /* LANG2 */
+ KEYCODE_LANG3, /* LANG3 */
+ KEYCODE_LANG4, /* LANG4 */
+ KEYCODE_LANG5, /* LANG5 */
+ KEYCODE_LANG6, /* LANG6 */
+ KEYCODE_LANG7, /* LANG7 */
+ KEYCODE_LANG8, /* LANG8 */
+
+ /* Context-specific function keys */
+
+ KEYCODE_F1, /* Function key 1 */
+ KEYCODE_F2, /* Function key 2 */
+ KEYCODE_F3, /* Function key 3 */
+ KEYCODE_F4, /* Function key 4 */
+ KEYCODE_F5, /* Function key 5 */
+ KEYCODE_F6, /* Function key 6 */
+ KEYCODE_F7, /* Function key 7 */
+ KEYCODE_F8, /* Function key 8 */
+ KEYCODE_F9, /* Function key 9 */
+ KEYCODE_F10, /* Function key 10 */
+ KEYCODE_F11, /* Function key 11 */
+ KEYCODE_F12, /* Function key 12 */
+ KEYCODE_F13, /* Function key 13 */
+ KEYCODE_F14, /* Function key 14 */
+ KEYCODE_F15, /* Function key 15 */
+ KEYCODE_F16, /* Function key 16 */
+ KEYCODE_F17, /* Function key 17 */
+ KEYCODE_F18, /* Function key 18 */
+ KEYCODE_F19, /* Function key 19 */
+ KEYCODE_F20, /* Function key 20 */
+ KEYCODE_F21, /* Function key 21 */
+ KEYCODE_F22, /* Function key 22 */
+ KEYCODE_F23, /* Function key 23 */
+ KEYCODE_F24 /* Function key 24 */
+};
+
+#define FIRST_KEYCODE KEYCODE_FWDDEL
+#define LAST_KEYCODE KEYCODE_F24
+
+/* kbd_decode() return values */
+
+#define KBD_PRESS 0 /* Key press event */
+#define KBD_RELEASE 1 /* Key release event */
+#define KBD_SPECPRESS 2 /* Special key press event */
+#define KBD_SPECREL 3 /* Special key release event */
+#define KBD_ERROR EOF /* Error or end-of-file */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct kbd_getstate_s
+{
+ uint8_t nch; /* Number of characters in the buffer */
+ uint8_t ndx; /* Index to next character in the buffer */
+ uint8_t buf[4]; /* Buffer of ungotten data */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * The following functions are intended for use by "producer", keyboard
+ * or keypad drivers to encode information into driver buffers.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_press
+ *
+ * Description:
+ * Indicates a normal key press event. Put one byte of normal keyboard
+ * data into the output stream.
+ *
+ * Input Parameters:
+ * ch - The character to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#define kbd_press(ch, stream) (stream)->put((stream), (int)(ch))
+
+/****************************************************************************
+ * Name: kbd_release
+ *
+ * Description:
+ * Encode the release of a normal key.
+ *
+ * Input Parameters:
+ * ch - The character associated with the key that was releared.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_release(uint8_t ch, FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * Name: kbd_specpress
+ *
+ * Description:
+ * Denotes a special key press event. Put one special keyboard command
+ * into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specpress(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * Name: kbd_specrel
+ *
+ * Description:
+ * Denotes a special key release event. Put one special keyboard
+ * command into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specrel(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream);
+
+/****************************************************************************
+ * The following functions are intended for use by "consumer" applications
+ * to remove and decode information from the driver provided buffer.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_decode
+ *
+ * Description:
+ * Get one byte of data or special command from the driver provided input
+ * buffer.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * kbd_keycode_e
+ * state - A user provided buffer to support parsing. This structure
+ * should be cleared the first time that kbd_decode is called.
+ *
+ * Returned Value:
+ *
+ * KBD_PRESS - Indicates the successful receipt of normal, keyboard data.
+ * This corresponds to a keypress event. The returned value in pch is a
+ * simple byte of text or control data corresponding to the pressed key.
+ * KBD_RELEASE - Indicates a key release event. The returned value in pch
+ * is the byte of text or control data corresponding to the released key.
+ * KBD_SPECPRESS - Indicates the successful receipt of a special keyboard
+ * command. The returned value in pch is a value from enum kbd_getstate_s.
+ * KBD_SPECREL - Indicates a special key release event. The returned value
+ * in pch is a value from enum kbd_getstate_s.
+ * EOF - An error has getting the next character (reported by the stream).
+ * Normally indicates the end of file.
+ *
+ ****************************************************************************/
+
+int kbd_decode(FAR struct lib_instream_s *stream,
+ FAR struct kbd_getstate_s *state, FAR uint8_t *pch);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LIB_KBDCODEC */
+#endif /* __INCLUDE_NUTTX_INPUT_KBD_CODEC_H */
+
diff --git a/nuttx/include/nuttx/lcd/ug-2864hsweg01.h b/nuttx/include/nuttx/lcd/ug-2864hsweg01.h
new file mode 100644
index 000000000..bbefd39be
--- /dev/null
+++ b/nuttx/include/nuttx/lcd/ug-2864hsweg01.h
@@ -0,0 +1,245 @@
+/**************************************************************************************
+ * include/nuttx/lcd/ug-2864hsweg01.h
+ * Driver for Univision UG-2864HSWEG01 OLED display (wih SSD1306 controller) in SPI
+ * mode
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * References:
+ * 1. Product Specification (Preliminary), Part Name: OEL Display Module, Part ID:
+ * UG-2864HSWEG01, Doc No: SAS1-9046-B, Univision Technology Inc.
+ * 2. SSD1306, 128 X 64 Dot Matrix OLED/PLED, Preliminary Segment/Common Driver with
+ * Controller, Solomon Systech
+ *
+ * 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.
+ *
+ **************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_UG_8264HSWEG01_H
+#define __INCLUDE_NUTTX_UG_8264HSWEG01_H
+
+/**************************************************************************************
+ * Included Files
+ **************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+
+#include <nuttx/arch.h>
+
+#ifdef CONFIG_LCD_UG2864HSWEG01
+
+/**************************************************************************************
+ * Pre-processor Definitions
+ **************************************************************************************/
+/* Configuration **********************************************************************/
+/* UG-2864HSWEG01 Configuration Settings:
+ *
+ * CONFIG_UG2864HSWEG01_SPIMODE - Controls the SPI mode
+ * CONFIG_UG2864HSWEG01_FREQUENCY - Define to use a different bus frequency
+ * CONFIG_UG2864HSWEG01_NINTERFACES - Specifies the number of physical UG-2864HSWEG01
+ * devices that will be supported.
+ *
+ * Required LCD driver settings:
+ *
+ * CONFIG_LCD_UG28HSWEG01 - Enable UG-2864HSWEG01 support
+ * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted.
+ * CONFIG_LCD_MAXPOWER must be 1
+ *
+ * Option LCD driver settings:
+ * CONFIG_LCD_LANDSCAPE, CONFIG_LCD_PORTRAIT, CONFIG_LCD_RLANDSCAPE, and
+ * CONFIG_LCD_RPORTRAIT - Display orientation.
+ *
+ * Required SPI driver settings:
+ * CONFIG_SPI_CMDDATA - Include support for cmd/data selection.
+ */
+
+/* SPI Interface
+ *
+ * "The serial interface consists of serial clock SCL, serial data SI, A0 and
+ * CS . SI is shifted into an 8-bit shift register on every rising edge of
+ * SCL in the order of D7, D6, … and D0. A0 is sampled on every eighth clock
+ * and the data byte in the shift register is written to the display data RAM
+ * or command register in the same clock."
+ *
+ * MODE 3:
+ * Clock polarity: High (CPOL=1)
+ * Clock phase: Sample on trailing (rising edge) (CPHA 1)
+ */
+
+#ifndef CONFIG_UG2864HSWEG01_SPIMODE
+# define CONFIG_UG2864HSWEG01_SPIMODE SPIDEV_MODE3
+#endif
+
+/* "This module determines whether the input data is interpreted as data or
+ * command. When A0 = “H”, the inputs at D7 - D0 are interpreted as data and be
+ * written to display RAM. When A0 = “L”, the inputs at D7 - D0 are interpreted
+ * as command, they will be decoded and be written to the corresponding command
+ * registers.
+ */
+
+#ifndef CONFIG_SPI_CMDDATA
+# error "CONFIG_SPI_CMDDATA must be defined in your NuttX configuration"
+#endif
+
+/* CONFIG_UG2864HSWEG01_NINTERFACES determines the number of physical interfaces
+ * that will be supported.
+ */
+
+#ifndef CONFIG_UG2864HSWEG01_NINTERFACES
+# define CONFIG_UG2864HSWEG01_NINTERFACES 1
+#endif
+
+/* Check contrast selection */
+
+#if !defined(CONFIG_LCD_MAXCONTRAST)
+# define CONFIG_LCD_MAXCONTRAST 255
+#endif
+
+#if CONFIG_LCD_MAXCONTRAST <= 0|| CONFIG_LCD_MAXCONTRAST > 255
+# error "CONFIG_LCD_MAXCONTRAST exceeds supported maximum"
+#endif
+
+#if CONFIG_LCD_MAXCONTRAST < 255
+# warning "Optimal setting of CONFIG_LCD_MAXCONTRAST is 255"
+#endif
+
+/* Check power setting */
+
+#if !defined(CONFIG_LCD_MAXPOWER)
+# define CONFIG_LCD_MAXPOWER 1
+#endif
+
+#if CONFIG_LCD_MAXPOWER != 1
+# warning "CONFIG_LCD_MAXPOWER exceeds supported maximum"
+# undef CONFIG_LCD_MAXPOWER
+# define CONFIG_LCD_MAXPOWER 1
+#endif
+
+/* Color is 1bpp monochrome with leftmost column contained in bits 0 */
+
+#ifdef CONFIG_NX_DISABLE_1BPP
+# warning "1 bit-per-pixel support needed"
+#endif
+
+/* Orientation */
+
+#if defined(CONFIG_LCD_LANDSCAPE)
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RLANDSCAPE
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_PORTRAIT)
+# undef CONFIG_LCD_LANDSCAPE
+# undef CONFIG_LCD_RLANDSCAPE
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_RLANDSCAPE)
+# undef CONFIG_LCD_LANDSCAPE
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RPORTRAIT
+#elif defined(CONFIG_LCD_RPORTRAIT)
+# undef CONFIG_LCD_LANDSCAPE
+# undef CONFIG_LCD_PORTRAIT
+# undef CONFIG_LCD_RLANDSCAPE
+#else
+# define CONFIG_LCD_LANDSCAPE 1
+# warning "Assuming landscape orientation"
+#endif
+
+/* Some important "colors" */
+
+#define UG_Y1_BLACK 0
+#define UG_Y1_WHITE 1
+
+/**************************************************************************************
+ * Public Types
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Public Data
+ **************************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************************************************************************
+ * Public Function Prototypes
+ **************************************************************************************/
+
+/**************************************************************************************
+ * Name: ug2864hsweg01_initialize
+ *
+ * Description:
+ * Initialize the UG-2864HSWEG01 video hardware. The initial state of the
+ * OLED is fully initialized, display memory cleared, and the OLED ready
+ * to use, but with the power setting at 0 (full off == sleep mode).
+ *
+ * Input Parameters:
+ *
+ * spi - A reference to the SPI driver instance.
+ * devno - A value in the range of 0 through CONFIG_UG2864HSWEG01_NINTERFACES-1.
+ * This allows support for multiple OLED devices.
+ *
+ * Returned Value:
+ *
+ * On success, this function returns a reference to the LCD object for
+ * the specified OLED. NULL is returned on any failure.
+ *
+ **************************************************************************************/
+
+struct lcd_dev_s; /* See include/nuttx/lcd/lcd.h */
+struct spi_dev_s; /* See include/nuttx/spi.h */
+FAR struct lcd_dev_s *ug2864hsweg01_initialize(FAR struct spi_dev_s *spi,
+ unsigned int devno);
+
+/************************************************************************************************
+ * Name: ug2864hsweg01_fill
+ *
+ * Description:
+ * This non-standard method can be used to clear the entire display by writing one
+ * color to the display. This is much faster than writing a series of runs.
+ *
+ * Input Parameters:
+ * priv - Reference to private driver structure
+ *
+ * Assumptions:
+ * Caller has selected the OLED section.
+ *
+ **************************************************************************************/
+
+void ug2864hsweg01_fill(FAR struct lcd_dev_s *dev, uint8_t color);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_LCD_UG2864HSWEG01 */
+#endif /* __INCLUDE_NUTTX_UG_8264HSWEG01_H */
diff --git a/nuttx/include/nuttx/net/mii.h b/nuttx/include/nuttx/net/mii.h
index 6a5fc6e89..de4dcdfd7 100644
--- a/nuttx/include/nuttx/net/mii.h
+++ b/nuttx/include/nuttx/net/mii.h
@@ -112,12 +112,12 @@
/* Luminary LM3S6918 built-in PHY: 0x07-0x0f, 0x14-0x16, 0x19-0x1f reserved */
-#define MII_LM3S_VSPECIFIC 0x10 /* Vendor-Specific */
-#define MII_LM3S_INTCS 0x11 /* Interrupt control/status */
-#define MII_LM3S_DIAGNOSTIC 0x12 /* Diagnostic */
-#define MII_LM3S_XCVRCONTROL 0x13 /* Transceiver Control */
-#define MII_LM3S_LEDCONFIG 0x17 /* LED Configuration */
-#define MII_LM3S_MDICONTROL 0x18 /* Ethernet PHY Management MDI/MDIX Control */
+#define MII_LM_VSPECIFIC 0x10 /* Vendor-Specific */
+#define MII_LM_INTCS 0x11 /* Interrupt control/status */
+#define MII_LM_DIAGNOSTIC 0x12 /* Diagnostic */
+#define MII_LM_XCVRCONTROL 0x13 /* Transceiver Control */
+#define MII_LM_LEDCONFIG 0x17 /* LED Configuration */
+#define MII_LM_MDICONTROL 0x18 /* Ethernet PHY Management MDI/MDIX Control */
/* Micrel KS8721: 0x15, 0x1b, and 0x1f */
@@ -323,79 +323,79 @@
/* LM3S6918-specific register bit settings **********************************/
/* LM3S6918 Vendor-Specific, address 0x10 */
-#define LM3S_VSPECIFIC_RXCC (1 << 0) /* Bit 0: Receive Clock Control*/
-#define LM3S_VSPECIFIC_PCSBP (1 << 1) /* Bit 1: PCS Bypass */
-#define LM3S_VSPECIFIC_RVSPOL (1 << 4) /* Bit 4: Receive Data Polarity */
-#define LM3S_VSPECIFIC_APOL (1 << 5) /* Bit 5: Auto-Polarity Disable */
-#define LM3S_VSPECIFIC_NL10 (1 << 10) /* Bit 10: Natural Loopback Mode */
-#define LM3S_VSPECIFIC_SQEI (1 << 11) /* Bit 11: SQE Inhibit Testing */
-#define LM3S_VSPECIFIC_TXHIM (1 << 12) /* Bit 12: Transmit High Impedance Mode */
-#define LM3S_VSPECIFIC_INPOL (1 << 14) /* Bit 14: Interrupt Polarity Value*/
-#define LM3S_VSPECIFIC_RPTR (1 << 15) /* Bit 15: Repeater mode*/
+#define LM_VSPECIFIC_RXCC (1 << 0) /* Bit 0: Receive Clock Control*/
+#define LM_VSPECIFIC_PCSBP (1 << 1) /* Bit 1: PCS Bypass */
+#define LM_VSPECIFIC_RVSPOL (1 << 4) /* Bit 4: Receive Data Polarity */
+#define LM_VSPECIFIC_APOL (1 << 5) /* Bit 5: Auto-Polarity Disable */
+#define LM_VSPECIFIC_NL10 (1 << 10) /* Bit 10: Natural Loopback Mode */
+#define LM_VSPECIFIC_SQEI (1 << 11) /* Bit 11: SQE Inhibit Testing */
+#define LM_VSPECIFIC_TXHIM (1 << 12) /* Bit 12: Transmit High Impedance Mode */
+#define LM_VSPECIFIC_INPOL (1 << 14) /* Bit 14: Interrupt Polarity Value*/
+#define LM_VSPECIFIC_RPTR (1 << 15) /* Bit 15: Repeater mode*/
/* LM3S6918 Interrupt Control/Status, address 0x11 */
-#define LM3S_INTCS_ANEGCOMPINT (1 << 0) /* Bit 0: Auto-Negotiation Complete Interrupt */
-#define LM3S_INTCS_RFAULTINT (1 << 1) /* Bit 1: Remote Fault Interrupt */
-#define LM3S_INTCS_LSCHGINT (1 << 2) /* Bit 2: Link Status Change Interrupt */
-#define LM3S_INTCS_LPACKINT (1 << 3) /* Bit 3: LP Acknowledge Interrupt */
-#define LM3S_INTCS_PDFINT (1 << 4) /* Bit 4: Parallel Detection Fault Interrupt */
-#define LM3S_INTCS_PRXINT (1 << 5) /* Bit 5: Page Receive Interrupt */
-#define LM3S_INTCS_RXERINT (1 << 6) /* Bit 6: Receive Error Interrupt */
-#define LM3S_INTCS_JABBERINT (1 << 7) /* Bit 7: Jabber Event Interrupt */
-#define LM3S_INTCS_ANEGCOMPIE (1 << 8) /* Bit 8: Auto-Negotiation Complete Interrupt Enable */
-#define LM3S_INTCS_RFAULTIE (1 << 9) /* Bit 9: Remote Fault Interrupt Enable */
-#define LM3S_INTCS_LSCHGIE (1 << 10) /* Bit 10: Link Status Change Interrupt Enable */
-#define LM3S_INTCS_LPACKIE (1 << 11) /* Bit 11: LP Acknowledge Interrupt Enable */
-#define LM3S_INTCS_PDFIE (1 << 12) /* Bit 12: Parallel Detection Fault Interrupt Enable */
-#define LM3S_INTCS_PRXIE (1 << 13) /* Bit 13: Page Received Interrupt Enable */
-#define LM3S_INTCS_RXERIE (1 << 14) /* Bit 14: Receive Error Interrupt Enable */
-#define LM3S_INTCS_JABBERIE (1 << 15) /* Bit 15: Jabber Interrupt Enable */
+#define LM_INTCS_ANEGCOMPINT (1 << 0) /* Bit 0: Auto-Negotiation Complete Interrupt */
+#define LM_INTCS_RFAULTINT (1 << 1) /* Bit 1: Remote Fault Interrupt */
+#define LM_INTCS_LSCHGINT (1 << 2) /* Bit 2: Link Status Change Interrupt */
+#define LM_INTCS_LPACKINT (1 << 3) /* Bit 3: LP Acknowledge Interrupt */
+#define LM_INTCS_PDFINT (1 << 4) /* Bit 4: Parallel Detection Fault Interrupt */
+#define LM_INTCS_PRXINT (1 << 5) /* Bit 5: Page Receive Interrupt */
+#define LM_INTCS_RXERINT (1 << 6) /* Bit 6: Receive Error Interrupt */
+#define LM_INTCS_JABBERINT (1 << 7) /* Bit 7: Jabber Event Interrupt */
+#define LM_INTCS_ANEGCOMPIE (1 << 8) /* Bit 8: Auto-Negotiation Complete Interrupt Enable */
+#define LM_INTCS_RFAULTIE (1 << 9) /* Bit 9: Remote Fault Interrupt Enable */
+#define LM_INTCS_LSCHGIE (1 << 10) /* Bit 10: Link Status Change Interrupt Enable */
+#define LM_INTCS_LPACKIE (1 << 11) /* Bit 11: LP Acknowledge Interrupt Enable */
+#define LM_INTCS_PDFIE (1 << 12) /* Bit 12: Parallel Detection Fault Interrupt Enable */
+#define LM_INTCS_PRXIE (1 << 13) /* Bit 13: Page Received Interrupt Enable */
+#define LM_INTCS_RXERIE (1 << 14) /* Bit 14: Receive Error Interrupt Enable */
+#define LM_INTCS_JABBERIE (1 << 15) /* Bit 15: Jabber Interrupt Enable */
/* LM3S6918 Diagnostic, address 0x12 */
-#define LM3S_DIAGNOSTIC_RX_LOCK (1 << 8) /* Bit 8: Receive PLL Lock */
-#define LM3S_DIAGNOSTIC_RXSD (1 << 9) /* Bit 9: Receive Detection */
-#define LM3S_DIAGNOSTIC_RATE (1 << 10) /* Bit 10: Rate */
-#define LM3S_DIAGNOSTIC_DPLX (1 << 11) /* Bit 11: Duplex Mode */
-#define LM3S_DIAGNOSTIC_ANEGF (1 << 12) /* Bit 12: Auto-Negotiation Failure */
+#define LM_DIAGNOSTIC_RX_LOCK (1 << 8) /* Bit 8: Receive PLL Lock */
+#define LM_DIAGNOSTIC_RXSD (1 << 9) /* Bit 9: Receive Detection */
+#define LM_DIAGNOSTIC_RATE (1 << 10) /* Bit 10: Rate */
+#define LM_DIAGNOSTIC_DPLX (1 << 11) /* Bit 11: Duplex Mode */
+#define LM_DIAGNOSTIC_ANEGF (1 << 12) /* Bit 12: Auto-Negotiation Failure */
/* LM3S6918 Transceiver Control, address 0x13 */
-#define LM3S_XCVRCONTROL_TXO_SHIFT 14 /* Bits 15-14: Transmit Amplitude Selection */
-#define LM3S_XCVRCONTROL_TXO_MASK (3 << LM3S_XCVRCONTROL_TXO_SHIFT)
-#define LM3S_XCVRCONTROL_TXO_00DB (0 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.0dB of insertion loss */
-#define LM3S_XCVRCONTROL_TXO_04DB (1 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.4dB of insertion loss */
-#define LM3S_XCVRCONTROL_TXO_08DB (2 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 0.8dB of insertion loss */
-#define LM3S_XCVRCONTROL_TXO_12DB (3 << LM3S_XCVRCONTROL_TXO_SHIFT) /* Gain 1.2dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_SHIFT 14 /* Bits 15-14: Transmit Amplitude Selection */
+#define LM_XCVRCONTROL_TXO_MASK (3 << LM_XCVRCONTROL_TXO_SHIFT)
+#define LM_XCVRCONTROL_TXO_00DB (0 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 0.0dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_04DB (1 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 0.4dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_08DB (2 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 0.8dB of insertion loss */
+#define LM_XCVRCONTROL_TXO_12DB (3 << LM_XCVRCONTROL_TXO_SHIFT) /* Gain 1.2dB of insertion loss */
/* LM3S6918 LED Configuration, address 0x17 */
-#define LM3S_LEDCONFIG_LED0_SHIFT (0) /* Bits 3-0: LED0 Source */
-#define LM3S_LEDCONFIG_LED0_MASK (0x0f << LM3S_LEDCONFIG_LED0_SHIFT)
-#define LM3S_LEDCONFIG_LED0_LINKOK (0 << LM3S_LEDCONFIG_LED0_SHIFT) /* Link OK */
-#define LM3S_LEDCONFIG_LED0_RXTX (1 << LM3S_LEDCONFIG_LED0_SHIFT) /* RX or TX activity */
-#define LM3S_LEDCONFIG_LED0_100BASET (5 << LM3S_LEDCONFIG_LED0_SHIFT) /* 100BASE-TX mode */
-#define LM3S_LEDCONFIG_LED0_10BASET (6 << LM3S_LEDCONFIG_LED0_SHIFT) /* 10BASE-T mode */
-#define LM3S_LEDCONFIG_LED0_FDUPLEX (7 << LM3S_LEDCONFIG_LED0_SHIFT) /* Full duplex */
-#define LM3S_LEDCONFIG_LED0_OKRXTX (8 << LM3S_LEDCONFIG_LED0_SHIFT) /* Full duplex */
-#define LM3S_LEDCONFIG_LED1_SHIFT (4) /* Bits 7-4: LED1 Source */
-#define LM3S_LEDCONFIG_LED1_MASK (0x0f << LM3S_LEDCONFIG_LED1_SHIFT)
-#define LM3S_LEDCONFIG_LED1_LINKOK (0 << LM3S_LEDCONFIG_LED1_SHIFT) /* Link OK */
-#define LM3S_LEDCONFIG_LED1_RXTX (1 << LM3S_LEDCONFIG_LED1_SHIFT) /* RX or TX activity */
-#define LM3S_LEDCONFIG_LED1_100BASET (5 << LM3S_LEDCONFIG_LED1_SHIFT) /* 100BASE-TX mode */
-#define LM3S_LEDCONFIG_LED1_10BASET (6 << LM3S_LEDCONFIG_LED1_SHIFT) /* 10BASE-T mode */
-#define LM3S_LEDCONFIG_LED1_FDUPLEX (7 << LM3S_LEDCONFIG_LED1_SHIFT) /* Full duplex */
-#define LM3S_LEDCONFIG_LED1_OKRXTX (8 << LM3S_LEDCONFIG_LED1_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED0_SHIFT (0) /* Bits 3-0: LED0 Source */
+#define LM_LEDCONFIG_LED0_MASK (0x0f << LM_LEDCONFIG_LED0_SHIFT)
+#define LM_LEDCONFIG_LED0_LINKOK (0 << LM_LEDCONFIG_LED0_SHIFT) /* Link OK */
+#define LM_LEDCONFIG_LED0_RXTX (1 << LM_LEDCONFIG_LED0_SHIFT) /* RX or TX activity */
+#define LM_LEDCONFIG_LED0_100BASET (5 << LM_LEDCONFIG_LED0_SHIFT) /* 100BASE-TX mode */
+#define LM_LEDCONFIG_LED0_10BASET (6 << LM_LEDCONFIG_LED0_SHIFT) /* 10BASE-T mode */
+#define LM_LEDCONFIG_LED0_FDUPLEX (7 << LM_LEDCONFIG_LED0_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED0_OKRXTX (8 << LM_LEDCONFIG_LED0_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED1_SHIFT (4) /* Bits 7-4: LED1 Source */
+#define LM_LEDCONFIG_LED1_MASK (0x0f << LM_LEDCONFIG_LED1_SHIFT)
+#define LM_LEDCONFIG_LED1_LINKOK (0 << LM_LEDCONFIG_LED1_SHIFT) /* Link OK */
+#define LM_LEDCONFIG_LED1_RXTX (1 << LM_LEDCONFIG_LED1_SHIFT) /* RX or TX activity */
+#define LM_LEDCONFIG_LED1_100BASET (5 << LM_LEDCONFIG_LED1_SHIFT) /* 100BASE-TX mode */
+#define LM_LEDCONFIG_LED1_10BASET (6 << LM_LEDCONFIG_LED1_SHIFT) /* 10BASE-T mode */
+#define LM_LEDCONFIG_LED1_FDUPLEX (7 << LM_LEDCONFIG_LED1_SHIFT) /* Full duplex */
+#define LM_LEDCONFIG_LED1_OKRXTX (8 << LM_LEDCONFIG_LED1_SHIFT) /* Full duplex */
/* LM3S6918 MDI/MDIX Control, address 0x18 */
-#define LM3S_MDICONTROL_MDIXSD_SHIFT (0) /* Bits 3-0: Auto-Switching Seed */
-#define LM3S_MDICONTROL_MDIXSD_MASK (0x0f << LM3S_MDICONTROL_MDIXSD_SHIFT)
-#define LM3S_MDICONTROL_MDIXCM (1 << 4) /* Bit 4: Auto-Switching Complete */
-#define LM3S_MDICONTROL_MDIX (1 << 5) /* Bit 5: Auto-Switching Configuration */
-#define LM3S_MDICONTROL_AUTOSW (1 << 6) /* Bit 6: Auto-Switching Enable */
-#define LM3S_MDICONTROL_PDMODE (1 << 7) /* Bit 7: Parallel Detection Mode */
+#define LM_MDICONTROL_MDIXSD_SHIFT (0) /* Bits 3-0: Auto-Switching Seed */
+#define LM_MDICONTROL_MDIXSD_MASK (0x0f << LM_MDICONTROL_MDIXSD_SHIFT)
+#define LM_MDICONTROL_MDIXCM (1 << 4) /* Bit 4: Auto-Switching Complete */
+#define LM_MDICONTROL_MDIX (1 << 5) /* Bit 5: Auto-Switching Configuration */
+#define LM_MDICONTROL_AUTOSW (1 << 6) /* Bit 6: Auto-Switching Enable */
+#define LM_MDICONTROL_PDMODE (1 << 7) /* Bit 7: Parallel Detection Mode */
/* KS8921-specific register bit settings ************************************/
/* KS8921 MII Control register bit definitions (not in 802.3) */
@@ -430,26 +430,26 @@
/* KS8921 10BASE-TX PHY control register */
-#define KS8721_10BTCR_BIT0 (1 << 0) /* Bit 0: xxx */
-#define KS8721_10BTCR_BIT1 (1 << 1) /* Bit 1: xxx */
-#define KS8721_10BTCR_MODE_SHIFT (2) /* Bits 2-4: Operation Mode Indication */
-#define KS8721_10BTCR_MODE_MASK (7 << KS8721_10BTCR_MODE_SHIFT)
-# define KS8721_10BTCR_MODE_ANEG (0 << KS8721_10BTCR_MODE_SHIFT) /* Still in auto-negotiation */
-# define KS8721_10BTCR_MODE_10BTHD (1 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T half-duplex */
-# define KS8721_10BTCR_MODE_100BTHD (2 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE_t half-duplex */
-# define KS8721_10BTCR_MODE_DEFAULT (3 << KS8721_10BTCR_MODE_SHIFT) /* Default */
-# define KS8721_10BTCR_MODE_10BTFD (5 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T full duplex */
-# define KS8721_10BTCR_MODE_100BTFD (6 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE-T full duplex */
-# define KS8721_10BTCR_MODE_ISOLATE (7 << KS8721_10BTCR_MODE_SHIFT) /* PHY/MII isolate */
-#define KS8721_10BTCR_ISOLATE (1 << 5) /* Bit 5: PHY isolate */
-#define KS8721_10BTCR_PAUSE (1 << 6) /* Bit 6: Enable pause */
-#define KS8721_10BTCR_ANEGCOMP (1 << 7) /* Bit 7: Auto-negotiation complete */
-#define KS8721_10BTCR_JABBERE (1 << 8) /* Bit 8: Enable Jabber */
-#define KS8721_10BTCR_INTLVL (1 << 9) /* Bit 9: Interrupt level */
-#define KS8721_10BTCR_POWER (1 << 10) /* Bit 10: Power saving */
-#define KS8721_10BTCR_FORCE (1 << 11) /* Bit 11: Force link */
-#define KS8721_10BTCR_ENERGY (1 << 12) /* Bit 12: Energy detect */
-#define KS8721_10BTCR_PAIRSWAPD (1 << 13) /* Bit 13: Pairswap disable */
+#define KS8721_10BTCR_BIT0 (1 << 0) /* Bit 0: xxx */
+#define KS8721_10BTCR_BIT1 (1 << 1) /* Bit 1: xxx */
+#define KS8721_10BTCR_MODE_SHIFT (2) /* Bits 2-4: Operation Mode Indication */
+#define KS8721_10BTCR_MODE_MASK (7 << KS8721_10BTCR_MODE_SHIFT)
+# define KS8721_10BTCR_MODE_ANEG (0 << KS8721_10BTCR_MODE_SHIFT) /* Still in auto-negotiation */
+# define KS8721_10BTCR_MODE_10BTHD (1 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T half-duplex */
+# define KS8721_10BTCR_MODE_100BTHD (2 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE_t half-duplex */
+# define KS8721_10BTCR_MODE_DEFAULT (3 << KS8721_10BTCR_MODE_SHIFT) /* Default */
+# define KS8721_10BTCR_MODE_10BTFD (5 << KS8721_10BTCR_MODE_SHIFT) /* 10BASE-T full duplex */
+# define KS8721_10BTCR_MODE_100BTFD (6 << KS8721_10BTCR_MODE_SHIFT) /* 100BASE-T full duplex */
+# define KS8721_10BTCR_MODE_ISOLATE (7 << KS8721_10BTCR_MODE_SHIFT) /* PHY/MII isolate */
+#define KS8721_10BTCR_ISOLATE (1 << 5) /* Bit 5: PHY isolate */
+#define KS8721_10BTCR_PAUSE (1 << 6) /* Bit 6: Enable pause */
+#define KS8721_10BTCR_ANEGCOMP (1 << 7) /* Bit 7: Auto-negotiation complete */
+#define KS8721_10BTCR_JABBERE (1 << 8) /* Bit 8: Enable Jabber */
+#define KS8721_10BTCR_INTLVL (1 << 9) /* Bit 9: Interrupt level */
+#define KS8721_10BTCR_POWER (1 << 10) /* Bit 10: Power saving */
+#define KS8721_10BTCR_FORCE (1 << 11) /* Bit 11: Force link */
+#define KS8721_10BTCR_ENERGY (1 << 12) /* Bit 12: Energy detect */
+#define KS8721_10BTCR_PAIRSWAPD (1 << 13) /* Bit 13: Pairswap disable */
/****************************************************************************
* Type Definitions
diff --git a/nuttx/include/nuttx/nx/nxfonts.h b/nuttx/include/nuttx/nx/nxfonts.h
index f1aecb9e5..91bce0036 100644
--- a/nuttx/include/nuttx/nx/nxfonts.h
+++ b/nuttx/include/nuttx/nx/nxfonts.h
@@ -113,6 +113,11 @@
#elif defined(CONFIG_NXFONT_SERIF38X49B)
# define NXFONT_DEFAULT FONTID_SERIF38X49B
+/* Mono-space fonts */
+
+#elif defined(CONFIG_NXFONT_MONO5X8)
+# define NXFONT_DEFAULT FONTID_MONO5X8
+
#endif
/****************************************************************************
@@ -125,6 +130,12 @@ enum nx_fontid_e
{
FONTID_DEFAULT = 0 /* The default font */
+/* Monospace fonts */
+
+#ifdef CONFIG_NXFONT_MONO5X8
+ , FONTID_MONO5X8 = 18 /* The 5x8 monospace font */
+#endif
+
/* Sans Serif fonts */
#ifdef CONFIG_NXFONT_SANS17X22
diff --git a/nuttx/include/nuttx/progmem.h b/nuttx/include/nuttx/progmem.h
index ac5a65940..2da59eab1 100644
--- a/nuttx/include/nuttx/progmem.h
+++ b/nuttx/include/nuttx/progmem.h
@@ -99,7 +99,7 @@ uint16_t up_progmem_pagesize(uint16_t page);
* Address to page conversion
*
* Input Parameters:
- * addr - Address without flash offet (aligned to page0)
+ * addr - Address with of without flash offset (absolute or aligned to page0)
*
* Returned Value:
* Page or negative value on error. The following errors are reported
@@ -165,7 +165,7 @@ int up_progmem_ispageerased(uint16_t page);
* the address be aligned inside the page boundaries.
*
* Input Parameters:
- * addr - Address without flash offet (aligned to page0)
+ * addr - Address with or without flash offset (absolute or aligned to page0)
* buf - Pointer to buffer
* count - Number of bytes to write *
*
diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h
index 6eaba6e9c..b2ec1cee4 100644
--- a/nuttx/include/nuttx/sched.h
+++ b/nuttx/include/nuttx/sched.h
@@ -1,7 +1,7 @@
/********************************************************************************
* include/nuttx/sched.h
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -202,6 +202,10 @@ struct _TCB
/* Task Management Fields *****************************************************/
pid_t pid; /* This is the ID of the thread */
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ pid_t parent; /* This is the ID of the parent thread */
+ uint16_t nchildren; /* This is the number active children */
+#endif
start_t start; /* Thread start function */
entry_t entry; /* Entry Point into the thread */
@@ -223,7 +227,7 @@ struct _TCB
# endif
#endif
-#ifdef CONFIG_SCHED_WAITPID
+#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
sem_t exitsem; /* Support for waitpid */
int *stat_loc; /* Location to return exit status */
#endif
@@ -382,6 +386,32 @@ EXTERN FAR struct streamlist *sched_getstreams(void);
EXTERN FAR struct socketlist *sched_getsockets(void);
#endif /* CONFIG_NSOCKET_DESCRIPTORS */
+/* Internal vfork support.The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() is provided in architecture-specific
+ * code.
+ * 2) vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) vfork() provides any additional operating context. vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * task_vforkabort() may be called if an error occurs between steps 3 and 6.
+ */
+
+FAR _TCB *task_vforksetup(start_t retaddr);
+pid_t task_vforkstart(FAR _TCB *child);
+void task_vforkabort(FAR _TCB *child, int errcode);
+
/* sched_foreach will enumerate over each task and provide the
* TCB of each task to a user callback functions. Interrupts
* will be disabled throughout this enumeration!
diff --git a/nuttx/include/nuttx/usb/hid.h b/nuttx/include/nuttx/usb/hid.h
index 5b83f08fc..877203a9c 100644
--- a/nuttx/include/nuttx/usb/hid.h
+++ b/nuttx/include/nuttx/usb/hid.h
@@ -619,7 +619,7 @@
#define USBHID_KBDUSE_RCTRL 0xe4 /* Keyboard RightControl */
#define USBHID_KBDUSE_RSHIFT 0xe5 /* Keyboard RightShift */
#define USBHID_KBDUSE_RALT 0xe6 /* Keyboard RightAlt */
-#define USBHID_KBDUSE_RGUI 0xe7 /* Keyboard Right GUI*/
+#define USBHID_KBDUSE_RGUI 0xe7 /* Keyboard Right GUI */
#define USBHID_KBDUSE_MAX 0xe7
diff --git a/nuttx/include/nuttx/wqueue.h b/nuttx/include/nuttx/wqueue.h
index c509bf197..d56901d89 100644
--- a/nuttx/include/nuttx/wqueue.h
+++ b/nuttx/include/nuttx/wqueue.h
@@ -68,7 +68,7 @@
* CONFIG_SCHED_WORKSTACKSIZE - The stack size allocated for the worker
* thread. Default: CONFIG_IDLETHREAD_STACKSIZE.
* CONFIG_SIG_SIGWORK - The signal number that will be used to wake-up
- * the worker thread. Default: 4
+ * the worker thread. Default: 17
*
* CONFIG_SCHED_LPWORK. If CONFIG_SCHED_WORKQUEUE is defined, then a single
* work queue is created by default. If CONFIG_SCHED_LPWORK is also defined
diff --git a/nuttx/include/pthread.h b/nuttx/include/pthread.h
index 5a08f13b6..a98b9aaaa 100644
--- a/nuttx/include/pthread.h
+++ b/nuttx/include/pthread.h
@@ -41,15 +41,17 @@
********************************************************************************/
#include <nuttx/config.h> /* Default settings */
-#include <nuttx/compiler.h> /* Compiler settings */
+#include <nuttx/compiler.h> /* Compiler settings, noreturn_function */
#include <sys/types.h> /* Needed for general types */
+#include <sys/prctl.h> /* Needed by pthread_[set|get]name_np */
+
#include <stdint.h> /* C99 fixed width integer types */
#include <stdbool.h> /* C99 boolean types */
+#include <unistd.h> /* For getpid */
#include <semaphore.h> /* Needed for sem_t */
#include <signal.h> /* Needed for sigset_t */
#include <time.h> /* Needed for struct timespec */
-#include <nuttx/compiler.h> /* For noreturn_function */
/********************************************************************************
* Compilation Switches
@@ -58,10 +60,11 @@
/* Standard POSIX switches */
#ifndef _POSIX_THREADS
-#define _POSIX_THREADS
+# define _POSIX_THREADS
#endif
+
#ifndef _POSIX_THREAD_ATTR_STACKSIZE
-#define _POSIX_THREAD_ATTR_STACKSIZE
+# define _POSIX_THREAD_ATTR_STACKSIZE
#endif
/********************************************************************************
@@ -153,10 +156,8 @@
********************************************************************************/
#ifdef __cplusplus
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
+extern "C"
+{
#endif
/* pthread-specific types */
@@ -245,28 +246,29 @@ struct sched_param; /* Defined in sched.h */
* the individual attributes used by a given implementation.
*/
-EXTERN int pthread_attr_init(FAR pthread_attr_t *attr);
+int pthread_attr_init(FAR pthread_attr_t *attr);
/* An attributes object can be deleted when it is no longer needed. */
-EXTERN int pthread_attr_destroy(pthread_attr_t *attr);
+int pthread_attr_destroy(pthread_attr_t *attr);
/* Set or obtain the default scheduling algorithm */
-EXTERN int pthread_attr_setschedpolicy(FAR pthread_attr_t *attr, int policy);
-EXTERN int pthread_attr_getschedpolicy(FAR pthread_attr_t *attr, int *policy);
-EXTERN int pthread_attr_setschedparam(FAR pthread_attr_t *attr,
- FAR const struct sched_param *param);
-EXTERN int pthread_attr_getschedparam(FAR pthread_attr_t *attr,
- FAR struct sched_param *param);
-EXTERN int pthread_attr_setinheritsched(FAR pthread_attr_t *attr, int inheritsched);
-EXTERN int pthread_attr_getinheritsched(FAR const pthread_attr_t *attr,
- FAR int *inheritsched);
+int pthread_attr_setschedpolicy(FAR pthread_attr_t *attr, int policy);
+int pthread_attr_getschedpolicy(FAR pthread_attr_t *attr, int *policy);
+int pthread_attr_setschedparam(FAR pthread_attr_t *attr,
+ FAR const struct sched_param *param);
+int pthread_attr_getschedparam(FAR pthread_attr_t *attr,
+ FAR struct sched_param *param);
+int pthread_attr_setinheritsched(FAR pthread_attr_t *attr,
+ int inheritsched);
+int pthread_attr_getinheritsched(FAR const pthread_attr_t *attr,
+ FAR int *inheritsched);
/* Set or obtain the default stack size */
-EXTERN int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize);
-EXTERN int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr);
+int pthread_attr_setstacksize(FAR pthread_attr_t *attr, long stacksize);
+int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr);
/* To create a thread object and runnable thread, a routine must be specified
* as the new thread's start routine. An argument may be passed to this
@@ -275,34 +277,33 @@ EXTERN int pthread_attr_getstacksize(FAR pthread_attr_t *attr, long *stackaddr);
* about the kind of thread being created.
*/
-EXTERN int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
- pthread_startroutine_t startroutine,
- pthread_addr_t arg);
+int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
+ pthread_startroutine_t startroutine, pthread_addr_t arg);
/* A thread object may be "detached" to specify that the return value and
* completion status will not be requested.
*/
-EXTERN int pthread_detach(pthread_t thread);
+int pthread_detach(pthread_t thread);
/* A thread may terminate it's own execution or the execution of another
* thread.
*/
-EXTERN void pthread_exit(pthread_addr_t value) noreturn_function;
-EXTERN int pthread_cancel(pthread_t thread);
-EXTERN int pthread_setcancelstate(int state, FAR int *oldstate);
-EXTERN void pthread_testcancel(void);
+void pthread_exit(pthread_addr_t value) noreturn_function;
+int pthread_cancel(pthread_t thread);
+int pthread_setcancelstate(int state, FAR int *oldstate);
+void pthread_testcancel(void);
/* A thread can await termination of another thread and retrieve the return
* value of the thread.
*/
-EXTERN int pthread_join(pthread_t thread, FAR pthread_addr_t *value);
+int pthread_join(pthread_t thread, FAR pthread_addr_t *value);
/* A thread may tell the scheduler that its processor can be made available. */
-EXTERN void pthread_yield(void);
+void pthread_yield(void);
/* A thread may obtain a copy of its own thread handle. */
@@ -314,91 +315,94 @@ EXTERN void pthread_yield(void);
/* Thread scheduling parameters */
-EXTERN int pthread_getschedparam(pthread_t thread, FAR int *policy,
- FAR struct sched_param *param);
-EXTERN int pthread_setschedparam(pthread_t thread, int policy,
- FAR const struct sched_param *param);
-EXTERN int pthread_setschedprio(pthread_t thread, int prio);
+int pthread_getschedparam(pthread_t thread, FAR int *policy,
+ FAR struct sched_param *param);
+int pthread_setschedparam(pthread_t thread, int policy,
+ FAR const struct sched_param *param);
+int pthread_setschedprio(pthread_t thread, int prio);
/* Thread-specific Data Interfaces */
-EXTERN int pthread_key_create(FAR pthread_key_t *key,
- CODE void (*destructor)(FAR void*));
-EXTERN int pthread_setspecific(pthread_key_t key, FAR void *value);
-EXTERN FAR void *pthread_getspecific(pthread_key_t key);
-EXTERN int pthread_key_delete(pthread_key_t key);
+int pthread_key_create(FAR pthread_key_t *key,
+ CODE void (*destructor)(FAR void*));
+int pthread_setspecific(pthread_key_t key, FAR void *value);
+FAR void *pthread_getspecific(pthread_key_t key);
+int pthread_key_delete(pthread_key_t key);
/* Create, operate on, and destroy mutex attributes. */
-EXTERN int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr);
-EXTERN int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr);
-EXTERN int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr, FAR int *pshared);
-EXTERN int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr, int pshared);
+int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr);
+int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr);
+int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr,
+ FAR int *pshared);
+int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr,
+ int pshared);
#ifdef CONFIG_MUTEX_TYPES
-EXTERN int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);
-EXTERN int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);
+int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
#endif
/* The following routines create, delete, lock and unlock mutexes. */
-EXTERN int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr);
-EXTERN int pthread_mutex_destroy(FAR pthread_mutex_t *mutex);
-EXTERN int pthread_mutex_lock(FAR pthread_mutex_t *mutex);
-EXTERN int pthread_mutex_trylock(FAR pthread_mutex_t *mutex);
-EXTERN int pthread_mutex_unlock(FAR pthread_mutex_t *mutex);
+int pthread_mutex_init(FAR pthread_mutex_t *mutex,
+ FAR pthread_mutexattr_t *attr);
+int pthread_mutex_destroy(FAR pthread_mutex_t *mutex);
+int pthread_mutex_lock(FAR pthread_mutex_t *mutex);
+int pthread_mutex_trylock(FAR pthread_mutex_t *mutex);
+int pthread_mutex_unlock(FAR pthread_mutex_t *mutex);
/* Operations on condition variables */
-EXTERN int pthread_condattr_init(FAR pthread_condattr_t *attr);
-EXTERN int pthread_condattr_destroy(FAR pthread_condattr_t *attr);
+int pthread_condattr_init(FAR pthread_condattr_t *attr);
+int pthread_condattr_destroy(FAR pthread_condattr_t *attr);
/* A thread can create and delete condition variables. */
-EXTERN int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr);
-EXTERN int pthread_cond_destroy(FAR pthread_cond_t *cond);
+int pthread_cond_init(FAR pthread_cond_t *cond, FAR pthread_condattr_t *attr);
+int pthread_cond_destroy(FAR pthread_cond_t *cond);
/* A thread can signal to and broadcast on a condition variable. */
-EXTERN int pthread_cond_broadcast(FAR pthread_cond_t *cond);
-EXTERN int pthread_cond_signal(FAR pthread_cond_t *cond);
+int pthread_cond_broadcast(FAR pthread_cond_t *cond);
+int pthread_cond_signal(FAR pthread_cond_t *cond);
/* A thread can wait for a condition variable to be signalled or broadcast. */
-EXTERN int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex);
+int pthread_cond_wait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex);
/* A thread can perform a timed wait on a condition variable. */
-EXTERN int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
- FAR const struct timespec *abstime);
+int pthread_cond_timedwait(FAR pthread_cond_t *cond,
+ FAR pthread_mutex_t *mutex,
+ FAR const struct timespec *abstime);
/* Barrier attributes */
-EXTERN int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr);
-EXTERN int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr);
-EXTERN int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr,
- FAR int *pshared);
-EXTERN int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr,
- int pshared);
+int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr);
+int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr);
+int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr,
+ FAR int *pshared);
+int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr,
+ int pshared);
/* Barriers */
-EXTERN int pthread_barrier_destroy(FAR pthread_barrier_t *barrier);
-EXTERN int pthread_barrier_init(FAR pthread_barrier_t *barrier,
+int pthread_barrier_destroy(FAR pthread_barrier_t *barrier);
+int pthread_barrier_init(FAR pthread_barrier_t *barrier,
FAR const pthread_barrierattr_t *attr,
unsigned int count);
-EXTERN int pthread_barrier_wait(FAR pthread_barrier_t *barrier);
+int pthread_barrier_wait(FAR pthread_barrier_t *barrier);
/* Pthread initialization */
-EXTERN int pthread_once(FAR pthread_once_t *once_control,
+int pthread_once(FAR pthread_once_t *once_control,
CODE void (*init_routine)(void));
/* Pthread signal management APIs */
-EXTERN int pthread_kill(pthread_t thread, int sig);
-EXTERN int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
+int pthread_kill(pthread_t thread, int sig);
+int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset);
-#undef EXTERN
#ifdef __cplusplus
}
#endif
diff --git a/nuttx/include/semaphore.h b/nuttx/include/semaphore.h
index 257a5826f..203118bd6 100644
--- a/nuttx/include/semaphore.h
+++ b/nuttx/include/semaphore.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/semaphore.h
*
- * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -103,9 +103,13 @@ typedef struct sem_s sem_t;
/* Initializers */
#ifdef CONFIG_PRIORITY_INHERITANCE
-# define SEM_INITIALIZER(c) {(c), SEMHOLDER_INITIALIZER}
+# if CONFIG_SEM_PREALLOCHOLDERS > 0
+# define SEM_INITIALIZER(c) {(c), NULL} /* semcount, hhead */
+# else
+# define SEM_INITIALIZER(c) {(c), SEMHOLDER_INITIALIZER} /* semcount, holder */
+# endif
#else
-# define SEM_INITIALIZER(c) {(c)}
+# define SEM_INITIALIZER(c) {(c)} /* semcount */
#endif
/****************************************************************************
diff --git a/nuttx/include/signal.h b/nuttx/include/signal.h
index 02b222343..30726105b 100644
--- a/nuttx/include/signal.h
+++ b/nuttx/include/signal.h
@@ -66,44 +66,56 @@
/* A few of the real time signals are used within the OS. They have
* default values that can be overridden from the configuration file. The
- * rest are all user signals:
+ * rest are all user signals.
+ *
+ * These are semi-standard signal definitions:
*/
#ifndef CONFIG_SIG_SIGUSR1
-#define SIGUSR1 0 /* User signal 1 */
+# define SIGUSR1 1 /* User signal 1 */
#else
-#define SIGUSR1 CONFIG_SIG_SIGUSR1
+# define SIGUSR1 CONFIG_SIG_SIGUSR1
#endif
#ifndef CONFIG_SIG_SIGUSR2
-#define SIGUSR2 1 /* User signal 2 */
+# define SIGUSR2 2 /* User signal 2 */
#else
-#define SIGUSR2 CONFIG_SIG_SIGUSR2
+# define SIGUSR2 CONFIG_SIG_SIGUSR2
#endif
#ifndef CONFIG_SIG_SIGALARM
-#define SIGALRM 2 /* Default signal used with POSIX timers (used only */
+# define SIGALRM 3 /* Default signal used with POSIX timers (used only */
/* no other signal is provided) */
#else
-#define SIGALRM CONFIG_SIG_SIGALARM
+# define SIGALRM CONFIG_SIG_SIGALARM
#endif
-#ifndef CONFIG_DISABLE_PTHREAD
-#ifndef CONFIG_SIG_SIGCONDTIMEDOUT
-#define SIGCONDTIMEDOUT 3 /* Used in the implementation of pthread_cond_timedwait */
-#else
-#define SIGCONDTIMEDOUT CONFIG_SIG_SIGCONDTIMEDOUT
+#ifdef CONFIG_SCHED_HAVE_PARENT
+# ifndef CONFIG_SIG_SIGCHLD
+# define SIGCHLD 4 /* Used by child threads to signal parent thread */
+# else
+# define SIGCHLD CONFIG_SIG_SIGCHLD
+# endif
#endif
+
+/* The following are non-standard signal definitions */
+
+#ifndef CONFIG_DISABLE_PTHREAD
+# ifndef CONFIG_SIG_SIGCONDTIMEDOUT
+# define SIGCONDTIMEDOUT 16 /* Used in the implementation of pthread_cond_timedwait */
+# else
+# define SIGCONDTIMEDOUT CONFIG_SIG_SIGCONDTIMEDOUT
+# endif
#endif
/* SIGWORK is used to wake up various internal, NuttX worker thread */
#if defined(CONFIG_SCHED_WORKQUEUE) || defined(CONFIG_PAGING)
-#ifndef CONFIG_SIG_SIGWORK
-#define SIGWORK 4 /* Used to wake up the work queue */
-#else
-#define SIGWORK CONFIG_SIG_SIGWORK
-#endif
+# ifndef CONFIG_SIG_SIGWORK
+# define SIGWORK 17 /* Used to wake up the work queue */
+# else
+# define SIGWORK CONFIG_SIG_SIGWORK
+# endif
#endif
/* sigprocmask() "how" definitions. Only one of the following can be specified: */
@@ -122,12 +134,18 @@
/* These are the possible values of the signfo si_code field */
-#define SI_USER 0 /* Signal sent from kill, raise, or abort */
-#define SI_QUEUE 1 /* Signal sent from sigqueue */
-#define SI_TIMER 2 /* Signal is result of timer expiration */
-#define SI_ASYNCIO 3 /* Signal is the result of asynch IO completion */
-#define SI_MESGQ 4 /* Signal generated by arrival of a message on an */
- /* empty message queue */
+#define SI_USER 0 /* Signal sent from kill, raise, or abort */
+#define SI_QUEUE 1 /* Signal sent from sigqueue */
+#define SI_TIMER 2 /* Signal is result of timer expiration */
+#define SI_ASYNCIO 3 /* Signal is the result of asynch IO completion */
+#define SI_MESGQ 4 /* Signal generated by arrival of a message on an */
+ /* empty message queue */
+#define CLD_EXITED 5 /* Child has exited (SIGCHLD only) */
+#define CLD_KILLED 6 /* Child was killed (SIGCHLD only) */
+#define CLD_DUMPED 7 /* Child terminated abnormally (SIGCHLD only) */
+#define CLD_TRAPPED 8 /* Traced child has trapped (SIGCHLD only) */
+#define CLD_STOPPED 9 /* Child has stopped (SIGCHLD only) */
+#define CLD_CONTINUED 10 /* Stopped child had continued (SIGCHLD only) */
/* Values for the sigev_notify field of struct sigevent */
@@ -175,6 +193,10 @@ struct siginfo
uint8_t si_signo; /* Identifies signal */
uint8_t si_code; /* Source: SI_USER, SI_QUEUE, SI_TIMER, SI_ASYNCIO, or SI_MESGQ */
union sigval si_value; /* Data passed with signal */
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ pid_t si_pid; /* Sending task ID */
+ int si_status; /* Exit value or signal (SIGCHLD only). */
+#endif
};
typedef struct siginfo siginfo_t;
diff --git a/nuttx/include/spawn.h b/nuttx/include/spawn.h
new file mode 100644
index 000000000..5e0ce3416
--- /dev/null
+++ b/nuttx/include/spawn.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+ * include/spawn.h
+ *
+ * Copyright (C) 2013 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_SPAWN_H
+#define __INCLUDE_SPAWN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <sched.h>
+#include <signal.h>
+#include <errno.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* "The spawn.h header shall define the flags that may be set in a
+ * posix_spawnattr_t object using the posix_spawnattr_setflags() function:"
+ */
+
+#define POSIX_SPAWN_RESETIDS (1 << 0) /* 1: Reset effective user ID */
+#define POSIX_SPAWN_SETPGROUP (1 << 1) /* 1: Set process group */
+#define POSIX_SPAWN_SETSCHEDPARAM (1 << 2) /* 1: Set task's priority */
+#define POSIX_SPAWN_SETSCHEDULER (1 << 3) /* 1: Set task's scheduler policy */
+#define POSIX_SPAWN_SETSIGDEF (1 << 4) /* 1: Set default signal actions */
+#define POSIX_SPAWN_SETSIGMASK (1 << 5) /* 1: Set sigmask */
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+/* "The spawn.h header shall define the posix_spawnattr_t and
+ * posix_spawn_file_actions_t types used in performing spawn operations.
+ *
+ * The internal structure underlying the posix_spawnattr_t is exposed here
+ * because the user will be required to allocate this memory.
+ */
+
+struct posix_spawnattr_s
+{
+ uint8_t flags;
+ uint8_t priority;
+ uint8_t policy;
+#ifndef CONFIG_DISABLE_SIGNALS
+ sigset_t sigmask;
+#endif
+};
+
+typedef struct posix_spawnattr_s posix_spawnattr_t;
+
+/* posix_spawn_file_actions_addclose(), posix_spawn_file_actions_adddup2(),
+ * and posix_spawn_file_actions_addopen() will allocate memory and append
+ * a new file action to an instance of posix_spawn_file_actions_t. The
+ * internal representation of these structures is not exposed to the user.
+ * The user need only know that the size sizeof(posix_spawn_file_actions_t)
+ * will hold a pointer to data.
+ */
+
+typedef FAR void *posix_spawn_file_actions_t;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+/* "The following shall be declared as functions and may also be defined as
+ * macros. Function prototypes shall be provided."
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* posix_spawn[p] interfaces ************************************************/
+
+#ifdef CONFIG_BINFMT_EXEPATH
+int posix_spawnp(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[]);
+#define posix_spawn(pid,path,file_actions,attr,argv,envp) \
+ posix_spawnp(pid,path,file_actions,attr,argv,envp)
+#else
+int posix_spawn(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[]);
+#endif
+
+/* File action interfaces ***************************************************/
+/* File action initialization and destruction */
+
+int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions);
+int posix_spawn_file_actions_destroy(FAR posix_spawn_file_actions_t *file_actions);
+
+/* Add file action interfaces */
+
+int posix_spawn_file_actions_addclose(FAR posix_spawn_file_actions_t *file_actions,
+ int fd);
+int posix_spawn_file_actions_adddup2(FAR posix_spawn_file_actions_t *file_actions,
+ int fd1, int fd2);
+int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions,
+ int fd, FAR const char *path, int oflags, mode_t mode);
+
+/* Spawn attributes interfaces **********************************************/
+/* Spawn attributes initialization and destruction */
+
+int posix_spawnattr_init(FAR posix_spawnattr_t *attr);
+
+/* int posix_spawnattr_destroy(FAR posix_spawnattr_t *); */
+#ifdef CONFIG_DEBUG
+# define posix_spawnattr_destroy(attr) (attr ? 0 : EINVAL)
+#else
+# define posix_spawnattr_destroy(attr) (0)
+#endif
+
+/* Get spawn attributes interfaces */
+
+int posix_spawnattr_getflags(FAR const posix_spawnattr_t *attr, FAR short *flags);
+#define posix_spawnattr_getpgroup(attr,group) (ENOSYS)
+int posix_spawnattr_getschedparam(FAR const posix_spawnattr_t *attr,
+ FAR struct sched_param *param);
+int posix_spawnattr_getschedpolicy(FAR const posix_spawnattr_t *attr,
+ FAR int *policy);
+#define posix_spawnattr_getsigdefault(attr,sigdefault) (ENOSYS)
+#ifndef CONFIG_DISABLE_SIGNALS
+int posix_spawnattr_getsigmask(FAR const posix_spawnattr_t *attr,
+ FAR sigset_t *sigmask);
+#else
+# define posix_spawnattr_getsigmask(attr,sigmask) (ENOSYS)
+#endif
+
+/* Set spawn attributes interfaces */
+
+int posix_spawnattr_setflags(FAR posix_spawnattr_t *attr, short flags);
+#define posix_spawnattr_setpgroup(attr,group) (ENOSYS)
+int posix_spawnattr_setschedparam(FAR posix_spawnattr_t *attr,
+ FAR const struct sched_param *param);
+int posix_spawnattr_setschedpolicy(FAR posix_spawnattr_t *attr, int policy);
+#define posix_spawnattr_setsigdefault(attr,sigdefault) (ENOSYS)
+#ifndef CONFIG_DISABLE_SIGNALS
+int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr,
+ FAR const sigset_t *sigmask);
+#else
+# define posix_spawnattr_setsigmask(attr,sigmask) (ENOSYS)
+#endif
+
+/* Non standard debug functions */
+
+#ifdef CONFIG_DEBUG
+void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions);
+void posix_spawnattr_dump(FAR posix_spawnattr_t *attr);
+#else
+# define posix_spawn_file_actions_dump(fa)
+# define posix_spawnattr_dump(a)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_SPAWN_H */
diff --git a/nuttx/include/stdbool.h b/nuttx/include/stdbool.h
index 9c16aee29..6c3302549 100644
--- a/nuttx/include/stdbool.h
+++ b/nuttx/include/stdbool.h
@@ -90,8 +90,8 @@
# define bool _Bool8
#endif
-#define true 1
-#define false 0
+#define true (bool)1
+#define false (bool)0
#define __bool_true_false_are_defined 1
diff --git a/nuttx/include/sys/types.h b/nuttx/include/sys/types.h
index 2ae69d4a7..95feee72e 100644
--- a/nuttx/include/sys/types.h
+++ b/nuttx/include/sys/types.h
@@ -154,7 +154,9 @@ typedef uint16_t dev_t;
typedef uint16_t ino_t;
-/* pid_t is used for process IDs and process group IDs */
+/* pid_t is used for process IDs and process group IDs. It must be signed because
+ * negative PID values are used to represent invalid PIDs.
+ */
typedef int pid_t;
diff --git a/nuttx/include/sys/wait.h b/nuttx/include/sys/wait.h
index 6af1e971e..2476adef9 100644
--- a/nuttx/include/sys/wait.h
+++ b/nuttx/include/sys/wait.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/sys/wait.h
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -66,7 +66,7 @@
#define WTERMSIG(s) (false) /* Return signal number that caused process to terminate */
/* The following symbolic constants are possible values for the options
- * argument to waitpi(1) (1) and/or waitid() (2),
+ * argument to waitpid() (1) and/or waitid() (2),
*/
#define WCONTINUED (1 << 0) /* Status for child that has been continued (1)(2) */
@@ -104,9 +104,9 @@ extern "C" {
#define EXTERN extern
#endif
-EXTERN pid_t wait(int *stat_loc);
-EXTERN int waitid(idtype_t idtype, id_t id, siginfo_t *siginfo, int options);
-EXTERN pid_t waitpid(pid_t pid, int *stat_loc, int options);
+EXTERN pid_t wait(FAR int *stat_loc);
+EXTERN int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options);
+EXTERN pid_t waitpid(pid_t pid, FAR int *stat_loc, int options);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/unistd.h b/nuttx/include/unistd.h
index 681ce9e63..46eb14cdd 100644
--- a/nuttx/include/unistd.h
+++ b/nuttx/include/unistd.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/unistd.h
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -129,6 +129,7 @@ EXTERN int optopt; /* unrecognized option character */
/* Task Control Interfaces */
+EXTERN pid_t vfork(void);
EXTERN pid_t getpid(void);
EXTERN void _exit(int status) noreturn_function;
EXTERN unsigned int sleep(unsigned int seconds);
@@ -159,6 +160,19 @@ EXTERN FAR char *getcwd(FAR char *buf, size_t size);
EXTERN int unlink(FAR const char *pathname);
EXTERN int rmdir(FAR const char *pathname);
+/* Execution of programs from files */
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+EXTERN int execl(FAR const char *path, ...);
+EXTERN int execv(FAR const char *path, FAR char *const argv[]);
+
+/* Non-standard functions to manage symbol tables */
+
+struct symtab_s; /* See include/nuttx/binfmt/symtab.h */
+EXTERN void exec_getsymtab(FAR const struct symtab_s **symtab, FAR int *nsymbols);
+EXTERN void exec_setsymtab(FAR const struct symtab_s *symtab, int nsymbols);
+#endif
+
/* Other */
EXTERN int getopt(int argc, FAR char *const argv[], FAR const char *optstring);
diff --git a/nuttx/libc/Kconfig b/nuttx/libc/Kconfig
index bd470be7f..72a6a5346 100644
--- a/nuttx/libc/Kconfig
+++ b/nuttx/libc/Kconfig
@@ -3,6 +3,8 @@
# see misc/tools/kconfig-language.txt.
#
+comment "Standard C Library Options"
+
config STDIO_BUFFER_SIZE
int "C STDIO buffer size"
default 64
@@ -69,6 +71,67 @@ config EOL_IS_EITHER_CRLF
endchoice
+config LIBC_EXECFUNCS
+ bool "Enable exec[l|v] / posix_spawn() Support"
+ default n
+ depends on !BINFMT_DISABLE
+ ---help---
+ Enable support for the exec[l|v] family of functions that can be
+ used to start other programs, terminating the current program and
+ the posix_spawn() familty of functions that can be used start other
+ programs without terminating the current program. The typical
+ usage of the exec[l|v] functions is (1) first call vfork() to create
+ a new thread, then (2) call exec[l|v] to replace the new thread with
+ a program from the file system.
+
+ NOTE 1: This two step process start is completely unnecessary in
+ NuttX and is provided only for compatibily with Unix systems. These
+ functions are essentially just wrapper functions that (1) call the
+ non-standard binfmt function 'exec', and then (2) exit(0). Since
+ the new thread will be terminated by the exec[l|v] call, it really
+ served no purpose other than to suport Unix compatility.
+
+ The posix_spawn() functions do not have this inefficiency.
+
+ NOTE 2: Support for exec[l|v] and posix_spawn() is conditional
+ because they require additional support for symbol tables that
+ will not be available in the typical system.
+
+if LIBC_EXECFUNCS
+
+config EXECFUNCS_SYMTAB
+ string "Symbol table used by exec[l|v]"
+ default "g_symtab"
+ ---help---
+ The exec[l|v] and posix_spawn() functions are wrapper functions that
+ call the non-standard binfmt function 'exec'). The binfmt
+ function 'exec' needs to have (1) a symbol table that provides the
+ list of symbols exported by the base code, and (2) the number of
+ symbols in that table. This selection provides the name of that
+ symbol table.
+
+config EXECFUNCS_NSYMBOLS
+ int "Number of Symbols in the Table"
+ default 0
+ ---help---
+ The exec[l|v] and posix_spawn() functions are wrapper functions that
+ call the non-standard binfmt function 'exec'). The binfmt
+ function 'exec' needs to have (1) a symbol table that provides the
+ list of symbols exported by the base code, and (2) the number of
+ symbols in that table. This selection provides the number of
+ symbols in the symbol table.
+
+config POSIX_SPAWN_STACKSIZE
+ int "posix_spawn Stack Size"
+ default 1024
+ ---help---
+ If posix_spawn[p] uses I/O redirection options, then it will require
+ an intermediary/proxy task to muck with the file descriptors. This
+ configuration item specifies the stack size used for the proxy. Default:
+ 1024 bytes.
+
+endif
+
config LIBC_STRERROR
bool "Enable strerror"
default n
@@ -273,3 +336,29 @@ config ARCH_BZERO
of bzero().
endif
+
+comment "Non-standard Helper Functions"
+
+config LIB_KBDCODEC
+ bool "Keyboard CODEC"
+ default n
+ ---help---
+ In NuttX, a keyboard/keypad driver is simply a character driver that
+ may have an (optional) encoding/decoding layer on the data returned
+ by the character driver. A keyboard may return simple text data
+ (alphabetic, numeric, and punctuaction) or control characters
+ (enter, control-C, etc.). We can think about this the normal
+ "in-band" keyboard data stream. However, in addition, most
+ keyboards support actions that cannot be represented as text data.
+ Such actions include things like cursor controls (home, up arrow,
+ page down, etc.), editing functions (insert, delete, etc.), volume
+ controls, (mute, volume up, etc.) and other special functions. We
+ can think about this as special, "out-of-band" keyboard commands.
+ In this case, some special encoding may be required to multiplex
+ the in-band text data and out-of-band command streams.
+
+ This option enables the functions that implement the encoding and
+ decoding of keyboard data. These are the interfaces prototyped in
+ include/nuttx/input/kbd_codec.h. While not correctly a part of
+ the C library, it is included here because the decoding side of this
+ interface must be accessible by end user programs.
diff --git a/nuttx/libc/Makefile b/nuttx/libc/Makefile
index 22dbba1d9..a76620585 100644
--- a/nuttx/libc/Makefile
+++ b/nuttx/libc/Makefile
@@ -57,6 +57,7 @@ include time/Make.defs
include libgen/Make.defs
include dirent/Make.defs
include termios/Make.defs
+include spawn/Make.defs
include queue/Make.defs
include misc/Make.defs
diff --git a/nuttx/libc/math/Kconfig b/nuttx/libc/math/Kconfig
index c24bfd53f..db9dfae63 100644
--- a/nuttx/libc/math/Kconfig
+++ b/nuttx/libc/math/Kconfig
@@ -4,7 +4,7 @@
#
config LIBM
- bool "Math library"
+ bool "Standard Math library"
default n
depends on !ARCH_MATH_H
---help---
diff --git a/nuttx/libc/misc/Make.defs b/nuttx/libc/misc/Make.defs
index f4284ac60..0d3c87d9d 100644
--- a/nuttx/libc/misc/Make.defs
+++ b/nuttx/libc/misc/Make.defs
@@ -63,6 +63,12 @@ CSRCS += lib_match.c
CSRCS += lib_crc32.c
CSRCS += lib_dbg.c lib_dumpbuffer.c
+# Keyboard driver encoder/decoder
+
+ifeq ($(CONFIG_LIB_KBDCODEC),y)
+CSRCS += lib_kbdencode.c lib_kbddecode.c
+endif
+
# Add the misc directory to the build
DEPPATH += --dep-path misc
diff --git a/nuttx/libc/misc/lib_filesem.c b/nuttx/libc/misc/lib_filesem.c
index 5cc4624ec..f38ff5f23 100644
--- a/nuttx/libc/misc/lib_filesem.c
+++ b/nuttx/libc/misc/lib_filesem.c
@@ -67,8 +67,8 @@
void lib_sem_initialize(FAR struct file_struct *stream)
{
- /* Initialize the LIB semaphore to one (to support one-at-
- * a-time access to private data sets.
+ /* Initialize the LIB semaphore to one (to support one-at-a-time access
+ * to private data sets.
*/
(void)sem_init(&stream->fs_sem, 0, 1);
@@ -98,13 +98,13 @@ void lib_take_semaphore(FAR struct file_struct *stream)
/* Take the semaphore (perhaps waiting) */
while (sem_wait(&stream->fs_sem) != 0)
- {
- /* The only case that an error should occr here is if
- * the wait was awakened by a signal.
- */
+ {
+ /* The only case that an error should occr here is if the wait
+ * was awakened by a signal.
+ */
- ASSERT(get_errno() == EINTR);
- }
+ ASSERT(get_errno() == EINTR);
+ }
/* We have it. Claim the stak and return */
diff --git a/nuttx/libc/misc/lib_kbddecode.c b/nuttx/libc/misc/lib_kbddecode.c
new file mode 100644
index 000000000..62554902c
--- /dev/null
+++ b/nuttx/libc/misc/lib_kbddecode.c
@@ -0,0 +1,267 @@
+/****************************************************************************
+ * libc/msic/lib_kbddecode.c
+ * Decoding side of the Keyboard CODEC
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: 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 <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/streams.h>
+#include <nuttx/ascii.h>
+#include <nuttx/input/kbd_codec.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#define NDX_ESC 0
+#define NDX_BRACKET 1
+#define NDX_CODE 2
+#define NDX_TERMINATOR 3
+
+#define NCH_ESC 1
+#define NCH_BRACKET 2
+#define NCH_CODE 3
+#define NCH_TERMINATOR 4
+
+#define TERM_MIN ('a' + KBD_RELEASE)
+#define TERM_MAX ('a' + KBD_SPECREL)
+#define TERM_RETURN(a) ((a) - 'a')
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_reget
+ *
+ * Description:
+ * We have unused characters from the last, unsuccessful. Return one of
+ * these instead of the .
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location character to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * kbd_keycode_e
+ *
+ * Returned Value:
+ * KBD_PRESS - Indicates the successful receipt of norma keyboard data.
+ *
+ ****************************************************************************/
+
+static int kbd_reget(FAR struct kbd_getstate_s *state, FAR uint8_t *pch)
+{
+ /* Return the next character */
+
+ *pch = state->buf[state->ndx];
+ state->ndx++;
+ state->nch--;
+ return KBD_PRESS;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_decode
+ *
+ * Description:
+ * Get one byte of data or special command from the driver provided input
+ * buffer.
+ *
+ * Input Parameters:
+ * stream - An instance of lib_instream_s to do the low-level get
+ * operation.
+ * pch - The location to save the returned value. This may be
+ * either a normal, character code or a special command from enum
+ * kbd_keycode_e
+ * state - A user provided buffer to support parsing. This structure
+ * should be cleared the first time that kbd_decode is called.
+ *
+ * Returned Value:
+ *
+ * KBD_PRESS - Indicates the successful receipt of normal, keyboard data.
+ * This corresponds to a keypress event. The returned value in pch is a
+ * simple byte of text or control data corresponding to the pressed key.
+ * KBD_RELEASE - Indicates a key release event. The returned value in pch
+ * is the byte of text or control data corresponding to the released key.
+ * KBD_SPECPRESS - Indicates the successful receipt of a special keyboard
+ * command. The returned value in pch is a value from enum kbd_getstate_s.
+ * KBD_SPECREL - Indicates a special key release event. The returned value
+ * in pch is a value from enum kbd_getstate_s.
+ * EOF - An error has getting the next character (reported by the stream).
+ * Normally indicates the end of file.
+ *
+ ****************************************************************************/
+
+int kbd_decode(FAR struct lib_instream_s *stream,
+ FAR struct kbd_getstate_s *state, FAR uint8_t *pch)
+{
+ int ch;
+
+ DEBUGASSERT(stream && state && pch);
+
+ /* Are their ungotten characters from the last, failed parse? */
+
+ if (state->nch > 0)
+ {
+ /* Yes, return the next ungotten character */
+
+ return kbd_reget(state, pch);
+ }
+
+ state->ndx = 0;
+
+ /* No, ungotten characters. Check for the beginning of an ESC sequence. */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream */
+
+ return KBD_ERROR;
+ }
+ else
+ {
+ state->buf[NDX_ESC] = (uint8_t)ch;
+ state->nch = NCH_ESC;
+
+ if (ch != ASCII_ESC)
+ {
+ /* Not the beginning of an escape sequence. Return the character. */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* Check for ESC-[ */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Return the escape character now. We will
+ * return the EOF indication next time.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ else
+ {
+ state->buf[NDX_BRACKET] = ch;
+ state->nch = NCH_BRACKET;
+
+ if (ch != '[')
+ {
+ /* Not the beginning of an escape sequence. Return the ESC now,
+ * return the following character later.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* Get and verify the special keyboard data to decode */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Unget everything and return the ESC character.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ else
+ {
+ state->buf[NDX_CODE] = (uint8_t)ch;
+ state->nch = NCH_CODE;
+
+ /* Check for a valid special command code */
+
+ if (ch < FIRST_KEYCODE || ch > LAST_KEYCODE)
+ {
+ /* Not a special command code, return the ESC now and the next two
+ * characters later.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* Check for the final semicolon */
+
+ ch = stream->get(stream);
+ if (ch == EOF)
+ {
+ /* End of file/stream. Unget everything and return the ESC character.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ else
+ {
+ state->buf[NDX_TERMINATOR] = (uint8_t)ch;
+ state->nch = NCH_TERMINATOR;
+
+ /* Check for a valid special command code */
+
+ if (ch < TERM_MIN || ch > TERM_MAX)
+ {
+ /* Not a special command code, return the ESC now and the next two
+ * characters later.
+ */
+
+ return kbd_reget(state, pch);
+ }
+ }
+
+ /* We have successfully parsed the the entire escape sequence. Return the
+ * keyboard value in pch and the value an indication determined by the
+ * terminating character.
+ */
+
+ *pch = state->buf[NDX_CODE];
+ state->nch = 0;
+ return TERM_RETURN(state->buf[NDX_TERMINATOR]);
+}
+
diff --git a/nuttx/libc/misc/lib_kbdencode.c b/nuttx/libc/misc/lib_kbdencode.c
new file mode 100644
index 000000000..80138ca80
--- /dev/null
+++ b/nuttx/libc/misc/lib_kbdencode.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * libc/msic/lib_kbdencode.c
+ * Encoding side of the Keyboard CODEC
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Authors: 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 <stdint.h>
+#include <assert.h>
+
+#include <nuttx/streams.h>
+#include <nuttx/ascii.h>
+#include <nuttx/input/kbd_codec.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_encode
+ *
+ * Description:
+ * Encode one special special sequence command into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ * terminator - Escape sequence terminating character.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void kbd_encode(uint8_t keycode, FAR struct lib_outstream_s *stream,
+ uint8_t terminator)
+{
+ stream->put(stream, ASCII_ESC);
+ stream->put(stream, '[');
+ stream->put(stream, (int)keycode);
+ stream->put(stream, terminator);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kbd_release
+ *
+ * Description:
+ * Encode the release of a normal key.
+ *
+ * Input Parameters:
+ * ch - The character associated with the key that was releared.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_release(uint8_t ch, FAR struct lib_outstream_s *stream)
+{
+ kbd_encode(ch, stream, ('a' + KBD_RELEASE));
+}
+
+/****************************************************************************
+ * Name: kbd_specpress
+ *
+ * Description:
+ * Denotes a special key press event. Put one special keyboard command
+ * into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specpress(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream)
+{
+ DEBUGASSERT(stream && keycode >= KEYCODE_FWDDEL && keycode <= LAST_KEYCODE);
+ kbd_encode((uint8_t)keycode, stream, ('a' + KBD_SPECPRESS));
+}
+
+/****************************************************************************
+ * Name: kbd_specrel
+ *
+ * Description:
+ * Denotes a special key release event. Put one special keyboard
+ * command into the output stream.
+ *
+ * Input Parameters:
+ * keycode - The command to be added to the output stream.
+ * stream - An instance of lib_outstream_s to do the low-level put
+ * operation.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void kbd_specrel(enum kbd_keycode_e keycode,
+ FAR struct lib_outstream_s *stream)
+{
+ DEBUGASSERT(stream && keycode >= KEYCODE_FWDDEL && keycode <= LAST_KEYCODE);
+ kbd_encode((uint8_t)keycode, stream, ('a' + KBD_SPECREL));
+}
diff --git a/nuttx/libc/misc/lib_streamsem.c b/nuttx/libc/misc/lib_streamsem.c
index e38298bdb..3397f9907 100644
--- a/nuttx/libc/misc/lib_streamsem.c
+++ b/nuttx/libc/misc/lib_streamsem.c
@@ -86,5 +86,3 @@ void stream_semgive(FAR struct streamlist *list)
{
sem_post(&list->sl_sem);
}
-
-
diff --git a/nuttx/libc/spawn/Make.defs b/nuttx/libc/spawn/Make.defs
new file mode 100644
index 000000000..99ee781ce
--- /dev/null
+++ b/nuttx/libc/spawn/Make.defs
@@ -0,0 +1,65 @@
+############################################################################
+# libc/spawn/Make.defs
+#
+# Copyright (C) 2013 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.
+#
+############################################################################
+
+# Add the spawn C files to the build
+
+ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
+
+CSRCS += lib_ps.c
+
+CSRCS += lib_psfa_addaction.c lib_psfa_addclose.c lib_psfa_adddup2.c
+CSRCS += lib_psfa_addopen.c lib_psfa_destroy.c lib_psfa_init.c
+
+ifeq ($(CONFIG_DEBUG),y)
+CSRCS += lib_psfa_dump.c
+endif
+
+CSRCS += lib_psa_getflags.c lib_psa_getschedparam.c lib_psa_getschedpolicy.c
+CSRCS += lib_psa_init.c lib_psa_setflags.c lib_psa_setschedparam.c
+CSRCS += lib_psa_setschedpolicy.c
+
+ifneq ($(CONFIG_DISABLE_SIGNALS),y)
+CSRCS += lib_psa_getsigmask.c lib_psa_setsigmask.c
+endif
+
+ifeq ($(CONFIG_DEBUG),y)
+CSRCS += lib_psa_dump.c
+endif
+
+# Add the spawn directory to the build
+
+DEPPATH += --dep-path spawn
+VPATH += :spawn
+endif
diff --git a/nuttx/libc/spawn/lib_ps.c b/nuttx/libc/spawn/lib_ps.c
new file mode 100644
index 000000000..638b27f87
--- /dev/null
+++ b/nuttx/libc/spawn/lib_ps.c
@@ -0,0 +1,623 @@
+/****************************************************************************
+ * libc/string/lib_ps.c
+ *
+ * Copyright (C) 2013 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 <semaphore.h>
+#include <signal.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/binfmt.h>
+
+#include "spawn/spawn.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct spawn_parms_s
+{
+ int result;
+ FAR pid_t *pid;
+ FAR const char *path;
+ FAR const posix_spawn_file_actions_t *file_actions;
+ FAR const posix_spawnattr_t *attr;
+ FAR char *const *argv;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_ps_parmsem = SEM_INITIALIZER(1);
+static sem_t g_ps_execsem = SEM_INITIALIZER(0);
+static struct spawn_parms_s g_ps_parms;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ps_semtake and ps_semgive
+ *
+ * Description:
+ * Give and take semaphores
+ *
+ * Input Parameters:
+ *
+ * sem - The semaphore to act on.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void ps_semtake(FAR sem_t *sem)
+{
+ int ret;
+
+ do
+ {
+ ret = sem_wait(sem);
+ ASSERT(ret == 0 || errno == EINTR);
+ }
+ while (ret != 0);
+}
+
+#define ps_semgive(sem) sem_post(sem)
+
+/****************************************************************************
+ * Name: ps_exec
+ *
+ * Description:
+ * Execute the task from the file system.
+ *
+ * Input Parameters:
+ *
+ * pidp - Upon successful completion, this will return the task ID of the
+ * child task in the variable pointed to by a non-NULL 'pid' argument.|
+ *
+ * path - The 'path' argument identifies the file to execute. If
+ * CONFIG_BINFMT_EXEPATH is defined, this may be either a relative or
+ * or an absolute path. Otherwise, it must be an absolute path.
+ *
+ * attr - If the value of the 'attr' parameter is NULL, the all default
+ * values for the POSIX spawn attributes will be used. Otherwise, the
+ * attributes will be set according to the spawn flags. The
+ * following spawn flags are supported:
+ *
+ * - POSIX_SPAWN_SETSCHEDPARAM: Set new tasks priority to the sched_param
+ * value.
+ * - POSIX_SPAWN_SETSCHEDULER: Set the new tasks scheduler priority to
+ * the sched_policy value.
+ *
+ * NOTE: POSIX_SPAWN_SETSIGMASK is handled in ps_proxy().
+ *
+ * argv - argv[] is the argument list for the new task. argv[] is an
+ * array of pointers to null-terminated strings. The list is terminated
+ * with a null pointer.
+ *
+ * Returned Value:
+ * This function will return zero on success. Otherwise, an error number
+ * will be returned as the function return value to indicate the error.
+ * This errno value may be that set by execv(), sched_setpolicy(), or
+ * sched_setparam().
+ *
+ ****************************************************************************/
+
+static int ps_exec(FAR pid_t *pidp, FAR const char *path,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[])
+{
+ struct sched_param param;
+ FAR const struct symtab_s *symtab;
+ int nsymbols;
+ int pid;
+ int ret = OK;
+
+ DEBUGASSERT(path);
+
+ /* Get the current symbol table selection */
+
+ exec_getsymtab(&symtab, &nsymbols);
+
+ /* Disable pre-emption so that we can modify the task parameters after
+ * we start the new task; the new task will not actually begin execution
+ * until we re-enable pre-emption.
+ */
+
+ sched_lock();
+
+ /* Start the task */
+
+ pid = exec(path, (FAR const char **)argv, symtab, nsymbols);
+ if (pid < 0)
+ {
+ ret = errno;
+ sdbg("ERROR: exec failed: %d\n", ret);
+ goto errout;
+ }
+
+ /* Return the task ID to the caller */
+
+ if (pid)
+ {
+ *pidp = pid;
+ }
+
+ /* Now set the attributes. Note that we ignore all of the return values
+ * here because we have already successfully started the task. If we
+ * return an error value, then we would also have to stop the task.
+ */
+
+ if (attr)
+ {
+ /* If we are only setting the priority, then call sched_setparm()
+ * to set the priority of the of the new task.
+ */
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0)
+ {
+ /* Get the priority from the attrributes */
+
+ param.sched_priority = attr->priority;
+
+ /* If we are setting *both* the priority and the scheduler,
+ * then we will call sched_setscheduler() below.
+ */
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) == 0)
+ {
+ svdbg("Setting priority=%d for pid=%d\n",
+ param.sched_priority, pid);
+
+ (void)sched_setparam(pid, &param);
+ }
+ }
+
+ /* If we are only changing the scheduling policy, then reset
+ * the priority to the default value (the same as this thread) in
+ * preparation for the sched_setscheduler() call below.
+ */
+
+ else if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
+ {
+ (void)sched_getparam(0, &param);
+ }
+
+ /* Are we setting the scheduling policy? If so, use the priority
+ * setting determined above.
+ */
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
+ {
+ svdbg("Setting policy=%d priority=%d for pid=%d\n",
+ attr->policy, param.sched_priority, pid);
+
+ (void)sched_setscheduler(pid, attr->policy, &param);
+ }
+ }
+
+ /* Re-enable pre-emption and return */
+
+errout:
+ sched_unlock();
+ return OK;
+}
+
+/****************************************************************************
+ * Name: spawn_close, spawn_dup2, and spawn_open
+ *
+ * Description:
+ * Implement individual file actions
+ *
+ * Input Parameters:
+ * action - describes the action to be performed
+ *
+ * Returned Value:
+ * posix_spawn() and posix_spawnp() will return zero on success.
+ * Otherwise, an error number will be returned as the function return
+ * value to indicate the error.
+ *
+ ****************************************************************************/
+
+static inline int spawn_close(FAR struct spawn_close_file_action_s *action)
+{
+ /* The return value from close() is ignored */
+
+ svdbg("Closing fd=%d\n", action->fd);
+
+ (void)close(action->fd);
+ return OK;
+}
+
+static inline int spawn_dup2(FAR struct spawn_dup2_file_action_s *action)
+{
+ int ret;
+
+ /* Perform the dup */
+
+ svdbg("Dup'ing %d->%d\n", action->fd1, action->fd2);
+
+ ret = dup2(action->fd1, action->fd2);
+ if (ret < 0)
+ {
+ int errcode = errno;
+
+ sdbg("ERROR: dup2 failed: %d\n", errcode);
+ return errcode;
+ }
+
+ return OK;
+}
+
+static inline int spawn_open(FAR struct spawn_open_file_action_s *action)
+{
+ int fd;
+ int ret = OK;
+
+ /* Open the file */
+
+ svdbg("Open'ing path=%s oflags=%04x mode=%04x\n",
+ action->path, action->oflags, action->mode);
+
+ fd = open(action->path, action->oflags, action->mode);
+ if (fd < 0)
+ {
+ ret = errno;
+ sdbg("ERROR: open failed: %d\n", ret);
+ }
+
+ /* Does the return file descriptor happen to match the required file
+ * desciptor number?
+ */
+
+ else if (fd != action->fd)
+ {
+ /* No.. dup2 to get the correct file number */
+
+ svdbg("Dup'ing %d->%d\n", fd, action->fd);
+
+ ret = dup2(fd, action->fd);
+ if (ret < 0)
+ {
+ ret = errno;
+ sdbg("ERROR: dup2 failed: %d\n", ret);
+ }
+
+ svdbg("Closing fd=%d\n", fd);
+ close(fd);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: spawn_proxy
+ *
+ * Description:
+ * Perform file_actions, then execute the task from the file system.
+ *
+ * Input Parameters:
+ * Standard task start-up parameters
+ *
+ * Returned Value:
+ * Standard task return value.
+ *
+ ****************************************************************************/
+
+static int spawn_proxy(int argc, char *argv[])
+{
+ FAR struct spawn_general_file_action_s *entry;
+ FAR const posix_spawnattr_t *attr = g_ps_parms.attr;
+ int ret = OK;
+
+ /* Perform file actions and/or set a custom signal mask. We get here only
+ * if the file_actions parameter to posix_spawn[p] was non-NULL and/or the
+ * option to change the signal mask was selected.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ DEBUGASSERT((g_ps_parms.file_actions && *g_ps_parms.file_actions) ||
+ (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0));
+#else
+ DEBUGASSERT(g_ps_parms.file_actions && *g_ps_parms.file_actions);
+#endif
+
+ /* Check if we need to change the signal mask */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if (attr && (attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)
+ {
+ (void)sigprocmask(SIG_SETMASK, &attr->sigmask, NULL);
+ }
+
+ /* Were we also requested to perform file actions? */
+
+ if (g_ps_parms.file_actions)
+#endif
+ {
+ /* Execute each file action */
+
+ for (entry = (FAR struct spawn_general_file_action_s *)*g_ps_parms.file_actions;
+ entry && ret == OK;
+ entry = entry->flink)
+ {
+ switch (entry->action)
+ {
+ case SPAWN_FILE_ACTION_CLOSE:
+ ret = spawn_close((FAR struct spawn_close_file_action_s *)entry);
+ break;
+
+ case SPAWN_FILE_ACTION_DUP2:
+ ret = spawn_dup2((FAR struct spawn_dup2_file_action_s *)entry);
+ break;
+
+ case SPAWN_FILE_ACTION_OPEN:
+ ret = spawn_open((FAR struct spawn_open_file_action_s *)entry);
+ break;
+
+ case SPAWN_FILE_ACTION_NONE:
+ default:
+ sdbg("ERROR: Unknown action: %d\n", entry->action);
+ ret = EINVAL;
+ break;
+ }
+ }
+ }
+
+ /* Check for failures */
+
+ if (ret == OK)
+ {
+ /* Start the task */
+
+ ret = ps_exec(g_ps_parms.pid, g_ps_parms.path, attr, g_ps_parms.argv);
+ }
+
+ /* Post the semaphore to inform the parent task that we have completed
+ * what we need to do.
+ */
+
+ g_ps_parms.result = ret;
+ ps_semgive(&g_ps_execsem);
+ return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn
+ *
+ * Description:
+ * The posix_spawn() and posix_spawnp() functions will create a new,
+ * child task, constructed from a regular executable file.
+ *
+ * Input Parameters:
+ *
+ * pid - Upon successful completion, posix_spawn() and posix_spawnp() will
+ * return the task ID of the child task to the parent task, in the
+ * variable pointed to by a non-NULL 'pid' argument. If the 'pid'
+ * argument is a null pointer, the process ID of the child is not
+ * returned to the caller.
+ *
+ * path - The 'path' argument to posix_spawn() is the absolute path that
+ * identifies the file to execute. The 'path' argument to posix_spawnp()
+ * may also be a relative path and will be used to construct a pathname
+ * that identifies the file to execute. In the case of a relative path,
+ * the path prefix for the file will be obtained by a search of the
+ * directories passed as the environment variable PATH.
+ *
+ * NOTE: NuttX provides only one implementation: If
+ * CONFIG_BINFMT_EXEPATH is defined, then only posix_spawnp() behavior
+ * is supported; otherwise, only posix_spawn behavior is supported.
+ *
+ * file_actions - If 'file_actions' is a null pointer, then file
+ * descriptors open in the calling process will remain open in the
+ * child process (unless CONFIG_FDCLONE_STDIO is defined). If
+ * 'file_actions' is not NULL, then the file descriptors open in the
+ * child process will be those open in the calling process as modified
+ * by the spawn file actions object pointed to by file_actions.
+ *
+ * attr - If the value of the 'attr' parameter is NULL, the all default
+ * values for the POSIX spawn attributes will be used. Otherwise, the
+ * attributes will be set according to the spawn flags. The
+ * posix_spawnattr_t spawn attributes object type is defined in spawn.h.
+ * It will contains these attributes, not all of which are supported by
+ * NuttX:
+ *
+ * - POSIX_SPAWN_SETPGROUP: Setting of the new task's process group is
+ * not supported. NuttX does not support process groups.
+ * - POSIX_SPAWN_SETSCHEDPARAM: Set new tasks priority to the sched_param
+ * value.
+ * - POSIX_SPAWN_SETSCHEDULER: Set the new task's scheduler policy to
+ * the sched_policy value.
+ * - POSIX_SPAWN_RESETIDS: Resetting of the effective user ID of the child
+ * process is not supported. NuttX does not support effective user
+ * IDs.
+ * - POSIX_SPAWN_SETSIGMASK: Set the new task's signal mask.
+ * - POSIX_SPAWN_SETSIGDEF: Resetting signal default actions is not
+ * supported. NuttX does not support default signal actions.
+ *
+ * argv - argv[] is the argument list for the new task. argv[] is an
+ * array of pointers to null-terminated strings. The list is terminated
+ * with a null pointer.
+ *
+ * envp - The envp[] argument is not used by NuttX and may be NULL. In
+ * standard implementations, envp[] is an array of character pointers to
+ * null-terminated strings that provide the environment for the new
+ * process image. The environment array is terminated by a null pointer.
+ * In NuttX, the envp[] argument is ignored and the new task will simply
+ * inherit the environment of the parent task.
+ *
+ * Returned Value:
+ * posix_spawn() and posix_spawnp() will return zero on success.
+ * Otherwise, an error number will be returned as the function return
+ * value to indicate the error:
+ *
+ * - EINVAL: The value specified by 'file_actions' or 'attr' is invalid.
+ * - Any errors that might have been return if vfork() and excec[l|v]()
+ * had been called.
+ *
+ * Assumptions/Limitations:
+ * - NuttX provides only posix_spawn() or posix_spawnp() behavior
+ * depending upon the setting of CONFIG_BINFMT_EXEPATH: If
+ * CONFIG_BINFMT_EXEPATH is defined, then only posix_spawnp() behavior
+ * is supported; otherwise, only posix_spawn behavior is supported.
+ * - The 'envp' argument is not used and the 'environ' variable is not
+ * altered (NuttX does not support the 'environ' variable).
+ * - Process groups are not supported (POSIX_SPAWN_SETPGROUP).
+ * - Effective user IDs are not supported (POSIX_SPAWN_RESETIDS).
+ * - Signal default actions cannot be modified in the newly task executed
+ * because NuttX does not support default signal actions
+ * (POSIX_SPAWN_SETSIGDEF).
+ *
+ * POSIX Compatibility
+ * - The value of the argv[0] received by the child task is assigned by
+ * NuttX. For the caller of posix_spawn(), the provided argv[0] will
+ * correspond to argv[1] received by the new task.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BINFMT_EXEPATH
+int posix_spawnp(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[])
+#else
+int posix_spawn(FAR pid_t *pid, FAR const char *path,
+ FAR const posix_spawn_file_actions_t *file_actions,
+ FAR const posix_spawnattr_t *attr,
+ FAR char *const argv[], FAR char *const envp[])
+#endif
+{
+ struct sched_param param;
+ pid_t proxy;
+ int ret;
+
+ DEBUGASSERT(path);
+
+ svdbg("pid=%p path=%s file_actions=%p attr=%p argv=%p\n",
+ pid, path, file_actions, attr, argv);
+
+ /* If there are no file actions to be performed and there is no change to
+ * the signal mask, then start the new child task directly from the parent task.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if ((file_actions == NULL || *file_actions == NULL) &&
+ (attr == NULL || (attr->flags & POSIX_SPAWN_SETSIGMASK) == 0))
+#else
+ if (file_actions == NULL || *file_actions == NULL)
+#endif
+ {
+ return ps_exec(pid, path, attr, argv);
+ }
+
+ /* Otherwise, we will have to go through an intermediary/proxy task in order
+ * to perform the I/O redirection. This would be a natural place to fork().
+ * However, true fork() behavior requires an MMU and most implementations
+ * of vfork() are not capable of these operations.
+ *
+ * Even without fork(), we can still do the job, but parameter passing is
+ * messier. Unfortunately, there is no (clean) way to pass binary values
+ * as a task parameter, so we will use a semaphore-protected global
+ * structure.
+ */
+
+ /* Get exclusive access to the global parameter structure */
+
+ ps_semtake(&g_ps_parmsem);
+
+ /* Populate the parameter structure */
+
+ g_ps_parms.result = ENOSYS;
+ g_ps_parms.pid = pid;
+ g_ps_parms.path = path;
+ g_ps_parms.file_actions = file_actions;
+ g_ps_parms.attr = attr;
+ g_ps_parms.argv = argv;
+
+ /* Get the priority of this (parent) task */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ int errcode = errno;
+
+ sdbg("ERROR: sched_getparam failed: %d\n", errcode);
+ ps_semgive(&g_ps_parmsem);
+ return errcode;
+ }
+
+ /* Start the intermediary/proxy task at the same priority as the parent task. */
+
+ proxy = TASK_CREATE("spawn_proxy", param.sched_priority,
+ CONFIG_POSIX_SPAWN_STACKSIZE, (main_t)spawn_proxy,
+ (FAR const char **)NULL);
+ if (proxy < 0)
+ {
+ int errcode = errno;
+
+ sdbg("ERROR: Failed to start spawn_proxy: %d\n", errcode);
+ ps_semgive(&g_ps_parmsem);
+ return errcode;
+ }
+
+ /* Wait for the proxy to complete its job */
+
+ ps_semtake(&g_ps_execsem);
+
+ /* Get the result and relinquish our access to the parameter structure */
+
+ ret = g_ps_parms.result;
+ ps_semgive(&g_ps_parmsem);
+ return ret;
+}
diff --git a/nuttx/libc/spawn/lib_psa_dump.c b/nuttx/libc/spawn/lib_psa_dump.c
new file mode 100644
index 000000000..03770c6ff
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_dump.c
@@ -0,0 +1,127 @@
+/****************************************************************************
+ * libc/string/lib_psa_dump.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+#include <debug.h>
+
+#ifdef CONFIG_DEBUG
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_dump
+ *
+ * Description:
+ * Show the current attributes.
+ *
+ * Input Parameters:
+ * attr - The address of the spawn attributes to be dumped.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void posix_spawnattr_dump(posix_spawnattr_t *attr)
+{
+ dbg("attr[%p]:\n", attr);
+ dbg(" flags: %04x\n", attr->flags);
+ if (attr->flags == 0)
+ {
+ dbg(" None\n");
+ }
+ else
+ {
+ if ((attr->flags & POSIX_SPAWN_RESETIDS) != 0)
+ {
+ dbg(" POSIX_SPAWN_RESETIDS\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETPGROUP) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETPGROUP\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDPARAM) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSCHEDPARAM\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSCHEDULER) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSCHEDULER\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSIGDEF) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSIGDEF\n");
+ }
+
+ if ((attr->flags & POSIX_SPAWN_SETSIGMASK) != 0)
+ {
+ dbg(" POSIX_SPAWN_SETSIGMASK\n");
+ }
+ }
+
+ dbg(" priority: %d\n", attr->priority);
+
+ dbg(" policy: %d\n", attr->policy);
+ if (attr->policy == SCHED_FIFO)
+ {
+ dbg(" SCHED_FIFO\n");
+ }
+ else if (attr->policy == SCHED_RR)
+ {
+ dbg(" SCHED_RR\n");
+ }
+ else
+ {
+ dbg(" Unrecognized\n");
+ }
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ dbg(" sigmask: %08x\n", attr->sigmask);
+#endif
+};
+
+#endif /* CONFIG_DEBUG */ \ No newline at end of file
diff --git a/nuttx/libc/spawn/lib_psa_getflags.c b/nuttx/libc/spawn/lib_psa_getflags.c
new file mode 100644
index 000000000..f0e07f0c2
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getflags.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * libc/string/lib_psa_getflags.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getflags
+ *
+ * Description:
+ * The posix_spawnattr_getflags() function will obtain the value of the
+ * spawn-flags attribute from the attributes object referenced by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * flags - The location to return the spawn flags
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getflags(FAR const posix_spawnattr_t *attr,
+ FAR short *flags)
+{
+ DEBUGASSERT(attr && flags);
+ *flags = (short)attr->flags;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_getschedparam.c b/nuttx/libc/spawn/lib_psa_getschedparam.c
new file mode 100644
index 000000000..ed8cb1f70
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getschedparam.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * libc/string/lib_psa_getschedparam.c
+ *
+ * Copyright (C) 2013 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 <sched.h>
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getschedparam
+ *
+ * Description:
+ * The posix_spawnattr_getschedparam() function will obtain the value of
+ * the spawn-schedparam attribute from the attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * flags - The location to return the spawn-schedparam value.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getschedparam(FAR const posix_spawnattr_t *attr,
+ FAR struct sched_param *param)
+{
+ DEBUGASSERT(attr && param);
+ param->sched_priority = attr->priority;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_getschedpolicy.c b/nuttx/libc/spawn/lib_psa_getschedpolicy.c
new file mode 100644
index 000000000..8f3645666
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getschedpolicy.c
@@ -0,0 +1,73 @@
+/****************************************************************************
+ * libc/string/lib_psa_getschedpolicy.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getschedpolicy
+ *
+ * Description:
+ * The posix_spawnattr_getschedpolicy() function shall obtain the value
+ * of the spawn-schedpolicy attribute from the attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * policy - The location to return the scheduler policy
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getschedpolicy(FAR const posix_spawnattr_t *attr,
+ FAR int *policy)
+{
+ DEBUGASSERT(attr && policy);
+ *policy = (int)attr->policy;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_getsigmask.c b/nuttx/libc/spawn/lib_psa_getsigmask.c
new file mode 100644
index 000000000..dd3495b4d
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_getsigmask.c
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * libc/string/lib_psa_getsigmask.c
+ *
+ * Copyright (C) 2013 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 <signal.h>
+#include <spawn.h>
+#include <assert.h>
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_getsigmask
+ *
+ * Description:
+ * The posix_spawnattr_getsigdefault() function will obtain the value of
+ * the spawn-sigmask attribute from the attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be queried.
+ * sigmask - The location to return the signal mask
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_getsigmask(FAR const posix_spawnattr_t *attr,
+ FAR sigset_t *sigmask)
+{
+ DEBUGASSERT(attr && sigmask);
+ *sigmask = attr->sigmask;
+ return OK;
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
diff --git a/nuttx/libc/spawn/lib_psa_init.c b/nuttx/libc/spawn/lib_psa_init.c
new file mode 100644
index 000000000..f76188c52
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_init.c
@@ -0,0 +1,93 @@
+/****************************************************************************
+ * libc/string/lib_psa_init.c
+ *
+ * Copyright (C) 2013 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 <sched.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_init
+ *
+ * Description:
+ * The posix_spawnattr_init() function initializes the object referenced
+ * by attr, to an empty set of spawn attributes for subsequent use in a
+ * call to posix_spawn() or posix_spawnp().
+ *
+ * Input Parameters:
+ * attr - The address of the spawn attributes to be initialized.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_init(posix_spawnattr_t *attr)
+{
+ struct sched_param param;
+ int ret;
+
+ DEBUGASSERT(attr);
+
+ /* Flags: None */
+
+ attr->flags = 0;
+
+ /* Set the default scheduler policy to the policy of this task */
+
+ attr->policy = sched_getscheduler(0);
+
+ /* Set the default priority to the same priority as this task */
+
+ ret = sched_getparam(0, &param);
+ if (ret < 0)
+ {
+ return errno;
+ }
+
+ attr->priority = param.sched_priority;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setflags.c b/nuttx/libc/spawn/lib_psa_setflags.c
new file mode 100644
index 000000000..34b71d841
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setflags.c
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * libc/string/lib_psa_setflags.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setflags
+ *
+ * Description:
+ * The posix_spawnattr_setflags() function will set the spawn-flags
+ * attribute in an initialized attributes object referenced by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * flags - The new value of the spawn flags
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setflags(FAR posix_spawnattr_t *attr, short flags)
+{
+ DEBUGASSERT(attr && (flags & ~0xff) == 0);
+ attr->flags = (uint8_t)flags;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setschedparam.c b/nuttx/libc/spawn/lib_psa_setschedparam.c
new file mode 100644
index 000000000..5e992e8a9
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setschedparam.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * libc/string/lib_psa_setschedparam.c
+ *
+ * Copyright (C) 2013 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 <sched.h>
+#include <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setschedparam
+ *
+ * Description:
+ * The posix_spawnattr_setschedparam() function shall set the spawn-
+ * schedparam attribute in an initialized attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * param - The new sched_priority to set.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setschedparam(FAR posix_spawnattr_t *attr,
+ FAR const struct sched_param *param)
+{
+ DEBUGASSERT(attr && param && (unsigned)param->sched_priority <= 0xff);
+ attr->priority = (uint8_t)param->sched_priority;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setschedpolicy.c b/nuttx/libc/spawn/lib_psa_setschedpolicy.c
new file mode 100644
index 000000000..136a6f0fd
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setschedpolicy.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * libc/string/lib_psa_setschedpolicy.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+#include <assert.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setschedpolicy
+ *
+ * Description:
+ * The posix_spawnattr_setschedpolicy() function will set the spawn-
+ * schedpolicy attribute in an initialized attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * flags - The new value of the spawn flags
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setschedpolicy(FAR posix_spawnattr_t *attr, int policy)
+{
+ DEBUGASSERT(attr && (policy == SCHED_FIFO || policy == SCHED_RR));
+ attr->policy = (uint8_t)policy;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psa_setsigmask.c b/nuttx/libc/spawn/lib_psa_setsigmask.c
new file mode 100644
index 000000000..28b7daf77
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psa_setsigmask.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * libc/string/lib_psa_setsigmask.c
+ *
+ * Copyright (C) 2013 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 <signal.h>
+#include <spawn.h>
+#include <assert.h>
+
+#ifndef CONFIG_DISABLE_SIGNALS
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawnattr_setsigmask
+ *
+ * Description:
+ * The posix_spawnattr_setsigmask() function will set the spawn-
+ * sigmask attribute in an initialized attributes object referenced
+ * by attr.
+ *
+ * Input Parameters:
+ * attr - The address spawn attributes to be used.
+ * flags - The new value of the default signal set
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr,
+ FAR const sigset_t *sigmask)
+{
+ DEBUGASSERT(attr && sigmask);
+ attr->sigmask = *sigmask;
+ return OK;
+}
+
+#endif /* !CONFIG_DISABLE_SIGNALS */
+
diff --git a/nuttx/libc/spawn/lib_psfa_addaction.c b/nuttx/libc/spawn/lib_psfa_addaction.c
new file mode 100644
index 000000000..3f297d7cf
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_addaction.c
@@ -0,0 +1,91 @@
+/****************************************************************************
+ * libc/string/lib_psfa_addaction.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+
+#include "spawn/spawn.h"
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: add_file_action
+ *
+ * Description:
+ * Add the file action to the end for the file action list.
+ *
+ * Input Parameters:
+ * file_actions - The head of the file action list.
+ * entry - The file action to be added
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void add_file_action(FAR posix_spawn_file_actions_t *file_actions,
+ FAR struct spawn_general_file_action_s *entry)
+{
+ FAR struct spawn_general_file_action_s *prev;
+ FAR struct spawn_general_file_action_s *next;
+
+ /* Find the end of the list */
+
+ for (prev = NULL, next = (FAR struct spawn_general_file_action_s *)*file_actions;
+ next;
+ prev = next, next = next->flink);
+
+ /* Here next is NULL and prev points to the last entry in the list (or
+ * is NULL if the list is empty).
+ */
+
+ if (prev)
+ {
+ prev->flink = entry;
+ }
+ else
+ {
+ *file_actions = (posix_spawn_file_actions_t)entry;
+ }
+
+ entry->flink = NULL;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_addclose.c b/nuttx/libc/spawn/lib_psfa_addclose.c
new file mode 100644
index 000000000..bf22a153a
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_addclose.c
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * libc/string/lib_psfa_addclose.c
+ *
+ * Copyright (C) 2013 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 <stdlib.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "spawn/spawn.h"
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_addclose
+ *
+ * Description:
+ * The posix_spawn_file_actions_addclose() function adds a close operation
+ * to the list of operations associated with the object referenced by
+ * file_actions, for subsequent use in a call to posix_spawn() or
+ * posix_spawnp(). The descriptor referred to by fd is closed as if
+ * close() had been called on it prior to the new child process starting
+ * execution.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to append the action.
+ * fd - The file descriptor to be closed.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_addclose(FAR posix_spawn_file_actions_t *file_actions,
+ int fd)
+{
+ FAR struct spawn_close_file_action_s *entry;
+
+ DEBUGASSERT(file_actions && fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS);
+
+ /* Allocate the action list entry */
+
+ entry = (FAR struct spawn_close_file_action_s *)
+ zalloc(sizeof(struct spawn_close_file_action_s));
+
+ if (!entry)
+ {
+ return ENOMEM;
+ }
+
+ /* Initialize the file action entry */
+
+ entry->action = SPAWN_FILE_ACTION_CLOSE;
+ entry->fd = fd;
+
+ /* And add it to the file action list */
+
+ add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_adddup2.c b/nuttx/libc/spawn/lib_psfa_adddup2.c
new file mode 100644
index 000000000..fc788a4e9
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_adddup2.c
@@ -0,0 +1,104 @@
+/****************************************************************************
+ * libc/string/lib_psfa_adddup2.c
+ *
+ * Copyright (C) 2013 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 <stdlib.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "spawn/spawn.h"
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_adddup2
+ *
+ * Description:
+ * The posix_spawn_file_actions_adddup2() function adds a dup2 operation to
+ * the list of operations associated with the object referenced by
+ * file_actions, for subsequent use in a call to posix_spawn() or
+ * posix_spawnp(). The descriptor referred to by fd2 is created as
+ * if dup2() had been called on fd1 prior to the new child process
+ * starting execution.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to append the action.
+ * fd1 - The first file descriptor to be argument to dup2.
+ * fd2 - The first file descriptor to be argument to dup2.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_adddup2(FAR posix_spawn_file_actions_t *file_actions,
+ int fd1, int fd2)
+{
+ FAR struct spawn_dup2_file_action_s *entry;
+
+ DEBUGASSERT(file_actions &&
+ fd1 >= 0 && fd1 < CONFIG_NFILE_DESCRIPTORS &&
+ fd2 >= 0 && fd2 < CONFIG_NFILE_DESCRIPTORS);
+
+ /* Allocate the action list entry */
+
+ entry = (FAR struct spawn_dup2_file_action_s *)
+ zalloc(sizeof(struct spawn_close_file_action_s));
+
+ if (!entry)
+ {
+ return ENOMEM;
+ }
+
+ /* Initialize the file action entry */
+
+ entry->action = SPAWN_FILE_ACTION_DUP2;
+ entry->fd1 = fd1;
+ entry->fd2 = fd2;
+
+ /* And add it to the file action list */
+
+ add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_addopen.c b/nuttx/libc/spawn/lib_psfa_addopen.c
new file mode 100644
index 000000000..385e1cfc3
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_addopen.c
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * libc/string/lib_psfa_addopen.c
+ *
+ * Copyright (C) 2013 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 <stdlib.h>
+#include <string.h>
+#include <spawn.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "spawn/spawn.h"
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_addopen
+ *
+ * Description:
+ * The posix_spawn_file_actions_addopen() function adds an open operation
+ * to the list of operations associated with the object referenced by
+ * file_actions, for subsequent use in a call to posix_spawn() or
+ * posix_spawnp(). The descriptor referred to by fd is opened using
+ * the path, oflag, and mode arguments as if open() had been called on it
+ * prior to the new child process starting execution. The string path is
+ * copied by the posix_spawn_file_actions_addopen() function during this
+ * process, so storage need not be persistent in the caller.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to append the action.
+ * fd - The file descriptor to be opened.
+ * path - The path to be opened.
+ * oflags - Open flags
+ * mode - File creation mode
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions,
+ int fd, FAR const char *path, int oflags,
+ mode_t mode)
+{
+ FAR struct spawn_open_file_action_s *entry;
+ size_t len;
+ size_t alloc;
+
+ DEBUGASSERT(file_actions && path &&
+ fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS);
+
+ /* Get the size of the action including storage for the path plus its NUL
+ * terminating character.
+ */
+
+ len = strlen(path);
+ alloc = SIZEOF_OPEN_FILE_ACTION_S(len);
+
+ /* Allocate the action list entry of this size */
+
+ entry = (FAR struct spawn_open_file_action_s *)zalloc(alloc);
+
+ if (!entry)
+ {
+ return ENOMEM;
+ }
+
+ /* Initialize the file action entry */
+
+ entry->action = SPAWN_FILE_ACTION_OPEN;
+ entry->fd = fd;
+ entry->oflags = oflags;
+ entry->mode = mode;
+ strncpy(entry->path, path, len+1);
+
+ /* And add it to the file action list */
+
+ add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_destroy.c b/nuttx/libc/spawn/lib_psfa_destroy.c
new file mode 100644
index 000000000..5d0a644d8
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_destroy.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * libc/string/lib_psfa_destroy.c
+ *
+ * Copyright (C) 2012 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 <stdlib.h>
+#include <spawn.h>
+#include <assert.h>
+
+#include "spawn/spawn.h"
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_destroy
+ *
+ * Description:
+ * The posix_spawn_file_actions_destroy() function destroys the object
+ * referenced by file_actions which was previously intialized by
+ * posix_spawn_file_actions_init(), returning any resources obtained at the
+ * time of initialization to the system for subsequent reuse. A
+ * posix_spawn_file_actions_t may be reinitialized after having been
+ * destroyed, but must not be reused after destruction, unless it has been
+ * reinitialized.
+ *
+ * Input Parameters:
+ * file_actions - The posix_spawn_file_actions_t to be destroyed.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_destroy(FAR posix_spawn_file_actions_t *file_actions)
+{
+ FAR struct spawn_general_file_action_s *curr;
+ FAR struct spawn_general_file_action_s *next;
+
+ DEBUGASSERT(file_actions);
+
+ /* Destroy each file action, one at a time */
+
+ for (curr = (FAR struct spawn_general_file_action_s *)*file_actions;
+ curr;
+ curr = next)
+ {
+ /* Get the pointer to the next element before destroying the current one */
+
+ next = curr->flink;
+ free(curr);
+ }
+
+ /* Mark the list empty */
+
+ *file_actions = NULL;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/lib_psfa_dump.c b/nuttx/libc/spawn/lib_psfa_dump.c
new file mode 100644
index 000000000..d7bf1576d
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_dump.c
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * libc/string/lib_psfa_dump.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+#include <assert.h>
+#include <debug.h>
+
+#include "spawn/spawn.h"
+
+#ifdef CONFIG_DEBUG
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_psfa_dump
+ *
+ * Description:
+ * Show the entryent file actions.
+ *
+ * Input Parameters:
+ * file_actions - The address of the file_actions to be dumped.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void posix_spawn_file_actions_dump(FAR posix_spawn_file_actions_t *file_actions)
+{
+ FAR struct spawn_general_file_action_s *entry;
+
+ DEBUGASSERT(file_actions);
+
+ dbg("File Actions[%p->%p]:\n", file_actions, *file_actions);
+ if (!*file_actions)
+ {
+ dbg(" NONE\n");
+ return;
+ }
+
+ /* Destroy each file action, one at a time */
+
+ for (entry = (FAR struct spawn_general_file_action_s *)*file_actions;
+ entry;
+ entry = entry->flink)
+ {
+ switch (entry->action)
+ {
+ case SPAWN_FILE_ACTION_CLOSE:
+ {
+ FAR struct spawn_close_file_action_s *action =
+ (FAR struct spawn_close_file_action_s *)entry;
+
+ dbg(" CLOSE: fd=%d\n", action->fd);
+ }
+ break;
+
+ case SPAWN_FILE_ACTION_DUP2:
+ {
+ FAR struct spawn_dup2_file_action_s *action =
+ (FAR struct spawn_dup2_file_action_s *)entry;
+
+ dbg(" DUP2: %d->%d\n", action->fd1, action->fd2);
+ }
+ break;
+
+ case SPAWN_FILE_ACTION_OPEN:
+ {
+ FAR struct spawn_open_file_action_s *action =
+ (FAR struct spawn_open_file_action_s *)entry;
+
+ svdbg(" OPEN: path=%s oflags=%04x mode=%04x fd=%d\n",
+ action->path, action->oflags, action->mode, action->fd);
+ }
+ break;
+
+ case SPAWN_FILE_ACTION_NONE:
+ default:
+ dbg(" ERROR: Unknown action: %d\n", entry->action);
+ break;
+ }
+ }
+}
+
+#endif /* CONFIG_DEBUG */ \ No newline at end of file
diff --git a/nuttx/libc/spawn/lib_psfa_init.c b/nuttx/libc/spawn/lib_psfa_init.c
new file mode 100644
index 000000000..5c902125a
--- /dev/null
+++ b/nuttx/libc/spawn/lib_psfa_init.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * libc/string/lib_psfa_init.c
+ *
+ * Copyright (C) 2013 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 <spawn.h>
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: posix_spawn_file_actions_init
+ *
+ * Description:
+ * The posix_spawn_file_actions_init() function initializes the object
+ * referenced by file_actions to an empty set of file actions for
+ * subsequent use in a call to posix_spawn() or posix_spawnp().
+ *
+ * Input Parameters:
+ * file_actions - The address of the posix_spawn_file_actions_t to be
+ * initialized.
+ *
+ * Returned Value:
+ * On success, these functions return 0; on failure they return an error
+ * number from <errno.h>.
+ *
+ ****************************************************************************/
+
+int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions)
+{
+ *file_actions = NULL;
+ return OK;
+}
diff --git a/nuttx/libc/spawn/spawn.h b/nuttx/libc/spawn/spawn.h
new file mode 100644
index 000000000..3f4e195cc
--- /dev/null
+++ b/nuttx/libc/spawn/spawn.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+ * libc/spawn/spawn.h
+ *
+ * Copyright (C) 2013 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.
+ *
+ ****************************************************************************/
+
+#ifndef __LIBC_SPAWN_SPAWN_H
+#define __LIBC_SPAWN_SPAWN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <spawn.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+/* This enumerator identifies a file action */
+
+enum spawn_file_actions_e
+{
+ SPAWN_FILE_ACTION_NONE = 0,
+ SPAWN_FILE_ACTION_CLOSE,
+ SPAWN_FILE_ACTION_DUP2,
+ SPAWN_FILE_ACTION_OPEN
+};
+
+/* posix_spawn_file_actions_addclose(), posix_spawn_file_actions_adddup2(),
+ * and posix_spawn_file_actions_addopen() will allocate memory and append
+ * a new file action to an instance of posix_spawn_file_actions_t. The
+ * internal representation of these structures are defined below:
+ */
+
+struct spawn_general_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* A member of enum spawn_file_actions_e */
+};
+
+struct spawn_close_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* SPAWN_FILE_ACTION_CLOSE */
+ int fd; /* The file descriptor to close */
+};
+
+struct spawn_dup2_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* SPAWN_FILE_ACTION_DUP2 */
+ int fd1; /* The first file descriptor for dup2() */
+ int fd2; /* The second file descriptor for dup2() */
+};
+
+struct spawn_open_file_action_s
+{
+ FAR struct spawn_general_file_action_s *flink; /* Supports a singly linked list */
+ enum spawn_file_actions_e action; /* SPAWN_FILE_ACTION_OPEN */
+ int fd; /* The file descriptor after opening */
+ int oflags; /* Open flags */
+ mode_t mode; /* File creation mode */
+ char path[1]; /* Start of the path to be
+ * opened */
+};
+
+#define SIZEOF_OPEN_FILE_ACTION_S(n) \
+ (sizeof(struct spawn_open_file_action_s) + (n))
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void add_file_action(FAR posix_spawn_file_actions_t *file_action,
+ FAR struct spawn_general_file_action_s *entry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIBC_SPAWN_SPAWN_H */
diff --git a/nuttx/libc/stdio/lib_libfread.c b/nuttx/libc/stdio/lib_libfread.c
index bc6479037..3e851bf17 100644
--- a/nuttx/libc/stdio/lib_libfread.c
+++ b/nuttx/libc/stdio/lib_libfread.c
@@ -301,9 +301,10 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream)
{
stream->fs_flags |= __FS_FLAG_EOF;
}
+
+ lib_give_semaphore(stream);
}
- lib_give_semaphore(stream);
return bytes_read;
/* Error exits */
diff --git a/nuttx/libc/string/lib_strndup.c b/nuttx/libc/string/lib_strndup.c
index 524e09754..5a78e2dcf 100644
--- a/nuttx/libc/string/lib_strndup.c
+++ b/nuttx/libc/string/lib_strndup.c
@@ -1,7 +1,7 @@
/************************************************************************
* libc/string//lib_strndup.c
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -68,13 +68,9 @@ FAR char *strndup(FAR const char *s, size_t size)
FAR char *news = NULL;
if (s)
{
- /* Get the size of the new string = MIN(strlen(s), size) */
+ /* Get the size of the new string (limited to size) */
- size_t allocsize = strlen(s);
- if (allocsize > size)
- {
- allocsize = size;
- }
+ size_t allocsize = strnlen(s, size);
/* Allocate the new string, adding 1 for the NUL terminator */
@@ -89,5 +85,6 @@ FAR char *strndup(FAR const char *s, size_t size)
news[allocsize] = '\0';
}
}
+
return news;
}
diff --git a/nuttx/libc/unistd/Make.defs b/nuttx/libc/unistd/Make.defs
index 67fce9b1d..ee3ac0fc9 100644
--- a/nuttx/libc/unistd/Make.defs
+++ b/nuttx/libc/unistd/Make.defs
@@ -41,6 +41,10 @@ ifneq ($(CONFIG_NFILE_DESCRIPTORS),0)
ifneq ($(CONFIG_DISABLE_ENVIRON),y)
CSRCS += lib_chdir.c lib_getcwd.c
endif
+
+ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
+CSRCS += lib_execl.c lib_execv.c lib_execsymtab.c
+endif
endif
# Add the unistd directory to the build
diff --git a/nuttx/libc/unistd/lib_execl.c b/nuttx/libc/unistd/lib_execl.c
new file mode 100644
index 000000000..fa50c1429
--- /dev/null
+++ b/nuttx/libc/unistd/lib_execl.c
@@ -0,0 +1,146 @@
+/****************************************************************************
+ * libc/unistd/lib_execl.c
+ *
+ * Copyright (C) 2013 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 <stdarg.h>
+#include <unistd.h>
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: execl
+ *
+ * Description:
+ * The standard 'exec' family of functions will replace the current process
+ * image with a new process image. The new image will be constructed from a
+ * regular, executable file called the new process image file. There will
+ * be no return from a successful exec, because the calling process image
+ * is overlaid by the new process image.
+ *
+ * Simplified 'execl()' and 'execv()' functions are provided by NuttX for
+ * compatibility. NuttX is a tiny embedded RTOS that does not support
+ * processes and hence the concept of overlaying a tasks process image with
+ * a new process image does not make any sense. In NuttX, these functions
+ * are wrapper functions that:
+ *
+ * 1. Call the non-standard binfmt function 'exec', and then
+ * 2. exit(0).
+ *
+ * Note the inefficiency when 'exec[l|v]()' is called in the normal, two-
+ * step process: (1) first call vfork() to create a new thread, then (2)
+ * call 'exec[l|v]()' to replace the new thread with a program from the
+ * file system. Since the new thread will be terminated by the
+ * 'exec[l|v]()' call, it really served no purpose other than to support
+ * Unix compatility.
+ *
+ * The non-standard binfmt function 'exec()' needs to have (1) a symbol
+ * table that provides the list of symbols exported by the base code, and
+ * (2) the number of symbols in that table. This information is currently
+ * provided to 'exec()' from 'exec[l|v]()' via NuttX configuration settings:
+ *
+ * CONFIG_LIBC_EXECFUNCS : Enable exec[l|v] support
+ * CONFIG_EXECFUNCS_SYMTAB : Symbol table used by exec[l|v]
+ * CONFIG_EXECFUNCS_NSYMBOLS : Number of symbols in the table
+ *
+ * As a result of the above, the current implementations of 'execl()' and
+ * 'execv()' suffer from some incompatibilities that may or may not be
+ * addressed in a future version of NuttX. Other than just being an
+ * inefficient use of MCU resource, the most serious of these is that
+ * the exec'ed task will not have the same task ID as the vfork'ed
+ * function. So the parent function cannot know the ID of the exec'ed
+ * task.
+ *
+ * Input Parameters:
+ * path - The path to the program to be executed. If CONFIG_BINFMT_EXEPATH
+ * is defined in the configuration, then this may be a relative path
+ * from the current working directory. Otherwise, path must be the
+ * absolute path to the program.
+ * ... - A list of the string arguments to be recevied by the
+ * program. Zero indicates the end of the list.
+ *
+ * Returned Value:
+ * This function does not return on success. On failure, it will return
+ * -1 (ERROR) and will set the 'errno' value appropriately.
+ *
+ ****************************************************************************/
+
+int execl(FAR const char *path, ...)
+{
+ FAR char *argv[CONFIG_MAX_TASK_ARGS+1];
+ va_list ap;
+ int argc;
+
+ /* Collect the arguments into the argv[] array */
+
+ va_start(ap, path);
+ for (argc = 0; argc < CONFIG_MAX_TASK_ARGS; argc++)
+ {
+ argv[argc] = va_arg(ap, FAR char *);
+ if (argv[argc] == NULL)
+ {
+ break;
+ }
+ }
+
+ argv[CONFIG_MAX_TASK_ARGS] = NULL;
+ va_end(ap);
+
+ /* Then let execv() do the real work */
+
+ return execv(path, (char * const *)&argv);
+}
+
+#endif /* CONFIG_LIBC_EXECFUNCS */ \ No newline at end of file
diff --git a/nuttx/libc/unistd/lib_execsymtab.c b/nuttx/libc/unistd/lib_execsymtab.c
new file mode 100644
index 000000000..34b798bb4
--- /dev/null
+++ b/nuttx/libc/unistd/lib_execsymtab.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+ * libc/unistd/lib_execsymtab.c
+ *
+ * Copyright (C) 2013 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 <assert.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/binfmt/symtab.h>
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* If CONFIG_LIBC_EXECFUNCS is defined in the configuration, then the
+ * following must also be defined:
+ */
+
+/* Symbol table used by exec[l|v] */
+
+#ifndef CONFIG_EXECFUNCS_SYMTAB
+# error "CONFIG_EXECFUNCS_SYMTAB must be defined"
+#endif
+
+/* Number of Symbols in the Table */
+
+#ifndef CONFIG_EXECFUNCS_NSYMBOLS
+# error "CONFIG_EXECFUNCS_NSYMBOLS must be defined"
+#endif
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+extern const struct symtab_s CONFIG_EXECFUNCS_SYMTAB;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static FAR const struct symtab_s *g_exec_symtab = &CONFIG_EXECFUNCS_SYMTAB;
+static int g_exec_nsymbols = CONFIG_EXECFUNCS_NSYMBOLS;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exec_getsymtab
+ *
+ * Description:
+ * Get the current symbol table selection as an atomic operation.
+ *
+ * Input Parameters:
+ * symtab - The location to store the symbol table.
+ * nsymbols - The location to store the number of symbols in the symbol table.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void exec_getsymtab(FAR const struct symtab_s **symtab, FAR int *nsymbols)
+{
+ irqstate_t flags;
+
+ DEBUGASSERT(symtab && nsymbols);
+
+ /* Disable interrupts very briefly so that both the symbol table and its
+ * size are returned as a single atomic operation.
+ */
+
+ flags = irqsave();
+ *symtab = g_exec_symtab;
+ *nsymbols = g_exec_nsymbols;
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: exec_setsymtab
+ *
+ * Description:
+ * Select a new symbol table selection as an atomic operation.
+ *
+ * Input Parameters:
+ * symtab - The new symbol table.
+ * nsymbols - The number of symbols in the symbol table.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void exec_setsymtab(FAR const struct symtab_s *symtab, int nsymbols)
+{
+ irqstate_t flags;
+
+ DEBUGASSERT(symtab);
+
+ /* Disable interrupts very briefly so that both the symbol table and its
+ * size are set as a single atomic operation.
+ */
+
+ flags = irqsave();
+ g_exec_symtab = symtab;
+ g_exec_nsymbols = nsymbols;
+ irqrestore(flags);
+}
+
+#endif /* CONFIG_LIBC_EXECFUNCS */ \ No newline at end of file
diff --git a/nuttx/libc/unistd/lib_execv.c b/nuttx/libc/unistd/lib_execv.c
new file mode 100644
index 000000000..48b089913
--- /dev/null
+++ b/nuttx/libc/unistd/lib_execv.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * libc/unistd/lib_execv.c
+ *
+ * Copyright (C) 2013 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 <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/binfmt/binfmt.h>
+
+#ifdef CONFIG_LIBC_EXECFUNCS
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: execv
+ *
+ * Description:
+ * The standard 'exec' family of functions will replace the current process
+ * image with a new process image. The new image will be constructed from a
+ * regular, executable file called the new process image file. There will
+ * be no return from a successful exec, because the calling process image
+ * is overlaid by the new process image.
+ *
+ * Simplified 'execl()' and 'execv()' functions are provided by NuttX for
+ * compatibility. NuttX is a tiny embedded RTOS that does not support
+ * processes and hence the concept of overlaying a tasks process image with
+ * a new process image does not make any sense. In NuttX, these functions
+ * are wrapper functions that:
+ *
+ * 1. Call the non-standard binfmt function 'exec', and then
+ * 2. exit(0).
+ *
+ * Note the inefficiency when 'exec[l|v]()' is called in the normal, two-
+ * step process: (1) first call vfork() to create a new thread, then (2)
+ * call 'exec[l|v]()' to replace the new thread with a program from the
+ * file system. Since the new thread will be terminated by the
+ * 'exec[l|v]()' call, it really served no purpose other than to support
+ * Unix compatility.
+ *
+ * The non-standard binfmt function 'exec()' needs to have (1) a symbol
+ * table that provides the list of symbols exported by the base code, and
+ * (2) the number of symbols in that table. This information is currently
+ * provided to 'exec()' from 'exec[l|v]()' via NuttX configuration settings:
+ *
+ * CONFIG_LIBC_EXECFUNCS : Enable exec[l|v] support
+ * CONFIG_EXECFUNCS_SYMTAB : Symbol table used by exec[l|v]
+ * CONFIG_EXECFUNCS_NSYMBOLS : Number of symbols in the table
+ *
+ * As a result of the above, the current implementations of 'execl()' and
+ * 'execv()' suffer from some incompatibilities that may or may not be
+ * addressed in a future version of NuttX. Other than just being an
+ * inefficient use of MCU resource, the most serious of these is that
+ * the exec'ed task will not have the same task ID as the vfork'ed
+ * function. So the parent function cannot know the ID of the exec'ed
+ * task.
+ *
+ * Input Parameters:
+ * path - The path to the program to be executed. If CONFIG_BINFMT_EXEPATH
+ * is defined in the configuration, then this may be a relative path
+ * from the current working directory. Otherwise, path must be the
+ * absolute path to the program.
+ * argv - A pointer to an array of string arguments. The end of the
+ * array is indicated with a NULL entry.
+ *
+ * Returned Value:
+ * This function does not return on success. On failure, it will return
+ * -1 (ERROR) and will set the 'errno' value appropriately.
+ *
+ ****************************************************************************/
+
+int execv(FAR const char *path, FAR char *const argv[])
+{
+ FAR const struct symtab_s *symtab;
+ int nsymbols;
+ int ret;
+
+ /* Get the current symbol table selection */
+
+ exec_getsymtab(&symtab, &nsymbols);
+
+ /* Start the task */
+
+ ret = exec(path, (FAR const char **)argv, symtab, nsymbols);
+ if (ret < 0)
+ {
+ sdbg("exec failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Then exit */
+
+ exit(0);
+
+ /* We should not get here, but might be needed by some compilers. Other,
+ * smarter compilers might complain that this code is unreachable. You just
+ * can't win.
+ */
+
+ return ERROR;
+}
+
+#endif /* CONFIG_LIBC_EXECFUNCS */
diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig
index bfaec3b5d..6d53a03aa 100644
--- a/nuttx/sched/Kconfig
+++ b/nuttx/sched/Kconfig
@@ -38,6 +38,17 @@ config TASK_NAME_SIZE
Useful if scheduler instrumentation is selected. Set to zero to
disable.
+config SCHED_HAVE_PARENT
+ bool "Remember Parent"
+ default n
+ ---help---
+ Remember the ID of the parent thread when a new child thread is
+ created. This support enables some additional features (such as
+ SIGCHLD) and modifies the behavior of other interfaces. For
+ example, it makes waitpid() more standards complete by restricting
+ the waited-for tasks to the children of the caller. Default:
+ disabled.
+
config JULIAN_TIME
bool "Enables Julian time conversions"
default n
@@ -127,6 +138,7 @@ config SDCLONE_DISABLE
config SCHED_WORKQUEUE
bool "Enable worker thread"
default n
+ depends on !DISABLE_SIGNALS
---help---
Create a dedicated "worker" thread to handle delayed processing from interrupt
handlers. This feature is required for some drivers but, if there are no
@@ -158,14 +170,6 @@ config SCHED_WORKSTACKSIZE
---help---
The stack size allocated for the worker thread. Default: 2K.
-config SIG_SIGWORK
- int "Worker thread wakeup signal"
- default 4
- depends on SCHED_WORKQUEUE
- ---help---
- The signal number that will be used to wake-up the worker thread.
- Default: 4
-
config SCHED_LPWORK
bool "Enable a lower priority worker thread"
default n
@@ -203,7 +207,12 @@ config SCHED_WAITPID
bool "Enable waitpid() API"
default n
---help---
- Enables the waitpid() API
+ Enables the waitpid() interface in a default, non-standard mode
+ (non-standard in the sense that the waited for PID need not be child
+ of the caller). If SCHED_HAVE_PARENT is also defined, then this
+ setting will modify the behavior or waitpid() (making more spec
+ compliant) and will enable the waitid() and wait() interfaces as
+ well.
config SCHED_ATEXIT
bool "Enable atexit() API"
@@ -310,6 +319,56 @@ config DISABLE_POLL
depends on DISABLE_OS_API
default n
+if !DISABLE_SIGNALS
+comment "Signal Numbers"
+
+config SIG_SIGUSR1
+ int "SIGUSR1"
+ default 1
+ ---help---
+ Value of standard user signal 1 (SIGUSR1). Default: 1
+
+config SIG_SIGUSR2
+ int "SIGUSR2"
+ default 2
+ ---help---
+ Value of standard user signal 2 (SIGUSR2). Default: 2
+
+config SIG_SIGALARM
+ int "SIGALRM"
+ default 3
+ ---help---
+ Default the signal number used with POSIX timers (SIGALRM).
+ Default: 3
+
+config SIG_SIGCHLD
+ int "SIGCHLD"
+ default 4
+ depends on SCHED_HAVE_PARENT
+ ---help---
+ The SIGCHLD signal is sent to the parent of a child process when it
+ exits, is interrupted (stopped), or resumes after being interrupted.
+ Default: 4
+
+config SIG_SIGCONDTIMEDOUT
+ int "SIGCONDTIMEDOUT"
+ default 16
+ depends on !DISABLE_PTHREAD
+ ---help---
+ This non-standard signal number is used the implementation of
+ pthread_cond_timedwait(). Default 16.
+
+config SIG_SIGWORK
+ int "SIGWORK"
+ default 17
+ depends on SCHED_WORKQUEUE
+ ---help---
+ SIGWORK is a non-standard signal used to wake up the internal NuttX
+ worker thread. This setting specifies the signal number that will be
+ used for SIGWORK. Default: 17
+
+endif
+
comment "Sizes of configurable things (0 disables)"
config MAX_TASKS
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile
index 82f74fc3c..3d6b58bac 100644
--- a/nuttx/sched/Makefile
+++ b/nuttx/sched/Makefile
@@ -1,7 +1,7 @@
############################################################################
# sched/Makefile
#
-# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,7 @@ MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c \
TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c \
task_start.c task_delete.c task_deletecurrent.c task_exithook.c \
- task_restart.c exit.c getpid.c sched_addreadytorun.c \
+ task_restart.c task_vfork.c exit.c getpid.c sched_addreadytorun.c \
sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \
sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \
sched_verifytcb.c sched_releasetcb.c
@@ -69,6 +69,9 @@ endif
ifeq ($(CONFIG_SCHED_WAITPID),y)
SCHED_SRCS += sched_waitpid.c
+ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
+SCHED_SRCS += sched_waitid.c sched_wait.c
+endif
endif
ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c \
diff --git a/nuttx/sched/clock_time2ticks.c b/nuttx/sched/clock_time2ticks.c
index 9265872bb..012f4e4f1 100644
--- a/nuttx/sched/clock_time2ticks.c
+++ b/nuttx/sched/clock_time2ticks.c
@@ -89,14 +89,48 @@
int clock_time2ticks(FAR const struct timespec *reltime, FAR int *ticks)
{
+#ifdef CONFIG_HAVE_LONG_LONG
+ int64_t relnsec;
+
+ /* Convert the relative time into nanoseconds. The range of the int64_t is
+ * sufficiently large that there is no real need for range checking.
+ */
+
+ relnsec = (int64_t)reltime->tv_sec * NSEC_PER_SEC +
+ (int64_t)reltime->tv_nsec;
+
+ /* Convert nanoseconds to clock ticks, rounding up to the smallest integer
+ * that is greater than or equal to the exact number of tick.
+ */
+
+ *ticks = (int)((relnsec + NSEC_PER_TICK - 1) / NSEC_PER_TICK);
+ return OK;
+#else
int32_t relusec;
- /* Convert the relative time into microseconds.*/
+ /* This function uses an int32_t to only the relative time in microseconds.
+ * that means that the maximum supported relative time is 2,147,487.647
+ * seconds
+ */
+
+#if 0 // overkill
+ DEBUGASSERT(reltime->tv_sec < 2147487 ||
+ reltime->tv_sec == 2147487 &&
+ reltime->tv_nsec <= 647 * NSEC_PER_MSEC);
+#endif
+
+ /* Convert the relative time into microseconds, rounding up to the smallest
+ * value that is greater than or equal to the exact number of microseconds.
+ */
- relusec = reltime->tv_sec * USEC_PER_SEC + reltime->tv_nsec / NSEC_PER_USEC;
+ relusec = reltime->tv_sec * USEC_PER_SEC +
+ (reltime->tv_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC;
- /* Convert microseconds to clock ticks */
+ /* Convert microseconds to clock ticks, rounding up to the smallest integer
+ * that is greater than or equal to the exact number of tick.
+ */
- *ticks = (relusec + USEC_PER_TICK - 1) / USEC_PER_TICK;
+ *ticks = (int)((relusec + USEC_PER_TICK - 1) / USEC_PER_TICK);
return OK;
+#endif
}
diff --git a/nuttx/sched/mq_initialize.c b/nuttx/sched/mq_initialize.c
index 5b03a1120..dd7c7ed0f 100644
--- a/nuttx/sched/mq_initialize.c
+++ b/nuttx/sched/mq_initialize.c
@@ -217,11 +217,11 @@ void mq_initialize(void)
void mq_desblockalloc(void)
{
- struct mq_des_block_s *mqdesblock;
+ FAR struct mq_des_block_s *mqdesblock;
/* Allocate a block of message descriptors */
- mqdesblock = (struct mq_des_block_s *)kmalloc(sizeof(struct mq_des_block_s));
+ mqdesblock = (FAR struct mq_des_block_s *)kmalloc(sizeof(struct mq_des_block_s));
if (mqdesblock)
{
int i;
diff --git a/nuttx/sched/os_bringup.c b/nuttx/sched/os_bringup.c
index e0a236bbe..610d8515a 100644
--- a/nuttx/sched/os_bringup.c
+++ b/nuttx/sched/os_bringup.c
@@ -57,9 +57,6 @@
#ifdef CONFIG_SCHED_WORKQUEUE
# include "work_internal.h"
#endif
-#ifdef CONFIG_BUILTIN_APP_START
-# include "apps/apps.h"
-#endif
#ifdef CONFIG_NUTTX_KERNEL
# include "arch/board/user_map.h"
#endif
@@ -112,22 +109,15 @@
* function is to serve as the "bottom half" of device
* drivers.
*
- * And the main application entry point. This may be one of two different
+ * And the main application entry point:
* symbols:
*
- * - USER_ENTRYPOINT: This is the default entry point used for all of the
- * example code in apps/examples.
- * - CONFIG_BUILTIN_APP_START: The system can also be configured to start
- * custom applications at however CONFIG_BUILTIN_APP_START
- * is defined in the NuttX start-up file.
+ * - USER_ENTRYPOINT: This is the default user application entry point.
*
****************************************************************************/
int os_bringup(void)
{
-#ifdef CONFIG_BUILTIN_APP_START
- static const char *argv[3] = {NULL, "init", NULL};
-#endif
int init_taskid;
/* Setup up the initial environment for the idle task. At present, this
@@ -188,19 +178,11 @@ int os_bringup(void)
svdbg("Starting init thread\n");
-#ifdef CONFIG_BUILTIN_APP_START
- /* Start the built-in named application, passing an "init" argument, so that
- * application can distinguish different run-levels
- */
-
- init_taskid = exec_namedapp(CONFIG_BUILTIN_APP_START, argv);
-#else
/* Start the default application at CONFIG_USER_ENTRYPOINT() */
init_taskid = TASK_CREATE("init", SCHED_PRIORITY_DEFAULT,
CONFIG_USERMAIN_STACKSIZE,
(main_t)CONFIG_USER_ENTRYPOINT, (const char **)NULL);
-#endif
ASSERT(init_taskid != ERROR);
/* We an save a few bytes by discarding the IDLE thread's environment. */
diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h
index 13b8083cf..32d9fb4ac 100644
--- a/nuttx/sched/os_internal.h
+++ b/nuttx/sched/os_internal.h
@@ -83,10 +83,10 @@ enum os_crash_codes_e
OSERR_BADREPRIORITIZESTATE /* Attempt to reprioritize in bad state or priority */
};
-/* Special task IDS */
+/* Special task IDS. Any negative PID is invalid. */
-#define NULL_TASK_PROCESS_ID 0
-#define INVALID_PROCESS_ID 0
+#define NULL_TASK_PROCESS_ID (pid_t)0
+#define INVALID_PROCESS_ID (pid_t)-1
/* Although task IDs can take the (positive, non-zero)
* range of pid_t, the number of tasks that will be supported
diff --git a/nuttx/sched/sched_addprioritized.c b/nuttx/sched/sched_addprioritized.c
index 8f19a4731..20178fb9c 100644
--- a/nuttx/sched/sched_addprioritized.c
+++ b/nuttx/sched/sched_addprioritized.c
@@ -114,7 +114,7 @@ bool sched_addprioritized(FAR _TCB *tcb, DSEG dq_queue_t *list)
(next && sched_priority <= next->sched_priority);
next = next->flink);
- /* Add the tcb to the spot found in the list. Check if the tcb
+ /* Add the tcb to the spot found in the list. Check if the tcb
* goes at the end of the list. NOTE: This could only happen if list
* is the g_pendingtasks list!
*/
diff --git a/nuttx/sched/sched_addreadytorun.c b/nuttx/sched/sched_addreadytorun.c
index f6117b6ff..1e1829343 100644
--- a/nuttx/sched/sched_addreadytorun.c
+++ b/nuttx/sched/sched_addreadytorun.c
@@ -84,8 +84,8 @@
* btcb - Points to the blocked TCB that is ready-to-run
*
* Return Value:
- * true if the currently active task (the head of the
- * g_readytorun list) has changed.
+ * true if the currently active task (the head of the g_readytorun list)
+ * has changed.
*
* Assumptions:
* - The caller has established a critical section before
@@ -104,7 +104,7 @@ bool sched_addreadytorun(FAR _TCB *btcb)
bool ret;
/* Check if pre-emption is disabled for the current running task and if
- * the new ready-to-run task would cause the current running task to be
+ * the new ready-to-run task would cause the current running task to be
* preempted.
*/
@@ -123,7 +123,7 @@ bool sched_addreadytorun(FAR _TCB *btcb)
else if (sched_addprioritized(btcb, (FAR dq_queue_t*)&g_readytorun))
{
- /* Information the instrumentation logic that we are switching tasks */
+ /* Inform the instrumentation logic that we are switching tasks */
sched_note_switch(rtcb, btcb);
diff --git a/nuttx/sched/sched_setuptaskfiles.c b/nuttx/sched/sched_setuptaskfiles.c
index fe0b14143..d01b8d4cd 100644
--- a/nuttx/sched/sched_setuptaskfiles.c
+++ b/nuttx/sched/sched_setuptaskfiles.c
@@ -200,7 +200,8 @@ static inline void sched_dupsockets(FAR _TCB *tcb)
* tcb - tcb of the new task.
*
* Return Value:
- * None
+ * Zero (OK) is returned on success; A negated errno value is returned on
+ * failure.
*
* Assumptions:
*
diff --git a/nuttx/sched/sched_unlock.c b/nuttx/sched/sched_unlock.c
index 9a52e8358..5eafcfc9e 100644
--- a/nuttx/sched/sched_unlock.c
+++ b/nuttx/sched/sched_unlock.c
@@ -126,5 +126,6 @@ int sched_unlock(void)
irqrestore(flags);
}
+
return OK;
}
diff --git a/nuttx/sched/sched_wait.c b/nuttx/sched/sched_wait.c
new file mode 100644
index 000000000..813d4f842
--- /dev/null
+++ b/nuttx/sched/sched_wait.c
@@ -0,0 +1,90 @@
+/*****************************************************************************
+ * sched/sched_wait.c
+ *
+ * Copyright (C) 2013 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/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <nuttx/sched.h>
+
+#include "os_internal.h"
+
+#if defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: wait
+ *
+ * Description:
+ * The wait() function will suspend execution of the calling thread until
+ * status information for one of its terminated child processes is
+ * available, or until delivery of a signal whose action is either to
+ * execute a signal-catching function or to terminate the process. If more
+ * than one thread is suspended in wait() or waitpid() awaiting termination
+ * of the same process, exactly one thread will return the process status
+ * at the time of the target process termination. If status information is
+ * available prior to the call to wait(), return will be immediate.
+ *
+ * The waitpid() function will behave identically to wait(), if the pid
+ * argument is (pid_t)-1 and the options argument is 0. Otherwise, its
+ * behaviour will be modified by the values of the pid and options arguments.
+ *
+ * Input Parameters:
+ * stat_loc - The location to return the exit status
+ *
+ * Returned Value:
+ * See waitpid();
+ *
+ *****************************************************************************/
+
+pid_t wait(FAR int *stat_loc)
+{
+ return waitpid((pid_t)-1, stat_loc, 0);
+}
+
+#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT*/
diff --git a/nuttx/sched/sched_waitid.c b/nuttx/sched/sched_waitid.c
new file mode 100644
index 000000000..eabc69afe
--- /dev/null
+++ b/nuttx/sched/sched_waitid.c
@@ -0,0 +1,256 @@
+/*****************************************************************************
+ * sched/sched_waitid.c
+ *
+ * Copyright (C) 2013 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/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <nuttx/sched.h>
+
+#include "os_internal.h"
+
+#if defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: waitid
+ *
+ * Description:
+ * The waitid() function suspends the calling thread until one child of
+ * the process containing the calling thread changes state. It records the
+ * current state of a child in the structure pointed to by 'info'. If a
+ * child process changed state prior to the call to waitid(), waitid()
+ * returns immediately. If more than one thread is suspended in wait() or
+ * waitpid() waiting termination of the same process, exactly one thread
+ * will return the process status at the time of the target process
+ * termination
+ *
+ * The idtype and id arguments are used to specify which children waitid()
+ * will wait for.
+ *
+ * If idtype is P_PID, waitid() will wait for the child with a process
+ * ID equal to (pid_t)id.
+ *
+ * If idtype is P_PGID, waitid() will wait for any child with a process
+ * group ID equal to (pid_t)id.
+ *
+ * If idtype is P_ALL, waitid() will wait for any children and id is
+ * ignored.
+ *
+ * The options argument is used to specify which state changes waitid()
+ * will will wait for. It is formed by OR-ing together one or more of the
+ * following flags:
+ *
+ * WEXITED - Wait for processes that have exited.
+ * WSTOPPED - Status will be returned for any child that has stopped
+ * upon receipt of a signal.
+ * WCONTINUED - Status will be returned for any child that was stopped
+ * and has been continued.
+ * WNOHANG - Return immediately if there are no children to wait for.
+ * WNOWAIT - Keep the process whose status is returned in 'info' in a
+ * waitable state. This will not affect the state of the process; the
+ * process may be waited for again after this call completes.
+ *
+ * The 'info' argument must point to a siginfo_t structure. If waitid()
+ * returns because a child process was found that satisfied the conditions
+ * indicated by the arguments idtype and options, then the structure pointed
+ * to by 'info' will be filled in by the system with the status of the
+ * process. The si_signo member will always be equal to SIGCHLD.
+ *
+ * Input Parameters:
+ * See description.
+ *
+ * Returned Value:
+ * If waitid() returns due to the change of state of one of its children,
+ * 0 is returned. Otherwise, -1 is returned and errno is set to indicate
+ * the error.
+ *
+ * The waitid() function will fail if:
+ *
+ * ECHILD - The calling process has no existing unwaited-for child
+ * processes.
+ * EINTR - The waitid() function was interrupted by a signal.
+ * EINVAL - An invalid value was specified for options, or idtype and id
+ * specify an invalid set of processes.
+ *
+ *****************************************************************************/
+
+int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
+{
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ sigset_t sigset;
+ int err;
+ int ret;
+
+ /* MISSING LOGIC: If WNOHANG is provided in the options, then this function
+ * should returned immediately. However, there is no mechanism available now
+ * know if the thread has child: The children remember their parents (if
+ * CONFIG_SCHED_HAVE_PARENT) but the parents do not remember their children.
+ */
+
+ /* None of the options are supported except for WEXITED (which must be
+ * provided. Currently SIGCHILD always reports CLD_EXITED so we cannot
+ * distinguish any other events.
+ */
+
+#ifdef CONFIG_DEBUG
+ if (options != WEXITED)
+ {
+ set_errno(ENOSYS);
+ return ERROR;
+ }
+#endif
+
+ /* Create a signal set that contains only SIGCHLD */
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+
+ /* Disable pre-emption so that nothing changes while the loop executes */
+
+ sched_lock();
+
+ /* Verify that this task actually has children and that the the requeste
+ * TCB is actually a child of this task.
+ */
+
+ if (rtcb->nchildren == 0)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (idtype == P_PID)
+ {
+ /* Get the TCB corresponding to this PID and make sure it is our child. */
+
+ FAR _TCB *ctcb = sched_gettcb((pid_t)id);
+ if (!ctcb || ctcb->parent != rtcb->pid)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+
+ /* Loop until the child that we are waiting for dies */
+
+ for (;;)
+ {
+ /* Check if the task has already died. Signals are not queued in
+ * NuttX. So a possibility is that the child has died and we
+ * missed the death of child signal (we got some other signal
+ * instead).
+ */
+
+ if (rtcb->nchildren == 0 ||
+ (idtype == P_PID && (ret = kill((pid_t)id, 0)) < 0))
+ {
+ /* We know that the child task was running okay we stared,
+ * so we must have lost the signal. What can we do?
+ * Let's claim we were interrupted by a signal.
+ */
+
+ err = EINTR;
+ goto errout_with_errno;
+ }
+
+ /* Wait for any death-of-child signal */
+
+ ret = sigwaitinfo(&sigset, info);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ /* Make there this was SIGCHLD */
+
+ if (info->si_signo == SIGCHLD)
+ {
+ /* Yes.. Are we waiting for the death of a specific child? */
+
+ if (idtype == P_PID)
+ {
+ /* Was this the death of the thread we were waiting for? */
+
+ if (info->si_pid == (pid_t)id)
+ {
+ /* Yes... return success */
+
+ break;
+ }
+ }
+
+ /* Are we waiting for any child to change state? */
+
+ else if (idtype == P_ALL)
+ {
+ /* Return success */
+
+ break;
+ }
+
+ /* Other ID types are not supported */
+
+ else /* if (idtype == P_PGID) */
+ {
+ set_errno(ENOSYS);
+ goto errout;
+ }
+ }
+ }
+
+ sched_unlock();
+ return OK;
+
+errout_with_errno:
+ set_errno(err);
+errout:
+ sched_unlock();
+ return ERROR;
+}
+
+#endif /* CONFIG_SCHED_WAITPID && CONFIG_SCHED_HAVE_PARENT*/
diff --git a/nuttx/sched/sched_waitpid.c b/nuttx/sched/sched_waitpid.c
index 692ef6410..dc715b2e9 100644
--- a/nuttx/sched/sched_waitpid.c
+++ b/nuttx/sched/sched_waitpid.c
@@ -1,7 +1,7 @@
/*****************************************************************************
* sched/sched_waitpid.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,13 +41,14 @@
#include <sys/wait.h>
#include <semaphore.h>
+#include <signal.h>
#include <errno.h>
#include <nuttx/sched.h>
#include "os_internal.h"
-#ifdef CONFIG_SCHED_WAITPID /* Experimental */
+#ifdef CONFIG_SCHED_WAITPID
/*****************************************************************************
* Private Functions
@@ -58,7 +59,7 @@
*****************************************************************************/
/*****************************************************************************
- * Name: sched_waitpid
+ * Name: waitpid
*
* Description:
*
@@ -172,10 +173,16 @@
*
*****************************************************************************/
-/***************************************************************************/
-/* NOTE: This is a partially functional, experimental version of waitpid() */
-/***************************************************************************/
+/***************************************************************************
+ * NOTE: This is a partially functional, experimental version of waitpid()
+ *
+ * If there is no SIGCHLD signal supported (CONFIG_SCHED_HAVE_PARENT not
+ * defined), then waitpid() is still available, but does not obey the
+ * restriction that the pid be a child of the caller.
+ *
+ ***************************************************************************/
+#ifndef CONFIG_SCHED_HAVE_PARENT
pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
_TCB *tcb;
@@ -183,9 +190,24 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
int err;
int ret;
+ DEBUGASSERT(stat_loc);
+
+ /* None of the options are supported */
+
+#ifdef CONFIG_DEBUG
+ if (options != 0)
+ {
+ set_errno(ENOSYS);
+ return ERROR;
+ }
+#endif
+
/* Disable pre-emption so that nothing changes in the following tests */
sched_lock();
+
+ /* Get the TCB corresponding to this PID */
+
tcb = sched_gettcb(pid);
if (!tcb)
{
@@ -193,16 +215,6 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
goto errout_with_errno;
}
- /* None of the options are supported */
-
-#ifdef CONFIG_DEBUG
- if (options != 0)
- {
- err = ENOSYS;
- goto errout_with_errno;
- }
-#endif
-
/* "If more than one thread is suspended in waitpid() awaiting termination of
* the same process, exactly one thread will return the process status at the
* time of the target process termination." Hmmm.. what do we return to the
@@ -245,4 +257,152 @@ errout:
return ERROR;
}
+/***************************************************************************
+ *
+ * If CONFIG_SCHED_HAVE_PARENT is defined, then waitpid will use the SIGHCLD
+ * signal. It can also handle the pid == (pid_t)-1 arguement. This is
+ * slightly more spec-compliant.
+ *
+ * But then I have to be concerned about the fact that NuttX does not queue
+ * signals. This means that a flurry of signals can cause signals to be
+ * lost (or to have the data in the struct siginfo to be overwritten by
+ * the next signal).
+ *
+ ***************************************************************************/
+
+#else
+pid_t waitpid(pid_t pid, int *stat_loc, int options)
+{
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ FAR struct siginfo info;
+ sigset_t sigset;
+ int err;
+ int ret;
+
+ DEBUGASSERT(stat_loc);
+
+ /* None of the options are supported */
+
+#ifdef CONFIG_DEBUG
+ if (options != 0)
+ {
+ set_errno(ENOSYS);
+ return ERROR;
+ }
+#endif
+
+ /* Create a signal set that contains only SIGCHLD */
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+
+ /* Disable pre-emption so that nothing changes while the loop executes */
+
+ sched_lock();
+
+ /* Verify that this task actually has children and that the the requeste
+ * TCB is actually a child of this task.
+ */
+
+ if (rtcb->nchildren == 0)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ else if (pid != (pid_t)-1)
+ {
+ /* Get the TCB corresponding to this PID and make sure it is our child. */
+
+ FAR _TCB *ctcb = sched_gettcb(pid);
+ if (!ctcb || ctcb->parent != rtcb->pid)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+
+ /* Loop until the child that we are waiting for dies */
+
+ for (;;)
+ {
+ /* Check if the task has already died. Signals are not queued in
+ * NuttX. So a possibility is that the child has died and we
+ * missed the death of child signal (we got some other signal
+ * instead).
+ */
+
+ if (pid == (pid_t)-1)
+ {
+ /* We are waiting for any child, check if there are still
+ * chilren.
+ */
+
+ if (rtcb->nchildren == 0)
+ {
+ /* There were one or more children when we started so they
+ * must have exit'ed. There are just no bread crumbs left
+ * behind to tell us the PID(s) of the existed children.
+ * Reporting ECHLD is about all we can do in this case.
+ */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+ else
+ {
+ /* We are waiting for a specific PID. We can use kill() with
+ * signal number 0 to determine if that task is still alive.
+ */
+
+ ret = kill(pid, 0);
+ if (ret < 0)
+ {
+ /* It is no longer running. We know that the child task was
+ * running okay when we started, so we must have lost the
+ * signal. In this case, we know that the task exit'ed, but
+ * we do not know its exit status. It would be better to
+ * reported ECHILD that bogus status.
+ */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
+
+ /* Wait for any death-of-child signal */
+
+ ret = sigwaitinfo(&sigset, &info);
+ if (ret < 0)
+ {
+ goto errout_with_lock;
+ }
+
+ /* Was this the death of the thread we were waiting for? In the of
+ * pid == (pid_t)-1, we are waiting for any child thread.
+ */
+
+ if (info.si_signo == SIGCHLD &&
+ (pid == (pid_t)-1 || info.si_pid == pid))
+ {
+ /* Yes... return the status and PID (in the event it was -1) */
+
+ *stat_loc = info.si_status;
+ pid = info.si_pid;
+ break;
+ }
+ }
+
+ sched_unlock();
+ return (int)pid;
+
+errout_with_errno:
+ set_errno(err);
+
+errout_with_lock:
+ sched_unlock();
+ return ERROR;
+}
+#endif /* CONFIG_SCHED_HAVE_PARENT */
+
#endif /* CONFIG_SCHED_WAITPID */
diff --git a/nuttx/sched/sig_kill.c b/nuttx/sched/sig_kill.c
index 17921015f..b3d74d8a1 100644
--- a/nuttx/sched/sig_kill.c
+++ b/nuttx/sched/sig_kill.c
@@ -84,6 +84,9 @@
int kill(pid_t pid, int signo)
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#endif
FAR _TCB *stcb;
siginfo_t info;
int ret = ERROR;
@@ -124,6 +127,10 @@ int kill(pid_t pid, int signo)
info.si_signo = signo;
info.si_code = SI_USER;
info.si_value.sival_ptr = NULL;
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = rtcb->pid;
+ info.si_status = OK;
+#endif
/* Send the signal */
diff --git a/nuttx/sched/sig_mqnotempty.c b/nuttx/sched/sig_mqnotempty.c
index 9a1fd7243..f7ae6fd0d 100644
--- a/nuttx/sched/sig_mqnotempty.c
+++ b/nuttx/sched/sig_mqnotempty.c
@@ -88,6 +88,9 @@ int sig_mqnotempty (int pid, int signo, union sigval value)
int sig_mqnotempty (int pid, int signo, void *sival_ptr)
#endif
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#endif
FAR _TCB *stcb;
siginfo_t info;
int ret = ERROR;
@@ -113,6 +116,10 @@ int sig_mqnotempty (int pid, int signo, void *sival_ptr)
#else
info.si_value.sival_ptr = sival_ptr;
#endif
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = rtcb->pid;
+ info.si_status = OK;
+#endif
/* Verify that we can perform the signalling operation */
diff --git a/nuttx/sched/sig_queue.c b/nuttx/sched/sig_queue.c
index dee1c798a..db404238e 100644
--- a/nuttx/sched/sig_queue.c
+++ b/nuttx/sched/sig_queue.c
@@ -111,6 +111,9 @@ int sigqueue (int pid, int signo, union sigval value)
int sigqueue(int pid, int signo, void *sival_ptr)
#endif
{
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+#endif
FAR _TCB *stcb;
siginfo_t info;
int ret = ERROR;
@@ -142,13 +145,17 @@ int sigqueue(int pid, int signo, void *sival_ptr)
/* Create the siginfo structure */
- info.si_signo = signo;
- info.si_code = SI_QUEUE;
+ info.si_signo = signo;
+ info.si_code = SI_QUEUE;
#ifdef CONFIG_CAN_PASS_STRUCTS
- info.si_value = value;
+ info.si_value = value;
#else
info.si_value.sival_ptr = sival_ptr;
#endif
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = rtcb->pid;
+ info.si_status = OK;
+#endif
/* Send the signal */
diff --git a/nuttx/sched/sig_timedwait.c b/nuttx/sched/sig_timedwait.c
index 1b8dfd162..f8c619b21 100644
--- a/nuttx/sched/sig_timedwait.c
+++ b/nuttx/sched/sig_timedwait.c
@@ -38,6 +38,7 @@
****************************************************************************/
#include <nuttx/config.h>
+#include <nuttx/compiler.h>
#include <stdint.h>
#include <string.h>
@@ -119,6 +120,10 @@ static void sig_timeout(int argc, uint32_t itcb)
u.wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT;
u.wtcb->sigunbinfo.si_code = SI_TIMER;
u.wtcb->sigunbinfo.si_value.sival_int = 0;
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ u.wtcb->sigunbinfo.si_pid = 0; /* Not applicable */
+ u.wtcb->sigunbinfo.si_status = OK;
+#endif
up_unblock_task(u.wtcb);
}
}
@@ -223,7 +228,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
/* The return value is the number of the signal that awakened us */
- ret = info->si_signo;
+ ret = sigpend->info.si_signo;
}
/* We will have to wait for a signal to be posted to this task. */
@@ -238,10 +243,25 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
if (timeout)
{
- /* Convert the timespec to milliseconds */
+ /* Convert the timespec to system clock ticks, making sure that
+ * the resultint delay is greater than or equal to the requested
+ * time in nanoseconds.
+ */
- waitticks = MSEC2TICK(timeout->tv_sec * MSEC_PER_SEC
- + timeout->tv_nsec / NSEC_PER_MSEC);
+#ifdef CONFIG_HAVE_LONG_LONG
+ uint64_t waitticks64 = ((uint64_t)timeout->tv_sec * NSEC_PER_SEC +
+ (uint64_t)timeout->tv_nsec + NSEC_PER_TICK - 1) /
+ NSEC_PER_TICK;
+ DEBUGASSERT(waitticks64 <= UINT32_MAX);
+ waitticks = (uint32_t)waitticks64;
+#else
+ uint32_t waitmsec;
+
+ DEBUGASSERT(timeout->tv_sec < UINT32_MAX / MSEC_PER_SEC);
+ waitmsec = timeout->tv_sec * MSEC_PER_SEC +
+ (timeout->tv_nsec + NSEC_PER_MSEC - 1) / NSEC_PER_MSEC;
+ waitticks = (waitmsec + MSEC_PER_TICK - 1) / MSEC_PER_TICK;
+#endif
/* Create a watchdog */
@@ -326,6 +346,7 @@ int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *info,
{
memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo));
}
+
irqrestore(saved_state);
}
diff --git a/nuttx/sched/task_create.c b/nuttx/sched/task_create.c
index 4d92c9bb0..801706cbf 100644
--- a/nuttx/sched/task_create.c
+++ b/nuttx/sched/task_create.c
@@ -169,6 +169,8 @@ static int thread_create(const char *name, uint8_t type, int priority,
ret = task_activate(tcb);
if (ret != OK)
{
+ /* The TCB was added to the active task list by task_schedsetup() */
+
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
goto errout_with_tcb;
}
diff --git a/nuttx/sched/task_deletecurrent.c b/nuttx/sched/task_deletecurrent.c
index 77025f5e0..e1e06acf6 100644
--- a/nuttx/sched/task_deletecurrent.c
+++ b/nuttx/sched/task_deletecurrent.c
@@ -90,6 +90,9 @@
* Return Value:
* OK on success; or ERROR on failure
*
+ * Assumeptions:
+ * Interrupts are disabled.
+ *
****************************************************************************/
int task_deletecurrent(void)
@@ -108,13 +111,16 @@ int task_deletecurrent(void)
(void)sched_removereadytorun(dtcb);
rtcb = (FAR _TCB*)g_readytorun.head;
- /* We are not in a bad state -- the head of the ready to run task list
+ /* We are now in a bad state -- the head of the ready to run task list
* does not correspond to the thread that is running. Disabling pre-
* emption on this TCB and marking the new ready-to-run task as not
* running (see, for example, get_errno_ptr()).
+ *
+ * We disable pre-emption here by directly incrementing the lockcount
+ * (vs. calling sched_lock()).
*/
- sched_lock();
+ rtcb->lockcount++;
rtcb->task_state = TSTATE_TASK_READYTORUN;
/* Move the TCB to the specified blocked task list and delete it */
@@ -132,9 +138,15 @@ int task_deletecurrent(void)
(void)sched_mergepending();
}
- /* Now calling sched_unlock() should have no effect */
+ /* We can't use sched_unlock() to decrement the lock count because the
+ * sched_mergepending() call above might have changed the task at the
+ * head of the ready-to-run list. Furthermore, we should not need to
+ * perform the unlock action anyway because we know that the pending
+ * task list is empty. So all we really need to do is to decrement
+ * the lockcount on rctb.
+ */
- sched_unlock();
+ rtcb->lockcount--;
return OK;
}
diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c
index 3bde8fb7a..1106f2885 100644
--- a/nuttx/sched/task_exithook.c
+++ b/nuttx/sched/task_exithook.c
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include <signal.h>
#include <debug.h>
#include <errno.h>
@@ -188,6 +189,70 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
#endif
/****************************************************************************
+ * Name: task_sigchild
+ *
+ * Description:
+ * Send the SIGCHILD signal to the parent thread
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static inline void task_sigchild(FAR _TCB *tcb, int status)
+{
+ FAR _TCB *ptcb;
+ siginfo_t info;
+
+ /* Keep things stationary through the following */
+
+ sched_lock();
+
+ /* Get the TCB of the receiving task */
+
+ ptcb = sched_gettcb(tcb->parent);
+ if (!ptcb)
+ {
+ /* The parent no longer exists... bail */
+
+ sched_unlock();
+ return;
+ }
+
+ /* Decrement the number of children from this parent */
+
+ DEBUGASSERT(ptcb->nchildren > 0);
+ ptcb->nchildren--;
+
+ /* Set the parent to an impossible PID. We do this because under certain
+ * conditions, task_exithook() can be called multiple times. If this
+ * function is called again, sched_gettcb() will fail on the invalid
+ * parent PID above, nchildren will be decremented once and all will be
+ * well.
+ */
+
+ tcb->parent = INVALID_PROCESS_ID;
+
+ /* Create the siginfo structure. We don't actually know the cause. That
+ * is a bug. Let's just say that the child task just exit-ted for now.
+ */
+
+ info.si_signo = SIGCHLD;
+ info.si_code = CLD_EXITED;
+ info.si_value.sival_ptr = NULL;
+ info.si_pid = tcb->pid;
+ info.si_status = status;
+
+ /* Send the signal. We need to use this internal interface so that we can
+ * provide the correct si_code value with the signal.
+ */
+
+ (void)sig_received(ptcb, &info);
+ sched_unlock();
+}
+#else
+# define task_sigchild(tcb,status)
+#endif
+
+/****************************************************************************
* Name: task_exitwakeup
*
* Description:
@@ -195,7 +260,7 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
*
****************************************************************************/
-#ifdef CONFIG_SCHED_WAITPID
+#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
static inline void task_exitwakeup(FAR _TCB *tcb, int status)
{
/* Wakeup any tasks waiting for this task to exit */
@@ -263,6 +328,10 @@ void task_exithook(FAR _TCB *tcb, int status)
task_onexit(tcb, status);
+ /* Send SIGCHLD to the parent of the exit-ing task */
+
+ task_sigchild(tcb, status);
+
/* Wakeup any tasks waiting for this task to exit */
task_exitwakeup(tcb, status);
diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c
index a37fb165a..92897f0ae 100644
--- a/nuttx/sched/task_setup.c
+++ b/nuttx/sched/task_setup.c
@@ -147,6 +147,37 @@ static int task_assignpid(FAR _TCB *tcb)
}
/****************************************************************************
+ * Name: task_saveparent
+ *
+ * Description:
+ * Save the task ID of the parent task in the child task's TCB.
+ *
+ * Parameters:
+ * tcb - The TCB of the new, child task.
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * The parent of the new task is the task at the head of the ready-to-run
+ * list.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static inline void task_saveparent(FAR _TCB *tcb)
+{
+ FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+
+ DEBUGASSERT(rtcb->nchildren < UINT16_MAX);
+ tcb->parent = rtcb->pid;
+ rtcb->nchildren++;
+}
+#else
+# define task_saveparent(tcb)
+#endif
+
+/****************************************************************************
* Name: task_dupdspace
*
* Description:
@@ -161,6 +192,8 @@ static int task_assignpid(FAR _TCB *tcb)
* None
*
* Assumptions:
+ * The parent of the new task is the task at the head of the ready-to-run
+ * list.
*
****************************************************************************/
@@ -231,8 +264,12 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main)
tcb->start = start;
tcb->entry.main = main;
- /* exec() and pthread_create() inherit the signal mask of the
- * parent thread. I suppose that task_create() should as well.
+ /* Save the task ID of the parent task in the TCB */
+
+ task_saveparent(tcb);
+
+ /* exec(), pthread_create(), task_create(), and vfork() all
+ * inherit the signal mask of the parent thread.
*/
#ifndef CONFIG_DISABLE_SIGNALS
@@ -243,7 +280,7 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main)
* until it is activated.
*/
- tcb->task_state = TSTATE_TASK_INVALID;
+ tcb->task_state = TSTATE_TASK_INVALID;
/* Clone the parent tasks D-Space (if it was running PIC). This
* must be done before calling up_initial_state() so that the
diff --git a/nuttx/sched/task_vfork.c b/nuttx/sched/task_vfork.c
new file mode 100644
index 000000000..46b2d8e9f
--- /dev/null
+++ b/nuttx/sched/task_vfork.c
@@ -0,0 +1,338 @@
+/****************************************************************************
+ * sched/task_vfork
+ *
+ * Copyright (C) 2013 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 <stdint.h>
+#include <assert.h>
+#include <queue.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/sched.h>
+
+#include "os_internal.h"
+#include "env_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: task_vforksetup
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the
+ * behavior is undefined if the process created by vfork() either modifies
+ * any data other than a variable of type pid_t used to store the return
+ * value from vfork(), or returns from the function in which vfork() was
+ * called, or calls any other function before successfully calling _exit()
+ * or one of the exec family of functions.
+ *
+ * This functin provides one step in the overall vfork() sequence: It
+ * Allocates and initializes the child task's TCB. The overall sequence is:
+ *
+ * 1) User code calls vfork(). vfork() is provided in architecture-specific
+ * code.
+ * 2) vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) up_vfork() provides any additional operating context. up_vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) up_vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * Input Paremeters:
+ * retaddr - The return address from vfork() where the child task
+ * will be started.
+ *
+ * Returned Value:
+ * Upon successful completion, task_vforksetup() returns a pointer to
+ * newly allocated and initalized child task's TCB. NULL is returned
+ * on any failure and the errno is set appropriately.
+ *
+ ****************************************************************************/
+
+FAR _TCB *task_vforksetup(start_t retaddr)
+{
+ _TCB *parent = (FAR _TCB *)g_readytorun.head;
+ _TCB *child;
+ int priority;
+ int ret;
+
+ DEBUGASSERT(retaddr);
+
+ /* Allocate a TCB for the child task. */
+
+ child = (FAR _TCB*)kzalloc(sizeof(_TCB));
+ if (!child)
+ {
+ set_errno(ENOMEM);
+ return NULL;
+ }
+
+ /* Associate file descriptors with the new task */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+ ret = sched_setuptaskfiles(child);
+ if (ret != OK)
+ {
+ goto errout_with_tcb;
+ }
+#endif
+
+ /* Clone the parent's task environment */
+
+ (void)env_dup(child);
+
+ /* Mark the type of this thread (this setting will be needed in
+ * task_schedsetup() when up_initial_state() is called.
+ */
+
+ child->flags |= TCB_FLAG_TTYPE_TASK;
+
+ /* Get the priority of the parent task */
+
+#ifdef CONFIG_PRIORITY_INHERITANCE
+ priority = parent->base_priority; /* "Normal," unboosted priority */
+#else
+ priority = parent->sched_priority; /* Current priority */
+#endif
+
+ /* Initialize the task control block. This calls up_initial_state() */
+
+ svdbg("Child priority=%d start=%p\n", priority, retaddr);
+ ret = task_schedsetup(child, priority, retaddr, parent->entry.main);
+ if (ret != OK)
+ {
+ goto errout_with_tcb;
+ }
+
+ svdbg("parent=%p, returning child=%p\n", parent, child);
+ return child;
+
+errout_with_tcb:
+ sched_releasetcb(child);
+ set_errno(-ret);
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: task_vforkstart
+ *
+ * Description:
+ * The vfork() function has the same effect as fork(), except that the
+ * behavior is undefined if the process created by vfork() either modifies
+ * any data other than a variable of type pid_t used to store the return
+ * value from vfork(), or returns from the function in which vfork() was
+ * called, or calls any other function before successfully calling _exit()
+ * or one of the exec family of functions.
+ *
+ * This functin provides one step in the overall vfork() sequence: It
+ * starts execution of the previously initialized TCB. The overall
+ * sequence is:
+ *
+ * 1) User code calls vfork()
+ * 2) Architecture-specific code provides vfork()and calls task_vforksetup().
+ * 3) task_vforksetup() allocates and configures the child task's TCB. This
+ * consists of:
+ * - Allocation of the child task's TCB.
+ * - Initialization of file descriptors and streams
+ * - Configuration of environment variables
+ * - Setup the intput parameters for the task.
+ * - Initialization of the TCB (including call to up_initial_state()
+ * 4) vfork() provides any additional operating context. vfork must:
+ * - Allocate and initialize the stack
+ * - Initialize special values in any CPU registers that were not
+ * already configured by up_initial_state()
+ * 5) vfork() then calls task_vforkstart()
+ * 6) task_vforkstart() then executes the child thread.
+ *
+ * Input Paremeters:
+ * retaddr - The return address from vfork() where the child task
+ * will be started.
+ *
+ * Returned Value:
+ * Upon successful completion, vfork() returns 0 to the child process and
+ * returns the process ID of the child process to the parent process.
+ * Otherwise, -1 is returned to the parent, no child process is created,
+ * and errno is set to indicate the error.
+ *
+ ****************************************************************************/
+
+pid_t task_vforkstart(FAR _TCB *child)
+{
+#if CONFIG_TASK_NAME_SIZE > 0
+ _TCB *parent = (FAR _TCB *)g_readytorun.head;
+#endif
+ FAR const char *name;
+ pid_t pid;
+#ifdef CONFIG_SCHED_WAITPID
+ int rc;
+#endif
+ int ret;
+
+ svdbg("Starting Child TCB=%p, parent=%p\n", child, g_readytorun.head);
+ DEBUGASSERT(child);
+
+ /* Setup to pass parameters to the new task */
+
+#if CONFIG_TASK_NAME_SIZE > 0
+ name = parent->name;
+#else
+ name = NULL;
+#endif
+
+ (void)task_argsetup(child, name, (const char **)NULL);
+
+ /* Get the assigned pid before we start the task */
+
+ pid = (int)child->pid;
+
+ /* Activate the task */
+
+ ret = task_activate(child);
+ if (ret != OK)
+ {
+ task_vforkabort(child, -ret);
+ return ERROR;
+ }
+
+ /* Since the child task has the same priority as the parent task, it is
+ * now ready to run, but has not yet ran. It is a requirement that
+ * the parent enivornment be stable while vfork runs; the child thread
+ * is still dependent on things in the parent thread... like the pointers
+ * into parent thread's stack which will still appear in the child's
+ * registers and environment.
+ *
+ * We do not have SIG_CHILD, so we have to do some silly things here.
+ * The simplest way to make sure that the child thread runs to completion
+ * is simply to yield here. Since the child can only do exit() or
+ * execv/l(), that should be all that is needed.
+ *
+ * Hmmm.. this is probably not sufficient. What if we are running
+ * SCHED_RR? What if the child thread is suspeneded and rescheduled
+ * after the parent thread again?
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+
+ /* We can also exploit a bug in the execv() implementation: The PID
+ * of the task exec'ed by the child will not be the same as the PID of
+ * the child task. Therefore, waitpid() on the child task's PID will
+ * accomplish what we need to do.
+ */
+
+ rc = 0;
+
+#ifdef CONFIG_DEBUG
+ ret = waitpid(pid, &rc, 0);
+ if (ret < 0)
+ {
+ sdbg("ERROR: waitpid failed: %d\n", errno);
+ }
+#else
+ (void)waitpid(pid, &rc, 0);
+#endif
+
+#else
+ /* The following logic does not appear to work... It gets stuff in an
+ * infinite kill() loop and hogs the processor. Therefore, it looks
+ * as though CONFIG_SCHED_WAITPID may be a requirement to used vfork().
+ *
+ * Again exploiting that execv() bug: Check if the child thread is
+ * still running.
+ */
+
+ while (kill(pid, 0) == OK)
+ {
+ /* Yes.. then we can yield to it -- assuming that it has not lowered
+ * its priority. sleep(0) might be a safer thing to do since it does
+ * not depend on prioirities: It will halt the parent thread for one
+ * system clock tick. This will delay the return to the parent thread.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ sleep(0);
+#else
+ sched_yield();
+#endif
+ }
+#endif
+
+ return pid;
+}
+
+/****************************************************************************
+ * Name: task_vforkabort
+ *
+ * Description:
+ * Recover from any errors after task_vforksetup() was called.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void task_vforkabort(FAR _TCB *child, int errcode)
+{
+ /* The TCB was added to the active task list by task_schedsetup() */
+
+ dq_rem((FAR dq_entry_t*)child, (dq_queue_t*)&g_inactivetasks);
+
+ /* Release the TCB */
+
+ sched_releasetcb(child);
+ set_errno(errcode);
+}
diff --git a/nuttx/sched/timer_settime.c b/nuttx/sched/timer_settime.c
index 1814ba898..f09842ad4 100644
--- a/nuttx/sched/timer_settime.c
+++ b/nuttx/sched/timer_settime.c
@@ -113,6 +113,10 @@ static void inline timer_sigqueue(FAR struct posix_timer_s *timer)
#else
info.si_value.sival_ptr = timer->pt_value.sival_ptr;
#endif
+#ifdef CONFIG_SCHED_HAVE_PARENT
+ info.si_pid = 0; /* Not applicable */
+ info.si_status = OK;
+#endif
/* Send the signal */
diff --git a/nuttx/tools/Makefile.host b/nuttx/tools/Makefile.host
index 4a46901e6..998d38916 100644
--- a/nuttx/tools/Makefile.host
+++ b/nuttx/tools/Makefile.host
@@ -37,31 +37,41 @@ TOPDIR ?= ${shell pwd}/..
-include $(TOPDIR)/Make.defs
include ${TOPDIR}/tools/Config.mk
+# Define HOSTCC on the make command line if it differs from these defaults
+# Define HOSTCFLAGS with -g on the make command line to build debug versions
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+
+# In the Windows native environment, the MinGW GCC compiler is assumed
+
+HOSTCC ?= mingw-gcc.exe
+HOSTCFLAGS ?= -O2 -Wall -Wstrict-prototypes -Wshadow -I. -DCONFIG_WINDOWS_NATIVE=y
+
+else
+
+# GCC is assumed in the POSIX environment.
# strtok_r is used in some tools, but does not seem to be available in
# the MinGW environment.
-ifneq ($(CONFIG_WINDOWS_NATIVE),y)
- HOSTCFLAGS += -D HAVE_STRTOK_C
+HOSTCC ?= gcc
+HOSTCFLAGS ?= -O2 -Wall -Wstrict-prototypes -Wshadow -I. -DHAVE_STRTOK_C
+
endif
+# Targets
+
all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \
- mkconfig$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) mksymtab$(HOSTEXEEXT) \
+ configure$(HOSTEXEEXT) mkconfig$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) mksymtab$(HOSTEXEEXT) \
mksyscall$(HOSTEXEEXT) mkversion$(HOSTEXEEXT)
default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT)
ifdef HOSTEXEEXT
-.PHONY: b16 bdf-converter cmpconfig clean mkconfig mkdeps mksymtab \
- mksyscall mkversion
+.PHONY: b16 bdf-converter cmpconfig clean configure mkconfig mkdeps mksymtab mksyscall mkversion
else
.PHONY: clean
endif
-# Add HOSTCFLAGS=-g on the make command line build debug versions
-
-HOSTCFLAGS ?= -O2 -Wall -I.
-HOSTCC ?= gcc
-
-# b16 - Fixed precision math converstion tool
+# b16 - Fixed precision math conversion tool
b16$(HOSTEXEEXT): b16.c
$(Q) $(HOSTCC) $(HOSTCFLAGS) -o b16$(HOSTEXEEXT) b16.c
@@ -70,10 +80,19 @@ ifdef HOSTEXEEXT
b16: b16$(HOSTEXEEXT)
endif
+# configure - Instantiate a canned NuttX configuration
+
+configure$(HOSTEXEEXT): configure.c cfgparser.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o configure$(HOSTEXEEXT) configure.c cfgparser.c
+
+ifdef HOSTEXEEXT
+configure: configure$(HOSTEXEEXT)
+endif
+
# mkconfig - Convert a .config file into a C config.h file
-mkconfig$(HOSTEXEEXT): mkconfig.c cfgparser.c
- $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkconfig$(HOSTEXEEXT) mkconfig.c cfgparser.c
+mkconfig$(HOSTEXEEXT): mkconfig.c cfgdefine.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkconfig$(HOSTEXEEXT) mkconfig.c cfgdefine.c
ifdef HOSTEXEEXT
mkconfig: mkconfig$(HOSTEXEEXT)
@@ -81,8 +100,8 @@ endif
# cmpconfig - Compare the contents of two configuration files
-cmpconfig$(HOSTEXEEXT): cmpconfig.c
- $(Q) $(HOSTCC) $(HOSTCFLAGS) -o cmpconfig$(HOSTEXEEXT) cmpconfig.c
+cmpconfig$(HOSTEXEEXT): cmpconfig.c cfgparser.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o cmpconfig$(HOSTEXEEXT) cmpconfig.c cfgparser.c
ifdef HOSTEXEEXT
cmpconfig: cmpconfig$(HOSTEXEEXT)
@@ -90,8 +109,8 @@ endif
# mkversion - Convert a .version file into a C version.h file
-mkversion$(HOSTEXEEXT): mkconfig.c cfgparser.c
- $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkversion$(HOSTEXEEXT) mkversion.c cfgparser.c
+mkversion$(HOSTEXEEXT): mkconfig.c cfgdefine.c
+ $(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkversion$(HOSTEXEEXT) mkversion.c cfgdefine.c
ifdef HOSTEXEEXT
mkversion: mkversion$(HOSTEXEEXT)
diff --git a/nuttx/tools/README.txt b/nuttx/tools/README.txt
index 2b9ac61f4..8df4a7783 100644
--- a/nuttx/tools/README.txt
+++ b/nuttx/tools/README.txt
@@ -26,19 +26,42 @@ Config.mk
override these default definitions as necessary.
configure.sh
+configure.bat
+configure.c, cfgparser.c, and cfgparser.h
------------
- This is a bash script that is used to configure NuttX for a given
- target board. See configs/README.txt or Documentation/NuttxPortingGuide.html
+ configure.sh is a bash script that is used to configure NuttX for a given
+ target board in a environment that supports POSIX paths (Linux, Cygwin,
+ OSX, or similar). See configs/README.txt or Documentation/NuttxPortingGuide.html
for a description of how to configure NuttX with this script.
+ configure.c, cfgparser.c, and cfgparser.h can be used to build a work-alike
+ program as a replacement for configure.sh. This work-alike program would be
+ used in environments that do not support Bash scripting (such as the Windows
+ native environment).
+
+ configure.bat is a small Windows batch file that can be used as a replacement
+ for configure.sh in a Windows native environment. configure.bat is actually
+ just a thin layer that execuates configure.exe if it is available. If
+ configure.exe is not available, then configure.bat will attempt to build it
+ first.
+
+ In order two build configure.exe from configure.c in the Windows native
+ environment, two assumptions are made:
+
+ 1) You have installed the MinGW GCC toolchain. This toolchain can be
+ downloaded from http://www.mingw.org/. Tt is recommended the you not
+ install the optional MSYS components as there may be conflicts.
+ 2) That path to bin bin/ directory containing mingw-gcc.exe must be
+ included in the PATH variable.
+
discover.py
-----------
Example script for discovering devices in the local network.
It is the counter part to apps/netutils/discover
-mkconfig.c, cfgparser.c, and cfgparser.h
+mkconfig.c, cfgdefine.c, and cfgdefine.h
----------------------------------------
These are Cs file that are used to build mkconfig program. The mkconfig
@@ -79,7 +102,7 @@ mkfsdata.pl
NOTE: This perl script comes from uIP and was (probably) written
by Adam Dunkels. uIP has a license that is compatible with NuttX.
-mkversion.c, cfgparser.c, and cfgparser.h
+mkversion.c, cfgdefine.c, and cfgdefine.h
-----------------------------------------
This is C file that is used to build mkversion program. The mkversion
@@ -413,6 +436,36 @@ unlink.bat
NTFS mklink.exe command instead of copying files. That logic, however,
has not been verified as of this writing.
+kconfig.bat
+-----------
+
+ Recent versions of NuttX support building NuttX from a native Windows
+ CMD.exe shell. But kconfig-frontends is a Linux tool and is not yet
+ available in the pure CMD.exe environment. At this point, there are
+ only a few options for the Windows user (see the top-level README.txt
+ file).
+
+ You can, with some effort, run the the Cygwin kconfig-mconf tool directly
+ in the CMD.exe shell. In this case, you do not have to modify the
+ .config file, but there are other complexities: You need to
+ temporarily set the Cgywin directories in the PATH variable and
+ then run kconfig-mconf outside of the Make system.
+
+ kconfig.bat is a Windows batch file at tools/kconfig.bat that automates
+ these steps. It is used from the top-level NuttX directory like:
+
+ tools/kconfig menuconfig
+
+ NOTE: There is an currently an issue with accessing DOS environment
+ variables from the Cygwin kconfig-mconf running in the CMD.exe shell.
+ The following change to the top-level Kconfig file seems to work around
+ these problems:
+
+ config APPSDIR
+ string
+ - option env="APPSDIR"
+ + default "../apps"
+
mkimage.sh
----------
diff --git a/nuttx/tools/bdf-converter.c b/nuttx/tools/bdf-converter.c
index b32209fcf..a03faa93e 100644
--- a/nuttx/tools/bdf-converter.c
+++ b/nuttx/tools/bdf-converter.c
@@ -43,6 +43,7 @@
* Included Files
****************************************************************************/
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
diff --git a/nuttx/tools/cfgdefine.c b/nuttx/tools/cfgdefine.c
new file mode 100644
index 000000000..f026a186f
--- /dev/null
+++ b/nuttx/tools/cfgdefine.c
@@ -0,0 +1,323 @@
+/****************************************************************************
+ * tools/cfgdefine.c
+ *
+ * Copyright (C) 2007-2012 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 <string.h>
+#include <ctype.h>
+#include "cfgdefine.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+char line[LINESIZE+1];
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* These are configuration variable name that are quoted by configuration tool
+ * but which must be unquoted when used in C code.
+ */
+
+static const char *dequote_list[] =
+{
+ /* NuttX */
+
+ "CONFIG_USER_ENTRYPOINT", /* Name of entry point function */
+ "CONFIG_EXECFUNCS_SYMTAB", /* Symbol table used by exec[l|v] */
+
+ /* NxWidgets/NxWM */
+
+ "CONFIG_NXWM_BACKGROUND_IMAGE", /* Name of bitmap image class */
+ "CONFIG_NXWM_STARTWINDOW_ICON", /* Name of bitmap image class */
+ "CONFIG_NXWM_NXCONSOLE_ICON", /* Name of bitmap image class */
+ "CONFIG_NXWM_CALIBRATION_ICON", /* Name of bitmap image class */
+ "CONFIG_NXWM_HEXCALCULATOR_ICON", /* Name of bitmap image class */
+
+ NULL /* Marks the end of the list */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+ /* Skip over any spaces */
+
+static char *skip_space(char *ptr)
+{
+ while (*ptr && isspace((int)*ptr)) ptr++;
+ return ptr;
+}
+
+/* Find the end of a variable string */
+
+static char *find_name_end(char *ptr)
+{
+ while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
+ return ptr;
+}
+
+/* Find the end of a value string */
+
+static char *find_value_end(char *ptr)
+{
+ while (*ptr && !isspace((int)*ptr))
+ {
+ if (*ptr == '"')
+ {
+ do ptr++; while (*ptr && *ptr != '"');
+ if (*ptr) ptr++;
+ }
+ else
+ {
+ do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
+ }
+ }
+ return ptr;
+}
+
+/* Read the next line from the configuration file */
+
+static char *read_line(FILE *stream)
+{
+ char *ptr;
+
+ for (;;)
+ {
+ line[LINESIZE] = '\0';
+ if (!fgets(line, LINESIZE, stream))
+ {
+ return NULL;
+ }
+ else
+ {
+ ptr = skip_space(line);
+ if (*ptr && *ptr != '#' && *ptr != '\n')
+ {
+ return ptr;
+ }
+ }
+ }
+}
+
+/* Parse the line from the configuration file into a variable name
+ * string and a value string.
+ */
+
+static void parse_line(char *ptr, char **varname, char **varval)
+{
+ /* Skip over any leading spaces */
+
+ ptr = skip_space(ptr);
+
+ /* The first no-space is the beginning of the variable name */
+
+ *varname = skip_space(ptr);
+ *varval = NULL;
+
+ /* Parse to the end of the variable name */
+
+ ptr = find_name_end(ptr);
+
+ /* An equal sign is expected next, perhaps after some white space */
+
+ if (*ptr && *ptr != '=')
+ {
+ /* Some else follows the variable name. Terminate the variable
+ * name and skip over any spaces.
+ */
+
+ *ptr = '\0';
+ ptr = skip_space(ptr + 1);
+ }
+
+ /* Verify that the equal sign is present */
+
+ if (*ptr == '=')
+ {
+ /* Make sure that the variable name is terminated (this was already
+ * done if the name was followed by white space.
+ */
+
+ *ptr = '\0';
+
+ /* The variable value should follow =, perhaps separated by some
+ * white space.
+ */
+
+ ptr = skip_space(ptr + 1);
+ if (*ptr)
+ {
+ /* Yes.. a variable follows. Save the pointer to the start
+ * of the variable string.
+ */
+
+ *varval = ptr;
+
+ /* Find the end of the variable string and make sure that it
+ * is terminated.
+ */
+
+ ptr = find_value_end(ptr);
+ *ptr = '\0';
+ }
+ }
+}
+
+static char *dequote_value(const char *varname, char *varval)
+{
+ const char **dqnam;
+ char *dqval = varval;
+ int len;
+
+ if (dqval)
+ {
+ /* Check if the variable name is in the list of strings to be dequoated */
+
+ for (dqnam = dequote_list; *dqnam; dqnam++)
+ {
+ if (strcmp(*dqnam, varname) == 0)
+ {
+ break;
+ }
+ }
+
+ /* Did we find the variable name in the list of configuration variables
+ * to be dequoated?
+ */
+
+ if (*dqnam)
+ {
+ /* Yes... Check if there is a traiing quote */
+
+ len = strlen(dqval);
+ if (dqval[len-1] == '"')
+ {
+ /* Yes... replace it with a terminator */
+
+ dqval[len-1] = '\0';
+ len--;
+ }
+
+ /* Is there a leading quote? */
+
+ if (dqval[0] == '"')
+ {
+ /* Yes.. skip over the leading quote */
+
+ dqval++;
+ len--;
+ }
+
+ /* Handle the case where nothing is left after dequoting */
+
+ if (len <= 0)
+ {
+ dqval = NULL;
+ }
+ }
+ }
+
+ return dqval;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void generate_definitions(FILE *stream)
+{
+ char *varname;
+ char *varval;
+ char *ptr;
+
+ /* Loop until the entire file has been parsed. */
+
+ do
+ {
+ /* Read the next line from the file */
+
+ ptr = read_line(stream);
+ if (ptr)
+ {
+ /* Parse the line into a variable and a value field */
+
+ parse_line(ptr, &varname, &varval);
+
+ /* Was a variable name found? */
+
+ if (varname)
+ {
+ /* Yes.. dequote the value if necessary */
+
+ varval = dequote_value(varname, varval);
+
+ /* If no value was provided or if the special value 'n' was provided,
+ * then undefine the configuration variable.
+ */
+
+ if (!varval || strcmp(varval, "n") == 0)
+ {
+ printf("#undef %s\n", varname);
+ }
+
+ /* Simply define the configuration variable if it has the special
+ * value "y"
+ */
+
+ else if (strcmp(varval, "y") == 0)
+ {
+ printf("#define %s 1\n", varname);
+ }
+
+ /* Otherwise, use the value as provided */
+
+ else
+ {
+ printf("#define %s %s\n", varname, varval);
+ }
+ }
+ }
+ }
+ while (ptr);
+}
diff --git a/apps/namedapp/namedapp.h b/nuttx/tools/cfgdefine.h
index 7fcdf42dc..f76ba73fb 100644
--- a/apps/namedapp/namedapp.h
+++ b/nuttx/tools/cfgdefine.h
@@ -1,10 +1,8 @@
/****************************************************************************
- * apps/namedaps/namedapp.h
+ * tools/cfgdefine.h
*
- * Copyright (C) 2011 Uros Platise. All rights reserved.
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
- * Authors: Uros Platise <uros.platise@isotel.eu>
- * Gregory Nutt <gnutt@nuttx.org>
+ * Copyright (C) 2007-2011 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
@@ -35,44 +33,32 @@
*
****************************************************************************/
-#ifndef __APPS_NAMEDAPP_NAMEDAPP_H
-#define __APPS_NAMEDAPP_NAMEDAPP_H
+#ifndef __TOOLS_CFGDEFINE_H
+#define __TOOLS_CFGDEFINE_H
/****************************************************************************
* Included Files
****************************************************************************/
-#include <nuttx/config.h>
-#include <apps/apps.h>
+#include <stdio.h>
+#include <limits.h>
/****************************************************************************
- * Public Types
+ * Definitions
****************************************************************************/
+#define LINESIZE ( PATH_MAX > 256 ? PATH_MAX : 256 )
+
/****************************************************************************
* Public Data
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
-#endif
-
-EXTERN const struct namedapp_s namedapps[];
+extern char line[LINESIZE+1];
/****************************************************************************
* Public Functions
****************************************************************************/
-EXTERN int number_namedapps(void);
-
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
-
-#endif /* __APPS_NAMEDAPP_NAMEDAPP_H */
+void generate_definitions(FILE *stream);
+#endif /* __TOOLS_CFGDEFINE_H */
diff --git a/nuttx/tools/cfgparser.c b/nuttx/tools/cfgparser.c
index 1a35f7857..ac25bd26b 100644
--- a/nuttx/tools/cfgparser.c
+++ b/nuttx/tools/cfgparser.c
@@ -38,7 +38,9 @@
****************************************************************************/
#include <string.h>
+#include <stdlib.h>
#include <ctype.h>
+
#include "cfgparser.h"
/****************************************************************************
@@ -55,28 +57,7 @@ char line[LINESIZE+1];
* Private Data
****************************************************************************/
-/* These are configuration variable name that are quoted by configuration tool
- * but which must be unquoted when used in C code.
- */
-
-static const char *dequote_list[] =
-{
- /* NuttX */
-
- "CONFIG_USER_ENTRYPOINT", /* Name of entry point function */
-
- /* NxWidgets/NxWM */
-
- "CONFIG_NXWM_BACKGROUND_IMAGE", /* Name of bitmap image class */
- "CONFIG_NXWM_STARTWINDOW_ICON", /* Name of bitmap image class */
- "CONFIG_NXWM_NXCONSOLE_ICON", /* Name of bitmap image class */
- "CONFIG_NXWM_CALIBRATION_ICON", /* Name of bitmap image class */
- "CONFIG_NXWM_HEXCALCULATOR_ICON", /* Name of bitmap image class */
-
- NULL /* Marks the end of the list */
-};
-
- /****************************************************************************
+/****************************************************************************
* Private Functions
****************************************************************************/
@@ -203,69 +184,15 @@ static void parse_line(char *ptr, char **varname, char **varval)
}
}
-static char *dequote_value(const char *varname, char *varval)
-{
- const char **dqnam;
- char *dqval = varval;
- int len;
-
- if (dqval)
- {
- /* Check if the variable name is in the list of strings to be dequoated */
-
- for (dqnam = dequote_list; *dqnam; dqnam++)
- {
- if (strcmp(*dqnam, varname) == 0)
- {
- break;
- }
- }
-
- /* Did we find the variable name in the list of configuration variables
- * to be dequoated?
- */
-
- if (*dqnam)
- {
- /* Yes... Check if there is a traiing quote */
-
- len = strlen(dqval);
- if (dqval[len-1] == '"')
- {
- /* Yes... replace it with a terminator */
-
- dqval[len-1] = '\0';
- len--;
- }
-
- /* Is there a leading quote? */
-
- if (dqval[0] == '"')
- {
- /* Yes.. skip over the leading quote */
-
- dqval++;
- len--;
- }
-
- /* Handle the case where nothing is left after dequoting */
-
- if (len <= 0)
- {
- dqval = NULL;
- }
- }
- }
-
- return dqval;
-}
-
/****************************************************************************
* Public Functions
****************************************************************************/
-void parse_file(FILE *stream)
+void parse_file(FILE *stream, struct variable_s **list)
{
+ struct variable_s *curr;
+ struct variable_s *prev;
+ struct variable_s *next;
char *varname;
char *varval;
char *ptr;
@@ -283,40 +210,87 @@ void parse_file(FILE *stream)
parse_line(ptr, &varname, &varval);
- /* Was a variable name found? */
+ /* If the variable has not value (or the special value 'n'), then
+ * ignore it.
+ */
- if (varname)
+ if (!varval || strcmp(varval, "n") == 0)
{
- /* Yes.. dequote the value if necessary */
+ continue;
+ }
- varval = dequote_value(varname, varval);
+ /* Make sure that a variable name was found. */
- /* If no value was provided or if the special value 'n' was provided,
- * then undefine the configuration variable.
+ if (varname)
+ {
+ int varlen = strlen(varname) + 1;
+ int vallen = 0;
+
+ /* Get the size of the value, including the NUL terminating
+ * character.
*/
- if (!varval || strcmp(varval, "n") == 0)
+ if (varval)
{
- printf("#undef %s\n", varname);
+ vallen = strlen(varval) + 1;
}
- /* Simply define the configuration variable if it has the special
- * value "y"
+ /* Allocate memory to hold the struct variable_s with the
+ * variable name and the value.
*/
- else if (strcmp(varval, "y") == 0)
+ curr = (struct variable_s *)malloc(sizeof(struct variable_s) + varlen + vallen - 1);
+ if (curr)
{
- printf("#define %s 1\n", varname);
+ /* Add the variable to the list */
+
+ curr->var = &curr->storage[0];
+ strcpy(curr->var, varname);
+
+ curr->val = NULL;
+ if (varval)
+ {
+ curr->val = &curr->storage[varlen];
+ strcpy(curr->val, varval);
+ }
}
- /* Otherwise, use the value as provided */
+ prev = 0;
+ next = *list;
+ while (next && strcmp(next->var, curr->var) <= 0)
+ {
+ prev = next;
+ next = next->flink;
+ }
+ if (prev)
+ {
+ prev->flink = curr;
+ }
else
{
- printf("#define %s %s\n", varname, varval);
+ *list = curr;
}
+
+ curr->flink = next;
}
}
}
while (ptr);
}
+
+struct variable_s *find_variable(const char *varname, struct variable_s *list)
+{
+ while (list)
+ {
+ if (strcmp(varname, list->var) == 0)
+ {
+ return list;
+ }
+
+ list = list->flink;
+ }
+
+ return NULL;
+}
+
diff --git a/nuttx/tools/cfgparser.h b/nuttx/tools/cfgparser.h
index b1c4bae76..b1f421a68 100644
--- a/nuttx/tools/cfgparser.h
+++ b/nuttx/tools/cfgparser.h
@@ -50,6 +50,18 @@
#define LINESIZE ( PATH_MAX > 256 ? PATH_MAX : 256 )
/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct variable_s
+{
+ struct variable_s *flink;
+ char *var;
+ char *val;
+ char storage[1];
+};
+
+/****************************************************************************
* Public Data
****************************************************************************/
@@ -59,6 +71,7 @@ extern char line[LINESIZE+1];
* Public Functions
****************************************************************************/
-extern void parse_file(FILE *stream);
+void parse_file(FILE *stream, struct variable_s **list);
+struct variable_s *find_variable(const char *varname, struct variable_s *list);
#endif /* __TOOLS_CFGPARSER_H */
diff --git a/nuttx/tools/cmpconfig.c b/nuttx/tools/cmpconfig.c
index 2958acdc7..a5a539401 100644
--- a/nuttx/tools/cmpconfig.c
+++ b/nuttx/tools/cmpconfig.c
@@ -43,6 +43,8 @@
#include <ctype.h>
#include <errno.h>
+#include "cfgparser.h"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -51,14 +53,6 @@
* Private Types
****************************************************************************/
-struct variable_s
-{
- struct variable_s *flink;
- char *var;
- char *val;
- char storage[1];
-};
-
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -69,154 +63,11 @@ static void show_usage(const char *progname)
exit(EXIT_FAILURE);
}
-static char *skip_space(char *ptr)
-{
- while (*ptr && isspace((int)*ptr)) ptr++;
- return ptr;
-}
-
-static char *read_line(FILE *stream, char *line, int len)
-{
- char *ptr;
-
- for (;;)
- {
- line[len-1] = '\0';
- if (!fgets(line, len, stream))
- {
- return NULL;
- }
- else
- {
- ptr = skip_space(line);
- if (*ptr && *ptr != '#' && *ptr != '\n')
- {
- return ptr;
- }
- }
- }
-}
-
-static char *find_name_end(char *ptr)
-{
- while (*ptr && (isalnum((int)*ptr) || *ptr == '_')) ptr++;
- return ptr;
-}
-
-static char *find_value_end(char *ptr)
-{
- while (*ptr && !isspace((int)*ptr))
- {
- if (*ptr == '"')
- {
- do ptr++; while (*ptr && *ptr != '"');
- if (*ptr) ptr++;
- }
- else
- {
- do ptr++; while (*ptr && !isspace((int)*ptr) && *ptr != '"');
- }
- }
- return ptr;
-}
-
-static void parse_line(char *ptr, char **varname, char **varval)
-{
- *varname = ptr;
- *varval = NULL;
-
- ptr = find_name_end(ptr);
- if (*ptr && *ptr != '=')
- {
- *ptr = '\0';
- ptr = skip_space(ptr + 1);
- }
-
- if (*ptr == '=')
- {
- *ptr = '\0';
- ptr = skip_space(ptr + 1);
- if (*ptr)
- {
- *varval = ptr;
- ptr = find_value_end(ptr);
- *ptr = '\0';
- }
- }
-}
-
-static void parse_file(FILE *stream, struct variable_s **list)
-{
- char line[10242];
- struct variable_s *curr;
- struct variable_s *prev;
- struct variable_s *next;
- char *varname;
- char *varval;
- char *ptr;
-
- do
- {
- ptr = read_line(stream, line, 1024);
- if (ptr)
- {
- parse_line(ptr, &varname, &varval);
- if (!varval || strcmp(varval, "n") == 0)
- {
- continue;
- }
-
- if (varname)
- {
- int varlen = strlen(varname) + 1;
- int vallen = 0;
-
- if (varval)
- {
- vallen = strlen(varval) + 1;
- }
-
- curr = (struct variable_s *)malloc(sizeof(struct variable_s) + varlen + vallen - 1);
- if (curr)
- {
- curr->var = &curr->storage[0];
- strcpy(curr->var, varname);
-
- curr->val = NULL;
- if (varval)
- {
- curr->val = &curr->storage[varlen];
- strcpy(curr->val, varval);
- }
- }
-
- prev = 0;
- next = *list;
- while (next && strcmp(next->var, curr->var) <= 0)
- {
- prev = next;
- next = next->flink;
- }
-
- if (prev)
- {
- prev->flink = curr;
- }
- else
- {
- *list = curr;
- }
- curr->flink = next;
- }
- }
- }
- while (ptr);
-}
-
static void compare_variables(struct variable_s *list1, struct variable_s *list2)
{
char *varval1;
char *varval2;
+ int result;
while (list1 || list2)
{
@@ -252,7 +103,7 @@ static void compare_variables(struct variable_s *list1, struct variable_s *list2
}
else
{
- int result = strcmp(list1->var, list2->var);
+ result = strcmp(list1->var, list2->var);
if (result < 0)
{
printf("file1: %s=%s\n", list1->var, varval1);
@@ -265,9 +116,9 @@ static void compare_variables(struct variable_s *list1, struct variable_s *list2
printf("file2: %s=%s\n\n", list2->var, varval2);
list2 = list2->flink;
}
- else
+ else /* if (result == 0) */
{
- int result = strcmp(varval1, varval2);
+ result = strcmp(varval1, varval2);
if (result != 0)
{
printf("file1: %s=%s\n", list1->var, varval1);
diff --git a/nuttx/tools/configure.bat b/nuttx/tools/configure.bat
new file mode 100644
index 000000000..7dc9ca116
--- /dev/null
+++ b/nuttx/tools/configure.bat
@@ -0,0 +1,127 @@
+@echo off
+
+rem tools/configure.bat
+rem
+rem Copyright (C) 2012 Gregory Nutt. All rights reserved.
+rem Author: Gregory Nutt <gnutt@nuttx.org>
+rem
+rem Redistribution and use in source and binary forms, with or without
+rem modification, are permitted provided that the following conditions
+rem are met:
+rem
+rem 1. Redistributions of source code must retain the above copyright
+rem notice, this list of conditions and the following disclaimer.
+rem 2. Redistributions in binary form must reproduce the above copyright
+rem notice, this list of conditions and the following disclaimer in
+rem the documentation and/or other materials provided with the
+rem distribution.
+rem 3. Neither the name NuttX nor the names of its contributors may be
+rem used to endorse or promote products derived from this software
+rem without specific prior written permission.
+rem
+rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+rem FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+rem COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+rem INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+rem BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+rem OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+rem AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+rem LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+rem ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+rem POSSIBILITY OF SUCH DAMAGE.
+rem
+
+rem Parse command line arguments
+
+set debug=
+set fmt=-w
+set posix=
+set help=
+set appdir=
+set config=
+
+:ArgLoop
+if "%1"=="" goto :NoConfig
+if "%1"=="-h" goto :ShowUsage
+if "%1"=="-d" goto :SetDebug
+if "%1"=="-w" goto :SetWindows
+if "%1"=="-l" goto :SetPosix
+if "%1"=="-a" goto :SetAppDir
+
+set config=%1
+goto EndOfLoop
+
+:SetDebug
+set debug=-d
+goto :NextArg
+
+:SetWindows
+set fmt=-w
+goto :NextArg
+
+:SetWindows
+set fmt=-l
+goto :NextArg
+
+:SetAppDir
+shift
+set appdir=-a %1
+
+:NextArg
+shift
+goto :ArgLoop
+
+:EndOfLoop
+
+rem Check if we have to build configure.exe
+
+if exist configure.exe goto :HaveConfigureExe
+
+set cc=mingw32-gcc.exe
+set cflags=-Wall -Wstrict-prototypes -Wshadow -g -pipe -I. -DCONFIG_WINDOWS_NATIVE=y
+%cc% %cflags% -o configure.exe configure.c cfgparser.c
+if errorlevel 1 (
+ echo ERROR: %cc% failed
+ echo Is ming32-gcc.exe installed? Is it in the PATH variable?
+ goto End
+)
+
+:HaveConfigureExe
+configure.exe %debug% %fmt% %appdir% %config%
+if errorlevel 1 echo configure.exe failed
+goto End
+
+:NoConfig
+echo Missing ^<board-name^>/^<config-name^> argument
+
+:ShowUsage
+echo USAGE: %0 [-d] [-w] [-l] [-h] [-a ^<app-dir^>] ^<board-name^>\^<config-name^>
+echo\nWhere:
+echo ^<board-name^>:
+echo Identifies the board. This must correspond to a board directory
+echo under nuttx/configs/.
+echo ^<config-name^>:
+echo Identifies the specific configuratin for the selected ^<board-name^>.
+echo This must correspond to a sub-directory under the board directory at
+echo under nuttx/configs/^<board-name^>/.
+echo ^<-d^>:
+echo Enables debug output
+echo ^<-w^>:
+echo Informs the tool that it should use Windows style paths like C:\\Program Files
+echo instead of POSIX style paths are used like /usr/local/bin. Windows
+echo style paths are used by default.
+echo ^<-l^>:
+echo Informs the tool that it should use POSIX style paths like /usr/local/bin.
+echo By default, Windows style paths like C:\\Program Files are used.
+echo -a ^<app-dir^>:
+echo Informs the configuration tool where the application build
+echo directory. This is a relative path from the top-level NuttX
+echo build directory. But default, this tool will look in the usual
+echo places to try to locate the application directory: ../apps or
+echo ../apps-xx.yy where xx.yy is the NuttX version number.
+echo ^<-h^>:
+echo Prints this message and exits.
+
+:End
diff --git a/nuttx/tools/configure.c b/nuttx/tools/configure.c
new file mode 100644
index 000000000..9e82c3657
--- /dev/null
+++ b/nuttx/tools/configure.c
@@ -0,0 +1,890 @@
+/****************************************************************************
+ * tools/configure.c
+ *
+ * Copyright (C) 2012 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 <sys/stat.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include "cfgparser.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define BUFFER_SIZE 1024
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_WINDOWS_NATIVE
+static char g_delim = '\\'; /* Delimiter to use when forming paths */
+static bool g_winpaths = true; /* True: Windows style paths */
+#else
+static char g_delim = '/'; /* Delimiter to use when forming paths */
+static bool g_winpaths = false; /* False: POSIX style paths */
+#endif
+static bool g_debug = false; /* Enable debug output */
+
+static const char *g_appdir = NULL; /* Relative path to the applicatin directory */
+static const char *g_boarddir = NULL; /* Name of board subdirectory */
+static char *g_configdir = NULL; /* Name of configuration subdirectory */
+
+static char *g_topdir = NULL; /* Full path to top-level NuttX build directory */
+static char *g_apppath = NULL; /* Full path to the applicatino directory */
+static char *g_configtop = NULL; /* Full path to the top-level configuration directory */
+static char *g_configpath = NULL; /* Full path to the configuration sub-directory */
+static char *g_verstring = "0.0"; /* Version String */
+
+static char *g_srcdefconfig = NULL; /* Source defconfig file */
+static char *g_srcmakedefs = NULL; /* Source Make.defs file */
+static char *g_srcappconfig = NULL ; /* Source appconfig file (optional) */
+static char *g_srcsetenvsh = NULL; /* Source setenv.sh file (optional) */
+static char *g_srcsetenvbat = NULL; /* Source setenv.bat file (optional) */
+
+static bool g_newconfig = false; /* True: New style configuration */
+static bool g_winnative = false; /* True: Windows native configuration */
+static bool g_needapppath = true; /* Need to add app path to the .config file */
+
+static char g_buffer[BUFFER_SIZE]; /* Scratch buffer for forming full paths */
+
+static struct variable_s *g_configvars = NULL;
+static struct variable_s *g_versionvars = NULL;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void show_usage(const char *progname, int exitcode)
+{
+ fprintf(stderr, "\nUSAGE: %s [-d] [-w] [-l] [-h] [-a <app-dir>] <board-name>[%c<config-name>]\n", progname, g_delim);
+ fprintf(stderr, "\nWhere:\n");
+ fprintf(stderr, " <board-name>:\n");
+ fprintf(stderr, " Identifies the board. This must correspond to a board directory\n");
+ fprintf(stderr, " under nuttx%cconfigs%c.\n", g_delim, g_delim);
+ fprintf(stderr, " <config-name>:\n");
+ fprintf(stderr, " Identifies the specific configuration for the selected <board-name>.\n");
+ fprintf(stderr, " This must correspond to a sub-directory under the board directory at\n");
+ fprintf(stderr, " under nuttx%cconfigs%c<board-name>%c.\n", g_delim, g_delim, g_delim);
+ fprintf(stderr, " <-d>:\n");
+ fprintf(stderr, " Enables debug output\n");
+ fprintf(stderr, " <-w>:\n");
+#ifdef CONFIG_WINDOWS_NATIVE
+ fprintf(stderr, " Informs the tool that it should use Windows style paths like C:\\Program Files\n");
+ fprintf(stderr, " instead of POSIX style paths are used like /usr/local/bin. Windows\n");
+ fprintf(stderr, " style paths are used by default.\n");
+#else
+ fprintf(stderr, " Informs the tool that it should use Windows style paths like C:\\Program Files.\n");
+ fprintf(stderr, " By default, POSIX style paths like /usr/local/bin are used.\n");
+#endif
+ fprintf(stderr, " <-l>:\n");
+#ifdef CONFIG_WINDOWS_NATIVE
+ fprintf(stderr, " Informs the tool that it should use POSIX style paths like /usr/local/bin.\n");
+ fprintf(stderr, " By default, Windows style paths like C:\\Program Files are used.\n");
+#else
+ fprintf(stderr, " Informs the tool that it should use POSIX style paths like /usr/local/bin\n");
+ fprintf(stderr, " instead of Windows style paths like C:\\Program Files are used. POSIX\n");
+ fprintf(stderr, " style paths are used by default.\n");
+#endif
+ fprintf(stderr, " -a <app-dir>:\n");
+ fprintf(stderr, " Informs the configuration tool where the application build\n");
+ fprintf(stderr, " directory. This is a relative path from the top-level NuttX\n");
+ fprintf(stderr, " build directory. But default, this tool will look in the usual\n");
+ fprintf(stderr, " places to try to locate the application directory: ..%capps or\n", g_delim);
+ fprintf(stderr, " ..%capps-xx.yy where xx.yy is the NuttX version number.\n", g_delim);
+ fprintf(stderr, " <-h>:\n");
+ fprintf(stderr, " Prints this message and exits.\n");
+ exit(exitcode);
+}
+
+static void debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (g_debug)
+ {
+ va_start(ap, fmt);
+ (void)vprintf(fmt, ap);
+ va_end(ap);
+ }
+}
+
+static void parse_args(int argc, char **argv)
+{
+ char *ptr;
+ int ch;
+
+ /* Parse command line options */
+
+ g_debug = false;
+
+ while ((ch = getopt(argc, argv, ":a:dwlh")) > 0)
+ {
+ switch (ch)
+ {
+ case 'a' :
+ g_appdir = optarg;
+ break;
+
+ case 'd' :
+ g_debug = true;
+ break;
+
+ case 'w' :
+ g_delim = '/';
+ g_winpaths = true;
+ break;
+
+ case 'l' :
+ g_delim = '\\';
+ g_winpaths = false;
+ break;
+
+ case 'h' :
+ show_usage(argv[0], EXIT_SUCCESS);
+
+ case '?' :
+ fprintf(stderr, "ERROR: Unrecognized option: %c\n", optopt);
+ show_usage(argv[0], EXIT_FAILURE);
+
+ case ':' :
+ fprintf(stderr, "ERROR: Missing option argument, option: %c\n", optopt);
+ show_usage(argv[0], EXIT_FAILURE);
+
+ break;
+ fprintf(stderr, "ERROR: Unexpected option: %c\n", ch);
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+ }
+
+ /* There should be exactly one argument following the options */
+
+ if (optind >= argc)
+ {
+ fprintf(stderr, "ERROR: Missing <board-name>%c<config-name>\n", g_delim);
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+
+ /* The required option should be the board directory name and the
+ * configuration directory name separated by '/' or '\'. Either is
+ * acceptable in this context.
+ */
+
+ g_boarddir = argv[optind];
+ optind++;
+
+ ptr = strchr(g_boarddir, '/');
+ if (!ptr)
+ {
+ ptr = strchr(g_boarddir, '\\');
+ }
+
+ if (!ptr)
+ {
+ fprintf(stderr, "ERROR: Invalid <board-name>%c<config-name>\n", g_delim);
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+
+ *ptr++ = '\0';
+ g_configdir = ptr;
+
+ if (optind < argc)
+ {
+ fprintf(stderr, "Unexpected garbage at the end of the line\n");
+ show_usage(argv[0], EXIT_FAILURE);
+ }
+}
+
+static void verify_directory(const char *directory)
+{
+ struct stat buf;
+
+ if (stat(directory, &buf) < 0)
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n", directory, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (!S_ISDIR(buf.st_mode))
+ {
+ fprintf(stderr, "ERROR: %s exists but is not a directory\n", directory);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static bool verify_optiondir(const char *directory)
+{
+ struct stat buf;
+
+ if (stat(directory, &buf) < 0)
+ {
+ /* It may be okay if the dirctory does not exist */
+
+ /* It may be okay if the file does not exist */
+
+ int errcode = errno;
+ if (errcode == ENOENT)
+ {
+ debug("verify_optiondir: stat of %s failed: %s\n", directory, strerror(errno));
+ return false;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n", directory, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!S_ISDIR(buf.st_mode))
+ {
+ fprintf(stderr, "ERROR: %s exists but is not a directory\n", directory);
+ exit(EXIT_FAILURE);
+ }
+
+ return true;
+}
+
+static bool verify_file(const char *path)
+{
+ struct stat buf;
+
+ if (stat(path, &buf) < 0)
+ {
+ /* It may be okay if the file does not exist */
+
+ int errcode = errno;
+ if (errcode == ENOENT)
+ {
+ debug("verify_file: stat of %s failed: %s\n", path, strerror(errno));
+ return false;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n", path, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!S_ISREG(buf.st_mode))
+ {
+ fprintf(stderr, "ERROR: %s exists but is not a regular file\n", path);
+ exit(EXIT_FAILURE);
+ }
+
+ return true;
+}
+
+static void get_topdir(void)
+{
+ /* Get and verify the top-level NuttX directory */
+
+ if (getcwd(g_buffer, BUFFER_SIZE) == NULL)
+ {
+ fprintf(stderr, "ERROR: getcwd failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ g_topdir = strdup(dirname(g_buffer));
+ debug("get_topdir: Checking topdir=%s\n", g_topdir);
+ verify_directory(g_topdir);
+}
+
+static void config_search(const char *boarddir)
+{
+ DIR *dir;
+ struct dirent *dp;
+ struct stat buf;
+ char *parent;
+ char *child;
+
+ /* Skip over any leading '/' or '\\'. This happens on the first second
+ * call because the starting boarddir is ""
+ */
+
+ if (boarddir[0] == g_delim)
+ {
+ boarddir++;
+ }
+
+ /* Get the full directory path and open it */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_configtop, g_delim, boarddir);
+ dir = opendir(g_buffer);
+ if (!dir)
+ {
+ fprintf(stderr, "ERROR: Could not open %s: %s\n",
+ g_buffer, strerror(errno));
+ return;
+ }
+
+ /* Make a copy of the path to the directory */
+
+ parent = strdup(g_buffer);
+
+ /* Vist each entry in the directory */
+
+ while ((dp = readdir (dir)) != NULL)
+ {
+ /* Ignore directory entries that start with '.' */
+
+ if (dp->d_name[0] == '.')
+ {
+ continue;
+ }
+
+ /* Get a properly terminated copy of d_name (if d_name is long it may
+ * not include a NUL terminator.\ */
+
+ child = strndup(dp->d_name, NAME_MAX);
+
+ /* Get the full path to d_name and stat the file/directory */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", parent, g_delim, child);
+ if (stat(g_buffer, &buf) < 0)
+ {
+ fprintf(stderr, "ERROR: stat of %s failed: %s\n",
+ g_buffer, strerror(errno));
+ free(child);
+ continue;
+ }
+
+ /* If it is a directory, the recurse */
+
+ if (S_ISDIR(buf.st_mode))
+ {
+ char *tmppath;
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", boarddir, g_delim, child);
+ tmppath = strdup(g_buffer);
+ config_search(tmppath);
+ free(tmppath);
+ }
+
+ /* If it is a regular file named 'defconfig' then we have found a
+ * configuration directory. We could terminate the serach in this case
+ * because we do not expect sub-directories within configuration
+ * directories.
+ */
+
+ else if (S_ISREG(buf.st_mode) && strcmp("defconfig", child) == 0)
+ {
+ fprintf(stderr, " %s\n", boarddir);
+ }
+
+ free(child);
+ }
+
+ free(parent);
+ closedir(dir);
+}
+
+static void enumerate_configs(void)
+{
+ fprintf(stderr, "Options for <board-name>[%c<config-name>] include:\n\n", g_delim);
+ config_search("");
+}
+
+static void check_configdir(void)
+{
+ /* Get the path to the top level configuration directory */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cconfigs", g_topdir, g_delim);
+ debug("check_configdir: Checking configtop=%s\n", g_buffer);
+
+ verify_directory(g_buffer);
+ g_configtop = strdup(g_buffer);
+
+ /* Get and verify the path to the selected configuration */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cconfigs%c%s%c%s",
+ g_topdir, g_delim, g_delim, g_boarddir, g_delim, g_configdir);
+ debug("check_configdir: Checking configpath=%s\n", g_buffer);
+
+ if (!verify_optiondir(g_buffer))
+ {
+ fprintf(stderr, "ERROR: No configuration at %s\n", g_buffer);
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_configpath = strdup(g_buffer);
+}
+
+static void read_configfile(void)
+{
+ FILE *stream;
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim);
+ stream = fopen(g_buffer, "r");
+ if (!stream)
+ {
+ fprintf(stderr, "ERROR: failed to open %s for reading: %s\n",
+ g_buffer, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ parse_file(stream, &g_configvars);
+ fclose(stream);
+}
+
+static void read_versionfile(void)
+{
+ FILE *stream;
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c.version", g_topdir, g_delim);
+ stream = fopen(g_buffer, "r");
+ if (!stream)
+ {
+ /* It may not be an error if there is no .version file */
+
+ debug("Failed to open %s for reading: %s\n",
+ g_buffer, strerror(errno));
+ }
+ else
+ {
+ parse_file(stream, &g_versionvars);
+ fclose(stream);
+ }
+}
+
+static void get_verstring(void)
+{
+ struct variable_s *var;
+
+ if (g_versionvars)
+ {
+ var = find_variable("CONFIG_VERSION_STRING", g_versionvars);
+ if (var && var->val)
+ {
+ g_verstring = strdup(var->val);
+ }
+ }
+
+ debug("get_verstring: Version string=%s\n", g_verstring);
+}
+
+static bool verify_appdir(const char *appdir)
+{
+ /* Does this directory exist? */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, appdir);
+ debug("verify_appdir: Checking apppath=%s\n", g_buffer);
+ if (verify_optiondir(g_buffer))
+ {
+ /* Yes.. Use this application directory path */
+
+ g_appdir = strdup(appdir);
+ g_apppath = strdup(g_buffer);
+ return true;
+ }
+
+ debug("verify_appdir: apppath=%s does not exist\n", g_buffer);
+ return false;
+}
+
+static void check_appdir(void)
+{
+ char tmp[16];
+
+ /* Get and verify the full path to the application directory */
+ /* Was the appdir provided on the command line? */
+
+ debug("check_appdir: Command line appdir=%s\n",
+ g_appdir ? g_appdir : "<null>");
+
+ if (!g_appdir)
+ {
+ /* No, was the path provided in the configuration? */
+
+ struct variable_s *var = find_variable("CONFIG_APP_DIR", g_configvars);
+ if (var)
+ {
+ debug("check_appdir: Config file appdir=%s\n",
+ var->val ? var->val : "<null>");
+
+ /* Yes.. does this directory exist? */
+
+ if (var->val && verify_appdir(var->val))
+ {
+ /* We are using the CONFIG_APP_DIR setting already
+ * in the defconfig file.
+ */
+
+ g_needapppath = false;
+ return;
+ }
+ }
+
+ /* Now try some canned locations */
+
+ /* Try ../apps-xx.yy where xx.yy is the version string */
+
+ snprintf(tmp, 16, ".%capps-%s", g_delim, g_verstring);
+ debug("check_appdir: Try appdir=%s\n", tmp);
+ if (verify_appdir(tmp))
+ {
+ return;
+ }
+
+ /* Try ../apps with no version */
+
+ snprintf(tmp, 16, "..%capps", g_delim);
+ debug("check_appdir: Try appdir=%s\n", tmp);
+ if (verify_appdir(tmp))
+ {
+ return;
+ }
+
+ /* Try ../apps-xx.yy where xx.yy are the NuttX version number */
+
+ fprintf(stderr, "ERROR: Could not find the path to the application directory\n");
+ exit(EXIT_FAILURE);
+ }
+ else
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_topdir, g_delim, g_appdir);
+ if (!verify_appdir(g_buffer))
+ {
+ fprintf(stderr, "ERROR: Command line path to application directory does not exist\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+static void check_configuration(void)
+{
+ struct variable_s *var;
+
+ /* Check if this the new style configuration based on kconfig-fontends */
+
+ var = find_variable("CONFIG_NUTTX_NEWCONFIG", g_configvars);
+ if (var && var->val && strcmp("y", var->val) == 0)
+ {
+ debug("check_configuration: New style configuration\n");
+ g_newconfig = true;
+ }
+
+ /* Check if this is a Windows native configuration */
+
+ var = find_variable("CONFIG_WINDOWS_NATIVE", g_configvars);
+ if (var && var->val && strcmp("y", var->val) == 0)
+ {
+ debug("check_configuration: Windows native configuration\n");
+ g_winnative = true;
+ }
+
+ /* All configurations must provide a defconfig and Make.defs file */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cdefconfig", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (!verify_file(g_buffer))
+ {
+ fprintf(stderr, "ERROR: No configuration in %s\n", g_configpath);
+ fprintf(stderr, " No defconfig file found.\n");
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_srcdefconfig = strdup(g_buffer);
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (!verify_file(g_buffer))
+ {
+ fprintf(stderr, "ERROR: Configuration corrupted in %s\n", g_configpath);
+ fprintf(stderr, " No Make.defs file found.\n");
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_srcmakedefs = strdup(g_buffer);
+
+ /* Windows native configurations may provide setenv.bat; POSIX
+ * configurations may provide a setenv.sh.
+ */
+
+ if (g_winnative)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.bat", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (verify_file(g_buffer))
+ {
+ g_srcsetenvbat = strdup(g_buffer);
+ }
+ }
+ else
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.sh", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (verify_file(g_buffer))
+ {
+ g_srcsetenvsh = strdup(g_buffer);
+ }
+ }
+
+ /* Old style configurations MUST provide an appconfig file */
+
+ if (!g_newconfig)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cappconfig", g_configpath, g_delim);
+ debug("check_configuration: Checking %s\n", g_buffer);
+ if (!verify_file(g_buffer))
+ {
+ fprintf(stderr, "ERROR: Configuration corrupted in %s\n", g_configpath);
+ fprintf(stderr, " Required appconfig file not found.\n");
+ enumerate_configs();
+ exit(EXIT_FAILURE);
+ }
+
+ g_srcappconfig = strdup(g_buffer);
+ }
+}
+
+static void copy_file(const char *srcpath, const char *destpath, mode_t mode)
+{
+ int nbytesread;
+ int nbyteswritten;
+ int rdfd;
+ int wrfd;
+
+ /* Open the source file for reading */
+
+ rdfd = open(srcpath, O_RDONLY);
+ if (rdfd < 0)
+ {
+ fprintf(stderr, "ERROR: Failed to open %s for reading: %s\n", srcpath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Now open the destination for writing*/
+
+ wrfd = open(destpath, O_WRONLY|O_CREAT|O_TRUNC, mode);
+ if (wrfd < 0)
+ {
+ fprintf(stderr, "ERROR: Failed to open %s for writing: %s\n", destpath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Now copy the file */
+
+ for (;;)
+ {
+ do
+ {
+ nbytesread = read(rdfd, g_buffer, BUFFER_SIZE);
+ if (nbytesread == 0)
+ {
+ /* End of file */
+
+ close(rdfd);
+ close(wrfd);
+ return;
+ }
+ else if (nbytesread < 0)
+ {
+ /* EINTR is not an error (but will still stop the copy) */
+
+ fprintf(stderr, "ERROR: Read failure: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ while (nbytesread <= 0);
+
+ do
+ {
+ nbyteswritten = write(wrfd, g_buffer, nbytesread);
+ if (nbyteswritten >= 0)
+ {
+ nbytesread -= nbyteswritten;
+ }
+ else
+ {
+ /* EINTR is not an error (but will still stop the copy) */
+
+ fprintf(stderr, "ERROR: Write failure: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ while (nbytesread > 0);
+ }
+}
+
+static void substitute(char *str, int ch1, int ch2)
+{
+ for (; *str; str++)
+ {
+ if (*str == ch1)
+ {
+ *str = ch2;
+ }
+ }
+}
+
+static void configure(void)
+{
+ char *destconfig;
+
+ /* Copy the defconfig file as .config */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_topdir, g_delim);
+ destconfig = strdup(g_buffer);
+ debug("configure: Copying from %s to %s\n", g_srcdefconfig, destconfig);
+ copy_file(g_srcdefconfig, destconfig, 0644);
+
+ /* Copy the Make.defs file as Make.defs */
+
+ snprintf(g_buffer, BUFFER_SIZE, "%s%cMake.defs", g_topdir, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcmakedefs, g_buffer);
+ copy_file(g_srcmakedefs, g_buffer, 0644);
+
+ /* Copy the setenv.sh file if have one and need one */
+
+ if (g_srcsetenvsh)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.sh", g_topdir, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcsetenvsh, g_buffer);
+ copy_file(g_srcsetenvsh, g_buffer, 0755);
+ }
+
+ /* Copy the setenv.bat file if have one and need one */
+
+ if (g_srcsetenvbat)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%csetenv.bat", g_topdir, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcsetenvbat, g_buffer);
+ copy_file(g_srcsetenvbat, g_buffer, 0644);
+ }
+
+ /* Copy the appconfig file to ../apps/.config if have one and need one */
+
+ if (g_srcappconfig)
+ {
+ snprintf(g_buffer, BUFFER_SIZE, "%s%c.config", g_apppath, g_delim);
+ debug("configure: Copying from %s to %s\n", g_srcappconfig, g_buffer);
+ copy_file(g_srcappconfig, g_buffer, 0644);
+ }
+
+ /* If we did not use the CONFIG_APPS_DIR that was in the defconfig config file,
+ * then append the correct application information to the tail of the .config
+ * file
+ */
+
+ if (g_needapppath)
+ {
+ FILE *stream;
+ char *appdir = strdup(g_appdir);
+
+ /* One complexity is if we are using Windows paths, but the configuration
+ * needs POSIX paths (or vice versa).
+ */
+
+ if (g_winpaths != g_winnative)
+ {
+ /* Not the same */
+
+ if (g_winpaths)
+ {
+ /* Using Windows paths, but the configuration wants POSIX paths */
+
+ substitute(appdir, '\\', '/');
+ }
+ else
+ {
+ /* Using POSIX paths, but the configuration wants Windows paths */
+
+ substitute(appdir, '/', '\\');
+ }
+ }
+
+ /* Open the file for appending */
+
+ stream = fopen(destconfig, "a");
+ if (!stream)
+ {
+ fprintf(stderr, "ERROR: Failed to open %s for append mode mode: %s\n",
+ destconfig, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stream, "\n# Application configuration\n\n");
+ fprintf(stream, "CONFIG_APPS_DIR=\"%s\"\n", appdir);
+ fclose(stream);
+ free(appdir);
+ }
+
+ free(destconfig);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, char **argv, char **envp)
+{
+ debug("main: Checking arguments\n");
+ parse_args(argc, argv);
+
+ debug("main: Checking Nuttx Directories\n");
+ get_topdir();
+ check_configdir();
+
+ debug("main: Reading the configuration/version files\n");
+ read_configfile();
+ read_versionfile();
+ get_verstring();
+
+ debug("main: Checking Configuration Directory\n");
+ check_configuration();
+
+ debug("main: Checking Application Directories\n");
+ check_appdir();
+ debug("main: Using apppath=%s\n", g_apppath ? g_apppath : "<null>");
+
+ debug("main: Configuring\n");
+ configure();
+ return EXIT_SUCCESS;
+}
diff --git a/nuttx/tools/configure.sh b/nuttx/tools/configure.sh
index ffa997178..89f2e2fbc 100755
--- a/nuttx/tools/configure.sh
+++ b/nuttx/tools/configure.sh
@@ -125,7 +125,6 @@ else
fi
src_config="${configpath}/defconfig"
-tmp_config="${TOPDIR}/.configX"
dest_config="${TOPDIR}/.config"
if [ ! -r "${src_config}" ]; then
@@ -201,7 +200,7 @@ if [ "X${have_setenv}" = "Xy" ]; then
{ echo "Failed to copy ${src_setenv}" ; exit 8 ; }
chmod 755 "${dest_setenv}"
fi
-install "${src_config}" "${tmp_config}" || \
+install "${src_config}" "${dest_config}" || \
{ echo "Failed to copy \"${src_config}\"" ; exit 9 ; }
# If we did not use the CONFIG_APPS_DIR that was in the defconfig config file,
@@ -209,14 +208,14 @@ install "${src_config}" "${tmp_config}" || \
# file
if [ "X${defappdir}" = "Xy" ]; then
- sed -i -e "/^CONFIG_APPS_DIR/d" "${tmp_config}"
- echo "" >> "${tmp_config}"
- echo "# Application configuration" >> "${tmp_config}"
- echo "" >> "${tmp_config}"
+ sed -i -e "/^CONFIG_APPS_DIR/d" "${dest_config}"
+ echo "" >> "${dest_config}"
+ echo "# Application configuration" >> "${dest_config}"
+ echo "" >> "${dest_config}"
if [ "X${winnative}" = "Xy" ]; then
- echo "CONFIG_APPS_DIR=\"$winappdir\"" >> "${tmp_config}"
+ echo "CONFIG_APPS_DIR=\"$winappdir\"" >> "${dest_config}"
else
- echo "CONFIG_APPS_DIR=\"$posappdir\"" >> "${tmp_config}"
+ echo "CONFIG_APPS_DIR=\"$posappdir\"" >> "${dest_config}"
fi
fi
@@ -232,9 +231,3 @@ if [ ! -z "${appdir}" -a "X${newconfig}" != "Xy" ]; then
{ echo "Failed to copy ${configpath}/appconfig" ; exit 10 ; }
fi
fi
-
-# install the final .configX only if it differs from any existing
-# .config file.
-
-install "${tmp_config}" "${dest_config}"
-rm -f "${tmp_config}"
diff --git a/nuttx/tools/kconfig.bat b/nuttx/tools/kconfig.bat
new file mode 100755
index 000000000..db01e7515
--- /dev/null
+++ b/nuttx/tools/kconfig.bat
@@ -0,0 +1,131 @@
+@echo off
+
+rem tools/kconfig.bat
+rem
+rem Copyright (C) 2012 Gregory Nutt. All rights reserved.
+rem Author: Gregory Nutt <gnutt@nuttx.org>
+rem
+rem Redistribution and use in source and binary forms, with or without
+rem modification, are permitted provided that the following conditions
+rem are met:
+rem
+rem 1. Redistributions of source code must retain the above copyright
+rem notice, this list of conditions and the following disclaimer.
+rem 2. Redistributions in binary form must reproduce the above copyright
+rem notice, this list of conditions and the following disclaimer in
+rem the documentation and/or other materials provided with the
+rem distribution.
+rem 3. Neither the name NuttX nor the names of its contributors may be
+rem used to endorse or promote products derived from this software
+rem without specific prior written permission.
+rem
+rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+rem FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+rem COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+rem INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+rem BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+rem OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+rem AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+rem LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+rem ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+rem POSSIBILITY OF SUCH DAMAGE.
+rem
+
+rem Remember the state of the PATH variable on entry
+
+set oldpath=%PATH%
+
+rem Handle command line options
+
+set action=%1
+shift
+if "%action%"=="" goto :MissingArgument
+
+set appsdir=..\apps
+set cygwindir=C:\Cygwin
+
+:ArgLoop
+
+if "%1"=="" goto :CheckArguments
+
+if "%1"=="-a" (
+ shift
+ set appsdir=%1
+ goto :NextArg
+)
+
+if "%1"=="-c" (
+ shift
+ set cygwindir=%1
+ goto :NextArg
+)
+
+echo ERROR: Unrecognized option: %1
+goto :ShowUsage
+
+:NextArg
+shift
+goto :ArgLoop
+
+rem Verify that all of the paths are valid
+
+:CheckArguments
+if exist "%appsdir%" goto :CheckCygwinDir
+
+echo ERROR: %appsdir% does not exist
+goto :ShowUsage
+
+:CheckCygwinDir
+
+if exist "%cygwindir%" goto :SetPath
+
+echo ERROR: %cygwindir% does not exist
+goto :ShowUsage
+
+rem Setup some required environment variables and PATH settings
+
+:SetPath
+set PATH=%cygwindir%\usr\local\bin;%cygwindir%\usr\bin;%cygwindir%\bin;%PATH%
+set APPSDIR=%appsdir%
+
+rem Execute the requested action
+
+if "%action%"=="config" goto :DoConfig
+if "%action%"=="oldconfig" goto :DoOldConfig
+if "%action%"=="menuconfig" goto :DoMenuConfig
+
+echo ERROR: Unrecognized action: %action%
+goto :ShowUsage
+
+:DoConfig
+kconfig-conf Kconfig
+goto End
+
+:DoOldConfig
+kconfig-conf --oldconfig Kconfig
+goto End
+
+:DoMenuConfig
+kconfig-mconf Kconfig
+goto End
+
+:MissingArgument
+
+echo ERROR: Missing required argument
+
+:ShowUsage
+echo USAGE: %0 ^<action^> [-a ^<appsdir^>] [-c ^<cygwindir^>]
+echo Where:
+echo ^<action^> is one of config, oldconf, or menuconfig
+echo ^<appsdir^> is the relative path to the apps\ directory.
+echo This defaults to ..\apps
+echo ^<cygwindir^> is the relative path to the Cygwin installation
+echo directory. This defaults to C:\Cygwin
+
+rem Restore the original PATH settings
+
+:End
+set PATH=%oldpath%
+
diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c
index 3e55f5097..fe3e00491 100644
--- a/nuttx/tools/mkconfig.c
+++ b/nuttx/tools/mkconfig.c
@@ -1,7 +1,7 @@
/****************************************************************************
* tools/mkconfig.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
#include <stdlib.h>
#include <errno.h>
-#include "cfgparser.h"
+#include "cfgdefine.h"
/****************************************************************************
* Pre-processor Definitions
@@ -99,7 +99,7 @@ int main(int argc, char **argv, char **envp)
printf("#ifndef __INCLUDE_NUTTX_CONFIG_H\n");
printf("#define __INCLUDE_NUTTX_CONFIG_H\n\n");
printf("/* Architecture-specific options *************************/\n\n");
- parse_file(stream);
+ generate_definitions(stream);
printf("\n/* Sanity Checks *****************************************/\n\n");
printf("/* If this is an NXFLAT, external build, then make sure that\n");
printf(" * NXFLAT support is enabled in the base code.\n");
@@ -213,14 +213,14 @@ int main(int argc, char **argv, char **envp)
printf("# undef CONFIG_FS_FAT\n");
printf("# undef CONFIG_FS_ROMFS\n");
printf("# undef CONFIG_FS_NXFFS\n");
- printf("# undef CONFIG_APPS_BINDIR\n");
+ printf("# undef CONFIG_FS_BINFS\n");
printf("# undef CONFIG_NFS\n");
printf("#endif\n\n");
printf("/* Check if any readable and writable filesystem (OR USB storage) is supported */\n\n");
printf("#undef CONFIG_FS_READABLE\n");
printf("#undef CONFIG_FS_WRITABLE\n");
printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_FS_ROMFS) || defined(CONFIG_USBMSC) || \\\n");
- printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_APPS_BINDIR) || defined(CONFIG_NFS)\n");
+ printf(" defined(CONFIG_FS_NXFFS) || defined(CONFIG_FS_BINFS) || defined(CONFIG_NFS)\n");
printf("# define CONFIG_FS_READABLE 1\n");
printf("#endif\n\n");
printf("#if defined(CONFIG_FS_FAT) || defined(CONFIG_USBMSC) || defined(CONFIG_FS_NXFFS) || \\\n");
diff --git a/nuttx/tools/mksyscall.c b/nuttx/tools/mksyscall.c
index a75e82d28..1d172a2a1 100644
--- a/nuttx/tools/mksyscall.c
+++ b/nuttx/tools/mksyscall.c
@@ -61,11 +61,11 @@ static FILE *g_stubstream;
* Private Functions
****************************************************************************/
-static bool is_vararg(const char *type, int index, int nparms)
+static bool is_vararg(const char *type, int ndx, int nparms)
{
if (strcmp(type,"...") == 0)
{
- if (index != (nparms-1))
+ if (ndx != (nparms-1))
{
fprintf(stderr, "%d: ... is not the last in the argument list\n", g_lineno);
exit(11);
@@ -75,8 +75,10 @@ static bool is_vararg(const char *type, int index, int nparms)
fprintf(stderr, "%d: Need one parameter before ...\n", g_lineno);
exit(14);
}
+
return true;
}
+
return false;
}
diff --git a/nuttx/tools/mkversion.c b/nuttx/tools/mkversion.c
index 32068df38..c6b00c5e5 100644
--- a/nuttx/tools/mkversion.c
+++ b/nuttx/tools/mkversion.c
@@ -41,7 +41,7 @@
#include <stdlib.h>
#include <errno.h>
-#include "cfgparser.h"
+#include "cfgdefine.h"
/****************************************************************************
* Definitions
@@ -98,7 +98,7 @@ int main(int argc, char **argv, char **envp)
printf("/* version.h -- Autogenerated! Do not edit. */\n\n");
printf("#ifndef __INCLUDE_NUTTX_VERSION_H\n");
printf("#define __INCLUDE_NUTTX_VERSION_H\n\n");
- parse_file(stream);
+ generate_definitions(stream);
printf("\n#define CONFIG_VERSION ((CONFIG_VERSION_MAJOR << 8) | (CONFIG_VERSION_MINOR))\n\n");
printf("#endif /* __INCLUDE_NUTTX_VERSION_H */\n");
fclose(stream);