Steward
分享是一種喜悅、更是一種幸福
驅動程式 - 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