ioctl是广大人民群众喜闻乐见的函数之一,这里略作笔记,把以前写的代码整理以下。
应用测试程序main.c
#include #include #include #include #include #include #include "../ioctl_c.h" GPIO_Data_S led_ctl; int main(int argc, char **argv) { int testdev = 0; int i = 0; int erro = 0; char buf[10]; //打开设备文件 testdev = open ("/dev/test",O_RDWR); if(testdev == -1) { printf("Cann't open file...../n"); exit(0); } while(1) { //led_ctl结构赋值 led_ctl.port='G'; led_ctl.bit=5; led_ctl.value=0; //调用ioctl函数 ioctl(testdev,GPIO_IO_SET,&led_ctl); ioctl(testdev,GPIO_IO_WRITE,&led_ctl); ioctl(testdev,GPIO_IO_READ,&led_ctl); sleep(1); led_ctl.port='G'; led_ctl.bit=6; led_ctl.value=0; ioctl(testdev,GPIO_IO_SET,&led_ctl); ioctl(testdev,GPIO_IO_WRITE,&led_ctl); ioctl(testdev,GPIO_IO_READ,&led_ctl); sleep(1); } close(testdev); } /* mknod /dev/test c 253 0 */
ioctl.h
#ifndef __IOCTL_C_H__ #define __IOCTL_C_H__ typedef struct GPIO_Data_t { unsigned char port; unsigned int bit; unsigned int value; }GPIO_Data_S; #define GPIO_IOC_MAGIC 12 //Documentation/ioctl-number.txt #define GPIO_IO_SET_GPG _IOW(GPIO_IOC_MAGIC,0,sizeof(GPIO_Data_S)) #define GPIO_IO_GET_GPG _IOWR(GPIO_IOC_MAGIC,1,sizeof(GPIO_Data_S)) #define GPIO_IO_WRITE _IOW(GPIO_IOC_MAGIC,2,sizeof(GPIO_Data_S)) #define GPIO_IO_READ _IOWR(GPIO_IOC_MAGIC,3,sizeof(GPIO_Data_S)) #endif
驱动层代码test.c
/************* linux headers **************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ioctl_c.h" //设备主次设备号 unsigned int test_major=253; unsigned int test_minor=0; struct cdev cdevc; MODULE_LICENSE("Dual BSD/GPL"); GPIO_Data_S led; static void led_ctl() { //G50 时写寄存器,具体参见s3c2440 datasheet //这里主要是控制开发板的led等闪烁,每秒闪以下 if(led.port=='G'&& led.bit==5 && led.value==0) { printk("G50/n"); __raw_writel(0x400,S3C2410_GPGCON); __raw_writel(0xffdf,S3C2410_GPGDAT); } //G60 时写寄存器 else if(led.port=='G' && led.bit==6 && led.value==0) { printk("G60/n"); __raw_writel(0x1000,S3C2410_GPGCON); __raw_writel(0xffbf,S3C2410_GPGDAT); } } static int read_test(struct file *file,char *buf,int count ,loff_t *f_pos) { printk("/n read_test"); printk("%d",count); return count; } static int write_test(struct file *file,const char *buf,int count, loff_t *f_pos) { printk("/n write_test"); return count; } static int ioctl_test(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { if(copy_from_user(&led,arg,sizeof(GPIO_Data_S))) { return - EFAULT; } printk("%c %d %d/n",led.port,led.bit,led.value); printk("/n ioctl_test"); switch(cmd) { case GPIO_IO_SET_GPG :led_ctl();break; case GPIO_IO_GET_GPG :led_ctl();break; // case GPIO_IO_WRITE :printk("cmd3") ;break; // case GPIO_IO_READ :printk("cmd3") ;break; default:break; } return cmd; } static int open_test(struct inode *inode,struct file *file) { printk("/n open_test"); return 0; } static void release_test(struct inode *inode,struct file *file) { printk("/n release_test"); } struct file_operations test_fops = { .owner=THIS_MODULE, .read=read_test, .write=write_test, .open=open_test, .ioctl=ioctl_test, .release=release_test, }; int simple_c_init_module(void) { int result; dev_t dev = 0; dev=MKDEV(test_major,test_minor); result = register_chrdev_region(dev,1,"test"); printk("major= %d,minor=%d /n",test_major,test_minor); if(result < 0) { printk(KERN_INFO "test : can't get major number/n"); return result; } cdev_init(&cdevc,&test_fops); cdevc.owner= THIS_MODULE; cdevc.ops=&test_fops; result=cdev_add(&cdevc,dev,1); if(result) printk("Error %d adding test",result); return 0; } void simple_c_cleanup_module(void) { dev_t dev=0; dev = MKDEV(test_major,test_minor); cdev_del(&cdevc); unregister_chrdev_region(dev,1); } module_init(simple_c_init_module); module_exit(simple_c_cleanup_module);
编译需要makefile
# To build modules outside of the kernel tree, we run "make" # in the kernel source tree; the Makefile these then includes this # Makefile once again. # This conditional selects whether we are being included from the # kernel Makefile or not. ifeq ($(KERNELRELEASE),) # Assume the source tree is where the running kernel was built # You should set KERNELDIR in the environment if it's elsewhere # KERNELDIR ?= /lib/modules/$(shell uname -r)/build KERNELDIR = /home/utu-linux_for_s3c2440_V1.5.3 # KERNELDIR=$(KDIR) # # The current directory is passed to sub-makes as argument PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules modules_install clean else # called from kernel build system: just declare what our modules are obj-m := test.o endif