Merged in antmerlino/apps/i8sak_daemon (pull request #151)
i8sak: i8sak daemon now gets shutdown if not in use. Previously, once the i8sak daemon was started, by running any command, it would stay running. This means that if you want to use i8sak to setup your network, but then want exclusive access to the char device, or network device, you have to manually shutdown the i8sak daemon. Now the daemon stays active as long as required to finish any commands, or stays open if a new command keeps it on, but when all work is finished, it shuts down. Approved-by: GregoryN <gnutt@nuttx.org>
This commit is contained in:
parent
8e249eb25f
commit
162fb66ecf
@ -124,13 +124,16 @@ struct i8sak_s
|
||||
pid_t daemon_pid;
|
||||
FAR char ifname[I8SAK_MAX_IFNAME];
|
||||
int result;
|
||||
int fd; /* File/Socket descriptor. Only to be used by operations
|
||||
* occuring within the Daemon TCB
|
||||
*/
|
||||
int fd; /* File/Socket descriptor. Only to be used by operations
|
||||
* occuring within the Daemon TCB
|
||||
*/
|
||||
|
||||
sem_t exclsem; /* For synchronizing access to the signaling semaphore */
|
||||
sem_t sigsem; /* For signaling various tasks */
|
||||
sem_t updatesem; /* For signaling the daemon that it's settings have changed */
|
||||
sem_t exclsem; /* For synchronizing access to the signaling semaphore */
|
||||
sem_t sigsem; /* For signaling various tasks */
|
||||
sem_t updatesem; /* For signaling the daemon that it's settings have changed */
|
||||
sem_t daemonlock; /* For synchronizing access to managing the daemon */
|
||||
|
||||
int daemonusers;
|
||||
|
||||
/* Fields related to event listener */
|
||||
|
||||
@ -202,6 +205,9 @@ struct i8sak_s
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int i8sak_requestdaemon(FAR struct i8sak_s *i8sak);
|
||||
int i8sak_releasedaemon(FAR struct i8sak_s *i8sak);
|
||||
|
||||
uint8_t i8sak_char2nibble (char ch);
|
||||
long i8sak_str2long (FAR const char *str);
|
||||
uint8_t i8sak_str2luint8 (FAR const char *str);
|
||||
|
@ -156,6 +156,8 @@ void i8sak_acceptassoc_cmd(FAR struct i8sak_s *i8sak, int argc,
|
||||
printf("i8sak: accepting all assoc requests\n");
|
||||
}
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
/* Register new callback for receiving the association notifications */
|
||||
|
||||
memset(&filter, 0, sizeof(struct i8sak_eventfilter_s));
|
||||
|
@ -214,6 +214,8 @@ void i8sak_assoc_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
/* Register new callback for receiving the association notifications. */
|
||||
|
||||
memset(&filter, 0, sizeof(struct i8sak_eventfilter_s));
|
||||
@ -260,7 +262,6 @@ void i8sak_assoc_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
i8sak->result = -EBUSY;
|
||||
|
||||
ret = sem_wait(&i8sak->sigsem);
|
||||
sem_post(&i8sak->exclsem);
|
||||
if (ret != OK)
|
||||
{
|
||||
i8sak->assoc = false;
|
||||
@ -311,6 +312,7 @@ void i8sak_assoc_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
/* Clean up and return */
|
||||
|
||||
(void)i8sak_eventlistener_removereceiver(i8sak, assoc_eventcb);
|
||||
i8sak_releasedaemon(i8sak);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,8 @@ void i8sak_blaster_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
{
|
||||
int option;
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
i8sak_blaster_start(i8sak);
|
||||
|
@ -140,6 +140,100 @@ static void i8sak_switch_instance(FAR char *ifname);
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name : i8sak_requestdaemon
|
||||
*
|
||||
* Description :
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int i8sak_requestdaemon(FAR struct i8sak_s *i8sak)
|
||||
{
|
||||
char daemonname[I8SAK_MAX_DAEMONNAME];
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
ret = sem_wait(&i8sak->daemonlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
DEBUGASSERT(ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (++i8sak->daemonusers == 1)
|
||||
{
|
||||
/* Create strings for task based on device. i.e. i8_ieee0 */
|
||||
|
||||
if (i8sak->mode == I8SAK_MODE_CHAR)
|
||||
{
|
||||
len = strlen(i8sak->ifname);
|
||||
snprintf(daemonname, I8SAK_DAEMONNAME_PREFIX_LEN + (len - 5),
|
||||
I8SAK_DAEMONNAME_FMT, &i8sak->ifname[5]);
|
||||
}
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
else if (i8sak->mode == I8SAK_MODE_NETIF)
|
||||
{
|
||||
len = strlen(i8sak->ifname);
|
||||
snprintf(daemonname, I8SAK_DAEMONNAME_PREFIX_LEN + len,
|
||||
I8SAK_DAEMONNAME_FMT, i8sak->ifname);
|
||||
}
|
||||
#endif
|
||||
|
||||
i8sak->daemon_started = true;
|
||||
i8sak->daemon_pid = task_create(daemonname, CONFIG_IEEE802154_I8SAK_PRIORITY,
|
||||
CONFIG_IEEE802154_I8SAK_STACKSIZE, i8sak_daemon,
|
||||
NULL);
|
||||
if (i8sak->daemon_pid < 0)
|
||||
{
|
||||
fprintf(stderr, "failed to start daemon\n");
|
||||
sem_post(&i8sak->daemonlock);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Use the signal semaphore to wait for daemon to start before returning */
|
||||
|
||||
ret = sem_wait(&i8sak->sigsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "i8sak:interrupted while daemon starting\n");
|
||||
sem_post(&i8sak->daemonlock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
sem_post(&i8sak->daemonlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name : i8sak_releasedaemon
|
||||
*
|
||||
* Description :
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int i8sak_releasedaemon(FAR struct i8sak_s *i8sak)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sem_wait(&i8sak->daemonlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
DEBUGASSERT(ret == EINTR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If this was the last user, signal the daemon to shutdown */
|
||||
|
||||
if (--i8sak->daemonusers == 0)
|
||||
{
|
||||
i8sak->daemon_shutdown = true;
|
||||
sem_post(&i8sak->updatesem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name : i8sak_str2payload
|
||||
*
|
||||
@ -496,10 +590,7 @@ static void i8sak_switch_instance(FAR char *ifname)
|
||||
|
||||
static int i8sak_setup(FAR struct i8sak_s *i8sak, FAR const char *ifname)
|
||||
{
|
||||
char daemonname[I8SAK_MAX_DAEMONNAME];
|
||||
int i;
|
||||
int ret;
|
||||
int len;
|
||||
int fd = 0;
|
||||
|
||||
if (i8sak->initialized)
|
||||
@ -507,23 +598,21 @@ static int i8sak_setup(FAR struct i8sak_s *i8sak, FAR const char *ifname)
|
||||
return OK;
|
||||
}
|
||||
|
||||
i8sak->chan = 11;
|
||||
i8sak->chpage = 0;
|
||||
|
||||
if (strlen(ifname) > I8SAK_MAX_IFNAME)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ifname too long\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
strcpy(&i8sak->ifname[0], ifname);
|
||||
|
||||
i8sak->chan = 11;
|
||||
i8sak->chpage = 0;
|
||||
i8sak->addrmode = IEEE802154_ADDRMODE_SHORT;
|
||||
|
||||
/* Initialize the default remote endpoint address */
|
||||
|
||||
i8sak->ep_addr.mode = IEEE802154_ADDRMODE_SHORT;
|
||||
|
||||
/* Initialize the default remote endpoint address */
|
||||
|
||||
for (i = 0; i < IEEE802154_EADDRSIZE; i++)
|
||||
{
|
||||
i8sak->ep_addr.eaddr[i] =
|
||||
@ -610,8 +699,11 @@ static int i8sak_setup(FAR struct i8sak_s *i8sak, FAR const char *ifname)
|
||||
|
||||
sem_init(&i8sak->eventsem, 0, 1);
|
||||
|
||||
sem_init(&i8sak->daemonlock, 0, 1);
|
||||
|
||||
i8sak->daemon_started = false;
|
||||
i8sak->daemon_shutdown = false;
|
||||
i8sak->daemonusers = 0;
|
||||
|
||||
i8sak->eventlistener_run = false;
|
||||
sq_init(&i8sak->eventreceivers);
|
||||
@ -623,41 +715,6 @@ static int i8sak_setup(FAR struct i8sak_s *i8sak, FAR const char *ifname)
|
||||
|
||||
i8sak->blasterperiod = 1000;
|
||||
|
||||
/* Create strings for task based on device. i.e. i8_ieee0 */
|
||||
|
||||
if (i8sak->mode == I8SAK_MODE_CHAR)
|
||||
{
|
||||
len = strlen(ifname);
|
||||
snprintf(daemonname, I8SAK_DAEMONNAME_PREFIX_LEN + (len - 5),
|
||||
I8SAK_DAEMONNAME_FMT, &ifname[5]);
|
||||
}
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
else if (i8sak->mode == I8SAK_MODE_NETIF)
|
||||
{
|
||||
len = strlen(ifname);
|
||||
snprintf(daemonname, I8SAK_DAEMONNAME_PREFIX_LEN + len,
|
||||
I8SAK_DAEMONNAME_FMT, ifname);
|
||||
}
|
||||
#endif
|
||||
|
||||
i8sak->daemon_pid = task_create(daemonname, CONFIG_IEEE802154_I8SAK_PRIORITY,
|
||||
CONFIG_IEEE802154_I8SAK_STACKSIZE, i8sak_daemon,
|
||||
NULL);
|
||||
if (i8sak->daemon_pid < 0)
|
||||
{
|
||||
fprintf(stderr, "failed to start daemon\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Use the signal semaphore to wait for daemon to start before returning */
|
||||
|
||||
ret = sem_wait(&i8sak->sigsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "i8sak:interrupted while daemon starting\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
i8sak->initialized = true;
|
||||
return OK;
|
||||
}
|
||||
@ -675,7 +732,6 @@ static int i8sak_daemon(int argc, FAR char *argv[])
|
||||
int ret;
|
||||
|
||||
fprintf(stderr, "i8sak: daemon started\n");
|
||||
i8sak->daemon_started = true;
|
||||
|
||||
if (i8sak->mode == I8SAK_MODE_CHAR)
|
||||
{
|
||||
@ -766,12 +822,12 @@ static int i8sak_showusage(FAR const char *progname, int exitcode)
|
||||
" acceptassoc [-h|e]\n"
|
||||
" assoc [-h|p|e|s|w|r|t]\n"
|
||||
" blaster [-h|q|f|p]\n"
|
||||
" get [-h] parameter"
|
||||
" get [-h] parameter\n"
|
||||
" poll [-h]\n"
|
||||
" regdump [-h]\n"
|
||||
" reset [-h]\n"
|
||||
" scan [-h|p|a|e] minch-maxch\n"
|
||||
" set [-h] param val"
|
||||
" set [-h] param val\n"
|
||||
" sniffer [-h|d]\n"
|
||||
" startpan [-h|b|s] xx:xx\n"
|
||||
" tx [-h|d|m] <hex-payload>\n"
|
||||
|
@ -110,6 +110,8 @@ void i8sak_poll_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
/* Register new oneshot callback for receiving the association notifications */
|
||||
|
||||
memset(&eventfilter, 0, sizeof(struct i8sak_eventfilter_s));
|
||||
@ -163,6 +165,8 @@ void i8sak_poll_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
printf("i8sak: poll cancelled\n");
|
||||
i8sak_cmd_error(i8sak);
|
||||
}
|
||||
|
||||
i8sak_releasedaemon(i8sak);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -161,6 +161,8 @@ void i8sak_scan_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
scan.channels[i] = minchannel + i;
|
||||
}
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
/* Register new callback for receiving the scan confirmation notification */
|
||||
|
||||
memset(&filter, 0, sizeof(struct i8sak_eventfilter_s));
|
||||
@ -257,4 +259,6 @@ static void scan_eventcb(FAR struct ieee802154_primitive_s *primitive, FAR void
|
||||
PRINTF_FORMAT_EADDR(scan->pandescs[i].coordaddr.eaddr));
|
||||
}
|
||||
}
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
}
|
||||
|
@ -171,6 +171,8 @@ void i8sak_sniffer_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
|
||||
close(fd);
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
/* Start the sniffer thread. We use the existing daemon thread so that this
|
||||
* thread belongs to the daemon task group.
|
||||
*/
|
||||
|
@ -201,6 +201,8 @@ void i8sak_tx_cmd(FAR struct i8sak_s *i8sak, int argc, FAR char *argv[])
|
||||
tx.meta.flags.indirect = false;
|
||||
}
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
|
||||
/* Register new oneshot callback for receiving the association notifications */
|
||||
|
||||
memset(&eventfilter, 0, sizeof(struct i8sak_eventfilter_s));
|
||||
@ -296,4 +298,6 @@ static void tx_eventcb(FAR struct ieee802154_primitive_s *primitive, FAR void *a
|
||||
}
|
||||
|
||||
sem_post(&i8sak->sigsem);
|
||||
|
||||
i8sak_requestdaemon(i8sak);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user