wireless/nrf24l01: Implement common RF IOCTLs and fix missing register reads.

Update the nrf24l01_ioctl function to fully comply with the common wireless
character driver interface defined in nuttx/wireless/ioctl.h, and complete
previously unimplemented device-specific commands.

* Add support for WLIOC_SETRADIOFREQ and WLIOC_GETRADIOFREQ with
  quantitative conversion between Hz (API) and MHz (Hardware).
* Add support for WLIOC_SETTXPOWER, WLIOC_GETTXPOWER, WLIOC_SETFINEPOWER,
  and WLIOC_GETFINEPOWER.
* Add WLIOC_SETMODU and WLIOC_GETMODU, strictly enforcing WLIOC_GFSK
  modulation as required by the nRF24L01 physical layer.
* Map WLIOC_SETADDR and WLIOC_GETADDR to the existing TX address routines.
* Resolve -ENOSYS in NRF24L01IOC_GETRETRCFG by reading the
  NRF24L01_SETUP_RETR register and decoding ARD/ARC shift bits.
* Resolve -ENOSYS in NRF24L01IOC_GETDATARATE by parsing RF_DR_LOW and
  RF_DR_HIGH bits from the NRF24L01_RF_SETUP register.

Signed-off-by: Chip L. <chplee@gmail.com>
This commit is contained in:
Chip L.
2026-03-01 05:47:53 +08:00
committed by Alan C. Assis
parent 2dae11461d
commit 47c7169825

View File

