⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serproto.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static int serial_chars_in_buffer (struct tty_struct *tty){	struct serproto_dev *device;	int n;	//dbg_rx(4,"entered");	if ((device = tty->driver_data) == NULL) {		dbg_rx (1, "not presently connected -> FAIL");		return (-EINVAL);	}	read_lock (&device->rwlock);	n = device->queued_bytes;	read_unlock (&device->rwlock);	//dbg_rx(4,"->%d",n);	return (n);}static struct tty_driver serial_tty_driver = {	magic:TTY_DRIVER_MAGIC,	driver_name:"usbd-serial",	name:"usb",	major:SERIAL_TTY_MAJOR,	minor_start:0,	num:SERIAL_TTY_MINORS,	type:TTY_DRIVER_TYPE_SERIAL,	subtype:SERIAL_TYPE_NORMAL,	flags:TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,	refcount:&serial_refcount,	table:serial_tty,	termios:serial_termios,	termios_locked:serial_termios_locked,	open:serial_open,	close:serial_close,	flush_buffer:serial_flush,	write:serial_write,	write_room:serial_write_room,	ioctl:serial_ioctl,	set_termios:serial_set_termios,	throttle:serial_throttle,	unthrottle:serial_unthrottle,	chars_in_buffer:serial_chars_in_buffer,};/* Library Interface Functions ***************************************************************** *//** * serproto_modinit - initialize the serproto library * @name: name  * @num: number of interfaces to allow * */int serproto_modinit (char *name, int num){	dbg_init (1, "%s[%d]", name, num);	rwlock_init (&serproto_rwlock);	serproto_devices = num;	if (!(serproto_device_array = kmalloc (sizeof (struct serproto_dev *) * num, GFP_KERNEL))) {		dbg_init (0, "kmalloc failed");		return -EINVAL;	}	memset (serproto_device_array, 0, sizeof (struct serproto_dev *) * num);	dbg_loop (1, "LOOPBACK mode");	return 0;}static void wakeup_writers (void *private){	struct serproto_dev *device = (struct serproto_dev *) private;	struct tty_struct *tty;	if (NULL != device && NULL != (tty = device->tty)) {		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && NULL != tty->ldisc.write_wakeup) {			(tty->ldisc.write_wakeup) (tty);		}		wake_up_interruptible (&tty->write_wait);	}	MOD_DEC_USE_COUNT;}/** * serproto_create - create a serial interface * @name: name * @xmit_data: callback to transmit data * @max_queue_entries: maximum number of outstanding requests to allow * @max_queue_bytes: maximum number of bytes to allow * * Create a serial interface, providing an xmit data function.  * * A returned value greater or equal to zero indicates success. This value can be  * used with subsequent function calls to indicate the created serial interface. */int serproto_create (char *name,		     int (*xmit_data) (int, unsigned char *, int),		     int tx_size,		     int max_queue_entries, int max_queue_bytes, int blocked, int trailer){	struct serproto_dev *device;	int i;	dbg_init (1, "array: %p name: %p[%s] xmit: %p", serproto_device_array, name, name,		  xmit_data);	if (!serproto_device_array) {		dbg_init (1, "invalid args -> FAIL");		return (-EINVAL);	}	/* Note: the tty layer assumes that if *_write_room() returns n > 0, that	   n more bytes can be queued up in UPTO n CALLS TO *_write().  It does not	   re-verify the available room.  This means that if we are limiting the	   number of queued entries, and we indicate that 64 _bytes_ can be queued,	   there may be upto 64 *_write(1) calls, which is probably going to overflow	   the queue.  It would also seem that the tty layer does not check the	   return value of the *_write() calls, so that calls which fail due to	   insufficient queue entries are simply lost.  For this reason, setting	   max_queue_entries to 0 allows unlimitied queueing. */	if (!serproto_device_array || !name || !strlen (name) || !xmit_data ||	    max_queue_entries < 0 || max_queue_bytes <= 0) {		dbg_init (1, "invalid args -> FAIL");		return (-EINVAL);	}	{		unsigned long flags;		write_lock_irqsave (&serproto_rwlock, flags);		for (i = 0; i < serproto_devices; i++) {			if (!(device = serproto_device_array[i])) {				break;			}		}		if (i == serproto_devices) {			write_unlock_irqrestore (&serproto_rwlock, flags);			dbg_init (1, "name: %s cannot find empty serproto_device slot", name);			return (-ENOMEM);		}		if (!(device = kmalloc (sizeof (struct serproto_dev), GFP_ATOMIC))) {			write_unlock_irqrestore (&serproto_rwlock, flags);			dbg_init (1, "name: %s kmalloc failed", name);			return (-ENOMEM);		}		memset (device, 0, sizeof (struct serproto_dev));		rwlock_init (&device->rwlock);		device->xmit_data = xmit_data;		device->tx_size = MIN (256, tx_size);	// maximum 256 bytes		device->max_queue_entries = max_queue_entries;		device->max_queue_bytes = max_queue_bytes;		device->write_wakeup_task.routine = wakeup_writers;		device->write_wakeup_task.data = device;		device->blocked = blocked;		device->trailer = trailer;		memcpy (&device->tty_driver, &serial_tty_driver, sizeof (struct tty_driver));		device->tty_driver.init_termios = tty_std_termios;		device->tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;		// Turn off echo fight with standard UNIX USB Host serial drivers.		device->tty_driver.init_termios.c_lflag &= ~(ECHO | ICANON);		/* We don't need \n -> \r\n output conversion */                device->tty_driver.init_termios.c_oflag &= ~ONLCR;		serproto_device_array[i] = device;		write_unlock_irqrestore (&serproto_rwlock, flags);	}	if (tty_register_driver (&device->tty_driver)) {		unsigned long flags;		write_lock_irqsave (&serproto_rwlock, flags);		serproto_device_array[i] = NULL;		kfree (device);		write_unlock_irqrestore (&serproto_rwlock, flags);		printk (KERN_ERR __FUNCTION__ "(%s) - failed to register tty driver\n", name);		dbg_init (1, "try registration failed");		return (-EINVAL);	}	dbg_init (2, "name: %s -> %d", name, i);	return (i);}/** * serproto_done - transmit done * @interface: device interface * @data: data buffer * @len: data length * @rc: non-zero indicates failure * */int serproto_done (int interface, void *data, int len, int rc){	struct serproto_dev *device;	unsigned long flags;	dbg_tx (4, "interface: %d", interface);	// Must be done with interrupts off, since sync may	// be set by another (different) call to queue_task()	write_lock_irqsave (&device->rwlock, flags);	if ((device = serproto_device_array[interface]) == NULL) {		write_unlock_irqrestore (&device->rwlock, flags);		dbg_tx (1, "no device -> FAIL");		return (-EINVAL);	}	device->queued_entries--;	device->queued_bytes -= len;	if (!device->write_wakeup_task.sync) {		// Queue a wakeup for anyone waiting to write,		// but lock the module in place first.		MOD_INC_USE_COUNT;		queue_task (&device->write_wakeup_task, &tq_immediate);		mark_bh (IMMEDIATE_BH);	}	write_unlock_irqrestore (&device->rwlock, flags);	return 0;}/** * serproto_recv - receive data * @data: data buffer * @length: length of valid data */int serproto_recv (int interface, unsigned char *data, int length){	struct serproto_dev *device;	struct tty_struct *tty;	unsigned long flags;	int i;	dbg_rx (4, "length=%d", length);	dbg_rx (5, "interface: %d data: %p serproto_device_array: %p",		interface, data, serproto_device_array);	dbg_rx (5, "device: %p", serproto_device_array[interface]);	if ((device = serproto_device_array[interface]) == NULL) {		dbg_rx (1, "no device -> FAIL");		return (-EINVAL);	}#if 0	if (0 != dbgflg_loopback) {		// serproto_done() will free data when transmission complete		device->xmit_data (device->number, data, length);		write_lock_irqsave (&device->rwlock, flags);		device->queued_entries++;		device->queued_bytes += length;		write_unlock_irqrestore (&device->rwlock, flags);		dbg_rx (3, "loopback->0");		return (0);	}#endif	if (device->opencnt <= 0 || (tty = device->tty) == NULL) {		dbg_rx (1, "no tty -> FAIL");		//kfree(data);		return (-EINVAL);	}	// XXX bail if not open for reading....	for (i = 0; i < length; ++i) {		tty_insert_flip_char (tty, data[i], 0);	}	tty_flip_buffer_push (tty);	//kfree(data);	dbg_rx (4, "->0");	return 0;}/** * serproto_control - control serial interface * @interface: serial interface * @operation: operation * * Control a serial interface,  */int serproto_control (int interface, int operation){	struct serproto_dev *device;	unsigned long flags;	dbg_mgmt (1, "interface: %d op=%d", interface, operation);	if ((device = serproto_device_array[interface]) == NULL) {		dbg_mgmt (1, "no device");		return (-ENODEV);	}	switch (operation) {	case SERPROTO_CONNECT:		write_lock_irqsave (&device->rwlock, flags);		device->connected = TRUE;		/* Wake up anybody who might have blocked waiting		   for the connection. */		// Must be done with interrupts off, since sync may		// be set by another (different) call to queue_task()		if (!device->write_wakeup_task.sync) {			// Queue a wakeup for anyone waiting to write,			// but lock the module in place first.			MOD_INC_USE_COUNT;			queue_task (&device->write_wakeup_task, &tq_immediate);			mark_bh (IMMEDIATE_BH);		}		write_unlock_irqrestore (&device->rwlock, flags);		break;	case SERPROTO_DISCONNECT:		device->connected = FALSE;		/* Send a HANGUP to anybody involved with this device. */		if (device->tty && !device->clocal) {			dbg_mgmt (1, "calling hangup");			tty_hangup (device->tty);		}	}	return 0;}/** * serproto_destroy - destroy a serial interface * @interface: serial interface * * Call to tear down a previously created serial interface */int serproto_destroy (int interface){	struct serproto_dev *device;	unsigned int flags;	dbg_init (1, "interface: %d", interface);	if ((device = serproto_device_array[interface]) == NULL) {		dbg_init (1, "no device");		return (0);	}	// grab device lock and delete device entry from serproto device array	write_lock_irqsave (&serproto_rwlock, flags);	device = serproto_device_array[interface];	serproto_device_array[interface] = NULL;	// Let write_wakeup_task know this device is toast.	device->tty = NULL;	write_unlock_irqrestore (&serproto_rwlock, flags);	// remove serial interace	tty_unregister_driver (&device->tty_driver);	// XXXX make sure write_wakeup_task is not scheduled!!!	kfree (device);	dbg_init (2, "->0");	return 0;}/**  * serproto_modexit - unload library * */void serproto_modexit (void){	int i;	int devices;	struct serproto_dev **device_array;	unsigned int flags;	dbg_init (1, "entered");	if (0 == serproto_devices) {		// nothing to do		return;	}	/* This should never be called from	   an interrupt context, so irq save/restore	   shouldn't be required, but it isn't going	   to be called often enough for the extra	   overhead to hurt either. */	write_lock_irqsave (&serproto_rwlock, flags);	devices = serproto_devices;	serproto_devices = 0;	write_unlock_irqrestore (&serproto_rwlock, flags);	for (i = 0; i < devices; i++) {		serproto_destroy (i);	}	write_lock_irqsave (&serproto_rwlock, flags);	device_array = serproto_device_array;	serproto_device_array = NULL;	write_unlock_irqrestore (&serproto_rwlock, flags);	kfree (serproto_device_array);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -