驅動程式 - Linux Device Driver (LDD) - 使用範例 - Assembly (ARM) - Char Device - Class Device



除了使用mknod工具建立Symbloic Link之外,字元驅動程式也可以自行建立這個Symbolic Link

建立步驟:

1. alloc_chrdev_region()
2. __class_create()
3. device_create()
4. cdev_init()
5. cdev_add()

釋放步驟:

1. device_destroy()
2. cdev_del()
3. class_destroy()
4. unregister_chrdev_region()

ldd.S

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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    .global init_module
    .global cleanup_module
 
    .section .modinfo, "ae"
__UNIQUE_ID_0: .asciz "license=GPL"
__UNIQUE_ID_1: .asciz "author=Steward Fu"
__UNIQUE_ID_2: .asciz "description=Linux Driver"
 
    .equ cdev.kobj,  0
    .equ cdev.owner, 36
    .equ cdev.ops,   40
    .equ cdev.list,  44
    .equ cdev.dev,   52
    .equ cdev.count, 56
 
    .struct 0
cdev_s:
    c0: .struct . + 36
    c1: .struct . + 4
    c2: .struct . + 4
    c3: .struct . + 8
    c4: .struct . + 4
    c5: .struct . + 4
cdev_e:
cdev_l = cdev_e - cdev_s
 
    .equ file_operations.owner,             0
    .equ file_operations.llseek,            4
    .equ file_operations.read,              8
    .equ file_operations.write,             12
    .equ file_operations.read_iter,         16
    .equ file_operations.write_iter,        20
    .equ file_operations.iterate,           24
    .equ file_operations.iterate_shared,    28
    .equ file_operations.poll,              32
    .equ file_operations.unlocked_ioctl,    36
    .equ file_operations.compat_ioctl,      40
    .equ file_operations.mmap,              44
    .equ file_operations.open,              48
    .equ file_operations.flush,             52
    .equ file_operations.release,           56
    .equ file_operations.fsync,             60
    .equ file_operations.fasync,            64
    .equ file_operations.lock,              68
    .equ file_operations.sendpage,          72
    .equ file_operations.get_unmapped_area, 76
    .equ file_operations.check_flags,       80
    .equ file_operations.setfl,             84
    .equ file_operations.flock,             88
    .equ file_operations.splice_write,      92
    .equ file_operations.splice_read,       96
    .equ file_operations.setlease,          100
    .equ file_operations.fallocate,         104
    .equ file_operations.show_fdinfo,       108
    .equ file_operations.mmap_capabilities, 112
    .equ file_operations.copy_file_range,   116
    .equ file_operations.clone_file_range,  120
    .equ file_operations.dedupe_file_range, 124
 
    .struct 0
file_operations_s:
    i0: .struct . + 4
    i1: .struct . + 4
    i2: .struct . + 4
    i3: .struct . + 4
    i4: .struct . + 4
    i5: .struct . + 4
    i6: .struct . + 4
    i7: .struct . + 4
    i8: .struct . + 4
    i9: .struct . + 4
    i10: .struct . + 4
    i11: .struct . + 4
    i12: .struct . + 4
    i13: .struct . + 4
    i14: .struct . + 4
    i15: .struct . + 4
    i16: .struct . + 4
    i17: .struct . + 4
    i18: .struct . + 4
    i19: .struct . + 4
    i20: .struct . + 4
    i21: .struct . + 4
    i22: .struct . + 4
    i23: .struct . + 4
    i24: .struct . + 4
    i25: .struct . + 4
    i26: .struct . + 4
    i27: .struct . + 4
    i28: .struct . + 4
    i29: .struct . + 4
    i30: .struct . + 4
    i31: .struct . + 4
file_operations_e:
file_operations_l = file_operations_e - file_operations_s
 
    .section .data
base:      .dcb 4
mycdev:    .space cdev_l
myfops:    .space file_operations_l
chr_name:  .asciz "myfile"
open_msg:  .asciz "myopen\n"
close_msg: .asciz "myclose\n"
myclass:   .dcb 4
 
    .align 2
    .section .text
myopen:
    push {lr}
    ldr r0, =open_msg
    bl printk
    mov r0, #0
    pop {pc}
 
myclose:
    push {lr}
    ldr r0, =close_msg
    bl printk
    mov r0, #0
    pop {pc}
 
init_module:
    push {r4, r5, lr}
 
    ldr r0, =myfops
    add r1, r0, #file_operations.open
    ldr r2, =myopen
    str r2, [r1]
    add r1, r0, #file_operations.release
    ldr r2, =myclose
    str r2, [r1]
 
    ldr r0, =base
    mov r1, #0
    mov r2, #1
    ldr r3, =chr_name
    bl alloc_chrdev_region
    ldr r4, =base
 
    mov r0, #0
    ldr r1, =chr_name
    ldr r2, =myclass
    bl __class_create
    ldr r1, =myclass
    str r0, [r1]
 
    mov r1, #0
    ldr r2, [r4]
    mov r3, #0
    ldr r5, =chr_name
    push {r5}
    bl device_create
    pop {r5}
 
    ldr r0, =mycdev
    ldr r1, =myfops
    bl cdev_init
 
    ldr r0, =mycdev
    ldr r1, [r4]
    mov r2, #1
    bl cdev_add
 
    mov r0, #0
    pop {r4, r5, pc}
 
cleanup_module:
    push {lr}
    ldr r0, =myclass
    ldr r0, [r0]
    ldr r1, =base
    ldr r1, [r1]
    bl device_destroy
 
    ldr r0, =mycdev
    bl cdev_del
 
    ldr r0, =myclass
    ldr r0, [r0]
    bl class_destroy
 
    ldr r0, =base
    ldr r0, [r0]
    mov r1, #1
    bl unregister_chrdev_region
    pop {pc}
    .end

init_module: 建立字元驅動程式
myopen: 對應User Application的open()
myclose: 對應User Application的close()
cleanup_module: 刪除字元驅動程式

安裝驅動

# insmod /boot/main.ko 

由於使用class device,因此,Symbolic已經建立完成,不再需要使用mknod建立

# ls -al /dev/myfile
    crw-r--r--    1 root     root      243,   0 Jan  1 00:00 /dev/myfile

開啟裝置

# echo "" > /dev/myfile
    myopen
    sh: write error: Invalid argument myclose