Skip to content

Commit

Permalink
checkpoint on implementation of better layer implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
anroOfCode committed Dec 23, 2012
1 parent e3431c6 commit ed8c28d
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 118 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -3,7 +3,7 @@
DRIVER = spike

TARGET = cc2520
OBJS = radio.o interface.o module.o platform.o sack.o
OBJS = radio.o interface.o module.o platform.o sack.o lpl.o

obj-m += $(TARGET).o
cc2520-objs = radio.o interface.o module.o platform.o sack.o
Expand Down
70 changes: 12 additions & 58 deletions cc2520.h
Expand Up @@ -6,8 +6,6 @@
#include <linux/workqueue.h>
#include <linux/spinlock.h>

#include "radio.h"

//////////////////////////////
// Configuration for driver
/////////////////////////////
Expand Down Expand Up @@ -55,6 +53,7 @@
#define SPI_BUS_CS0 0
#define SPI_BUS_SPEED 500000
#define SPI_BUFF_SIZE 256
#define PKT_BUFF_SIZE 127

// Defaults for Radio Operation
#define CC2520_DEF_CHANNEL 26
Expand All @@ -64,84 +63,39 @@
#define CC2520_DEF_EXT_ADDR 0x01


// XOSC Period in nanoseconds.
#define CC2520_XOSC_PERIOD 31

//////////////////////////////
// Structs and definitions
/////////////////////////////

// XOSC Period in nanoseconds.
#define CC2520_XOSC_PERIOD 31
struct cc2520_interface {
int (*tx)(u8 *buf, u8 len);
void (*tx_done)(u8 status);
void (*rx_done)(u8 *buf, u8 len);
};

#define PKT_BUFF_SIZE 127
///
// KEEP THESE AROUND FOR LEGACY REASONS:
//

struct cc2520_gpio_state {
unsigned int fifop_irq;
unsigned int sfd_irq;
};

enum cc2520_radio_state_enum {
CC2520_RADIO_STATE_IDLE,
CC2520_RADIO_STATE_RX,
CC2520_RADIO_STATE_TX
};

struct cc2520_state {
// Hardware
struct cc2520_gpio_state gpios;

////////////////////////////////////
// Character device and buffers
////////////////////////////////////
unsigned int major;
u8 *tx_buf_c;
u8 *rx_buf_c;
size_t tx_pkt_len;

// Allows for only a single rx or tx
// to occur simultaneously.
struct semaphore tx_sem;
struct semaphore rx_sem;

// Used by the character driver
// to indicate when a blocking tx
// or rx has completed.
struct semaphore tx_done_sem;
struct semaphore rx_done_sem;

// Results, stored by the callbacks
int tx_result;
int rx_result;

////////////////////////////////////
// Spi device and buffers
//////////////////////////////////
struct spi_device *spi_device;

////////////////////////////////////
// Radio parameters
//////////////////////////////////

// CURRENTLY UNUSED:
struct work_struct work; /* for deferred work */
struct workqueue_struct *wq;
};

// Platform
int cc2520_plat_gpio_init(void);
void cc2520_plat_gpio_free(void);

int cc2520_plat_spi_init(void);
void cc2520_plat_spi_free(void);

// Interface
int cc2520_interface_init(void);
void cc2520_interface_free(void);
void cc2520_interface_write_cb(int result);

// Software ACK Layer
void cc2520_sack_tx(u8 *buf, u8 len);

extern struct cc2520_state state;

extern const char cc2520_name[];

//////////////////////////////
Expand Down
116 changes: 76 additions & 40 deletions interface.c
Expand Up @@ -6,8 +6,47 @@
#include <linux/types.h>
#include <linux/semaphore.h>
#include <linux/slab.h>

#include "ioctl.h"
#include "cc2520.h"
#include "interface.h"
#include "radio.h"

struct cc2520_interface *interface_bottom;

static unsigned int major;
static u8 *tx_buf_c;
static u8 *rx_buf_c;
static size_t tx_pkt_len;

// Allows for only a single rx or tx
// to occur simultaneously.
static struct semaphore tx_sem;
static struct semaphore rx_sem;

// Used by the character driver
// to indicate when a blocking tx
// or rx has completed.
static struct semaphore tx_done_sem;
static struct semaphore rx_done_sem;

// Results, stored by the callbacks
static int tx_result;
static int rx_result;

///////////////////////
// Interface callbacks
///////////////////////
void cc2520_interface_tx_done(u8 status)
{
tx_result = status;
up(&tx_done_sem);
}

void cc2520_interface_rx_done(u8 *buf, u8 len)
{

}

