[PATCH RFC lora-next 4/4] net: lora: sx1301: introduce a lora frame for packet metadata

From: Ben Whitten
Date: Wed Dec 19 2018 - 10:56:47 EST


Information such as spreading factor, coding rate and power are on a per
transmission basis so it makes sence to include this in a header much
like CAN frames do.

Signed-off-by: Ben Whitten <ben.whitten@xxxxxxxxxxxxx>
---
drivers/net/lora/dev.c | 2 -
drivers/net/lora/sx1301.c | 79 +++++++++++++++++++++++++++++++++------
include/uapi/linux/lora.h | 46 +++++++++++++++++++++++
3 files changed, 114 insertions(+), 13 deletions(-)

diff --git a/drivers/net/lora/dev.c b/drivers/net/lora/dev.c
index 0d4823de8c06..62dbe21668b0 100644
--- a/drivers/net/lora/dev.c
+++ b/drivers/net/lora/dev.c
@@ -11,8 +11,6 @@
#include <linux/lora/skb.h>
#include <net/rtnetlink.h>

-#define LORA_MTU 256 /* XXX */
-
struct sk_buff *alloc_lora_skb(struct net_device *dev, u8 **data)
{
struct sk_buff *skb;
diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 9bcbb967f307..fed6d6201bf3 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -584,7 +584,7 @@ static int sx1301_load_tx_gain_lut(struct sx1301_priv *priv)
return ret;
};

-static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
+static int sx1301_tx(struct sx1301_priv *priv, struct lora_frame *frame)
{
int ret, i;
u8 buff[256 + 16];
@@ -617,11 +617,67 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
hdr->tx_power = 15; /* HACK power entry 15 */

hdr->u.lora.crc16_en = 1; /* Enable CRC16 */
- hdr->u.lora.cr = 1; /* CR 4/5 */
- hdr->u.lora.sf = 7; /* SF7 */
- hdr->u.lora.payload_len = len; /* Set the data len to the skb len */
+
+ switch (frame->cr) {
+ case LORA_CR_4_5:
+ hdr->u.lora.cr = 1; /* CR 4/5 */
+ break;
+ case LORA_CR_4_6:
+ hdr->u.lora.cr = 2; /* CR 4/6 */
+ break;
+ case LORA_CR_4_7:
+ hdr->u.lora.cr = 3; /* CR 4/7 */
+ break;
+ case LORA_CR_4_8:
+ hdr->u.lora.cr = 4; /* CR 4/8 */
+ break;
+ default:
+ return -ENXIO;
+ }
+
+ switch (frame->sf) {
+ case LORA_SF_6:
+ hdr->u.lora.sf = 6; /* SF6 */
+ break;
+ case LORA_SF_7:
+ hdr->u.lora.sf = 7; /* SF7 */
+ break;
+ case LORA_SF_8:
+ hdr->u.lora.sf = 8; /* SF8 */
+ break;
+ case LORA_SF_9:
+ hdr->u.lora.sf = 9; /* SF9 */
+ break;
+ case LORA_SF_10:
+ hdr->u.lora.sf = 10; /* SF10 */
+ break;
+ case LORA_SF_11:
+ hdr->u.lora.sf = 11; /* SF11 */
+ break;
+ case LORA_SF_12:
+ hdr->u.lora.sf = 12; /* SF12 */
+ break;
+ default:
+ return -ENXIO;
+ }
+
+ hdr->u.lora.payload_len = frame->len; /* Set the data length */
hdr->u.lora.implicit_header = 0; /* No implicit header */
- hdr->u.lora.mod_bw = 0; /* Set 125KHz BW */
+
+ switch (frame->bw) {
+ case LORA_BW_125KHZ:
+ hdr->u.lora.mod_bw = 0; /* 125KHz BW */
+ break;
+ case LORA_BW_250KHZ:
+ hdr->u.lora.mod_bw = 1; /* 250KHz BW */
+ break;
+ case LORA_BW_500KHZ:
+ hdr->u.lora.mod_bw = 2; /* 500KHz BW */
+ break;
+ default:
+ return -ENXIO;
+ }
+
hdr->u.lora.ppm_offset = 0; /* TODO no ppm offset? */
hdr->u.lora.invert_pol = 0; /* TODO set no inverted polarity */

@@ -632,7 +688,7 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)

