#include <linux/module.h> #include <linux/kernel.h> #include <linux/io.h> #include <linux/fs.h> #include <asm/uaccess.h> #include <linux/miscdevice.h> #include <linux/pci.h> #include <linux/ioctl.h> #include <linux/init.h> #define DEVICE_NAME "leds0" // (/dev/leds) #define UGPMCON (*(volatile unsigned long *)S3C64XX_GPMCON) #define UGPMDAT (*(volatile unsigned long *)S3C64XX_GPMDAT) #define UGPMPUD (*(volatile unsigned long *)S3C64XX_GPMPUD) static long S3C64XX_GPMCON=0xF4500820; static long S3C64XX_GPMDAT=0xF4500824; #define LED_MAJOR 240 static int led_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { // printk(KERN_ALERT"\ncmd = %d arg = %d \n", cmd, arg); switch(cmd) { case 0: printk(KERN_ALERT"led%d off\n", arg); switch(arg) { case 0: UGPMDAT |= 0x01; break; case 1: UGPMDAT |= 0x02; break; case 2: UGPMDAT |= 0x04; break; case 3: UGPMDAT |= 0x08; break; default: break; } break; case 1: printk(KERN_ALERT"led%d on\n", arg); switch(arg) { case 0: UGPMDAT &= 0xfe; break; case 1: UGPMDAT &= 0xfd; break; case 2: UGPMDAT &= 0xfb; break; case 3: UGPMDAT &= 0xf7; break; default: break; } break; case 11: printk(KERN_ALERT"led all on\n"); UGPMDAT &= 0xe0; break; case 10: printk(KERN_ALERT"led all off\n"); UGPMDAT |= 0xff; break; default: break; } return 0; } struct file_operations led_fops={ .owner = THIS_MODULE, .unlocked_ioctl = led_ioctl, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, //动态设备号 .name = DEVICE_NAME, .fops = &led_fops, }; static int __init led_init(void) { int rc; rc = misc_register(&misc); outl(0x00111111,S3C64XX_GPMCON); outl(0xff,S3C64XX_GPMDAT); if(rc<0) { printk(KERN_ALERT"register %s char dev error\n","leds"); return -1; } printk(KERN_ALERT"OK!\n"); return 0; } static void __exit led_exit(void) { unregister_chrdev(LED_MAJOR, "leds"); printk(KERN_ALERT"module exit\n"); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("cw");
Makefile
KERNELDIR :=/home/share/linux/linux3.0/kernel/linux-3.0.1 #KERNELDIR :=/home/share/linux/linux2.6.36/linux-2.6.36.2-v1.05 PWD :=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install obj-m:=led.o clean: rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
測試程式
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> int main(int argc, char **argv) { int on, cmd; int led_no; int fd; if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 || led_ no < 0 || led_no > 3) { fprintf(stderr, "Usage: leds led_no 0|1|2|3\n"); exit(1); } fd = open("/dev/leds0", 0); if(fd < 0) printf("Can't open /dev/leds!\n"); ioctl(fd, on, led_no); close(fd); return 0; }