// Should accept a 6LowPAN frame, no longer than 127 bytes.
static ssize_t interface_write(
Expand All @@ -21,52 +60,46 @@ static ssize_t interface_write(
// Step 1: Get an exclusive lock on writing to the
// radio.
if (filp->f_flags & O_NONBLOCK) {
result = down_trylock(&state.tx_sem);
result = down_trylock(&tx_sem);
if (result)
return -EAGAIN;
}
else {
result = down_interruptible(&state.tx_sem);
result = down_interruptible(&tx_sem);
if (result)
return -ERESTARTSYS;
}
printk(KERN_INFO "[cc2520] - write lock obtained.\n");

// Step 2: Copy the packet to the incoming buffer.
pkt_len = min(len, (size_t)127);
if (copy_from_user(state.tx_buf_c, in_buf, pkt_len)) {
if (copy_from_user(tx_buf_c, in_buf, pkt_len)) {
result = -EFAULT;
goto error;
}
state.tx_pkt_len = pkt_len;
tx_pkt_len = pkt_len;

// Step 3: Launch off into sending this packet,
// wait for an asynchronous callback to occur in
// the form of a semaphore.
printk(KERN_INFO "[cc2520] - performing software ack test %d.\n", pkt_len);
cc2520_sack_tx(state.tx_buf_c, pkt_len);
result = down_interruptible(&state.tx_done_sem);
interface_bottom->tx(tx_buf_c, pkt_len);
result = down_interruptible(&tx_done_sem);
if (result)
return -ERESTARTSYS;

// Step 4: Finally return and allow other callers to write
// packets.
printk(KERN_INFO "[cc2520] - returned from sack cb.\n");
up(&state.tx_sem);
up(&tx_sem);

return state.tx_result ? state.tx_result : pkt_len;
return tx_result ? tx_result : pkt_len;

error:
up(&state.tx_sem);
up(&tx_sem);
return -EFAULT;
}

void cc2520_interface_write_cb(int result)
{
state.tx_result = result;
up(&state.tx_done_sem);
}

static ssize_t interface_read(struct file *filp, char __user *buff, size_t count,
loff_t *offp)
{
Expand Down Expand Up @@ -164,38 +197,41 @@ int cc2520_interface_init()
{
int result;

sema_init(&state.tx_sem, 1);
sema_init(&state.rx_sem, 1);
interface_bottom->tx_done = cc2520_interface_tx_done;
interface_bottom->rx_done = cc2520_interface_rx_done;

sema_init(&tx_sem, 1);
sema_init(&rx_sem, 1);

sema_init(&state.tx_done_sem, 0);
sema_init(&state.rx_done_sem, 0);
sema_init(&tx_done_sem, 0);
sema_init(&rx_done_sem, 0);

state.tx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);
if (!state.tx_buf_c) {
tx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);
if (!tx_buf_c) {
result = -EFAULT;
goto error;
}

state.rx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);
if (!state.rx_buf_c) {
rx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);
if (!rx_buf_c) {
result = -EFAULT;
goto error;
}

state.major = register_chrdev(0, cc2520_name, &fops);
printk(KERN_INFO "[cc2520] - Char interface registered on %d\n", state.major);
major = register_chrdev(0, cc2520_name, &fops);
printk(KERN_INFO "[cc2520] - Char interface registered on %d\n", major);
return 0;

error:

if (state.rx_buf_c) {
kfree(state.rx_buf_c);
state.rx_buf_c = 0;
if (rx_buf_c) {
kfree(rx_buf_c);
rx_buf_c = 0;
}

if (state.tx_buf_c) {
kfree(state.tx_buf_c);
state.tx_buf_c = 0;
if (tx_buf_c) {
kfree(tx_buf_c);
tx_buf_c = 0;
}

return result;
Expand All @@ -205,25 +241,25 @@ void cc2520_interface_free()
{
int result;

result = down_interruptible(&state.tx_sem);
result = down_interruptible(&tx_sem);
if (result) {
printk("[cc2520] - critical error occurred on free.");
}

result = down_interruptible(&state.rx_sem);
result = down_interruptible(&rx_sem);
if (result) {
printk("[cc2520] - critical error occurred on free.");
}

unregister_chrdev(state.major, cc2520_name);
unregister_chrdev(major, cc2520_name);

if (state.rx_buf_c) {
kfree(state.rx_buf_c);
state.rx_buf_c = 0;
if (rx_buf_c) {
kfree(rx_buf_c);
rx_buf_c = 0;
}

if (state.tx_buf_c) {
kfree(state.tx_buf_c);
state.tx_buf_c = 0;
if (tx_buf_c) {
kfree(tx_buf_c);
tx_buf_c = 0;
}
}
10 changes: 10 additions & 0 deletions interface.h
@@ -0,0 +1,10 @@
#ifndef INTERFACE_H
#define iNTERFACE_H

// Interface
int cc2520_interface_init(void);
void cc2520_interface_free(void);

extern struct cc2520_interface *interface_bottom;

#endif
39 changes: 39 additions & 0 deletions lpl.c
@@ -0,0 +1,39 @@
#include <linux/types.h>
#include "lpl.h"
#include "cc2520.h"

struct cc2520_interface *lpl_top;
struct cc2520_interface *lpl_bottom;

static int cc2520_lpl_tx(u8 * buf, u8 len);
static void cc2520_lpl_tx_done(u8 status);
static void cc2520_lpl_rx_done(u8 *buf, u8 len);

int cc2520_lpl_init()
{
lpl_top->tx = cc2520_lpl_tx;
lpl_bottom->tx_done = cc2520_lpl_tx_done;
lpl_bottom->rx_done = cc2520_lpl_rx_done;

return 0;
}

void cc2520_lpl_free()
{

}

static int cc2520_lpl_tx(u8 * buf, u8 len)
{
return lpl_bottom->tx(buf, len);
}

static void cc2520_lpl_tx_done(u8 status)
{
lpl_top->tx_done(status);
}

static void cc2520_lpl_rx_done(u8 *buf, u8 len)
{
lpl_top->rx_done(buf, len);
}
12 changes: 12 additions & 0 deletions lpl.h
@@ -0,0 +1,12 @@
#ifndef LPL_H
#define LPL_H

#include "cc2520.h"

extern struct cc2520_interface *lpl_top;
extern struct cc2520_interface *lpl_bottom;

int cc2520_lpl_init(void);
void cc2520_lpl_free(void);

#endif

0 comments on commit ed8c28d

Please sign in to comment.