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

📄 usbserial.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* pass on to the driver specific version of this function */	if (serial->type->unthrottle)		serial->type->unthrottle(port);exit:	up (&port->sem);}static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	int retval = -ENODEV;	if (!serial)		return -ENODEV;	down (&port->sem);	dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);	if (!port->open_count) {		dbg ("%s - port not open", __FUNCTION__);		goto exit;	}	/* pass on to the driver specific version of this function if it is available */	if (serial->type->ioctl)		retval = serial->type->ioctl(port, file, cmd, arg);	else		retval = -ENOIOCTLCMD;exit:	up (&port->sem);	return retval;}static void serial_set_termios (struct tty_struct *tty, struct termios * old){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	if (!serial)		return;	down (&port->sem);	dbg("%s - port %d", __FUNCTION__, port->number);	if (!port->open_count) {		dbg("%s - port not open", __FUNCTION__);		goto exit;	}	/* pass on to the driver specific version of this function if it is available */	if (serial->type->set_termios)		serial->type->set_termios(port, old);exit:	up (&port->sem);}static void serial_break (struct tty_struct *tty, int break_state){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	if (!serial)		return;	down (&port->sem);	dbg("%s - port %d", __FUNCTION__, port->number);	if (!port->open_count) {		dbg("%s - port not open", __FUNCTION__);		goto exit;	}	/* pass on to the driver specific version of this function if it is available */	if (serial->type->break_ctl)		serial->type->break_ctl(port, break_state);exit:	up (&port->sem);}static void serial_shutdown (struct usb_serial *serial){	dbg ("%s", __FUNCTION__);	if (serial->type->shutdown)		serial->type->shutdown(serial);	else		generic_shutdown(serial);}static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data){	struct usb_serial *serial;	int length = 0;	int i;	off_t begin = 0;	char tmp[40];	dbg("%s", __FUNCTION__);	length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);	for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {		serial = get_serial_by_minor(i);		if (serial == NULL)			continue;		length += sprintf (page+length, "%d:", i);		if (serial->type->owner)			length += sprintf (page+length, " module:%s", serial->type->owner->name);		length += sprintf (page+length, " name:\"%s\"", serial->type->name);		length += sprintf (page+length, " vendor:%04x product:%04x", serial->vendor, serial->product);		length += sprintf (page+length, " num_ports:%d", serial->num_ports);		length += sprintf (page+length, " port:%d", i - serial->minor + 1);		usb_make_path(serial->dev, tmp, sizeof(tmp));		length += sprintf (page+length, " path:%s", tmp);					length += sprintf (page+length, "\n");		if ((length + begin) > (off + count))			goto done;		if ((length + begin) < off) {			begin += length;			length = 0;		}	}	*eof = 1;done:	if (off >= (length + begin))		return 0;	*start = page + (off-begin);	return ((count < begin+length-off) ? count : begin+length-off);}/***************************************************************************** * generic devices specific driver functions *****************************************************************************/static int generic_open (struct usb_serial_port *port, struct file *filp){	struct usb_serial *serial = port->serial;	int result = 0;	if (port_paranoia_check (port, __FUNCTION__))		return -ENODEV;	dbg("%s - port %d", __FUNCTION__, port->number);	/* force low_latency on so that our tty_push actually forces the data through, 	   otherwise it is scheduled, and with high data rates (like with OHCI) data	   can get lost. */	if (port->tty)		port->tty->low_latency = 1;	/* if we have a bulk interrupt, start reading from it */	if (serial->num_bulk_in) {		/* Start reading from the device */		usb_fill_bulk_urb (port->read_urb, serial->dev,				   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),				   port->read_urb->transfer_buffer,				   port->read_urb->transfer_buffer_length,				   ((serial->type->read_bulk_callback) ?				     serial->type->read_bulk_callback :				     generic_read_bulk_callback),				   port);		result = usb_submit_urb(port->read_urb);		if (result)			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);	}	return result;}static void generic_cleanup (struct usb_serial_port *port){	struct usb_serial *serial = port->serial;	dbg("%s - port %d", __FUNCTION__, port->number);	if (serial->dev) {		/* shutdown any bulk reads that might be going on */		if (serial->num_bulk_out)			usb_unlink_urb (port->write_urb);		if (serial->num_bulk_in)			usb_unlink_urb (port->read_urb);	}}static void generic_close (struct usb_serial_port *port, struct file * filp){	dbg("%s - port %d", __FUNCTION__, port->number);	generic_cleanup (port);}static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count){	struct usb_serial *serial = port->serial;	int result;	unsigned long flags;	if (count == 0) {		dbg("%s - write request of 0 bytes", __FUNCTION__);		return (0);	}	if (count < 0) {		err("%s - port %d: write request of %d bytes", __FUNCTION__,		    port->number, count);		return (0);	}	/* only do something if we have a bulk out endpoint */	if (serial->num_bulk_out) {		if (port->write_busy) {			/* Happens when two threads run port_helper. Watch. */			info("%s - already writing", __FUNCTION__);			return (0);		}		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;		if (from_user) {			if (copy_from_user(port->write_urb->transfer_buffer, buf, count))				return -EFAULT;		} else {			memcpy (port->write_urb->transfer_buffer, buf, count);		}		dbg("%s - port %d [%d]", __FUNCTION__, port->number, count);		/* set up our urb */		usb_fill_bulk_urb (port->write_urb, serial->dev,				   usb_sndbulkpipe (serial->dev,						    port->bulk_out_endpointAddress),				   port->write_urb->transfer_buffer, count,				   ((serial->type->write_bulk_callback) ? 				     serial->type->write_bulk_callback :				     generic_write_bulk_callback), port);		/* send the data out the bulk port */		port->write_busy = 1;		result = usb_submit_urb(port->write_urb);		if (result) {			err("%s - port %d: failed submitting write urb (%d)",			     __FUNCTION__, port->number, result);			port->write_busy = 0;			spin_lock_irqsave(&post_lock, flags);			if (port->write_backlog != 0)				schedule_task(&post_task);			spin_unlock_irqrestore(&post_lock, flags);		} else			result = count;		return result;	}	/* no bulk out, so return 0 bytes written */	return (0);}static int generic_write_room (struct usb_serial_port *port){	struct usb_serial *serial = port->serial;	int room = 0;	if (serial->num_bulk_out) {		if (!port->write_busy && port->write_backlog == 0)			room = port->bulk_out_size;	}	dbg("%s - port %d, returns %d", __FUNCTION__, port->number, room);	return (room);}static int generic_chars_in_buffer (struct usb_serial_port *port){	struct usb_serial *serial = port->serial;	int chars = 0;	dbg("%s - port %d", __FUNCTION__, port->number);	if (serial->num_bulk_out) {		if (port->write_busy)			chars += port->write_urb->transfer_buffer_length;		chars += port->write_backlog;	/* spin_lock... Baah */	}	dbg("%s - returns %d", __FUNCTION__, chars);	return (chars);}static void generic_read_bulk_callback (struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;	int i;	int result;	dbg("%s - port %d", __FUNCTION__, port->number);	if (!serial) {		dbg("%s - bad serial pointer, exiting", __FUNCTION__);		return;	}	if (urb->status) {		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);		return;	}	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);	tty = port->tty;	if (tty && urb->actual_length) {		for (i = 0; i < urb->actual_length ; ++i) {			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {				tty_flip_buffer_push(tty);			}			/* this doesn't actually push the data through unless tty->low_latency is set */			tty_insert_flip_char(tty, data[i], 0);		}	  	tty_flip_buffer_push(tty);	}	/* Continue trying to always read  */	usb_fill_bulk_urb (port->read_urb, serial->dev,			   usb_rcvbulkpipe (serial->dev,				   	    port->bulk_in_endpointAddress),			   port->read_urb->transfer_buffer,			   port->read_urb->transfer_buffer_length,			   ((serial->type->read_bulk_callback) ? 			     serial->type->read_bulk_callback : 			     generic_read_bulk_callback), port);	result = usb_submit_urb(port->read_urb);	if (result)		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);}static void generic_write_bulk_callback (struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	dbg("%s - port %d", __FUNCTION__, port->number);	port->write_busy = 0;	wmb();	if (!serial) {		err("%s - null serial pointer, exiting", __FUNCTION__);		return;	}	if (urb->status) {		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);	}	queue_task(&port->tqueue, &tq_immediate);	mark_bh(IMMEDIATE_BH);	return;}static void generic_shutdown (struct usb_serial *serial){	int i;	dbg("%s", __FUNCTION__);	/* stop reads and writes on all ports */	for (i=0; i < serial->num_ports; ++i) {		generic_cleanup (&serial->port[i]);	}}static void port_softint(void *private){	struct usb_serial_port *port = (struct usb_serial_port *)private;	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);	struct tty_struct *tty;	unsigned long flags;	struct tty_ldisc *ld;	dbg("%s - port %d", __FUNCTION__, port->number);		if (!serial)		return;	spin_lock_irqsave(&post_lock, flags);	if (port->write_backlog != 0)		schedule_task(&post_task);	spin_unlock_irqrestore(&post_lock, flags);	tty = port->tty;	if (!tty)		return;	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) {		ld = tty_ldisc_ref(tty);		if(ld) {			if(ld->write_wakeup) {				ld->write_wakeup(tty);				dbg("%s - write wakeup call.", __FUNCTION__);			}			tty_ldisc_deref(ld);		}	}	wake_up_interruptible(&tty->write_wait);}static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,			       const struct usb_device_id *id){	struct usb_serial *serial = NULL;	struct usb_serial_port *port;	struct usb_interface *interface;	struct usb_interface_descriptor *iface_desc;	struct usb_endpoint_descriptor *endpoint;	struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];	struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];	struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];	struct usb_serial_device_type *type = NULL;	struct list_head *tmp;	int found;	int minor;	int buffer_size;	int i;	int num_interrupt_in = 0;	int num_bulk_in = 0;	int num_bulk_out = 0;	int num_ports;	int max_endpoints;	const struct usb_device_id *id_pattern = NULL;	unsigned long flags;	/* loop through our list of known serial converters, and see if this	   device matches. */	found = 0;	interface = &dev->actconfig->interface[ifnum];	list_for_each (tmp, &usb_serial_driver_list) {		type = list_entry(tmp, struct usb_serial_device_type, driver_list);		id_pattern = usb_match_id(dev, interface, type->id_table);		if (id_pattern != NULL) {			dbg("descriptor matches");			found = 1;			break;		}	}	if (!found) {		/* no match */		dbg("none matched");		return(NULL);	}		/* descriptor matches, let's find the endpoints needed */	/* check out the endpoints */	iface_desc = &interface->altsetting[0];	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {		endpoint = &iface_desc->endpoint[i];				if ((endpoint->bEndpointAddress & 0x80) &&

⌨️ 快捷键说明

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