/* Copy the TX data into the buffer ready to go */

- memcpy((void *)&buff[16], data, len);
+ memcpy((void *)&buff[16], frame->data, frame->len);

/* Reset any transmissions */
ret = regmap_write(priv->regmap, SX1301_TX_TRIG, 0);
@@ -644,7 +700,7 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
if (ret)
return ret;
ret = regmap_noinc_write(priv->regmap, SX1301_TX_DATA_BUF_DATA, buff,
- len + 16);
+ frame->len + 16);
if (ret)
return ret;

@@ -653,8 +709,8 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
if (ret)
return ret;

- dev_dbg(priv->dev, "Transmitting packet of size %d: ", len);
- for (i = 0; i < len + 16; i++)
+ dev_dbg(priv->dev, "Transmitting packet of size %d: ", frame->len);
+ for (i = 0; i < frame->len + 16; i++)
dev_dbg(priv->dev, "%X", buff[i]);

return ret;
@@ -683,17 +739,18 @@ static void sx1301_tx_work_handler(struct work_struct *ws)
struct sx1301_priv *priv = container_of(ws, struct sx1301_priv,
tx_work);
struct net_device *netdev = dev_get_drvdata(priv->dev);
+ struct lora_frame *frame = (struct lora_frame *)priv->tx_skb->data;
int ret;

netdev_dbg(netdev, "%s\n", __func__);

if (priv->tx_skb) {
- ret = sx1301_tx(priv, priv->tx_skb->data, priv->tx_skb->len);
+ ret = sx1301_tx(priv, frame);
if (ret) {
netdev->stats.tx_errors++;
} else {
netdev->stats.tx_packets++;
- netdev->stats.tx_bytes += priv->tx_skb->len;
+ netdev->stats.tx_bytes += frame->len;
}

if (!(netdev->flags & IFF_ECHO) ||
diff --git a/include/uapi/linux/lora.h b/include/uapi/linux/lora.h
index 4ff00b9c3c20..d675025d2a6e 100644
--- a/include/uapi/linux/lora.h
+++ b/include/uapi/linux/lora.h
@@ -21,4 +21,50 @@ struct sockaddr_lora {
} lora_addr;
};

+#define LORA_MAX_DLEN 256
+
+enum lora_bw {
+ LORA_BW_125KHZ,
+ LORA_BW_250KHZ,
+ LORA_BW_500KHZ,
+};
+
+enum lora_cr {
+ LORA_CR_4_5,
+ LORA_CR_4_6,
+ LORA_CR_4_7,
+ LORA_CR_4_8,
+};
+
+enum lora_sf {
+ LORA_SF_6,
+ LORA_SF_7,
+ LORA_SF_8,
+ LORA_SF_9,
+ LORA_SF_10,
+ LORA_SF_11,
+ LORA_SF_12,
+};
+
+/**
+ * struct lora_frame - LoRa frame structure
+ * @freq: Frequency of LoRa transmission in Hz
+ * @power: Power of transmission in dBm
+ * @bw: bandwidth, 125, 250 or 500 KHz
+ * @cr: coding rate, 4/5 to 4/8
+ * @sf: spreading factor from SF6 to 12
+ * @data: LoRa frame payload (up to LORA_MAX_DLEN byte)
+ */
+struct lora_frame {
+ __u32 freq; /* transmission frequency in Hz */
+ __u8 power; /* transmission power in dBm */
+ enum lora_bw bw; /* bandwidth */
+ enum lora_cr cr; /* coding rate */
+ enum lora_sf sf; /* spreading factor */
+ __u8 len;
+ __u8 data[LORA_MAX_DLEN] __attribute__((aligned(8)));
+};
+
+#define LORA_MTU (sizeof(struct lora_frame))
+
#endif /* _UAPI_LINUX_LORA_H */
--
2.17.1