铅笔

在你的害怕中坚持的越多,你就会越自信
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

led驱动 write

Posted on 2017-01-04 09:26  黑色の铅笔  阅读(227)  评论(0编辑  收藏  举报

perled.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#define DEVICE_NAME "myled"   /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
static struct class *leds_class;
static struct class *led_dev_class;
int major;


/* 应用程序对设备文件/dev/leds执行open(...)时,
 * 就会调用s3c24xx_leds_open函数
 */
static int led_open (struct inode *inode, struct file *filep)  
{  
    // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能
    s3c2410_gpio_cfgpin( S3C2410_GPF6, S3C2410_GPF5_OUTP); 
    return 0;  
}  


static ssize_t led_write(struct file *file, const char __user *data,
                  size_t len, loff_t * ppos)
{
    int val;
    copy_from_user(&val, data, 1); //    copy_to_user();
    s3c2410_gpio_setpin(S3C2410_GPF5, (val & 0x1));//避免使用if语句   
    
    return 1;
                      
}
/* 这个结构是字符设备驱动程序的核心
 * 当应用程序操作设备文件时所调用的open、read、write等函数,
 * 最终会调用这个结构中指定的对应函数
 */
static struct file_operations led_ops=  
{    
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   = led_open,  
    .write  = led_write,
}; 
 
/*
 * 执行insmod命令时就会调用这个函数 
 */
  
static int led_init(void)  
{  
    int ret;
    /* 注册字符设备
     * 参数为主设备号、设备名字、file_operations结构;
     * 这样,主设备号就和具体的file_operations结构联系起来了,
     * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数
     * LED_MAJOR可以设为0,表示由内核自动分配主设备号
     */
     major = register_chrdev(0, DEVICE_NAME, &led_ops);
      if (major < 0) 
      {
      printk(DEVICE_NAME  " can't register major number number::%d\n",major);
      return ret;
      }
    printk(DEVICE_NAME " initialized1\n");
    leds_class = class_create(THIS_MODULE, "leds");
    if (IS_ERR(leds_class))
        return PTR_ERR(leds_class);
    led_dev_class = class_device_create(leds_class, NULL, MKDEV(major, 0), NULL, "perled"); /* /dev/leds */ 
    return 0;

}

/*
 * 执行rmmod命令时就会调用这个函数 
 */
static void led_exit(void)
{
    class_device_unregister(led_dev_class, MKDEV(major, 0));
    class_destroy(leds_class);       
     /* 卸载驱动程序 */
    unregister_chrdev(major, DEVICE_NAME);
  
}






module_init(led_init);  
module_exit(led_exit);  


MODULE_AUTHOR("http://www.100ask.net");
MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver");
MODULE_LICENSE("GPL");  

test.c

#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <stdio.h>  
#include <sys/ioctl.h>


/*
  *  ledtest <dev> <on|off>
  */

void print_usage(char *file)
{
    printf("Usage:\n");
    printf("%s <dev> <on|off>\n",file);
    printf("eg. \n");
    printf("%s /dev/leds on\n", file);
    printf("%s /dev/leds off\n", file);
    printf("%s /dev/led1 on\n", file);
    printf("%s /dev/led1 off\n", file);
}
int main(int argc,char**argv)  
{  
    int fd;  
	int ret;
	int num=1;
	char val;
	
	if(argc!=2)
	{
		
		printf("error USAGE\n");
		exit(1);
	}
  //1、打开设备
    fd = open("/dev/perled",O_RDWR);  
    if(fd<0)  
    {  
        perror("open fail \n");  
        return -1;  
    }  
   if (!strcmp("on", argv[1]))
    {
        // 亮灯
        val = 0;
        write(fd, &val, 1);
    }
    else if (!strcmp("off", argv[1]))
    {
        // 灭灯
        val = 1;
        write(fd, &val, 1);
    }
    else
    {
        print_usage(argv[0]);
        return 0;
    }
    
  
    close(fd);
	return 0;
}