In Linux Device Driver light up an LED, write a header file such as ioctl_c.h. In this article, we will continue to use this file. The Code is as follows:
# Ifndef _ ioctl_c_h __< br/> # DEFINE _ ioctl_c_h __< br/> typedef struct gpio_data_t <br/>{< br/> unsigned int port; <br/> unsigned int bit; <br/> unsigned int value; <br/> unsigned int V; <br/>} gpio_data_s; <br/> # define gpio_ioc_magic 12 // documentation/ioctl-number.txt <br/> # define gpio_io_set _ Iow (gpio_ioc_magic, 0, sizeof (gpio_data_s )) <br/> # define writable _ IOWR (gpio_ioc_magic, 1, sizeof (gpio_data_s) <br/> # define gpio_io_write _ Iow (gpio_ioc_magic, 2, sizeof (random )) <br/> # define gpio_io_read _ IOWR (gpio_ioc_magic, 3, sizeof (gpio_data_s) <br/> # endif
Then there is the driver module program, the Code is as follows:
# Include <Linux/types. h> <br/> # include <Linux/Fs. h> <br/> # include <Linux/mm. h> <br/> # include <Linux/errno. h> <br/> # include <Linux/module. h> <br/> # include <Linux/moduleparam. h> <br/> # include <Linux/kernel. h> <br/> # include <ASM/uaccess. h> <br/> # include <Linux/cdev. h> <br/> # include <Linux/IOCTL. h> <br/> # include <Linux/slab. h> <br/> # include <Linux/fcntl. h> <br/> # include <ASM/segment. h> <br/> # include <SM/Io. h> <br/> # include <ASM/ARCH/regs-gpio.h> <br/> # include "ioctl_c.h" <br/> unsigned int test_major = 253; <br/> unsigned int test_minor = 0; <br/> struct cdev cdevc; <br/> module_license ("dual BSD/GPL"); <br/> gpio_data_s IOCTL; <br/> static int read_test (struct file * file, char * Buf, int count, loff_t * f_pos) <br/>{< br/> printk ("/n read_test"); <br/> printk ("% d", count); <br/> return count; <br/>}< br/> stati C int write_test (struct file * file, const char * Buf, int count, loff_t * f_pos) <br/>{< br/> printk ("/n write_test "); <br/> return count; <br/>}< br/> static void gpio_cfg () <br/>{< br/> size_t data; <br/> printk ("gpio_cfg start! /N "); <br/> DATA = _ raw_readl (IOCTL. Port * 0x10 + s3c2410_gpacon); <br/> Data & = ~ (3 <2 * IOCTL. bit); <br/> data | = (IOCTL. value <2 * IOCTL. bit); <br/>__ raw_writel (data, IOCTL. port * 0x10 + s3c2410_gpacon); <br/>}< br/> static void gpio_read () <br/>{< br/> printk ("gpio_read start !! /N "); <br/> size_t data_con, data_dat; <br/> data_con = _ raw_readl (IOCTL. port * 0x10 + s3c2410_gpacon); <br/> data_dat = _ raw_readl (IOCTL. port * 0x10 + s3c2410_gpadat); <br/> printk ("% LD/n % LD/N", data_con, data_dat ); <br/>}< br/> static void gpio_write () <br/>{< br/> printk ("gpio-Write Start !! /N "); <br/> size_t data; <br/> DATA = _ raw_readl (IOCTL. port * 0x10 + s3c2410_gpadat); <br/> Data & = ~ (1 <IOCTL. bit); <br/> data | = (IOCTL. v <IOCTL. bit); <br/>__ raw_writel (data, IOCTL. port * 0x10 + s3c2410_gpadat); <br/>}< br/> static int ioctl_test (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long Arg) <br/>{< br/> If (copy_from_user (& ioctl, ARG, sizeof (gpio_data_s) <br/>{< br/> return-efault; <br/>}< br/> printk ("/n ioctl_test"); <br/> switch (CMD) <br/>{< br/> case gpio_io_set: gpio_cfg (); break; <br/> // case gpio_io_get:; break; <br/> case gpio_io_write: gpio_write (); break; <br/> case gpio_io_read: gpio_read (); break; <br/> default: break; <br/>}< br/> return cmd; <br/>}< br/> static int open_test (struct inode * inode, struct file * file) <br/>{< br/> printk ("/n open_test"); <br/> return 0; <br/>}< br/> static void release_test (struct inode * inode, struct file * file) <br/>{< br/> printk ("/n release_test"); <br/>}< br/> struct file_operations test_fops ={ <br/>. owner = this_module, <br/>. read = read_test, <br/>. write = write_test, <br/>. open = open_test, <br/>. IOCTL = ioctl_test, <br/>. release = release_test, <br/>}; <br/> int simple_c_init_module (void) <br/>{< br/> int result; <br/> dev_t Dev = 0; </P> <p> Dev = mkdev (test_major, test_minor); <br/> result = register_chrdev_region (Dev, 1, "test "); </P> <p> printk ("Major = % d, minor = % d/N", test_major, test_minor ); </P> <p> If (result <0) <br/> {<br/> printk (kern_info "test: Can't Get Major number/N "); <br/> return result; <br/>}</P> <p> cdev_init (& cdevc, & test_fops); <br/> cdevc. owner = this_module; <br/> cdevc. ops = & test_fops; <br/> result = cdev_add (& cdevc, Dev, 1); <br/> If (result) <br/> printk ("error % d adding test", result); <br/> return 0; <br/>}< br/> void simple_c_cleanup_module (void) <br/>{ <br/> dev_t Dev = 0; <br/> Dev = mkdev (test_major, test_minor); <br/> cdev_del (& cdevc ); <br/> unregister_chrdev_region (Dev, 1); <br/>}< br/> module_init (simple_c_init_module); <br/> module_exit (simple_c_cleanup_module );
Here only the difference with the previous Module Program is described. The first is the ioctl_test function.
Static int ioctl_test (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long Arg)
{
If (copy_from_user (& ioctl, ARG, sizeof (gpio_data_s )))
{
Return-efault;
}
Printk ("/n ioctl_test ");
Switch (CMD)
{
Case gpio_io_set: gpio_cfg (); break;
// Case gpio_io_get:; break;
Case gpio_io_write: gpio_write (); break;
Case gpio_io_read: gpio_read (); break;
Default: break;
}
Return cmd;
}
There are more
Case gpio_io_set: gpio_cfg (); break;
Case gpio_io_write: gpio_write (); break;
Case gpio_io_read: gpio_read (); break;
From the names of the three functions, we can know that they are Io configuration and read/write operations. How can we implement them? transfer them to these three functions immediately.
Static void gpio_cfg ()
{
Size_t data;
Printk ("gpio_cfg start! /N ");
Data = _ raw_readl (IOCTL. Port * 0x10 + s3c2410_gpacon );
Data & = ~ (3 <2 * IOCTL. Bit );
Data | = (IOCTL. value <2 * IOCTL. Bit );
_ Raw_writel (data, IOCTL. Port * 0x10 + s3c2410_gpacon );
}
Function Description: This function is used to configure gpgcon.
Static void gpio_read ()
{
Printk ("gpio_read start !! /N ");
Size_t data_con, data_dat;
Data_con = _ raw_readl (IOCTL. Port * 0x10 + s3c2410_gpacon );
Data_dat = _ raw_readl (IOCTL. Port * 0x10 + s3c2410_gpadat );
Printk ("% LD/n % LD/N", data_con, data_dat );
}
Function Description: Read gpio functions.
Static void gpio_write ()
{
Printk ("gpio-Write Start !! /N ");
Size_t data;
Data = _ raw_readl (IOCTL. Port * 0x10 + s3c2410_gpadat );
Data & = ~ (1 <IOCTL. Bit );
Data | = (IOCTL. v <IOCTL. Bit );
_ Raw_writel (data, IOCTL. Port * 0x10 + s3c2410_gpadat );
}
Function Description: Write gpio functions.
The following is an application program. Writing an application becomes much more convenient. You need to configure Io before reading and writing.
# Include <stdio. h> <br/> # include <sys/types. h> <br/> # include <sys/STAT. h> <br/> # include <fcntl. h> <br/> # include <unistd. h> <br/> # include <Linux/IOCTL. h> <br/> # include ".. /ioctl_c.h "<br/> gpio_data_s io_ctl; <br/> void main (void) <br/>{< br/> int testdev; <br/> int I; <br/> char Buf [10]; <br/> testdev = open ("/dev/test", o_rdwr); <br/> If (testdev =-1) <br/>{< br/> printf ("cann't open file ..... /n "); <br/> exit (0); <br/>}< br/> printf (" Buf = 0x % x/N ", Buf ); <br/> Read (testdev, Buf, 10); <br/> write (testdev, Buf, 1); <br/> while (1) <br/>{< br/> io_ctl.port = 6; <br/> io_ctl.bit = 5; <br/> io_ctl.value = 1; <br/> io_ctl.v = 0; <br/> IOCTL (testdev, gpio_io_set, & io_ctl); <br/> IOCTL (testdev, gpio_io_write, & io_ctl); <br/> IOCTL (testdev, gpio_io_read, & io_ctl); <br/> io_ctl.port = 6; <br/> io_ctl.bit = 6; <br/> io_ctl.value = 1; <br/> io_ctl.v = 1; <br/> IOCTL (testdev, gpio_io_set, & io_ctl); <br/> IOCTL (testdev, gpio_io_write, & io_ctl); <br/> IOCTL (testdev, gpio_io_read, & io_ctl); <br/> sleep (1); <br/> io_ctl.port = 6; <br/> io_ctl.bit = 6; <br/> io_ctl.value = 1; <br/> io_ctl.v = 0; <br/> IOCTL (testdev, gpio_io_set, & io_ctl); <br/> IOCTL (testdev, gpio_io_write, & io_ctl ); <br/> IOCTL (testdev, gpio_io_read, & io_ctl); <br/> io_ctl.port = 6; <br/> io_ctl.bit = 5; <br/> io_ctl.value = 1; <br/> io_ctl.v = 1; <br/> IOCTL (testdev, gpio_io_set, & io_ctl); <br/> IOCTL (testdev, gpio_io_write, & io_ctl ); <br/> IOCTL (testdev, gpio_io_read, & io_ctl); <br/> sleep (1); <br/>}< br/> // IOCTL (testdev, gpio_io_write, sizeof (gpio_data_s); <br/> // IOCTL (testdev, gpio_io_read, sizeof (gpio_data_s); <br/> printf ("% s", Buf ); <br/> // for (I = 0; I <10; I ++) <br/> // printf ("[% d]/n ", buf [I]); <br/> close (testdev ); <br/>}< br/>/* <br/> mknod/dev/test C 253 0 <br/> */