Linux Embedded Drive Learning path ⑩ character device driver-my_led

Source: Internet
Author: User
Tags volatile

First put the code:

Character Device driver code:

/**
*file NAME:LED.C
*/
#include <linux/sched.h>#include<linux/signal.h>#include<linux/spinlock.h>#include<linux/errno.h>#include<linux/random.h>#include<linux/poll.h>#include<linux/init.h>#include<linux/slab.h>#include<linux/module.h>#include<linux/wait.h>#include<linux/mutex.h>#include<linux/io.h>#include<linux/fs.h>Static struct class*led_class;//Create ClassStatic structClass_device *led_class_devs[4];//Create a device that corresponds to a Class 1 total device files 3 single lamp device filesvolatileUnsignedLong*gpfcon =NULL;volatileUnsignedLong*gpfdat =NULL;intLed_open (structInode *inode,structFile *FP) { intMinor = minor (inode->I_rdev); //Get the secondary device number to open the device file Switch(minor) { Case 0: *gpfcon &= ~ ((0x3<< (4*2))| (0x3<< (5*2))| (0x3<< (6*2))); *gpfcon |= (0x1<< (4*2))| (0x1<< (5*2))| (0x1<< (6*2)); Break; Case 1: *gpfcon &= ~ (0x3<< (4*2)); *gpfcon |= (0x1<< (4*2)); Break; Case 2: *gpfcon &= ~ (0x3<< (5*2)); *gpfcon |= (0x1<< (5*2)); Break; Case 3: *gpfcon &= ~ (0x3<< (6*2)); *gpfcon |= (0x1<< (6*2)); Break; } return 0;} ssize_t Led_read (structFile *FP,Char__user *c, size_t *t) {int minor = minor (Fp->f_dentry->d_inode->i_rdev);
Char Leds_status;
Switch (minor)
{
Case 0:
Leds_status = ((*gpfdat & ((1<<4) | ( 1&LT;&LT;5) | (1<<6))) &GT;&GT;4)) &0x7;
Copy_to_user (buff, (const void *) &leds_status,1);//Copy data from user to kernel space
Break
Case 1:
Leds_status = (~ (*gpfdat>>4)) &0x1;
Copy_to_user (buff, (const void *) &leds_status,1);
Break
Case 2:
Leds_status = (~ (*gpfdat>>5)) &0x1;
Copy_to_user (buff, (const void *) &leds_status,1);
Break
Case 3:
Leds_status = (~ (*gpfdat>>6)) &0x1;
Copy_to_user (buff, (const void *) &leds_status,1);
Break
}}ssize_t Led_write (structFile *FP,Const Char__user *buf, size_t count, loff_t *PPOs) { intMinor = minor (fp->f_dentry->d_inode->I_rdev); intVal; Copy_from_user (&val, BUF,1); Switch(minor) { Case 0: Val&=0x1; *gpfdat &= ~ ((1<<4)| (1<<5)| (1<<6)); *gpfdat |= (val<<4)| (val<<5)| (val<<6); Break; Case 1: *gpfdat &= ~ (1<<4); *gpfdat |= (val&0x1) <<4; Break; Case 2: *gpfdat &= ~ (1<<5); *gpfdat |= (val&0x1) <<5; Break; Case 3: *gpfdat &= ~ (1<<6); *gpfdat |= (val&0x1) <<6; Break; }}structFile_operations led_fops={. Owner=this_module,. Open=Led_open,. Write=Led_write,};intMajor;Static intLed_init (void){ intMinor; Major= Register_chrdev (0,"Led_drv", &led_fops); The system automatically generates a device number when the specified device number is 0 o'clock led_class= Class_create (This_module,"my_leds"); if(Is_err (led_class))returnPtr_err (Led_class); led_class_devs[0] = Class_device_create (Led_class,null,mkdev (Major,0), NULL,"my_leds"); //Create a device file if(Unlikely (Is_err (Led_class_devs)))returnPtr_err (Led_class_devs); for(minor=1; minor<4; minor++) {Led_class_devs[minor]= Class_device_create (Led_class,null,mkdev (Major,minor), NULL,"my_led%d", minor); if(Unlikely (Is_err (Led_class_devs)))returnPtr_err (Led_class_devs); } Gpfcon= (volatileUnsignedLong*) Ioremap (0x56000050, -); //Physical address mapped to virtual address Gpfdat= Gpfcon +1; PRINTK ("led Install module\n"); return 0;}Static voidLed_exit (void) {Unregister_chrdev (major,"Led_drv" ); Class_device_unregister (led_class_devs[0]); //Unregister device file class_device_unregister (led_class_devs[1]); Class_device_unregister (led_class_devs[2]); Class_device_unregister (led_class_devs[3]);              Class_destroy (Led_class);                   //Destroy Class Iounmap (Gpfcon); //de-Physical Address mapping PRINTK ("led Module exit\n");} Module_init (Led_init); Module_exit (Led_exit); Module_license ("GPL");

Makefile of the module:

obj-m:=led.okerneldir:=/home/jz2440/linux-2.6. 22.6 pwd:=$ (Shell PWD)default:    -C $ (kerneldir)  m=$ (PWD) Modulesclean:    -rf *.o *.mod.c *.mod.o *.ko *.symvers

Test file:

#include <sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>intMainintargcChar**argv) {    intFD; intval =1; if(ARGC! =3) {printf ("Please input righ data\n"); printf ("eg:/dev/my_leds <on\ "off>\n"); return 0; } FD= Open (argv[1], O_RDWR); if(fd<0) {printf ("Open failed\n"); return 0; }        if(strcmp (argv[2]," on")==0) {Val=0; }    Else{val=1; } write (FD,&val,4);
Read (fd, &val,1);
printf ("LED status =%d\n", Val); return 0;}

Finish

Linux Embedded Drive Learning path ⑩ character device driver-my_led

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.