LinuxQuestions.org
Visit Jeremy's Blog.
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 09-07-2005, 02:11 PM   #1
Igor007
Member
 
Registered: Aug 2004
Posts: 76

Rep: Reputation: 15
Linux Device Drivers, Third Edition --- scull module???


Hi guys
Who have read and gone through examples successfully of the book ”Linux Device Drivers, Third Edition”

First scull module does not work properly. The functions scull_read and scull_write are note invoked


At least I cannot notice it using debugging techniques offered in this book: gdb kdb printk
Results of work of this module are fine
data is always 0;
scull_devices[0].data = 0x0

cat > /dev/scull
Hello World

I pressed Ctrl-D

cat /dev/scull
Hello World


Please help
 
Old 09-08-2005, 09:35 AM   #2
Matir
LQ Guru
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Debian, Arch
Posts: 8,507

Rep: Reputation: 128Reputation: 128
And dmesg shows nothing from the printk technique?
 
Old 09-09-2005, 05:05 PM   #3
Igor007
Member
 
Registered: Aug 2004
Posts: 76

Original Poster
Rep: Reputation: 15
And dmesg shows nothing from the printk that I put in read write functions ?

Here I give some code of my module it is big But I cannot give you other way the whole picture
////////////////////////////////
//scull.h////////////////////
////////////////////////////////
#define SCULL_DEBUG
#define FUNCDEBUG


#ifndef SCULL_H
#define SCULL_H

#include <linux/ioctl.h>

#ifndef SCULL_MAJOR
#define SCULL_MAJOR 0
#endif

#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 4
#endif

#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 4
#endif

#ifndef SCULL_QUANTUM
#define SCULL_QUANTUM 4000
#endif

#ifndef SCULL_QSET
#define SCULL_QSET 1000
#endif

//#ifndef SCULL_P_BUFFER
//#define SCULL_PBUFFER 4000
//#endif



#define TYPE(minor) (((minor)>>4)&0xf);//hinible
#define NUM(minor) ((minor)&0xf);//lownible
extern int scull_major;
extern int scull_nr_devs;
extern int scull_quantumn;
extern int scull_qset;

//extern int scull_p_buffer; //pipe.c
struct scull_qset{
void** data;
struct scull_qset* next;
};



struct scull_dev{
struct scull_qset *data;
int quantum;
int qset;
unsigned long size;
unsigned int access_key;
struct semaphore sem;
struct cdev cdev;
};
//int scull_p_init(dev_t dev);
//void scull_p_cleanup();
//int scull_access_init(dev_t dev);
//void scull_access_cleanup();

int scull_trim(struct scull_dev *dev);
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
loff_t scull_llseek(struct file *filp, loff_t off, int whence);
int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
#define SCULL_IOCSQUANTUM _IOW(SCULL_IOCMAGIC, 1,int)
/*to be continued ...*/

#endif//SCULL_H
//////////////////////////////
////scull.cpp
///////////////////////////
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <linux/seq_file.h>
#include <linux/cdev.h>

#include <asm/system.h>
#include <asm/uaccess.h>

#include "scull.h"

int read_function_count =0;
int write_function_count =0;

int scull_major = SCULL_MAJOR;
int scull_minor = 0;
int scull_nr_devs=SCULL_NR_DEVS;
int scull_quantum = SCULL_QUANTUM;
int scull_qset=SCULL_QSET;
module_param(scull_major,int,S_IRUGO);
module_param(scull_minor,int,S_IRUGO);
module_param(scull_nr_devs,int,S_IRUGO);
module_param(scull_quantum,int,S_IRUGO);
module_param(scull_qset,int,S_IRUGO);

MODULE_AUTHOR("IgorD");
MODULE_LICENSE("Dual BSD/?GPL");

struct scull_dev *scull_devices;


