Re: Submit of a driver for Pi433 - a radio module for Raspberry Pi

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!
 
Ok. Thanks for the info. Didn't observe that.
 I'll give the old patch another try.
 
I will send a new patch as soon, as I know. how to produce the 
poper format (with subjects, signing and so on).

Cheers,

Marcus

 
 
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 268d4e6..fdf060c 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -110,4 +110,6 @@ source "drivers/staging/ccree/Kconfig"
 
 source "drivers/staging/typec/Kconfig"
 
+source "drivers/staging/pi433/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index b93e6f5..998f644 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_KS7010)        += ks7010/
 obj-$(CONFIG_GREYBUS)        += greybus/
 obj-$(CONFIG_BCM2835_VCHIQ)    += vc04_services/
 obj-$(CONFIG_CRYPTO_DEV_CCREE)    += ccree/
+obj-$(CONFIG_PI433)        += pi433/
diff --git a/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts
b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts
new file mode 100644
index 0000000..004b502
--- /dev/null
+++ b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts
@@ -0,0 +1,53 @@
+// Definitions for Pi433
+/dts-v1/;
+/plugin/;
+
+/ {
+        compatible = "bcm,bcm2835", "bcm,bcm2708", "bcm,bcm2709";
+
+        fragment@0 {
+                target = <&spi0>;
+                __overlay__ {
+                        status = "okay";
+
+                        spidev@0{
+                                status = "disabled";
+                        };
+
+                        spidev@1{
+                                status = "disabled";
+                        };
+                };
+        };
+
+    fragment@1 {
+        target = <&gpio>;
+        __overlay__ {
+            pi433_pins: pi433_pins {
+                brcm,pins = <7 25 24>;
+                brcm,function = <0 0 0>; // in in in
+            };
+        };
+    };
+
+    fragment@2 {
+        target = <&spi0>;
+        __overlay__ {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            status = "okay";
+
+            pi433: pi433@0 {
+                compatible = "Smarthome-Wolf,pi433";
+                reg = <0>;
+                spi-max-frequency = <10000000>;
+                status = "okay";
+
+                pinctrl-0 = <&pi433_pins>;
+                DIO0-gpio = <&gpio 24 0>;
+                DIO1-gpio = <&gpio 25 0>;
+                DIO2-gpio = <&gpio  7 0>;
+            };
+        };
+    };
+};
diff --git a/drivers/staging/pi433/Documentation/devicetree/pi433.txt
b/drivers/staging/pi433/Documentation/devicetree/pi433.txt
new file mode 100644
index 0000000..14197c6
--- /dev/null
+++ b/drivers/staging/pi433/Documentation/devicetree/pi433.txt
@@ -0,0 +1,62 @@
+* Smarthome-Wolf Pi433 - a 433MHz radio module/shield for Raspberry Pi (see
www.pi433.de)
+
+Required properties:
+- compatible: must be "Smarthome-Wolf,pi433"
+- reg: chip select of SPI Interface
+- DIOx-gpio must be dedicated to the GPIO, connected with DIOx of the RFM69
module
+
+
+Example:
+
+With the following lines in gpio-section, the gpio pins, connected with pi433
are
+reserved/declared.
+
+&gpio{
+    [...]
+
+    pi433_pins: pi433_pins {
+        brcm,pins = <7 25 24>;
+        brcm,function = <0 0 0>; // in in in
+    };
+
+    [...]
+}
+
+With the following lines in spi section, the device pi433 is declared.
+It consists of the three gpio pins and an spi interface (here chip select 0)
+
+&spi0{
+    [...]
+
+    pi433: pi433@0 {
+        compatible = "Smarthome-Wolf,pi433";
+        reg = <0>; /* CE 0 */
+        #address-cells = <1>;
+        #size-cells = <0>;
+        spi-max-frequency = <10000000>;
+
+        pinctrl-0 = <&pi433_pins>;
+        DIO0-gpio = <&gpio 24 0>;
+        DIO1-gpio = <&gpio 25 0>;
+        DIO2-gpio = <&gpio  7 0>;
+    };
+}
+
+
+
+For Raspbian users only
+=======================
+Since Raspbian supports device tree overlays, you may use and overlay, instead
+of editing your boards device tree.
+For using the overlay, you need to compile the file pi433-overlay.dts you can
+find aside to this documentation.
+The file needs to be compiled - either manually or by integration in your
kernel
+source tree. For a manual compile, you may use a command line like the
following:
+'linux/scripts/dtc/dtc -@ -I dts -O dtb -o pi433.dtbo pi433-overlay.dts'
+
+For compiling inside of the kernel tree, you need to copy pi433-overlay.dts to
+arch/arm/boot/dts/overlays and you need to add the file to the list of files
+in the Makefile over there. Execute 'make dtbs' in kernel tree root to make the
+kernel make files compile the device tree overlay for you.
+
+
diff --git a/drivers/staging/pi433/Documentation/pi433.txt
b/drivers/staging/pi433/Documentation/pi433.txt
new file mode 100644
index 0000000..860dd0f
--- /dev/null
+++ b/drivers/staging/pi433/Documentation/pi433.txt
@@ -0,0 +1,274 @@
+=====
+Pi433
+=====
+
+
+Introduction
+============
+This driver is for controlling pi433, a radio module for the Raspberry Pi
+(www.pi433.de). It supports transmission and reception. It can be opened
+by multiple applications for transmission and reception. While transmit
+jobs were queued and process automatically in the background, the first  
+application asking for reception will block out all other applications  
+until something gets received terminates the read request.  
+The driver supports on the fly reloading of the hardware fifo of the rf
+chip, thus enabling for much longer telegrams then hardware fifo size.
+
+Discription of driver operation
+===============================
+
+a) transmission
+
+Each transmission can take place with a different configuration of the rf
+module. Therfore each application can set its own set of parameters. The driver
+takes care, that each transmission takes place with the parameterset of the
+application, that requests the transmission. To allow the transmission to take
+place in the background, a tx thread is introduced.
+The transfer of data from the main thread to the tx thread is realised by a
+kfifo. With each write request of an application, the passed in data and the
+corresponding parameter set gets written to the kfifo.  
+On the other "side" of the kfifo, the tx thread continuously checks, whether
the
+kfifo is empty. If not, it gets one set of config and data from the kfifo. If  
+there is no receive request or the receiver is still waiting for something in
+the air, the rf module is set to standby, the parameters for transmission gets
+set, the hardware fifo of the rf chip gets preloaded and the transmission gets
+started. Upon hardware fifo threshold interrupt it gets reloaded, thus enabling
+much longer telegrams then hardware fifo size. If the telegram is send and
there
+is more data available in the kfifo, the procedure is repeated. If not the
+transmission cycle ends.
+
+b) reception
+
+Since there is only one application allowed to receive data at a time, for
+reception there is only one configuration set.
+As soon as an application sets an request for receiving a telegram, the
reception
+configuration set is written to the rf module and it gets set into receiving
mode.  
+Now the driver is waiting, that a predefined RSSI level (signal strength at the
+receiver) is reached. Until this hasn't happened, the reception can be
+interrupted by the transmission thread at any time to insert a transmission
cycle.
+As soon as the predefined RSSI level is meat, a receiving cycle starts. Similar
+as described for the transmission cycle the read out of the hardware fifo is
done
+dynamically. Upon each hardware fifo threshold interrupt, a portion of data
gets
+read. So also for reception it is possible to receive more data then the
hardware
+fifo can hold.
+
+
+Driver API
+==========
+
+The driver is currently implemented as a character device. Therefore it
supports
+the calls open, ioctl, read, write and close.
+
+
+params for ioctl
+----------------
+
+There are four options:  
+PI433_IOC_RD_TX_CFG - get the transmission parameters from the driver
+PI433_IOC_WR_TX_CFG - set the transmission parameters
+PI433_IOC_RD_RX_CFG - get the receiving parameters from the driver
+PI433_IOC_WR_RX_CFG - set the receiving parameters  
+
+The tx configuration is transfered via struct pi433_tx_cfg, the parameterset
for transmission.  
+It is devided into two sections: rf parameters and packet format.
+
+rf params:
+    frequency
+        frequency used for transmission.  
+        Allowed values: 433050000...434790000
+    bit_rate
+        bit rate used for transmission.  
+        Allowed values: #####
+    dev_frequency
+        frequency deviation in case of FSK.  
+        Allowed values: 600...500000
+    modulation
+        FSK - frequency shift key
+        OOK - On-Off-key
+    modShaping
+        shapingOff    - no shaping
+        shaping1_0    - gauss filter with BT 1 (FSK only)
+        shaping0_5    - gauss filter with BT 0.5 (FSK only)
+        shaping0_3    - gauss filter with BT 0.3 (FSK only)
+        shapingBR    - filter cut off at BR (OOK only)
+        shaping2BR    - filter cut off at 2*BR (OOK only)
+    paRamp (FSK only)
+        ramp3400    - amp ramps up in 3.4ms
+        ramp2000    - amp ramps up in 2.0ms
+        ramp1000    - amp ramps up in 1ms
+        ramp500        - amp ramps up in 500us
+        ramp250        - amp ramps up in 250us
+        ramp125        - amp ramps up in 125us
+        ramp100        - amp ramps up in 100us
+        ramp62        - amp ramps up in 62us
+        ramp50        - amp ramps up in 50us
+        ramp40        - amp ramps up in 40us
+        ramp31        - amp ramps up in 31us
+        ramp25        - amp ramps up in 25us
+        ramp20        - amp ramps up in 20us
+        ramp15        - amp ramps up in 15us
+        ramp12        - amp ramps up in 12us
+        ramp10        - amp ramps up in 10us
+    tx_start_condition
+        fifoLevel    - transmission starts, if fifo is filled to
+                  threshold level
+        fifoNotEmpty    - transmission starts, as soon as there is one
+                  byte in internal fifo
+    repetitions
+        This gives the option, to send a telegram multiple times. Default: 1
+
+packet format:
+    enable_preamble
+        optionOn    - a preamble will be automatically generated
+        optionOff    - no preamble will be generated
+    enable_sync
+        optionOn    - a sync word will be automatically added to
+                  the telegram after preamble
+        optionOff    - no sync word will be added
+        Attention: While possible to generate sync without preamble, the
+        receiver won't be able to detect the sync without preamble.
+    enable_length_byte
+        optionOn    - the length of the telegram will be automatically
+                  added to the telegram. It's part of the payload
+        optionOff    - no length information will be automatically added
+                  to the telegram.
+        Attention: For telegram length over 255 bytes, this option can't be
used
+        Attention: should be used in combination with sync, only
+    enable_address_byte
+        optionOn    - the address byte will be automatically added to the
+                  telgram. It's part of the payload
+        optionOff    - the address byte will not be added to the telegram.
+        The address byte can be used for address filtering, so the receiver
+        will only receive telegrams with a given address byte.
+        Attention: should be used in combination with sync, only
+    enable_crc
+        optionOn    - an crc will be automatically calculated over the
+                  payload of the telegram and added to the telegram
+                  after payload.
+        optionOff    - no crc will be calculated        
+    preamble_length
+        length of the preamble. Allowed values: 0...65536
+    sync_length
+        length of the sync word. Allowed values: 0...8
+    fixed_message_length
+        length of the payload of the telegram. Will override the length
+        given by the buffer, passed in with the write command. Will be
+        ignored if set to zero.
+    sync_pattern[8]
+        contains up to eight values, that are used as the sync pattern
+        on sync option
+    address_byte
+        one byte, used as address byte on address byte option.
+
+
+The rx configuration is transfered via struct pi433_rx_cfg, the parameterset
for receiving. It is devided into two sections: rf parameters and packet format.
+
+rf params:
+    frequency
+        frequency used for transmission.  
+        Allowed values: 433050000...434790000
+    bit_rate
+        bit rate used for transmission.
+        Allowed values: #####
+    dev_frequency
+        frequency deviation in case of FSK.
+        Allowed values: 600...500000
+    modulation
+        FSK - frequency shift key
+        OOK - on off key
+    rssi_threshold
+        threshold value for the signal strength on the receiver input.
+        If this value is exeeded, a reception cycle starts
+        Allowed values: 0...255
+    thresholdDecrement
+        in order to adapt to different levels of singnal strength, over
+        time the receiver gets more and more sensitive. This value  
+        determs, how fast the sensitivity increases.
+        step_0_5db    - increase in 0,5dB steps
+        step_1_0db    - increase in 1 db steps
+        step_1_5db    - increase in 1,5dB steps
+        step_2_0db    - increase in 2 db steps
+        step_3_0db    - increase in 3 db steps
+        step_4_0db    - increase in 4 db steps
+        step_5_0db    - increase in 5 db steps
+        step_6_0db    - increase in 6 db steps
+    antennaImpedance
+        sets the electrical adoption of the antenna
+        fiftyOhm    - for antennas with an impedance of 50Ohm
+        twohundretOhm    - for antennas with an impedance of 200Ohm
+    lnaGain
+        sets the gain of the low noise amp
+        automatic    - lna gain is determed by an agc
+        max        - lna gain is set to maximum
+        maxMinus6    - lna gain is set to  6db below max
+        maxMinus12    - lna gain is set to 12db below max
+        maxMinus24    - lna gain is set to 24db below max
+        maxMinus36    - lna gain is set to 36db below max
+        maxMinus48    - lna gain is set to 48db below max
+    bw_mantisse
+        sets the bandwidth of the channel filter - part one: mantisse.  
+        mantisse16    - mantisse is set to 16
+        mantisse20    - mantisse is set to 20
+        mantisse24    - mantisse is set to 24
+    bw_exponent
+        sets the bandwidth of the channel filter - part two: exponent.  
+        Allowd values: 0...7
+    dagc;
+        operation mode of the digital automatic gain control
+        normalMode
+        improve
+        improve4LowModulationIndex
+
+ packet format:
+    enable_sync
+        optionOn  - sync detection is enabled. If configured sync pattern
+                isn't found, telegram will be internally discarded  
+        optionOff - sync detection is disabled.
+    enable_length_byte
+        optionOn   - First byte of payload will be used as length byte,  
+                 regardless of the amount of bytes that were requested  
+                 by the read request.
+        optionOff  - Number of bytes to be read will be set according to
+                 amount of bytes that were requested by the read request.
+        Attention: should be used in combination with sync, only
+    enable_address_filtering;
+        filteringOff        - no adress filtering will take place
+        nodeAddress        - all telegrams, not matching the node  
+                      address will be internally discarded
+        nodeOrBroadcastAddress    - all telegrams, neither matching the
+                      node, nor the broadcast address will
+                      be internally discarded
+        Attention: Sync option must be enabled in order to use this feature
+    enable_crc
+        optionOn    - a crc will be calculated over the payload of
+                  the telegram, that was received. If the
+                  calculated crc doesn't match to two bytes,
+                  that follow the payload, the telegram will be
+                  internally discarded.
+        Attention: This option is only operational, if sync on and fixed length
+        or length byte is used
+    sync_length
+        Gives the length of the payload.  
+        Attention: This setting must meet the setting of the transmitter,
+        if sync option is used.
+    fixed_message_length
+        Overrides the telegram length either given by the first byte of
+        payload or by the read request.
+    bytes_to_drop
+        gives the number of bytes, that will be dropped before transfering
+        data to the read buffer
+        This option is only usefull, if all packet helper are switched
+        off and the rf chip is used in raw receiving mode. This may be
+        needed, if a telegram of a third party device should be received,
+        using a protocol not compatible with the packet engine of the rf69
chip.
+    sync_pattern[8]
+        contains up to eight values, that are used as the sync pattern
+        on sync option.
+        This setting must meet the configuration of the transmitting device,
+        if sync option is enabled.
+    node_address
+        one byte, used as node address byte on address byte option.
+    broadcast_address
+        one byte, used as broadcast address byte on address byte option.
+        
+
diff --git a/drivers/staging/pi433/Kconfig b/drivers/staging/pi433/Kconfig
new file mode 100644
index 0000000..61b4b4e
--- /dev/null
+++ b/drivers/staging/pi433/Kconfig
@@ -0,0 +1,16 @@
+config PI433
+        tristate "Pi433 - a 433MHz radio module for Raspberry Pi"
+        default n
+        ---help---
+          This option allows you to enable support for the radio module Pi433.
+
+          Pi433 is a shield that fits onto the GPIO header of a Raspberry Pi
+          or compatible. It extends the Raspberry Pi with the option, to
+          send and receive data in the 433MHz ISM band - for example to
+          communicate between two systems without using ethernet or bluetooth
+          or for control or read sockets, actors, sensors, widely available
+          for low price.
+
+          For details or the option to buy, please visit
https://pi433.de/en.html
+
+          If in doubt, say N here, but saying yes most probably won't hurt
diff --git a/drivers/staging/pi433/Makefile b/drivers/staging/pi433/Makefile
new file mode 100644
index 0000000..417f3e4
--- /dev/null
+++ b/drivers/staging/pi433/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_PI433) += pi433.o
+
+pi433-objs := pi433_if.o rf69.o
diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c
new file mode 100644
index 0000000..57edf91
--- /dev/null
+++ b/drivers/staging/pi433/pi433_if.c
@@ -0,0 +1,1315 @@
+/*
+ * userspace interface for pi433 radio module
+ *
+ * Pi433 is a 433MHz radio module for the Raspberry Pi.
+ * It is based on the HopeRf Module RFM69CW. Therefore inside of this
+ * driver, you'll find an abstraction of the rf69 chip.
+ *
+ * If needed, this driver could be extended, to also support other
+ * devices, basing on HopeRfs rf69.
+ *
+ * The driver can also be extended, to support other modules of
+ * HopeRf with a similar interace - e. g. RFM69HCW, RFM12, RFM95, ...
+ *
+ * Copyright (C) 2016 Wolf-Entwicklungen
+ *    Marcus Wolf <linux@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#undef DEBUG
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/idr.h>
+#include <linux/ioctl.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/err.h>
+#include <linux/kfifo.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/spi/spi.h>
+#ifdef CONFIG_COMPAT
+#include <asm/compat.h>
+#endif
+
+#include "pi433_if.h"
+#include "rf69.h"
+
+
+#define N_PI433_MINORS            (1U << MINORBITS) /*32*/    /* ... up to 256
*/
+#define MAX_MSG_SIZE            900    /* min: FIFO_SIZE! */
+#define MSG_FIFO_SIZE            65536   /* 65536 = 2^16  */
+#define NUM_DIO                2
+
+static dev_t pi433_dev;
+static DEFINE_IDR(pi433_idr);
+static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */
+
+static struct class *pi433_class; /* mainly for udev to create /dev/pi433 */
+
+/* tx config is instance specific
+    so with each open a new tx config struct is needed */
+/* rx config is device specific
+    so we have just one rx config, ebedded in device struct */
+struct pi433_device {
+    /* device handling related values */
+    dev_t            devt;
+    int            minor;
+    struct device        *dev;
+    struct cdev        *cdev;
+    struct spi_device    *spi;
+    unsigned        users;
+
+    /* irq related values */
+    struct gpio_desc    *gpiod[NUM_DIO];
+    int            irq_num[NUM_DIO];
+    u8            irq_state[NUM_DIO];
+
+    /* tx related values */
+    STRUCT_KFIFO_REC_1(MSG_FIFO_SIZE) tx_fifo;
+    struct mutex        tx_fifo_lock; // TODO: check, whether necessary or
obsolete
+    struct task_struct    *tx_task_struct;
+    wait_queue_head_t    tx_wait_queue;
+    u8            free_in_fifo;
+
+    /* rx related values */
+    struct pi433_rx_cfg    rx_cfg;
+    u8            *rx_buffer;
+    unsigned int        rx_buffer_size;
+    u32            rx_bytes_to_drop;
+    u32            rx_bytes_dropped;
+    unsigned int        rx_position;
+    struct mutex        rx_lock;
+    wait_queue_head_t    rx_wait_queue;
+
+    /* fifo wait queue */
+    struct task_struct    *fifo_task_struct;
+    wait_queue_head_t    fifo_wait_queue;
+
+    /* flags */
+    bool            rx_active;
+    bool            tx_active;
+    bool            interrupt_rx_allowed;
+};
+
+struct pi433_instance {
+    struct pi433_device    *device;
+    struct pi433_tx_cfg    tx_cfg;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* macro for checked access of registers of radio module */
+#define SET_CHECKED(retval) \
+    if (retval < 0) \
+        return retval;
+
+/*-------------------------------------------------------------------------*/
+
+/* GPIO interrupt handlers */
+static irq_handler_t
+DIO0_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs)
+{
+    struct pi433_device *device = dev_id;
+
+    if      (device->irq_state[DIO0] == DIO_PacketSent)
+    {
+        device->free_in_fifo = FIFO_SIZE;
+        printk("DIO0 irq: Packet sent\n"); // TODO: printk() should include
KERN_ facility level
+        wake_up_interruptible(&device->fifo_wait_queue);
+    }
+    else if (device->irq_state[DIO0] == DIO_Rssi_DIO0)
+    {
+        printk("DIO0 irq: RSSI level over threshold\n");
+        wake_up_interruptible(&device->rx_wait_queue);
+    }
+    else if (device->irq_state[DIO0] == DIO_PayloadReady)
+    {
+        printk("DIO0 irq: PayloadReady\n");
+        device->free_in_fifo = 0;
+        wake_up_interruptible(&device->fifo_wait_queue);
+    }
+
+    return (irq_handler_t) IRQ_HANDLED;
+}
+
+static irq_handler_t
+DIO1_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs)
+{
+    struct pi433_device *device = dev_id;
+
+    if      (device->irq_state[DIO1] == DIO_FifoNotEmpty_DIO1)
+    {
+        device->free_in_fifo = FIFO_SIZE;
+    }
+    else if (device->irq_state[DIO1] == DIO_FifoLevel)
+    {
+        if (device->rx_active)    device->free_in_fifo = FIFO_THRESHOLD - 1;
+        else            device->free_in_fifo = FIFO_SIZE - FIFO_THRESHOLD - 1;
+    }
+    printk("DIO1 irq: %d bytes free in fifo\n", device->free_in_fifo); // TODO:
printk() should include KERN_ facility level
+    wake_up_interruptible(&device->fifo_wait_queue);
+
+    return (irq_handler_t) IRQ_HANDLED;
+}
+
+static void *DIO_irq_handler[NUM_DIO] = {
+    DIO0_irq_handler,
+    DIO1_irq_handler
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int
+rf69_set_rx_cfg(struct pi433_device *dev, struct pi433_rx_cfg *rx_cfg)
+{
+    int payload_length;
+
+    /* receiver config */
+    SET_CHECKED(rf69_set_frequency    (dev->spi, rx_cfg->frequency));
+    SET_CHECKED(rf69_set_bit_rate    (dev->spi, rx_cfg->bit_rate));
+    SET_CHECKED(rf69_set_modulation    (dev->spi, rx_cfg->modulation));
+    SET_CHECKED(rf69_set_antenna_impedance     (dev->spi,
rx_cfg->antenna_impedance));
+    SET_CHECKED(rf69_set_rssi_threshold     (dev->spi,
rx_cfg->rssi_threshold));
+    SET_CHECKED(rf69_set_ook_threshold_dec     (dev->spi,
rx_cfg->thresholdDecrement));
+    SET_CHECKED(rf69_set_bandwidth          (dev->spi, rx_cfg->bw_mantisse,
rx_cfg->bw_exponent));
+    SET_CHECKED(rf69_set_bandwidth_during_afc(dev->spi, rx_cfg->bw_mantisse,
rx_cfg->bw_exponent));
+    SET_CHECKED(rf69_set_dagc          (dev->spi, rx_cfg->dagc));
+
+    dev->rx_bytes_to_drop = rx_cfg->bytes_to_drop;
+
+    /* packet config */
+    /* enable */
+    SET_CHECKED(rf69_set_sync_enable(dev->spi, rx_cfg->enable_sync));
+    if (rx_cfg->enable_sync == optionOn)
+    {
+        SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi,
afterSyncInterrupt));
+    }
+    else
+    {
+        SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, always));
+    }
+    SET_CHECKED(rf69_set_packet_format  (dev->spi,
rx_cfg->enable_length_byte));
+    SET_CHECKED(rf69_set_adressFiltering(dev->spi,
rx_cfg->enable_address_filtering));
+    SET_CHECKED(rf69_set_crc_enable        (dev->spi, rx_cfg->enable_crc));
+
+    /* lengths */
+    SET_CHECKED(rf69_set_sync_size(dev->spi, rx_cfg->sync_length));
+    if (rx_cfg->enable_length_byte == optionOn)
+    {
+        SET_CHECKED(rf69_set_payload_length(dev->spi, 0xff));
+    }
+    else if (rx_cfg->fixed_message_length != 0)
+    {
+        payload_length = rx_cfg->fixed_message_length;
+        if (rx_cfg->enable_length_byte  == optionOn) payload_length++;
+        if (rx_cfg->enable_address_filtering != filteringOff) payload_length++;
+        SET_CHECKED(rf69_set_payload_length(dev->spi, payload_length));
+    }
+    else
+    {
+        SET_CHECKED(rf69_set_payload_length(dev->spi, 0));
+    }
+
+    /* values */
+    if (rx_cfg->enable_sync == optionOn)
+    {
+        SET_CHECKED(rf69_set_sync_values(dev->spi, rx_cfg->sync_pattern));
+    }
+    if (rx_cfg->enable_address_filtering != filteringOff)
+    {
+        SET_CHECKED(rf69_set_node_address     (dev->spi,
rx_cfg->node_address));
+        SET_CHECKED(rf69_set_broadcast_address(dev->spi,
rx_cfg->broadcast_address));
+    }
+
+    return 0;
+}
+
+static int
+rf69_set_tx_cfg(struct pi433_device *dev, struct pi433_tx_cfg *tx_cfg)
+{
+    SET_CHECKED(rf69_set_frequency    (dev->spi, tx_cfg->frequency));
+    SET_CHECKED(rf69_set_bit_rate    (dev->spi, tx_cfg->bit_rate));
+    SET_CHECKED(rf69_set_modulation    (dev->spi, tx_cfg->modulation));
+    SET_CHECKED(rf69_set_deviation    (dev->spi, tx_cfg->dev_frequency));
+    SET_CHECKED(rf69_set_pa_ramp    (dev->spi, tx_cfg->pa_ramp));
+    SET_CHECKED(rf69_set_modulation_shaping(dev->spi, tx_cfg->modShaping));
+    SET_CHECKED(rf69_set_tx_start_condition(dev->spi,
tx_cfg->tx_start_condition));
+
+    /* packet format enable */
+    if (tx_cfg->enable_preamble == optionOn)
+    {
+        SET_CHECKED(rf69_set_preamble_length(dev->spi,
tx_cfg->preamble_length));
+    }
+    else
+    {
+        SET_CHECKED(rf69_set_preamble_length(dev->spi, 0));
+    }
+    SET_CHECKED(rf69_set_sync_enable  (dev->spi, tx_cfg->enable_sync));
+    SET_CHECKED(rf69_set_packet_format(dev->spi, tx_cfg->enable_length_byte));
+    SET_CHECKED(rf69_set_crc_enable      (dev->spi, tx_cfg->enable_crc));
+
+    /* configure sync, if enabled */
+    if (tx_cfg->enable_sync == optionOn)
+    {
+        SET_CHECKED(rf69_set_sync_size(dev->spi, tx_cfg->sync_length));
+        SET_CHECKED(rf69_set_sync_values(dev->spi, tx_cfg->sync_pattern));
+    }
+
+    return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+pi433_start_rx(struct pi433_device *dev)
+{
+    int retval;
+
+    /* return without action, if no pending read request */
+    if (!dev->rx_active)
+        return 0;
+
+    /* setup for receiving */
+    retval = rf69_set_rx_cfg(dev, &dev->rx_cfg);
+    if (retval) return retval;
+
+    /* setup rssi irq */
+    SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO0, DIO_Rssi_DIO0));
+    dev->irq_state[DIO0] = DIO_Rssi_DIO0;
+    irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
+
+    /* setup fifo level interrupt */
+    SET_CHECKED(rf69_set_fifo_threshold(dev->spi, FIFO_SIZE - FIFO_THRESHOLD));
+    SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO1, DIO_FifoLevel));
+    dev->irq_state[DIO1] = DIO_FifoLevel;
+    irq_set_irq_type(dev->irq_num[DIO1], IRQ_TYPE_EDGE_RISING);
+
+    /* set module to receiving mode */
+    SET_CHECKED(rf69_set_mode(dev->spi, receive));
+
+    return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+int
+pi433_receive(void *data)
+{
+    struct pi433_device *dev = data;
+    struct spi_device *spi = dev->spi; /* needed for SET_CHECKED */
+    int bytes_to_read, bytes_total;
+    int retval;
+
+    dev->interrupt_rx_allowed = false;
+
+    /* wait for any tx to finish */
+    dev_dbg(dev->dev,"rx: going to wait for any tx to finish");
+    retval = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active);
+    if(retval) /* wait was interrupted */
+    {
+        dev->interrupt_rx_allowed = true;
+        wake_up_interruptible(&dev->tx_wait_queue);
+        return retval;
+    }
+
+    /* prepare status vars */
+    dev->free_in_fifo = FIFO_SIZE;
+    dev->rx_position = 0;
+    dev->rx_bytes_dropped = 0;
+
+    /* setup radio module to listen for something "in the air" */
+    retval = pi433_start_rx(dev);
+    if (retval)
+        return retval;
+
+    /* now check RSSI, if low wait for getting high (RSSI interrupt) */
+    while ( !rf69_get_flag(dev->spi, rssiExceededThreshold) )
+    {
+        /* 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");
+        retval = wait_event_interruptible(dev->rx_wait_queue,
+                                      rf69_get_flag(dev->spi,
+
                                                       rssiExceededThreshold));
+        if (retval) goto abort; /* wait was interrupted */
+        dev->interrupt_rx_allowed = false;
+
+        /* cross check for ongoing tx */
+        if (!dev->tx_active) break;
+    }
+
+    /* configure payload ready irq */
+    SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PayloadReady));
+    dev->irq_state[DIO0] = DIO_PayloadReady;
+    irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
+
+    /* fixed or unlimited length? */
+    if (dev->rx_cfg.fixed_message_length != 0)
+    {
+        if (dev->rx_cfg.fixed_message_length > dev->rx_buffer_size)
+        {
+            retval = -1;
+            goto abort;
+        }
+        bytes_total = dev->rx_cfg.fixed_message_length;
+        dev_dbg(dev->dev,"rx: msg len set to %d by fixed length", bytes_total);
+    }
+    else
+    {
+        bytes_total = dev->rx_buffer_size;
+        dev_dbg(dev->dev, "rx: msg len set to %d as requested by read",
bytes_total);
+    }
+
+    /* length byte enabled? */
+    if (dev->rx_cfg.enable_length_byte == optionOn)
+    {
+        retval = wait_event_interruptible(dev->fifo_wait_queue,
+                          dev->free_in_fifo < FIFO_SIZE);
+        if (retval) goto abort; /* wait was interrupted */
+
+        rf69_read_fifo(spi, (u8 *)&bytes_total, 1);
+        if (bytes_total > dev->rx_buffer_size)
+        {
+            retval = -1;
+            goto abort;
+        }
+        dev->free_in_fifo++;
+        dev_dbg(dev->dev, "rx: msg len reset to %d due to length byte",
bytes_total);
+    }
+
+    /* address byte enabled? */
+    if (dev->rx_cfg.enable_address_filtering != filteringOff)
+    {
+        u8 dummy;
+
+        bytes_total--;
+
+        retval = wait_event_interruptible(dev->fifo_wait_queue,
+                          dev->free_in_fifo < FIFO_SIZE);
+        if (retval) goto abort; /* wait was interrupted */
+
+        rf69_read_fifo(spi, &dummy, 1);
+        dev->free_in_fifo++;
+        dev_dbg(dev->dev, "rx: address byte stripped off");
+    }
+
+    /* get payload */
+    while (dev->rx_position < bytes_total)
+    {
+        if ( !rf69_get_flag(dev->spi, payloadReady) )
+        {
+            retval = wait_event_interruptible(dev->fifo_wait_queue,
+                              dev->free_in_fifo < FIFO_SIZE);
+            if (retval) goto abort; /* wait was interrupted */
+        }
+
+        /* need to drop bytes or acquire? */
+        if (dev->rx_bytes_to_drop > dev->rx_bytes_dropped)
+            bytes_to_read = dev->rx_bytes_to_drop - dev->rx_bytes_dropped;
+        else
+            bytes_to_read = bytes_total - dev->rx_position;
+
+
+        /* access the fifo */
+        if (bytes_to_read > FIFO_SIZE - dev->free_in_fifo)
+            bytes_to_read = FIFO_SIZE - dev->free_in_fifo;
+        retval = rf69_read_fifo(spi,
+                    &dev->rx_buffer[dev->rx_position],
+                    bytes_to_read);
+        if (retval) goto abort; /* read failed */
+        dev->free_in_fifo += bytes_to_read;
+
+        /* adjust status vars */
+        if (dev->rx_bytes_to_drop > dev->rx_bytes_dropped)
+            dev->rx_bytes_dropped += bytes_to_read;
+        else
+            dev->rx_position += bytes_to_read;
+    }
+
+
+    /* rx done, wait was interrupted or error occured */
+abort:
+    dev->interrupt_rx_allowed = true;
+    SET_CHECKED(rf69_set_mode(dev->spi, standby));
+    wake_up_interruptible(&dev->tx_wait_queue);
+
+    if (retval)
+        return retval;
+    else
+        return bytes_total;
+}
+
+int
+pi433_tx_thread(void *data)
+{
+    struct pi433_device *device = data;
+    struct spi_device *spi = device->spi; /* needed for SET_CHECKED */
+    struct pi433_tx_cfg tx_cfg;
+    u8     buffer[MAX_MSG_SIZE];
+    size_t size;
+    bool   rx_interrupted = false;
+    int    position, repetitions;
+    int    retval;
+
+    while (1)
+    {
+        /* wait for fifo to be populated or for request to terminate*/
+        dev_dbg(device->dev, "thread: going to wait for new messages");
+        wait_event_interruptible(device->tx_wait_queue,
+                     ( !kfifo_is_empty(&device->tx_fifo) ||
+                        kthread_should_stop() ));
+        if ( kthread_should_stop() )
+            return 0;
+
+        /* get data from fifo in the following order:
+           - tx_cfg
+           - size of message
+           - message */
+        mutex_lock(&device->tx_fifo_lock);
+
+        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", retval, (unsigned int)sizeof(tx_cfg) );
+            mutex_unlock(&device->tx_fifo_lock);
+            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", retval, (unsigned int)sizeof(size_t) );
+            mutex_unlock(&device->tx_fifo_lock);
+            continue;
+        }
+
+        /* use fixed message length, if requested */
+        if (tx_cfg.fixed_message_length != 0)
+            size = tx_cfg.fixed_message_length;
+
+        /* increase size, if len byte is requested */
+        if (tx_cfg.enable_length_byte == optionOn)
+            size++;
+
+        /* increase size, if adr byte is requested */
+        if (tx_cfg.enable_address_byte == optionOn)
+            size++;
+
+        /* prime buffer */
+        memset(buffer, 0, size);
+        position = 0;
+
+        /* add length byte, if requested */
+        if (tx_cfg.enable_length_byte  == optionOn)
+            buffer[position++] = size-1; /* according to spec length byte
itself must be excluded from the length calculation */
+
+        /* add adr byte, if requested */
+        if (tx_cfg.enable_address_byte == optionOn)
+            buffer[position++] = tx_cfg.address_byte;
+
+        /* finally get message data from fifo */
+        retval = kfifo_out(&device->tx_fifo, &buffer[position],
sizeof(buffer)-position );
+        dev_dbg(device->dev, "read %d message byte(s) from fifo queue.",
retval);
+        mutex_unlock(&device->tx_fifo_lock);
+
+        /* if rx is active, we need to interrupt the waiting for
+           incoming telegrams, to be able to send something.
+           We are only allowed, if currently no reception takes
+           place otherwise we need to  wait for the incoming telegram
+           to finish */
+        wait_event_interruptible(device->tx_wait_queue,
+                     !device->rx_active ||
+                      device->interrupt_rx_allowed == true);
+
+        /* prevent race conditions
+           irq will be reenabled after tx config is set */
+        disable_irq(device->irq_num[DIO0]);
+        device->tx_active = true;
+
+        if (device->rx_active && rx_interrupted == false)
+        {
+            /* rx is currently waiting for a telegram;
+               we need to set the radio module to standby */
+            SET_CHECKED(rf69_set_mode(device->spi, standby));
+            rx_interrupted = true;
+        }
+
+        /* clear fifo, set fifo threshold, set payload length */
+        SET_CHECKED(rf69_set_mode(spi, standby)); /* this clears the fifo */
+        SET_CHECKED(rf69_set_fifo_threshold(spi, FIFO_THRESHOLD));
+        if (tx_cfg.enable_length_byte == optionOn)
+        {
+            SET_CHECKED(rf69_set_payload_length(spi, size *
tx_cfg.repetitions));
+        }
+        else
+        {
+            SET_CHECKED(rf69_set_payload_length(spi, 0));
+        }
+
+        /* configure the rf chip */
+        rf69_set_tx_cfg(device, &tx_cfg);
+
+        /* enable fifo level interrupt */
+        SET_CHECKED(rf69_set_dio_mapping(spi, DIO1, DIO_FifoLevel));
+        device->irq_state[DIO1] = DIO_FifoLevel;
+        irq_set_irq_type(device->irq_num[DIO1], IRQ_TYPE_EDGE_FALLING);
+
+        /* enable packet sent interrupt */
+        SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PacketSent));
+        device->irq_state[DIO0] = DIO_PacketSent;
+        irq_set_irq_type(device->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
+        enable_irq(device->irq_num[DIO0]); /* was disabled by rx active check
*/
+
+        /* enable transmission */
+        SET_CHECKED(rf69_set_mode(spi, transmit));
+
+        /* transfer this msg (and repetitions) to chip fifo */
+        device->free_in_fifo = FIFO_SIZE;
+        position = 0;
+        repetitions = tx_cfg.repetitions;
+        while( (repetitions > 0) && (size > position) )
+        {
+            if ( (size - position) > device->free_in_fifo)
+            {    /* msg to big for fifo - take a part */
+                int temp = device->free_in_fifo;
+                device->free_in_fifo = 0;
+                rf69_write_fifo(spi,
+                                &buffer[position],
+                                temp);
+                position +=temp;
+            }
+            else
+            {    /* msg fits into fifo - take all */
+                device->free_in_fifo -= size;
+                repetitions--;
+                rf69_write_fifo(spi,
+                        &buffer[position],
+                        (size - position) );
+                position = 0; /* reset for next repetition */
+            }
+
+            retval = wait_event_interruptible(device->fifo_wait_queue,
+                              device->free_in_fifo > 0);
+            if (retval) { printk("ABORT\n"); goto abort; }
+        }
+
+        /* we are done. Wait for packet to get sent */
+        dev_dbg(device->dev, "thread: wiat for packet to get sent/fifo to be
empty");
+        wait_event_interruptible(device->fifo_wait_queue,
+                     device->free_in_fifo == FIFO_SIZE ||
+                     kthread_should_stop() );
+        if ( kthread_should_stop() )    printk("ABORT\n");
+
+
+        /* STOP_TRANSMISSION */
+        dev_dbg(device->dev, "thread: Packet sent. Set mode to stby.");
+        SET_CHECKED(rf69_set_mode(spi, standby));
+
+        /* everything sent? */
+        if ( kfifo_is_empty(&device->tx_fifo) )
+        {
+abort:
+            if (rx_interrupted)
+            {
+                rx_interrupted = false;
+                pi433_start_rx(device);
+            }
+            device->tx_active = false;
+            wake_up_interruptible(&device->rx_wait_queue);
+        }
+    }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static ssize_t
+pi433_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
+{
+    struct pi433_instance    *instance;
+    struct pi433_device    *device;
+    unsigned int        bytes_received;
+    ssize_t            retval;
+
+    /* check, whether internal buffer is big enough for requested size */
+    if (size > MAX_MSG_SIZE)
+        return -EMSGSIZE;
+
+    instance = filp->private_data;
+    device = instance->device;
+
+    /* just one read request at a time */
+    mutex_lock(&device->rx_lock);
+    if (device->rx_active)
+    {
+        mutex_unlock(&device->rx_lock);
+        return -EAGAIN;
+    }
+    else
+    {
+        device->rx_active = true;
+        mutex_unlock(&device->rx_lock);
+    }
+
+    /* start receiving */
+    /* will block until something was received*/
+    device->rx_buffer_size = size;
+    bytes_received = pi433_receive(device);
+
+    /* release rx */
+    mutex_lock(&device->rx_lock);
+    device->rx_active = false;
+    mutex_unlock(&device->rx_lock);
+
+    /* if read was successful copy to user space*/
+    if (bytes_received >= 0)
+    {
+        retval = copy_to_user(buf, device->rx_buffer, bytes_received);
+        if (retval)
+            return retval;
+    }
+
+    return bytes_received;
+}
+
+
+static ssize_t
+pi433_write(struct file *filp, const char __user *buf,
+        size_t count, loff_t *f_pos)
+{
+    struct pi433_instance    *instance;
+    struct pi433_device    *device;
+    int                     copied, retval;
+
+    instance = filp->private_data;
+    device = instance->device;
+
+    /* check, whether internal buffer (tx thread) is big enough for requested
size */
+    if (count > MAX_MSG_SIZE)
+        return -EMSGSIZE;
+
+    /* write the following sequence into fifo:
+       - tx_cfg
+       - size of message
+       - message */
+    mutex_lock(&device->tx_fifo_lock);
+    retval = kfifo_in(&device->tx_fifo, &instance->tx_cfg,
sizeof(instance->tx_cfg));
+    if ( retval != sizeof(instance->tx_cfg) )
+        goto abort;
+
+    retval = kfifo_in (&device->tx_fifo, &count, sizeof(size_t));
+    if ( retval != sizeof(size_t) )
+        goto abort;
+
+    retval = kfifo_from_user(&device->tx_fifo, buf, count, &copied);
+    if (retval || copied != count)
+        goto abort;
+
+    mutex_unlock(&device->tx_fifo_lock);
+
+    /* start transfer */
+    wake_up_interruptible(&device->tx_wait_queue);
+    dev_dbg(device->dev, "write: generated new msg with %d bytes.", copied);
+
+    return 0;
+
+abort:
+    dev_dbg(device->dev, "write to fifo failed: 0x%x", retval);
+    kfifo_reset(&device->tx_fifo); // TODO: maybe find a solution, not to
discard already stored, valid entries
+    mutex_unlock(&device->tx_fifo_lock);
+    return -EAGAIN;
+}
+
+
+static long
+pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    int            err = 0;
+    int            retval = 0;
+    struct pi433_instance    *instance;
+    struct pi433_device    *device;
+    u32            tmp;
+
+    /* Check type and command number */
+    if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC)
+        return -ENOTTY;
+
+    /* Check access direction once here; don't repeat below.
+     * IOC_DIR is from the user perspective, while access_ok is
+     * from the kernel perspective; so they look reversed.
+     */
+    if (_IOC_DIR(cmd) & _IOC_READ)
+        err = !access_ok(VERIFY_WRITE,
+                 (void __user *)arg,
+                 _IOC_SIZE(cmd));
+
+    if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
+        err = !access_ok(VERIFY_READ,
+                 (void __user *)arg,
+                 _IOC_SIZE(cmd));
+    if (err)
+        return -EFAULT;
+
+    /* TODO? guard against device removal before, or while,
+     * we issue this ioctl. --> device_get()
+     */
+    instance = filp->private_data;
+    device = instance->device;
+
+    if (device == NULL)
+        return -ESHUTDOWN;
+
+    switch (cmd) {
+    case PI433_IOC_RD_TX_CFG:
+        tmp = _IOC_SIZE(cmd);
+        if ( (tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0) )
+        {
+            retval = -EINVAL;
+            break;
+        }
+
+        if (__copy_to_user((void __user *)arg,
+                    &instance->tx_cfg,
+                    tmp))
+        {
+            retval = -EFAULT;
+            break;
+        }
+
+        break;
+    case PI433_IOC_WR_TX_CFG:
+        tmp = _IOC_SIZE(cmd);
+        if ( (tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0) )
+        {
+            retval = -EINVAL;
+            break;
+        }
+
+        if (__copy_from_user(&instance->tx_cfg,
+                     (void __user *)arg,
+                     tmp))
+        {
+            retval = -EFAULT;
+            break;
+        }
+
+        break;
+
+    case PI433_IOC_RD_RX_CFG:
+        tmp = _IOC_SIZE(cmd);
+        if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) {
+            retval = -EINVAL;
+            break;
+        }
+
+        if (__copy_to_user((void __user *)arg,
+                   &device->rx_cfg,
+                   tmp))
+        {
+            retval = -EFAULT;
+            break;
+        }
+
+        break;
+    case PI433_IOC_WR_RX_CFG:
+        tmp = _IOC_SIZE(cmd);
+        mutex_lock(&device->rx_lock);
+
+        /* during pendig read request, change of config not allowed */
+        if (device->rx_active) {
+            retval = -EAGAIN;
+            mutex_unlock(&device->rx_lock);
+            break;
+        }
+
+        if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) {
+            retval = -EINVAL;
+            mutex_unlock(&device->rx_lock);
+            break;
+        }
+
+        if (__copy_from_user(&device->rx_cfg,
+                     (void __user *)arg,
+                     tmp))
+        {
+            retval = -EFAULT;
+            mutex_unlock(&device->rx_lock);
+            break;
+        }
+
+        mutex_unlock(&device->rx_lock);
+        break;
+    default:
+        retval = -EINVAL;
+    }
+
+    return retval;
+}
+
+#ifdef CONFIG_COMPAT
+static long
+pi433_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    return pi433_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#else
+#define pi433_compat_ioctl NULL
+#endif /* CONFIG_COMPAT */
+
+/*-------------------------------------------------------------------------*/
+
+static int pi433_open(struct inode *inode, struct file *filp)
+{
+    struct pi433_device    *device;
+    struct pi433_instance    *instance;
+
+    mutex_lock(&minor_lock);
+    device = idr_find(&pi433_idr, iminor(inode));
+
+    mutex_unlock(&minor_lock);
+    if (!device) {
+        dev_dbg(device->dev, "device: minor %d unknown.\n", iminor(inode));
+        return -ENODEV;
+    }
+
+    if (!device->rx_buffer) {
+        device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL);
+        if (!device->rx_buffer)
+        {
+            dev_dbg(device->dev, "open/ENOMEM\n");
+            return -ENOMEM;
+        }
+    }
+
+    device->users++;
+    instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+    if (!instance)
+    {
+        kfree(device->rx_buffer);
+        device->rx_buffer = NULL;
+        return -ENOMEM;
+    }
+
+    /* 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;
+    nonseekable_open(inode, filp);
+
+    return 0;
+}
+
+static int pi433_release(struct inode *inode, struct file *filp)
+{
+    struct pi433_instance    *instance;
+    struct pi433_device    *device;
+
+    instance = filp->private_data;
+    device = instance->device;
+    kfree(instance);
+    filp->private_data = NULL;
+
+    /* last close? */
+    device->users--;
+
+    if (!device->users) {
+        kfree(device->rx_buffer);
+        device->rx_buffer = NULL;
+        if (device->spi == NULL)
+            kfree(device);
+    }
+
+    return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int setup_GPIOs(struct pi433_device *device)
+{
+    char     name[5];
+    int    retval;
+    int    i;
+
+    for (i=0; i<NUM_DIO; i++)
+    {
+        /* "construct" name and get the gpio descriptor */
+        snprintf(name, sizeof(name), "DIO%d", i);
+        device->gpiod[i] = gpiod_get(&device->spi->dev, name, 0 /*GPIOD_IN*/);
+
+        if (device->gpiod[i] == ERR_PTR(-ENOENT))
+        {
+            dev_dbg(&device->spi->dev, "Could not find entry for %s.
Ignoring.", name);
+            continue;
+        }
+
+        if (device->gpiod[i] == ERR_PTR(-EBUSY))
+            dev_dbg(&device->spi->dev, "%s is busy.", name);
+
+        if ( IS_ERR(device->gpiod[i]) )
+        {
+            retval = PTR_ERR(device->gpiod[i]);
+            /* release already allocated gpios */
+            for (i--; i>=0; i--)
+            {
+                free_irq(device->irq_num[i], device);
+                gpiod_put(device->gpiod[i]);
+            }
+            return retval;
+        }
+
+
+        /* configure the pin */
+        gpiod_unexport(device->gpiod[i]);
+        retval = gpiod_direction_input(device->gpiod[i]);
+        if (retval) return retval;
+
+
+        /* configure irq */
+        device->irq_num[i] = gpiod_to_irq(device->gpiod[i]);
+        if (device->irq_num[i] < 0)
+        {
+            device->gpiod[i] = ERR_PTR(-EINVAL);//(struct gpio_desc
*)device->irq_num[i];
+            return device->irq_num[i];
+        }
+        retval = request_irq(device->irq_num[i],
+                     DIO_irq_handler[i],
+                     0, /* flags */
+                     name,
+                     device);
+
+        if (retval)
+            return retval;
+
+        dev_dbg(&device->spi->dev, "%s succesfully configured", name);
+    }
+
+    return 0;
+}
+
+static void free_GPIOs(struct pi433_device *device)
+{
+    int i;
+
+    for (i=0; i<NUM_DIO; i++)
+    {
+        /* check if gpiod is valid */
+        if ( IS_ERR(device->gpiod[i]) )
+            continue;
+
+        free_irq(device->irq_num[i], device);
+        gpiod_put(device->gpiod[i]);
+    }
+    return;
+}
+
+static int pi433_get_minor(struct pi433_device *device)
+{
+    int retval = -ENOMEM;
+
+    mutex_lock(&minor_lock);
+    retval = idr_alloc(&pi433_idr, device, 0, N_PI433_MINORS, GFP_KERNEL);
+    if (retval >= 0) {
+        device->minor = retval;
+        retval = 0;
+    } else if (retval == -ENOSPC) {
+        dev_err(device->dev, "too many pi433 devices\n");
+        retval = -EINVAL;
+    }
+    mutex_unlock(&minor_lock);
+    return retval;
+}
+
+static void pi433_free_minor(struct pi433_device *dev)
+{
+    mutex_lock(&minor_lock);
+    idr_remove(&pi433_idr, dev->minor);
+    mutex_unlock(&minor_lock);
+}
+/*-------------------------------------------------------------------------*/
+
+static const struct file_operations pi433_fops = {
+    .owner =    THIS_MODULE,
+    /* REVISIT switch to aio primitives, so that userspace
+     * gets more complete API coverage.  It'll simplify things
+     * too, except for the locking.
+     */
+    .write =    pi433_write,
+    .read =        pi433_read,
+    .unlocked_ioctl = pi433_ioctl,
+    .compat_ioctl = pi433_compat_ioctl,
+    .open =        pi433_open,
+    .release =    pi433_release,
+    .llseek =    no_llseek,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int pi433_probe(struct spi_device *spi)
+{
+    struct pi433_device    *device;
+    int            retval;
+
+    /* setup spi parameters */
+    spi->mode = 0x00;
+    spi->bits_per_word = 8;
+    /* spi->max_speed_hz = 10000000;  1MHz already set by device tree overlay
*/
+
+    retval = spi_setup(spi);
+    if (retval)
+    {
+        dev_dbg(&spi->dev, "configuration of SPI interface failed!\n");
+        return retval;
+    }
+    else
+    {
+        dev_dbg(&spi->dev,
+            "spi interface setup: mode 0x%2x, %d bits per word, %dhz max
speed",
+            spi->mode, spi->bits_per_word, spi->max_speed_hz);
+    }
+
+    /* Ping the chip by reading the version register */
+    retval = spi_w8r8(spi, 0x10);
+    if (retval < 0)
+        return retval;
+
+    switch(retval)
+    {
+        case 0x24:
+            dev_dbg(&spi->dev, "fonud pi433 (ver. 0x%x)", retval);
+            break;
+        default:
+            dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval);
+            return -ENODEV;
+    }
+
+    /* Allocate driver data */
+    device = kzalloc(sizeof(*device), GFP_KERNEL);
+    if (!device)
+        return -ENOMEM;
+
+    /* Initialize the driver data */
+    device->spi = spi;
+    device->rx_active = false;
+    device->tx_active = false;
+    device->interrupt_rx_allowed = false;
+
+    /* init wait queues */
+    init_waitqueue_head(&device->tx_wait_queue);
+    init_waitqueue_head(&device->rx_wait_queue);
+    init_waitqueue_head(&device->fifo_wait_queue);
+
+    /* init fifo */
+    INIT_KFIFO(device->tx_fifo);
+
+    /* init mutexes and locks */
+    mutex_init(&device->tx_fifo_lock);
+    mutex_init(&device->rx_lock);
+
+    /* setup GPIO (including irq_handler) for the different DIOs */
+    retval = setup_GPIOs(device);
+    if (retval)
+    {
+        dev_dbg(&spi->dev, "setup of GPIOs failed");
+        goto GPIO_failed;
+    }
+
+    /* setup the radio module */
+    SET_CHECKED(rf69_set_mode        (spi, standby));
+    SET_CHECKED(rf69_set_data_mode        (spi, packet));
+    SET_CHECKED(rf69_set_amplifier_0    (spi, optionOn));
+    SET_CHECKED(rf69_set_amplifier_1    (spi, optionOff));
+    SET_CHECKED(rf69_set_amplifier_2    (spi, optionOff));
+    SET_CHECKED(rf69_set_output_power_level    (spi, 13));
+    SET_CHECKED(rf69_set_antenna_impedance    (spi, fiftyOhm));
+
+    /* start tx thread */
+    device->tx_task_struct = kthread_run(pi433_tx_thread,
+                         device,
+                         "pi433_tx_task");
+    if (device->tx_task_struct < 0)
+    {
+        dev_dbg(device->dev, "start of send thread failed");
+        goto send_thread_failed;
+    }
+
+    /* determ minor number */
+    retval = pi433_get_minor(device);
+    if (retval)
+    {
+        dev_dbg(device->dev, "get of minor number failed");
+        goto minor_failed;
+    }
+
+    /* create device */
+    device->devt = MKDEV(MAJOR(pi433_dev), device->minor);
+    device->dev = device_create(pi433_class,
+                    &spi->dev,
+                    device->devt,
+                    device,
+                    "pi433");
+    if (IS_ERR(device->dev)) {
+        pr_err("pi433: device register failed\n");
+        retval = PTR_ERR(device->dev);
+        goto device_create_failed;
+    }
+    else {
+        dev_dbg(device->dev,
+            "created device for major %d, minor %d\n",
+            MAJOR(pi433_dev),
+            device->minor);
+    }
+
+    /* create cdev */
+    device->cdev = cdev_alloc();
+    device->cdev->owner = THIS_MODULE;
+    cdev_init(device->cdev, &pi433_fops);
+    retval = cdev_add(device->cdev, device->devt, 1);
+    if (retval)
+    {
+        dev_dbg(device->dev, "register of cdev failed");
+        goto cdev_failed;
+    }
+
+    /* spi setup */
+    spi_set_drvdata(spi, device);
+
+    return 0;
+
+cdev_failed:
+    device_destroy(pi433_class, device->devt);
+device_create_failed:
+    pi433_free_minor(device);
+minor_failed:
+    kthread_stop(device->tx_task_struct);
+send_thread_failed:
+    free_GPIOs(device);
+GPIO_failed:
+    kfree(device);
+
+    return retval;
+}
+
+static int pi433_remove(struct spi_device *spi)
+{
+    struct pi433_device    *device = spi_get_drvdata(spi);
+
+    /* free GPIOs */
+    free_GPIOs(device);
+
+    /* make sure ops on existing fds can abort cleanly */
+    device->spi = NULL;
+
+    kthread_stop(device->tx_task_struct);
+
+    device_destroy(pi433_class, device->devt);
+
+    cdev_del(device->cdev);
+
+    pi433_free_minor(device);
+
+    if (device->users == 0)
+        kfree(device);
+
+    return 0;
+}
+
+static const struct of_device_id pi433_dt_ids[] = {
+    { .compatible = "Smarthome-Wolf,pi433" },
+    {},
+};
+
+MODULE_DEVICE_TABLE(of, pi433_dt_ids);
+
+static struct spi_driver pi433_spi_driver = {
+    .driver = {
+        .name =        "pi433",
+        .owner =    THIS_MODULE,
+        .of_match_table = of_match_ptr(pi433_dt_ids),
+    },
+    .probe =    pi433_probe,
+    .remove =    pi433_remove,
+
+    /* NOTE:  suspend/resume methods are not necessary here.
+     * We don't do anything except pass the requests to/from
+     * the underlying controller.  The refrigerator handles
+     * most issues; the controller driver handles the rest.
+     */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init pi433_init(void)
+{
+    int status;
+
+    /* If MAX_MSG_SIZE is smaller then FIFO_SIZE, the driver won't
+           work stable - risk of buffer overflow */
+    if (MAX_MSG_SIZE < FIFO_SIZE)
+        return -EINVAL;
+
+    /* Claim device numbers.  Then register a class
+     * that will key udev/mdev to add/remove /dev nodes.  Last, register
+     * Last, register the driver which manages those device numbers.
+     */
+    status = alloc_chrdev_region(&pi433_dev, 0 /*firstminor*/, N_PI433_MINORS
/*count*/, "pi433" /*name*/);
+    if (status < 0)
+        return status;
+
+    pi433_class = class_create(THIS_MODULE, "pi433");
+    if (IS_ERR(pi433_class))
+    {
+        unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+        return PTR_ERR(pi433_class);
+    }
+
+    status = spi_register_driver(&pi433_spi_driver);
+    if (status < 0)
+    {
+        class_destroy(pi433_class);
+        unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+    }
+
+    return status;
+}
+
+module_init(pi433_init);
+
+static void __exit pi433_exit(void)
+{
+    spi_unregister_driver(&pi433_spi_driver);
+    class_destroy(pi433_class);
+    unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name);
+}
+module_exit(pi433_exit);
+
+MODULE_AUTHOR("Marcus Wolf, <linux@xxxxxxxxxxxxxxxxxxxxx>");
+MODULE_DESCRIPTION("Driver for Pi433");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:pi433");
diff --git a/drivers/staging/pi433/pi433_if.h b/drivers/staging/pi433/pi433_if.h
new file mode 100644
index 0000000..e6ed3cd
--- /dev/null
+++ b/drivers/staging/pi433/pi433_if.h
@@ -0,0 +1,152 @@
+/*
+ * include/linux/TODO
+ *
+ * userspace interface for pi433 radio module
+ *
+ * Pi433 is a 433MHz radio module for the Raspberry Pi.
+ * It is based on the HopeRf Module RFM69CW. Therefore inside of this
+ * driver, you'll find an abstraction of the rf69 chip.
+ *
+ * If needed, this driver could be extended, to also support other
+ * devices, basing on HopeRfs rf69.
+ *
+ * The driver can also be extended, to support other modules of
+ * HopeRf with a similar interace - e. g. RFM69HCW, RFM12, RFM95, ...
+ * Copyright (C) 2016 Wolf-Entwicklungen
+ *    Marcus Wolf <linux@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PI433_H
+#define PI433_H
+
+#include <linux/types.h>
+#include "rf69_enum.h"
+
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+
+/* IOCTL structs and commands */
+
+/**
+ * struct pi433_tx_config - describes the configuration of the radio module for
sending
+ * @frequency:
+ * @bit_rate:
+ * @modulation:
+ * @data_mode:
+ * @preamble_length:
+ * @sync_pattern:
+ * @tx_start_condition:
+ * @payload_length:
+ * @repetitions:
+ *
+ * ATTENTION:
+ * If the contents of 'pi433_tx_config' ever change
+ * incompatibly, then the ioctl number (see define below) must change.
+ *
+ * NOTE: struct layout is the same in 64bit and 32bit userspace.
+ */
+#define PI433_TX_CFG_IOCTL_NR     0
+struct pi433_tx_cfg
+{
+    __u32            frequency;
+    __u16            bit_rate;
+    __u32            dev_frequency;
+    enum modulation        modulation;
+    enum modShaping        modShaping;
+
+    enum paRamp        pa_ramp;
+
+    enum txStartCondition    tx_start_condition;
+
+    __u16            repetitions;
+
+
+    /* packet format */
+    enum optionOnOff    enable_preamble;
+    enum optionOnOff    enable_sync;
+    enum optionOnOff    enable_length_byte;
+    enum optionOnOff    enable_address_byte;
+    enum optionOnOff    enable_crc;
+
+    __u16            preamble_length;
+    __u8            sync_length;
+    __u8            fixed_message_length;
+
+    __u8            sync_pattern[8];
+    __u8            address_byte;
+};
+
+
+/**
+ * struct pi433_rx_config - describes the configuration of the radio module for
sending
+ * @frequency:
+ * @bit_rate:
+ * @modulation:
+ * @data_mode:
+ * @preamble_length:
+ * @sync_pattern:
+ * @tx_start_condition:
+ * @payload_length:
+ * @repetitions:
+ *
+ * ATTENTION:
+ * If the contents of 'pi433_rx_config' ever change
+ * incompatibly, then the ioctl number (see define below) must change
+ *
+ * NOTE: struct layout is the same in 64bit and 32bit userspace.
+ */
+#define PI433_RX_CFG_IOCTL_NR     1
+struct pi433_rx_cfg {
+    __u32            frequency;
+    __u16            bit_rate;
+    __u32            dev_frequency;
+
+    enum modulation        modulation;
+
+    __u8            rssi_threshold;
+    enum thresholdDecrement    thresholdDecrement;
+    enum antennaImpedance    antenna_impedance;
+    enum lnaGain        lna_gain;
+    enum mantisse        bw_mantisse;    /* normal: 0x50 */
+    __u8            bw_exponent;    /* during AFC: 0x8b */
+    enum dagc        dagc;
+
+
+
+    /* packet format */
+    enum optionOnOff    enable_sync;
+    enum optionOnOff    enable_length_byte;      /* should be used in
combination with sync, only */
+    enum addressFiltering    enable_address_filtering; /* operational with
sync, only */
+    enum optionOnOff    enable_crc;          /* only operational, if sync on
and fixed length or length byte is used */
+
+    __u8            sync_length;
+    __u8            fixed_message_length;
+    __u32            bytes_to_drop;
+
+    __u8            sync_pattern[8];
+    __u8            node_address;
+    __u8            broadcast_address;
+};
+
+
+#define PI433_IOC_MAGIC            'r'
+
+#define PI433_IOC_RD_TX_CFG    _IOR(PI433_IOC_MAGIC, PI433_TX_CFG_IOCTL_NR,
char[sizeof(struct pi433_tx_cfg)])
+#define PI433_IOC_WR_TX_CFG    _IOW(PI433_IOC_MAGIC, PI433_TX_CFG_IOCTL_NR,
char[sizeof(struct pi433_tx_cfg)])
+
+#define PI433_IOC_RD_RX_CFG    _IOR(PI433_IOC_MAGIC, PI433_RX_CFG_IOCTL_NR,
char[sizeof(struct pi433_rx_cfg)])
+#define PI433_IOC_WR_RX_CFG    _IOW(PI433_IOC_MAGIC, PI433_RX_CFG_IOCTL_NR,
char[sizeof(struct pi433_rx_cfg)])
+
+#endif /* PI433_H */
diff --git a/drivers/staging/pi433/rf69.c b/drivers/staging/pi433/rf69.c
new file mode 100644
index 0000000..b6bc45b
--- /dev/null
+++ b/drivers/staging/pi433/rf69.c
@@ -0,0 +1,982 @@
+/*
+ * abstraction of the spi interface of HopeRf rf69 radio module
+ *
+ * Copyright (C) 2016 Wolf-Entwicklungen
+ *    Marcus Wolf <linux@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* enable prosa debug info */
+#undef DEBUG
+/* enable print of values on reg access */
+#undef DEBUG_VALUES
+/* enable print of values on fifo access */
+#undef DEBUG_FIFO_ACCESS
+
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+
+#include "rf69.h"
+#include "rf69_registers.h"
+
+#define F_OSC      32000000 /* in Hz */
+#define FIFO_SIZE 66        /* in byte */
+
+/*-------------------------------------------------------------------------*/
+
+#define READ_REG(x)    rf69_read_reg (spi, x)
+#define WRITE_REG(x,y)    rf69_write_reg(spi, x, y)
+#define INVALID_PARAM \
+    { \
+        dev_dbg(&spi->dev, "set: illegal input param"); \
+        return -EINVAL; \
+    }
+
+/*-------------------------------------------------------------------------*/
+
+int rf69_set_mode(struct spi_device *spi, enum mode mode)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: mode");
+    #endif
+
+    switch (mode){
+    case transmit:      return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) &
~MASK_OPMODE_MODE) | OPMODE_MODE_TRANSMIT);
+    case receive:      return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) &
~MASK_OPMODE_MODE) | OPMODE_MODE_RECEIVE);
+    case synthesizer: return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) &
~MASK_OPMODE_MODE) | OPMODE_MODE_SYNTHESIZER);
+    case standby:      return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) &
~MASK_OPMODE_MODE) | OPMODE_MODE_STANDBY);
+    case mode_sleep:  return WRITE_REG(REG_OPMODE, (READ_REG(REG_OPMODE) &
~MASK_OPMODE_MODE) | OPMODE_MODE_SLEEP);
+    default:      INVALID_PARAM;
+    }
+
+    // we are using packet mode, so this check is not really needed
+    // but waiting for mode ready is necessary when going from sleep because
the FIFO may not be immediately available from previous mode
+    //while (_mode == RF69_MODE_SLEEP && (READ_REG(REG_IRQFLAGS1) &
RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady
+
+}
+
+int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: data mode");
+    #endif
+
+    switch (dataMode) {
+    case packet:        return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_PACKET);
+    case continuous:    return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) | DATAMODUL_MODE_CONTINUOUS);
+    case continuousNoSync:  return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODE) |
DATAMODUL_MODE_CONTINUOUS_NOSYNC);
+    default:        INVALID_PARAM;
+    }
+}
+
+int rf69_set_modulation(struct spi_device *spi, enum modulation modulation)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: modulation");
+    #endif
+
+    switch (modulation) {
+    case OOK:   return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) &
~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_OOK);
+    case FSK:   return WRITE_REG(REG_DATAMODUL, (READ_REG(REG_DATAMODUL) &
~MASK_DATAMODUL_MODULATION_TYPE) | DATAMODUL_MODULATION_TYPE_FSK);
+    default:    INVALID_PARAM;
+    }
+}
+
+enum modulation rf69_get_modulation(struct spi_device *spi)
+{
+    u8 currentValue;    
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "get: mode");
+    #endif
+
+    currentValue = READ_REG(REG_DATAMODUL);
+
+    switch (currentValue & MASK_DATAMODUL_MODULATION_TYPE >> 3)  // TODO
improvement: change 3 to define
+    {
+    case DATAMODUL_MODULATION_TYPE_OOK: return OOK;
+    case DATAMODUL_MODULATION_TYPE_FSK: return FSK;
+    default:                return undefined;
+    }
+}
+
+int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping
modShaping)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: mod shaping");
+    #endif
+
+    if (rf69_get_modulation(spi) == FSK)
+    {
+        switch (modShaping) {
+        case shapingOff: return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_NONE);
+        case shaping1_0: return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_1_0);
+        case shaping0_5: return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_0_3);
+        case shaping0_3: return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_0_5);
+        default:     INVALID_PARAM;
+        }
+    }
+    else
+    {
+        switch (modShaping) {
+        case shapingOff: return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_NONE);
+        case shapingBR:     return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_BR);
+        case shaping2BR: return WRITE_REG(REG_DATAMODUL,
(READ_REG(REG_DATAMODUL) & ~MASK_DATAMODUL_MODULATION_SHAPE) |
DATAMODUL_MODULATION_SHAPE_2BR);
+        default:     INVALID_PARAM;
+        }
+    }
+}
+
+int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate)
+{
+    int retval;
+    u32 bitRate_min;
+    u32 bitRate_reg;
+    u8 msb;
+    u8 lsb;
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: bit rate");
+    #endif
+
+    // check input value
+    bitRate_min = F_OSC / 8388608; // 8388608 = 2^23;
+    if (bitRate < bitRate_min)
+    {
+        dev_dbg(&spi->dev, "setBitRate: illegal input param");
+        INVALID_PARAM;
+    }
+
+    // calculate reg settings
+    bitRate_reg = (F_OSC / bitRate);
+
+    msb = (bitRate_reg&0xff00)   >>  8;
+    lsb = (bitRate_reg&0xff);
+
+    // transmit to RF 69
+    retval = WRITE_REG(REG_BITRATE_MSB, msb);
+    if (retval)  return retval;
+    retval = WRITE_REG(REG_BITRATE_LSB, lsb);
+    if (retval)  return retval;
+
+    return 0;
+}
+
+int rf69_set_deviation(struct spi_device *spi, u32 deviation)
+{
+    int retval;
+//    u32 f_max; TODO: Abhängigkeit von Bitrate beachten!!
+    u64 f_reg;
+    u64 f_step;
+    u8 msb;
+    u8 lsb;
+    u64 factor = 1000000; // to improve precision of calculation
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: deviation");
+    #endif
+
+    if (deviation < 600 || deviation > 500000) //TODO: Abhängigkeit von Bitrate
beachten!!
+    {
+        dev_dbg(&spi->dev, "set_deviation: illegal input param");
+        INVALID_PARAM;
+    }
+
+    // calculat f step
+    f_step = F_OSC * factor;
+    do_div(f_step, 524288); //  524288 = 2^19
+
+    // calculate register settings
+    f_reg = deviation * factor;
+    do_div(f_reg  , f_step);
+
+    msb = (f_reg&0xff00)   >>  8;
+    lsb = (f_reg&0xff);
+
+    // check msb
+    if (msb & !FDEVMASB_MASK)
+    {
+        dev_dbg(&spi->dev, "set_deviation: err in calc of msb");
+        INVALID_PARAM;
+    }
+
+    // write to chip
+    retval = WRITE_REG(REG_FDEV_MSB, msb);
+    if (retval)  return retval;
+    retval = WRITE_REG(REG_FDEV_LSB, lsb);
+    if (retval)  return retval;
+
+    return 0;
+}
+
+int rf69_set_frequency(struct spi_device *spi, u32 frequency)
+{
+    int retval;
+    u32 f_max;
+    u64 f_reg;
+    u64 f_step;
+    u8 msb;
+    u8 mid;
+    u8 lsb;
+    u64 factor = 1000000; // to improve precision of calculation
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: frequency");
+    #endif
+
+    // calculat f step
+    f_step = F_OSC * factor;
+    do_div(f_step, 524288); //  524288 = 2^19
+
+    // check input value
+    f_max = f_step * 8388608 / factor;
+    if (frequency > f_max)
+    {
+        dev_dbg(&spi->dev, "setFrequency: illegal input param");
+        INVALID_PARAM;
+    }
+
+    // calculate reg settings
+    f_reg = frequency * factor;
+    do_div(f_reg  , f_step);
+
+    msb = (f_reg&0xff0000) >> 16;
+    mid = (f_reg&0xff00)   >>  8;
+    lsb = (f_reg&0xff);
+
+    // write to chip
+    retval = WRITE_REG(REG_FRF_MSB, msb);
+    if (retval)  return retval;
+    retval = WRITE_REG(REG_FRF_MID, mid);
+    if (retval)  return retval;
+    retval = WRITE_REG(REG_FRF_LSB, lsb);
+    if (retval)  return retval;
+
+    return 0;
+}
+
+int rf69_set_amplifier_0(struct spi_device *spi, enum optionOnOff optionOnOff)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: amp #0");
+    #endif
+
+    switch(optionOnOff) {
+    case optionOn:    return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) |
 MASK_PALEVEL_PA0) );
