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

📄 usb-serial.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		retval = serial->type->open(port, filp);		if (retval) {			port->open_count = 0;			module_put(serial->type->owner);			kref_put(&serial->kref);		}	}bailout:	return retval;}static void serial_close(struct tty_struct *tty, struct file * filp){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	if (!port)		return;	dbg("%s - port %d", __FUNCTION__, port->number);	--port->open_count;	if (port->open_count <= 0) {		/* only call the device specific close if this 		 * port is being closed by the last owner */		port->serial->type->close(port, filp);		port->open_count = 0;		if (port->tty) {			if (port->tty->driver_data)				port->tty->driver_data = NULL;			port->tty = NULL;		}	}	module_put(port->serial->type->owner);	kref_put(&port->serial->kref);}static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	int retval = -EINVAL;	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);	if (!port->open_count) {		dbg("%s - port not opened", __FUNCTION__);		goto exit;	}	/* pass on to the driver specific version of this function */	retval = port->serial->type->write(port, from_user, buf, count);exit:	return retval;}static int serial_write_room (struct tty_struct *tty) {	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	int retval = -EINVAL;	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 */	retval = port->serial->type->write_room(port);exit:	return retval;}static int serial_chars_in_buffer (struct tty_struct *tty) {	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	int retval = -EINVAL;	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 */	retval = port->serial->type->chars_in_buffer(port);exit:	return retval;}static void serial_throttle (struct tty_struct * tty){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	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 (port->serial->type->throttle)		port->serial->type->throttle(port);exit:	;}static void serial_unthrottle (struct tty_struct * tty){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	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 (port->serial->type->unthrottle)		port->serial->type->unthrottle(port);exit:	;}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;	int retval = -ENODEV;	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 (port->serial->type->ioctl)		retval = port->serial->type->ioctl(port, file, cmd, arg);	else		retval = -ENOIOCTLCMD;exit:	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;	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 (port->serial->type->set_termios)		port->serial->type->set_termios(port, old);exit:	;}static void serial_break (struct tty_struct *tty, int break_state){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	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 (port->serial->type->break_ctl)		port->serial->type->break_ctl(port, break_state);exit:	;}static void serial_shutdown (struct usb_serial *serial){	dbg ("%s", __FUNCTION__);	serial->type->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 = usb_serial_get_by_index(i);		if (serial == NULL)			continue;		length += sprintf (page+length, "%d:", i);		if (serial->type->owner)			length += sprintf (page+length, " module:%s", module_name(serial->type->owner));		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;		}		kref_put(&serial->kref);	}	*eof = 1;done:	if (off >= (length + begin))		return 0;	*start = page + (off-begin);	return ((count < begin+length-off) ? count : begin+length-off);}static int serial_tiocmget (struct tty_struct *tty, struct file *file){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	dbg("%s - port %d", __FUNCTION__, port->number);	if (!port->open_count) {		dbg("%s - port not open", __FUNCTION__);		goto exit;	}	if (port->serial->type->tiocmget)		return port->serial->type->tiocmget(port, file);exit:	return -EINVAL;}static int serial_tiocmset (struct tty_struct *tty, struct file *file,			    unsigned int set, unsigned int clear){	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;	dbg("%s - port %d", __FUNCTION__, port->number);	if (!port->open_count) {		dbg("%s - port not open", __FUNCTION__);		goto exit;	}	if (port->serial->type->tiocmset)		return port->serial->type->tiocmset(port, file, set, clear);exit:	return -EINVAL;}void usb_serial_port_softint(void *private){	struct usb_serial_port *port = (struct usb_serial_port *)private;	struct tty_struct *tty;	dbg("%s - port %d", __FUNCTION__, port->number);		if (!port)		return;	tty = port->tty;	if (!tty)		return;	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {		dbg("%s - write wakeup call.", __FUNCTION__);		(tty->ldisc.write_wakeup)(tty);	}	wake_up_interruptible(&tty->write_wait);}static void destroy_serial(struct kref *kref){	struct usb_serial *serial;	struct usb_serial_port *port;	int i;	serial = to_usb_serial(kref);	dbg ("%s - %s", __FUNCTION__, serial->type->name);	serial_shutdown (serial);	/* return the minor range that this device had */	return_serial(serial);	for (i = 0; i < serial->num_ports; ++i)		serial->port[i]->open_count = 0;	/* the ports are cleaned up and released in port_release() */	for (i = 0; i < serial->num_ports; ++i)		if (serial->port[i]->dev.parent != NULL) {			device_unregister(&serial->port[i]->dev);			serial->port[i] = NULL;		}	/* If this is a "fake" port, we have to clean it up here, as it will	 * not get cleaned up in port_release() as it was never registered with	 * the driver core */	if (serial->num_ports < serial->num_port_pointers) {		for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {			port = serial->port[i];			if (!port)				continue;			if (port->read_urb) {				usb_unlink_urb(port->read_urb);				usb_free_urb(port->read_urb);			}			if (port->write_urb) {				usb_unlink_urb(port->write_urb);				usb_free_urb(port->write_urb);			}			if (port->interrupt_in_urb) {				usb_unlink_urb(port->interrupt_in_urb);				usb_free_urb(port->interrupt_in_urb);			}			kfree(port->bulk_in_buffer);			kfree(port->bulk_out_buffer);			kfree(port->interrupt_in_buffer);		}	}	usb_put_dev(serial->dev);	/* free up any memory that we allocated */	kfree (serial);}static void port_release(struct device *dev){	struct usb_serial_port *port = to_usb_serial_port(dev);	dbg ("%s - %s", __FUNCTION__, dev->bus_id);	if (port->read_urb) {		usb_unlink_urb(port->read_urb);		usb_free_urb(port->read_urb);	}	if (port->write_urb) {		usb_unlink_urb(port->write_urb);		usb_free_urb(port->write_urb);	}	if (port->interrupt_in_urb) {		usb_unlink_urb(port->interrupt_in_urb);		usb_free_urb(port->interrupt_in_urb);	}	kfree(port->bulk_in_buffer);	kfree(port->bulk_out_buffer);	kfree(port->interrupt_in_buffer);	kfree(port);}static struct usb_serial * create_serial (struct usb_device *dev, 					  struct usb_interface *interface,					  struct usb_serial_device_type *type){	struct usb_serial *serial;	serial = kmalloc (sizeof (*serial), GFP_KERNEL);	if (!serial) {		dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);		return NULL;	}	memset (serial, 0, sizeof(*serial));	serial->dev = usb_get_dev(dev);	serial->type = type;	serial->interface = interface;	serial->vendor = dev->descriptor.idVendor;	serial->product = dev->descriptor.idProduct;	kref_init(&serial->kref, destroy_serial);	return serial;}int usb_serial_probe(struct usb_interface *interface,			       const struct usb_device_id *id){	struct usb_device *dev = interface_to_usbdev (interface);	struct usb_serial *serial = NULL;	struct usb_serial_port *port;	struct usb_host_interface *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 retval;	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 = 0;	int max_endpoints;	const struct usb_device_id *id_pattern = NULL;	/* loop through our list of known serial converters, and see if this	   device matches. */	found = 0;	list_for_each (tmp, &usb_serial_driver_list) {		type = list_entry(tmp, struct usb_serial_device_type, driver_list);		id_pattern = usb_match_id(interface, type->id_table);		if (id_pattern != NULL) {			dbg("descriptor matches");			found = 1;			break;		}	}	if (!found) {		/* no match */		dbg("none matched");		return -ENODEV;	}	serial = create_serial (dev, interface, type);	if (!serial) {		dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);		return -ENODEV;	}	/* if this device type has a probe function, call it */	if (type->probe) {		if (!try_module_get(type->owner)) {			dev_err(&interface->dev, "module get failed, exiting\n");			kfree (serial);			return -EIO;		}		retval = type->probe (serial, id_pattern);		module_put(type->owner);		if (retval) {

⌨️ 快捷键说明

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