int scull_trim(struct scull_dev* dev)
{
struct scull_qset *next, *dptr;
int qset=dev->qset;
int i;
#ifdef FUNCDEBUG
printk("<0> scull_trim begin\n");
#endif//FUNCDEBUG
for(dptr=dev->data;dptr;dptr=next){
if(dptr->data){
for (i=0;i<qset;++i);
kfree(dptr->data[i]);
kfree(dptr->data);
dptr->data=NULL;
}
next=dptr->next;
kfree(dptr);
}
dev->size=0;
dev->quantum=scull_quantum;
dev->qset=scull_qset;
dev->data=NULL;
#ifdef FUNCDEBUG
printk("<0> scull_trim end\n");
#endif//FUNCDEBUG
return 0;
}

#ifdef SCULL_DEBUG
int scull_read_procmem(char *buf, char **start, off_t offset, int count, int* eof, void*data){
int i, j, len=0;
int limit=count-80;
for (i=0;i<scull_nr_devs && len<=limit;i++){
struct scull_dev *d=&scull_devices[i];
struct scull_qset *qs =d->data;
if(down_interruptible(&d->sem))
return -ERESTARTSYS;
len+= sprintf(buf+len,"\nDevices %i qset %i, q %i, sz %li\n",i,d->qset,d->quantum,d->size);
for(; qs&& len<=limit;qs=qs->next){
if(qs->data && !qs->next){
sprintf(buf+len," item at %p,qset at %p",qs,qs->data);
for(j=0;j<d->qset;j++){
if(qs->data[j])
len+=sprintf(buf+len,"%4i : %8p\n",j, qs->data[j]);
}

}
}
up(&d->sem);
}
*eof=1;
return len;
}
static void* scull_seq_start(struct seq_file *s, loff_t* pos){
if(*pos >= scull_nr_devs)
return NULL;
return scull_devices+*pos;
}
static void* scull_seq_next(struct seq_file *s, void * v, loff_t* pos){
++(*pos);
if(*pos >= scull_nr_devs)
return NULL;
return scull_devices+*pos;
}
static void scull_seq_stop(struct seq_file *s, void * v){

}
static int scull_seq_show(struct seq_file* s, void *v){

struct scull_dev *dev = (struct scull_dev* ) v;
struct scull_qset *d;
int i;

if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
seq_printf(s,"\nDevice %i: qset %i q %i sz %li\n", (int)(dev-scull_devices), dev->qset,dev->quantum, dev->size);
for(d = dev->data;d; d=d->next){
seq_printf(s," item at %p, qset at %p\n",d,d->data);
if (d->data && d->next){
for(i = 0; i < dev->qset; ++i){
if(d->data[i])
seq_printf(s," % 4i: %8p\n",i,d->data[i]);
}
}
}
up(&dev->sem);
return 0;
}
static struct seq_operations scull_seq_ops = {
.start = scull_seq_start,
.next = scull_seq_next,
.stop = scull_seq_stop,
.show =scull_seq_show
};
static int scull_proc_open(struct inode* inode,struct file *file){
return seq_open(file,&scull_seq_ops);
}
static struct file_operations scull_proc_ops = {
.owner =THIS_MODULE,
.open =scull_proc_open,
.read =seq_read,
.llseek=seq_lseek,
.release=seq_release
};
static void scull_create_proc(void){
struct proc_dir_entry *entry;
create_proc_read_entry("scullmem",0,NULL,scull_read_procmem,NULL);
entry = create_proc_entry("scullseq",0,NULL);
if(entry)
entry->proc_fops = &scull_proc_ops;
}
static void scull_remove_proc(void){
remove_proc_entry("scull_mem",NULL);
remove_proc_entry("scull_seq",NULL);
}

/*to be continued*/
#endif