@@ -1116,27 +1116,31 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
switch (cmd) switch (cmd)
{ {
case WLIOC_SETRADIOFREQ: /* Set radio frequency. Arg: Pointer to /* --- Common Wireless IOCTLs --- */
* uint32_t frequency value */
case WLIOC_SETRADIOFREQ:
{ {
FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
DEBUGASSERT(ptr != NULL); DEBUGASSERT(ptr != NULL);
nrf24l01_setradiofreq(dev, *ptr); /* Convert Hz from ioctl to MHz for the underlying function */
nrf24l01_setradiofreq(dev, *ptr / 1000000);
} }
break; break;
case WLIOC_GETRADIOFREQ: /* Get current radio frequency. arg: Pointer case WLIOC_GETRADIOFREQ:
* to uint32_t frequency value */
{ {
FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg); FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
DEBUGASSERT(ptr != NULL); DEBUGASSERT(ptr != NULL);
*ptr = nrf24l01_getradiofreq(dev);
/* Convert MHz from the underlying function to Hz for ioctl */
*ptr = nrf24l01_getradiofreq(dev) * 1000000;
} }
break; break;
case NRF24L01IOC_SETTXADDR: /* Set current TX addr. arg: Pointer to case WLIOC_SETADDR:
* uint8_t array defining the address */
{ {
FAR const uint8_t *addr = (FAR const uint8_t *)(arg); FAR const uint8_t *addr = (FAR const uint8_t *)(arg);
DEBUGASSERT(addr != NULL); DEBUGASSERT(addr != NULL);
@@ -1144,8 +1148,7 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case NRF24L01IOC_GETTXADDR: /* Get current TX addr. arg: Pointer to case WLIOC_GETADDR:
* uint8_t array defining the address */
{ {
FAR uint8_t *addr = (FAR uint8_t *)(arg); FAR uint8_t *addr = (FAR uint8_t *)(arg);
DEBUGASSERT(addr != NULL); DEBUGASSERT(addr != NULL);
@@ -1153,8 +1156,7 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case WLIOC_SETTXPOWER: /* Set current radio frequency. arg: Pointer case WLIOC_SETTXPOWER:
* to int32_t, output power */
{ {
FAR int32_t *ptr = (FAR int32_t *)(arg); FAR int32_t *ptr = (FAR int32_t *)(arg);
DEBUGASSERT(ptr != NULL); DEBUGASSERT(ptr != NULL);
@@ -1162,8 +1164,7 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case WLIOC_GETTXPOWER: /* Get current radio frequency. arg: Pointer case WLIOC_GETTXPOWER:
* to int32_t, output power */
{ {
FAR int32_t *ptr = (FAR int32_t *)(arg); FAR int32_t *ptr = (FAR int32_t *)(arg);
DEBUGASSERT(ptr != NULL); DEBUGASSERT(ptr != NULL);
@@ -1171,8 +1172,55 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case NRF24L01IOC_SETRETRCFG: /* Set retransmit params. arg: Pointer case WLIOC_SETFINEPOWER:
* to nrf24l01_retrcfg_t */ {
FAR int32_t *ptr = (FAR int32_t *)(arg);
DEBUGASSERT(ptr != NULL);
/* Convert from 0.01 dBm to standard dBm */
nrf24l01_settxpower(dev, *ptr / 100);
}
break;
case WLIOC_GETFINEPOWER:
{
FAR int32_t *ptr = (FAR int32_t *)(arg);
DEBUGASSERT(ptr != NULL);
/* Convert from standard dBm to 0.01 dBm */
*ptr = nrf24l01_gettxpower(dev) * 100;
}
break;
case WLIOC_SETMODU:
{
FAR enum wlioc_modulation_e *ptr =
(FAR enum wlioc_modulation_e *)(arg);
DEBUGASSERT(ptr != NULL);
/* nRF24L01 only supports GFSK modulation natively */
if (*ptr != WLIOC_GFSK)
{
ret = -EINVAL;
}
}
break;
case WLIOC_GETMODU:
{
FAR enum wlioc_modulation_e *ptr =
(FAR enum wlioc_modulation_e *)(arg);
DEBUGASSERT(ptr != NULL);
*ptr = WLIOC_GFSK;
}
break;
/* --- nRF24L01 Specific IOCTLs --- */
case NRF24L01IOC_SETRETRCFG:
{ {
FAR nrf24l01_retrcfg_t *ptr = (FAR nrf24l01_retrcfg_t *)(arg); FAR nrf24l01_retrcfg_t *ptr = (FAR nrf24l01_retrcfg_t *)(arg);
DEBUGASSERT(ptr != NULL); DEBUGASSERT(ptr != NULL);
@@ -1180,9 +1228,19 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case NRF24L01IOC_GETRETRCFG: /* Get retransmit params. arg: Pointer case NRF24L01IOC_GETRETRCFG:
* to nrf24l01_retrcfg_t */ {
ret = -ENOSYS; /* TODO */ FAR nrf24l01_retrcfg_t *ptr = (FAR nrf24l01_retrcfg_t *)(arg);
uint8_t val;
DEBUGASSERT(ptr != NULL);
nrf24l01_lock(dev->spi);
val = nrf24l01_readregbyte(dev, NRF24L01_SETUP_RETR);
nrf24l01_unlock(dev->spi);
ptr->delay = (val >> NRF24L01_ARD_SHIFT) & 0x0f;
ptr->count = (val >> NRF24L01_ARC_SHIFT) & 0x0f;
}
break; break;
case NRF24L01IOC_SETPIPESCFG: case NRF24L01IOC_SETPIPESCFG:
@@ -1251,14 +1309,34 @@ static int nrf24l01_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{ {
FAR nrf24l01_datarate_t *drp = (FAR nrf24l01_datarate_t *)(arg); FAR nrf24l01_datarate_t *drp = (FAR nrf24l01_datarate_t *)(arg);
DEBUGASSERT(drp != NULL); DEBUGASSERT(drp != NULL);
nrf24l01_setdatarate(dev, *drp); nrf24l01_setdatarate(dev, *drp);
break; break;
} }
case NRF24L01IOC_GETDATARATE: case NRF24L01IOC_GETDATARATE:
ret = -ENOSYS; /* TODO */ {
break; FAR nrf24l01_datarate_t *drp = (FAR nrf24l01_datarate_t *)(arg);
uint8_t val;
DEBUGASSERT(drp != NULL);
nrf24l01_lock(dev->spi);
val = nrf24l01_readregbyte(dev, NRF24L01_RF_SETUP);
nrf24l01_unlock(dev->spi);
if (val & NRF24L01_RF_DR_LOW)
{
*drp = RATE_250kbps;
}
else if (val & NRF24L01_RF_DR_HIGH)
{
*drp = RATE_2Mbps;
}
else
{
*drp = RATE_1Mbps;
}
break;
}
case NRF24L01IOC_SETADDRWIDTH: case NRF24L01IOC_SETADDRWIDTH:
{ {