#include <linux/string.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <mach/gpio.h> //包含管脚操作的相关函数
#include <linux/device.h> //包含创建设备文件的相关函数
#define DEVICE_NAME "SAM9261-LED_TEST"
static int LED_Major = 0;
struct cdev cdev;
/** 应用程序执行 ioctl(fd, cmd, arg)时的第 2 个参数 **/
#define LED_OFF 0
#define LED_ON 1
static unsigned long led_table [] =
{
AT91_PIN_PA13, /**led_1**/
AT91_PIN_PA14, /**led_2**/
};
/*应用程序对设备文件/dev/leds 执行 open()时,
*就会调用SAM9261_ledtest_open */
static int SAM9261_ledtest_open(struct inode *inode, struct file *file)
{
printk("SAM9261-ledtest Driver Open Called!\n");
return 0;
}
static long SAM9261_ledtest_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
if((cmd != 1 && cmd != 0) || (arg != 1 && arg != 0))
return -1;
switch(cmd)
{
case LED_ON:
if(arg)
{
at91_set_gpio_value(led_table[arg], 0);
}
else
{
at91_set_gpio_value(led_table[arg], 0);
}
break;
case LED_OFF:
if(arg)
{
at91_set_gpio_value(led_table[arg], 1);
}
else
{
at91_set_gpio_value(led_table[arg], 1);
}
break;
default:
return -EINVAL;
}
return 0;
}
static int SAM9261_ledtest_release(struct inode *inode, struct file *file)
{
printk("SAM9261_LED Driver Release Called!\n");
return 0;
}
/*这个结构是字符设备驱动程序的核心
*当应用程序操作设备文件时调用的 open、read等函数,
*最终会调用这个结构中指定的对应函数 */
static struct file_operations SAM9261_ledtest_fops =
{
.owner = THIS_MODULE,
.open = SAM9261_ledtest_open,
.release = SAM9261_ledtest_release,
.unlocked_ioctl = SAM9261_ledtest_ioctl,
};
static struct class *SAM9261_ledtest_class = NULL;
/**模块的初始化函数**/
static int __init SAM9261_ledtest_init(void)
{
int result,err;
dev_t devno = MKDEV(LED_Major, 0);
/**采用自动分配主设备号**/
if (LED_Major)
{
result = register_chrdev_region(devno, 1, DEVICE_NAME);
printk("Got the Major number by register_chrdev_region !\n ");
}
else
{
result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
LED_Major=MAJOR(devno);
printk("Got the Major number by alloc_chrdev_region !\n");
}
if (result < 0)
{
printk(DEVICE_NAME " can't register major number\n");
return result;
}
printk("register SAM9261_ledtest Driver OK! Major = %d\n", LED_Major);
/**初始化cdev结构**/
cdev_init(&cdev,&SAM9261_ledtest_fops);
cdev.owner=THIS_MODULE;
cdev.ops=&SAM9261_ledtest_fops;
/**注册字符设备**/
err=cdev_add(&cdev, MKDEV(LED_Major, 0), 1);
if (err)
{
printk("error %d adding led \n ", err);
goto fail_cdev_add;
}
/**自动创建设备文件**/
SAM9261_ledtest_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(SAM9261_ledtest_class))
{
printk("Err: failed in SAM9261_ledtest class. \n");
goto fail_create_class;
}
device_create(SAM9261_ledtest_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME);
/**初始化PA13,PA14 PA23引脚**/
at91_set_gpio_output(AT91_PIN_PA13, 1);
at91_set_gpio_output(AT91_PIN_PA14, 1);
at91_set_gpio_output(AT91_PIN_PA23, 1);
at91_set_deglitch(AT91_PIN_PA13, 1);
at91_set_deglitch(AT91_PIN_PA14, 1);
at91_set_deglitch(AT91_PIN_PA23, 1);
printk(DEVICE_NAME " initialized\n");
return 0;
fail_create_class:
cdev_del(&cdev);
fail_cdev_add:
unregister_chrdev_region(devno, 1);
return -1;
}
/**模块的撤销函数**/
static void __exit SAM9261_ledtest_exit(void)
{
printk("SAM9261 LED DRIVER MODULE EXIT\n");
device_destroy(SAM9261_ledtest_class, MKDEV(LED_Major, 0));
class_destroy(SAM9261_ledtest_class);
cdev_del(&cdev);
unregister_chrdev(LED_Major, DEVICE_NAME);
}
/**指定驱动程序的初始化函数和卸载函数**/
module_init(SAM9261_ledtest_init);
module_exit(SAM9261_ledtest_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("none");
MODULE_DESCRIPTION("SAM9261_LEDTEST drivers");
MODULE_ALIAS("LED Driver module.");