int scull_open(struct inode* inode, struct file* filp)
{
struct scull_dev *dev;
#ifdef FUNCDEBUG
printk("<0> scull_open begin\n");
#endif//FUNCDEBUG
dev=container_of(inode->i_cdev,struct scull_dev, cdev);
filp->private_data=dev;
if((filp->f_flags & O_ACCMODE) == O_WRONLY){
scull_trim(dev);
}
#ifdef FUNCDEBUG
printk("<0> scull_open end\n");
#endif//FUNCDEBUG
return 0;
}
int scull_release(struct inode *inode,struct file *filp){
#ifdef FUNCDEBUG
printk("<0> scull_release begin\n");
#endif//FUNCDEBUG
#ifdef FUNCDEBUG
printk("<0> scull_release end\n");
#endif//FUNCDEBUG
return 0;
}
struct scull_qset *scull_follow(struct scull_dev *dev,int n){
struct scull_qset *qs = dev->data;
#ifdef FUNCDEBUG
printk("<0> scull_follow begin\n");
#endif//FUNCDEBUG
if(qs==NULL){
qs=dev->data=kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
if(qs==NULL)
return NULL;
memset(qs,0,sizeof(struct scull_qset));
}
while(n--){
if(qs->next==NULL){
qs->next=kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
if(qs->next==NULL);
return NULL;
memset(qs->next,0,sizeof(struct scull_qset));

}
qs=qs->next;
continue;
}
#ifdef FUNCDEBUG
printk("<0> scull_follow end\n");
#endif//FUNCDEBUG
return qs;

}

