Misc(或miscellaneous)驱动是一些拥有着共同特性的简单字符设备驱动。内核抽象出这些特性而形成一些API(在文件
drivers/char/misc.c中实现),以简化这些设备驱动程序的初始化。所有的misc设备被分配同一个主设备号
MISC_MAJOR(10),但是每一个可以选择一个单独的次设备号。如果一个字符设备驱动要驱动多个设备,那么它就不应该用misc设备来实现。如下:
================================================================================================
.c文件:
/*
* this is just a led driver test
* just for fun and train
*
* author : hyy
* time : 2012-08-31 11:21:20
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "my_led.h"
static int b_flg = 0;
struct cdev *led_device;
struct class *myclass;
static struct tast_struct * led_th=NULL;
unsigned int GpioId;
static unsigned long led_table[] =
{
((0x02DC << 16) | (2)),//GPIO2_2_GPIO,//MFP_PIN_GPIO2_2,//blue
((0x02E0 << 16) | (3)),//GPIO3_2_GPIO,//MFP_PIN_GPIO3_2,//yellow
((0x02E4 << 16) | (4)),//GPIO4_2_GPIO,//MFP_PIN_GPIO4_2,//green
((0x02E8 << 16) | (5)),//GPIO5_2_GPIO,//MFP_PIN_GPIO5_2,//red
((0x04E0 << 16) | (83)),//GPIO83_GPIO,//MFP_PIN_GPIO83,//keypad backlight
};
static int __init light_init(void);
static void __exit light_exit (void);
int light_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
int light_open(struct inode *inode, struct file *filp);
int light_release(struct inode *inode, struct file *filp);
static void blink_led(int i);
static void blink_led(int i)
{
pdeg(" my_led debug message: ");
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_ON);
msleep(125);
gpio_direction_output(GpioId,LED_OFF);
msleep(125);
gpio_direction_output(GpioId,LED_ON);
msleep(125);
gpio_direction_output(GpioId,LED_OFF);
msleep(125);
}
int light_release(struct inode *inode, struct file *filp)
{
pdeg(" my_led debug message: ");
return 0;
}
int light_open(struct inode *inode, struct file *filp)
{
pdeg(" my_led debug message: ");
return 0;
}
int light_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int i = 0;
pdeg(" my_led debug message: ");
if (arg > 5 && arg < 0 ) {
error("arg must in 0 ~ 5\n");
return -EINVAL;
}
switch(cmd) {
case CMD_LED_OFF:
if (arg == 5 ) {
for (i = 0 ; i <5 ; i++ ) {
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_OFF);
}
}else {
GpioId = mfp_to_gpio(led_table[arg]);
gpio_direction_output(GpioId,LED_OFF);
}
break;
case CMD_LED_ON:
if (arg == 5 ) {
for (i = 0 ; i <5 ; i++ ) {
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_ON);
}
}else {
GpioId = mfp_to_gpio(led_table[arg]);
gpio_direction_output(GpioId,LED_ON);
}
break;
case CMD_BLINK:
if (arg == 5 ) {
if (!b_flg){
led_th = kthread_run(&led_abcd,NULL,"led kernel thread");
if (led_th == NULL ) {
error("create kernel thread failed!\n");
return -1;
}
b_flg = 1;
}else {
if (led_th ) {
kthread_stop(led_th);
led_th = NULL;
}
error("b_flg = %d\t led_th = %d\n",b_flg,led_th);
b_flg = 0;
}
} else {
blink_led(arg);
}
break;
default:
printk("error argument!\n");
return -EINVAL;
}
return 0;
}
static struct file_operations light_fops = {
.owner = THIS_MODULE,
.ioctl = light_ioctl,
.open = light_open,
.release = light_release,
};
static struct miscdevice light_misdev =
{
.minor = 53,
.name = "hyy_led",
.fops = &light_fops,
};
static int __init light_init(void)
{
int ret = 0;
int i, GpioId ;
pdeg(" my_led debug message: ");
ret = misc_register(&light_misdev);
if (ret < 0 ) {
printk("misc register fail! ret = %d\n",ret);
return ret;
}
for (i = 0 ; i <5 ; i++ ) {
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_OFF);
}
return 0;
}
static void __exit light_exit (void)
{
pdeg(" my_led debug message: ");
misc_deregister(&light_misdev);
// free the kthread
if (led_th ) {
kthread_stop(led_th);
led_th = NULL;
}
}
module_init(light_init);
module_exit(light_exit);
MODULE_AUTHOR("hyy");
MODULE_LICENSE("GPL");
================================================================================================
.h 文件和makefile 文件和(一)相同,使用miscdevice 的时候,简化了,申请设备号,用udev创建设备文件等等一系列的代码工作,从而简化了驱动。
所以使用miscdevice的目的就是为了简化、方便字符设备的驱动的编写。
在struct miscdevice 中
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
如果指定nodename则 misc 会创建其指定的名字作为设备结点文件的名字,如果不指定,则会默认使用 name
阅读(1129) | 评论(0) | 转发(0) |