Skip to content

Commit

Permalink
Merge pull request #14 from bradjc/auto_reg
Browse files Browse the repository at this point in the history
Character Device Now Automatically Creates Device File
  • Loading branch information
anroOfCode committed Mar 18, 2013
2 parents a70d3ee + 5cf8eb4 commit ea79252
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 47 deletions.
30 changes: 3 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,35 +155,11 @@ gcc read.c -o read

**To Load the Module**

I've included two utilities to make things a little easier.
These utilities do really really basic stuff:
Simply run

* <code>setup.sh</code> - Installs a character driver interface and sets proper
permissions for use.
* <code>reload.sh</code> - Removes the module from the system if loaded, and reloads
it.
sudo ./reload.sh

**NOTE:** The setup.sh script assumes the character driver major number to be 251,
but that might be different on your system. After running <code>reload.sh</code>
check <code>/var/log/kern.log</code> for the following lines to determine what
major number your driver has been assigned:

```
Jan 11 00:29:11 raspberrypi kernel: [ 6291.240366] loading CC2520 Kernel Module v0.01...
Jan 11 00:29:11 raspberrypi kernel: [ 6291.240491] [cc2520] - Driver [spidev] already registered for spi0.0. Nuking from orbit.
Jan 11 00:29:11 raspberrypi kernel: [ 6291.243147] spi spi0.0: setup: cd 0: 500000 Hz, bpw 8, mode 0x0 -> CS=00000000 CDIV=0200
Jan 11 00:29:11 raspberrypi kernel: [ 6291.243178] spi spi0.0: setup mode 0, 8 bits/w, 500000 Hz max --> 0
Jan 11 00:29:11 raspberrypi kernel: [ 6291.243306] bcm2708_spi bcm2708_spi.0: registered child spi0.0
Jan 11 00:29:11 raspberrypi kernel: [ 6291.243359] [cc2520] - Inserting SPI protocol driver.
Jan 11 00:29:11 raspberrypi kernel: [ 6291.243549] [cc2520] - Char interface registered on 251
```

So to get things up and running just go ahead and run them both:

```
sudo ./reload.sh
sudo ./setup.sh
```
in the same directory as cc2520.ko.

**To Test the Driver**

Expand Down
76 changes: 59 additions & 17 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/device.h>

#include "ioctl.h"
#include "cc2520.h"
Expand All @@ -19,19 +21,24 @@
struct cc2520_interface *interface_bottom;

static unsigned int major;
static dev_t char_d_mm;
static struct cdev char_d_cdev;
static struct class* cl;
static struct device* de;

static u8 *tx_buf_c;
static u8 *rx_buf_c;
static size_t tx_pkt_len;
static size_t rx_pkt_len;

// Allows for only a single rx or tx
// to occur simultaneously.
// 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.
// or rx has completed.
static struct semaphore tx_done_sem;
static struct semaphore rx_done_sem;

Expand Down Expand Up @@ -116,7 +123,7 @@ static ssize_t interface_write(
else {
result = down_interruptible(&tx_sem);
if (result)
return -ERESTARTSYS;
return -ERESTARTSYS;
}
DBG((KERN_INFO "[cc2520] - write lock obtained.\n"));

Expand All @@ -134,12 +141,12 @@ static ssize_t interface_write(

// Step 3: Launch off into sending this packet,
// wait for an asynchronous callback to occur in
// the form of a semaphore.
// the form of a semaphore.
interface_bottom->tx(tx_buf_c, pkt_len);
down(&tx_done_sem);

// Step 4: Finally return and allow other callers to write
// packets.
// packets.
DBG((KERN_INFO "[cc2520] - wrote %d bytes.\n", pkt_len));
up(&tx_sem);
return tx_result ? tx_result : pkt_len;
Expand Down Expand Up @@ -237,7 +244,7 @@ static void interface_ioctl_set_channel(struct cc2520_set_channel_data *data)
{
int result;
struct cc2520_set_channel_data ldata;

result = copy_from_user(&ldata, data, sizeof(struct cc2520_set_channel_data));

if (result) {
Expand Down Expand Up @@ -306,11 +313,11 @@ static void interface_ioctl_set_lpl(struct cc2520_set_lpl_data *data)
return;
}

INFO((KERN_INFO "[cc2520] - setting lpl enabled: %d, window: %d, interval: %d\n",
INFO((KERN_INFO "[cc2520] - setting lpl enabled: %d, window: %d, interval: %d\n",
ldata.enabled, ldata.window, ldata.interval));
cc2520_lpl_set_enabled(ldata.enabled);
cc2520_lpl_set_listen_length(ldata.window);
cc2520_lpl_set_wakeup_interval(ldata.interval);
cc2520_lpl_set_wakeup_interval(ldata.interval);
}

static void interface_ioctl_set_csma(struct cc2520_set_csma_data *data)
Expand All @@ -333,12 +340,12 @@ static void interface_ioctl_set_csma(struct cc2520_set_csma_data *data)
}

/////////////////
// init/free
// init/free
///////////////////

int cc2520_interface_init()
{
int result;
int result;

interface_bottom->tx_done = cc2520_interface_tx_done;
interface_bottom->rx_done = cc2520_interface_rx_done;
Expand All @@ -354,22 +361,51 @@ int cc2520_interface_init()
result = -EFAULT;
goto error;
}
rx_buf_c = kmalloc(PKT_BUFF_SIZE, GFP_KERNEL);

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

major = register_chrdev(0, cc2520_name, &fops);
// Allocate a major number for this device
result = alloc_chrdev_region(&char_d_mm, 0, 1, cc2520_name);
if (result < 0) {
printk(KERN_INFO "[cc2520] - Could not allocate a major number\n");
goto error;
}
major = MAJOR(char_d_mm);

// Register the character device
cdev_init(&char_d_cdev, &fops);
char_d_cdev.owner = THIS_MODULE;
result = cdev_add(&char_d_cdev, char_d_mm, 1);
if (result < 0) {
printk(KERN_INFO "[cc2520] - Unable to register char dev\n");
goto error;
}
printk(KERN_INFO "[cc2520] - Char interface registered on %d\n", major);

cl = class_create(THIS_MODULE, "cc2520");
if (cl == NULL) {
printk(KERN_INFO "[cc2520] - Could not create device class\n");
goto error;
}

// Create the device in /dev/radio
de = device_create(cl, NULL, char_d_mm, NULL, "radio");
if (de == NULL) {
printk(KERN_INFO "[cc2520] - Could not create device\n");
goto error;
}

return 0;

error:

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

if (tx_buf_c) {
Expand All @@ -394,11 +430,17 @@ void cc2520_interface_free()
printk("[cc2520] - critical error occurred on free.");
}

unregister_chrdev(major, cc2520_name);
cdev_del(&char_d_cdev);
unregister_chrdev(char_d_mm, cc2520_name);
device_destroy(cl, char_d_mm);
class_destroy(cl);


printk(KERN_INFO "[cc2520] - Removed character device\n");

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

if (tx_buf_c) {
Expand Down
3 changes: 0 additions & 3 deletions setup.sh

This file was deleted.

0 comments on commit ea79252

Please sign in to comment.