转自:http://blog.chinaunix.net/uid-29165999-id-4296162.html
#define GPIO_MAJOR 230 // major device NO.
#define GPIO_MINOR 0 // minor device NO.
#define DEVICE_NAME "gpios"
#define SET_OUTPUT_LOW 0
#define SET_OUTPUT_HIGH 1
#define GET_VALUE 2
#define SET_INPUT 3
static struct class *gpio_class;
static struct gpio gpio_array[] =
{
{ GPIO_TO_PIN(0, 0), GPIOF_OUT_INIT_LOW, "RTU_WDI_SIGNAL" },
{ GPIO_TO_PIN(0, 1), GPIOF_OUT_INIT_HIGH, "RTU_PLC_BAK_IO1"},
};
static int gpio_open(struct inode *inode,struct file *file)
{
printk(KERN_WARNING"gpio open success!
");
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
printk (KERN_ALERT "Device gpio released
");
return 0;
}
static long gpio_ioctl(struct file *file,unsigned int cmd,unsigned long gpio)
{
int i;
unsigned long gpio_num = (gpio/100)*16+gpio%100;
for (i = 0; i < ARRAY_SIZE(gpio_array); i++) {
if(gpio_array[i].gpio == gpio_num)
goto valid_gpio;
}
return -1;
valid_gpio:
switch(cmd)//cmd表示应用程序传入的 GPIO 动作
{
case SET_OUTPUT_LOW://0
{
gpio_direction_output(gpio_num, 0);
break;
}
case SET_OUTPUT_HIGH://1
{
gpio_direction_output(gpio_num, 1);
break;
}
case GET_VALUE://2
{
return gpio_get_value(gpio_num);
}
case SET_INPUT://3
{
gpio_direction_input(gpio_num);
break;
}
default:
{
printk(KERN_EMERG "GPIO command mistake!!!
");
break;
}
}
return 0;
}
static const struct file_operations gpio_fops =
{
.owner = THIS_MODULE,
.open = gpio_open,
.release = gpio_release,
.unlocked_ioctl = gpio_ioctl,
};
//驱动加载函数
static int __init gpio_init(void)
{
int ret;
//注册一些列GPIO
ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array));
if (ret < 0)
{
printk(KERN_EMERG "GPIO request failed
");
goto request_failed;
}
const char *name = DEVICE_NAME;
dev_t my_dev_no;
struct cdev *gpio_cdev;
//分配cdev结构体
gpio_cdev = cdev_alloc();
if(gpio_cdev == NULL)
{
printk(KERN_EMERG "Cannot alloc cdev
");
goto request_failed;
}
//初始化cdev结构体
cdev_init(gpio_cdev,&gpio_fops);
gpio_cdev->owner=THIS_MODULE;
int result=alloc_chrdev_region(&my_dev_no,0,1,DEVICE_NAME); //动态分配设备号
if(result < 0)
{
printk(KERN_EMERG "alloc_chrdev_region failed
");
goto request_failed;
}
kobject_set_name(&cdev->kobj, "%s", name);
ret=cdev_add(gpio_cdev,my_dev_no,1);
if(ret < 0)
{
printk(KERN_EMERG "GPIO register failed
");
goto request_failed;
}
//在sysfs文件系统下创建一个类
gpio_class = class_create(THIS_MODULE, DEVICE_NAME);
//在/dev中创建设备节点
device_create(gpio_class, NULL, my_dev_no, NULL, DEVICE_NAME);
return ret;
request_failed:
gpio_free_array(gpio_array, ARRAY_SIZE(gpio_array));
return ret;
}
static void __exit gpio_exit(void)
{
device_destroy(gpio_class, MKDEV(GPIO_MAJOR, GPIO_MINOR));
class_unregister(gpio_class);
unregister_chrdev(GPIO_MAJOR, DEVICE_NAME);
}
module_init(gpio_init);
module_exit(gpio_exit);
MODULE_LICENSE("GPL");