On 8/14/08, Bartek Dolewski <doles2@xxxxxxxxx> wrote:> Hi all> I`ve written my first character device which can read and write. I think> that read and write functions are ok but it seems to be some errors during> initialization my device. Here is the source code:> #include <linux/kernel.h>> #include <linux/module.h>> #include <linux/init.h>> #include <linux/fs.h>> #include <linux/cdev.h>> #include <asm/uaccess.h>>> static int FirstModuleInit(void);> static void FirstModuleExit(void);>> static int FirstModule_Open(struct inode *, struct file *);> static int FirstModule_Release(struct inode *, struct file *);> static ssize_t FirstModule_Read(struct file *, char *, size_t, loff_t *);> static ssize_t FirstModule_Write(struct file *, const char *, size_t,> loff_t *);>> #define DEV_LICENSE "GPL"> #define SUCCESS 0> #define DEVICE_NAME "mydevice"> #define BUF_LEN 128>> static int Major;> static int Device_Open = 0;>> static char msg[BUF_LEN];> static char *msg_Ptr;>> static struct cdev* my_cdev;Should be not poiter but normal structure:static struct cdev my_cdev; >> static struct file_operations fops = {> .read = FirstModule_Read,> .write = FirstModule_Write,> .open = FirstModule_Open,> .release = FirstModule_Release> };>> static int FirstModuleInit(void)> {> int result, err;> dev_t dev = 0;>> result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);> Major = MAJOR(dev);>> if (result < 0 ) {> printk(KERN_WARNING "First: unable to get major number-> %d",Major);> return result;> }>Than here small modifications:> cdev_init(my_cdev, &fops);cdev_init(&my_cdev, &fops); > my_cdev->owner = THIS_MODULE;my_cdev.owner = THIS_MODULE;> my_cdev->ops = &fops;my_cdev.ops = &fops; > err = cdev_add(my_cdev, dev, 1);err = cdev_add(&my_cdev, dev, 1);>> if (err)> printk(KERN_NOTICE "Error during adding %s device", DEVICE_NAME);>> printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);> printk(KERN_INFO "My dev = %d", dev);> printk(KERN_INFO "'mknod /dev/%s c %d 0'\n", DEVICE_NAME, Major);>> return SUCCESS;> }>> static void FirstModuleExit(void)> {> cdev_del(my_cdev);cdev_del(&my_cdev);> }>> static int FirstModule_Open(struct inode *inode, struct file *file)> {> static int counter = 0;> if(Device_Open)> return -EBUSY;>> Device_Open++;> sprintf(msg, "I`ve already told you %d times Hello World!\n",> counter++);> msg_Ptr = msg;> try_module_get(THIS_MODULE);>> return SUCCESS;> }>> static int FirstModule_Release(struct inode *inode, struct file *file)> {> Device_Open--;> module_put(THIS_MODULE);> return 0;> }>> static ssize_t FirstModule_Read(struct file *flip, char *buffer, size_t> length, loff_t *offset)> {> int bytes_read = 0;> if(*msg_Ptr == 0)> return 0;>> while(length && *msg_Ptr){> put_user( *(msg_Ptr++), buffer++);> length--;> bytes_read++;> }> return bytes_read;> }>> static ssize_t FirstModule_Write(struct file *flip, const char *buffer,> size_t length, loff_t *off)> {> int i;> for(i=0; i < length && i < BUF_LEN; i++)> get_user(msg[i],buffer+i);> msg_Ptr = msg;> printk(KERN_INFO "Your message from Userland is: %s",msg);> return i;> }>> /*licence of the module*/> module_init(FirstModuleInit);> module_exit(FirstModuleExit);>> MODULE_LICENSE(DEV_LICENSE);> MODULE_AUTHOR("Bartosz Dolewski");> MODULE_DESCRIPTION("Simple char device ");> MODULE_SUPPORTED_DEVICE("TestDevice");>> I guess that I made something wrong with major and minor numbers or with> dev_t dev. I just wanted to dynamically register this device not at compile> time. Here is dmesg output message:>> RIP: 0010:[<ffffffff803142e0>] [<ffffffff803142e0>] memset_c+0x20/0x30> RSP: 0018:ffff81002cca7e20 EFLAGS: 00010212> RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000000000000d> RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000> RBP: ffff81002fecc6c0 R08: 0000000000000000 R09: 0000000000000000> R10: 0000000000200200 R11: 0000000000000001 R12: ffffffff88384ba0> R13: 0000000000000011 R14: ffffc200004f3b98 R15: 0000000000000001> FS: 00002b2c2017a6e0(0000) GS:ffff8100375f8ac0(0000) knlGS:0000000000000000> CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b> CR2: 0000000000000000 CR3: 0000000036098000 CR4: 00000000000006e0> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400> Process insmod (pid: 3325, threadinfo ffff81002cca6000, task> ffff8100376a9800)> Stack: ffffffff8029a6cf 0000000000000001 0000000000000000 ffffffff88384c80> ffffffff88384102 0000000000000011 0fa00000004f3b98 ffffffff88384c80> ffffffff80256c30 0000000000002ac7 0000000000000000 0000000000000000> Call Trace:> [<ffffffff8029a6cf>] cdev_init+0x19/0x3e> [<ffffffff88384102>] :first:FirstModuleInit+0x61/0xe4> [<ffffffff80256c30>] sys_init_module+0x16e3/0x1821> [<ffffffff8020be2e>] system_call+0x7e/0x83>>> Code: f3 48 ab 44 89 c1 f3 aa 4c 89 c8 c3 0f 1f 40 00 eb ce 66 66> RIP [<ffffffff803142e0>] memset_c+0x20/0x30> RSP <ffff81002cca7e20>> CR2: 0000000000000000> ---[ end trace adc72f43f989e1df ]---> Of course insmod failed with "Terminated" message. I was learning from> http://tldp.org/LDP/lkmpg/2.6/html/x569.html but as far as> I know there are old way (register_chrdev()). I would like to use new> structure cdev but I can see it is to sophisticated for me.> Thanks for any help> --> -----BEGIN GEEK CODE BLOCK-----> GCS d- s:- a--- C+++ P L+++>+++++ E---- W+ N+ o? K- w--- O- M- V? PS++ PE++> Y PGP++ t--- 5? X R tv-- b+ DI+ D- G++ e- h! !r(--) !z+> ------END GEEK CODE BLOCK------> Than it works for 100% (I test it). Enjoy Marek-- Marek BeliškoRuská Nová Ves 21908005 PrešovSlovakiahttp://binaural.ifastnet.com��.n��������+%����w�j)p���{.n����z�ޖw�n'���q���b�������v��m�����Y�����