功能: 不用ioctl函数控制LED,用read函数读取PIO寄存器值, Write函数写入寄存器值实现控制LED灯
myleds_2.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/io.h>
#include <linux/string.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#define DEV_NAME "leddev"
#define NUMBER_OF_DEVICE 1
#define PIO_LED 0x00401420|0xE0000000
struct class *led_class;
static struct cdev cdev;
dev_t devno;
static ssize_t led_open(struct inode *inode, struct file *file)
{
//printk(KERN_ALERT "led device open successfully!\n");
return 0;
}
static ssize_t led_release(struct inode *inode, struct file *file)
{
//printk(KERN_ALERT "led device close successfully!\n");
return 0;
}
static ssize_t led_read(struct file *file, char __user *buff, size_t count, loff_t *offp){
unsigned char led_dat;
char led_string;
if(NULL == file){
return -1;
}
led_dat = readb(PIO_LED) & 0x0f;
if(sprintf(&led_string,"%x",led_dat)==0) {
printk(KERN_ALERT "read:sprintf error\n");
return -EFAULT;
}
if(copy_to_user(buff,&led_string,count)!=0) {
printk(KERN_ALERT "read:copy_to_user error\n");
return -EFAULT;
}
return count;
}
static ssize_t led_write(struct file *file, char __user *buff, size_t count, loff_t *offp){
unsigned char led_dat;
char led_string;
if(NULL == file){
return -1;
}
if(copy_from_user(&led_string,buff,count)!=0){
printk(KERN_ALERT "write:user pointer is not valid\n");
return -EFAULT;
}
if(sscanf(&led_string,"%x",&led_dat)==0){
printk(KERN_ALERT "write:sscanf error\n");
return -EFAULT;
}
writeb(led_dat,PIO_LED);
return count;
}
static struct file_operations led_fops=
{
.owner= THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
static int led_init(void)
{
int ret;
ret = alloc_chrdev_region(&devno,0, NUMBER_OF_DEVICE, DEV_NAME);
if(ret<0){
printk(KERN_ALERT "%s alloc device error",__func__);
return ret;
}
led_class = class_create(THIS_MODULE,"led_char_class");
if(IS_ERR(led_class)){
printk(KERN_ALERT "%s create class error\n",__func__);
return -1;
}
device_create(led_class, NULL, devno, NULL, DEV_NAME);
cdev_init(&cdev, &led_fops);
cdev.owner = THIS_MODULE;
cdev_add(&cdev, devno, NUMBER_OF_DEVICE);
return 0;
}
static void led_exit(void)
{
printk(KERN_ALERT "%s",__func__);
cdev_del(&cdev);
device_destroy(led_class,devno);
class_destroy(led_class);
unregister_chrdev_region(devno,NUMBER_OF_DEVICE);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kimi Shi");
test_led_2.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
int main(int argc,char **argv)
{
int fd, led_dat;
char arg[3];
char buff;
//check argument
if(argc!=2 && argc!=3){
printf("INPUT ERROR, Use format below:\n");
printf("test_led_2 -r --read data from PIO_LED register\n");
printf("test_led_2 -w [0-15] --set PIO_LED register\n");
exit(1);
}
//check argument 1
if(sscanf(argv[1],"%s",&arg)!=1 || (strcmp(arg,"-r")!=0 && strcmp(arg,"-w")!=0) ){
printf("Input argument 1 wrong!\n");
exit(1);
}
//open led device
fd=open("/dev/leddev",O_RDWR);
if(fd<0){
perror("open led device\n");
exit(1);
}
//read PIO_LED register data
if(strcmp(arg,"-r")==0){
read(fd, &buff, 1);
printf("Value of PIO_LED register: %c\n",buff);
}
//Wrtie data to PIO_LED register
if(strcmp(arg,"-w")==0){
//check argument, 0x00 to 0x0f
if(sscanf(argv[2],"%d",&led_dat)!=1 ||led_dat<0 ||led_dat>15){
printf("input argument 2 wrong!\n");
exit(1);
}
sprintf(&buff,"%x",led_dat);
write(fd,&buff,1);
}
//clode device
close(fd);
return 0;
}
test_led_3.c 流水灯
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <unistd.h>
int main(int argc,char **argv)
{
int fd = -1;
int i, cnt;
unsigned char led = 0x0f;
unsigned char buff;
//open
fd = open("/dev/leddev",O_RDWR);
if(0>fd){
perror("open err:");
exit(1);
}
//light water
while(1){
for(i=0;i<4;i++){
led &= (1 << i);
sprintf(&buff, "%x",led);
cnt = write(fd, &buff, 1);
if(0>cnt){
perror("write err:");
exit(1);
}
led = 0x0f;
sleep(1);
}
}
//close
close(fd);
return 0;
}