드라이버 디바이스 모듈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/gpio.h> #include <linux/delay.h> #include <linux/kthread.h> #include <asm/siginfo.h> /* siginfo */ #include <linux/rcupdate.h> /* rcu_read_lock */ #define DEBUG 1 #define SIG_TEST 44 #define PIR 24 struct siginfo info; struct task_struct *t; struct task_struct *ut; pid_t pid = 0; // 파일 읽기 함수 static ssize_t drv_hw_pir_read(struct file * file, char * buf, size_t length, loff_t * ofs) { int ret; int stat; stat = gpio_get_value(PIR); ret = copy_to_user(buf, &stat, sizeof(stat)); #if DEBUG printk("### [%s] stat = %d\n", __FUNCTION__, stat); #endif return (ret == 0) ? sizeof(stat) : ret; } // 파일 쓰기 함수 static ssize_t drv_sig_write(struct file * file, const char * buf, size_t length, loff_t * ofs) { int ret; // 유저로부터 pid를 받아온다. buf 를 pid에 복사 ret = copy_from_user(&pid, buf, length); printk("%d\n", pid); if(ret != 0){ printk("%s: pid = %d \n",__FUNCTION__, pid); return -EFAULT; } return length; } static struct file_operations drv_hw_pir_fops = { .owner = THIS_MODULE, .read = drv_hw_pir_read, .write = drv_sig_write, }; static struct miscdevice drv_hw_pir_driver = { .minor = MISC_DYNAMIC_MINOR, .name = "drv_hw_pir", .fops = &drv_hw_pir_fops, }; static int my_send_sig(int gpio_val) { int ret; memset(&info, 0, sizeof(struct siginfo)); //siginfo 구조체 초기화. info.si_signo = SIG_TEST; //시그널 번호 설정. info.si_code = SI_QUEUE; info.si_int = gpio_val; // gpio 값 입력 rcu_read_lock(); // pid_task 함수를 이용하여 task_struct 구조체 리턴. ut = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID); if(ut == NULL){ printk("no such pid\n"); rcu_read_unlock(); return -ENODEV; } rcu_read_unlock(); //siginfo 구조체를 이용하여 시그널 보내기 ret = send_sig_info(SIG_TEST, &info, ut); /* send the signal */ if (ret < 0) { printk("error sending signal\n"); return ret; } return 0; } int pir_thread(void *data) { int stat; while(!kthread_should_stop()) { // gpio 값 가져오기 stat = gpio_get_value(PIR); // gpio 값이 1 이라면 if (stat == 1) { my_send_sig(stat); } // printk("pir state : %d\n",stat); ssleep(1); } printk("stop thread...\n"); return 0; } static int drv_hw_pir_init(void) { int ret; printk("#1 \n"); // 쓰래드 실행. ut = kthread_run(pir_thread, NULL, "my_thread"); printk("#2 \n"); // 24 gpio 할당 ret = gpio_request(PIR, "gpio pir"); printk("#3 \n"); if(ret) printk("#### FAILED Request gpio %d. error : %d \n", PIR, ret); else gpio_direction_input(PIR); // 24 gpio 입력으로 설정 // 미스크 디바이스 드라이버 노드 생성 return misc_register(&drv_hw_pir_driver); } static void drv_hw_pir_exit(void) { gpio_free(PIR); kthread_stop(ut); misc_deregister(&drv_hw_pir_driver); } module_init(drv_hw_pir_init); module_exit(drv_hw_pir_exit); MODULE_AUTHOR("PlanX Studio"); MODULE_DESCRIPTION("drv_hw_pir"); MODULE_LICENSE("Dual BSD/GPL"); | cs |
유저 어플리케이션
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <fcntl.h> #define NODE_NAME "/dev/drv_hw_pir" #define SIG_TEST 44 static void receive_signal(int n, siginfo_t *info, void *unused) { printf("recive_signal %d\n", info->si_int); } int main(int argc, char * argv[]) { struct sigaction sig; int status, i, fd; pid_t pid; // sigaction 구조체에 함수 들록 sig.sa_sigaction = receive_signal; sig.sa_flags = SA_SIGINFO; // 44번으로 sigaction 구조체 등록 // 시그널 생성시 receive_signal 함수 콜 sigaction(SIG_TEST , &sig, NULL); fd = open(NODE_NAME, O_RDWR); if (fd < 0) { perror("sign open failed"); return 0; } // pid 가져오기 pid = getpid(); printf("user pid = %d\n",pid); write(fd, &pid, sizeof(pid)); while(1) pause(); close(fd); exit(0); } | cs |
출처 : 인지소프트웨어 기술포럼 ( 전유진 강사님 수업자료)
'임베디드 > 디바이스 드라이버' 카테고리의 다른 글
디바이스 드라이버 모션센터 인터럽트 예 (0) | 2018.01.02 |
---|---|
디바이스 드라이버 인터럽트 (0) | 2017.12.28 |
디바이스 드라이버 GPIO 모션 센서 예제 (0) | 2017.12.28 |
디바이스 드라이버 GPIO 조이스틱 예제 (0) | 2017.12.28 |
Misc 디바이스 드라이버2 (0) | 2017.12.27 |