The char driver code
1: #include <linux/kernel.h> /* We're doing kernel work */2: #include <linux/module.h> /* Specifically, a module */3: #include <linux/fs.h>4: #include <asm/uaccess.h> /* for get_user and put_user */5: #include <linux/slab.h>6:7: #include "chardev.h"8: #define SUCCESS 09: #define DEVICE_NAME "char_dev"10: #define BUF_LEN 8011: #define DEBUG12: /*
13: * Is the device open right now? Used to prevent14: * concurent access into the same device15: */16: int Device_Open = 0;17:18: static int device_open(struct inode *inode, struct file *file)19: {20: printk(KERN_INFO "device_open(%p)\n", file);21:22: /*
23: * currenlty void more then on client at a time24: */25: if (Device_Open)26: {27: return -EBUSY;28: }29: Device_Open++;30: /*
31: * Initialize the message32: */33:34: try_module_get(THIS_MODULE);35: return SUCCESS;36: }37:38: static int device_release(struct inode *inode, struct file *file)39: {40: #ifdef DEBUG41: printk(KERN_INFO "device_release(%p,%p)\n", inode, file);42: #endif43:44: /*
45: * We're now ready for our next caller46: */47: Device_Open--;48:49: module_put(THIS_MODULE);50:51: return SUCCESS;52: }53:54: static void HandleCountFor (void * userData )55: {56: int mFrom ;57:58: int mTo;59:60: int mStep;61:62: int * theKernelSpaceData ;63:64: printk(KERN_ALERT "Enter HandleCountFor 1\n");65:66: theKernelSpaceData = kmalloc(sizeof(int) * 3, GFP_KERNEL);67:68: copy_from_user(theKernelSpaceData, (void *)userData, sizeof(int) * 3);69:70: mFrom = theKernelSpaceData[0];71:72: mTo = theKernelSpaceData[1];73:74: mStep = theKernelSpaceData[2];75:76: printk(KERN_ALERT "Countr From %d mTo %d mStep %d \n" , mFrom, mTo, mStep);77:78: kfree(theKernelSpaceData);79:80: }81:82:83: int device_ioctl(84: struct file *file, /* ditto */85: unsigned int ioctl_num, /* number and param for ioctl */86: unsigned long ioctl_param)87: {88: /*
89: * Switch according to the ioctl called90: */91: switch (ioctl_num) {92: case IOCTL_SET_COUNTFOR_VARIABLES:93:94: HandleCountFor (ioctl_param);95:96: break;97:98: }99:100: return SUCCESS;101: }102:103: /* Module Declarations */104:105: /*
106: * This structure will hold the functions to be called107: * when a process does something to the device we108: * created. Since a pointer to this structure is kept in109: * the devices table, it can't be local to110: * init_module. NULL is for unimplemented functions.111: */112: struct file_operations Fops = {113: .unlocked_ioctl = device_ioctl,114: .open = device_open,115: .release = device_release, /* a.k.a. close */116: };117:118: /*
119: * Initialize the module - Register the character device120: */121: int init_module()122: {123: int ret_val;124: /*
125: * Register the character device (atleast try)126: */127: ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);128:129: /*
130: * Negative values signify an error131: */132: if (ret_val < 0) {133: printk(KERN_ALERT "%s failed with %d\n",134: "Sorry, registering the character device ", ret_val);135: return ret_val;136: }137:138: printk(KERN_INFO "%s The major device number is %d.\n",139: "Registeration is a success", MAJOR_NUM);140: printk(KERN_INFO "If you want to talk to the device driver,\n");141: printk(KERN_INFO "you'll have to create a device file. \n");142: printk(KERN_INFO "We suggest you use:\n");143: printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);144: printk(KERN_INFO "The device file name is important, because\n");145: printk(KERN_INFO "the ioctl program assumes that's the\n");146: printk(KERN_INFO "file you'll use.\n");147:148: return 0;149: }150:151: /*
152: * Cleanup - unregister the appropriate file from /proc153: */154: void cleanup_module()155: {156: unregister_chrdev(MAJOR_NUM, DEVICE_NAME);157: }
The header file
1: #include <linux/ioctl.h>2:3: /*
4: * The major device number. We can't rely on dynamic5: * registration any more, because ioctls need to know6: * it.7: */8: #define MAJOR_NUM 1009:10: #define IOCTL_SET_COUNTFOR_VARIABLES _IOWR(MAJOR_NUM, 3, int * )11:12: /*
13: * The name of the device file14: */15: #define DEVICE_FILE_NAME "char_dev"
The make file
1: obj-m := chardev.o2:3: KDIR := /lib/modules/$(shell uname -r)/build4: PWD := $(shell pwd)5:6: default:
7: $(MAKE) -C $(KDIR) M=$(PWD) modules8:
The test file
1: #include <stdio.h>2: #include <stdlib.h>3: #include <fcntl.h> /* open */
4: #include <unistd.h> /* exit */
5: #include <sys/ioctl.h> /* ioctl */
6:7:8: #include <linux/ioctl.h>9:10: #define MAJOR_NUM 10011:12: #define IOCTL_SET_COUNTFOR_VARIABLES _IOWR(MAJOR_NUM, 3, int * )
13:14: /*
15: * The name of the device file16: */17: #define DEVICE_FILE_NAME "char_dev"
18:19: void ioctl_Send_FromToStep (int file_desc,int pFrom, int pTo, int pStep)20: {21: int theBuf [3];
22:23: theBuf[0] = pFrom;24:25: theBuf[1] = pTo;26:27: theBuf[2] = pStep;28:29: ioctl(file_desc, IOCTL_SET_COUNTFOR_VARIABLES, theBuf);30:31: }32:33: void main()
34: {35: int file_desc, ret_val;
36: char *msg = "Message passed by ioctl\n";37:38: char * theDriver = "/home/zvika/myStaff/CharDrivers/chardev/char_dev3";39:40: printf (theDriver);
41:42: file_desc = open(theDriver, O_RDWR);
43: if (file_desc < 0) {
44: printf("Can't open device file: %s\n", "char_dev");45: exit(-1);
46: }47:48: ioctl_Send_FromToStep (file_desc ,1 , 60 , 4);49:50: close(file_desc);
51: }
The helper bash file to compile and deploy the device
1: #!/bin/bash2:3: echo "use: sudo ./chardev.sh"
4:5: echo "Start deploying"
6:7: # Root or die8: if [ "$(id -u)" != "0" ]9: then10: echo "You must be root to load or unload kernel modules"
11: exit 1
12: fi13:14: make15:16: rmmod chardev.ko17:18: insmod chardev.koThe Result:
Calling: dmesg[ 6385.292794] device_open(ffff88008025b700)
[ 6385.292798] Enter HandleCountFor 1
[ 6385.292801] Countr From 1 mTo 100 mStep 2
zvika@ubuntu:~/myStaff/CharDrivers/PlayWithKernel$Making a device file so a user mode program could access it
zvika@ubuntu:~/myStaff/CharDrivers/PlayWithKernel$ sudo mknod char_dev c 100 0Remove the device file
zvika@ubuntu:~/myStaff/CharDrivers/PlayWithKernel$ unlink char_dev
Deploy the module
zvika@ubuntu:~/myStaff/CharDrivers/PlayWithKernel$ sudo insmod chardev.ko
Remove the deployed module
zvika@ubuntu:~/myStaff/CharDrivers/PlayWithKernel$ sudo rmmod chardev.koResources:
http://www.techrepublic.com/article/loading-and-unloading-modules-in-linux/5031591
http://stackoverflow.com/questions/10713956/failed-to-open-device
http://elinux.org/Debugging_by_printing
http://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/
אין תגובות:
הוסף רשומת תגובה