Aprendizaje del controlador LINUX integrado Programación del controlador del dispositivo de caracteres 5.ioctl (dos) Código de implementación del espacio del kernel
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
struct led_source {
char * name;
unsigned led_num;
} ;
struct led_source led_info[ ] = {
{
. name = "LED1" ,
. led_num = PAD_GPIO_C + 12
} ,
{
. name = "LED2" ,
. led_num = PAD_GPIO_C + 11
} ,
{
. name = "LED3" ,
. led_num = PAD_GPIO_C + 7
} ,
{
. name = "LED4" ,
. led_num = PAD_GPIO_B + 26
}
} ;
long led_ioctl ( struct file * file, unsigned int cmd, unsigned long arg) {
unsigned long kindex[ 4 ] ;
copy_from_user ( kindex, arg, 4 ) ;
switch ( cmd) {
case LED_ON :
gpio_set_value ( led_info[ kindex[ 0 ] - 1 ] . led_num, 0 ) ;
break ;
case LED_OFF :
gpio_set_value ( led_info[ kindex[ 0 ] - 1 ] . led_num, 1 ) ;
break ;
case LED_STATE :
led_state ( kindex) ;
copy_to_user ( arg, kindex, sizeof ( int ) * 4 ) ;
break ;
default :
break ;
}
}
static struct file_operations fops= {
. owner = THIS_MODULE,
. unlocked_ioctl = led_ioctl
} ;
static dev_t dev_num;
static struct cdev cdev;
static int led_init ( void ) {
int i = 0 ;
for ( ; i < ARRAY_SIZE ( led_info) ; i++ ) {
gpio_request ( led_info[ i] . led_num, led_info[ i] . name) ;
gpio_direction_output ( led_info[ i] . led_num, 1 ) ;
}
alloc_chrdev_region ( & dev_num, 0 , 4 , "led_ioctl_test" ) ;
cdev_init ( & cdev, & fops) ;
cdev_add ( & cdev, dev_num, 4 ) ;
return 0 ;
}
static void led_exit ( void ) {
int i = 0 ;
for ( ; i< ARRAY_SIZE ( led_info) ; i++ ) {
gpio_set_value ( led_info[ i] . led_num, 1 ) ;
gpio_free ( led_info[ i] . led_num) ;
}
cdev_del ( & cdev) ;
}
module_init ( led_init) ;
module_exit ( led_exit) ;
MODULE_LICENSE ( "GPL" ) ;