#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#endif
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include "pi433_if.h"
#include "rf69.h"
struct pi433_instance {
struct pi433_device *device;
struct pi433_tx_cfg tx_cfg;
+
+ /* control flags */
+ bool tx_cfg_initialized;
};
/*-------------------------------------------------------------------------*/
ret = rf69_set_frequency(dev->spi, rx_cfg->frequency);
if (ret < 0)
return ret;
- ret = rf69_set_bit_rate(dev->spi, rx_cfg->bit_rate);
+ ret = rf69_set_modulation(dev->spi, rx_cfg->modulation);
if (ret < 0)
return ret;
- ret = rf69_set_modulation(dev->spi, rx_cfg->modulation);
+ ret = rf69_set_bit_rate(dev->spi, rx_cfg->bit_rate);
if (ret < 0)
return ret;
ret = rf69_set_antenna_impedance(dev->spi, rx_cfg->antenna_impedance);
ret = rf69_set_frequency(dev->spi, tx_cfg->frequency);
if (ret < 0)
return ret;
- ret = rf69_set_bit_rate(dev->spi, tx_cfg->bit_rate);
+ ret = rf69_set_modulation(dev->spi, tx_cfg->modulation);
if (ret < 0)
return ret;
- ret = rf69_set_modulation(dev->spi, tx_cfg->modulation);
+ ret = rf69_set_bit_rate(dev->spi, tx_cfg->bit_rate);
if (ret < 0)
return ret;
ret = rf69_set_deviation(dev->spi, tx_cfg->dev_frequency);
/*-------------------------------------------------------------------------*/
-static int
-pi433_start_rx(struct pi433_device *dev)
+static int pi433_start_rx(struct pi433_device *dev)
{
int retval;
/*-------------------------------------------------------------------------*/
-static int
-pi433_receive(void *data)
+static int pi433_receive(void *data)
{
struct pi433_device *dev = data;
struct spi_device *spi = dev->spi;
dev->interrupt_rx_allowed = false;
/* wait for any tx to finish */
- dev_dbg(dev->dev, "rx: going to wait for any tx to finish");
+ dev_dbg(dev->dev, "rx: going to wait for any tx to finish\n");
retval = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active);
if (retval) {
/* wait was interrupted */
return retval;
/* now check RSSI, if low wait for getting high (RSSI interrupt) */
- while (!rf69_get_flag(dev->spi, rssi_exceeded_threshold)) {
+ while (!(rf69_read_reg(spi, REG_IRQFLAGS1) & MASK_IRQFLAGS1_RSSI)) {
/* allow tx to interrupt us while waiting for high RSSI */
dev->interrupt_rx_allowed = true;
wake_up_interruptible(&dev->tx_wait_queue);
/* wait for RSSI level to become high */
- dev_dbg(dev->dev, "rx: going to wait for high RSSI level");
+ dev_dbg(dev->dev, "rx: going to wait for high RSSI level\n");
retval = wait_event_interruptible(dev->rx_wait_queue,
- rf69_get_flag(dev->spi,
- rssi_exceeded_threshold));
+ rf69_read_reg(spi, REG_IRQFLAGS1) &
+ MASK_IRQFLAGS1_RSSI);
if (retval) /* wait was interrupted */
goto abort;
dev->interrupt_rx_allowed = false;
goto abort;
}
bytes_total = dev->rx_cfg.fixed_message_length;
- dev_dbg(dev->dev, "rx: msg len set to %d by fixed length",
+ dev_dbg(dev->dev, "rx: msg len set to %d by fixed length\n",
bytes_total);
} else {
bytes_total = dev->rx_buffer_size;
- dev_dbg(dev->dev, "rx: msg len set to %d as requested by read",
+ dev_dbg(dev->dev, "rx: msg len set to %d as requested by read\n",
bytes_total);
}
goto abort;
}
dev->free_in_fifo++;
- dev_dbg(dev->dev, "rx: msg len reset to %d due to length byte",
+ dev_dbg(dev->dev, "rx: msg len reset to %d due to length byte\n",
bytes_total);
}
rf69_read_fifo(spi, &dummy, 1);
dev->free_in_fifo++;
- dev_dbg(dev->dev, "rx: address byte stripped off");
+ dev_dbg(dev->dev, "rx: address byte stripped off\n");
}
/* get payload */
while (dev->rx_position < bytes_total) {
- if (!rf69_get_flag(dev->spi, payload_ready)) {
+ if (!(rf69_read_reg(spi, REG_IRQFLAGS2) & MASK_IRQFLAGS2_PAYLOAD_READY)) {
retval = wait_event_interruptible(dev->fifo_wait_queue,
dev->free_in_fifo < FIFO_SIZE);
if (retval) /* wait was interrupted */
return bytes_total;
}
-static int
-pi433_tx_thread(void *data)
+static int pi433_tx_thread(void *data)
{
struct pi433_device *device = data;
struct spi_device *spi = device->spi;
while (1) {
/* wait for fifo to be populated or for request to terminate*/
- dev_dbg(device->dev, "thread: going to wait for new messages");
+ dev_dbg(device->dev, "thread: going to wait for new messages\n");
wait_event_interruptible(device->tx_wait_queue,
(!kfifo_is_empty(&device->tx_fifo) ||
kthread_should_stop()));
retval = kfifo_out(&device->tx_fifo, &tx_cfg, sizeof(tx_cfg));
if (retval != sizeof(tx_cfg)) {
dev_dbg(device->dev,
- "reading tx_cfg from fifo failed: got %d byte(s), expected %d",
+ "reading tx_cfg from fifo failed: got %d byte(s), expected %d\n",
retval, (unsigned int)sizeof(tx_cfg));
continue;
}
retval = kfifo_out(&device->tx_fifo, &size, sizeof(size_t));
if (retval != sizeof(size_t)) {
dev_dbg(device->dev,
- "reading msg size from fifo failed: got %d, expected %d",
+ "reading msg size from fifo failed: got %d, expected %d\n",
retval, (unsigned int)sizeof(size_t));
continue;
}
retval = kfifo_out(&device->tx_fifo, &device->buffer[position],
sizeof(device->buffer) - position);
dev_dbg(device->dev,
- "read %d message byte(s) from fifo queue.", retval);
+ "read %d message byte(s) from fifo queue.\n", retval);
/*
* if rx is active, we need to interrupt the waiting for
/* we are done. Wait for packet to get sent */
dev_dbg(device->dev,
- "thread: wait for packet to get sent/fifo to be empty");
+ "thread: wait for packet to get sent/fifo to be empty\n");
wait_event_interruptible(device->fifo_wait_queue,
device->free_in_fifo == FIFO_SIZE ||
kthread_should_stop());
return 0;
/* STOP_TRANSMISSION */
- dev_dbg(device->dev, "thread: Packet sent. Set mode to stby.");
+ dev_dbg(device->dev, "thread: Packet sent. Set mode to stby.\n");
retval = rf69_set_mode(spi, standby);
if (retval < 0)
goto abort;
if (count > MAX_MSG_SIZE)
return -EMSGSIZE;
+ /*
+ * check if tx_cfg has been initialized otherwise we won't be able to
+ * config the RF trasmitter correctly due to invalid settings
+ */
+ if (!instance->tx_cfg_initialized) {
+ dev_notice_once(device->dev,
+ "write: failed due to unconfigured tx_cfg (see PI433_IOC_WR_TX_CFG)\n");
+ return -EINVAL;
+ }
+
/*
* write the following sequence into fifo:
* - tx_cfg
required = sizeof(instance->tx_cfg) + sizeof(size_t) + count;
available = kfifo_avail(&device->tx_fifo);
if (required > available) {
- dev_dbg(device->dev, "write to fifo failed: %d bytes required but %d available",
+ dev_dbg(device->dev, "write to fifo failed: %d bytes required but %d available\n",
required, available);
mutex_unlock(&device->tx_fifo_lock);
return -EAGAIN;
/* start transfer */
wake_up_interruptible(&device->tx_wait_queue);
- dev_dbg(device->dev, "write: generated new msg with %d bytes.", copied);
+ dev_dbg(device->dev, "write: generated new msg with %d bytes.\n", copied);
return copied;
abort:
dev_warn(device->dev,
- "write to fifo failed, non recoverable: 0x%x", retval);
+ "write to fifo failed, non recoverable: 0x%x\n", retval);
mutex_unlock(&device->tx_fifo_lock);
return -EAGAIN;
}
-static long
-pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static long pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct pi433_instance *instance;
struct pi433_device *device;
return -EFAULT;
mutex_lock(&device->tx_fifo_lock);
memcpy(&instance->tx_cfg, &tx_cfg, sizeof(struct pi433_tx_cfg));
+ instance->tx_cfg_initialized = true;
mutex_unlock(&device->tx_fifo_lock);
break;
case PI433_IOC_RD_RX_CFG:
/* setup instance data*/
instance->device = device;
- instance->tx_cfg.bit_rate = 4711;
- // TODO: fill instance->tx_cfg;
/* instance data as context */
filp->private_data = instance;
if (device->gpiod[i] == ERR_PTR(-ENOENT)) {
dev_dbg(&device->spi->dev,
- "Could not find entry for %s. Ignoring.", name);
+ "Could not find entry for %s. Ignoring.\n", name);
continue;
}
if (device->gpiod[i] == ERR_PTR(-EBUSY))
- dev_dbg(&device->spi->dev, "%s is busy.", name);
+ dev_dbg(&device->spi->dev, "%s is busy.\n", name);
if (IS_ERR(device->gpiod[i])) {
retval = PTR_ERR(device->gpiod[i]);
if (retval)
return retval;
- dev_dbg(&device->spi->dev, "%s successfully configured", name);
+ dev_dbg(&device->spi->dev, "%s successfully configured\n", name);
}
return 0;
.llseek = no_llseek,
};
+static int pi433_debugfs_regs_show(struct seq_file *m, void *p)
+{
+ struct pi433_device *dev;
+ u8 reg_data[114];
+ int i;
+ char *fmt = "0x%02x, 0x%02x\n";
+ int ret;
+
+ dev = m->private;
+
+ mutex_lock(&dev->tx_fifo_lock);
+ mutex_lock(&dev->rx_lock);
+
+ // wait for on-going operations to finish
+ ret = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active);
+ if (ret)
+ goto out_unlock;
+
+ ret = wait_event_interruptible(dev->tx_wait_queue, !dev->rx_active);
+ if (ret)
+ goto out_unlock;
+
+ // skip FIFO register (0x0) otherwise this can affect some of uC ops
+ for (i = 1; i < 0x50; i++)
+ reg_data[i] = rf69_read_reg(dev->spi, i);
+
+ reg_data[REG_TESTLNA] = rf69_read_reg(dev->spi, REG_TESTLNA);
+ reg_data[REG_TESTPA1] = rf69_read_reg(dev->spi, REG_TESTPA1);
+ reg_data[REG_TESTPA2] = rf69_read_reg(dev->spi, REG_TESTPA2);
+ reg_data[REG_TESTDAGC] = rf69_read_reg(dev->spi, REG_TESTDAGC);
+ reg_data[REG_TESTAFC] = rf69_read_reg(dev->spi, REG_TESTAFC);
+
+ seq_puts(m, "# reg, val\n");
+
+ for (i = 1; i < 0x50; i++)
+ seq_printf(m, fmt, i, reg_data[i]);
+
+ seq_printf(m, fmt, REG_TESTLNA, reg_data[REG_TESTLNA]);
+ seq_printf(m, fmt, REG_TESTPA1, reg_data[REG_TESTPA1]);
+ seq_printf(m, fmt, REG_TESTPA2, reg_data[REG_TESTPA2]);
+ seq_printf(m, fmt, REG_TESTDAGC, reg_data[REG_TESTDAGC]);
+ seq_printf(m, fmt, REG_TESTAFC, reg_data[REG_TESTAFC]);
+
+out_unlock:
+ mutex_unlock(&dev->rx_lock);
+ mutex_unlock(&dev->tx_fifo_lock);
+
+ return ret;
+}
+
+static int pi433_debugfs_regs_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, pi433_debugfs_regs_show, inode->i_private);
+}
+
+static const struct file_operations debugfs_fops = {
+ .llseek = seq_lseek,
+ .open = pi433_debugfs_regs_open,
+ .owner = THIS_MODULE,
+ .read = seq_read,
+ .release = single_release
+};
+
/*-------------------------------------------------------------------------*/
static int pi433_probe(struct spi_device *spi)
{
struct pi433_device *device;
int retval;
+ struct dentry *entry;
/* setup spi parameters */
spi->mode = 0x00;
}
dev_dbg(&spi->dev,
- "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed",
+ "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed\n",
spi->mode, spi->bits_per_word, spi->max_speed_hz);
- /* Ping the chip by reading the version register */
- retval = spi_w8r8(spi, 0x10);
+ /* read chip version */
+ retval = rf69_get_version(spi);
if (retval < 0)
return retval;
switch (retval) {
case 0x24:
- dev_dbg(&spi->dev, "found pi433 (ver. 0x%x)", retval);
+ dev_dbg(&spi->dev, "found pi433 (ver. 0x%x)\n", retval);
break;
default:
- dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval);
+ dev_dbg(&spi->dev, "unknown chip version: 0x%x\n", retval);
return -ENODEV;
}
/* setup GPIO (including irq_handler) for the different DIOs */
retval = setup_gpio(device);
if (retval) {
- dev_dbg(&spi->dev, "setup of GPIOs failed");
+ dev_dbg(&spi->dev, "setup of GPIOs failed\n");
goto GPIO_failed;
}
/* determ minor number */
retval = pi433_get_minor(device);
if (retval) {
- dev_dbg(&spi->dev, "get of minor number failed");
+ dev_dbg(&spi->dev, "get of minor number failed\n");
goto minor_failed;
}
"pi433.%d_tx_task",
device->minor);
if (IS_ERR(device->tx_task_struct)) {
- dev_dbg(device->dev, "start of send thread failed");
+ dev_dbg(device->dev, "start of send thread failed\n");
retval = PTR_ERR(device->tx_task_struct);
goto send_thread_failed;
}
/* create cdev */
device->cdev = cdev_alloc();
if (!device->cdev) {
- dev_dbg(device->dev, "allocation of cdev failed");
+ dev_dbg(device->dev, "allocation of cdev failed\n");
retval = -ENOMEM;
goto cdev_failed;
}
cdev_init(device->cdev, &pi433_fops);
retval = cdev_add(device->cdev, device->devt, 1);
if (retval) {
- dev_dbg(device->dev, "register of cdev failed");
+ dev_dbg(device->dev, "register of cdev failed\n");
goto del_cdev;
}
/* spi setup */
spi_set_drvdata(spi, device);
+ entry = debugfs_create_dir(dev_name(device->dev),
+ debugfs_lookup(KBUILD_MODNAME, NULL));
+ debugfs_create_file("regs", 0400, entry, device, &debugfs_fops);
+
return 0;
del_cdev:
static void pi433_remove(struct spi_device *spi)
{
struct pi433_device *device = spi_get_drvdata(spi);
+ struct dentry *mod_entry = debugfs_lookup(KBUILD_MODNAME, NULL);
+
+ debugfs_remove(debugfs_lookup(dev_name(device->dev), mod_entry));
/* free GPIOs */
free_gpio(device);
return PTR_ERR(pi433_class);
}
+ debugfs_create_dir(KBUILD_MODNAME, NULL);
+
status = spi_register_driver(&pi433_spi_driver);
if (status < 0) {
class_destroy(pi433_class);
spi_unregister_driver(&pi433_spi_driver);
class_destroy(pi433_class);
unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+ debugfs_remove_recursive(debugfs_lookup(KBUILD_MODNAME, NULL));
}
module_exit(pi433_exit);