Skip to content

Commit 75c6d1e

Browse files
committed
Basic ioctl added, patch to gpio code
1 parent 9f8ea3b commit 75c6d1e

File tree

5 files changed

+248
-33
lines changed

5 files changed

+248
-33
lines changed

drivers/staging/media/ledcube/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33

44
obj-$(CONFIG_PILED_STAGING) += piled.o
55
obj-$(CONFIG_PILED_STAGING) += piled_gpio.o
6+
obj-$(CONFIG_PILED_STAGING) += piled_ioctl.o

drivers/staging/media/ledcube/piled.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
#include <linux/gpio.h>
3636
#include <linux/slab.h>
3737

38+
#include <linux/fs.h>
39+
#include <linux/cdev.h>
40+
#include <linux/device.h>
41+
3842
#include "piled.h"
3943

4044
// Driver var
@@ -63,11 +67,14 @@ static int __init piled_init( void)
6367
// Init filesystem (TODO)
6468

6569
// Init hr_timer
66-
piled->ktime = ktime_set( 0, MS_TO_NS( DELAY_IN_MS) );
70+
piled->ktime = ktime_set( 0, US_TO_NS( DELAY_STANDARD) );
6771
hrtimer_init( &piled->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
6872
piled->hr_timer.function = &piled_gpio_update;
6973
hrtimer_start( &piled->hr_timer, piled->ktime, HRTIMER_MODE_REL);
7074

75+
// Init lock
76+
spin_lock_init( &piled->ledBufferLock);
77+
7178
//
7279
print_deb( "piled_init says Hi!");
7380
return 0;
@@ -130,3 +137,4 @@ module_exit( piled_exit_module);
130137
MODULE_DESCRIPTION("A LedCube driver for the Raspberry Pi");
131138
MODULE_AUTHOR("Riemer van der Zee <riemervdzee@gmail.com>");
132139
MODULE_LICENSE("GPL");
140+

drivers/staging/media/ledcube/piled.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,53 @@
6464
#define PILED_GPIO_LAYER_POWER 23 // Pin 16
6565

6666
// Delay defines
67-
#define DELAY_IN_MS 1000
68-
#define MS_TO_NS( t) ( t * 1E6L)
67+
#define DELAY_STANDARD 1000 * 1000
68+
#define DELAY_SELECT_NS 5
69+
#define DELAY_DATABUS_NS 5
70+
71+
#define US_TO_NS( t) ( t * 1000)
72+
73+
// IO ctl
74+
#define PILED_GET_POWER _IOR('p', 1, int)
75+
#define PILED_SET_POWER _IOW('p', 2, int)
76+
#define PILED_GET_DELAY _IOR('p', 3, int)
77+
#define PILED_SET_DELAY _IOW('p', 4, int)
78+
#define PILED_GET_DEBUG _IOR('p', 5, int)
79+
#define PILED_SET_DEBUG _IOW('p', 6, int)
6980

7081

7182
/**
7283
*Driver struct (under construction)
7384
*/
7485
struct piled_driver
7586
{
87+
// Contains the ledState, and the upcoming ledState (we got doublebuffering)
88+
char ledBuffer[64];
89+
char ledBuffer_next[64];
90+
7691
// HR timer struct
7792
struct hrtimer hr_timer;
7893

79-
// Reference to our RPi gpiochip
80-
struct gpio_chip *gpiochip;
94+
// There is a chance we are already writing to the buffer, so we need a lock
95+
// Use a spinlock instead of mutex, as they are allowed in soft-irqs
96+
spinlock_t ledBufferLock;
8197

8298
// Interval time for the hrtimer
8399
ktime_t ktime;
84100

101+
// Reference to our RPi gpiochip
102+
struct gpio_chip *gpiochip;
85103

104+
// Character driver vars
105+
dev_t dev;
106+
struct cdev c_dev;
107+
struct class *cl;
108+
109+
// Maybe we can change dirty to an atomic_int, to get rid of the lock
110+
int dirty;
111+
int power;
112+
int layer;
113+
int debug;
86114
};
87115

88116
// Driver var
@@ -92,3 +120,7 @@ extern struct piled_driver *piled;
92120
enum hrtimer_restart piled_gpio_update( struct hrtimer *timer);
93121
int piled_gpio_init( void);
94122
void piled_gpio_free( void);
123+
long piled_ioctl( struct file *f, unsigned int cmd, unsigned long arg);
124+
int __init piled_ioctl_init( void);
125+
void __exit piled_ioctl_exit( void);
126+

drivers/staging/media/ledcube/piled_gpio.c

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,43 +32,75 @@
3232
#include <linux/spinlock.h>
3333
#include <linux/gpio.h>
3434

35-
#include "piled.h"
35+
#include <linux/fs.h>
36+
#include <linux/cdev.h>
37+
#include <linux/device.h>
3638

37-
static int value = 0;
39+
#include "piled.h"
3840

3941
/**
4042
* Updater function
4143
*/
4244
enum hrtimer_restart piled_gpio_update( struct hrtimer *timer)
4345
{
4446
// Print something
45-
//print_deb( "Update function called\n");
46-
47-
//
48-
gpio_set_value( PILED_GPIO_DATA_1, value);
49-
gpio_set_value( PILED_GPIO_DATA_2, value);
50-
gpio_set_value( PILED_GPIO_DATA_3, value);
51-
gpio_set_value( PILED_GPIO_DATA_4, value);
52-
gpio_set_value( PILED_GPIO_DATA_5, value);
53-
gpio_set_value( PILED_GPIO_DATA_6, value);
54-
gpio_set_value( PILED_GPIO_DATA_7, value);
55-
gpio_set_value( PILED_GPIO_DATA_8, value);
56-
57-
gpio_set_value( PILED_GPIO_CHIP_1, value);
58-
gpio_set_value( PILED_GPIO_CHIP_2, value);
59-
gpio_set_value( PILED_GPIO_CHIP_3, value);
60-
gpio_set_value( PILED_GPIO_CHIP_POWER, value);
61-
62-
gpio_set_value( PILED_GPIO_LAYER_1, value);
63-
gpio_set_value( PILED_GPIO_LAYER_2, value);
64-
gpio_set_value( PILED_GPIO_LAYER_3, value);
65-
gpio_set_value( PILED_GPIO_LAYER_POWER, value);
66-
67-
if(value == 0)
68-
value = 1;
69-
else
70-
value = 0;
47+
int i;
48+
char* buf = &(piled->ledBuffer[ piled->layer * 8]);
49+
50+
// Disable and set the value of the layer
51+
gpio_set_value( PILED_GPIO_LAYER_POWER, 0);
52+
53+
// Select the next layer
54+
gpio_set_value( PILED_GPIO_LAYER_1, piled->layer & 1);
55+
gpio_set_value( PILED_GPIO_LAYER_2, piled->layer & 2);
56+
gpio_set_value( PILED_GPIO_LAYER_3, piled->layer & 4);
57+
58+
// Set the values of the 74hc547 chips
59+
for ( i = 0; i < 8; i++, buf++)
60+
{
61+
// Disable the chip-select
62+
gpio_set_value( PILED_GPIO_CHIP_POWER, 0);
63+
64+
// Select the next chip
65+
gpio_set_value( PILED_GPIO_CHIP_1, i & 1);
66+
gpio_set_value( PILED_GPIO_CHIP_2, i & 2);
67+
gpio_set_value( PILED_GPIO_CHIP_3, i & 4);
68+
69+
// Set the databus
70+
gpio_set_value( PILED_GPIO_DATA_1, /*buf & 1*/1);
71+
gpio_set_value( PILED_GPIO_DATA_2, /*buf & 2*/1);
72+
gpio_set_value( PILED_GPIO_DATA_3, /*buf & 4*/1);
73+
gpio_set_value( PILED_GPIO_DATA_4, /*buf & 8*/1);
74+
gpio_set_value( PILED_GPIO_DATA_5, /*buf & 16*/1);
75+
gpio_set_value( PILED_GPIO_DATA_6, /*buf & 32*/1);
76+
gpio_set_value( PILED_GPIO_DATA_7, /*buf & 64*/1);
77+
gpio_set_value( PILED_GPIO_DATA_8, /*buf & 128*/1);
78+
79+
// Wait till the chip is selected, enable the chip-select chip, wait till the databus is copied to the 74hc547
80+
ndelay( DELAY_SELECT_NS); // Most likely can be removed
81+
gpio_set_value( PILED_GPIO_CHIP_POWER, 1);
82+
ndelay( DELAY_DATABUS_NS);
83+
}
84+
85+
// Enable the layer
86+
gpio_set_value( PILED_GPIO_LAYER_POWER, 1);
7187

88+
// Increase layer (AND to 7, so we don't exceed the amount layers 8)
89+
piled->layer = (piled->layer + 1) & 7;
90+
91+
// try to lock the ledBuffer
92+
if( spin_trylock( &piled->ledBufferLock) )
93+
{
94+
// Should we copy?
95+
if( piled->dirty == 1)
96+
{
97+
memcpy( &piled->ledBuffer, &piled->ledBuffer_next, 64);
98+
piled->dirty = 0;
99+
}
100+
101+
// Always unlock
102+
spin_unlock( &piled->ledBufferLock);
103+
}
72104

73105
// Always restart the timer
74106
hrtimer_forward_now( timer, piled->ktime);
@@ -313,3 +345,4 @@ void piled_gpio_free( void)
313345
gpio_free( PILED_GPIO_LAYER_3);
314346
gpio_free( PILED_GPIO_LAYER_POWER);
315347
}
348+
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* piled_ioctl.c
3+
*
4+
* piled - Explanation is coming up
5+
*
6+
* Copyright (C) 2012-2013 Riemer van der Zee <riemervdzee@gmail.com>,
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation; either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program; if not, write to the Free Software
20+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21+
*/
22+
23+
#include <linux/errno.h>
24+
#include <linux/sched.h>
25+
#include <linux/kernel.h>
26+
#include <linux/time.h>
27+
#include <linux/hrtimer.h>
28+
#include <linux/ktime.h>
29+
#include <linux/delay.h>
30+
#include <linux/platform_device.h>
31+
#include <linux/irq.h>
32+
#include <linux/spinlock.h>
33+
#include <linux/gpio.h>
34+
35+
#include <linux/module.h>
36+
#include <linux/kernel.h>
37+
#include <linux/version.h>
38+
#include <linux/fs.h>
39+
#include <linux/cdev.h>
40+
#include <linux/device.h>
41+
#include <linux/errno.h>
42+
#include <asm/uaccess.h>
43+
44+
#include "piled.h"
45+
46+
#define FIRST_MINOR 0
47+
#define MINOR_CNT 1
48+
49+
static int piled_open( struct inode *i, struct file *f)
50+
{
51+
return 0;
52+
}
53+
static int piled_close( struct inode *i, struct file *f)
54+
{
55+
return 0;
56+
}
57+
58+
long piled_ioctl( struct file *f, unsigned int cmd, unsigned long arg)
59+
{
60+
switch ( cmd)
61+
{
62+
case PILED_GET_POWER:
63+
return piled->power;
64+
case PILED_SET_POWER:
65+
piled->power = arg;
66+
break;
67+
68+
case PILED_SET_DELAY:
69+
piled->ktime = ktime_set( 0, US_TO_NS( arg) );
70+
break;
71+
72+
case PILED_GET_DEBUG:
73+
return piled->debug;
74+
case PILED_SET_DEBUG:
75+
piled->debug = arg;
76+
break;
77+
78+
default:
79+
return -EINVAL;
80+
}
81+
82+
return 0;
83+
}
84+
85+
static struct file_operations piled_fops =
86+
{
87+
.owner = THIS_MODULE,
88+
.open = piled_open,
89+
.release = piled_close,
90+
.unlocked_ioctl = piled_ioctl,
91+
};
92+
93+
94+
int __init piled_ioctl_init( void)
95+
{
96+
int ret;
97+
struct device *dev_ret;
98+
99+
ret = alloc_chrdev_region( &piled->dev, FIRST_MINOR, MINOR_CNT, PILED_DRIVER_NAME);
100+
if (ret < 0)
101+
{
102+
return ret;
103+
}
104+
105+
cdev_init( &piled->c_dev, &piled_fops);
106+
107+
ret = cdev_add( &piled->c_dev, piled->dev, MINOR_CNT);
108+
if (ret < 0)
109+
{
110+
return ret;
111+
}
112+
113+
114+
piled->cl = class_create( THIS_MODULE, "char");
115+
if ( IS_ERR( piled->cl))
116+
{
117+
cdev_del(&piled->c_dev);
118+
unregister_chrdev_region( piled->dev, MINOR_CNT);
119+
return PTR_ERR (piled->cl);
120+
}
121+
122+
dev_ret = device_create( piled->cl, NULL, piled->dev, NULL, PILED_DRIVER_NAME);
123+
if (IS_ERR( dev_ret))
124+
{
125+
class_destroy(piled->cl);
126+
cdev_del(&piled->c_dev);
127+
unregister_chrdev_region(piled->dev, MINOR_CNT);
128+
return PTR_ERR( dev_ret);
129+
}
130+
131+
return 0;
132+
}
133+
134+
void __exit piled_ioctl_exit( void)
135+
{
136+
device_destroy( piled->cl, piled->dev);
137+
class_destroy( piled->cl);
138+
cdev_del( &piled->c_dev);
139+
unregister_chrdev_region( piled->dev, MINOR_CNT);
140+
}
141+

0 commit comments

Comments
 (0)