Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
From 3e52c3dc8cdd4dfebf518e58df1770460e410803 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Taveira?= <joao.p.taveira@gmail.com>
Date: Sun, 5 Jan 2014 16:12:15 +0000
Subject: [PATCH 1/4] Added XBee driver support
---
drivers/net/ieee802154/Kconfig | 4 +
drivers/net/ieee802154/Makefile | 1 +
drivers/net/ieee802154/xbee.c | 4539 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/tty.h | 1 +
4 files changed, 4545 insertions(+)
create mode 100644 drivers/net/ieee802154/xbee.c
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index 08ae465..acc8eb8 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -30,6 +30,10 @@ config IEEE802154_FAKELB
This driver can also be built as a module. To do so say M here.
The module will be called 'fakelb'.
+config IEEE802154_XBEE
+ depends on IEEE802154_DRIVERS && MAC802154
+ tristate "Xbee UART driver"
+
config IEEE802154_AT86RF230
depends on IEEE802154_DRIVERS && MAC802154
tristate "AT86RF230/231 transceiver driver"
diff --git a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile
index abb0c08..72899e3 100644
--- a/drivers/net/ieee802154/Makefile
+++ b/drivers/net/ieee802154/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
+obj-$(CONFIG_IEEE802154_XBEE) += xbee.o
obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
diff --git a/drivers/net/ieee802154/xbee.c b/drivers/net/ieee802154/xbee.c
new file mode 100644
index 0000000..ec349fd
--- /dev/null
+++ b/drivers/net/ieee802154/xbee.c
@@ -0,0 +1,4539 @@
+/*
+ * Xbee: XBee TTY for Xbee RF 868 OEM using 802.15.4 stack
+ *
+ * Authors:
+ * Joao Pedro Taveira <joao.silva@inov.pt>
+ *
+ * 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.
+ */
+
+/**
+ * @file main.c
+ *
+ * @date Jun 25, 2013
+ * @author Joao Pedro Taveira
+ */
+
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <termios.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define BUG() do{exit(1);}while(0);
+
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
+#define KERN_EMERG "emerg: " /* system is unusable */
+#define KERN_ALERT "alert: " /* action must be taken immediately */
+#define KERN_CRIT "crit : " /* critical conditions */
+#define KERN_ERR "error: " /* error conditions */
+#define KERN_WARNING "warn : " /* warning conditions */
+#define KERN_NOTICE "notic: " /* normal but significant condition */
+#define KERN_INFO "info : " /* informational */
+#define KERN_DEBUG "debug: " /* debug-level messages */
+
+#define printk printf
+
+#define pr_debug(fmt, ...) \
+ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+
+#define IEEE802154_ADDR_LEN 8
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#ifdef __GNUC__
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#else
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif /* __GNUC__ */
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+
+struct ieee802154_hw_addr_filt {
+ __le16 pan_id; /* Each independent PAN selects a unique
+ * identifier. This PAN id allows communication
+ * between devices within a network using short
+ * addresses and enables transmissions between
+ * devices across independent networks.
+ */
+ __le16 short_addr;
+ uint8_t ieee_addr[IEEE802154_ADDR_LEN];
+ uint8_t pan_coord;
+};
+
+struct ieee802154_dev {
+ /* filled by the driver */
+ int extra_tx_headroom;
+ uint32_t flags;
+ struct device *parent;
+
+ /* filled by mac802154 core */
+ struct ieee802154_hw_addr_filt hw_filt;
+ void *priv;
+ struct wpan_phy *phy;
+};
+
+#else
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/completion.h>
+#include <linux/tty.h>
+#include <linux/skbuff.h>
+#include <linux/sched.h>
+#include <linux/netdevice.h>
+#include <net/mac802154.h>
+#include <net/ieee802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/wpan-phy.h>
+
+#define MAX_DATA_SIZE 127
+
+#endif /* __KERNEL__ */
+
+/*
+ * API Operation
+ *
+ * Start Del 1B Len 2-3B Bytes 4-n Byte n+1
+ * +------------+ +-----+------+ +------------+ +------------+
+ * | 0x7E | | MSB | LSB | |API-specifc | | ChkSum 1B |
+ * +------------+ +-----+------+ +------------+ +------------+
+ *
+ * Escape characters. When sending or receiving a UART data frame,
+ * specific data values must be escaped (flagged) so they do not
+ * interfere with the data frame sequencing. To escape an
+ * interfering data byte, insert 0x7D and follow it with the byte
+ * to be escaped XOR’d with 0x20.
+ *
+ * Data bytes that need to be escaped:
+ * 0x7E – Frame Delimiter
+ * 0x7D – Escape
+ * 0x11 – XON
+ * 0x13 – XOFF
+ * Example - Raw UART Data Frame (before escaping interfering bytes): 
+ * 0x7E 0x00 0x02 0x23 0x11 0xCB
+ * 0x11 needs to be escaped which results in the following frame: 
+ * 0x7E 0x00 0x02 0x23 0x7D 0x31 0xCB
+ * Note: In the above example, the length of the raw data (excluding
+ * the checksum) is 0x0002 and the checksum of the non-escaped data
+ * (excluding frame delimiter and length) is calculated as:
+ * 0xFF - (0x23 + 0x11) = (0xFF - 0x34) = 0xCB.
+ *
+ * Length
+ * The length field has two-byte value that specifies the number of
+ * bytes that will be contained in the frame data field. It does not
+ * include the checksum field.
+ */
+
+#define XBEE_SYSFS_STATS 1
+
+#define XBEE_START_DELIM 0x7E
+#define XBEE_ESCAPE 0x7D
+#define XBEE_XON 0x11
+#define XBEE_XOFF 0x13
+
+#define XBEE_ADDR_LEN 8
+#define XBEE_DEFAULT_BROADCAST_RADIUS 1
+
+#define XBEE_MAX_FRAME_ID 0x3F /* 0011 1111 mask */
+#define XBEE_TRANSMIT_SPLITTED 0x80 /* 1000 0000 mask */
+#define XBEE_TRANSMIT_PART2 0x40 /* 0100 0000 mask */
+
+//typedef enum mode {
+// MODE_IDLE,
+// MODE_RX,
+// MODE_TX,
+// MODE_CMD,
+// MODE_SLEEP
+//} xbee_pro_mode_t;
+
+typedef enum recv_state {
+ RECV_STATE_WAIT_START_DELIM,
+ RECV_STATE_WAIT_MSB,
+ RECV_STATE_WAIT_LSB,
+ RECV_STATE_WAIT_DATA,
+ RECV_STATE_WAIT_CHECKSUM
+} xbee_recv_state_t;
+
+enum motes {
+ NOT_SUPPORTED_MOTE = -1,
+ UNKNOWN_MOTE = 0,
+ XBEE_XB08_DP_MOTE = 1,
+ HM_TRP_433D_MOTE,
+ HM_TRP_868D_MOTE,
+ MAX_MOTE
+};
+
+struct xbee_device {
+ /* Relative devices */
+#ifdef __KERNEL__
+ struct tty_struct *tty;
+ struct ieee802154_dev *dev;
+ int device_driver;
+#else
+ int tty_fd;
+ const char *tty_path;
+#endif
+
+#ifdef __KERNEL__
+ struct mutex mutex;
+#else
+ pthread_mutex_t mutex;
+#endif /* __KERNEL__ */
+ uint8_t frame_id_counter;
+
+ int escaped_mode;
+// xbee_pro_mode_t mode;
+
+ /* Command (rx) processing */
+ uint16_t recv_data_size;
+ unsigned int recv_data_offset;
+ int recv_data_escape_next;
+ uint8_t *recv_data;
+ int recv_state;
+ uint8_t recv_data_sum;
+
+ wait_queue_head_t wq;
+ struct workqueue_struct *frames_workqueue;
+
+#ifndef __KERNEL__
+ int rx_thread_running;
+ int rx_thread_end;
+ pthread_t rx_thread_tid;
+#endif /* !__KERNEL__ */
+
+ u8 dev_addr[IEEE802154_ADDR_LEN];
+ u16 pan_id;
+ //u8 rf_max_payload;
+
+};
+
+static u8 global_lqi = 0;
+
+#define FRAME_TYPE_AT_CMD 0x08
+#define FRAME_TYPE_AT_CMD_QUEUE 0x09
+#define FRAME_TYPE_TRANSMIT_REQ 0x10
+#define FRAME_TYPE_EXPLICIT_ADDR_CMD 0x11
+#define FRAME_TYPE_REMOTE_AT_CMD_REQ 0x17
+#define FRAME_TYPE_AT_CMD_RESP 0x88
+#define FRAME_TYPE_TRANSMIT_STATUS2 0x89
+#define FRAME_TYPE_MODEM_STATUS 0x8A
+#define FRAME_TYPE_TRANSMIT_STATUS1 0x8B
+#define FRAME_TYPE_RECEIVE_PACKET 0x90
+#define FRAME_TYPE_EXPLICIT_RX_INDICATOR 0x91
+#define FRAME_TYPE_NODE_ID_INDICATOR 0x95
+#define FRAME_TYPE_REMOTE_CMD_RESP 0x97
+
+#define FRAME_TYPE_RAW_TRANSMIT_REQ 0x20 /* simple RAW packet */
+#define FRAME_TYPE_RAW_RECEIVE FRAME_TYPE_RAW_TRANSMIT_REQ
+#define FRAME_TYPE_RAW_TRANSMIT_STATUS 0xA0 /* RAW packet send completion */
+
+#define TRANSMIT_OPTION_DISABLE_ACK(x) (x | 0x01)
+#define TRANSMIT_OPTION_ENABLE_ACK(x) (x & ~0x01)
+
+#define TRANSMIT_OPTION_DISABLE_ROUTE_DISCOVERY(x) (x | 0x02)
+#define TRANSMIT_OPTION_ENABLE_ROUTE_DISCOVERY(x) (x & ~0x02)
+
+typedef char at_command_t[2];
+typedef char at_command_param_t[4];
+
+typedef struct api_generic {
+ uint8_t api_id;
+} api_frame_generic_t;
+
+typedef struct at_cmd {
+ uint8_t api_id;
+ uint8_t frame_id;
+ at_command_t at_command;
+ at_command_param_t parameter_value;
+ uint8_t parameter_value_len;
+} api_frame_at_cmd_t;
+
+typedef struct at_cmd_queue {
+ uint8_t api_id;
+ uint8_t frame_id;
+ at_command_t at_command;
+ at_command_param_t parameter_value;
+ uint8_t parameter_value_len;
+} api_frame_at_cmd_queue_t;
+
+typedef struct transmit_req {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint8_t dst_addr[XBEE_ADDR_LEN]; // 0x000000000000FFFF - Broadcast address
+ uint16_t reserved; // 0xFFFE
+ uint8_t brd_radius;
+ uint8_t options; // bit 0: disable ACK bit 1: Dont Attempt route Disc
+ uint8_t *payload;
+ uint8_t payload_len;
+} api_frame_transmit_req_t;
+
+typedef struct raw_packet {
+ uint8_t api_id;
+ union {
+ uint8_t frame_id;
+ uint8_t lqi;
+ };
+ uint8_t *payload;
+ uint8_t payload_len;
+} api_frame_raw_packet_t;
+
+typedef struct explicit_addr_cmd {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint8_t dst_addr[XBEE_ADDR_LEN]; // 0x000000000000FFFF - Broadcast address
+ uint16_t reserved; // 0xFFFE
+ uint8_t src_endpoint;
+ uint8_t dst_endpoint;
+ uint16_t cluster_id;
+ uint16_t profile_id;
+ uint8_t brd_radius;
+ uint8_t options; // bit 0: disable ACK bit 1: Dont Attempt route Disc
+ uint8_t *payload;
+ uint8_t payload_len;
+} api_frame_explicit_addr_cmd_t;
+
+typedef struct remote_at_cmd_req {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint8_t dst_addr[XBEE_ADDR_LEN]; // 0x000000000000FFFF - Broadcast address
+ uint16_t reserved; // 0xFFFE
+ uint8_t remote_options; // 0x02 - Apply changes on remote. (If not set, AC command must be sent before changes will take effect.) All other bits must be set to 0.
+ at_command_t at_command;
+ at_command_param_t parameter_value;
+ uint8_t parameter_value_len;
+} api_frame_remote_at_cmd_req_t;
+
+typedef struct at_cmd_resp {
+ uint8_t api_id;
+ uint8_t frame_id;
+ at_command_t at_command;
+ uint8_t cmd_status; // 0 = OK; 1 = ERROR; 2 = Invalid Command; 3 = Invalid Parameter
+ at_command_param_t cmd_data;
+ uint8_t cmd_data_len;
+} api_frame_at_cmd_resp_t;
+
+typedef struct modem_status {
+ uint8_t api_id;
+ uint8_t status;
+ // 0x00: Hardware reset
+ // 0x01: Watchdog timer reset
+ // 0x0B: Network woke up
+ // 0x0C: Network went to sleep
+} api_frame_modem_status_t;
+
+typedef struct transmit_status {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint16_t reserved; // 0xFFFE
+ uint8_t transmit_retry_count; // #transmission retries took place
+ uint8_t delivery_status;
+ // 0x00 = Success
+ // 0x01 = MAC ACK Failure
+ // 0x15 = Invalid destination endpoint
+ // 0x21 = Network ACK Failure
+ // 0x25 = Route Not Found
+ uint8_t discovery_status;
+ // 0x00 = No Discovery Overhead
+ // 0x02 = Route Discovery
+} api_frame_transmit_status1_t;
+
+typedef struct transmit_status2 {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint8_t delivery_status;
+ // 0x00 - Success, no errors were detected on transmission.
+ // 0x01 - An expected MAC acknowledgment never occurred.
+ // 0x02 - CCA failure.
+ // 0x03 - Transmission was purged because it was attempted before the stack was up.
+ // 0x04 - Physical error occurred on the interface with the WiFi transceiver.
+ // 0x18 - No Buffers.
+ // 0x03 - Packet was purged without being transmitted.
+ // 0x21 - An expected network acknowledgment never occurred.
+ // 0x22 - Not joined to network.
+ // 0x23 - Self-addressed.
+ // 0x24 - Address not found.
+ // 0x25 - Route not found.
+ // 0x26 - Broadcast relay was not heard.
+ // 0x2B - Invalid Binding Table Index.
+ // 0x2C - Invalid Endpoint.
+ // 0x31 - A software error occurred.
+ // 0x32 - Resource Error.
+ // 0x74 - Data payload too large.
+ // 0x76 - Attempt to create a client socket failed.
+ // 0xBB - Key not authorized.
+} api_frame_transmit_status2_t;
+
+typedef struct raw_transmit_status {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint8_t retries;
+ uint8_t delivery_status;
+} api_frame_raw_transmit_status_t;
+
+typedef struct receive_packet {
+ uint8_t api_id;
+ uint8_t src_addr[XBEE_ADDR_LEN];
+ uint16_t reserved; // 0xFFFE
+ uint8_t options; // 0x01 - Packet Acknowledged; 0x02 - Packet was a broadcast packet
+ uint8_t *payload;
+ uint8_t payload_len;
+} api_frame_receive_packet_t;
+
+typedef struct explicit_rx_indicator {
+ uint8_t api_id;
+ uint8_t src_addr[XBEE_ADDR_LEN];
+ uint16_t reserved; // 0xFFFE
+ uint8_t src_endpoint;
+ uint8_t dst_endpoint;
+ uint16_t cluster_id;
+ uint16_t profile_id;
+ uint8_t options; // 0x01 - Packet Acknowledged; 0x02 - Packet was a broadcast packet
+ uint8_t *payload;
+ uint8_t payload_len;
+} api_frame_explicit_rx_indicator_t;
+
+typedef struct node_id_indicator {
+ uint8_t api_id;
+ uint8_t sender_addr[XBEE_ADDR_LEN]; // 64bit addr sender
+ uint16_t sender_short_addr; // 16bit addr senders
+ uint8_t options; // 0x01 - Packet Acknowledged; 0x02 - Packet was a broadcast packet
+ uint16_t src_short_addr; // Set to the 16-bit network address of the remote. Set to 0xFFFE if unknown.
+ uint8_t src_addr[XBEE_ADDR_LEN];
+ unsigned char *ni_string;
+ uint16_t parent_short_addr;
+} api_frame_node_id_indicator_t;
+
+typedef struct remote_cmd_resp {
+ uint8_t api_id;
+ uint8_t frame_id;
+ uint8_t src_addr[XBEE_ADDR_LEN];
+ uint16_t reserved; // 0xFFFE
+ at_command_t at_command;
+ uint8_t cmd_status; // 0 = OK; 1 = ERROR; 2 = Invalid Command; 3 = Invalid Parameter
+ at_command_param_t cmd_data;
+ uint8_t cmd_data_len;
+} api_frame_remote_cmd_resp_t;
+
+typedef struct xbee_api_frame {
+ uint16_t len;
+ uint8_t api_id;
+ uint8_t *raw_data;
+ union api_cmd_data_union {
+ api_frame_generic_t api_generic;
+ api_frame_at_cmd_t at_cmd;
+ api_frame_at_cmd_queue_t at_cmd_queue;
+ api_frame_transmit_req_t transmit_req;
+ api_frame_explicit_addr_cmd_t explitcit_addr_cmd;
+ api_frame_remote_at_cmd_req_t remote_at_cmd_req;
+ api_frame_at_cmd_resp_t at_cmd_resp;
+ api_frame_modem_status_t modem_status;
+ api_frame_transmit_status1_t transmit_status;
+ api_frame_transmit_status2_t transmit_status2;
+ api_frame_receive_packet_t receive_packet;
+ api_frame_explicit_rx_indicator_t explicit_rx_indicator;
+ api_frame_node_id_indicator_t node_id_indicator;
+ api_frame_remote_cmd_resp_t remote_cmd_resp;
+
+ api_frame_raw_packet_t raw_packet;
+ api_frame_raw_transmit_status_t raw_transmit_status;
+ } *api_data;
+ uint8_t checksum;
+
+#ifdef __KERNEL__
+ struct completion complete;
+ struct mutex mutex;
+#else
+ pthread_cond_t complete;
+ pthread_mutex_t mutex;
+#endif
+ struct xbee_api_frame *response;
+
+} _api_frame_t;
+
+/*
+ * TTY Helpers
+ */
+
+#ifndef __KERNEL__
+
+/*
+ * functions from:
+ * http://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
+ */
+
+static int set_interface_attribs(int fd, int speed, int parity) {
+ struct termios tty;
+ memset(&tty, 0, sizeof tty);
+ if (tcgetattr(fd, &tty) != 0) {
+ printk(KERN_ERR "%s(): error %d from tcgetattr", __func__, errno);
+ return -1;
+ }
+
+ cfsetospeed(&tty, speed);
+ cfsetispeed(&tty, speed);
+
+ tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
+ // disable IGNBRK for mismatched speed tests; otherwise receive break
+ // as \000 chars
+ tty.c_iflag &= ~IGNBRK; // ignore break signal
+ tty.c_lflag = 0; // no signaling chars, no echo,
+ // no canonical processing
+ tty.c_oflag = 0; // no remapping, no delays
+ tty.c_cc[VMIN] = 0; // read doesn't block
+ tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
+
+ tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
+
+ tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
+ // enable reading
+ tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
+ tty.c_cflag |= parity;
+ tty.c_cflag &= ~CSTOPB;
+ tty.c_cflag &= ~CRTSCTS;
+
+ if (tcsetattr(fd, TCSANOW, &tty) != 0) {
+ printk(KERN_ERR "%s(): error %d from tcsetattr", __func__, errno);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+set_blocking (int fd, int should_block)
+{
+ struct termios tty;
+ memset(&tty, 0, sizeof tty);
+ if (tcgetattr(fd, &tty) != 0) {
+ printk(KERN_ERR "%s(): error %d from tggetattr", __func__, errno);
+ return;
+ }
+
+ tty.c_cc[VMIN] = should_block ? 1 : 0;
+ tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
+
+ if (tcsetattr(fd, TCSANOW, &tty) != 0)
+ printk(KERN_ERR "%s(): error %d setting term attributes", __func__,
+ errno);
+}
+
+
+/*
+ * XBee Dev helpers
+ */
+static
+struct xbee_device *xbee_device_new()
+{
+ struct xbee_device *xbee_dev;
+#ifdef __KERNEL__
+ xbee_dev = kzalloc(sizeof(struct xbee_device),GFP_KERNEL);
+#else
+ xbee_dev = calloc(1,sizeof(struct xbee_device));
+#endif
+ if(!xbee_dev)
+ {
+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
+ BUG();
+ }
+ xbee_dev->escaped_mode = 1;
+ xbee_dev->frame_id_counter = 1;
+ xbee_dev->recv_state = RECV_STATE_WAIT_START_DELIM;
+// xbee_dev->rf_max_payload = 100;
+
+#ifdef __KERNEL__
+ mutex_init(&xbee_dev->mutex);
+#else
+ pthread_mutex_init(&xbee_dev->mutex,NULL);
+#endif
+
+ return xbee_dev;
+}
+
+static
+void xbee_device_release(struct xbee_device *xbee_dev)
+{
+ if(!xbee_dev)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(xbee_dev->recv_data)
+ {
+#ifdef __KERNEL__
+ kfree(xbee_dev->recv_data);
+#else
+ free(xbee_dev->recv_data);
+#endif
+ xbee_dev->recv_data = NULL;
+ }
+
+#ifndef __KERNEL__
+ pthread_mutex_destroy(&xbee_dev->mutex);
+#endif
+
+#ifndef __KERNEL__
+ if(xbee_dev->tty_fd>0)
+ {
+ close(xbee_dev->tty_fd);
+ }
+#endif
+
+#ifdef __KERNEL__
+ kfree(xbee_dev);
+#else
+ free(xbee_dev);
+#endif
+ xbee_dev = NULL;
+}
+
+#endif /* !__KERNEL__ */
+
+#ifdef __KERNEL__
+#ifdef XBEE_SYSFS_STATS
+typedef struct xbee_mac_stat {
+ int defined;
+ u8 addr[XBEE_ADDR_LEN];
+ unsigned long last_update; // in jiffies
+ u8 last_lqi;
+} xbee_mac_stat_t;
+
+#define XBEE_MOTE_MAXCOUNT 256
+typedef struct xbee_mac_stats {
+ struct mutex mutex;
+ xbee_mac_stat_t mote[XBEE_MOTE_MAXCOUNT];
+} xbee_stats_t;
+
+static xbee_stats_t *stats = NULL;
+
+int xbee_addr_equals(u8 addr1[XBEE_ADDR_LEN], u8 addr2[XBEE_ADDR_LEN])
+{
+ int i = 0;
+ for(i=0;i<XBEE_ADDR_LEN;i++)
+ {
+ if(addr1[i] != addr2[i])
+ return 0;
+ }
+ return 1;
+}
+
+xbee_mac_stat_t *xbee_stat_get_unsafe(u8 addr[XBEE_ADDR_LEN])
+{
+ int i = 0;
+ xbee_mac_stat_t *mac_stat = NULL;
+ for(i=0;i<XBEE_MOTE_MAXCOUNT;i++)
+ {
+ mac_stat = &stats->mote[i];
+ if(!mac_stat->defined)
+ {
+ memcpy(mac_stat->addr,addr, XBEE_ADDR_LEN);
+ mac_stat->defined = 1;
+ break;
+ } else if(xbee_addr_equals(addr,mac_stat->addr)){
+ break;
+ }
+ }
+ return mac_stat;
+}
+
+int xbee_stat_update_lqi(u8 addr[XBEE_ADDR_LEN], u8 lqi)
+{
+ xbee_mac_stat_t *mac_stat = NULL;
+ mutex_lock(&stats->mutex);
+ mac_stat = xbee_stat_get_unsafe(addr);
+ if(mac_stat)
+ {
+ mac_stat->last_lqi = lqi;
+ mac_stat->last_update = jiffies;
+ }
+ mutex_unlock(&stats->mutex);
+ return 0;
+}
+
+static const char *
+eui64_address_to_str(uint8_t addr[XBEE_ADDR_LEN],char eui64_addr_str[24]);
+
+#define XBEE_LQI_TABLE_MAX_LEN 4096
+
+static ssize_t
+xbee_stat_get_lqi_table(char str[XBEE_LQI_TABLE_MAX_LEN])
+{
+ ssize_t count = 0;
+ ssize_t len = 0;
+ int i = 0;
+ unsigned long now = jiffies;
+ unsigned long diff = 0;
+ xbee_mac_stat_t *mac_stat = NULL;
+ char eui64_addr_str[24] = {};
+ mutex_lock(&stats->mutex);
+ for(i = 0;i<XBEE_MOTE_MAXCOUNT; i++)
+ {
+ mac_stat = &stats->mote[i];
+ if(mac_stat && mac_stat->defined)
+ {
+ diff = (long) now - (long) mac_stat->last_update;
+ count = sprintf(str+len,"%s\t%6ld ms\t%3d (0x%02X)\n",eui64_address_to_str(mac_stat->addr,eui64_addr_str),diff * 1000 / HZ, mac_stat->last_lqi,mac_stat->last_lqi);
+ len += count;
+ }
+ }
+ mutex_unlock(&stats->mutex);
+ return len;
+}
+
+static int xbee_stats_init(void){
+ stats = kzalloc(sizeof(xbee_stats_t),GFP_KERNEL);
+ if(!stats)
+ return -ENOMEM;
+ mutex_init(&stats->mutex);
+ return 0;
+}
+
+static int xbee_stats_tini(void) {
+ if(stats)
+ kfree(stats);
+ return 0;
+}
+
+#endif
+#endif
+
+static uint8_t
+_xbee_device_gen_frame_id(struct xbee_device *xbee_dev)
+{
+ uint8_t frame_id;
+ if(!xbee_dev)
+ return 0;
+#ifdef __KERNEL__
+ mutex_lock(&xbee_dev->mutex);
+#else
+ pthread_mutex_lock(&xbee_dev->mutex);
+#endif
+ frame_id = xbee_dev->frame_id_counter = (xbee_dev->frame_id_counter+1)%XBEE_MAX_FRAME_ID;
+ if(frame_id == 0)
+ {
+ frame_id = xbee_dev->frame_id_counter = 1;
+ }
+#ifdef __KERNEL__
+ mutex_unlock(&xbee_dev->mutex);
+#else
+ pthread_mutex_unlock(&xbee_dev->mutex);
+#endif
+ return frame_id;
+}
+
+
+static int escape_required(uint8_t c);
+
+#ifndef __KERNEL__
+static int
+xbee_device_write_to_phy(struct xbee_device *xbee_dev, unsigned char *buf, unsigned int len)
+{
+ int i = 0;
+ uint8_t raw_byte = 0;
+ uint8_t escape_value = XBEE_ESCAPE;
+ unsigned char *raw_data = (unsigned char *) buf;
+ for(i = 0;i<len;i++){
+ raw_byte = ((unsigned char)*(raw_data+i));
+ if(i > 2 && xbee_dev->escaped_mode && escape_required(raw_byte))
+ {
+ //printf("%02X ",XBEE_ESCAPE);
+ write(xbee_dev->tty_fd,&escape_value,1);
+ raw_byte = raw_byte^0x20;
+ }
+ write(xbee_dev->tty_fd,&raw_byte,1);
+ //printf("%02X ",raw_byte);
+ }
+ printf("\n");
+ return len;
+}
+
+static int
+xbee_device_init(struct xbee_device *xbee_dev)
+{
+ if(!xbee_dev)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+#ifndef __KERNEL__
+ if((xbee_dev->tty_fd = open(xbee_dev->tty_path,O_RDWR | O_NOCTTY | O_SYNC)) < 0)
+ {
+ printk(KERN_ERR "%s: error opening tty %s: %s\n", __func__, xbee_dev->tty_path,strerror(errno));
+ return -1;
+ }
+
+ set_interface_attribs (xbee_dev->tty_fd, B9600, 0); // set speed to 115,200 bps, 8n1 (no parity)
+ set_blocking (xbee_dev->tty_fd, 0); // set no blocking
+#endif /* !__KERNEL__ */
+ return 0;
+}
+#endif /* !__KERNEL__ */
+
+#ifdef __KERNEL__
+
+#define XBEE_FRAME_MAX_SIZE 255
+
+static struct mote_id {
+ int type;
+ u8 id[4];
+ char *description;
+} mote_ids[4] = {
+ {
+ .type = XBEE_XB08_DP_MOTE,
+ .id = {0x00,0x06,0x00,0x00},
+ .description = "XBee 868 point to multi-point (868MHz for EU market)",
+ },
+ {
+ .type = HM_TRP_433D_MOTE,
+ .id = {0xFF,0xFF,0x00,0x43},
+ .description = "HM-TRP Series 100mW Transceiver modules (HM-TRP-433D)",
+ },
+ {
+ .type = HM_TRP_868D_MOTE,
+ .id = {0xFF,0xFF,0x00,0x86},
+ .description = "HM-TRP Series 100mW Transceiver modules (HM-TRP-868D)",
+ },
+ {
+ .type = NOT_SUPPORTED_MOTE,
+ .id = {0x00,0x00,0x00,0x00},
+ .description = "Not supported device",
+ },
+};
+
+int mote_id_equals(u8 id1[4], u8 id2[4]){
+ int i = 0;
+ for(i=0;i<4;i++){
+ if(id1[i] != id2[i])
+ return 0;
+ }
+ return 1;
+}
+
+static int
+xbee_api_at_command_read_u32(struct xbee_device *xbee_dev, const char cmdid[3], uint8_t value[4]);
+
+static int
+xbee_device_get_type(struct xbee_device *xbee_dev){
+ int mote_type = UNKNOWN_MOTE;
+ u8 mote_id[4] = {0};
+ int i = 0;
+ int err = 0;
+ mutex_lock(&xbee_dev->mutex);
+ mote_type = xbee_dev->device_driver;
+ mutex_unlock(&xbee_dev->mutex);
+ if(mote_type != UNKNOWN_MOTE){
+ return mote_type;
+ }
+ err = xbee_api_at_command_read_u32(xbee_dev,"DD",mote_id);
+ if(err) {
+ printk(KERN_ERR "%s: error getting device type\n", __func__);
+ return err;
+ }
+ else {
+ print_hex_dump_bytes("xbee_device_get_type(): device type: ", DUMP_PREFIX_NONE, mote_id, 4);
+ }
+ while(mote_type != NOT_SUPPORTED_MOTE){
+ mote_type = mote_ids[i].type;
+ //printk(KERN_INFO "%s: checking type: %d: %s\n", __func__,mote_ids[i].type,mote_ids[i].description);
+ //print_hex_dump_bytes("xbee_device_get_type(): checking: ", DUMP_PREFIX_NONE, mote_ids[i].id, 4);
+ if(mote_id_equals(mote_ids[i].id,mote_id) || mote_type == NOT_SUPPORTED_MOTE){
+ mutex_lock(&xbee_dev->mutex);
+ xbee_dev->device_driver = mote_type;
+ mutex_unlock(&xbee_dev->mutex);
+ printk(KERN_INFO "xbee: found mote: %s\n", mote_ids[i].description);
+ break;
+ }
+ i++;
+ }
+ return mote_type;
+}
+
+static int
+xbee_device_write_to_phy(struct xbee_device *xbee_dev, unsigned char *buf, unsigned int len){
+ struct tty_struct *tty;
+ unsigned int sent = 0;
+
+ int i = 0;
+ u8 raw_byte = 0;
+ u8 escape_value = XBEE_ESCAPE;
+ unsigned char *raw_data = (unsigned char *) buf;
+
+ BUG_ON(!xbee_dev);
+ tty = xbee_dev->tty;
+ if (!tty)
+ return -ENODEV;
+
+ /* Debug info */
+ pr_debug("%s(): %d bytes frame\n", __func__, len);
+#ifdef DEBUG
+ print_hex_dump_bytes("send_pending_data ", DUMP_PREFIX_NONE,
+ buf, len);
+#endif
+
+ pr_debug("%s(): sending %d\n", __func__,len);
+ for(i = 0;i<len;i++){
+ raw_byte = ((unsigned char)*(raw_data+i));
+ if(i > 0 && xbee_dev->escaped_mode && escape_required(raw_byte))
+ {
+ if (tty->driver->ops->write(tty, &escape_value,1) != 1) {
+ printk(KERN_ERR "%s: device write failed\n", __func__);
+ return -1;
+ }
+ raw_byte = raw_byte^0x20;
+ }
+ if (tty->driver->ops->write(tty, &raw_byte,1) != 1) {
+ printk(KERN_ERR "%s: device write failed\n", __func__);
+ return -1;
+ }
+ sent++;
+ }
+ return sent;
+}
+#endif /* __KERNEL__ */
+
+static _api_frame_t *temporary_frames_list[1000] = {};
+static int
+_api_frame_should_wait_response(_api_frame_t *api_frame);
+
+static int
+xbee_device_add_pendent_req(struct xbee_device *xbee_dev, _api_frame_t *api_frame)
+{
+ int index = 0;
+
+ if(xbee_dev == NULL)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: api_frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+#ifdef __KERNEL__
+ //if (mutex_lock_interruptible(&xbee_dev->mutex))
+ // return -EINTR;
+ mutex_lock(&xbee_dev->mutex);
+#else
+ if(pthread_mutex_lock(&xbee_dev->mutex))
+ return -EINTR;
+#endif
+
+ index = _api_frame_should_wait_response(api_frame);
+ temporary_frames_list[index] = api_frame;
+
+#ifdef __KERNEL__
+ mutex_unlock(&xbee_dev->mutex);
+#else
+ pthread_mutex_unlock(&xbee_dev->mutex);
+#endif
+
+ return 0;
+}
+
+static int
+xbee_device_remove_pendent_req(struct xbee_device *xbee_dev, _api_frame_t *api_frame)
+{
+ int index = 0;
+
+ if(xbee_dev == NULL)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: api_frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+ pr_debug("%s(): removing pendent req\n", __func__);
+
+#ifdef __KERNEL__
+ if (mutex_lock_interruptible(&xbee_dev->mutex))
+ return -EINTR;
+#else
+ if(pthread_mutex_lock(&xbee_dev->mutex))
+ return -EINTR;
+#endif
+
+ index = _api_frame_should_wait_response(api_frame);
+ if(index)
+ temporary_frames_list[index] = NULL;
+
+#ifdef __KERNEL__
+ mutex_unlock(&xbee_dev->mutex);
+#else
+ pthread_mutex_unlock(&xbee_dev->mutex);
+#endif
+
+ return 0;
+}
+
+static int
+_api_frame_should_signal_pendent(_api_frame_t *api_frame);
+static void
+_api_frame_print(_api_frame_t *api_frame);
+
+static int
+xbee_device_signal_pendent_req(struct xbee_device *xbee_dev, _api_frame_t *api_frame_response)
+{
+ int index = 0;
+ _api_frame_t *api_frame_req = NULL;
+
+ if(xbee_dev == NULL)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(api_frame_response == NULL)
+ {
+ printk(KERN_ERR "%s: api_frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+#ifdef __KERNEL__
+ if (mutex_lock_interruptible(&xbee_dev->mutex))
+ return -EINTR;
+#else
+ if(pthread_mutex_lock(&xbee_dev->mutex))
+ return -EINTR;
+#endif
+
+ index = _api_frame_should_signal_pendent(api_frame_response);
+ api_frame_req = temporary_frames_list[index];
+
+ if(api_frame_req != NULL)
+ {
+ pr_debug("%s(): api_frame found...\n", __func__);
+ _api_frame_print(api_frame_req);
+#ifndef __KERNEL__
+ pthread_mutex_lock(&api_frame_req->mutex);
+#endif
+ api_frame_req->response = api_frame_response;
+#ifndef __KERNEL__
+ pthread_cond_signal(&api_frame_req->complete);
+ pthread_mutex_unlock(&api_frame_req->mutex);
+#else
+ complete(&api_frame_req->complete);
+#endif
+ }
+ else
+ {
+ printk(KERN_DEBUG "%s: api_frame NOT found: %d\n", __func__,index);
+ }
+
+ temporary_frames_list[index] = NULL;
+
+#ifdef __KERNEL__
+ mutex_unlock(&xbee_dev->mutex);
+#else
+ pthread_mutex_unlock(&xbee_dev->mutex);
+#endif
+
+ return 0;
+}
+
+/*
+ * Debug helpers
+ */
+
+#ifdef DEBUG
+static const char *
+xbee_recv_state_str(int recv_state)
+{
+ switch(recv_state)
+ {
+ case RECV_STATE_WAIT_START_DELIM:
+ return "RECV_STATE_WaitStartDelim";
+ break;
+ case RECV_STATE_WAIT_MSB:
+ return "RECV_STATE_WaitMSB";
+ break;
+ case RECV_STATE_WAIT_LSB:
+ return "RECV_STATE_WaitLSB";
+ break;
+ case RECV_STATE_WAIT_DATA:
+ return "RECV_STATE_WaitData";
+ break;
+ case RECV_STATE_WAIT_CHECKSUM:
+ return "RECV_STATE_WaitCheckSum";
+ break;
+ default:
+ return "RECV_STATE_Unknown";
+ break;
+ }
+ return "RECV_STATE_Unknown";
+}
+#endif /* DEBUG */
+
+static int
+at_command_get_parameter_len(_api_frame_t *api_frame)
+{
+ int at_parameter_len = 0;
+ if(!api_frame)
+ return 0;
+ switch(api_frame->api_id){
+ case FRAME_TYPE_AT_CMD:
+ at_parameter_len = api_frame->len-4;
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ at_parameter_len = api_frame->len-4;
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ at_parameter_len = api_frame->len-15;
+ break;
+ case FRAME_TYPE_AT_CMD_RESP:
+ at_parameter_len = api_frame->len-5;
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ at_parameter_len = api_frame->len-15;
+ break;
+ default:
+ return 0;
+ }
+ return at_parameter_len;
+}
+
+#ifdef DEBUG
+static const char *
+at_command_get_parameter_str(_api_frame_t *api_frame,char *str_aux)
+{
+ uint8_t *at_data = NULL;
+ int wrote_bytes = 0;
+ int at_parameter_len = 0;
+ int i = 0;
+ if(!api_frame)
+ return "";
+ at_parameter_len = at_command_get_parameter_len(api_frame);
+ switch(api_frame->api_id){
+ case FRAME_TYPE_AT_CMD:
+ at_data = (uint8_t *) api_frame->api_data->at_cmd.parameter_value;
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ at_data = (uint8_t *) api_frame->api_data->at_cmd_queue.parameter_value;
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ at_data = (uint8_t *) api_frame->api_data->remote_at_cmd_req.parameter_value;
+ break;
+ case FRAME_TYPE_AT_CMD_RESP:
+ at_data = (uint8_t *) api_frame->api_data->at_cmd_resp.cmd_data;
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ at_data = (uint8_t *) api_frame->api_data->remote_cmd_resp.cmd_data;
+ break;
+ default:
+ return "";
+ }
+ for(i=0;i<at_parameter_len;i++)
+ {
+ wrote_bytes += sprintf(str_aux+wrote_bytes,"%02X",at_data[i]);
+ }
+ str_aux[wrote_bytes] = '\0';
+ return str_aux;
+}
+#endif /* DEBUG */
+
+static const char *
+eui64_address_to_str(uint8_t addr[XBEE_ADDR_LEN],char eui64_addr_str[24])
+{
+ int i = 0;
+ int wrote_bytes = 0;
+ for(i=0;i<XBEE_ADDR_LEN;i++)
+ {
+ if(i)
+ wrote_bytes += sprintf(eui64_addr_str+wrote_bytes,":");
+ wrote_bytes += sprintf(eui64_addr_str+wrote_bytes,"%02X",addr[i]);
+ }
+ eui64_addr_str[wrote_bytes] = '\0';
+ return eui64_addr_str;
+}
+
+
+/*
+ * API Frame helpers
+ */
+
+static void _api_frame_free(_api_frame_t *api_frame);
+
+static _api_frame_t *
+_api_frame_alloc(size_t frame_len, size_t data_len)
+{
+ void *api_data = NULL;
+ _api_frame_t *api_frame = NULL;
+#ifdef __KERNEL__
+ api_frame = kzalloc(sizeof(_api_frame_t),GFP_KERNEL);
+#else
+ api_frame = calloc(1,sizeof(_api_frame_t));
+#endif
+ if(!api_frame)
+ {
+ printk(KERN_ERR "%s(): unable to allocate memory to api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->len = frame_len;
+#ifdef __KERNEL__
+ api_data = kzalloc(data_len,GFP_KERNEL);
+#else
+ api_data = calloc(data_len,sizeof(uint8_t));
+#endif
+ if(!api_data)
+ {
+ printk(KERN_ERR "%s(): unable to allocate memory to api_data\n", __func__);
+ _api_frame_free(api_frame);
+ api_frame = NULL;
+ BUG();
+ }
+
+ api_frame->api_data = (union api_cmd_data_union*) api_data;
+
+#ifdef __KERNEL__
+ mutex_init(&api_frame->mutex);
+#else
+ pthread_mutex_init(&api_frame->mutex,NULL);
+#endif
+
+#ifdef __KERNEL__
+ init_completion(&api_frame->complete);
+#else
+ pthread_cond_init(&api_frame->complete,NULL);
+#endif
+
+ api_frame->response = NULL;
+
+ return api_frame;
+}
+
+static uint8_t *
+_api_frame_to_raw(_api_frame_t *api_frame, uint16_t *p_len)
+{
+ uint8_t *raw_data = NULL;
+ uint8_t frame_sum = 0;
+ int raw_offset = 0;
+ int i = 0;
+ uint16_t raw_data_len = 1 /* start delim */ + 2 /* 16 bit length */;
+ if(!api_frame)
+ {
+ printk(KERN_ERR "%s(): invalid frame\n", __func__);
+ BUG();
+ }
+ if(!p_len)
+ {
+ printk(KERN_ERR "%s(): invalid len pointer\n", __func__);
+ BUG();
+ }
+
+ /* Compute buffer length */
+ switch(api_frame->api_id)
+ {
+ // Requests
+ case FRAME_TYPE_AT_CMD:
+ raw_data_len += 1 /* frame type */ + 1 /* frame id */ + 2 /* at command */;
+ raw_data_len += api_frame->api_data->at_cmd.parameter_value_len;
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ raw_data_len += 1 /* frame type */ + 1 /* frame id */ + 2 /* at command */;
+ raw_data_len += api_frame->api_data->at_cmd_queue.parameter_value_len;
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ raw_data_len += 1 /* frame type */ + 1 /* frame id */;
+ raw_data_len += 8 /* dst addr */ + 2 /* reserved */;
+ raw_data_len += 1 /* bcast radius */ + 1 /* options */;
+ raw_data_len += api_frame->api_data->transmit_req.payload_len;
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ raw_data_len += 1 /* frame type */ + 1 /* frame id */;
+ raw_data_len += api_frame->api_data->raw_packet.payload_len;
+ break;
+ case FRAME_TYPE_EXPLICIT_ADDR_CMD:
+ raw_data_len += 1 /* frame type */ + 1 /* frame id */;
+ raw_data_len += 8 /* dst addr */ + 2 /* reserved */;
+ raw_data_len += 1 /* src endpoint */ + 1 /* dst endpoint */;
+ raw_data_len += 2 /* clusterID */ + 2 /* profile ID*/;
+ raw_data_len += 1 /* bcast radius */ + 1 /* options */;
+ raw_data_len += api_frame->api_data->explitcit_addr_cmd.payload_len;
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ raw_data_len += 1 /* frame type */ + 1 /* frame id */;
+ raw_data_len += 8 /* dst addr */ + 2 /* reserved */;
+ raw_data_len += 1 /* remote command options */ + 2 /* at command */;
+ raw_data_len += api_frame->api_data->remote_at_cmd_req.parameter_value_len;
+ break;
+
+ // Responses
+ case FRAME_TYPE_AT_CMD_RESP:
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_STATUS:
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ break;
+ default:
+ printk(KERN_WARNING "%s(): Unknown Type (0x%02X)\n", __func__,api_frame->api_id);
+ break;
+ return NULL;
+ }
+ raw_data_len += 1 /* checksum */;
+
+#ifdef __KERNEL__
+ raw_data = kzalloc(raw_data_len*sizeof(uint8_t),GFP_KERNEL);
+#else
+ raw_data = calloc(raw_data_len,sizeof(uint8_t));
+#endif
+ if(!raw_data)
+ {
+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
+ return NULL;
+ }
+
+ *p_len = raw_data_len;
+
+ raw_data[raw_offset++] = XBEE_START_DELIM;
+ raw_data[raw_offset++] = (raw_data_len-4) >> 8 & 0xFF;
+ raw_data[raw_offset++] = (raw_data_len-4) & 0xFF;
+
+ /* Fill buffer */
+ switch(api_frame->api_id)
+ {
+ // Requests
+ case FRAME_TYPE_AT_CMD:
+ raw_data[raw_offset] = api_frame->api_data->at_cmd.api_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->at_cmd.frame_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->at_cmd.at_command[0];
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->at_cmd.at_command[1];
+ frame_sum += raw_data[raw_offset++];
+ for(i=0;i<api_frame->api_data->at_cmd.parameter_value_len;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->at_cmd.parameter_value[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ raw_data[raw_offset] = api_frame->api_data->at_cmd_queue.api_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->at_cmd_queue.frame_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->at_cmd_queue.at_command[0];
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->at_cmd_queue.at_command[1];
+ frame_sum += raw_data[raw_offset++];
+ for(i=0;i<api_frame->api_data->at_cmd_queue.parameter_value_len;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->at_cmd_queue.parameter_value[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.api_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.frame_id;
+ frame_sum += raw_data[raw_offset++];
+ for(i=0;i<XBEE_ADDR_LEN;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.dst_addr[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.reserved >> 8 & 0xFF;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.reserved & 0xFF;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.brd_radius;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.options;
+ frame_sum += raw_data[raw_offset++];
+
+ for(i=0;i<api_frame->api_data->transmit_req.payload_len;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->transmit_req.payload[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ raw_data[raw_offset] = api_frame->api_data->raw_packet.api_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->raw_packet.frame_id;
+ frame_sum += raw_data[raw_offset++];
+ for(i=0;i<api_frame->api_data->raw_packet.payload_len;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->raw_packet.payload[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ break;
+ case FRAME_TYPE_EXPLICIT_ADDR_CMD:
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.api_id;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.frame_id;
+ frame_sum += raw_data[raw_offset++];
+ for(i=0;i<XBEE_ADDR_LEN;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.dst_addr[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.reserved >> 8 & 0xFF;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.reserved & 0xFF;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.remote_options;
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.at_command[0];
+ frame_sum += raw_data[raw_offset++];
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.at_command[1];
+ frame_sum += raw_data[raw_offset++];
+ for(i=0;i<api_frame->api_data->remote_at_cmd_req.parameter_value_len;i++)
+ {
+ raw_data[raw_offset] = api_frame->api_data->remote_at_cmd_req.parameter_value[i];
+ frame_sum += raw_data[raw_offset++];
+ }
+ break;
+
+ // Responses
+ case FRAME_TYPE_AT_CMD_RESP:
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_STATUS:
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ break;
+ default:
+ printk(KERN_WARNING "%s(): Unknown Type (0x%02X)\n", __func__,api_frame->api_id);
+#ifdef __KERNEL__
+ kfree(raw_data);
+#else
+ free(raw_data);
+#endif
+ *p_len = 0;
+ break;
+ return NULL;
+ }
+ raw_data[raw_offset++] = 0xFF - frame_sum;
+
+ return raw_data;
+}
+
+static int
+_api_frame_should_wait_response(_api_frame_t *api_frame)
+{
+ switch(api_frame->api_id)
+ {
+ // Requests
+ case FRAME_TYPE_AT_CMD:
+ if(api_frame->api_data->at_cmd.frame_id)
+ return api_frame->api_data->at_cmd.frame_id;
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ if(api_frame->api_data->at_cmd_queue.frame_id)
+ return api_frame->api_data->at_cmd_queue.frame_id;
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ if(api_frame->api_data->transmit_req.frame_id)
+ return api_frame->api_data->transmit_req.frame_id;
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ if(api_frame->api_data->raw_packet.frame_id)
+ return api_frame->api_data->raw_packet.frame_id;
+ break;
+ case FRAME_TYPE_EXPLICIT_ADDR_CMD:
+ if(api_frame->api_data->explitcit_addr_cmd.frame_id)
+ return api_frame->api_data->explitcit_addr_cmd.frame_id;
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ if(api_frame->api_data->remote_at_cmd_req.frame_id)
+ return api_frame->api_data->remote_at_cmd_req.frame_id;
+ break;
+
+ // Responses
+ case FRAME_TYPE_AT_CMD_RESP:
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_STATUS:
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ break;
+ default:
+ printk(KERN_WARNING "%s(): Unknown Type (0x%02X)\n", __func__,api_frame->api_id);
+ break;
+ return 0;
+ }
+ return 0;
+}
+
+static int
+_api_frame_should_signal_pendent(_api_frame_t *api_frame)
+{
+ switch(api_frame->api_id)
+ {
+ // Requests
+ case FRAME_TYPE_AT_CMD:
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ break;
+ case FRAME_TYPE_EXPLICIT_ADDR_CMD:
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ break;
+
+ // Responses
+ case FRAME_TYPE_AT_CMD_RESP:
+ if(api_frame->api_data->at_cmd_resp.frame_id)
+ return api_frame->api_data->at_cmd_resp.frame_id;
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ return 0;
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ if(api_frame->api_data->transmit_status.frame_id)
+ return api_frame->api_data->transmit_status.frame_id;
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ if(api_frame->api_data->transmit_status2.frame_id)
+ return api_frame->api_data->transmit_status2.frame_id;
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_STATUS:
+ if(api_frame->api_data->raw_transmit_status.frame_id)
+ return api_frame->api_data->raw_transmit_status.frame_id;
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ return 0;
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ return 0;
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ return 0;
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ if(api_frame->api_data->remote_cmd_resp.frame_id)
+ return api_frame->api_data->remote_cmd_resp.frame_id;
+ break;
+ default:
+ printk(KERN_WARNING "%s(): Unknown Type (0x%02X)\n", __func__,api_frame->api_id);
+ break;
+ return 0;
+ }
+ return 0;
+}
+
+static _api_frame_t *
+_api_frame_parse(uint16_t frame_len, uint8_t *raw_data, uint8_t checksum)
+{
+ size_t api_data_size = 0;
+ _api_frame_t *api_frame = NULL;
+ int i = 0;
+ int ni_string_len = 0;
+#ifdef __KERNEL__
+ api_frame = kzalloc(sizeof(_api_frame_t),GFP_KERNEL);
+#else
+ api_frame = calloc(1,sizeof(_api_frame_t));
+#endif
+ if(!api_frame)
+ {
+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
+ _api_frame_free(api_frame);
+ BUG();
+ }
+
+ api_frame->len = frame_len;
+ api_frame->raw_data = raw_data;
+ api_frame->api_id = *(api_frame->raw_data);
+ api_frame->checksum = checksum;
+ api_frame->response = NULL;
+
+ switch(api_frame->api_id)
+ {
+ // Requests
+ case FRAME_TYPE_AT_CMD:
+ api_data_size = sizeof(api_frame_at_cmd_t);
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ api_data_size = sizeof(api_frame_transmit_req_t);
+ break;
+
+ // Responses
+ case FRAME_TYPE_AT_CMD_RESP:
+ api_data_size = sizeof(api_frame_at_cmd_resp_t);
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ api_data_size = sizeof(api_frame_modem_status_t);
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ api_data_size = sizeof(api_frame_transmit_status1_t);
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ api_data_size = sizeof(api_frame_transmit_status2_t);
+ break;
+ case FRAME_TYPE_RAW_TRANSMIT_STATUS:
+ api_data_size = sizeof(api_frame_raw_transmit_status_t);
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ api_data_size = sizeof(api_frame_receive_packet_t);
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ api_data_size = sizeof(api_frame_explicit_rx_indicator_t);
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ api_data_size = sizeof(api_frame_node_id_indicator_t);
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ api_data_size = sizeof(api_frame_remote_cmd_resp_t);
+ break;
+
+ // RAW
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ api_data_size = sizeof(api_frame_raw_packet_t);
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unknown or unimplemented parsing: Type: 0x%02X\n", __func__,api_frame->api_id);
+ print_hex_dump_bytes("xbee_net_rx(): ", DUMP_PREFIX_NONE, raw_data,frame_len);
+ api_frame->raw_data = NULL;
+ _api_frame_free(api_frame);
+ return NULL;
+ }
+
+#ifdef __KERNEL__
+ api_frame->api_data = kzalloc(api_data_size,GFP_KERNEL);
+#else
+ api_frame->api_data = calloc(api_data_size,sizeof(uint8_t));
+#endif
+ if(!api_frame->api_data)
+ {
+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
+ api_frame->raw_data = NULL;
+ _api_frame_free(api_frame);
+ BUG();
+ }
+ switch(api_frame->api_id)
+ {
+ case FRAME_TYPE_AT_CMD:
+ api_frame->api_data->at_cmd.api_id = *(api_frame->raw_data);
+ api_frame->api_data->at_cmd.frame_id = *(api_frame->raw_data+1);
+ api_frame->api_data->at_cmd.at_command[0] = *(api_frame->raw_data+2);
+ api_frame->api_data->at_cmd.at_command[1] = *(api_frame->raw_data+3);
+ api_frame->api_data->at_cmd.parameter_value_len = at_command_get_parameter_len(api_frame);
+ for(i=0;i<api_frame->api_data->at_cmd.parameter_value_len;i++)
+ {
+ api_frame->api_data->at_cmd.parameter_value[i] = *(api_frame->raw_data+4+i);
+ }
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ api_frame->api_data->transmit_req.api_id = *(api_frame->raw_data);
+ api_frame->api_data->transmit_req.frame_id = *(api_frame->raw_data+1);
+ memcpy(api_frame->api_data->transmit_req.dst_addr, api_frame->raw_data+2, XBEE_ADDR_LEN);
+ api_frame->api_data->transmit_req.reserved = ((*(api_frame->raw_data+10))<<8)+*(api_frame->raw_data+11);
+ api_frame->api_data->transmit_req.brd_radius = *(api_frame->raw_data+12);
+ api_frame->api_data->transmit_req.options = *(api_frame->raw_data+13);
+ api_frame->api_data->transmit_req.payload = api_frame->raw_data+14;
+ api_frame->api_data->transmit_req.payload_len = api_frame->len-14;
+ break;
+
+ // Responses
+ case FRAME_TYPE_AT_CMD_RESP:
+ api_frame->api_data->at_cmd_resp.api_id = *(api_frame->raw_data);
+ api_frame->api_data->at_cmd_resp.frame_id = *(api_frame->raw_data+1);
+ api_frame->api_data->at_cmd_resp.at_command[0] = *(api_frame->raw_data+2);
+ api_frame->api_data->at_cmd_resp.at_command[1] = *(api_frame->raw_data+3);
+ api_frame->api_data->at_cmd_resp.cmd_status = *(api_frame->raw_data+4);
+ api_frame->api_data->at_cmd_resp.cmd_data_len = at_command_get_parameter_len(api_frame);
+ for(i=0;i<api_frame->api_data->at_cmd_resp.cmd_data_len;i++)
+ {
+ api_frame->api_data->at_cmd_resp.cmd_data[i] = *(api_frame->raw_data+5+i);
+ }
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ api_frame->api_data->modem_status.api_id = *(api_frame->raw_data);
+ api_frame->api_data->modem_status.status = *(api_frame->raw_data+1);
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ api_frame->api_data->transmit_status.api_id = *(api_frame->raw_data);
+ api_frame->api_data->transmit_status.frame_id = *(api_frame->raw_data+1);
+ api_frame->api_data->transmit_status.reserved = ((*(api_frame->raw_data+2))<<8)+*(api_frame->raw_data+3);
+ api_frame->api_data->transmit_status.transmit_retry_count = *(api_frame->raw_data+4);
+ api_frame->api_data->transmit_status.delivery_status = *(api_frame->raw_data+5);
+ api_frame->api_data->transmit_status.discovery_status = *(api_frame->raw_data+6);
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ api_frame->api_data->transmit_status2.api_id = *(api_frame->raw_data);
+ api_frame->api_data->transmit_status2.frame_id = *(api_frame->raw_data+1);
+ api_frame->api_data->transmit_status2.delivery_status = *(api_frame->raw_data+2);
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ api_frame->api_data->receive_packet.api_id = *(api_frame->raw_data);
+ memcpy(api_frame->api_data->receive_packet.src_addr, api_frame->raw_data+1, XBEE_ADDR_LEN);
+ api_frame->api_data->receive_packet.reserved = ((*(api_frame->raw_data+9))<<8)+*(api_frame->raw_data+10);
+ api_frame->api_data->receive_packet.options = *(api_frame->raw_data+11);
+ //api_frame->api_data->receive_packet.split_header = *(api_frame->raw_data+12);
+ api_frame->api_data->receive_packet.payload = api_frame->raw_data+12;
+ api_frame->api_data->receive_packet.payload_len = api_frame->len-12;
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ api_frame->api_data->explicit_rx_indicator.api_id = *(api_frame->raw_data);
+ memcpy(api_frame->api_data->explicit_rx_indicator.src_addr, api_frame->raw_data+1, XBEE_ADDR_LEN);
+ api_frame->api_data->explicit_rx_indicator.reserved = ((*(api_frame->raw_data+9))<<8)+*(api_frame->raw_data+10);
+ api_frame->api_data->explicit_rx_indicator.src_endpoint = *(api_frame->raw_data+11);
+ api_frame->api_data->explicit_rx_indicator.dst_endpoint = *(api_frame->raw_data+12);
+ api_frame->api_data->explicit_rx_indicator.cluster_id = ((*(api_frame->raw_data+13))<<8)+*(api_frame->raw_data+14);
+ api_frame->api_data->explicit_rx_indicator.profile_id = ((*(api_frame->raw_data+15))<<8)+*(api_frame->raw_data+16);
+ api_frame->api_data->explicit_rx_indicator.options = *(api_frame->raw_data+17);
+ api_frame->api_data->explicit_rx_indicator.payload = api_frame->raw_data+18;
+ api_frame->api_data->explicit_rx_indicator.payload_len = api_frame->len-18;
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ api_frame->api_data->node_id_indicator.api_id = *(api_frame->raw_data);
+ memcpy(api_frame->api_data->node_id_indicator.sender_addr, api_frame->raw_data+1, XBEE_ADDR_LEN);
+ api_frame->api_data->node_id_indicator.sender_short_addr = ((*(api_frame->raw_data+9))<<8)+*(api_frame->raw_data+10);
+ api_frame->api_data->node_id_indicator.options = *(api_frame->raw_data+11);
+ api_frame->api_data->node_id_indicator.src_short_addr = ((*(api_frame->raw_data+12))<<8)+*(api_frame->raw_data+13);
+ memcpy(api_frame->api_data->node_id_indicator.src_addr, api_frame->raw_data+14, XBEE_ADDR_LEN);
+ api_frame->api_data->node_id_indicator.ni_string = api_frame->raw_data+22;
+ ni_string_len = strlen((char*)api_frame->api_data->node_id_indicator.ni_string);
+ api_frame->api_data->node_id_indicator.parent_short_addr = ((*(api_frame->raw_data+22+ni_string_len+1))<<8)+*(api_frame->raw_data+23+ni_string_len+1);
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ api_frame->api_data->remote_cmd_resp.api_id = *(api_frame->raw_data);
+ api_frame->api_data->remote_cmd_resp.frame_id = *(api_frame->raw_data+1);
+ memcpy(api_frame->api_data->remote_cmd_resp.src_addr, api_frame->raw_data+2, XBEE_ADDR_LEN);
+ api_frame->api_data->remote_cmd_resp.reserved = ((*(api_frame->raw_data+10))<<8)+*(api_frame->raw_data+11);
+ api_frame->api_data->remote_cmd_resp.at_command[0] = *(api_frame->raw_data+12);
+ api_frame->api_data->remote_cmd_resp.at_command[1] = *(api_frame->raw_data+13);
+ api_frame->api_data->remote_cmd_resp.cmd_status = *(api_frame->raw_data+14);
+ api_frame->api_data->remote_cmd_resp.cmd_data_len = at_command_get_parameter_len(api_frame);
+ for(i=0;i<api_frame->api_data->remote_cmd_resp.cmd_data_len;i++)
+ {
+ api_frame->api_data->remote_cmd_resp.cmd_data[i] = *(api_frame->raw_data+15+i);
+ }
+ break;
+
+ // RAW packet
+ // case FRAME_TYPE_RAW_RECEIVE:
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ api_frame->api_data->raw_packet.api_id = *(api_frame->raw_data);
+ api_frame->api_data->raw_packet.frame_id = *(api_frame->raw_data+1); // this is the LQI on RAW received
+ api_frame->api_data->raw_packet.payload = api_frame->raw_data+2;
+ api_frame->api_data->raw_packet.payload_len = api_frame->len-2;
+ break;
+
+ case FRAME_TYPE_RAW_TRANSMIT_STATUS:
+ api_frame->api_data->raw_transmit_status.api_id = *(api_frame->raw_data);
+ api_frame->api_data->raw_transmit_status.frame_id = *(api_frame->raw_data+1);
+ api_frame->api_data->raw_transmit_status.retries = *(api_frame->raw_data+2);
+ api_frame->api_data->raw_transmit_status.delivery_status = *(api_frame->raw_data+3);
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unknown or unimplemented parsing #2: Type: 0x%02X\n", __func__,api_frame->api_id);
+ api_frame->raw_data = NULL;
+ _api_frame_free(api_frame);
+ return NULL;
+ }
+
+#ifdef __KERNEL__
+ mutex_init(&api_frame->mutex);
+#else
+ pthread_mutex_init(&api_frame->mutex,NULL);
+ pthread_cond_init(&api_frame->complete,NULL);
+#endif
+
+#ifndef __KERNEL__
+#ifdef DEBUG
+ printk(KERN_DEBUG "%s(): new frame %"PRIu16" bytes length: cmdID: 0x%02X\n",
+ __func__,api_frame->len,api_frame->api_id);
+#endif
+#endif
+
+ return api_frame;
+}
+
+static void
+_api_frame_free(_api_frame_t *api_frame)
+{
+ if(!api_frame)
+ {
+ printk(KERN_ERR "%s: api frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+ if(api_frame->response)
+ {
+ _api_frame_free(api_frame->response);
+ }
+
+ if(api_frame->api_data)
+ {
+#ifdef __KERNEL__
+ kfree(api_frame->api_data);
+#else
+ free(api_frame->api_data);
+#endif
+ api_frame->api_data = NULL;
+ }
+ if(api_frame->raw_data)
+ {
+#ifdef __KERNEL__
+ kfree(api_frame->raw_data);
+#else
+ free(api_frame->raw_data);
+#endif
+ api_frame->raw_data = NULL;
+ }
+
+#ifndef __KERNEL__
+ pthread_mutex_destroy(&api_frame->mutex);
+#endif
+
+#ifndef __KERNEL__
+ pthread_cond_destroy(&api_frame->complete);
+#endif
+
+#ifdef __KERNEL__
+ kfree(api_frame);
+#else
+ free(api_frame);
+#endif
+ api_frame = NULL;
+}
+
+static void
+_api_frame_print(_api_frame_t *api_frame)
+{
+#ifdef DEBUG
+ char str_aux[20] = {};
+ //123456789012345678901234
+ //AA:BB:CC:DD:EE:FF:11:22
+ char eui64_addr_str[24] = {};
+ int i = 0;
+
+ if(!api_frame)
+ {
+ printk(KERN_DEBUG "%s: api frame NULL pointer\n", __func__);
+ return;
+ }
+ printk(KERN_DEBUG "%s(): ______________________________________________________\n", __func__);
+ switch(api_frame->api_id)
+ {
+ case FRAME_TYPE_AT_CMD:
+ printk(KERN_DEBUG "%s(): Type: AT Command\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->at_cmd.frame_id);
+ printk(KERN_DEBUG "%s(): Command: %c%c\n", __func__,api_frame->api_data->at_cmd.at_command[0],api_frame->api_data->at_cmd.at_command[1]);
+ printk(KERN_DEBUG "%s(): Parameter: %s\n", __func__,at_command_get_parameter_str(api_frame,str_aux));
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ printk(KERN_DEBUG "%s(): AT Command Queue Type\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->at_cmd.frame_id);
+ printk(KERN_DEBUG "%s(): Command: %c%c\n", __func__,api_frame->api_data->at_cmd.at_command[0],api_frame->api_data->at_cmd.at_command[1]);
+ printk(KERN_DEBUG "%s(): Parameter: %s\n", __func__,at_command_get_parameter_str(api_frame,str_aux));
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ printk(KERN_DEBUG "%s(): Type: Transmit Request\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->transmit_req.frame_id);
+ printk(KERN_DEBUG "%s(): Dst Addr: %s\n", __func__,eui64_address_to_str(api_frame->api_data->transmit_req.dst_addr,eui64_addr_str));
+ printk(KERN_DEBUG "%s(): Reserved: %04X\n", __func__,api_frame->api_data->transmit_req.reserved);
+ printk(KERN_DEBUG "%s(): BroadcastRadius: %d\n", __func__,api_frame->api_data->transmit_req.brd_radius);
+ if(api_frame->api_data->transmit_req.options & 0x01)
+ printk(KERN_DEBUG "%s(): Ack Disabled\n", __func__);
+ if(api_frame->api_data->transmit_req.options & 0x02)
+ printk(KERN_DEBUG "%s(): Don't attempt route Discovery\n", __func__);
+ printk(KERN_DEBUG "%s(): Payload Lenght: %d\n", __func__,api_frame->api_data->transmit_req.payload_len);
+ printk(KERN_DEBUG "%s(): Payload: ", __func__);
+ for(i = 0;i<api_frame->api_data->transmit_req.payload_len;i++){
+ printk("%02X ",api_frame->api_data->transmit_req.payload[i]);
+ }
+ printk("\n");
+ break;
+ case FRAME_TYPE_RAW_PACKET:
+ printk(KERN_DEBUG "%s(): Type: Raw Packet\n", __func__);
+ printk(KERN_DEBUG "%s(): Payload Lenght: %d\n", __func__,api_frame->api_data->raw_packet.payload_len);
+ printk(KERN_DEBUG "%s(): Payload: ", __func__);
+ for(i = 0;i<api_frame->api_data->raw_packet.payload_len;i++){
+ printk("%02X ",api_frame->api_data->raw_packet.payload[i]);
+ }
+ printk("\n");
+ break;
+ case FRAME_TYPE_EXPLICIT_ADDR_CMD:
+ printk(KERN_DEBUG "%s(): Type: Explicit Addressing Command\n", __func__);
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ printk(KERN_DEBUG "%s(): Type: Remote AT Command Request\n", __func__);
+ break;
+ case FRAME_TYPE_AT_CMD_RESP:
+ printk(KERN_DEBUG "%s(): Type: AT Command Response\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->at_cmd_resp.frame_id);
+ printk(KERN_DEBUG "%s(): Command: %c%c\n", __func__,api_frame->api_data->at_cmd_resp.at_command[0],api_frame->api_data->at_cmd_resp.at_command[1]);
+ switch(api_frame->api_data->at_cmd_resp.cmd_status)
+ {
+ case 0x00:
+ printk(KERN_DEBUG "%s(): Command Status: OK\n", __func__);
+ break;
+ case 0x01:
+ printk(KERN_DEBUG "%s(): Command Status: Error\n", __func__);
+ break;
+ case 0x02:
+ printk(KERN_DEBUG "%s(): Command Status: Invalid Command\n", __func__);
+ break;
+ case 0x03:
+ printk(KERN_DEBUG "%s(): Command Status: Invalid Parameter\n", __func__);
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Command Status: Unknown status 0x%02X\n", __func__,api_frame->api_data->at_cmd_resp.cmd_status);
+ break;
+ }
+ if(api_frame->api_data->at_cmd_resp.cmd_data_len)
+ printk(KERN_DEBUG "%s(): Parameter: %s\n", __func__,at_command_get_parameter_str(api_frame,str_aux));
+ break;
+ case FRAME_TYPE_MODEM_STATUS:
+ printk(KERN_DEBUG "%s(): Type: Modem Status\n", __func__);
+ switch(api_frame->api_data->modem_status.status)
+ {
+ case 0x00:
+ printk(KERN_DEBUG "%s(): Status: Hardware reset\n", __func__);
+ break;
+ case 0x01:
+ printk(KERN_DEBUG "%s(): Status: Watchdog time reset\n", __func__);
+ break;
+ case 0x0B:
+ printk(KERN_DEBUG "%s(): Status: Network Woke Up\n", __func__);
+ break;
+ case 0x0C:
+ printk(KERN_DEBUG "%s(): Status: Network Went To Sleep\n", __func__);
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Status: Unknown (0x%02X)\n", __func__,api_frame->api_data->modem_status.status);
+ break;
+ }
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS1:
+ printk(KERN_DEBUG "%s(): Type: Transmit Status\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->transmit_status.frame_id);
+ printk(KERN_DEBUG "%s(): Reserved: %04X\n", __func__,api_frame->api_data->transmit_status.reserved);
+ printk(KERN_DEBUG "%s(): Transmit Retry Count: %d\n", __func__,api_frame->api_data->transmit_status.transmit_retry_count);
+ switch(api_frame->api_data->transmit_status.delivery_status)
+ {
+ case 0x00:
+ printk(KERN_DEBUG "%s(): Delivery Status: Success\n", __func__);
+ break;
+ case 0x01:
+ printk(KERN_DEBUG "%s(): Delivery Status: MAC ACK Failure\n", __func__);
+ break;
+ case 0x15:
+ printk(KERN_DEBUG "%s(): Delivery Status: Invalid destination endpoint\n", __func__);
+ break;
+ case 0x21:
+ printk(KERN_DEBUG "%s(): Delivery Status: Network ACK Failure\n", __func__);
+ break;
+ case 0x25:
+ printk(KERN_DEBUG "%s(): Delivery Status: Route Not Found\n", __func__);
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Delivery Status: Unknown (0x%02X)\n", __func__,api_frame->api_data->transmit_status.delivery_status);
+ break;
+ }
+ switch(api_frame->api_data->transmit_status.discovery_status)
+ {
+ case 0x00:
+ printk(KERN_DEBUG "%s(): Discovery Status: No Discovery Overhead\n", __func__);
+ break;
+ case 0x02:
+ printk(KERN_DEBUG "%s(): Discovery Status: Route Discovery\n", __func__);
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Discovery Status: Unknown (0x%02X)\n", __func__,api_frame->api_data->transmit_status.discovery_status);
+ break;
+ }
+ break;
+ case FRAME_TYPE_TRANSMIT_STATUS2:
+ printk(KERN_DEBUG "%s(): Type: Transmit Status 2\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->transmit_status2.frame_id);
+ switch(api_frame->api_data->transmit_status2.delivery_status)
+ {
+ case 0x00:
+ printk(KERN_DEBUG "%s(): Success, no errors were detected on transmission.\n", __func__);
+ break;
+ case 0x01:
+ printk(KERN_DEBUG "%s(): An expected MAC acknowledgement never occurred.\n", __func__);
+ break;
+ case 0x02:
+ printk(KERN_DEBUG "%s(): CCA failure.\n", __func__);
+ break;
+ case 0x03:
+ printk(KERN_DEBUG "%s(): Transmission was purged because it was attempted before the stack was up.\n", __func__);
+ break;
+ case 0x04:
+ printk(KERN_DEBUG "%s(): Physical error occurred on the interface with the WiFi transceiver.\n", __func__);
+ break;
+ case 0x18:
+ printk(KERN_DEBUG "%s(): No Buffers.\n", __func__);
+ break;
+ case 0x21:
+ printk(KERN_DEBUG "%s(): An expected network acknowledgement never occurred.\n", __func__);
+ break;
+ case 0x22:
+ printk(KERN_DEBUG "%s(): Not joined to network.\n", __func__);
+ break;
+ case 0x23:
+ printk(KERN_DEBUG "%s(): Self-addressed.\n", __func__);
+ break;
+ case 0x24:
+ printk(KERN_DEBUG "%s(): Address not found.\n", __func__);
+ break;
+ case 0x25:
+ printk(KERN_DEBUG "%s(): Route not found.\n", __func__);
+ break;
+ case 0x26:
+ printk(KERN_DEBUG "%s(): Broadcast relay was not heard.\n", __func__);
+ break;
+ case 0x2B:
+ printk(KERN_DEBUG "%s(): Invalid Binding Table Index.\n", __func__);
+ break;
+ case 0x2C:
+ printk(KERN_DEBUG "%s(): Invalid Endpoint.\n", __func__);
+ break;
+ case 0x31:
+ printk(KERN_DEBUG "%s(): A software error occurred.\n", __func__);
+ break;
+ case 0x32:
+ printk(KERN_DEBUG "%s(): Resource Error.\n", __func__);
+ break;
+ case 0x74:
+ printk(KERN_DEBUG "%s(): Data payload too large.\n", __func__);
+ break;
+ case 0x76:
+ printk(KERN_DEBUG "%s(): Attempt to create a client socket failed.\n", __func__);
+ break;
+ case 0xBB:
+ printk(KERN_DEBUG "%s(): Key not authorized.\n", __func__);
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Delivery Status: Unknown (0x%02X)\n", __func__,api_frame->api_data->transmit_status2.delivery_status);
+ break;
+ }
+ break;
+ case FRAME_TYPE_RECEIVE_PACKET:
+ printk(KERN_DEBUG "%s(): Type: Receive Packet\n", __func__);
+ printk(KERN_DEBUG "%s(): Src Addr: %s\n", __func__,eui64_address_to_str(api_frame->api_data->receive_packet.src_addr,eui64_addr_str));
+ printk(KERN_DEBUG "%s(): Reserved: %04X\n", __func__,api_frame->api_data->receive_packet.reserved);
+ if(api_frame->api_data->receive_packet.options & 0x01)
+ printk(KERN_DEBUG "%s(): Packet Acknowleged\n", __func__);
+ if(api_frame->api_data->receive_packet.options & 0x02)
+ printk(KERN_DEBUG "%s(): Packet was broadcast packet\n", __func__);
+ printk(KERN_DEBUG "%s(): Payload Lenght: %d\n", __func__,api_frame->api_data->receive_packet.payload_len);
+ printk(KERN_DEBUG "%s(): Payload: ", __func__);
+ for(i = 0;i<api_frame->api_data->receive_packet.payload_len;i++){
+ printk("%02X ",api_frame->api_data->receive_packet.payload[i]);
+ }
+ printk("\n");
+
+ break;
+ case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+ printk(KERN_DEBUG "%s(): Type: Explitict RX Indicator\n", __func__);
+ printk(KERN_DEBUG "%s(): Src Addr: %s\n", __func__,eui64_address_to_str(api_frame->api_data->explicit_rx_indicator.src_addr,eui64_addr_str));
+ printk(KERN_DEBUG "%s(): Reserved: %04X\n", __func__,api_frame->api_data->explicit_rx_indicator.reserved);
+ printk(KERN_DEBUG "%s(): Src Endpoint: 0x%02X\n", __func__,api_frame->api_data->explicit_rx_indicator.src_endpoint);
+ printk(KERN_DEBUG "%s(): Dst Endpoint: 0x%02X\n", __func__,api_frame->api_data->explicit_rx_indicator.dst_endpoint);
+ printk(KERN_DEBUG "%s(): ClusterID: %04X\n", __func__,api_frame->api_data->explicit_rx_indicator.cluster_id);
+ printk(KERN_DEBUG "%s(): ProfileID: %04X\n", __func__,api_frame->api_data->explicit_rx_indicator.profile_id);
+ if(api_frame->api_data->explicit_rx_indicator.options & 0x01)
+ printk(KERN_DEBUG "%s(): Packet Acknowleged\n", __func__);
+ if(api_frame->api_data->explicit_rx_indicator.options & 0x02)
+ printk(KERN_DEBUG "%s(): Packet was broadcast packet\n", __func__);
+ printk(KERN_DEBUG "%s(): Payload Lenght: %d\n", __func__,api_frame->api_data->explicit_rx_indicator.payload_len);
+ printk(KERN_DEBUG "%s(): Payload: ", __func__);
+ for(i = 0;i<api_frame->api_data->explicit_rx_indicator.payload_len;i++){
+ printk("%02X ",api_frame->api_data->explicit_rx_indicator.payload[i]);
+ }
+ printk("\n");
+
+ break;
+ case FRAME_TYPE_NODE_ID_INDICATOR:
+ printk(KERN_DEBUG "%s(): Type: Node Identification Indicator\n", __func__);
+ printk(KERN_DEBUG "%s(): Sender Addr: %s\n", __func__,eui64_address_to_str(api_frame->api_data->node_id_indicator.sender_addr,eui64_addr_str));
+ printk(KERN_DEBUG "%s(): Sender Short Addr: %04X\n", __func__,api_frame->api_data->node_id_indicator.sender_short_addr);
+ if(api_frame->api_data->node_id_indicator.options & 0x01)
+ printk(KERN_DEBUG "%s(): Packet Acknowleged\n", __func__);
+ if(api_frame->api_data->node_id_indicator.options & 0x02)
+ printk(KERN_DEBUG "%s(): Packet was broadcast packet\n", __func__);
+ printk(KERN_DEBUG "%s(): Remote Short Addr: %04X\n", __func__,api_frame->api_data->node_id_indicator.src_short_addr);
+ printk(KERN_DEBUG "%s(): Remote Addr: %s\n", __func__,eui64_address_to_str(api_frame->api_data->node_id_indicator.src_addr,eui64_addr_str));
+ printk(KERN_DEBUG "%s(): Ni: \"%s\"\n", __func__,api_frame->api_data->node_id_indicator.ni_string);
+ printk(KERN_DEBUG "%s(): Remote Short Addr: %04X\n", __func__,api_frame->api_data->node_id_indicator.parent_short_addr);
+
+ break;
+ case FRAME_TYPE_REMOTE_CMD_RESP:
+ printk(KERN_DEBUG "%s(): Type: Remote Command Response\n", __func__);
+ printk(KERN_DEBUG "%s(): FrameID: %d\n", __func__,api_frame->api_data->remote_cmd_resp.frame_id);
+ printk(KERN_DEBUG "%s(): Src Addr: %s\n", __func__,eui64_address_to_str(api_frame->api_data->remote_cmd_resp.src_addr,eui64_addr_str));
+ printk(KERN_DEBUG "%s(): Reserved: %04X\n", __func__,api_frame->api_data->remote_cmd_resp.reserved);
+ printk(KERN_DEBUG "%s(): Command: %c%c\n", __func__,api_frame->api_data->remote_cmd_resp.at_command[0],api_frame->api_data->remote_cmd_resp.at_command[1]);
+ switch(api_frame->api_data->remote_cmd_resp.cmd_status)
+ {
+ case 0x00:
+ printk(KERN_DEBUG "%s(): Command Status: OK\n", __func__);
+ break;
+ case 0x01:
+ printk(KERN_DEBUG "%s(): Command Status: Error\n", __func__);
+ break;
+ case 0x02:
+ printk(KERN_DEBUG "%s(): Command Status: Invalid Command\n", __func__);
+ break;
+ case 0x03:
+ printk(KERN_DEBUG "%s(): Command Status: Invalid Parameter\n", __func__);
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Command Status: Unknown status 0x%02X\n", __func__,api_frame->api_data->remote_cmd_resp.cmd_status);
+ break;
+ }
+ if(api_frame->api_data->remote_cmd_resp.cmd_data_len)
+ printk(KERN_DEBUG "%s(): Parameter: %s\n", __func__,at_command_get_parameter_str(api_frame,str_aux));
+
+ break;
+ default:
+ printk(KERN_DEBUG "%s(): Type: Unknown (0x%02X)\n", __func__,api_frame->api_id);
+ break;
+ }
+
+ printk(KERN_DEBUG "%s(): ______________________________________________________\n", __func__);
+#endif
+}
+
+
+/*
+ * Escape helpers
+ */
+static int
+escape_required(uint8_t c)
+{
+ return ((XBEE_START_DELIM == c) ||
+ (XBEE_ESCAPE == c) ||
+ (XBEE_XON == c) ||
+ (XBEE_XOFF == c));
+}
+static int
+unescape_required(uint8_t c)
+{
+ return (XBEE_ESCAPE == c);
+}
+
+/*
+ * Received data processing
+ */
+
+static int
+_api_frame_process_response(_api_frame_t *api_frame)
+{
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: api_frame NULL pointer\n", __func__);
+ BUG();
+ }
+ pr_debug("%s(): api_frame request 0x%02X with response 0x%02X\n", __func__,api_frame->api_id,api_frame->response->api_id);
+ switch(api_frame->api_id)
+ {
+ // Requests
+ case FRAME_TYPE_AT_CMD:
+ if(api_frame->response->api_id != FRAME_TYPE_AT_CMD_RESP)
+ {
+ printk(KERN_WARNING "%s: invalid response type: 0x%02X (expected 0x%02X)\n", __func__,api_frame->response->api_id,FRAME_TYPE_AT_CMD_RESP);
+ return -EINVAL;
+ }
+ if(api_frame->response->api_data->at_cmd_resp.cmd_status != 0)
+ {
+ printk(KERN_DEBUG "%s: error issuing AT command: 0x%02X\n", __func__,api_frame->response->api_data->at_cmd_resp.cmd_status);
+ return -EINVAL;
+ }
+ break;
+ case FRAME_TYPE_AT_CMD_QUEUE:
+ if(api_frame->response->api_id != FRAME_TYPE_AT_CMD_RESP)
+ {
+ printk(KERN_WARNING "%s: invalid response type: 0x%02X (expected 0x%02X)\n", __func__,api_frame->response->api_id,FRAME_TYPE_AT_CMD_RESP);
+ return -EINVAL;
+ }
+ if(api_frame->response->api_data->at_cmd_resp.cmd_status != 0)
+ {
+ printk(KERN_DEBUG "%s: error issuing AT command: 0x%02X\n", __func__,api_frame->response->api_data->at_cmd_resp.cmd_status);
+ return -EINVAL;
+ }
+ break;
+ case FRAME_TYPE_TRANSMIT_REQ:
+ if(api_frame->response->api_id != FRAME_TYPE_TRANSMIT_STATUS1 && api_frame->response->api_id != FRAME_TYPE_TRANSMIT_STATUS2)
+ {
+ printk(KERN_WARNING "%s: invalid response type: 0x%02X (expected 0x%02X)\n", __func__,api_frame->response->api_id,FRAME_TYPE_TRANSMIT_STATUS1);
+ return -EINVAL;
+ }
+ if(api_frame->response->api_data->transmit_status.delivery_status)
+ {
+ printk(KERN_DEBUG "%s: error transmitting data: 0x%02X retries: %d disc: 0x%02X\n", __func__,
+ api_frame->response->api_data->transmit_status.delivery_status,
+ api_frame->response->api_data->transmit_status.transmit_retry_count,
+ api_frame->response->api_data->transmit_status.discovery_status);
+ return -EAGAIN;
+ }
+ break;
+
+ case FRAME_TYPE_RAW_TRANSMIT_REQ:
+ if(api_frame->response->api_id != FRAME_TYPE_RAW_TRANSMIT_STATUS)
+ {
+ printk(KERN_WARNING "%s: invalid response type: 0x%02X (expected 0x%02X)\n", __func__,api_frame->response->api_id,FRAME_TYPE_RAW_TRANSMIT_STATUS);
+ return -EINVAL;
+ }
+ if(api_frame->response->api_data->raw_transmit_status.delivery_status)
+ {
+ printk(KERN_DEBUG "%s: error transmitting data: 0x%02X\n", __func__,
+ api_frame->response->api_data->raw_transmit_status.delivery_status);
+ return -EAGAIN;
+ }
+ break;
+
+ case FRAME_TYPE_EXPLICIT_ADDR_CMD:
+ if(api_frame->response->api_id != FRAME_TYPE_TRANSMIT_STATUS1 && api_frame->response->api_id != FRAME_TYPE_TRANSMIT_STATUS2)
+ {
+ printk(KERN_WARNING "%s: invalid response type: 0x%02X (expected 0x%02X)\n", __func__,api_frame->response->api_id,FRAME_TYPE_TRANSMIT_STATUS1);
+ return -EINVAL;
+ }
+ if(api_frame->response->api_data->transmit_status.delivery_status)
+ {
+ printk(KERN_DEBUG "%s: error transmitting data: 0x%02X\n", __func__,api_frame->response->api_data->transmit_status.delivery_status);
+ return -EAGAIN;
+ }
+ break;
+ case FRAME_TYPE_REMOTE_AT_CMD_REQ:
+ if(api_frame->response->api_id != FRAME_TYPE_REMOTE_CMD_RESP)
+ {
+ printk(KERN_WARNING "%s: invalid response type: 0x%02X (expected 0x%02X)\n", __func__,api_frame->response->api_id,FRAME_TYPE_REMOTE_CMD_RESP);
+ return -EINVAL;
+ }
+ if(api_frame->response->api_data->remote_cmd_resp.cmd_status != 0)
+ {
+ printk(KERN_DEBUG "%s: error issuing AT command: 0x%02X\n", __func__,api_frame->response->api_data->remote_cmd_resp.cmd_status);
+ return -EINVAL;
+ }
+ break;
+
+ // Responses
+// case FRAME_TYPE_AT_CMD_RESP:
+// return 1;
+// break;
+// case FRAME_TYPE_MODEM_STATUS:
+// return 1;
+// break;
+// case FRAME_TYPE_TRANSMIT_STATUS:
+// return 1;
+// break;
+// case FRAME_TYPE_RECEIVE_PACKET:
+// return 1;
+// break;
+// case FRAME_TYPE_EXPLICIT_RX_INDICATOR:
+// return 1;
+// break;
+// case FRAME_TYPE_NODE_ID_INDICATOR:
+// return 1;
+// break;
+// case FRAME_TYPE_REMOTE_CMD_RESP:
+// return 1;
+// break;
+ default:
+ printk(KERN_WARNING "%s(): Invalid Request Type (0x%02X)\n", __func__,api_frame->api_id);
+ break;
+ return 0;
+ }
+ return 0;
+}
+
+static void
+ieee802154_net_rx(struct xbee_device *xbee_dev, _api_frame_t *api_frame);
+
+static int
+_api_frame_process(struct xbee_device *xbee_dev, _api_frame_t *api_frame)
+{
+ int ret = 0;
+ if(xbee_dev == NULL)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: api_frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+#ifdef DEBUG
+ printk(KERN_INFO "%s(): Call process frame\n", __func__);
+#endif
+
+ //_api_frame_print(api_frame);
+
+ if(_api_frame_should_signal_pendent(api_frame))
+ {
+ xbee_device_signal_pendent_req(xbee_dev,api_frame);
+ }
+ else
+ {
+ //TODO: not pendent request response
+ _api_frame_print(api_frame);
+
+ //FIXME we should only push to stack the received_packets frames or RAW
+ ieee802154_net_rx(xbee_dev,api_frame);
+
+ _api_frame_free(api_frame);
+ api_frame = NULL;
+ }
+
+ return ret;
+}
+
+static int
+xbee_process_char(struct xbee_device *xbee_dev, unsigned char c)
+{
+ _api_frame_t *api_frame = NULL;
+//#ifdef DEBUG
+// printk(KERN_INFO "%s(): current state %s\n", __func__,
+// xbee_recv_state_str(xbee_dev->recv_state));
+//
+// printk(KERN_INFO "%s(): processing %3d (0x%02X)\n", __func__,c,c);
+//#endif
+
+ /* Data processing */
+ switch (xbee_dev->recv_state) {
+ case RECV_STATE_WAIT_START_DELIM:
+ if (XBEE_START_DELIM == c)
+ {
+ xbee_dev->recv_state = RECV_STATE_WAIT_MSB;
+ }
+ break;
+ case RECV_STATE_WAIT_MSB:
+ xbee_dev->recv_data_size = c;
+ xbee_dev->recv_state = RECV_STATE_WAIT_LSB;
+ break;
+ case RECV_STATE_WAIT_LSB:
+
+ if(xbee_dev->recv_data)
+ {
+ printk(KERN_INFO "%s(): we shouldnt get data buffers here!\n",__func__);
+ }
+
+ xbee_dev->recv_data_size <<= 8;
+ xbee_dev->recv_data_size += c;
+ xbee_dev->recv_state = RECV_STATE_WAIT_DATA;
+
+#ifdef __KERNEL__
+ xbee_dev->recv_data = kzalloc(xbee_dev->recv_data_size, GFP_KERNEL);
+#else
+ xbee_dev->recv_data = calloc(xbee_dev->recv_data_size,sizeof(uint8_t));
+#endif
+ if (!xbee_dev->recv_data) {
+ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
+ xbee_dev->recv_data_size = 0;
+ return -ENOMEM;
+ }
+
+ xbee_dev->recv_data_offset = 0;
+ xbee_dev->recv_data_sum = 0;
+
+#ifndef __KERNEL__
+#ifdef DEBUG
+ printk(KERN_INFO "%s(): Got payload length: %"PRIu16"\n", __func__,xbee_dev->recv_data_size);
+#endif
+#endif
+
+ break;
+ case RECV_STATE_WAIT_DATA:
+//#ifdef DEBUG
+// printk(KERN_INFO "%s(): processing: index data[%u]\n", __func__,xbee_dev->recv_data_offset);
+//#endif
+ xbee_dev->recv_data_sum += c;
+ xbee_dev->recv_data[xbee_dev->recv_data_offset++] = c;
+ if(xbee_dev->recv_data_offset == xbee_dev->recv_data_size)
+ {
+ xbee_dev->recv_state = RECV_STATE_WAIT_CHECKSUM;
+ }
+ break;
+ case RECV_STATE_WAIT_CHECKSUM:
+ if(0xFF - xbee_dev->recv_data_sum != c)
+ {
+ printk(KERN_WARNING "%s(): checksum failed: got 0x%02X (expected 0x%02X)\n", __func__,c,0xFF - xbee_dev->recv_data_sum);
+ printk(KERN_WARNING "%s(): Error parsing frame: discarding\n", __func__);
+ printk(KERN_WARNING "%s(): received %d bytes\n", __func__,xbee_dev->recv_data_size);
+ print_hex_dump_bytes("xbee_process_char(): ", DUMP_PREFIX_NONE, xbee_dev->recv_data, xbee_dev->recv_data_size);
+
+#ifdef __KERNEL__
+ if(xbee_dev->recv_data)
+ kfree(xbee_dev->recv_data);
+#else
+ free(xbee_dev->recv_data);
+#endif
+ xbee_dev->recv_data = NULL;
+ xbee_dev->recv_data_offset = 0;
+ xbee_dev->recv_data_escape_next = 0;
+ xbee_dev->recv_data_sum = 0;
+ xbee_dev->recv_data_size = 0;
+ }
+ else
+ {
+#ifdef DEBUG
+ printk(KERN_INFO "%s(): Got valid frame\n", __func__);
+#endif
+ api_frame = _api_frame_parse(xbee_dev->recv_data_size,xbee_dev->recv_data,c);
+ if(api_frame)
+ {
+ xbee_dev->recv_data = NULL;
+ xbee_dev->recv_data_offset = 0;
+ xbee_dev->recv_data_escape_next = 0;
+ xbee_dev->recv_data_sum = 0;
+ xbee_dev->recv_data_size = 0;
+ if(_api_frame_process(xbee_dev,api_frame))
+ {
+ printk(KERN_WARNING "%s(): error processing frame\n", __func__);
+ }
+ api_frame = NULL;
+ }
+ else
+ {
+ printk(KERN_WARNING "%s(): Error parsing frame: discarding\n", __func__);
+#ifdef __KERNEL__
+ if(xbee_dev->recv_data)
+ kfree(xbee_dev->recv_data);
+#else
+ free(xbee_dev->recv_data);
+#endif
+ xbee_dev->recv_data = NULL;
+ xbee_dev->recv_data_offset = 0;
+ xbee_dev->recv_data_escape_next = 0;
+ xbee_dev->recv_data_sum = 0;
+ xbee_dev->recv_data_size = 0;
+ }
+ }
+
+ xbee_dev->recv_state = RECV_STATE_WAIT_START_DELIM;
+ wake_up(&xbee_dev->wq);
+
+ break;
+ default:
+ BUG(); //FIXME check if we can reach this point
+ break;
+ }
+ return 0;
+}
+
+static int
+xbee_receive(struct xbee_device *xbee_dev, const unsigned char *buf, int count)
+{
+ uint8_t rx_data = 0;
+ int i = 0;
+ if(xbee_dev == NULL)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(buf == NULL)
+ {
+ printk(KERN_ERR "%s: buf NULL pointer\n", __func__);
+ BUG();
+ }
+ for (i=0; i < count; ++i){
+ rx_data = buf[i];
+ if(xbee_dev->recv_state != RECV_STATE_WAIT_START_DELIM && xbee_dev->escaped_mode) {
+ if(unescape_required(rx_data))
+ {
+ xbee_dev->recv_data_escape_next = 1;
+ }
+ else if(xbee_dev->recv_data_escape_next)
+ {
+ xbee_dev->recv_data_escape_next = 0;
+ rx_data = buf[i]^0x20;
+ xbee_process_char(xbee_dev, rx_data);
+ } else {
+ xbee_process_char(xbee_dev, rx_data);
+ }
+ } else {
+ xbee_process_char(xbee_dev, rx_data);
+ }
+ }
+ return 0;
+}
+
+static int
+xbee_send(struct xbee_device *xbee_dev, _api_frame_t *api_frame)
+{
+ int ret = 0;
+#ifndef __KERNEL__
+ struct timeval tv = {0,0};
+ struct timespec waitspec = {0,0};
+ //pthread_attr_t attr;
+#endif
+
+ uint16_t len = 0;
+ uint8_t *raw_frame = NULL;
+ if(xbee_dev == NULL)
+ {
+ printk(KERN_ERR "%s: xbee_dev NULL pointer\n", __func__);
+ BUG();
+ }
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: api_frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+ raw_frame = _api_frame_to_raw(api_frame,&len);
+
+ if(raw_frame == NULL)
+ {
+ printk(KERN_ERR "%s: raw_frame NULL pointer\n", __func__);
+ BUG();
+ }
+
+ if(_api_frame_should_wait_response(api_frame))
+ {
+ xbee_device_add_pendent_req(xbee_dev,api_frame);
+ }
+
+ if((ret = xbee_device_write_to_phy(xbee_dev,raw_frame,len)) != len)
+ {
+ printk(KERN_ERR "%s: error writing to phy media: ret: %d len: %u\n", __func__,ret,len);
+ BUG(); // FIXME
+ /*
+ * [ 1034.907503] xbee_send: error writing to phy media
+[ 1034.924140] ------------[ cut here ]------------
+[ 1034.928770] kernel BUG at drivers/net/ieee802154/xbee.c:2177!
+[ 1034.934507] Internal error: Oops - BUG: 0 [#1] PREEMPT ARM
+
+Entering kdb (current=0xda84a080, pid 6) Oops: (null)
+due to oops @ 0xbf1a4ed0
+
+Pid: 6, comm: kworker/u:0
+CPU: 0 Not tainted (3.9.6+ #1)
+PC is at xbee_send+0x12c/0x854 [xbee]
+LR is at xbee_send+0x12c/0x854 [xbee]
+pc : [<bf1a4ed0>] lr : [<bf1a4ed0>] psr: 60000113
+sp : da851e90 ip : 60000113 fp : 00000089
+r10: 0000006f r9 : da850000 r8 : 00000000
+r7 : 0000006f r6 : d99b49e0 r5 : d8511b40 r4 : da9c2660
+r3 : 00000000 r2 : c057f344 r1 : c0571a80 r0 : 00000025
+Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
+Control: 00c5387d Table: 1aac0008 DAC: 00000017
+ *
+ */
+ } else {
+ ret = 0;
+ }
+
+ if(raw_frame)
+ {
+#ifdef __KERNEL__
+ kfree(raw_frame);
+#else
+ free(raw_frame);
+#endif
+ raw_frame = NULL;
+ }
+
+ if(_api_frame_should_wait_response(api_frame))
+ {
+ //xbee_device_add_pendent_req(xbee_dev,api_frame);
+#ifdef __KERNEL__
+ INIT_COMPLETION(api_frame->complete);
+ ret = wait_for_completion_interruptible_timeout(
+ &api_frame->complete,
+ 2 * HZ);
+ if (ret == -ERESTARTSYS){
+ xbee_device_remove_pendent_req(xbee_dev,api_frame);
+ goto err;
+ }
+ if (ret == 0) {
+ xbee_device_remove_pendent_req(xbee_dev,api_frame);
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+#else
+ printk(KERN_DEBUG "%s: waiting for response...\n", __func__);
+ gettimeofday(&tv,NULL);
+ waitspec.tv_sec = tv.tv_sec + 5;
+ waitspec.tv_nsec = 0;
+ pthread_mutex_lock(&api_frame->mutex);
+ ret = pthread_cond_timedwait(&api_frame->complete,&api_frame->mutex,&waitspec);
+ if(ret != 0 && ret != ETIMEDOUT){
+ printk(KERN_ERR "%s: some error occur waiting for status to change: %d", __func__, ret);
+ pthread_mutex_unlock(&api_frame->mutex);
+ goto err;
+ }
+ pthread_mutex_unlock(&api_frame->mutex);
+ if(ret == ETIMEDOUT){
+ printk(KERN_DEBUG "%s: timeout!!!\n", __func__);
+ goto err;
+ }else{
+ printk(KERN_DEBUG "%s: response received\n", __func__);
+ }
+#endif
+ xbee_device_remove_pendent_req(xbee_dev,api_frame);
+ if(!api_frame->response)
+ {
+ printk(KERN_DEBUG "%s: response not available\n", __func__);
+ ret = -EBUSY;
+ goto err;
+ }
+ ret = _api_frame_process_response(api_frame);
+ if(ret)
+ {
+ printk(KERN_DEBUG "%s: error in response\n", __func__);
+ goto err;
+ }
+ }
+
+
+err:
+ pr_debug("%s(): ret: %d\n", __func__,ret);
+ return ret;
+}
+
+/*
+ * Frame API AT Command
+ */
+
+static _api_frame_t *
+_api_frame_new_at_command(struct xbee_device *xbee_dev,const char cmdid[3])
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(4,sizeof(api_frame_at_cmd_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd.api_id = FRAME_TYPE_AT_CMD;
+ api_frame->api_data->at_cmd.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd.parameter_value_len = 0;
+ return api_frame;
+}
+
+static _api_frame_t *
+_api_frame_new_at_command_u8(struct xbee_device *xbee_dev,const char cmdid[3],uint8_t arg)
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(5,sizeof(api_frame_at_cmd_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd.api_id = FRAME_TYPE_AT_CMD;
+ api_frame->api_data->at_cmd.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd.parameter_value[0] = arg;
+ api_frame->api_data->at_cmd.parameter_value_len = 1;
+ return api_frame;
+}
+
+static _api_frame_t *
+_api_frame_new_at_command_u16(struct xbee_device *xbee_dev,const char cmdid[3],uint8_t arg[2])
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(6,sizeof(api_frame_at_cmd_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd.api_id = FRAME_TYPE_AT_CMD;
+ api_frame->api_data->at_cmd.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd.parameter_value[0] = arg[0];
+ api_frame->api_data->at_cmd.parameter_value[1] = arg[1];
+ api_frame->api_data->at_cmd.parameter_value_len = 2;
+ return api_frame;
+}
+
+static _api_frame_t *
+_api_frame_new_at_command_u32(struct xbee_device *xbee_dev,const char cmdid[3],uint8_t arg[4])
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(8,sizeof(api_frame_at_cmd_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd.api_id = FRAME_TYPE_AT_CMD;
+ api_frame->api_data->at_cmd.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd.parameter_value[0] = arg[0];
+ api_frame->api_data->at_cmd.parameter_value[1] = arg[1];
+ api_frame->api_data->at_cmd.parameter_value[2] = arg[2];
+ api_frame->api_data->at_cmd.parameter_value[3] = arg[3];
+ api_frame->api_data->at_cmd.parameter_value_len = 4;
+ return api_frame;
+}
+
+/*
+ * Frame API AT Command - Queue Parameter Value
+ */
+
+static _api_frame_t *
+_api_frame_new_at_command_queue(struct xbee_device *xbee_dev,const char cmdid[3])
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(4,sizeof(api_frame_at_cmd_queue_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd_queue.api_id = FRAME_TYPE_AT_CMD_QUEUE;
+ api_frame->api_data->at_cmd_queue.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd_queue.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd_queue.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd_queue.parameter_value_len = 0;
+ return api_frame;
+}
+
+static _api_frame_t *
+_api_frame_new_at_command_queue_u8(struct xbee_device *xbee_dev,const char cmdid[3],uint8_t arg)
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(5,sizeof(api_frame_at_cmd_queue_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd_queue.api_id = FRAME_TYPE_AT_CMD_QUEUE;
+ api_frame->api_data->at_cmd_queue.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd_queue.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd_queue.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd_queue.parameter_value[0] = arg;
+ api_frame->api_data->at_cmd_queue.parameter_value_len = 1;
+ return api_frame;
+}
+
+static _api_frame_t *
+_api_frame_new_at_command_queue_u16(struct xbee_device *xbee_dev,const char cmdid[3],uint8_t arg[2])
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(6,sizeof(api_frame_at_cmd_queue_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd_queue.api_id = FRAME_TYPE_AT_CMD_QUEUE;
+ api_frame->api_data->at_cmd_queue.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd_queue.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd_queue.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd_queue.parameter_value[0] = arg[0];
+ api_frame->api_data->at_cmd_queue.parameter_value[1] = arg[1];
+ api_frame->api_data->at_cmd_queue.parameter_value_len = 2;
+ return api_frame;
+}
+
+static _api_frame_t *
+_api_frame_new_at_command_queue_u32(struct xbee_device *xbee_dev,const char cmdid[3],uint8_t arg[4])
+{
+ _api_frame_t *api_frame = NULL;
+ api_frame = _api_frame_alloc(8,sizeof(api_frame_at_cmd_queue_t));
+ if(api_frame == NULL)
+ {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->at_cmd_queue.api_id = FRAME_TYPE_AT_CMD_QUEUE;
+ api_frame->api_data->at_cmd_queue.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->at_cmd_queue.at_command[0] = cmdid[0];
+ api_frame->api_data->at_cmd_queue.at_command[1] = cmdid[1];
+ api_frame->api_data->at_cmd_queue.parameter_value[0] = arg[0];
+ api_frame->api_data->at_cmd_queue.parameter_value[1] = arg[1];
+ api_frame->api_data->at_cmd_queue.parameter_value[2] = arg[2];
+ api_frame->api_data->at_cmd_queue.parameter_value[3] = arg[3];
+ api_frame->api_data->at_cmd_queue.parameter_value_len = 4;
+ return api_frame;
+}
+
+/*
+ * Frame API Transmit Request
+ */
+
+static _api_frame_t *
+_api_frame_new_transmit_request(struct xbee_device *xbee_dev,
+ uint8_t dst_addr[XBEE_ADDR_LEN], uint8_t options, uint8_t *payload,
+ uint16_t payload_len) {
+ _api_frame_t *api_frame = NULL;
+ size_t frame_len = 1 /* frame type */ +
+ 1 /* frameID*/ +
+ XBEE_ADDR_LEN +
+ 2 /* reserved */ +
+ 1 /* broadcast radius */ +
+ 1 /* transmit options */ +
+ payload_len;
+ api_frame = _api_frame_alloc(frame_len,sizeof(api_frame_transmit_req_t));
+ if (api_frame == NULL ) {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->transmit_req.api_id = FRAME_TYPE_TRANSMIT_REQ;
+ api_frame->api_data->transmit_req.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ memcpy(api_frame->api_data->transmit_req.dst_addr, dst_addr, XBEE_ADDR_LEN);
+ api_frame->api_data->transmit_req.reserved = 0xFFFE;
+ api_frame->api_data->transmit_req.brd_radius = XBEE_DEFAULT_BROADCAST_RADIUS;
+ api_frame->api_data->transmit_req.options = options;
+ api_frame->api_data->transmit_req.payload = payload;
+ api_frame->api_data->transmit_req.payload_len = payload_len;
+ return api_frame;
+}
+
+/*
+ * Frame API IEEE 802.15.4 Raw Packet
+ */
+
+static _api_frame_t *
+_api_frame_new_raw_packet(struct xbee_device *xbee_dev, uint8_t *payload, uint16_t payload_len) {
+ _api_frame_t *api_frame = NULL;
+ size_t frame_len = 1 /* frame type */ +
+ payload_len;
+ api_frame = _api_frame_alloc(frame_len,sizeof(api_frame_transmit_req_t));
+ if (api_frame == NULL ) {
+ printk(KERN_ERR "%s: error creating api_frame\n", __func__);
+ BUG();
+ }
+ api_frame->api_id = api_frame->api_data->raw_packet.api_id = FRAME_TYPE_RAW_TRANSMIT_REQ;
+ api_frame->api_data->raw_packet.frame_id = _xbee_device_gen_frame_id(xbee_dev);
+ api_frame->api_data->raw_packet.payload = payload;
+ api_frame->api_data->raw_packet.payload_len = payload_len;
+ return api_frame;
+}
+
+/*
+ * Frame API Explicit Addressing Command
+ */
+
+//static _api_frame_t *
+//_api_frame_new_explicit_addressing(struct xbee_device *xbee_dev,
+// uint8_t dst_addr[XBEE_ADDR_LEN], uint8_t options, uint8_t *payload,
+// uint16_t payload_len) {
+// //TODO: _api_frame_new_explicit_addressing: not implemented
+// return NULL;
+//}
+
+/*
+ * Frame API Remote AT Command Request
+ */
+
+//static _api_frame_t *
+//_api_frame_new_remote_at_command(struct xbee_device *xbee_dev,
+// uint8_t dst_addr[XBEE_ADDR_LEN], const char cmdid[3]) {
+// //TODO: _api_frame_new_remote_at_command_u32: not implemented
+// return NULL ;
+//}
+//
+//static _api_frame_t *
+//_api_frame_new_remote_at_command_u8(struct xbee_device *xbee_dev,
+// uint8_t dst_addr[XBEE_ADDR_LEN], const char cmdid[3], uint8_t arg[1]) {
+// //TODO: _api_frame_new_remote_at_command_u8: not implemented
+// return NULL ;
+//}
+//
+//static _api_frame_t *
+//_api_frame_new_remote_at_command_u16(struct xbee_device *xbee_dev,
+// uint8_t dst_addr[XBEE_ADDR_LEN], const char cmdid[3], uint8_t arg[2]) {
+// //TODO: _api_frame_new_remote_at_command_u16: not implemented
+// return NULL ;
+//}
+//
+//static _api_frame_t *
+//_api_frame_new_remote_at_command_u32(struct xbee_device *xbee_dev,
+// uint8_t dst_addr[XBEE_ADDR_LEN], const char cmdid[3], uint8_t arg[4]) {
+// //TODO: _api_frame_new_remote_at_command_u32: not implemented
+// return NULL ;
+//}
+
+/*
+ * XBee AT Command Read 32 bit parameter
+ */
+
+static int
+xbee_api_at_command_read_uN(struct xbee_device *xbee_dev, const char cmdid[3], uint8_t value[4], uint8_t len)
+{
+ int ret = 0;
+ int i = 0;
+ _api_frame_t *api_frame = NULL;
+
+ if (NULL == xbee_dev) {
+ printk(KERN_ERR "%s: wrong xbee device\n", __func__);
+ return -EINVAL;
+ }
+
+ api_frame = _api_frame_new_at_command(xbee_dev,cmdid);
+
+ ret = xbee_send(xbee_dev,api_frame);
+
+ if(ret)
+ {
+ printk(KERN_ERR "%s: error sending API frame: %s: %d\n", __func__,cmdid,ret);
+ goto err;
+ }
+
+ if(!api_frame->response)
+ {
+ printk(KERN_ERR "%s: response is NULL\n", __func__);
+ ret = -EAGAIN;
+ goto err;
+ }
+
+ if(api_frame->response->api_data->at_cmd_resp.cmd_data_len != len)
+ {
+ printk(KERN_ERR "%s: invalid response value len\n", __func__);
+ ret = -EAGAIN;
+ goto err;
+ }
+
+ _api_frame_print(api_frame);
+ if(api_frame && api_frame->response)
+ _api_frame_print(api_frame->response);
+
+ for(i=0;i<api_frame->response->api_data->at_cmd_resp.cmd_data_len;i++)
+ {
+ value[i] = api_frame->response->api_data->at_cmd_resp.cmd_data[i];
+ }
+
+ pr_debug("%s(): xbee_send ret: %d\n", __func__,ret);
+
+err:
+ if(api_frame)
+ {
+ _api_frame_free(api_frame);
+ }
+
+ return 0;
+}
+
+static int
+xbee_api_at_command_read_u8(struct xbee_device *xbee_dev, const char cmdid[3], uint8_t value[1])
+{
+ return xbee_api_at_command_read_uN(xbee_dev,cmdid,value,1);
+}
+
+static int
+xbee_api_at_command_read_u16(struct xbee_device *xbee_dev, const char cmdid[3], uint8_t value[2])
+{
+ return xbee_api_at_command_read_uN(xbee_dev,cmdid,value,2);
+}
+
+static int
+xbee_api_at_command_read_u32(struct xbee_device *xbee_dev, const char cmdid[3], uint8_t value[4])
+{
+ return xbee_api_at_command_read_uN(xbee_dev,cmdid,value,4);
+}
+
+#ifndef __KERNEL__
+static void
+dump_hex(uint8_t *buf, int len);
+#endif
+
+//static int
+//xbee_ieee_address(struct xbee_device *xbee_dev, uint8_t addr[IEEE802154_ADDR_LEN])
+////xbee_ieee_address(struct ieee802154_dev *dev, uint8_t addr[IEEE802154_ADDR_LEN])
+//{
+// //struct xbee_device *xbee_dev = NULL;
+//
+//// uint8_t serial_number_high[4] = {};
+//// uint8_t serial_number_low[4] = {};
+//
+// int ret = 0;
+// pr_debug("%s\n", __func__);
+//
+// //xbee_dev = dev->priv;
+// if (NULL == xbee_dev) {
+// printk(KERN_ERR "%s: wrong phy\n", __func__);
+// return -EINVAL;
+// }
+//
+// //ret = xbee_api_at_command_read_u32(xbee_dev,"SH",serial_number_high);
+// ret = xbee_api_at_command_read_u32(xbee_dev,"SH",addr);
+// if(ret)
+// {
+// printk(KERN_ERR "%s: error getting serial high value\n", __func__);
+// return ret;
+// }
+// //dump_hex(serial_number_high, 4); printf("\n");
+//
+// //ret = xbee_api_at_command_read_u32(xbee_dev,"SL",serial_number_low);
+// ret = xbee_api_at_command_read_u32(xbee_dev,"SL",addr+4);
+// if(ret)
+// {
+// printk(KERN_ERR "%s: error getting serial low value\n", __func__);
+// return ret;
+// }
+// //dump_hex(serial_number_low, 4); printf("\n");
+//
+//#ifndef __KERNEL__
+// dump_hex(addr, 8); printf("\n");
+//#endif
+// pr_debug("%s end\n", __func__);
+// return ret;
+//}
+
+static uint8_t
+xbee_get_rssi(struct ieee802154_dev *dev)
+{
+ struct xbee_device *xbee_dev = NULL;
+ uint8_t result = 0x00;
+ int ret = 0;
+ pr_debug("%s\n", __func__);
+
+ xbee_dev = dev->priv;
+ if (NULL == xbee_dev) {
+ printk(KERN_ERR "%s: wrong phy\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = xbee_api_at_command_read_u8(xbee_dev,"DB",&result);
+ if(ret)
+ {
+ printk(KERN_ERR "%s: error getting RSSI value\n", __func__);
+ return ret;
+ }
+
+ global_lqi = result;
+
+#ifndef __KERNEL__
+ dump_hex(addr, 8); printf("\n");
+#endif
+ pr_debug("%s end\n", __func__);
+ return result;
+}
+
+//static uint16_t
+//xbee_get_pan_id(struct ieee802154_dev *dev)
+//{
+// struct xbee_device *xbee_dev = NULL;
+// uint8_t at_cmd_result[4] = {0,0,0,0};
+// uint16_t result = 0x0000;
+// int ret = 0;
+// pr_debug("%s\n", __func__);
+//
+// xbee_dev = dev->priv;
+// if (NULL == xbee_dev) {
+// printk(KERN_ERR "%s: wrong phy\n", __func__);
+// return -EINVAL;
+// }
+//
+// ret = xbee_api_at_command_read_u16(xbee_dev,"ID",&at_cmd_result);
+// if(ret)
+// {
+// printk(KERN_ERR "%s: error getting network id value\n", __func__);
+// return ret;
+// }
+//#ifndef __KERNEL__
+// dump_hex(addr, 8); printf("\n");
+//#endif
+// result = ((at_cmd_result[0] << 8) & 0xFF00) + (at_cmd_result[1] & 0xFF);
+//
+// pr_debug("%s end\n", __func__);
+// return result;
+//}
+
+static uint8_t
+xbee_get_dsn(struct ieee802154_dev *dev)
+{
+ struct xbee_device *xbee_dev = NULL;
+ uint8_t dsn = 0x00;
+ pr_debug("%s\n", __func__);
+
+ xbee_dev = dev->priv;
+ if (NULL == xbee_dev) {
+ printk(KERN_ERR "%s: wrong phy\n", __func__);
+ return -EINVAL;
+ }
+
+#ifdef __KERNEL__
+ mutex_lock(&xbee_dev->mutex);
+#else
+ pthread_mutex_lock(&xbee_dev->mutex);
+#endif
+ dsn = xbee_dev->frame_id_counter;
+#ifdef __KERNEL__
+ mutex_unlock(&xbee_dev->mutex);
+#else
+ pthread_mutex_unlock(&xbee_dev->mutex);
+#endif
+
+ pr_debug("%s end\n", __func__);
+ return dsn;
+}
+
+#ifdef __KERNEL__
+
+/*
+ * MAC802154 parsing functions
+ */
+
+static inline int mac802154_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 1)))
+ return -EINVAL;
+
+ *val = skb->data[0];
+ skb_pull(skb, 1);
+
+ return 0;
+}
+
+static inline int mac802154_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+{
+ if (unlikely(!pskb_may_pull(skb, 2)))
+ return -EINVAL;
+
+ *val = skb->data[0] | (skb->data[1] << 8);
+ skb_pull(skb, 2);
+
+ return 0;
+}
+
+static inline void mac802154_haddr_copy_swap(u8 *dest, const u8 *src)
+{
+ int i;
+ for (i = 0; i < IEEE802154_ADDR_LEN; i++)
+ dest[IEEE802154_ADDR_LEN - i - 1] = src[i];
+}
+
+static int mac802154_parse_frame_start(struct sk_buff *skb)
+{
+ u8 *head = skb->data;
+ u16 fc;
+
+ if (mac802154_fetch_skb_u16(skb, &fc) ||
+ mac802154_fetch_skb_u8(skb, &(mac_cb(skb)->seq)))
+ goto err;
+
+ pr_debug("fc: %04x dsn: %02x\n", fc, head[2]);
+
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc);
+ mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc);
+ mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc);
+
+ if (fc & IEEE802154_FC_INTRA_PAN)
+ mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN;
+
+ if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) {
+ if (mac802154_fetch_skb_u16(skb, &(mac_cb(skb)->da.pan_id)))
+ goto err;
+
+ /* source PAN id compression */
+ if (mac_cb_is_intrapan(skb))
+ mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id;
+
+ pr_debug("dest PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
+
+ if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) {
+ u16 *da = &(mac_cb(skb)->da.short_addr);
+
+ if (mac802154_fetch_skb_u16(skb, da))
+ goto err;
+
+ pr_debug("destination address is short: %04x\n",
+ mac_cb(skb)->da.short_addr);
+ } else {
+ if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
+ goto err;
+
+ mac802154_haddr_copy_swap(mac_cb(skb)->da.hwaddr,
+ skb->data);
+ skb_pull(skb, IEEE802154_ADDR_LEN);
+
+ pr_debug("destination address is hardware\n");
+ }
+ }
+
+ if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) {
+ /* non PAN-compression, fetch source address id */
+ if (!(mac_cb_is_intrapan(skb))) {
+ u16 *sa_pan = &(mac_cb(skb)->sa.pan_id);
+
+ if (mac802154_fetch_skb_u16(skb, sa_pan))
+ goto err;
+ }
+
+ pr_debug("source PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
+
+ if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) {
+ u16 *sa = &(mac_cb(skb)->sa.short_addr);
+
+ if (mac802154_fetch_skb_u16(skb, sa))
+ goto err;
+
+ pr_debug("source address is short: %04x\n",
+ mac_cb(skb)->sa.short_addr);
+ } else {
+ if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
+ goto err;
+
+ mac802154_haddr_copy_swap(mac_cb(skb)->sa.hwaddr,
+ skb->data);
+ skb_pull(skb, IEEE802154_ADDR_LEN);
+
+ pr_debug("source address is hardware\n");
+ }
+ }
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+/*
+ * to bind XBEE RX API frame to a ieee802154_addr
+ * addr_type = IEEE802154_ADDR_LONG (EUI-64 + PanId)
+ * pan_id = network ID (cmd ATID result should be used)
+ * hwaddr = RX EUI-64bit addr from API
+struct ieee802154_addr {
+ int addr_type;
+ u16 pan_id;
+ union {
+ u8 hwaddr[IEEE802154_ADDR_LEN];
+ u16 short_addr;
+ };
+};
+ *
+ */
+
+static int mac802154_header_create(struct sk_buff *skb,
+ struct ieee802154_dev *dev,
+ unsigned short type,
+ const void *_daddr,
+ const void *_saddr,
+ unsigned len)
+{
+ const struct ieee802154_addr *saddr = _saddr;
+ const struct ieee802154_addr *daddr = _daddr;
+ struct ieee802154_addr dev_addr;
+ struct xbee_device *xbee_dev = dev->priv;
+ int pos = 2;
+ u8 head[MAC802154_FRAME_HARD_HEADER_LEN];
+ u16 fc;
+
+ if (!daddr)
+ return -EINVAL;
+
+ //head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */ /* we should use FrameID here!!!! */
+ //head[pos++] = xbee_get_dsn(dev);
+ head[pos++] = 0;
+ fc = mac_cb_type(skb);
+
+ if (!saddr) {
+ //spin_lock_bh(&zbdev->mib_lock);
+
+// if (zbdev->short_addr == IEEE802154_ADDR_BROADCAST ||
+// zbdev->short_addr == IEEE802154_ADDR_UNDEF ||
+// zbdev->pan_id == IEEE802154_PANID_BROADCAST) {
+ dev_addr.addr_type = IEEE802154_ADDR_LONG;
+//
+ // replace here with EUI64 of the hw
+ memcpy(dev_addr.hwaddr, xbee_dev->dev_addr, IEEE802154_ADDR_LEN);
+// } else {
+// dev_addr.addr_type = IEEE802154_ADDR_SHORT;
+// dev_addr.short_addr = zbdev->short_addr;
+// }
+
+ dev_addr.pan_id = xbee_dev->pan_id; // network addr ATID?
+ saddr = &dev_addr;
+
+ //spin_unlock_bh(&zbdev->mib_lock);
+ }
+
+ if (daddr->addr_type != IEEE802154_ADDR_NONE) {
+ fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
+
+ head[pos++] = daddr->pan_id & 0xff;
+ head[pos++] = daddr->pan_id >> 8;
+
+ if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
+ head[pos++] = daddr->short_addr & 0xff;
+ head[pos++] = daddr->short_addr >> 8;
+ } else {
+ mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
+ pos += IEEE802154_ADDR_LEN;
+ }
+ }
+
+ if (saddr->addr_type != IEEE802154_ADDR_NONE) {
+ fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
+
+ if ((saddr->pan_id == daddr->pan_id) &&
+ (saddr->pan_id != IEEE802154_PANID_BROADCAST)) {
+ /* PANID compression/intra PAN */
+ fc |= IEEE802154_FC_INTRA_PAN;
+ } else {
+ head[pos++] = saddr->pan_id & 0xff;
+ head[pos++] = saddr->pan_id >> 8;
+ }
+
+ if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
+ head[pos++] = saddr->short_addr & 0xff;
+ head[pos++] = saddr->short_addr >> 8;
+ } else {
+ mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
+ pos += IEEE802154_ADDR_LEN;
+ }
+ }
+
+ head[0] = fc;
+ head[1] = fc >> 8;
+
+ memcpy(skb_push(skb, pos), head, pos);
+
+ return pos;
+}
+
+//#define DEBUG 1
+static int enable_debug = 0;
+
+static int
+ieee802154_hm_trp_xmit(struct ieee802154_dev *dev, struct sk_buff *skb){
+ struct xbee_device *xbee_dev = NULL;
+ _api_frame_t *api_frame = NULL;
+
+ struct sk_buff *sskb = NULL;
+ int ret = 0;
+
+ xbee_dev = dev->priv;
+ if (NULL == xbee_dev) {
+ printk(KERN_ERR "%s: wrong phy\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s(): recv_state: %d\n", __func__, xbee_dev->recv_state);
+
+ pr_debug("%s(): BEFORE wait\n", __func__);
+ if (wait_event_interruptible_timeout(xbee_dev->wq,
+ xbee_dev->recv_state == RECV_STATE_WAIT_START_DELIM,
+ msecs_to_jiffies(1000)) > 0) {
+ pr_debug("%s(): AFTER wait\n", __func__);
+ } else {
+ ret = -ETIMEDOUT;
+ pr_debug("%s(): TIMEOUT\n", __func__);
+ goto out;
+ }
+
+ sskb = skb_clone(skb, GFP_ATOMIC);
+ if (sskb) {
+ api_frame = _api_frame_new_raw_packet(xbee_dev,sskb->data,sskb->len);
+
+ if(api_frame){
+ _api_frame_print(api_frame);
+
+ ret = xbee_send(xbee_dev,api_frame);
+ if(ret){
+ ret = -EAGAIN;
+ if(enable_debug){
+ print_hex_dump_bytes("ieee802154_serial_xmit(): before parse: ", DUMP_PREFIX_NONE,sskb->data, sskb->len);
+ }
+ }
+ pr_debug("%s: xbee_send ret: %d\n", __func__,ret);
+ _api_frame_free(api_frame);
+ } else {
+ ret = -ENOMEM;
+ printk(KERN_DEBUG "%s: xbee_send ret: %d\n", __func__,ret);
+ }
+ kfree_skb(sskb);
+ }
+out:
+ pr_debug("%s end\n", __func__);
+ return ret;
+}
+
+static int
+ieee802154_xbee_xmit(struct ieee802154_dev *dev, struct sk_buff *skb){
+ u8 broadcast_check = 0x00;
+ u8 xbee_broadcast_addr[XBEE_ADDR_LEN] = {0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF};
+ struct xbee_device *xbee_dev = NULL;
+ _api_frame_t *api_frame = NULL;
+
+ struct sk_buff *sskb = NULL;
+ int ret = 0;
+
+ xbee_dev = dev->priv;
+ if (NULL == xbee_dev) {
+ printk(KERN_ERR "%s: wrong phy\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s(): recv_state: %d\n", __func__, xbee_dev->recv_state);
+
+ pr_debug("%s(): BEFORE wait\n", __func__);
+ if (wait_event_interruptible_timeout(xbee_dev->wq,
+ xbee_dev->recv_state == RECV_STATE_WAIT_START_DELIM,
+ msecs_to_jiffies(1000)) > 0) {
+ pr_debug("%s(): AFTER wait\n", __func__);
+ } else {
+ ret = -ETIMEDOUT;
+ pr_debug("%s(): TIMEOUT\n", __func__);
+ goto out;
+ }
+