system: nxlooper: add nxlooper for loopback test

N/A

which record and play raw data using audio subsystem
to verify audio record and playback function

Signed-off-by: danguanghua <danguanghua@xiaomi.com>

Change-Id: I2c768b8e8234a31f9622cb9955f785329cf402a5
Signed-off-by: danguanghua <danguanghua@xiaomi.com>
This commit is contained in:
danguanghua 2020-11-27 17:41:42 +08:00 committed by Xiang Xiao
parent 961fface44
commit a4f240e0e1
6 changed files with 2351 additions and 0 deletions

254
include/system/nxlooper.h Normal file
View File

@ -0,0 +1,254 @@
/****************************************************************************
* apps/include/system/nxlooper.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_INCLUDE_SYSTEM_NXLOOPER_H
#define __APPS_INCLUDE_SYSTEM_NXLOOPER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Type Declarations
****************************************************************************/
/* This structure describes the internal state of the NxLooper */
struct nxlooper_s
{
int loopstate; /* Current looper test state */
int recorddev_fd; /* File descriptor of active
* record device */
char recorddev[CONFIG_NAME_MAX]; /* Preferred record device */
int playdev_fd; /* File descriptor of active
* play device */
char playdev[CONFIG_NAME_MAX]; /* Preferred loopback device */
int crefs; /* Number of references */
sem_t sem; /* Thread sync semaphore */
char mqname[16]; /* Name of play message queue */
mqd_t mq; /* Message queue for the
* loopthread */
pthread_t loop_id; /* Thread ID of the loopthread */
#ifdef CONFIG_AUDIO_MULTI_SESSION
FAR void *pplayses; /* Session assignment from device */
#endif
#ifdef CONFIG_AUDIO_MULTI_SESSION
FAR void *precordses; /* Session assignment from device */
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
uint16_t volume; /* Volume as a whole percentage (0-100) */
#endif
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: nxlooper_create
*
* Allocates and Initializes a NxLooper context that is passed to all
* nxlooper routines. The looper MUST be destroyed using the
* nxlooper_destroy() routine since the context is reference counted.
* The context can be used in a mode where the caller creates the
* context, starts a looping, and then forgets about the context
* and it will self free. This is because the nxlooper_loopraw
* will also create a reference to the context, so the client calling
* nxlooper_destroy() won't actually de-allocate anything. The freeing
* will occur after the loopthread has completed.
*
* Alternately, the caller can create the object and hold on to it, then
* the context will persist until the original creator destroys it.
*
* Input Parameters: None
*
* Returned Value:
* Pointer to created NxLooper context or NULL if error.
****************************************************************************/
FAR struct nxlooper_s *nxlooper_create(void);
/****************************************************************************
* Name: nxlooper_release
*
* Reduces the reference count to the looper and if it reaches zero,
* frees all memory used by the context.
*
* Input Parameters:
* plooper Pointer to the NxLooper context
*
* Returned Value:
* None
*
****************************************************************************/
void nxlooper_release(FAR struct nxlooper_s *plooper);
/****************************************************************************
* Name: nxlooper_reference
*
* Increments the reference count to the looper.
*
* Input Parameters:
* plooper Pointer to the NxLooper context
*
* Returned Value:
* None
*
****************************************************************************/
void nxlooper_reference(FAR struct nxlooper_s *plooper);
/****************************************************************************
* Name: nxlooper_setdevice
*
* Sets the preferred Audio device to use with the instance of the
* nxlooper. Without a preferred device set, the nxlooper will search
* the audio subsystem to find a suitable device depending on the
* type of audio operation requested.
*
* Input Parameters:
* plooper - Pointer to the context to initialize
* device - Pointer to pathname of the preferred device
*
* Returned Value:
* OK if context initialized successfully, error code otherwise.
*
****************************************************************************/
int nxlooper_setdevice(FAR struct nxlooper_s *plooper,
FAR const char *device);
/****************************************************************************
* Name: nxlooper_stop
*
* Stops current loopback.
*
* Input Parameters:
* plooper - Pointer to the context to initialize
*
* Returned Value:
* OK if file found, device found, and loopback started.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
int nxlooper_stop(FAR struct nxlooper_s *plooper);
#endif
/****************************************************************************
* Name: nxlooper_pause
*
* Pauses current loopback.
*
* Input Parameters:
* plooper - Pointer to the context to initialize
*
* Returned Value:
* OK if file found, device found, and loopback started.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
int nxlooper_pause(FAR struct nxlooper_s *plooper);
#endif
/****************************************************************************
* Name: nxlooper_resume
*
* Resumes current loopback.
*
* Input Parameters:
* plooper - Pointer to the context to initialize
*
* Returned Value:
* OK if file found, device found, and loopback started.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
int nxlooper_resume(FAR struct nxlooper_s *plooper);
#endif
/****************************************************************************
* Name: nxlooper_setvolume
*
* Sets the loopback volume. The volume is represented in 1/10th of a
* percent increments, so the range is 0-1000. A value of 10 would mean
* 1%.
*
* Input Parameters:
* plooper - Pointer to the context to initialize
* volume - Volume level to set in 1/10th percent increments
*
* Returned Value:
* OK if file found, device found, and loopback started.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
int nxlooper_setvolume(FAR struct nxlooper_s *plooper, uint16_t volume);
#endif
/****************************************************************************
* Name: nxlooper_systemreset
*
* Performs an audio system reset, including a hardware reset on all
* registered audio devices.
*
* Input Parameters:
* plooper - Pointer to the context to initialize
*
* Returned Value:
* OK if file found, device found, and loopback started.
*
****************************************************************************/
#ifdef CONFIG_NXLOOPER_INCLUDE_SYSTEM_RESET
int nxlooper_systemreset(FAR struct nxlooper_s *plooper);
#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_INCLUDE_SYSTEM_NXLOOPER_H */

80
system/nxlooper/Kconfig Normal file
View File

@ -0,0 +1,80 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config SYSTEM_NXLOOPER
bool "NxLooper audio test application"
default n
depends on AUDIO
---help---
Enable support for the NxLoop media tester library and optional
command line interface.
if SYSTEM_NXLOOPER
config NXLOOPER_MAINTHREAD_STACKSIZE
int "NxLooper main thread stack size"
default DEFAULT_TASK_STACKSIZE
---help---
Stack size to use with the NxLooper main thread.
config NXLOOPER_LOOPTHREAD_STACKSIZE
int "NxLooper thread stack size"
default PTHREAD_STACK_DEFAULT
---help---
Stack size to use with the NxLooper play thread.
config NXLOOPER_MSG_PRIO
int "NxLooper priority of message queen"
default 1
---help---
Priority of stop message to notice NxLooper thread.
config NXLOOPER_COMMAND_LINE
tristate "Include nxlooper command line application"
default y
---help---
Compiles in code for the nxlooper command line control.
This is a text-based command line interface that uses
the nxlooper library to play media files, control the
volume, balance, bass, etc.
if NXLOOPER_COMMAND_LINE
config NXLOOPER_INCLUDE_HELP
bool "Include HELP command and text"
default y
---help---
Compiles in the NxLooper help text to provide online help
for available commands with syntax.
endif
config NXLOOPER_INCLUDE_DEVICE_SEARCH
bool "Include audio device search code"
default y
---help---
Compiles in extra code to search the audio device directory
for a suitable audio device to play the specified file.
Disabling this feature saves some code space, but it will
mean the calling application must specify the path of the
audio device to use before performing any other operations.
config NXLOOPER_INCLUDE_PREFERRED_DEVICE
bool "Include preferred audio device specification code"
default y
---help---
Adds support for identifying a specific audio device to use
for audio operations. If this feature is not enabled, then
an audio device search will be performed.
config NXLOOPER_INCLUDE_SYSTEM_RESET
bool "Include support for system / hardware reset"
default n
---help---
When enabled, this feature will add code to enable issuing
a HW reset via program call. The system reset will perform
a reset on all registered audio devices.
endif

24
system/nxlooper/Make.defs Normal file
View File

@ -0,0 +1,24 @@
############################################################################
# apps/system/nxlooper/Make.defs
# Adds selected applications to apps/ build
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifneq ($(CONFIG_SYSTEM_NXLOOPER),)
CONFIGURED_APPS += $(APPDIR)/system/nxlooper
endif

36
system/nxlooper/Makefile Normal file
View File

@ -0,0 +1,36 @@
############################################################################
# apps/system/nxlooper/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
include $(APPDIR)/Make.defs
# NxLooper Library
CSRCS = nxlooper.c
ifneq ($(CONFIG_NXLOOPER_COMMAND_LINE),)
PROGNAME = nxlooper
PRIORITY = SCHED_PRIORITY_DEFAULT
STACKSIZE = $(CONFIG_NXLOOPER_MAINTHREAD_STACKSIZE)
MODULE = $(CONFIG_NXLOOPER_COMMAND_LINE)
MAINSRC = nxlooper_main.c
endif
include $(APPDIR)/Application.mk

1364
system/nxlooper/nxlooper.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,593 @@
/****************************************************************************
* apps/system/nxlooper/nxlooper_main.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/audio/audio.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include "system/readline.h"
#include "system/nxlooper.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NXLOOPER_VER "1.00"
#ifdef CONFIG_NXLOOPER_INCLUDE_HELP
# define NXLOOPER_HELP_TEXT(x) x
#else
# define NXLOOPER_HELP_TEXT(x)
#endif
/****************************************************************************
* Private Type Declarations
****************************************************************************/
typedef int (*nxlooper_func)(FAR struct nxlooper_s *plooper, char *pargs);
struct mp_cmd_s
{
FAR const char *cmd; /* The command text */
FAR const char *arghelp; /* Text describing the args */
nxlooper_func pfunc; /* Pointer to command handler */
FAR const char *help; /* The help text */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int nxlooper_cmd_quit(FAR struct nxlooper_s *plooper, char *parg);
static int nxlooper_cmd_loopback(FAR struct nxlooper_s *plooper, char *parg);
#ifdef CONFIG_NXLOOPER_INCLUDE_SYSTEM_RESET
static int nxlooper_cmd_reset(FAR struct nxlooper_s *plooper, char *parg);
#endif
#ifdef CONFIG_NXLOOPER_INCLUDE_PREFERRED_DEVICE
static int nxlooper_cmd_device(FAR struct nxlooper_s *plooper, char *parg);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
static int nxlooper_cmd_pause(FAR struct nxlooper_s *plooper, char *parg);
static int nxlooper_cmd_resume(FAR struct nxlooper_s *plooper, char *parg);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
static int nxlooper_cmd_stop(FAR struct nxlooper_s *plooper, char *parg);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
static int nxlooper_cmd_volume(FAR struct nxlooper_s *plooper, char *parg);
#endif
#ifdef CONFIG_NXLOOPER_INCLUDE_HELP
static int nxlooper_cmd_help(FAR struct nxlooper_s *plooper, char *parg);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static const struct mp_cmd_s g_nxlooper_cmds[] =
{
#ifdef CONFIG_NXLOOPER_INCLUDE_PREFERRED_DEVICE
{
"device",
"devfile",
nxlooper_cmd_device,
NXLOOPER_HELP_TEXT("Specify a preferred play/record device")
},
#endif
#ifdef CONFIG_NXLOOPER_INCLUDE_HELP
{
"h",
"",
nxlooper_cmd_help,
NXLOOPER_HELP_TEXT("Display help for commands")
},
{
"help",
"",
nxlooper_cmd_help,
NXLOOPER_HELP_TEXT("Display help for commands")
},
#endif
{
"loopback",
"channels bpsamp samprate chmap",
nxlooper_cmd_loopback,
NXLOOPER_HELP_TEXT("Audio loopback test")
},
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
{
"pause",
"",
nxlooper_cmd_pause,
NXLOOPER_HELP_TEXT("Pause loopback")
},
#endif
#ifdef CONFIG_NXLOOPER_INCLUDE_SYSTEM_RESET
{
"reset",
"",
nxlooper_cmd_reset,
NXLOOPER_HELP_TEXT("Perform a HW reset")
},
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
{
"resume",
"",
nxlooper_cmd_resume,
NXLOOPER_HELP_TEXT("Resume loopback")
},
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
{
"stop",
"",
nxlooper_cmd_stop,
NXLOOPER_HELP_TEXT("Stop loopback")
},
#endif
{
"q",
"",
nxlooper_cmd_quit,
NXLOOPER_HELP_TEXT("Exit NxLooper")
},
{
"quit",
"",
nxlooper_cmd_quit,
NXLOOPER_HELP_TEXT("Exit NxLooper")
},
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
{
"volume",
"d%",
nxlooper_cmd_volume,
NXLOOPER_HELP_TEXT("Set volume to level specified")
}
#endif
};
static const int g_nxlooper_cmd_count = sizeof(g_nxlooper_cmds) /
sizeof(struct mp_cmd_s);
/****************************************************************************
* Name: nxlooper_cmd_loopback
*
* nxlooper_cmd_loop() play and record the raw data file using the nxlooper
* context.
*
****************************************************************************/
static int nxlooper_cmd_loopback(FAR struct nxlooper_s *plooper, char *parg)
{
int ret;
int channels = 0;
int bpsamp = 0;
int samprate = 0;
int chmap = 0;
sscanf(parg, "%d %d %d %d", &channels, &bpsamp,
&samprate, &chmap);
/* Try to loopback raw data with settings specified */
ret = nxlooper_loopraw(plooper, channels, bpsamp,
samprate, chmap);
/* nxlooper_loopraw returned values:
*
* OK Loopback is being run
* -EBUSY The media device is busy
* -ENOSYS The audio format is not unsupported
* -ENODEV No audio device suitable to play and record the media type
*/
switch (-ret)
{
case OK:
break;
case ENODEV:
printf("No suitable Audio Device found\n");
break;
case EBUSY:
printf("Audio device busy\n");
break;
case ENOSYS:
printf("Unknown audio format\n");
break;
default:
printf("Error loopback test: %d\n", -ret);
break;
}
return ret;
}
/****************************************************************************
* Name: nxlooper_cmd_volume
*
* nxlooper_cmd_volume() sets the volume level.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
static int nxlooper_cmd_volume(FAR struct nxlooper_s *plooper, char *parg)
{
uint16_t percent;
/* If no arg given, then print current volume */
if (parg == NULL || *parg == '\0')
{
printf("volume: %d\n", plooper->volume / 10);
}
else
{
/* Get the percentage value from the argument */
percent = (uint16_t)(atof(parg) * 10.0);
return nxlooper_setvolume(plooper, percent);
}
return OK;
}
#endif
/****************************************************************************
* Name: nxlooper_cmd_reset
*
* nxlooper_cmd_reset() performs a HW reset of all the audio devices.
*
****************************************************************************/
#ifdef CONFIG_NXLOOPER_INCLUDE_SYSTEM_RESET
static int nxlooper_cmd_reset(FAR struct nxlooper_s *plooper, char *parg)
{
return nxlooper_systemreset(plooper);
}
#endif
/****************************************************************************
* Name: nxlooper_cmd_stop
*
* nxlooper_cmd_stop() stops loopback
* context.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
static int nxlooper_cmd_stop(FAR struct nxlooper_s *plooper, char *parg)
{
/* Stop the loopback */
return nxlooper_stop(plooper);
}
#endif
/****************************************************************************
* Name: nxlooper_cmd_pause
*
* nxlooper_cmd_pause() pauses loopback
* context.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
static int nxlooper_cmd_pause(FAR struct nxlooper_s *plooper, char *parg)
{
/* Pause the loopback */
return nxlooper_pause(plooper);
}
#endif
/****************************************************************************
* Name: nxlooper_cmd_resume
*
* nxlooper_cmd_resume() resumes loopback
* context.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
static int nxlooper_cmd_resume(FAR struct nxlooper_s *plooper, char *parg)
{
/* Resume the loopback */
return nxlooper_resume(plooper);
}
#endif
/****************************************************************************
* Name: nxlooper_cmd_device
*
* nxlooper_cmd_device() sets the preferred audio device for loopback
*
****************************************************************************/
#ifdef CONFIG_NXLOOPER_INCLUDE_PREFERRED_DEVICE
static int nxlooper_cmd_device(FAR struct nxlooper_s *plooper, char *parg)
{
int ret;
char path[32];
/* First try to open the file directly */
ret = nxlooper_setdevice(plooper, parg);
if (ret == -ENOENT)
{
/* Append the /dev/audio path and try again */
#ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH
#ifdef CONFIG_AUDIO_DEV_ROOT
snprintf(path, sizeof(path), "/dev/%s", parg);
#else
snprintf(path, sizeof(path), CONFIG_AUDIO_DEV_PATH "/%s", parg);
#endif
#else
snprintf(path, sizeof(path), "/dev/audio/%s", parg);
#endif
ret = nxlooper_setdevice(plooper, path);
}
/* Test if the device file exists */
if (ret == -ENOENT)
{
/* Device doesn't exit. Report error */
printf("Device %s not found\n", parg);
return ret;
}
/* Test if is is an audio device */
if (ret == -ENODEV)
{
printf("Device %s is not an audio device\n", parg);
return ret;
}
if (ret < 0)
{
return ret;
}
/* Device set successfully */
return OK;
}
#endif /* CONFIG_NXLOOPER_INCLUDE_PREFERRED_DEVICE */
/****************************************************************************
* Name: nxlooper_cmd_quit
*
* nxlooper_cmd_quit() terminates the application
****************************************************************************/
static int nxlooper_cmd_quit(FAR struct nxlooper_s *plooper, char *parg)
{
/* Stop the loopback if any */
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
return nxlooper_stop(plooper);
#endif
return OK;
}
/****************************************************************************
* Name: nxlooper_cmd_help
*
* nxlooper_cmd_help() displays the application's help information on
* supported commands and command syntax.
****************************************************************************/
#ifdef CONFIG_NXLOOPER_INCLUDE_HELP
static int nxlooper_cmd_help(FAR struct nxlooper_s *plooper, char *parg)
{
int len;
int maxlen = 0;
int x;
int c;
/* Calculate length of longest cmd + arghelp */
for (x = 0; x < g_nxlooper_cmd_count; x++)
{
len = strlen(g_nxlooper_cmds[x].cmd) +
strlen(g_nxlooper_cmds[x].arghelp);
if (len > maxlen)
{
maxlen = len;
}
}
printf("NxLooper commands\n================\n");
for (x = 0; x < g_nxlooper_cmd_count; x++)
{
/* Print the command and it's arguments */
printf(" %s %s", g_nxlooper_cmds[x].cmd, g_nxlooper_cmds[x].arghelp);
/* Calculate number of spaces to print before the help text */
len = maxlen - (strlen(g_nxlooper_cmds[x].cmd) +
strlen(g_nxlooper_cmds[x].arghelp));
for (c = 0; c < len; c++)
{
printf(" ");
}
printf(" : %s\n", g_nxlooper_cmds[x].help);
}
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxlooper
*
* nxlooper() reads in commands from the console using the readline
* system add-in and impalements a command-line based media loop
* tester that uses the NuttX audio system to record and then play
* raw data from the lower audio driver. Commands are provided for
* setting volume, base and other audio features, as well as for
* pausing and stopping the test.
*
* Input Parameters:
* buf - The user allocated buffer to be filled.
* buflen - the size of the buffer.
* instream - The stream to read characters from
* outstream - The stream to each characters to.
*
* Returned values:
* On success, the (positive) number of bytes transferred is returned.
* EOF is returned to indicate either an end of file condition or a
* failure.
*
****************************************************************************/
int main(int argc, FAR char *argv[])
{
char buffer[CONFIG_NSH_LINELEN];
int len;
int x;
int running;
FAR char *cmd;
FAR char *arg;
FAR struct nxlooper_s *plooper;
printf("NxLooper version " NXLOOPER_VER "\n");
printf("h for commands, q to exit\n");
printf("\n");
/* Initialize our NxLooper context */
plooper = nxlooper_create();
if (plooper == NULL)
{
printf("Error: Out of RAM\n");
return -ENOMEM;
}
/* Loop until the user exits */
running = TRUE;
while (running)
{
/* Print a prompt */
printf("nxlooper> ");
fflush(stdout);
/* Read a line from the terminal */
len = readline(buffer, sizeof(buffer), stdin, stdout);
buffer[len] = '\0';
if (len > 0)
{
if (strncmp(buffer, "!", 1) != 0)
{
/* nxlooper command */
if (buffer[len - 1] == '\n')
{
buffer[len - 1] = '\0';
}
/* Parse the command from the argument */
cmd = strtok_r(buffer, " \n", &arg);
if (cmd == NULL)
{
continue;
}
/* Find the command in our cmd array */
for (x = 0; x < g_nxlooper_cmd_count; x++)
{
if (strcmp(cmd, g_nxlooper_cmds[x].cmd) == 0)
{
/* Command found. Call it's handler if not NULL */
if (g_nxlooper_cmds[x].pfunc != NULL)
{
g_nxlooper_cmds[x].pfunc(plooper, arg);
}
/* Test if it is a quit command */
if (g_nxlooper_cmds[x].pfunc == nxlooper_cmd_quit)
{
running = FALSE;
}
break;
}
}
}
else
{
#ifdef CONFIG_SYSTEM_SYSTEM
/* Transfer nuttx shell */
system(buffer + 1);
#else
printf("%s: unknown nxlooper command\n", buffer);
#endif
}
}
}
/* Release the NxLooper context */
nxlooper_release(plooper);
return OK;
}