ssize_t scull_read(struct file* flip, char __user *buf, size_t count, loff_t* f_pos){



struct scull_dev* dev=flip->private_data;
struct scull_qset* dptr;
int quantum=dev->quantum,qset=dev->qset;
int itemsize=quantum*qset;
int item,s_pos,q_pos,rest;
ssize_t retval=0;
read_function_count+=1;
#ifdef FUNCDEBUG
printk("<0> scull_read begin\n");
#endif//FUNCDEBUG
if (down_interruptible(&dev->sem))
return -ERESTARTSYS;
if (*f_pos > dev->size)
goto out;
if(*f_pos+count>dev->size)
count=dev->size-*f_pos;

item=(long)*f_pos / itemsize;
rest=(long)*f_pos % itemsize;
s_pos=rest / quantum;q_pos=rest % quantum;
dptr = scull_follow(dev,item);
if(dptr==NULL || !dptr->data || !dptr->data[s_pos])
goto out;
if(count > quantum-q_pos)
count=quantum-q_pos;
if(copy_to_user(buf,dptr->data[s_pos]+q_pos,count)){
retval=-EFAULT;
goto out;
}
*f_pos+=count;
retval=count;
out:
up(&dev->sem);
#ifdef FUNCDEBUG
printk("<0> scull_read end\n");
#endif//FUNCDEBUG
return retval;
}
ssize_t scull_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos){


struct scull_dev *dev =filp->private_data;
struct scull_qset *dptr;
int quantum=dev->quantum, qset=dev->qset;
int itemsize=quantum * qset;
int item, s_pos, q_pos, rest;
ssize_t retval= -ENOMEM;
write_function_count=+1;
#ifdef FUNCDEBUG
printk("<0> scull_write begin\n");
#endif//FUNCDEBUG
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
item=(long)*f_pos/itemsize;
rest=(long)*f_pos%itemsize;
s_pos=rest/quantum;q_pos=rest%quantum;
dptr=scull_follow(dev,item);
if(dptr==NULL)
goto out;
if(dptr->data==NULL){
dptr->data=kmalloc(qset*sizeof(char *),GFP_KERNEL);
if(dptr->data==NULL)
goto out;
memset(dptr->data,0,qset*sizeof(char *));
}
if(!dptr->data[s_pos]){
dptr->data[s_pos]=kmalloc(quantum,GFP_KERNEL);
if(!dptr->data[s_pos])
goto out;
}
if (count> quantum-q_pos)
count=quantum-q_pos;
if(copy_from_user(dptr->data[s_pos]+q_pos,buf,count)){
retval=-EFAULT;
goto out;
}
*f_pos=+count;
retval=count;
if(dev->size < *f_pos)
dev->size=*f_pos;
out:
up(&dev->sem);
#ifdef FUNCDEBUG
printk("<0> scull_write begin\n");
#endif//FUNCDEBUG
return retval;
}
int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){
#ifdef FUNCDEBUG
printk("<0> scull_ioctl begin\n");
#endif//FUNCDEBUG
//to be continued
#ifdef FUNCDEBUG
printk("<0> scull_ioctl end\n");
#endif//FUNCDEBUG
return 0;
}
loff_t scull_llseek(struct file* filp, loff_t off,int whence){

struct scull_dev *dev=filp->private_data;
loff_t newpos;
#ifdef FUNCDEBUG
printk("<0> scull_llseek begin\n");
#endif//FUNCDEBUG
switch(whence){
case 0: //SEEK_SET
newpos=off;
break;
case 1://SEEK_CUR
newpos=filp->f_pos+off;
break;
case 2://SEEK_END
newpos=dev->size+off;
break;
default:
return -EINVAL;
}
if(newpos<0)return -EINVAL;
filp->f_pos=newpos;
#ifdef FUNCDEBUG
printk("<0> scull_llseek end\n");
#endif//FUNCDEBUG
return newpos;
}
struct file_operations scull_fops={
.owner=THIS_MODULE,
.llseek=scull_llseek,
.read=scull_read,
.write=scull_write,
.ioctl=scull_ioctl,
.open=scull_open,
.release=scull_release
};
//module stuff
void scull_cleanup_module(void){
int i;
dev_t devno=MKDEV(scull_major,scull_minor);
if(scull_devices!=NULL){
for(i=0;i<scull_nr_devs;++i){
scull_trim(scull_devices+i);
cdev_del(&scull_devices[i].cdev);
}
kfree(scull_devices);
}
#ifdef SCULL_DEBUG
scull_remove_proc();
#endif
unregister_chrdev_region(devno,scull_nr_devs);
//scull_p_clean_up();
//scull_access_cleanup();
printk("<0> Scull Module has been unregistered\n");
}
static void scull_setup_cdev(struct scull_dev* dev, int index)
{

int err, devno=MKDEV(scull_major,scull_major+index);
cdev_init(&dev->cdev,&scull_fops);
dev->cdev.owner=THIS_MODULE;
dev->cdev.ops=&scull_fops;
err=cdev_add(&dev->cdev,devno,1);
//if failed
#ifdef FUNCDEBUG
printk("<0> scull_setup_cdev begin\n");
#endif//FUNCDEBUG
if(err)
printk(KERN_NOTICE "Error %d adding scull %d",err,index);
#ifdef FUNCDEBUG
printk("<0> scull_setup_cdev end\n");
#endif//FUNCDEBUG
}
int scull_init_module(void){

int result, i;
dev_t dev=0;
if(scull_major!=0){
dev = MKDEV(scull_major,scull_minor);
result = register_chrdev_region(dev,scull_nr_devs,"scull");
}else{
result = alloc_chrdev_region(&dev,scull_minor,scull_nr_devs,"scull");
scull_major=MAJOR(dev);
}
if (result < 0){
printk(KERN_WARNING "scull cannot get major %d\n", scull_major);
return result;
}
scull_devices=kmalloc(scull_nr_devs*sizeof(struct scull_dev),GFP_KERNEL);
if(scull_devices==NULL){
result =-ENOMEM;
goto fail;
}
memset(scull_devices,0,scull_nr_devs*sizeof(struct scull_dev));
for(i=0;i<scull_nr_devs;++i){
scull_devices[i].quantum=scull_quantum;
scull_devices[i].qset=scull_qset;
init_MUTEX(&scull_devices[i].sem);
scull_setup_cdev(&scull_devices[i],i);
}
dev=MKDEV(scull_major,scull_minor+scull_nr_devs);
//dev += scull_p_init(dev);
//dev += scull_access_init(dev);
#ifdef SCULL_DEBUG
scull_create_proc();
#endif
printk("<0> Scull Module has been registered\n");
return 0;
fail:
scull_cleanup_module();
return result;
}
module_init(scull_init_module);
module_exit(scull_cleanup_module);



Last edited by Igor007; 09-09-2005 at 05:09 PM.
 
  


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
C++ or pure C for Linux kernel module, Linux device driver development. What to use? Igor007 Programming 91 07-19-2014 11:55 AM
Scull Device Driver (problems to compile) manuzinhac Linux - Hardware 0 05-19-2005 09:00 AM
Sample module coding: Linux Device Drivers leosgb Programming 0 12-29-2004 03:59 PM
Trouble running make to compile example scull device driver taillefer Programming 3 03-23-2004 12:53 AM
linux device drivers alaios Programming 1 05-24-2003 08:23 PM

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

All times are GMT -5. The time now is 02:46 PM.

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