LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-21-2006, 09:21 AM   #1
tomkaith13
LQ Newbie
 
Registered: Nov 2006
Posts: 6

Rep: Reputation: 0
Doubt in char device driver for linux 2.6


Hi everyone,

I am a newbie to the world of device drivers...
I tried my hand on character dev driver .. it doesn go smooth..


The problem is while tryin to read from the dev:

Say

cat /dev/scull ( i am includin the program later)

i get the followin:


================ error logged in /var/log/messages===============
Nov 21 20:06:46 datacom kernel: Unable to handle kernel NULL pointer dereference at virtual address 00000000
Nov 21 20:06:46 datacom kernel: printing eip:
Nov 21 20:06:46 datacom kernel: c01df982
Nov 21 20:06:46 datacom kernel: *pde = 00000000
Nov 21 20:06:46 datacom kernel: Oops: 0002 [#1]
Nov 21 20:06:46 datacom kernel: last sysfs file: /block/ram0/dev
Nov 21 20:06:46 datacom kernel: Modules linked in: chardev(U) i915 drm ntfs(U) parport_pc lp parport autofs4 sunrpc video button battery ac ipv6 uhci_hcd ehci_hcd hw_random i2c_i801 i2c_core snd_intel8x0 snd_ac97_codec snd_ac97_bus snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd soundcore snd_page_alloc e100 mii floppy dm_snapshot dm_zero dm_mirror ext3 jbd dm_mod
Nov 21 20:06:46 datacom kernel: CPU: 0
Nov 21 20:06:46 datacom kernel: EIP: 0060:[<c01df982>] Tainted: P VLI
Nov 21 20:06:46 datacom kernel: EFLAGS: 00010213 (2.6.15-1.1831_FC4)
Nov 21 20:06:46 datacom kernel: EIP is at vsnprintf+0x54/0x62d
Nov 21 20:06:46 datacom kernel: eax: 00000049 ebx: 00000000 ecx: e08471f8 edx: 7fffffff
Nov 21 20:06:46 datacom kernel: esi: 00000000 edi: ffffffff ebp: ddd9f124 esp: d49cae94
Nov 21 20:06:46 datacom sshd(pam_unix)[2200]: session closed for user bibin
Nov 21 20:06:46 datacom kernel: ds: 007b es: 007b ss: 0068
Nov 21 20:06:46 datacom su(pam_unix)[2237]: session closed for user root
Nov 21 20:06:46 datacom kernel: Process cat (pid: 2543, threadinfo=d49ca000 task=d76c1ab0)
Nov 21 20:06:46 datacom kernel: Stack: badc0ded df08c000 df0c1eb0 00008001 00000000 d7267580 00000000 00000000
Nov 21 20:06:46 datacom kernel: 00000000 c01dcc97 00000000 c016350d da43bd00 00000000 e08471f8 00000000
Nov 21 20:06:46 datacom kernel: e0847d80 00000000 ddd9f124 c01e0006 d49caef4 d49caef4 e0847054 00000000
Nov 21 20:06:47 datacom kernel: Call Trace:
Nov 21 20:06:47 datacom kernel: [<c01dcc97>] kobject_get+0xf/0x13 [<c016350d>] cdev_get+0xe/0x4c
Nov 21 20:06:47 datacom kernel: [<c01e0006>] sprintf+0x20/0x24 [<e0847054>] device_open+0x54/0x79 [chardev]
Nov 21 20:06:47 datacom kernel: [<c01635f8>] chrdev_open+0x83/0x146 [<c0163575>] chrdev_open+0x0/0x146
Nov 21 20:06:47 datacom kernel: [<c015a3fe>] __dentry_open+0xa8/0x1d2 [<c015a5ff>] nameidata_to_filp+0x31/0x3a
Nov 21 20:06:47 datacom kernel: [<c015a557>] filp_open+0x2f/0x35 [<c013c3a4>] audit_syscall_entry+0x10b/0x15e
Nov 21 20:06:47 datacom kernel: [<c015a710>] get_unused_fd+0xac/0xce [<c013c7f4>] audit_getname+0x6c/0xd1
Nov 21 20:06:47 datacom kernel: [<c015a7f1>] do_sys_open+0x31/0xad [<c0102e75>] syscall_call+0x7/0xb

==============================================================




Here is the program:
Kindly request y'all to go thro and help me out:

==================Driver code=================================
#include <linux/module.h>
#include <linux/init.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/kobj_map.h>
#include <linux/cdev.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
#include <linux/cdev.h>

#define DEVICE_NAME "scull"
#define SUCCESS 0
#define FAIL -1
#define SIZE 100


static int Major, Minor;
static int device_opened = 0;

static char MSGBUF[SIZE];
static char *msg_ptr;
static char *msg;


static int device_open (struct inode *in, struct file *filp);
static int device_release (struct inode *in, struct file *filp);
static int device_read(struct file *filp,char *msg_ptr,int count,int *offp);
//static int device_write(struct file *filp,char *msg_ptr,int count,int *offp);




static int
device_open (struct inode *in, struct file *filp)
{
if (device_opened)
{
printk(KERN_ALERT "Driver is in use");
return -EBUSY;
}
device_opened++;

if(!try_module_get(THIS_MODULE))
return -EBUSY;

sprintf(msg,"Initial Driver Content !!");

printk("<1> %s",msg);

msg_ptr = msg;


return SUCCESS;
}



static int
device_release (struct inode *in, struct file *filp)
{

device_opened--;
module_put(THIS_MODULE);
return SUCCESS;
}




static struct file_operations scull_fops = {
.open = device_open,
.release = device_release,
.owner = THIS_MODULE,
.read = device_read,
// .write = device_write,
};



struct cdev scull_cdev ;
int dev_num;






static int scull_init (void)
{
/* dev_t dev=MKDEV(63,0); */
dev_t dev;
int retval;


retval=alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
if(!retval)
{
Major=MAJOR(dev);
Minor=MINOR(dev);
}
else {
return FAIL;
}


printk("MAJOR(dev)=%d\n", MAJOR(dev));

printk("<1> Before cdev_init\n");

printk("<1> after cdev_init:\n");

cdev_init(&scull_cdev,&scull_fops);

// dev_num=MKDEV(Major,Minor);

retval=cdev_add(&scull_cdev,dev,1);
if(retval)
{
cdev_del(&scull_cdev);
unregister_chrdev_region(dev, 1);
printk("<1> Error in cdev_add:");
return -EBUSY;
}
printk ("<1> scull_init was a Success and the major device number is %d \n", Major);
return 0;


}










static int device_read(struct file *filp,char *msgusr,int count,int *offp)
{
int i;
unsigned long ret;

msgusr=NULL;
count=25;

if(*msg_ptr == 0)
return 0;

printk ("<1> \n\n Here we are Reading!!\n");

ret= copy_to_user(msgusr,msg_ptr,count);

if(ret <= 0)
{
printk("<1> Error in reading !!");
return -EFAULT;
}

// for(i=0;i<count;i++)
// printk("<1> The Msg read from the char driver is %c\n",*(msgusr++) );

return SUCCESS;
}




static void scull_exit (void)
{
printk ("<1> Removing scull drivers from /proc/devices\n");
cdev_del(&scull_cdev);
unregister_chrdev_region (MKDEV(Major,0), 1);
}


module_init (scull_init);
module_exit (scull_exit);
===============================================================
 
Old 11-21-2006, 09:34 AM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Code:
sprintf(msg,"Initial Driver Content !!");
The first error message is explained by the above code. You are asking sprintf to write to a string which has no storage allocated for it. The char pointer 'msg' is not initialized. Start by fixing that. I didn't look any further, so there may be other problems. This is not a problem specific to kernel/driver coding.

--- rod.
 
Old 11-21-2006, 09:43 AM   #3
tomkaith13
LQ Newbie
 
Registered: Nov 2006
Posts: 6

Original Poster
Rep: Reputation: 0
thanks a lot !!!

I never thought abt the sprintf causin the fuzz...
 
Old 11-22-2006, 03:59 AM   #4
tomkaith13
LQ Newbie
 
Registered: Nov 2006
Posts: 6

Original Poster
Rep: Reputation: 0
The read in char driver

hi,

The sprintf issue is solved ..
The module is working fine except that it is not reading ..

If i try a cat /dev/scull,this is wat i get
cat: /dev/scull: Bad address

if i check the /var/log/messages ,this is the message:

Nov 22 15:05:12 datacom kernel: Here we are Reading!!
Nov 22 15:05:14 datacom kernel: no of bytes read :4096<1> Error in reading !!





Here is the read function alone:

====================Read function alone ==================
static int device_read(struct file *filp,char *msgusr,int count,int *offp)
{
int i;
unsigned long ret;

// msgusr=NULL;
//count=25;

if(*msg_ptr == 0)
return 0;

//while (data_not_ready) {
//interruptible_sleep_on(&scull_wait);
//}


printk ("<1> \n\n Here we are Reading!!\n");


ret= copy_to_user(msgusr,*(msg_ptr),count);

// ret is 4096 on execution, and not zero

printk("<1> no of bytes read :%d",ret);

if(ret != 0)
{
printk("<1> Error in reading !!");
return -EFAULT;
}


return SUCCESS;
}
=============================================================

Am i supposed to use offp ??
Please help !!

Last edited by tomkaith13; 11-22-2006 at 04:00 AM.
 
Old 11-22-2006, 09:18 AM   #5
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Code:
ret= copy_to_user(msgusr,*(msg_ptr),count);
I don't know what copy_to_user() does, but it appears to copy a buffer from kernel space to user space, of size 'count'. If so, then it looks like the second argument should just be 'msg_ptr' (Which you initialized to point at an information string in device_open() ). You seem to be having a bad char day.

It would be helpful to wrap your code listings in code tags to preserve formatting.

--- rod.
 
Old 11-23-2006, 04:15 AM   #6
tomkaith13
LQ Newbie
 
Registered: Nov 2006
Posts: 6

Original Poster
Rep: Reputation: 0
Ah !! finally the code worked ..
Thanks for the help...you are right abt the copy_to_user()..

No one seem to use copy_to_user func ...
Everyone seems to be content with put_user() itself..

I thought i wil try the latter func .... thats wat landed me in this mess ..
 
Old 11-27-2006, 04:46 AM   #7
tomkaith13
LQ Newbie
 
Registered: Nov 2006
Posts: 6

Original Poster
Rep: Reputation: 0
hi all,
Here is the final working code of a simple char driver implemented using copy_to_user and copy_from_user :

Quote:
#include <linux/module.h>
#include <linux/init.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/kobj_map.h>
#include <linux/cdev.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
#include <linux/cdev.h>

#define DEVICE_NAME "scull"
#define SUCCESS 0
#define FAIL -1
#define SIZE 100




static int Major, Minor;
static int device_opened = 0;
int bytes=25,bytes_read=0;
static char *msg_ptr;
static char msg[SIZE];


static int device_open (struct inode *in, struct file *filp);
static int device_release (struct inode *in, struct file *filp);
static int device_read(struct file *,char *,int ,int *);
static int device_write(struct file *,char *,int ,int *);

static int
device_open (struct inode *in, struct file *filp)
{
if (device_opened)
{
printk(KERN_ALERT "Driver is in use");
return -EBUSY;
}
device_opened++;

if(!try_module_get(THIS_MODULE))
return -EBUSY;


msg_ptr = msg;


return SUCCESS;
}



static int
device_release (struct inode *in, struct file *filp)
{

device_opened--;
module_put(THIS_MODULE);
return SUCCESS;
}




static struct file_operations scull_fops = {
.open = device_open,
.release = device_release,
.owner = THIS_MODULE,
.read = device_read,
.write = device_write,
};

struct cdev scull_cdev ;
int dev_num;

static int scull_init (void)
{

dev_t dev;
int retval;


retval=alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
if(!retval)
{
Major=MAJOR(dev);
Minor=MINOR(dev);
}
else {
return FAIL;
}


printk("MAJOR(dev)=%d\n", MAJOR(dev));

printk("<1> Before cdev_init\n");

printk("<1> after cdev_init:\n");

cdev_init(&scull_cdev,&scull_fops);



retval=cdev_add(&scull_cdev,dev,1);
if(retval)
{
cdev_del(&scull_cdev);
unregister_chrdev_region(dev, 1);
printk("<1> Error in cdev_add:");
return -EBUSY;
}
printk ("<1> scull_init was a Success and the major device number is %d \n", Major);

memset(msg,'0',100);
sprintf(msg,"Initial Driver Content !!");

printk("<1> %s",msg);

return 0;


}

static int device_read(struct file *filp,char *msgusr,int count,int *offp)
{
int i;
unsigned long ret;



if(*msg_ptr == 0)
return 0;

printk ("<1> \n\n Here we are Reading!!\n");

if(bytes==0)
return 0;

ret= copy_to_user(msgusr,msg_ptr,bytes);


if(ret != 0)
{
printk("<1> Error in reading !!");
return -EFAULT;
}


bytes_read=bytes;
bytes=0;

return bytes_read;
}

static ssize_t device_write (struct file *filp,char *msgusr,int count,int *offp)
{
int err,i=1;
i++;
printk("<1> i is :%d",i);
printk("<1> We are writing !!");

err = copy_from_user(msg_ptr,msgusr,count);
if (err != 0)
{
printk("<1>\n Write error\n");
return -EFAULT;
}

offp-=count;
bytes += count;

printk("<1>\n\n no of chars wriiten :%d\n",count);
return count;
}
static void scull_exit (void)
{
printk ("<1> Removing scull drivers from /proc/devices\n");
cdev_del(&scull_cdev);
unregister_chrdev_region (MKDEV(Major,0), 1);
}


module_init (scull_init);
module_exit (scull_exit);


Last edited by tomkaith13; 11-27-2006 at 04:48 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
char device module the_uplink2x Programming 2 05-24-2005 10:53 PM
char driver on linux-kernel-2.6.10 prashy Programming 2 05-09-2005 01:44 PM
user-mode Linux char device driver with "unresolved symbol __generic_copy_to_user" dlobron Linux - General 0 11-14-2004 09:41 AM
char device i810_rng djgerbavore Linux - Newbie 1 08-18-2004 08:33 PM
Driver Doubt. bella General 1 05-07-2003 06:58 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:36 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration