实验描述:ioctl控制LED
注意事项:unlocked_ioctl(...)是控制32bit
内核版本:Linux 2.6.38
开发板: Mini 6410
驱动程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
/*
Kernel Version: Linux 2.6.38
Arm Version: Mini 6410
*/
#define MyPrintk printk
#define CTL_Led1 3
#define CTL_Led2 4
#define CTL_Led3 5
#define CTL_Led4 6
static dev_t Leds_Major ;
static char * DEVICE_NAME = "IoctlLeds";
volatile unsigned long *gpkcon0 = NULL;
volatile unsigned long *gpkdat = NULL;
static struct class *leds_class;
static int buttons_leds_init (struct inode *inode, struct file *file)
{
*gpkcon0 &= ~( (0xF<<4*4) | (0xF<<5*4) | (0xF<<6*4) | (0xF<<7*4));
*gpkcon0 |= ( (0x1<<4*4) |(0x1<<5*4) | (0x1<<6*4) | (0x1<<7*4));
*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;
return 0;
}
long unlocked_ioctl_leds (struct file * file, unsigned int cmd, unsigned long count)
{
MyPrintk (KERN_EMERG "unlocked Cmd value: %d, %lu\n", cmd, count);
*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;
if( cmd == CTL_Led1){
*gpkdat &= ~ ((1<<4) | (0<<5) | (0<<6) | (0<<7)) ;
}else if(cmd == CTL_Led2){
*gpkdat &= ~ ((0<<4) | (1<<5) | (0<<6) | (0<<7));
}else if(cmd == CTL_Led3){
*gpkdat &= ~ ((0<<4) | (0<<5) | (1<<6) | (0<<7));
}else if(cmd == CTL_Led4){
*gpkdat &= ~ ((0<<4) | (0<<5) | (0<<6) | (1<<7));
}
return 0;
}
long compat_ioctl_leds (struct file * file, unsigned int cmd , unsigned long count)
{
MyPrintk (KERN_EMERG "locked Cmd value: %d, %lu\n", cmd, count);
*gpkdat |= (1<<4) | (1<<5) | (1<<6) | (1<<7) ;
if( cmd == CTL_Led1){
*gpkdat &= ~ ((1<<4) | (0<<5) | (0<<6) | (0<<7)) ;
}else if(cmd == CTL_Led2){
*gpkdat &= ~ ((0<<4) | (1<<5) | (0<<6) | (0<<7));
}else if(cmd == CTL_Led3){
*gpkdat &= ~ ((0<<4) | (0<<5) | (1<<6) | (0<<7));
}else if(cmd == CTL_Led4){
*gpkdat &= ~ ((0<<4) | (0<<5) | (0<<6) | (1<<7));
}
return 0;
}
static struct file_operations s3c64XX_leds_fops = {
.owner = THIS_MODULE,
.open = buttons_leds_init,
.compat_ioctl = compat_ioctl_leds,
.unlocked_ioctl = unlocked_ioctl_leds,
};
static int myleds_init(void)
{
Leds_Major = register_chrdev(Leds_Major,DEVICE_NAME , &s3c64XX_leds_fops);
if(Leds_Major < 0){
MyPrintk (KERN_EMERG "Sorry, Can not register the leds device!\n");
}
MyPrintk (KERN_EMERG " Register the %s device\n", DEVICE_NAME);
leds_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(leds_class, NULL , MKDEV(Leds_Major, 0), NULL, DEVICE_NAME);
gpkcon0 = (volatile unsigned long *)ioremap(0x7F008800,12);
gpkdat = gpkcon0 + 2;
return 0;
}
static void myleds_exit(void)
{
unregister_chrdev(Leds_Major, DEVICE_NAME);
device_destroy(leds_class, MKDEV(Leds_Major, 0));
class_destroy(leds_class);
iounmap(gpkcon0);
MyPrintk (KERN_EMERG "%s Linux Byebye\n", DEVICE_NAME);
}
module_init(myleds_init);
module_exit(myleds_exit);
MODULE_LICENSE("GPL");
测试程序:
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#define CTL_Led1 3
#define CTL_Led2 4
#define CTL_Led3 5
#define CTL_Led4 6
int main(int argc, char **argv)
{
int fd;
int val = 1;
int ret;
fd = open("/dev/IoctlLeds", O_RDWR);
if (fd < 0){
printf("Sorry, can't open!\n");
}
int arg = 12;
ret = ioctl(fd, CTL_Led1, &arg);
if (ret != 0){
printf("Sorry, can't ioctl!\n");
}
sleep(2);
arg = 11;
ret = ioctl(fd, CTL_Led2, &arg);
if (ret != 0){
printf("Sorry, can't ioctl!\n");
}
sleep(2);
arg = 10;
ret = ioctl(fd, CTL_Led3, &arg);
if (ret != 0){
printf("Sorry, can't ioctl!\n");
}
sleep(2);
arg = 9;
ret = ioctl(fd, CTL_Led4, &arg);
if (ret != 0){
printf("Sorry, can't ioctl!\n");
}
sleep(2);
return 0;
}