内核驱动:led驱动
#include <linux/string.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <mach/gpio.h> //包含管脚操作的相关函数
#include <linux/device.h> //包含创建设备文件的相关函数
#define DEVICE_NAME "MYS-SAM9X5-ledtest"
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_PB18, /**led_blue**/
AT91_PIN_PD21, /**led_red**/
};
/*应用程序对设备文件/dev/leds 执行 open()时,
*就会调用MYS_SAM9X5_ledtest_open */
static int MYS_SAM9X5_ledtest_open(struct inode *inode, struct file *file)
{
printk("MYS-SAM9X5-ledtest Driver Open Called!\n");
return 0;
}
static long MYS_SAM9X5_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], 1);
}
else
{
at91_set_gpio_value(led_table[arg], 0);
}
break;
case LED_OFF:
if(arg)
{
at91_set_gpio_value(led_table[arg], 0);
}
else
{
at91_set_gpio_value(led_table[arg], 1);
}
break;
default:
return -EINVAL;
}
return 0;
}
static int MYS_SAM9X5_ledtest_release(struct inode *inode, struct file *file)
{
printk("MYS_SAM9X5_LED Driver Release Called!\n");
return 0;
}
/*这个结构是字符设备驱动程序的核心
*当应用程序操作设备文件时调用的 open、read等函数,
*最终会调用这个结构中指定的对应函数 */
static struct file_operations MYS_SAM9X5_ledtest_fops =
{
.owner = THIS_MODULE,
.open = MYS_SAM9X5_ledtest_open,
.release = MYS_SAM9X5_ledtest_release,
.unlocked_ioctl = MYS_SAM9X5_ledtest_ioctl,
};
static struct class *MYS_SAM9X5_ledtest_class = NULL;
/**模块的初始化函数**/
static int __init MYS_SAM9X5_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 MYS_SAM9X5_ledtest Driver OK! Major = %d\n", LED_Major);
/**初始化cdev结构**/
cdev_init(&cdev,&MYS_SAM9X5_ledtest_fops);
cdev.owner=THIS_MODULE;
cdev.ops=&MYS_SAM9X5_ledtest_fops;
/**注册字符设备**/
err=cdev_add(&cdev, MKDEV(LED_Major, 0), 1);
if (err)
{
printk("error %d adding led \n ", err);
goto fail_cdev_add;
}
/**自动创建设备文件**/
MYS_SAM9X5_ledtest_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(MYS_SAM9X5_ledtest_class))
{
printk("Err: failed in MYS_SAM9X5_ledtest class. \n");
goto fail_create_class;
}
device_create(MYS_SAM9X5_ledtest_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME);
/**初始化PB18,PD21引脚**/
at91_set_gpio_output(AT91_PIN_PB18, 1);
at91_set_gpio_output(AT91_PIN_PD21, 1);
at91_set_deglitch(AT91_PIN_PB18, 1);
at91_set_deglitch(AT91_PIN_PD21, 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 MYS_SAM9X5_ledtest_exit(void)
{
printk("MYS_SAM9X5 LED DRIVER MODULE EXIT\n");
device_destroy(MYS_SAM9X5_ledtest_class, MKDEV(LED_Major, 0));
class_destroy(MYS_SAM9X5_ledtest_class);
cdev_del(&cdev);
unregister_chrdev(LED_Major, DEVICE_NAME);
}
/**指定驱动程序的初始化函数和卸载函数**/
module_init(MYS_SAM9X5_ledtest_init);
module_exit(MYS_SAM9X5_ledtest_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alvin");
MODULE_DESCRIPTION("This is an example of MYS_SAM9X5_LEDTEST drivers");
MODULE_ALIAS("A simplest module.");
调用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define LED_DEV "/dev/MYS-SAM9X5-ledtest"
int main(int argc, char **argv)
{
int fd, ret, led_num, led_status;
if (argc!=3 || sscanf(argv[1],"%d", &led_num)!=1
|| sscanf(argv[2],"%d", &led_status)!=1)
{
printf("\r\nPlease input correct parameters !\r\n\n");
printf("usage:\r\n%s <led_num> <led_status>\r\n", argv[0]);
printf("\r\nOptions:\r\n");
printf(" led_num\t- 1 for red led, 0 for blue led.\r\n led_status\t- 1 for ON, 0 for OFF.\r\n\n");
exit(1);
}
if((led_status!=1 && led_status!=0) || (led_num!=0 && led_num!=1))
{
printf("\r\nError: The parameter value must be '0' or '1' !\r\n");
printf("\r\nPlease try again !!! !\r\n\n");
exit(1);
}
fd = open(LED_DEV, 0);
if (fd < 0)
{
printf("\r\nFail to open device '%s'!\r\n\n", LED_DEV);
exit(1);
}
ret = ioctl(fd, led_status, led_num);
if(ret < 0)
{
printf("\r\nFail calling ioctl !\r\n\n");
}
close(fd);
return 0;
}
浙公网安备 33010602011771号