mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
read_pkt() terminates the received payload with buff[ret], but a full-size read can leave no room for that trailing NUL byte. Limit the read length to one byte less than the buffer size so the received payload remains safely terminated before it is printed. Signed-off-by: Old-Ding <ai.neo.ae86@gmail.com>
359 lines
8.6 KiB
C
359 lines
8.6 KiB
C
/****************************************************************************
|
|
* apps/examples/nrf24l01_term/nrf24l01_term.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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 <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <inttypes.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <nuttx/debug.h>
|
|
#include <poll.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <nuttx/wireless/nrf24l01.h>
|
|
|
|
#include "system/readline.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define DEV_NAME "/dev/nrf24l01"
|
|
|
|
#ifndef STDIN_FILENO
|
|
# define STDIN_FILENO 0
|
|
#endif
|
|
|
|
#define DEFAULT_RADIOFREQ 2450
|
|
|
|
#define DEFAULT_TXPOWER -6 /* (0, -6, -12, or -18 dBm) */
|
|
|
|
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
|
|
# define N_PFDS 2 /* If RX support is enabled, poll both stdin and the message reception */
|
|
#else
|
|
# define N_PFDS 1 /* If RX support is not enabled, we cannot poll the wireless device */
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
int wireless_cfg(int fd);
|
|
|
|
int wireless_open(void);
|
|
|
|
int send_pkt(int wl_fd);
|
|
|
|
int read_pkt(int wl_fd);
|
|
|
|
void usage(void);
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static const uint8_t defaultaddr[NRF24L01_MAX_ADDR_LEN] =
|
|
{
|
|
0x01, 0xca, 0xfe, 0x12, 0x34
|
|
};
|
|
|
|
char buff[NRF24L01_MAX_PAYLOAD_LEN + 1] = "";
|
|
|
|
/* polled file descr */
|
|
|
|
static struct pollfd pfds[N_PFDS];
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
int wireless_cfg(int fd)
|
|
{
|
|
int error = 0;
|
|
|
|
uint32_t rf = DEFAULT_RADIOFREQ;
|
|
int32_t txpow = DEFAULT_TXPOWER;
|
|
nrf24l01_datarate_t datarate = RATE_1Mbps;
|
|
nrf24l01_retrcfg_t retrcfg =
|
|
{
|
|
.count = 5,
|
|
.delay = DELAY_1000us
|
|
};
|
|
|
|
uint32_t addrwidth = NRF24L01_MAX_ADDR_LEN;
|
|
|
|
uint8_t pipes_en = (1 << 0); /* Only pipe #0 is enabled */
|
|
nrf24l01_pipecfg_t pipe0cfg;
|
|
nrf24l01_pipecfg_t *pipes_cfg[NRF24L01_PIPE_COUNT] =
|
|
{
|
|
&pipe0cfg, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
nrf24l01_state_t primrxstate;
|
|
|
|
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
|
|
primrxstate = ST_RX;
|
|
#else
|
|
primrxstate = ST_POWER_DOWN;
|
|
#endif
|
|
|
|
/* Define the pipe #0 parameters (AA enabled and dynamic payload length) */
|
|
|
|
pipe0cfg.en_aa = true;
|
|
pipe0cfg.payload_length = NRF24L01_DYN_LENGTH;
|
|
memcpy (pipe0cfg.rx_addr, defaultaddr, NRF24L01_MAX_ADDR_LEN);
|
|
|
|
/* Set radio parameters */
|
|
|
|
ioctl(fd, WLIOC_SETRADIOFREQ, (unsigned long)((uint32_t *)&rf));
|
|
ioctl(fd, WLIOC_SETTXPOWER, (unsigned long)((int32_t *)&txpow));
|
|
ioctl(fd, NRF24L01IOC_SETDATARATE,
|
|
(unsigned long)((nrf24l01_datarate_t *)&datarate));
|
|
ioctl(fd, NRF24L01IOC_SETRETRCFG,
|
|
(unsigned long)((nrf24l01_retrcfg_t *)&retrcfg));
|
|
|
|
ioctl(fd, NRF24L01IOC_SETADDRWIDTH,
|
|
(unsigned long)((uint32_t *)&addrwidth));
|
|
ioctl(fd, NRF24L01IOC_SETTXADDR, (unsigned long)((uint8_t *)&defaultaddr));
|
|
|
|
ioctl(fd, NRF24L01IOC_SETPIPESCFG,
|
|
(unsigned long)((nrf24l01_pipecfg_t **)&pipes_cfg));
|
|
ioctl(fd, NRF24L01IOC_SETPIPESENABLED,
|
|
(unsigned long)((uint8_t *)&pipes_en));
|
|
|
|
/* Enable receiver */
|
|
|
|
ioctl(fd, NRF24L01IOC_SETSTATE,
|
|
(unsigned long)((nrf24l01_state_t *)&primrxstate));
|
|
|
|
return error;
|
|
}
|
|
|
|
int wireless_open(void)
|
|
{
|
|
int fd;
|
|
|
|
fd = open(DEV_NAME, O_RDWR);
|
|
|
|
if (fd < 0)
|
|
{
|
|
perror("Cannot open nRF24L01 device");
|
|
}
|
|
else
|
|
{
|
|
wireless_cfg(fd);
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
int send_pkt(int wl_fd)
|
|
{
|
|
int ret;
|
|
int len;
|
|
|
|
/* Remove carriage return */
|
|
|
|
len = strlen(buff);
|
|
if (len > 0 && buff[len - 1] == '\n')
|
|
{
|
|
len--;
|
|
buff[len] = '\0';
|
|
}
|
|
|
|
ret = write(wl_fd, buff, len);
|
|
if (ret < 0)
|
|
{
|
|
perror("Error sending packet");
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
int retrcount;
|
|
|
|
ioctl(wl_fd, NRF24L01IOC_GETLASTXMITCOUNT,
|
|
(unsigned long)((uint32_t *)&retrcount));
|
|
printf("Packet sent successfully ! (%d retransmitted packets)\n",
|
|
retrcount);
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
int read_pkt(int wl_fd)
|
|
{
|
|
int ret;
|
|
uint32_t pipeno;
|
|
|
|
ret = read(wl_fd, buff, sizeof(buff) - 1);
|
|
if (ret < 0)
|
|
{
|
|
perror("Error reading packet\n");
|
|
return ret;
|
|
}
|
|
|
|
if (ret == 0)
|
|
{
|
|
/* Should not happen ... */
|
|
|
|
printf("Packet payload empty !\n");
|
|
return ERROR;
|
|
}
|
|
|
|
/* Get the recipient pipe #
|
|
* (for demo purpose, as here the receiving pipe can only be pipe #0...)
|
|
*/
|
|
|
|
ioctl(wl_fd, NRF24L01IOC_GETLASTPIPENO,
|
|
(unsigned long)((uint32_t *)&pipeno));
|
|
|
|
buff[ret] = '\0'; /* end the string */
|
|
printf("Message received : %s (on pipe #%" PRId32 ")\n", buff, pipeno);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void usage(void)
|
|
{
|
|
printf("nRF24L01+ wireless terminal demo.\nUsage:\n");
|
|
printf("- Type in any message ( <= 32 char length)"
|
|
" to send it to communication peer.\n");
|
|
printf("- Ctrl-C to exit.\n\n");
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
int main(int argc, FAR char *argv[])
|
|
{
|
|
int ret;
|
|
bool quit = false;
|
|
|
|
int wl_fd;
|
|
|
|
wl_fd = wireless_open();
|
|
if (wl_fd < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
usage();
|
|
|
|
pfds[0].fd = STDIN_FILENO;
|
|
pfds[0].events = POLLIN;
|
|
|
|
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
|
|
pfds[1].fd = wl_fd;
|
|
pfds[1].events = POLLIN;
|
|
#endif
|
|
|
|
while (!quit)
|
|
{
|
|
ret = poll(pfds, N_PFDS, -1);
|
|
if (ret < 0)
|
|
{
|
|
perror("Error polling console / wireless");
|
|
goto out;
|
|
}
|
|
|
|
if (pfds[0].revents & POLLIN)
|
|
{
|
|
char c;
|
|
read(STDIN_FILENO, &c, 1);
|
|
|
|
if (c < ' ')
|
|
{
|
|
/* Any non printable char -> exits */
|
|
|
|
quit = true;
|
|
}
|
|
else
|
|
{
|
|
printf("Message to send > %c", c);
|
|
fflush(stdout);
|
|
|
|
/* Prepend the initial character */
|
|
|
|
buff[0] = c;
|
|
|
|
#ifndef CONFIG_SYSTEM_READLINE
|
|
/* Use fgets if readline utility method is not enabled */
|
|
|
|
if (fgets(&buff[1], sizeof(buff) - 1, stdin) == NULL)
|
|
{
|
|
printf("ERROR: fgets failed: %d\n", errno);
|
|
goto out;
|
|
}
|
|
#else
|
|
ret = readline_stream(&buff[1], sizeof(buff) - 1,
|
|
stdin, stdout);
|
|
|
|
/* Readline normally returns the number of characters read,
|
|
* but will return EOF on end of file or if an error occurs.
|
|
* Either will cause the session to terminate.
|
|
*/
|
|
|
|
if (ret == EOF)
|
|
{
|
|
printf("ERROR: readline failed: %d\n", ret);
|
|
goto out;
|
|
}
|
|
#endif
|
|
|
|
/* Send content */
|
|
|
|
send_pkt(wl_fd);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_WL_NRF24L01_RXSUPPORT
|
|
if (!quit && (pfds[1].revents & POLLIN))
|
|
{
|
|
read_pkt(wl_fd);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
out:
|
|
close(wl_fd);
|
|
|
|
printf ("Bye !\n");
|
|
return 0;
|
|
}
|