serial device driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 hello all,
   i am newbee. i am trying to write a serial device driver. i saw the
one in LDD3 by Rubino. I coded the driver but now it is giving me
following error
error =>

 root@rahul:/home/rahul/driver # make
make -C /usr/src/linux-2.6.10 SUBDIRS=/home/rahul/driver modules
make[1]: Entering directory `/usr/src/linux-2.6.10'
  CC [M]  /home/rahul/driver/tiny1.o
/home/rahul/driver/tiny1.c: In function `tiny_open':
/home/rahul/driver/tiny1.c:72: error: `MOD_INC_USE_COUNT' undeclared
(first use in this function)
/home/rahul/driver/tiny1.c:72: error: (Each undeclared identifier is
reported only once
/home/rahul/driver/tiny1.c:72: error: for each function it appears in.)
/home/rahul/driver/tiny1.c:78: warning: implicit declaration of function `minor'
/home/rahul/driver/tiny1.c:78: error: structure has no member named `device'
/home/rahul/driver/tiny1.c:83: error: `MOD_DEC_USE_COUNT' undeclared
(first use in this function)
/home/rahul/driver/tiny1.c:91: error: structure has no member named `device'
/home/rahul/driver/tiny1.c: In function `do_close':
/home/rahul/driver/tiny1.c:145: error: `MOD_DEC_USE_COUNT' undeclared
(first use in this function)
/home/rahul/driver/tiny1.c: At top level:
/home/rahul/driver/tiny1.c:223: warning: initialization makes integer
from pointer without a cast
/home/rahul/driver/tiny1.c:224: error: unknown field `table' specified
in initializer
/home/rahul/driver/tiny1.c:224: warning: initialization from
incompatible pointer type
/home/rahul/driver/tiny1.c:230: warning: initialization from
incompatible pointer type
make[2]: *** [/home/rahul/driver/tiny1.o] Error 1
make[1]: *** [_module_/home/rahul/driver] Error 2
make[1]: Leaving directory `/usr/src/linux-2.6.10'
make: *** [default] Error 2


should i try to replace the MOD_.. with a local counter .However doing
this further generates other errors.

My code=>


#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/sched.h>

#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "RAHUL"
#define DRIVER_DESC "Tiny TTY driver"

/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");

#define DELAY_TIME		HZ * 2	/* 2 seconds per character */
#define TINY_DATA_CHARACTER	't'

#define TINY_TTY_MAJOR		240	/* experimental range */
#define TINY_TTY_MINORS		255	/* use the whole major up */

struct tiny_serial {
	struct tty_struct	*tty;		/* pointer to the tty for this device */
	int			open_count;	/* number of times this port has been opened */
	struct semaphore	sem;		/* locks this structure */
	struct timer_list	*timer;
};

static int			       tiny_refcount;
static struct tty_driver	tiny_tty_driver;
static struct tty_struct	*tiny_tty[TINY_TTY_MINORS];
static struct termios		*tiny_termios[TINY_TTY_MINORS];
static struct termios		*tiny_termios_locked[TINY_TTY_MINORS];
static struct tiny_serial	*tiny_table[TINY_TTY_MINORS];	/* initially all NULL */


static void tiny_timer (unsigned long data)
{
	struct tiny_serial *tiny = (struct tiny_serial *)data;
	struct tty_struct *tty;

	if (!tiny)
		return;

	tty = tiny->tty;

	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
		tty_flip_buffer_push(tty);

	/* add two characters to the tty port */
	/* this doesn't actually push the data through unless
tty->low_latency is set */
	tty_insert_flip_char(tty, TINY_DATA_CHARACTER, 0);
	tty_insert_flip_char(tty, '\n', 0);

	tty_flip_buffer_push(tty);
	tty_schedule_flip (tty);
	
	/* resubmit the timer again */
	tiny->timer->expires = jiffies + DELAY_TIME;
	add_timer (tiny->timer);
}

static int tiny_open (struct tty_struct *tty, struct file * filp)
{
	struct tiny_serial *tiny;
	struct timer_list *timer;

	MOD_INC_USE_COUNT;

	/* initialize the pointer incase something fails */
	tty->driver_data = NULL;

	/* get the serial object associated with this tty pointer */
	tiny = tiny_table[minor(tty->device)];
	if (tiny == NULL) {
		/* first time accessing this device, let's create it */
		tiny = kmalloc (sizeof (*tiny), GFP_KERNEL);
		if (!tiny) {
			MOD_DEC_USE_COUNT;
			return -ENOMEM;
		}

		init_MUTEX (&tiny->sem);
		tiny->open_count = 0;
		tiny->timer = NULL;

		tiny_table[minor(tty->device)] = tiny;
	}

	down (&tiny->sem);

	/* save our structure within the tty structure */
	tty->driver_data = tiny;
	tiny->tty = tty;


	++tiny->open_count;
	if (tiny->open_count == 1) {
		/* this is the first time this port is opened */
		/* do any hardware initialization needed here */

		/* create our timer and submit it */
		if (!tiny->timer) {
			timer = kmalloc (sizeof (*timer), GFP_KERNEL);
			if (!timer) {
				up (&tiny->sem);
				MOD_DEC_USE_COUNT;
				return -ENOMEM;
			}
			tiny->timer = timer;
		}
		init_timer (tiny->timer);
		tiny->timer->data = (unsigned long )tiny;
		tiny->timer->expires = jiffies + DELAY_TIME;
		tiny->timer->function = tiny_timer;
		add_timer (tiny->timer);
	}

	up (&tiny->sem);
	return 0;
}

static void do_close (struct tiny_serial *tiny)
{
	down (&tiny->sem);

	if (!tiny->open_count) {
		/* port was never opened */
		return;
	}

	--tiny->open_count;
	if (tiny->open_count <= 0) {
		/* The port is being closed by the last user. */
		/* Do any hardware specific stuff here */

		/* shut down our timer */
		del_timer (tiny->timer);
	}

	MOD_DEC_USE_COUNT;

	up (&tiny->sem);
}

static void tiny_close (struct tty_struct *tty, struct file * filp)
{
	struct tiny_serial *tiny = tty->driver_data;

	if (!tiny) {
		return;
	}

	do_close (tiny);
}	

static int tiny_write (struct tty_struct * tty, int from_user, const
unsigned char *buf, int count)
{
	struct tiny_serial *tiny = tty->driver_data;
	int retval = -EINVAL;

	if (!tiny) {
		return -ENODEV;
	}

	down (&tiny->sem);

	if (!tiny->open_count) {
		/* port was not opened */
		goto exit;
	}

	/* now send the data out the harware port */
	retval = count;

exit:
	up (&tiny->sem);
	return retval;
}

static int tiny_write_room (struct tty_struct *tty) 
{
	struct tiny_serial *tiny = tty->driver_data;
	int room;

	if (!tiny) {
		return -ENODEV;
	}

	down (&tiny->sem);
	
	if (!tiny->open_count) {
		/* port was not opened */
		return -EINVAL;
	}

	/* calculate how much room is left in the device */
	room = 255;

	up (&tiny->sem);

	return room;
}

static struct tty_driver tiny_tty_driver = {
	magic:			TTY_DRIVER_MAGIC,
	driver_name:		"tiny_tty",
#ifndef CONFIG_DEVFS_FS
	name:			"ttty",
#else
	name:			"tts/ttty%d",
#endif
	major:			TINY_TTY_MAJOR,
	num:			TINY_TTY_MINORS,
	type:			TTY_DRIVER_TYPE_SERIAL,
	subtype:		SERIAL_TYPE_NORMAL,
	flags:			TTY_DRIVER_REAL_RAW,
	
	refcount:		&tiny_refcount,
	table:			tiny_tty,
	termios:		tiny_termios,
	termios_locked:		tiny_termios_locked,

	open:			tiny_open,
	close:			tiny_close,
	write:			tiny_write,
	write_room:		tiny_write_room,
};

static int __init tiny_init(void)
{
	/* register the tty driver */
	tiny_tty_driver.init_termios          = tty_std_termios;
	tiny_tty_driver.init_termios.c_cflag  = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
	if (tty_register_driver (&tiny_tty_driver)) {
		printk (KERN_ERR "failed to register tiny tty driver\n");
		return -1;
	}

	printk (KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");

	return 0;
}

static void __exit tiny_exit(void)
{
	struct tiny_serial *tiny;
	int i;

	tty_unregister_driver(&tiny_tty_driver);

	/* shut down all of the timers and free the memory */
	for (i = 0; i < TINY_TTY_MINORS; ++i) {
		tiny = tiny_table[i];
		if (tiny) {
			/* close the port */
			while (tiny->open_count)
				do_close (tiny);

			/* shut down our timer and free the memory */
			del_timer (tiny->timer);
			kfree (tiny->timer);
			kfree (tiny);
			tiny_table[i] = NULL;
		}
	}
}

module_init(tiny_init);
module_exit(tiny_exit);

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux