[smart.c]
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/delay.h>
#include <asm/mach/map.h> #include <asm/io.h> #include <asm/uaccess.h>
#include "smart.h"
#define SMART_MAJOR 501 #define NAME "SMART_DRV"
#define GPIO_BASE_PA 0x3F200000 #define GPIO_GPFSEL1 (0x04) #define GPIO_GPFSEL2 (0x08) #define GPIO_GPSET0 (0x1C) #define GPIO_GPCLR0 (0x28) #define GPIO_GPLEV0 (0x34)
#define GPIO_FSEL23_OUT (1<<9)
#define GPIO_23 (1<<23)
static void __iomem *gpio_base_va; volatile unsigned *gpfsel1; volatile unsigned *gpfsel2; volatile unsigned *gpset0; volatile unsigned *gpclr0; volatile unsigned *gplev0;
unsigned int old_reg;
static void all_led_onoff(void) { *gpset0 |= GPIO_23; mdelay(500);
*gpclr0 |= GPIO_23; } static void led_on(void) { *gpset0 |= GPIO_23; }
static void led_off(void) { *gpclr0 |= GPIO_23; }
int led_open(struct inode *inode, struct file *filp) { printk("RPi LED init=n");
gpio_base_va = ioremap(GPIO_BASE_PA, 0x60); printk("gpio_base: %p\n", gpio_base_va);
gpfsel1 = (volatile unsigned *)(gpio_base_va + GPIO_GPFSEL1); gpfsel2 = (volatile unsigned *)(gpio_base_va + GPIO_GPFSEL2); gpset0 = (volatile unsigned *)(gpio_base_va + GPIO_GPSET0); gpclr0 = (volatile unsigned *)(gpio_base_va + GPIO_GPCLR0); gplev0 = (volatile unsigned *)(gpio_base_va + GPIO_GPLEV0);
printk("gpfsel2- addr: %p, value: %x\n", gpfsel2, *gpfsel2); old_reg = *gpfsel2; *gpfsel2 |= (GPIO_FSEL23_OUT);
all_led_onoff();
return 0; }
int led_release(struct inode *inode, struct file *filp) { printk("RPi LED exit\n");
all_led_onoff();
*gpfsel2 = old_reg;
iounmap( (void *)gpio_base_va);
return 0; }
ssize_t led_read(struct file *filp, char *user, size_t size, loff_t *pos) { int val; unsigned int led_state = 0;
printk("RPi LED Read\n");
val = *gplev0;
if(val & GPIO_23) led_state |= 1;
return led_state; }
ssize_t led_write(struct file *flip, const char *user, size_t size, loff_t *pos) { unsigned int led_state = 0;
printk("RPi LED Write\n");
get_user(led_state, (unsigned int *)user); printk("led valude: %d\n", led_state);
if(led_state & 1) led_on(); else led_off();
return led_state; }
long led_ioctl(struct file *flip, unsigned int cmd, unsigned long addr) { int size; unsigned int led_state = 0;
printk("RPi LED ioctl\n");
if(_IOC_TYPE(cmd) != LED_IOCTL_MAGIC) return -EINVAL; if(_IOC_NR(cmd) >= LED_IOCTL_MAX) return -EINVAL;
size = _IOC_SIZE(cmd);
if(size) { if(_IOC_DIR(cmd) & _IOC_READ) if(access_ok(VERITY_WRITE, (void *)addr, size) < 0) return -ENOMEM; if(_IOC_DIR(cmd) & _IOC_WRITE) if(access_ok(VERITY_READ, (void *)addr, size) < 0) return -ENOMEM; }
switch(cmd) { case LED_INIT: all_led_onoff(); break; case LED_RED_ON: led_on(); break; case LED_RED_OFF: led_off(); break; case LED_ON_OFF: get_user(led_state, (unsigned int*)addr); printk("led_state: %d\n", led_state);
if(led_state & 1) led_on(); else led_off();
break; } return 0; }
struct file_operations led_fops = { .open = led_open, .release = led_release, .read = led_read, .write = led_write, .unlocked_ioctl = led_ioctl };
static int smart_init(void) { int ret = register_chrdev(SMART_MAJOR, NAME, &led_fops);
if(ret < 0) { printk("RPi LED Driver registration failed: %d\n", ret); } else { printk("RPi LED Driver registration success"); }
return ret; }
static void smart_exit(void) { unregister_chrdev(SMART_MAJOR, NAME); printk("RPi LED Driver unregistered\n");
return; }
module_init(smart_init); module_exit(smart_exit);
MODULE_LICENSE("GPL");
[led_app.c]
#include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h>
#include <fcntl.h> #include <unistd.h> #include <stdio.h>
#include "smart.h"
#define SMART_MAJOR 501 #define SMART_MINOR 100 #define NAME "SMART_DRV"
#define LED_ON 1 #define LED_OFF 0
int main(void) { int iFd; int iRtn=0; dev_t led_dev; unsigned int led_state = 0; char * cpBuf = ""; unsigned char cInput; unsigned int uiCnt; int iBuf = 0;
led_dev = makedev(SMART_MAJOR, SMART_MINOR); mknod(NAME, S_IFCHR|0666, led_dev);
iFd = open(NAME, O_RDWR); printf("led fd: %d\n", iFd);
sleep(1); printf("ioctl: LED_INIT\n"); ioctl(iFd, LED_INIT); sleep(1);
while(1) { if(iRtn == 100) break; printf("Please input command ::\n"); printf("0: LED OFF 1: LED ON 2: LED ON/OFF 3: QUIT\n"); read(0, &cInput, sizeof(char)); switch(cInput) { default: break; case '0': printf("LED OFF\n"); ioctl(iFd, LED_RED_OFF); iRtn = read(iFd, &iBuf, 4); printf("LED state: %X, RTN: %d\n", iBuf, iRtn); sleep(1); break;
case '1': printf("LED ON\n"); ioctl(iFd, LED_RED_ON); iRtn = read(iFd, &iBuf, 4); printf("LED state: %X, RTN: %d\n", iBuf, iRtn); sleep(1); break;
case '2': printf("LED ON/OFF\n"); for(uiCnt = 0; uiCnt < 3; ++uiCnt) { led_state = LED_ON; ioctl(iFd, LED_ON_OFF, &led_state); iRtn = read(iFd, &iBuf, 4); printf("LED state: %X, RTN: %d\n", iBuf, iRtn); sleep(1);
led_state = LED_OFF; ioctl(iFd, LED_ON_OFF, &led_state); iRtn = read(iFd, &iBuf, 4); printf("LED state: %X, RTN: %d\n", iBuf, iRtn); sleep(1); } break;
case '3': iRtn = 100; printf("program terminated\n"); break;
} if( '\n' == getchar() ); putchar('\n'); }
return 0; }
[smart.h]
#ifndef __SMART_H__ #define __SMART_H__
#define LED_IOCTL_MAGIC '1'
#define LED_INIT _IO(LED_IOCTL_MAGIC, 0) #define LED_RED_ON _IO(LED_IOCTL_MAGIC, 1) #define LED_RED_OFF _IO(LED_IOCTL_MAGIC, 2) #define LED_ON_OFF _IOW(LED_IOCTL_MAGIC, 7, int)
#define LED_IOCTL_MAX 8
#endif // __SMART_H__
[Makefile]
obj-m = smart.o
KDIR = /usr/src/linux
PWD = $(shell pwd)
all: @clear $(MAKE) -C $(KDIR) M=$(PWD) modules @ls -al smart.ko
up: @clear @insmod smart.ko @echo ================== dmesg ================= @dmesg | tail @echo ================== dmesg =================
down: @clear @rmmod smart @echo ================== dmesg ================= @dmesg | tail @echo ================== dmesg =================
clean: @clear @rm -rf *.ko @rm -rf *.mod.* @rm -rf .*.cmd @rm -rf *.o @rm -rf modules.order @rm -rf Module.symvers @rm -rf .tmp_versions @ls -al @echo Clean :Done.
|