#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <mach/regs-gpio.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <linux/uaccess.h>
#define LIGHT_LEDS_MAJOR 0
#define DEVICE_NAME "TLYYY-LEDS"
#define LIGHT_LEDS_ON 1
#define LIGHT_LEDS_OFF 0
MODULE_AUTHOR("SONG SIR");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("FLASH LEDS Driver");
static unsigned long light_leds_table[] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int light_leds_cfg_table[] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static void light_leds_on(unsigned long arg)
{
s3c2410_gpio_setpin(light_leds_table[arg],0);
}
static void light_leds_off(unsigned long arg)
{
s3c2410_gpio_setpin(light_leds_table[arg],1);
}
//device struct
struct light_leds_dev
{
struct cdev cdev;
unsigned char value;
};
struct light_leds_dev *light_leds_devp;
int light_leds_major = LIGHT_LEDS_MAJOR;
//open func
int light_leds_open(struct inode *inode, struct file *filp)
{
struct light_leds_dev *dev;
dev = container_of(inode->i_cdev, struct light_leds_dev, cdev);
filp->private_data = dev;
return 0;
}
int light_leds_release(struct inode * inode,struct file * filp)
{
return 0;
}
ssize_t light_leds_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct light_leds_dev *dev = filp->private_data;
if(copy_to_user(buf, &(dev->value), 1))//succeed return 0
return -EFAULT;
return 1;
}
ssize_t light_leds_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
struct light_leds_dev *dev = filp->private_data;
if(copy_from_user(&(dev->value), buf, 1))
{
return -EFAULT;
}
if(dev->value == 1)
// s3c2410_gpio_setpin(light_leds_table[*f_pos],0);
light_leds_on(*f_pos);
else
// s3c2410_gpio_setpin(light_leds_table[*f_pos],1);
light_leds_off(*f_pos);
return 1;
}
int light_leds_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
struct light_leds_dev *dev = filp->private_data;
switch(cmd)
{
case LIGHT_LEDS_ON:
dev->value = 1;
// s3c2410_gpio_setpin(light_leds_table[arg],0);
light_leds_on(arg);
printk(KERN_ALERT"leds_on arg is %ld\n",arg);
break;
case LIGHT_LEDS_OFF:
dev->value = 0;
// s3c2410_gpio_setpin(light_leds_table[arg],1);
light_leds_off(arg);
printk(KERN_ALERT"leds_off arg is %ld\n",arg);
break;
default:
return - ENOTTY;
}
return 0;
}
struct file_operations light_leds_fops =
{
.owner = THIS_MODULE,
.read = light_leds_read,
.write = light_leds_write,
.ioctl = light_leds_ioctl,
.open = light_leds_open,
.release= light_leds_release,
};
static struct class *light_leds_class;
static void light_leds_setup_cdev(struct light_leds_dev *dev, int index)
{
int err, devno = MKDEV(light_leds_major, index);
cdev_init(&dev->cdev, &light_leds_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &light_leds_fops;
err = cdev_add(&dev->cdev, devno , 1);
if(err)
printk(KERN_NOTICE"Error %d adding LED %d\n", err, index);
}
static int __init light_leds_init(void)
{
int result;
dev_t dev = MKDEV(light_leds_major, 0);
printk(KERN_ALERT"get dev is %d \n", dev);
if(light_leds_major)
result = register_chrdev(dev, DEVICE_NAME, &light_leds_fops);
else
{
result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
light_leds_major = MAJOR(dev);
}
if(result < 0)
{
printk(KERN_ALERT"unable to get a major %d\n", light_leds_major);
return result;
}
printk(KERN_ALERT"get major is %d\n", light_leds_major);
light_leds_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(light_leds_class, NULL, MKDEV(light_leds_major,0), NULL, DEVICE_NAME);
if(!light_leds_major)
light_leds_major = result;
light_leds_devp = kmalloc(sizeof(struct light_leds_dev),GFP_KERNEL);
if(light_leds_devp == NULL)
{
result = - ENOMEM;
printk(KERN_ALERT"kmalloc failed!\n");
goto fail_malloc;
}
memset(light_leds_devp , 0, sizeof(struct light_leds_dev));
light_leds_setup_cdev(light_leds_devp, 0);
printk(KERN_ALERT"install module successfully!\n");
return 0;
fail_malloc:
unregister_chrdev_region(dev, 1);
printk(KERN_ALERT"install module unsuccessfully!");
return result;
}
static void __exit light_leds_cleanup(void)
{
cdev_del(&light_leds_devp->cdev);
kfree(light_leds_devp);
unregister_chrdev_region(MKDEV(light_leds_major, 0), 1);
device_destroy(light_leds_class, MKDEV(light_leds_major, 0));
class_destroy(light_leds_class);
printk(KERN_ALERT"\nuninstall module successfully!\n");
}
module_init(light_leds_init);
module_exit(light_leds_cleanup);
简单的应用程序:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/ioctl.h>
5
6 int main(int argc, char* argv[])
7 {
8 int on;
9 int led_on;
10 int fd;
11
12 if(argc != 3 || sscanf(argv[1], "%d", &led_on) != 1 || sscanf(argv[2], "%d", &on) != 1 || on < 0 || on > 1 || led_on < 1 || led_on > 4)
13 {
14 fprintf(stderr,"Usage: leds len_on 0|1\n");
15 exit(1);
16 }
17 fd = open ("/dev/TLYYY-LEDS", 0);
18 if(fd < 0)
19 {
20 perror("open device leds");
21 fprintf(stdout,"fd = %d, on = %d, led_on = %d, argc = %d\n",fd, on, led_on, argc);
22 exit(1);
23 }
24
25 ioctl(fd, on, (led_on-1));
26 fprintf(stdout,"fd = %d, on = %d, led_on = %d, argc = %d\n",fd, on, led_on, argc);
27 close(fd);
28 return 0;
29
30 }