+    case optionOff:    return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) &
~MASK_PALEVEL_PA0) );
+    default:    INVALID_PARAM;
+    }
+}    
+
+int rf69_set_amplifier_1(struct spi_device *spi, enum optionOnOff optionOnOff)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: amp #1");
+    #endif
+
+    switch(optionOnOff) {
+    case optionOn:    return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) |
 MASK_PALEVEL_PA1) );
+    case optionOff: return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) &
~MASK_PALEVEL_PA1) );
+    default:    INVALID_PARAM;
+    }
+}
+
+int rf69_set_amplifier_2(struct spi_device *spi, enum optionOnOff optionOnOff)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: amp #2");
+    #endif
+
+    switch(optionOnOff) {
+    case optionOn:    return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) |
 MASK_PALEVEL_PA2) );
+    case optionOff:    return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) &
~MASK_PALEVEL_PA2) );
+    default:    INVALID_PARAM;
+    }
+}
+
+int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: power level");
+    #endif
+
+    powerLevel +=18; // TODO Abhängigkeit von PA0,1,2 setting
+
+    // check input value
+    if (powerLevel > 0x1f)
+        INVALID_PARAM;
+
+    // write value
+    return WRITE_REG(REG_PALEVEL, (READ_REG(REG_PALEVEL) &
~MASK_PALEVEL_OUTPUT_POWER) | powerLevel);
+}
+
+int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: pa ramp");
+    #endif
+
+    switch(paRamp) {
+    case ramp3400:    return WRITE_REG(REG_PARAMP, PARAMP_3400);
+    case ramp2000:    return WRITE_REG(REG_PARAMP, PARAMP_2000);
+    case ramp1000:    return WRITE_REG(REG_PARAMP, PARAMP_1000);
+    case ramp500:    return WRITE_REG(REG_PARAMP, PARAMP_500);
+    case ramp250:    return WRITE_REG(REG_PARAMP, PARAMP_250);
+    case ramp125:    return WRITE_REG(REG_PARAMP, PARAMP_125);
+    case ramp100:    return WRITE_REG(REG_PARAMP, PARAMP_100);
+    case ramp62:    return WRITE_REG(REG_PARAMP, PARAMP_62);
+    case ramp50:    return WRITE_REG(REG_PARAMP, PARAMP_50);
+    case ramp40:    return WRITE_REG(REG_PARAMP, PARAMP_40);
+    case ramp31:    return WRITE_REG(REG_PARAMP, PARAMP_31);
+    case ramp25:    return WRITE_REG(REG_PARAMP, PARAMP_25);
+    case ramp20:    return WRITE_REG(REG_PARAMP, PARAMP_20);
+    case ramp15:    return WRITE_REG(REG_PARAMP, PARAMP_15);
+    case ramp12:    return WRITE_REG(REG_PARAMP, PARAMP_12);
+    case ramp10:    return WRITE_REG(REG_PARAMP, PARAMP_10);
+    default:    INVALID_PARAM;
+    }
+}
+
+int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance
antennaImpedance)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: antenna impedance");
+    #endif
+
+    switch(antennaImpedance) {
+    case fiftyOhm:        return WRITE_REG(REG_LNA, (READ_REG(REG_LNA) &
~MASK_LNA_ZIN) );
+    case twohundretOhm: return WRITE_REG(REG_LNA, (READ_REG(REG_LNA) |
 MASK_LNA_ZIN) );
+    default:        INVALID_PARAM;
+    }
+}
+
+int rf69_set_lna_gain(struct spi_device *spi, enum lnaGain lnaGain)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: lna gain");
+    #endif
+
+    switch(lnaGain) {
+    case automatic:     return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_AUTO) );
+    case max:     return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_MAX) );
+    case maxMinus6:  return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_6) );
+    case maxMinus12: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_12) );
+    case maxMinus24: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_24) );
+    case maxMinus36: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_36) );
+    case maxMinus48: return WRITE_REG(REG_LNA, ( (READ_REG(REG_LNA) &
~MASK_LNA_GAIN) & LNA_GAIN_MAX_MINUS_48) );
+    default:     INVALID_PARAM;
+    }
+}
+
+enum lnaGain rf69_get_lna_gain(struct spi_device *spi)
+{
+    u8 currentValue;    
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "get: lna gain");
+    #endif
+
+    currentValue = READ_REG(REG_LNA);
+
+    switch (currentValue & MASK_LNA_CURRENT_GAIN >> 3)  // improvement: change
3 to define
+    {
+    case LNA_GAIN_AUTO:        return automatic;
+    case LNA_GAIN_MAX:        return max;
+    case LNA_GAIN_MAX_MINUS_6:  return maxMinus6;
+    case LNA_GAIN_MAX_MINUS_12: return maxMinus12;
+    case LNA_GAIN_MAX_MINUS_24: return maxMinus24;
+    case LNA_GAIN_MAX_MINUS_36: return maxMinus36;
+    case LNA_GAIN_MAX_MINUS_48: return maxMinus48;
+    default:            return undefined;
+    }
+}
+
+int rf69_set_dc_cut_off_frequency_intern(struct spi_device *spi ,u8 reg, enum
dccPercent dccPercent)
+{
+    switch (dccPercent) {
+    case dcc16Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_16_PERCENT) );
+    case dcc8Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_8_PERCENT) );
+    case dcc4Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_4_PERCENT) );
+    case dcc2Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_2_PERCENT) );
+    case dcc1Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_1_PERCENT) );
+    case dcc0_5Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_0_5_PERCENT) );
+    case dcc0_25Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_0_25_PERCENT) );
+    case dcc0_125Percent:    return WRITE_REG(reg, ( (READ_REG(reg) &
~MASK_BW_DCC_FREQ) | BW_DCC_0_125_PERCENT) );
+    default:        INVALID_PARAM;
+    }
+}
+
+int rf69_set_dc_cut_off_frequency(struct spi_device *spi, enum dccPercent
dccPercent)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: cut off freq");
+    #endif
+
+    return rf69_set_dc_cut_off_frequency_intern(spi, REG_RXBW, dccPercent);
+}
+
+int rf69_set_dc_cut_off_frequency_during_afc(struct spi_device *spi, enum
dccPercent dccPercent)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: cut off freq during afc");
+    #endif
+
+    return rf69_set_dc_cut_off_frequency_intern(spi, REG_AFCBW, dccPercent);
+}
+
+int rf69_set_bandwidth_intern(struct spi_device *spi, u8 reg, enum mantisse
mantisse, u8 exponent)
+{
+    u8 newValue;
+
+    // check value for mantisse and exponent
+    if (exponent > 7)   INVALID_PARAM;
+    if ( (mantisse!=mantisse16) &&
+         (mantisse!=mantisse20) &&
+             (mantisse!=mantisse24) ) INVALID_PARAM;
+
+    // read old value
+    newValue = READ_REG(reg);
+
+    // "delete" mantisse and exponent = just keep the DCC setting
+    newValue = newValue & MASK_BW_DCC_FREQ;
+
+    // add new mantisse
+    switch(mantisse) {
+    case mantisse16: newValue = newValue | BW_MANT_16;    break;
+    case mantisse20: newValue = newValue | BW_MANT_20;    break;
+    case mantisse24: newValue = newValue | BW_MANT_24;    break;
+    }
+
+    // add new exponent
+    newValue = newValue | exponent;
+
+    // write back
+    return WRITE_REG(reg, newValue);
+}
+
+int rf69_set_bandwidth(struct spi_device *spi, enum mantisse mantisse, u8
exponent)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: band width");
+    #endif
+
+    return rf69_set_bandwidth_intern(spi, REG_RXBW, mantisse, exponent);
+}
+
+int rf69_set_bandwidth_during_afc(struct spi_device *spi, enum mantisse
mantisse, u8 exponent)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: band width during afc");
+    #endif
+
+    return rf69_set_bandwidth_intern(spi, REG_AFCBW, mantisse, exponent);
+}
+
+int rf69_set_ook_threshold_type(struct spi_device *spi, enum thresholdType
thresholdType)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: threshold type");
+    #endif
+
+    switch (thresholdType)
+    {
+    case fixed:    return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_FIXED) );
+    case peak:    return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_PEAK) );
+    case average:    return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESTYPE) | OOKPEAK_THRESHTYPE_AVERAGE) );
+    default:    INVALID_PARAM;
+    }
+}
+
+int rf69_set_ook_threshold_step(struct spi_device *spi, enum thresholdStep
thresholdStep)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: threshold step");
+    #endif
+
+    switch (thresholdStep) {
+    case step_0_5db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_0_5_DB) );
+    case step_1_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_1_0_DB) );
+    case step_1_5db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_1_5_DB) );
+    case step_2_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_2_0_DB) );
+    case step_3_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_3_0_DB) );
+    case step_4_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_4_0_DB) );
+    case step_5_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_5_0_DB) );
+    case step_6_0db: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESSTEP) | OOKPEAK_THRESHSTEP_6_0_DB) );
+    default:     INVALID_PARAM;
+    }
+}
+
+int rf69_set_ook_threshold_dec(struct spi_device *spi, enum thresholdDecrement
thresholdDecrement)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: threshold decrement");
+    #endif
+
+    switch (thresholdDecrement) {
+    case dec_every8th: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_8TH) );
+    case dec_every4th: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_4TH) );
+    case dec_every2nd: return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_EVERY_2ND) );
+    case dec_once:       return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK)
& ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_ONCE) );
+    case dec_twice:       return WRITE_REG(REG_OOKPEAK, (
(READ_REG(REG_OOKPEAK) & ~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_TWICE) );
+    case dec_4times:   return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_4_TIMES) );
+    case dec_8times:   return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_8_TIMES) );
+    case dec_16times:  return WRITE_REG(REG_OOKPEAK, ( (READ_REG(REG_OOKPEAK) &
~MASK_OOKPEAK_THRESDEC) | OOKPEAK_THRESHDEC_16_TIMES) );
+    default:       INVALID_PARAM;
+    }
+}
+
+int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value)
+{
+    u8 mask;
+    u8 shift;
+    u8 regaddr;
+    u8 regValue;
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: DIO mapping");
+    #endif
+
+    // check DIO number
+    if (DIONumber > 5) INVALID_PARAM;
+
+    switch (DIONumber) {
+    case 0: mask=MASK_DIO0; shift=SHIFT_DIO0; regaddr=REG_DIOMAPPING1; break;
+    case 1: mask=MASK_DIO1; shift=SHIFT_DIO1; regaddr=REG_DIOMAPPING1; break;
+    case 2: mask=MASK_DIO2; shift=SHIFT_DIO2; regaddr=REG_DIOMAPPING1; break;
+    case 3: mask=MASK_DIO3; shift=SHIFT_DIO3; regaddr=REG_DIOMAPPING1; break;
+    case 4: mask=MASK_DIO4; shift=SHIFT_DIO4; regaddr=REG_DIOMAPPING2; break;
+    case 5: mask=MASK_DIO5; shift=SHIFT_DIO5; regaddr=REG_DIOMAPPING2; break;
+    }
+
+    // read reg
+    regValue=READ_REG(regaddr);
+    // delete old value
+    regValue = regValue & ~mask;
+    // add new value
+    regValue = regValue | value << shift;
+    // write back
+    return WRITE_REG(regaddr,regValue);
+}
+
+bool rf69_get_flag(struct spi_device *spi, enum flag flag)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "get: flag");
+    #endif
+
+    switch(flag) {
+    case modeSwitchCompleted:     return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_MODE_READY);
+    case readyToReceive:          return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_RX_READY);
+    case readyToSend:          return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_TX_READY);
+    case pllLocked:              return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_PLL_LOCK);
+    case rssiExceededThreshold:   return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_RSSI);
+    case timeout:              return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_TIMEOUT);
+    case automode:              return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_AUTOMODE);
+    case syncAddressMatch:          return (READ_REG(REG_IRQFLAGS1) &
MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH);
+    case fifoFull:              return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_FIFO_FULL);
+/*    case fifoNotEmpty:          return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_FIFO_NOT_EMPTY); */
+    case fifoEmpty:              return !(READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_FIFO_NOT_EMPTY);
+    case fifoLevelBelowThreshold: return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_FIFO_LEVEL);
+    case fifoOverrun:          return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_FIFO_OVERRUN);
+    case packetSent:          return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_PACKET_SENT);
+    case payloadReady:          return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_PAYLOAD_READY);
+    case crcOk:              return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_CRC_OK);
+    case batteryLow:          return (READ_REG(REG_IRQFLAGS2) &
MASK_IRQFLAGS2_LOW_BAT);
+    default:              return false;
+    }
+}
+
+int rf69_reset_flag(struct spi_device *spi, enum flag flag)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "reset: flag");
+    #endif
+
+    switch(flag) {
+    case rssiExceededThreshold: return WRITE_REG(REG_IRQFLAGS1,
MASK_IRQFLAGS1_RSSI);
+    case syncAddressMatch:        return WRITE_REG(REG_IRQFLAGS1,
MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH);
+    case fifoOverrun:        return WRITE_REG(REG_IRQFLAGS2,
MASK_IRQFLAGS2_FIFO_OVERRUN);
+    default:            INVALID_PARAM;
+    }
+}
+
+int rf69_set_rssi_threshold(struct spi_device *spi, u8 threshold)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: rssi threshold");
+    #endif
+
+    /* no value check needed - u8 exactly matches register size */
+
+    return WRITE_REG(REG_RSSITHRESH, threshold);
+}
+
+int rf69_set_rx_start_timeout(struct spi_device *spi, u8 timeout)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: start timeout");
+    #endif
+
+    /* no value check needed - u8 exactly matches register size */
+
+    return WRITE_REG(REG_RXTIMEOUT1, timeout);
+}
+
+int rf69_set_rssi_timeout(struct spi_device *spi, u8 timeout)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: rssi timeout");
+    #endif
+
+    /* no value check needed - u8 exactly matches register size */
+
+    return WRITE_REG(REG_RXTIMEOUT2, timeout);
+}
+
+int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength)
+{
+    int retval;
+    u8 msb, lsb;
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: preample length");
+    #endif
+
+    /* no value check needed - u16 exactly matches register size */
+
+    /* calculate reg settings */
+    msb = (preambleLength&0xff00)   >>  8;
+    lsb = (preambleLength&0xff);
+
+    /* transmit to chip */
+    retval = WRITE_REG(REG_PREAMBLE_MSB, msb);
+    if (retval) return retval;
+    retval = WRITE_REG(REG_PREAMBLE_LSB, lsb);
+
+    return retval;
+}
+
+int rf69_set_sync_enable(struct spi_device *spi, enum optionOnOff optionOnOff)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: sync enable");
+    #endif
+
+    switch(optionOnOff) {
+    case optionOn:    return WRITE_REG(REG_SYNC_CONFIG,
(READ_REG(REG_SYNC_CONFIG) |  MASK_SYNC_CONFIG_SYNC_ON) );
+    case optionOff:    return WRITE_REG(REG_SYNC_CONFIG,
(READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_SYNC_ON) );
+    default:    INVALID_PARAM;
+    }
+}
+
+int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition
fifoFillCondition)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: fifo fill condition");
+    #endif
+
+    switch(fifoFillCondition) {
+    case always:         return WRITE_REG(REG_SYNC_CONFIG,
(READ_REG(REG_SYNC_CONFIG) |  MASK_SYNC_CONFIG_FIFO_FILL_CONDITION) );
+    case afterSyncInterrupt: return WRITE_REG(REG_SYNC_CONFIG,
(READ_REG(REG_SYNC_CONFIG) & ~MASK_SYNC_CONFIG_FIFO_FILL_CONDITION) );
+    default:         INVALID_PARAM;
+    }
+}
+
+int rf69_set_sync_size(struct spi_device *spi, u8 syncSize)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: sync size");
+    #endif
+
+    // check input value
+    if (syncSize > 0x07)
+        INVALID_PARAM;
+
+    // write value
+    return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) &
~MASK_SYNC_CONFIG_SYNC_SIZE) | (syncSize << 3) );
+}
+
+int rf69_set_sync_tolerance(struct spi_device *spi, u8 syncTolerance)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: sync tolerance");
+    #endif
+
+    // check input value
+    if (syncTolerance > 0x07)
+        INVALID_PARAM;
+
+    // write value
+    return WRITE_REG(REG_SYNC_CONFIG, (READ_REG(REG_SYNC_CONFIG) &
~MASK_SYNC_CONFIG_SYNC_SIZE) | syncTolerance);
+}
+
+int rf69_set_sync_values(struct spi_device *spi, u8 syncValues[8])
+{
+    int retval = 0;
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: sync values");
+    #endif
+
+    retval += WRITE_REG(REG_SYNCVALUE1, syncValues[0]);
+    retval += WRITE_REG(REG_SYNCVALUE2, syncValues[1]);
+    retval += WRITE_REG(REG_SYNCVALUE3, syncValues[2]);
+    retval += WRITE_REG(REG_SYNCVALUE4, syncValues[3]);
+    retval += WRITE_REG(REG_SYNCVALUE5, syncValues[4]);
+    retval += WRITE_REG(REG_SYNCVALUE6, syncValues[5]);
+    retval += WRITE_REG(REG_SYNCVALUE7, syncValues[6]);
+    retval += WRITE_REG(REG_SYNCVALUE8, syncValues[7]);
+
+    return retval;
+}
+
+int rf69_set_packet_format(struct spi_device * spi, enum packetFormat
packetFormat)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: packet format");
+    #endif
+
+    switch(packetFormat) {
+    case packetLengthVar: return WRITE_REG(REG_PACKETCONFIG1,
(READ_REG(REG_PACKETCONFIG1) |  MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE) );
+    case packetLengthFix: return WRITE_REG(REG_PACKETCONFIG1,
(READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE) );
+    default:          INVALID_PARAM;
+    }
+}
+
+int rf69_set_crc_enable(struct spi_device *spi, enum optionOnOff optionOnOff)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: crc enable");
+    #endif
+
+    switch(optionOnOff) {
+    case optionOn:    return WRITE_REG(REG_PACKETCONFIG1,
(READ_REG(REG_PACKETCONFIG1) |  MASK_PACKETCONFIG1_CRC_ON) );
+    case optionOff:    return WRITE_REG(REG_PACKETCONFIG1,
(READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_CRC_ON) );
+    default:    INVALID_PARAM;
+    }
+}
+
+int rf69_set_adressFiltering(struct spi_device *spi, enum addressFiltering
addressFiltering)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: address filtering");
+    #endif
+
+    switch (addressFiltering) {
+    case filteringOff:         return WRITE_REG(REG_PACKETCONFIG1, (
(READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) |
PACKETCONFIG1_ADDRESSFILTERING_OFF) );
+    case nodeAddress:         return WRITE_REG(REG_PACKETCONFIG1, (
(READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) |
PACKETCONFIG1_ADDRESSFILTERING_NODE) );
+    case nodeOrBroadcastAddress: return WRITE_REG(REG_PACKETCONFIG1, (
(READ_REG(REG_PACKETCONFIG1) & ~MASK_PACKETCONFIG1_ADDRESSFILTERING) |
PACKETCONFIG1_ADDRESSFILTERING_NODEBROADCAST) );
+    default:             INVALID_PARAM;
+    }
+}
+
+int rf69_set_payload_length(struct spi_device *spi, u8 payloadLength)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: payload length");
+    #endif
+
+    return WRITE_REG(REG_PAYLOAD_LENGTH, payloadLength);
+}
+
+u8  rf69_get_payload_length(struct spi_device *spi)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "get: payload length");
+    #endif
+
+    return (u8) READ_REG(REG_PAYLOAD_LENGTH);
+}
+
+int rf69_set_node_address(struct spi_device *spi, u8 nodeAddress)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: node address");
+    #endif
+
+    return WRITE_REG(REG_NODEADRS, nodeAddress);
+}
+
+int rf69_set_broadcast_address(struct spi_device *spi, u8 broadcastAddress)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: broadcast address");
+    #endif
+
+    return WRITE_REG(REG_BROADCASTADRS, broadcastAddress);
+}
+
+int rf69_set_tx_start_condition(struct spi_device *spi, enum txStartCondition
txStartCondition)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: start condition");
+    #endif
+
+    switch(txStartCondition) {
+    case fifoLevel:       return WRITE_REG(REG_FIFO_THRESH,
(READ_REG(REG_FIFO_THRESH) & ~MASK_FIFO_THRESH_TXSTART) );
+    case fifoNotEmpty: return WRITE_REG(REG_FIFO_THRESH,
(READ_REG(REG_FIFO_THRESH) |  MASK_FIFO_THRESH_TXSTART) );
+    default:       INVALID_PARAM;
+    }
+}
+
+int rf69_set_fifo_threshold(struct spi_device *spi, u8 threshold)
+{
+    int retval;
+
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: fifo threshold");
+    #endif
+
+    // check input value
+    if (threshold & 0x80)
+        INVALID_PARAM;
+
+    // write value
+    retval = WRITE_REG(REG_FIFO_THRESH, (READ_REG(REG_FIFO_THRESH) &
~MASK_FIFO_THRESH_VALUE) | threshold);
+    if (retval)
+        return retval;
+
+    // access the fifo to activate new threshold
+    return rf69_read_fifo (spi, (u8*) &retval, 1); // retval used as buffer
+}
+
+int rf69_set_dagc(struct spi_device *spi, enum dagc dagc)
+{
+    #ifdef DEBUG
+        dev_dbg(&spi->dev, "set: dagc");
+    #endif
+
+    switch(dagc) {
+    case normalMode:         return WRITE_REG(REG_TESTDAGC, DAGC_NORMAL);
+    case improve:             return WRITE_REG(REG_TESTDAGC,
DAGC_IMPROVED_LOWBETA0);
+    case improve4LowModulationIndex: return WRITE_REG(REG_TESTDAGC,
DAGC_IMPROVED_LOWBETA1);
+    default:             INVALID_PARAM;
+    }
+}
+
+/*-------------------------------------------------------------------------*/
+
+int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size)
+{
+    #ifdef DEBUG_FIFO_ACCESS    
+        int i;
+    #endif
+    struct spi_transfer transfer;
+    u8 local_buffer[FIFO_SIZE + 1];
+    int retval;
+
+    if (size > FIFO_SIZE)
+    {
+        #ifdef DEBUG
+            dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then
internal buffer \n");
+        #endif
+        return -EMSGSIZE;
+    }
+
+    /* prepare a bidirectional transfer */
+    local_buffer[0] = REG_FIFO;
+    memset(&transfer, 0, sizeof(transfer));
+      transfer.tx_buf = local_buffer;
+      transfer.rx_buf = local_buffer;
+    transfer.len    = size+1;
+
+    retval = spi_sync_transfer(spi, &transfer, 1);
+
+    #ifdef DEBUG_FIFO_ACCESS
+        for (i=0; i<size; i++)
+            dev_dbg(&spi->dev, "%d - 0x%x\n", i, local_buffer[i+1]);
+    #endif
+
+    memcpy(buffer, &local_buffer[1], size);  // TODO: ohne memcopy wäre schöner
+
+    return retval;
+}
+
+int rf69_write_fifo(struct spi_device *spi, u8 *buffer, unsigned int size)
+{
+    #ifdef DEBUG_FIFO_ACCESS    
+        int i;
+    #endif
+    char spi_address = REG_FIFO | WRITE_BIT;
+    u8 local_buffer[FIFO_SIZE + 1];
+
+    if (size > FIFO_SIZE)
+    {
+        #ifdef DEBUG
+            dev_dbg(&spi->dev, "read fifo: passed in buffer bigger then
internal buffer \n");
+        #endif
+        return -EMSGSIZE;
+    }
+
+    local_buffer[0] = spi_address;
+    memcpy(&local_buffer[1], buffer, size);  // TODO: ohne memcopy wäre schöner
+
+    #ifdef DEBUG_FIFO_ACCESS
+        for (i=0; i<size; i++)
+            dev_dbg(&spi->dev, "0x%x\n",buffer[i]);
+    #endif
+
+    return spi_write (spi, local_buffer, size + 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+u8 rf69_read_reg(struct spi_device *spi, u8 addr)
+{
+    int retval;
+
+    retval = spi_w8r8(spi, addr);
+
+    #ifdef DEBUG_VALUES
+        if (retval < 0)
+            /* should never happen, since we already checked,
+               that module is connected. Therefore no error
+               handling, just an optional error message... */
+            dev_dbg(&spi->dev, "read 0x%x FAILED\n",
+                addr);
+        else
+            dev_dbg(&spi->dev, "read 0x%x from reg 0x%x\n",
+                retval,
+                addr);
+    #endif
+
+    return retval;
+}
+
+int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value)
+{
+    int retval;
+    char buffer[2];
+    
+    buffer[0] = addr | WRITE_BIT;
+    buffer[1] = value;
+
+    retval = spi_write(spi, &buffer, 2);
+
+    #ifdef DEBUG_VALUES
+        if (retval < 0)
+            /* should never happen, since we already checked,
+               that module is connected. Therefore no error
+               handling, just an optional error message... */
+            dev_dbg(&spi->dev, "write 0x%x to 0x%x FAILED\n",
+                value,
+                addr);
+        else
+            dev_dbg(&spi->dev, "wrote 0x%x to reg 0x%x\n",
+                value,
+                addr);
+    #endif
+
+    return retval;
+}
+
+
diff --git a/drivers/staging/pi433/rf69.h b/drivers/staging/pi433/rf69.h
new file mode 100644
index 0000000..6a6841b
--- /dev/null
+++ b/drivers/staging/pi433/rf69.h
@@ -0,0 +1,82 @@
+/*
+ * hardware abstraction/register access for HopeRf rf69 radio module
+ *
+ * Copyright (C) 2016 Wolf-Entwicklungen
+ *    Marcus Wolf <linux@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef RF69_H
+#define RF69_H
+
+#include "rf69_enum.h"
+#include "rf69_registers.h"
+
+#define F_OSC         32000000  /* in Hz */
+#define FREQUENCY    433920000 /* in Hz, modifying this value impacts CE
certification */
+#define FIFO_SIZE     66        /* in byte */
+#define FIFO_THRESHOLD    15       /* in byte */
+
+int rf69_set_mode(struct spi_device *spi, enum mode mode);
+int rf69_set_data_mode(struct spi_device *spi, enum dataMode dataMode);
+int rf69_set_modulation(struct spi_device *spi, enum modulation modulation);
+enum modulation rf69_get_modulation(struct spi_device *spi);
+int rf69_set_modulation_shaping(struct spi_device *spi, enum modShaping
modShaping);
+int rf69_set_bit_rate(struct spi_device *spi, u16 bitRate);
+int rf69_set_deviation(struct spi_device *spi, u32 deviation);
+int rf69_set_frequency(struct spi_device *spi, u32 frequency);
+int rf69_set_amplifier_0(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_set_amplifier_1(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_set_amplifier_2(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_set_output_power_level(struct spi_device *spi, u8 powerLevel);
+int rf69_set_pa_ramp(struct spi_device *spi, enum paRamp paRamp);
+int rf69_set_antenna_impedance(struct spi_device *spi, enum antennaImpedance
antennaImpedance);
+int rf69_set_lna_gain(struct spi_device *spi, enum lnaGain lnaGain);
+enum lnaGain rf69_get_lna_gain(struct spi_device *spi);
+int rf69_set_dc_cut_off_frequency_intern(struct spi_device *spi, u8 reg, enum
dccPercent dccPercent);
+int rf69_set_dc_cut_off_frequency(struct spi_device *spi, enum dccPercent
dccPercent);
+int rf69_set_dc_cut_off_frequency_during_afc(struct spi_device *spi, enum
dccPercent dccPercent);
+int rf69_set_bandwidth(struct spi_device *spi, enum mantisse mantisse, u8
exponent);
+int rf69_set_bandwidth_during_afc(struct spi_device *spi, enum mantisse
mantisse, u8 exponent);
+int rf69_set_ook_threshold_type(struct spi_device *spi, enum thresholdType
thresholdType);
+int rf69_set_ook_threshold_step(struct spi_device *spi, enum thresholdStep
thresholdStep);
+int rf69_set_ook_threshold_dec(struct spi_device *spi, enum thresholdDecrement
thresholdDecrement);
+int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value);
+bool rf69_get_flag(struct spi_device *spi, enum flag flag);
+int rf69_reset_flag(struct spi_device *spi, enum flag flag);
+int rf69_set_rssi_threshold(struct spi_device *spi, u8 threshold);
+int rf69_set_rx_start_timeout(struct spi_device *spi, u8 timeout);
+int rf69_set_rssi_timeout(struct spi_device *spi, u8 timeout);
+int rf69_set_preamble_length(struct spi_device *spi, u16 preambleLength);
+int rf69_set_sync_enable(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_set_fifo_fill_condition(struct spi_device *spi, enum fifoFillCondition
fifoFillCondition);
+int rf69_set_sync_size(struct spi_device *spi, u8 sync_size);
+int rf69_set_sync_tolerance(struct spi_device *spi, u8 syncTolerance);
+int rf69_set_sync_values(struct spi_device *spi, u8 syncValues[8]);
+int rf69_set_packet_format(struct spi_device * spi, enum packetFormat
packetFormat);
+int rf69_set_crc_enable(struct spi_device *spi, enum optionOnOff optionOnOff);
+int rf69_set_adressFiltering(struct spi_device *spi, enum addressFiltering
addressFiltering);
+int rf69_set_payload_length(struct spi_device *spi, u8 payloadLength);
+u8  rf69_get_payload_length(struct spi_device *spi);
+int rf69_set_node_address(struct spi_device *spi, u8 nodeAddress);
+int rf69_set_broadcast_address(struct spi_device *spi, u8 broadcastAddress);
+int rf69_set_tx_start_condition(struct spi_device *spi, enum txStartCondition
txStartCondition);
+int rf69_set_fifo_threshold(struct spi_device *spi, u8 threshold);
+int rf69_set_dagc(struct spi_device *spi, enum dagc dagc);
+
+int rf69_read_fifo (struct spi_device *spi, u8 *buffer, unsigned int size);
+int rf69_write_fifo(struct spi_device *spi, u8 *buffer, unsigned int size);
+
+u8  rf69_read_reg (struct spi_device *spi, u8 addr);
+int rf69_write_reg(struct spi_device *spi, u8 addr, u8 value);
+
+
+#endif
diff --git a/drivers/staging/pi433/rf69_enum.h
b/drivers/staging/pi433/rf69_enum.h
new file mode 100644
index 0000000..fbfb59b
--- /dev/null
+++ b/drivers/staging/pi433/rf69_enum.h
@@ -0,0 +1,201 @@
+/*
+ * enumerations for HopeRf rf69 radio module
+ *
+ * Copyright (C) 2016 Wolf-Entwicklungen
+ *    Marcus Wolf <linux@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef RF69_ENUM_H
+#define RF69_ENUM_H
+
+enum optionOnOff
+{
+    optionOff,
+    optionOn
+};
+
+enum mode
+{
+    mode_sleep,
+    standby,
+    synthesizer,
+    transmit,
+    receive
+};
+
+enum dataMode
+{
+    packet,
+    continuous,
+    continuousNoSync
+};
+
+enum modulation
+{
+    OOK,
+    FSK
+};
+
+enum modShaping
+{
+    shapingOff,
+    shaping1_0,
+    shaping0_5,
+    shaping0_3,
+    shapingBR,
+    shaping2BR
+};
+
+enum paRamp
+{
+    ramp3400,
+    ramp2000,
+    ramp1000,
+    ramp500,
+    ramp250,
+    ramp125,
+    ramp100,
+    ramp62,
+    ramp50,
+    ramp40,
+    ramp31,
+    ramp25,
+    ramp20,
+    ramp15,
+    ramp12,
+    ramp10
+};
+
+enum antennaImpedance
+{
+    fiftyOhm,
+    twohundretOhm
+};
+
+enum lnaGain
+{
+    automatic,
+    max,
+    maxMinus6,
+    maxMinus12,
+    maxMinus24,
+    maxMinus36,
+    maxMinus48,
+    undefined
+};
+
+enum dccPercent
+{
+    dcc16Percent,
+    dcc8Percent,
+    dcc4Percent,
+    dcc2Percent,
+    dcc1Percent,
+    dcc0_5Percent,
+    dcc0_25Percent,
+    dcc0_125Percent
+};
+
+enum mantisse
+{
+    mantisse16,
+    mantisse20,
+    mantisse24
+};
+
+enum thresholdType
+{
+    fixed,
+    peak,
+    average
+};
+
+enum thresholdStep
+{
+    step_0_5db,
+    step_1_0db,
+    step_1_5db,
+    step_2_0db,
+    step_3_0db,
+    step_4_0db,
+    step_5_0db,
+    step_6_0db
+};
+
+enum thresholdDecrement
+{
+    dec_every8th,
+    dec_every4th,
+    dec_every2nd,
+    dec_once,
+    dec_twice,
+    dec_4times,
+    dec_8times,
+    dec_16times
+};
+
+enum flag
+{
+    modeSwitchCompleted,
+    readyToReceive,
+    readyToSend,
+    pllLocked,
+    rssiExceededThreshold,
+    timeout,
+    automode,
+    syncAddressMatch,
+    fifoFull,
+//    fifoNotEmpty, collision with next enum; replaced by following enum...
+    fifoEmpty,
+    fifoLevelBelowThreshold,
+    fifoOverrun,
+    packetSent,
+    payloadReady,
+    crcOk,
+    batteryLow
+};
+
+enum fifoFillCondition
+{
+    afterSyncInterrupt,
+    always
+};
+
+enum packetFormat
+{
+    packetLengthFix,
+    packetLengthVar
+};
+
+enum txStartCondition
+{
+    fifoLevel,
+    fifoNotEmpty
+};
+
+enum addressFiltering
+{
+    filteringOff,
+    nodeAddress,
+    nodeOrBroadcastAddress
+};
+
+enum dagc
+{
+    normalMode,
+    improve,
+    improve4LowModulationIndex
+};
+
+
+#endif
diff --git a/drivers/staging/pi433/rf69_registers.h
b/drivers/staging/pi433/rf69_registers.h
new file mode 100644
index 0000000..d0c4992
--- /dev/null
+++ b/drivers/staging/pi433/rf69_registers.h
@@ -0,0 +1,489 @@
+/*
+ * register description for HopeRf rf69 radio module
+ *
+ * Copyright (C) 2016 Wolf-Entwicklungen
+ *    Marcus Wolf <linux@xxxxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*******************************************/
+/* RF69 register addresses           */
+/*******************************************/
+#define  REG_FIFO            0x00
+#define  REG_OPMODE            0x01
+#define  REG_DATAMODUL            0x02
+#define  REG_BITRATE_MSB        0x03
+#define  REG_BITRATE_LSB        0x04
+#define  REG_FDEV_MSB            0x05
+#define  REG_FDEV_LSB            0x06
+#define  REG_FRF_MSB            0x07
+#define  REG_FRF_MID            0x08
+#define  REG_FRF_LSB            0x09
+#define  REG_OSC1            0x0A
+#define  REG_AFCCTRL            0x0B
+#define  REG_LOWBAT            0x0C
+#define  REG_LISTEN1            0x0D
+#define  REG_LISTEN2            0x0E
+#define  REG_LISTEN3            0x0F
+#define  REG_VERSION            0x10
+#define  REG_PALEVEL            0x11
+#define  REG_PARAMP            0x12
+#define  REG_OCP            0x13
+#define  REG_AGCREF            0x14 /* not available on RF69 */
+#define  REG_AGCTHRESH1            0x15 /* not available on RF69 */
+#define  REG_AGCTHRESH2            0x16 /* not available on RF69 */
+#define  REG_AGCTHRESH3            0x17 /* not available on RF69 */
+#define  REG_LNA            0x18
+#define  REG_RXBW            0x19
+#define  REG_AFCBW            0x1A
+#define  REG_OOKPEAK            0x1B
+#define  REG_OOKAVG            0x1C
+#define  REG_OOKFIX            0x1D
+#define  REG_AFCFEI            0x1E
+#define  REG_AFCMSB            0x1F
+#define  REG_AFCLSB            0x20
+#define  REG_FEIMSB            0x21
+#define  REG_FEILSB            0x22
+#define  REG_RSSICONFIG            0x23
+#define  REG_RSSIVALUE            0x24
+#define  REG_DIOMAPPING1        0x25
+#define  REG_DIOMAPPING2        0x26
+#define  REG_IRQFLAGS1            0x27
+#define  REG_IRQFLAGS2            0x28
+#define  REG_RSSITHRESH            0x29
+#define  REG_RXTIMEOUT1            0x2A
+#define  REG_RXTIMEOUT2            0x2B
+#define  REG_PREAMBLE_MSB        0x2C
+#define  REG_PREAMBLE_LSB        0x2D
+#define  REG_SYNC_CONFIG        0x2E
+#define  REG_SYNCVALUE1            0x2F
+#define  REG_SYNCVALUE2            0x30
+#define  REG_SYNCVALUE3            0x31
+#define  REG_SYNCVALUE4            0x32
+#define  REG_SYNCVALUE5            0x33
+#define  REG_SYNCVALUE6            0x34
+#define  REG_SYNCVALUE7            0x35
+#define  REG_SYNCVALUE8            0x36
+#define  REG_PACKETCONFIG1        0x37
+#define  REG_PAYLOAD_LENGTH        0x38
+#define  REG_NODEADRS            0x39
+#define  REG_BROADCASTADRS        0x3A
+#define  REG_AUTOMODES            0x3B
+#define  REG_FIFO_THRESH        0x3C
+#define  REG_PACKETCONFIG2        0x3D
+#define  REG_AESKEY1            0x3E
+#define  REG_AESKEY2            0x3F
+#define  REG_AESKEY3            0x40
+#define  REG_AESKEY4            0x41
+#define  REG_AESKEY5            0x42
+#define  REG_AESKEY6            0x43
+#define  REG_AESKEY7            0x44
+#define  REG_AESKEY8            0x45
+#define  REG_AESKEY9            0x46
+#define  REG_AESKEY10            0x47
+#define  REG_AESKEY11            0x48
+#define  REG_AESKEY12            0x49
+#define  REG_AESKEY13            0x4A
+#define  REG_AESKEY14            0x4B
+#define  REG_AESKEY15            0x4C
+#define  REG_AESKEY16            0x4D
+#define  REG_TEMP1            0x4E
+#define  REG_TEMP2            0x4F
+#define  REG_TESTPA1            0x5A /* only present on RFM69HW */
+#define  REG_TESTPA2            0x5C /* only present on RFM69HW */
+#define  REG_TESTDAGC            0x6F
+
+/******************************************************/
+/* RF69/SX1231 bit definition                */
+/******************************************************/
+/* write bit */
+#define WRITE_BIT                0x80
+
+/* RegOpMode */
+#define  MASK_OPMODE_SEQUENCER_OFF        0x80
+#define  MASK_OPMODE_LISTEN_ON            0x40
+#define  MASK_OPMODE_LISTEN_ABORT        0x20
+#define  MASK_OPMODE_MODE            0x1C
+
+#define  OPMODE_MODE_SLEEP            0x00
+#define  OPMODE_MODE_STANDBY            0x04 /* default */
+#define  OPMODE_MODE_SYNTHESIZER        0x08
+#define  OPMODE_MODE_TRANSMIT            0x0C
+#define  OPMODE_MODE_RECEIVE            0x10
+
+/* RegDataModul */
+#define  MASK_DATAMODUL_MODE            0x06
+#define  MASK_DATAMODUL_MODULATION_TYPE        0x18
+#define  MASK_DATAMODUL_MODULATION_SHAPE    0x03
+
+#define  DATAMODUL_MODE_PACKET            0x00 /* default */
+#define  DATAMODUL_MODE_CONTINUOUS        0x40
+#define  DATAMODUL_MODE_CONTINUOUS_NOSYNC    0x60
+
+#define  DATAMODUL_MODULATION_TYPE_FSK        0x00 /* default */
+#define  DATAMODUL_MODULATION_TYPE_OOK        0x08
+
+#define  DATAMODUL_MODULATION_SHAPE_NONE    0x00 /* default */
+#define  DATAMODUL_MODULATION_SHAPE_1_0        0x01
+#define  DATAMODUL_MODULATION_SHAPE_0_5        0x02
+#define  DATAMODUL_MODULATION_SHAPE_0_3        0x03
+#define  DATAMODUL_MODULATION_SHAPE_BR        0x01
+#define  DATAMODUL_MODULATION_SHAPE_2BR        0x02
+
+/* RegFDevMsb (0x05)*/
+#define FDEVMASB_MASK                0x3f
+
+/*
+// RegOsc1
+#define  OSC1_RCCAL_START            0x80
+#define  OSC1_RCCAL_DONE            0x40
+
+// RegLowBat
+#define  LOWBAT_MONITOR                0x10
+#define  LOWBAT_ON                0x08
+#define  LOWBAT_OFF                0x00  // Default
+
+#define  LOWBAT_TRIM_1695            0x00
+#define  LOWBAT_TRIM_1764            0x01
+#define  LOWBAT_TRIM_1835            0x02  // Default
+#define  LOWBAT_TRIM_1905            0x03
+#define  LOWBAT_TRIM_1976            0x04
+#define  LOWBAT_TRIM_2045            0x05
+#define  LOWBAT_TRIM_2116            0x06
+#define  LOWBAT_TRIM_2185            0x07
+
+
+// RegListen1
+#define  LISTEN1_RESOL_64            0x50
+#define  LISTEN1_RESOL_4100            0xA0  // Default
+#define  LISTEN1_RESOL_262000            0xF0
+
+#define  LISTEN1_CRITERIA_RSSI            0x00  // Default
+#define  LISTEN1_CRITERIA_RSSIANDSYNC        0x08
+
+#define  LISTEN1_END_00                0x00
+#define  LISTEN1_END_01                0x02  // Default
+#define  LISTEN1_END_10                0x04
+
+
+// RegListen2
+#define  LISTEN2_COEFIDLE_VALUE            0xF5 // Default
+
+// RegListen3
+#define  LISTEN3_COEFRX_VALUE            0x20 // Default
+*/
+
+// RegPaLevel
+#define  MASK_PALEVEL_PA0            0x80
+#define  MASK_PALEVEL_PA1            0x40
+#define  MASK_PALEVEL_PA2            0x20
+#define  MASK_PALEVEL_OUTPUT_POWER        0x1F
+
+
+
+// RegPaRamp
+#define  PARAMP_3400                0x00
+#define  PARAMP_2000                0x01
+#define  PARAMP_1000                0x02
+#define  PARAMP_500                0x03
+#define  PARAMP_250                0x04
+#define  PARAMP_125                0x05
+#define  PARAMP_100                0x06
+#define  PARAMP_62                0x07
+#define  PARAMP_50                0x08
+#define  PARAMP_40                0x09 /* default */
+#define  PARAMP_31                0x0A
+#define  PARAMP_25                0x0B
+#define  PARAMP_20                0x0C
+#define  PARAMP_15                0x0D
+#define  PARAMP_12                0x0E
+#define  PARAMP_10                0x0F
+
+#define  MASK_PARAMP                0x0F
+
+/*
+// RegOcp
+#define  OCP_OFF                0x0F
+#define  OCP_ON                    0x1A  // Default
+
+#define  OCP_TRIM_45                0x00
+#define  OCP_TRIM_50                0x01
+#define  OCP_TRIM_55                0x02
+#define  OCP_TRIM_60                0x03
+#define  OCP_TRIM_65                0x04
+#define  OCP_TRIM_70                0x05
+#define  OCP_TRIM_75                0x06
+#define  OCP_TRIM_80                0x07
+#define  OCP_TRIM_85                0x08
+#define  OCP_TRIM_90                0x09
+#define  OCP_TRIM_95                0x0A
+#define  OCP_TRIM_100                0x0B  // Default
+#define  OCP_TRIM_105                0x0C
+#define  OCP_TRIM_110                0x0D
+#define  OCP_TRIM_115                0x0E
+#define  OCP_TRIM_120                0x0F
+*/
+
+/* RegLna (0x18) */
+#define  MASK_LNA_ZIN                0x80
+#define  MASK_LNA_CURRENT_GAIN            0x38
+#define  MASK_LNA_GAIN                0x07
+
+#define  LNA_GAIN_AUTO                0x00 /* default */
+#define  LNA_GAIN_MAX                0x01
+#define  LNA_GAIN_MAX_MINUS_6            0x02
+#define  LNA_GAIN_MAX_MINUS_12            0x03
+#define  LNA_GAIN_MAX_MINUS_24            0x04
+#define  LNA_GAIN_MAX_MINUS_36            0x05
+#define  LNA_GAIN_MAX_MINUS_48            0x06
+
+
+/* RegRxBw (0x19) and RegAfcBw (0x1A) */
+#define  MASK_BW_DCC_FREQ            0xE0
+#define  MASK_BW_MANTISSE            0x18
+#define  MASK_BW_EXPONENT            0x07
+
+#define  BW_DCC_16_PERCENT            0x00
+#define  BW_DCC_8_PERCENT            0x20
+#define  BW_DCC_4_PERCENT            0x40 /* default */
+#define  BW_DCC_2_PERCENT            0x60
+#define  BW_DCC_1_PERCENT            0x80
+#define  BW_DCC_0_5_PERCENT            0xA0
+#define  BW_DCC_0_25_PERCENT            0xC0
+#define  BW_DCC_0_125_PERCENT            0xE0
+
+#define  BW_MANT_16                0x00
+#define  BW_MANT_20                0x08
+#define  BW_MANT_24                0x10 /* default */
+
+
+/* RegOokPeak (0x1B) */
+#define  MASK_OOKPEAK_THRESTYPE            0xc0
+#define  MASK_OOKPEAK_THRESSTEP            0x38
+#define  MASK_OOKPEAK_THRESDEC            0x07
+
+#define  OOKPEAK_THRESHTYPE_FIXED        0x00
+#define  OOKPEAK_THRESHTYPE_PEAK        0x40 /* default */
+#define  OOKPEAK_THRESHTYPE_AVERAGE        0x80
+
+#define  OOKPEAK_THRESHSTEP_0_5_DB        0x00 /* default */
+#define  OOKPEAK_THRESHSTEP_1_0_DB        0x08
+#define  OOKPEAK_THRESHSTEP_1_5_DB        0x10
+#define  OOKPEAK_THRESHSTEP_2_0_DB        0x18
+#define  OOKPEAK_THRESHSTEP_3_0_DB        0x20
+#define  OOKPEAK_THRESHSTEP_4_0_DB        0x28
+#define  OOKPEAK_THRESHSTEP_5_0_DB        0x30
+#define  OOKPEAK_THRESHSTEP_6_0_DB        0x38
+
+#define  OOKPEAK_THRESHDEC_ONCE            0x00 /* default */
+#define  OOKPEAK_THRESHDEC_EVERY_2ND        0x01
+#define  OOKPEAK_THRESHDEC_EVERY_4TH        0x02
+#define  OOKPEAK_THRESHDEC_EVERY_8TH        0x03
+#define  OOKPEAK_THRESHDEC_TWICE        0x04
+#define  OOKPEAK_THRESHDEC_4_TIMES        0x05
+#define  OOKPEAK_THRESHDEC_8_TIMES        0x06
+#define  OOKPEAK_THRESHDEC_16_TIMES        0x07
+
+/*
+// RegOokAvg
+#define  OOKAVG_AVERAGETHRESHFILT_00        0x00
+#define  OOKAVG_AVERAGETHRESHFILT_01        0x40
+#define  OOKAVG_AVERAGETHRESHFILT_10        0x80  // Default
+#define  OOKAVG_AVERAGETHRESHFILT_11        0xC0
+
+
+// RegAfcFei
+#define  AFCFEI_FEI_DONE            0x40
+#define  AFCFEI_FEI_START            0x20
+#define  AFCFEI_AFC_DONE            0x10
+#define  AFCFEI_AFCAUTOCLEAR_ON            0x08
+#define  AFCFEI_AFCAUTOCLEAR_OFF        0x00  // Default
+
+#define  AFCFEI_AFCAUTO_ON            0x04
+#define  AFCFEI_AFCAUTO_OFF            0x00  // Default
+
+#define  AFCFEI_AFC_CLEAR            0x02
+#define  AFCFEI_AFC_START            0x01
+
+// RegRssiConfig
+#define  RSSI_FASTRX_ON                0x08
+#define  RSSI_FASTRX_OFF            0x00  // Default
+#define  RSSI_DONE                0x02
+#define  RSSI_START                0x01
+*/
+
+/* RegDioMapping1 */
+#define  MASK_DIO0                0xC0
+#define  MASK_DIO1                0x30
+#define  MASK_DIO2                0x0C
+#define  MASK_DIO3                0x03
+#define  SHIFT_DIO0                6
+#define  SHIFT_DIO1                4
+#define  SHIFT_DIO2                2
+#define  SHIFT_DIO3                0
+
+/* RegDioMapping2 */
+#define  MASK_DIO4                0xC0
+#define  MASK_DIO5                0x30
+#define  SHIFT_DIO4                6
+#define  SHIFT_DIO5                4
+
+/* DIO numbers */
+#define  DIO0                    0
+#define  DIO1                    1
+#define  DIO2                    2
+#define  DIO3                    3
+#define  DIO4                    4
+#define  DIO5                    5
+
+/* DIO Mapping values (packet mode) */
+#define  DIO_ModeReady_DIO4            0x00
+#define  DIO_ModeReady_DIO5            0x03
+#define  DIO_ClkOut                0x00
+#define  DIO_Data                0x01
+#define  DIO_TimeOut_DIO1            0x03
+#define  DIO_TimeOut_DIO4            0x00
+#define  DIO_Rssi_DIO0                0x03
+#define  DIO_Rssi_DIO3_4            0x01
+#define  DIO_RxReady                0x02
+#define  DIO_PLLLock                0x03
+#define  DIO_TxReady                0x01
+#define  DIO_FifoFull_DIO1            0x01
+#define  DIO_FifoFull_DIO3            0x00
+#define  DIO_SyncAddress            0x02
+#define  DIO_FifoNotEmpty_DIO1            0x02
+#define  DIO_FifoNotEmpty_FIO2            0x00
+#define  DIO_Automode                0x04
+#define  DIO_FifoLevel                0x00
+#define  DIO_CrcOk                0x00
+#define  DIO_PayloadReady            0x01
+#define  DIO_PacketSent                0x00
+#define  DIO_Dclk                0x00
+
+/* RegDioMapping2 CLK_OUT part */
+#define  MASK_DIOMAPPING2_CLK_OUT        0x07
+
+#define  DIOMAPPING2_CLK_OUT_NO_DIV        0x00
+#define  DIOMAPPING2_CLK_OUT_DIV_2        0x01
+#define  DIOMAPPING2_CLK_OUT_DIV_4        0x02
+#define  DIOMAPPING2_CLK_OUT_DIV_8        0x03
+#define  DIOMAPPING2_CLK_OUT_DIV_16        0x04
+#define  DIOMAPPING2_CLK_OUT_DIV_32        0x05
+#define  DIOMAPPING2_CLK_OUT_RC            0x06
+#define  DIOMAPPING2_CLK_OUT_OFF        0x07 /* default */
+
+/* RegIrqFlags1 */
+#define  MASK_IRQFLAGS1_MODE_READY        0x80
+#define  MASK_IRQFLAGS1_RX_READY        0x40
+#define  MASK_IRQFLAGS1_TX_READY        0x20
+#define  MASK_IRQFLAGS1_PLL_LOCK        0x10
+#define  MASK_IRQFLAGS1_RSSI            0x08
+#define  MASK_IRQFLAGS1_TIMEOUT            0x04
+#define  MASK_IRQFLAGS1_AUTOMODE        0x02
+#define  MASK_IRQFLAGS1_SYNC_ADDRESS_MATCH    0x01
+
+/* RegIrqFlags2 */
+#define  MASK_IRQFLAGS2_FIFO_FULL        0x80
+#define  MASK_IRQFLAGS2_FIFO_NOT_EMPTY        0x40
+#define  MASK_IRQFLAGS2_FIFO_LEVEL        0x20
+#define  MASK_IRQFLAGS2_FIFO_OVERRUN        0x10
+#define  MASK_IRQFLAGS2_PACKET_SENT        0x08
+#define  MASK_IRQFLAGS2_PAYLOAD_READY        0x04
+#define  MASK_IRQFLAGS2_CRC_OK            0x02
+#define  MASK_IRQFLAGS2_LOW_BAT            0x01
+
+/* RegSyncConfig */
+#define  MASK_SYNC_CONFIG_SYNC_ON        0x80 /* default */
+#define  MASK_SYNC_CONFIG_FIFO_FILL_CONDITION    0x40
+#define  MASK_SYNC_CONFIG_SYNC_SIZE        0x38
+#define  MASK_SYNC_CONFIG_SYNC_TOLERANCE    0x07
+
+/* RegPacketConfig1 */
+#define  MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE    0x80
+#define  MASK_PACKETCONFIG1_DCFREE            0x60
+#define  MASK_PACKETCONFIG1_CRC_ON            0x10 /* default */
+#define  MASK_PACKETCONFIG1_CRCAUTOCLEAR_OFF        0x08
+#define  MASK_PACKETCONFIG1_ADDRESSFILTERING        0x06
+
+#define  PACKETCONFIG1_DCFREE_OFF            0x00 /* default */
+#define  PACKETCONFIG1_DCFREE_MANCHESTER        0x20
+#define  PACKETCONFIG1_DCFREE_WHITENING            0x40
+#define  PACKETCONFIG1_ADDRESSFILTERING_OFF        0x00 /* default */
+#define  PACKETCONFIG1_ADDRESSFILTERING_NODE        0x02
+#define  PACKETCONFIG1_ADDRESSFILTERING_NODEBROADCAST    0x04
+
+/*
+// RegAutoModes
+#define  AUTOMODES_ENTER_OFF            0x00  // Default
+#define  AUTOMODES_ENTER_FIFONOTEMPTY        0x20
+#define  AUTOMODES_ENTER_FIFOLEVEL        0x40
+#define  AUTOMODES_ENTER_CRCOK            0x60
+#define  AUTOMODES_ENTER_PAYLOADREADY        0x80
+#define  AUTOMODES_ENTER_SYNCADRSMATCH        0xA0
+#define  AUTOMODES_ENTER_PACKETSENT        0xC0
+#define  AUTOMODES_ENTER_FIFOEMPTY        0xE0
+
+#define  AUTOMODES_EXIT_OFF            0x00  // Default
+#define  AUTOMODES_EXIT_FIFOEMPTY        0x04
+#define  AUTOMODES_EXIT_FIFOLEVEL        0x08
+#define  AUTOMODES_EXIT_CRCOK            0x0C
+#define  AUTOMODES_EXIT_PAYLOADREADY        0x10
+#define  AUTOMODES_EXIT_SYNCADRSMATCH        0x14
+#define  AUTOMODES_EXIT_PACKETSENT        0x18
+#define  AUTOMODES_EXIT_RXTIMEOUT        0x1C
+
+#define  AUTOMODES_INTERMEDIATE_SLEEP        0x00  // Default
+#define  AUTOMODES_INTERMEDIATE_STANDBY        0x01
+#define  AUTOMODES_INTERMEDIATE_RECEIVER    0x02
+#define  AUTOMODES_INTERMEDIATE_TRANSMITTER    0x03
+
+*/
+/* RegFifoThresh (0x3c) */
+#define  MASK_FIFO_THRESH_TXSTART        0x80
+#define  MASK_FIFO_THRESH_VALUE            0x7F
+
+/*
+
+// RegPacketConfig2
+#define  PACKET2_RXRESTARTDELAY_1BIT        0x00  // Default
+#define  PACKET2_RXRESTARTDELAY_2BITS        0x10
+#define  PACKET2_RXRESTARTDELAY_4BITS        0x20
+#define  PACKET2_RXRESTARTDELAY_8BITS        0x30
+#define  PACKET2_RXRESTARTDELAY_16BITS        0x40
+#define  PACKET2_RXRESTARTDELAY_32BITS        0x50
+#define  PACKET2_RXRESTARTDELAY_64BITS        0x60
+#define  PACKET2_RXRESTARTDELAY_128BITS        0x70
+#define  PACKET2_RXRESTARTDELAY_256BITS        0x80
+#define  PACKET2_RXRESTARTDELAY_512BITS        0x90
+#define  PACKET2_RXRESTARTDELAY_1024BITS    0xA0
+#define  PACKET2_RXRESTARTDELAY_2048BITS    0xB0
+#define  PACKET2_RXRESTARTDELAY_NONE        0xC0
+#define  PACKET2_RXRESTART            0x04
+
+#define  PACKET2_AUTORXRESTART_ON        0x02  // Default
+#define  PACKET2_AUTORXRESTART_OFF        0x00
+
+#define  PACKET2_AES_ON                0x01
+#define  PACKET2_AES_OFF            0x00  // Default
+
+
+// RegTemp1
+#define  TEMP1_MEAS_START            0x08
+#define  TEMP1_MEAS_RUNNING            0x04
+#define  TEMP1_ADCLOWPOWER_ON            0x01  // Default
+#define  TEMP1_ADCLOWPOWER_OFF            0x00
+*/
+
+// RegTestDagc (0x6F)
+#define  DAGC_NORMAL                0x00 /* Reset value */
+#define  DAGC_IMPROVED_LOWBETA1            0x20
+#define  DAGC_IMPROVED_LOWBETA0            0x30 /* Recommended val */
 
 

> Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx> hat am 15. Juli 2017 um 15:02
> geschrieben:
>
>
> On Sat, Jul 15, 2017 at 02:59:25PM +0200, Marcus Wolf wrote:
> > Hi!
> >
> > It's me again. Seems like I also need help on sending the email :-/
> >
> > I checked the whitespace/line wrap problem, but couldn't find any suspicious
> > lines.
> >
> > What I did:
> > * Looked into my outbox - the copy of my mail to you seems to be okay...
> > * I sent the patch once again (just to me) - result: Seems to be fine, too.
> >
> > Maybe you can bounce back my mail? Maybe I'll get an idea what went wrong,
> > if I
> > see the smashed code...
>
> You sent the patch in html format, which caused all of the whitespace
> corruption. html will not work for kernel patches for obvious reasons
> :)
>
> thanks,
>
> greg k-h
>
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux