/**************************************************************
demo.c
linux driver example for UP_CUP6410 platform
It can be compiled for x86 PC
modify by sprife
derive from zou jian-guo's driver exp.
***************************************************************/
#ifdef MODULE
#include
#ifdef CONFIG_DEVFS_FS
#include
#endif
#include
#include /* printk() */
#include /* kmalloc() */
#include /* everything... */
#include /* error codes */
#include /* size_t */
#include
#include /* O_ACCMODE */
#include /* COPY_TO_USER */
#include /* cli(), *_flags */
#define DEVICE_NAME "UP-TECH DEMO"
#define DEMORAW_MINOR 1
#define DEMO_Devfs_path "demo/0"
static int demoMajor = 0;
static int MAX_BUF_LEN=1024;
static char drv_buf[1024];
static int WRI_LENGTH=0;
/*************************************************************************************/
/*逆序排列缓冲区数据*/
static void do_write(void)
{
int i;
int len = WRI_LENGTH;
int mid = len>>1;
char tmp;
for(i = 0; i < mid; i++,len--){
tmp = drv_buf[len-1];
drv_buf[len-1] = drv_buf[i];
drv_buf[i] = tmp;
}
}
/*************************************************************************************/
static ssize_t demo_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
{
if(count > MAX_BUF_LEN)count = MAX_BUF_LEN;
copy_from_user(drv_buf , buffer, count);
WRI_LENGTH = count;
// printk("user write data to driver\\n");
do_write();
return count;
}
/*************************************************************************************/
static ssize_t demo_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
{
if(count > MAX_BUF_LEN)
count=MAX_BUF_LEN;
copy_to_user(buffer, drv_buf,count);
// printk("user read data from driver\\n");
return count;
}
/*************************************************************************************/
static int demo_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
// printk("ioctl runing\\n");
switch(cmd){
case 1:printk("runing command 1 \\n");break;
case 2:printk("runing command 2 \\n");break;
default:
printk("error cmd number\\n");break;
}
return 0;
}
/*************************************************************************************/
static int demo_open(struct inode *inode, struct file *filp)
{
// MOD_INC_USE_COUNT;
printk(KERN_DEBUG" device open sucess!\\n");
return 0;
}
/*************************************************************************************/
static int demo_release(struct inode *inode, struct file *filp)
{
// MOD_DEC_USE_COUNT;
printk(KERN_DEBUG "device release\\n");
return 0;
}
/*************************************************************************************/
static struct file_operations pxa270_fops = {
owner: THIS_MODULE,
write: demo_write,
read: demo_read,
ioctl: demo_ioctl,
open: demo_open,
release: demo_release,
};
/*************************************************************************************/
static int __init demo_init(void)
{
int ret;
ret = register_chrdev(0, DEVICE_NAME, &pxa270_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't get major number\\n");
return ret;
}
demoMajor=ret;
printk("demo driver initialized \\n");
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(demoMajor, DEMORAW_MINOR),
S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, DEMO_Devfs_path);
#endif
return 0;
}
/*************************************************************************************/
#ifdef MODULE
void __exit demo_exit(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_remove(DEMO_Devfs_path);
#endif
unregister_chrdev(demoMajor, DEVICE_NAME);
}
module_exit(demo_exit);
#endif
/*************************************************************************************/
module_init(demo_init);
MODULE_LICENSE("Dual BSD/GPL");
#endif // 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.
TARGET = test_demo
CROSS_COMPILE =
CC = $(CROSS_COMPILE)gcc
STRIP = $(CROSS_COMPILE)strip
#CFLAGS = -O2
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 ?=/home/sprife/kernel/linux-2.6.24.4
KERNELDIR ?=/linux-2.6.21
# KERNELDIR ?= /usr/src/kernels/2.6.9-42.EL-smp-i686/
# The current directory is passed to sub-makes as argument
PWD := $(shell pwd)
all: $(TARGET) modules
$(TARGET):
$(CC) -o $(TARGET) $(TARGET).c
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 $(TARGET)
.PHONY: modules modules_install clean
else
# called from kernel build system: just declare what our modules are
obj-m := demo.o
endif
#include
#include
#include
#include
#include
void showbuf(char *buf);
int MAX_LEN=32;
/*
* 驱动测试文件如下
*/
int main(int argc,char **argv)
{
int fd;
int i;
char buf[255];
for(i=0; i
buf[i]=i;
}
fd=open("/dev/demo",O_RDWR);
if(fd < 0){
printf("####DEMO device open fail####\\n");
return (-1);
}
printf("write %d bytes data to /dev/demo \\n",MAX_LEN);
showbuf(buf);
write(fd,buf,MAX_LEN);
printf("Read %d bytes data from /dev/demo \\n",MAX_LEN);
read(fd,buf,MAX_LEN);
showbuf(buf);
// ioctl(fd,1,NULL);
// ioctl(fd,4,NULL);
close(fd);
return 0;
}
void showbuf(char *buf)
{
int i,j=0;
for(i=0;i
if(i%4 ==0)
printf("\\n%4d: ",j++);
printf("%4d ",buf[i]);
}
printf("\\n*****************************************************\\n");
}