드라이버 디바이스 모듈


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, 0sizeof(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





출처 : 인지소프트웨어 기술포럼 ( 전유진 강사님 수업자료)

+ Recent posts