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

📄 usb-serial.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (port->serial->type->set_termios)		port->serial->type->set_termios(port, old);}static void serial_break (struct tty_struct *tty, int break_state){	struct usb_serial_port *port = tty->driver_data;	dbg("%s - port %d", __FUNCTION__, port->number);	if (!port->open_count) {		dbg("%s - port not open", __FUNCTION__);		return;	}	/* 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);}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:2.0\n");	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->driver.owner)			length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));		length += sprintf (page+length, " name:\"%s\"", serial->type->description);		length += sprintf (page+length, " vendor:%04x product:%04x", 				   le16_to_cpu(serial->dev->descriptor.idVendor), 				   le16_to_cpu(serial->dev->descriptor.idProduct));		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, destroy_serial);	}	*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 = 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 = 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 = private;	struct tty_struct *tty;	dbg("%s - port %d", __FUNCTION__, port->number);		if (!port)		return;	tty = port->tty;	if (!tty)		return;	tty_wakeup(tty);}static void port_release(struct device *dev){	struct usb_serial_port *port = to_usb_serial_port(dev);	dbg ("%s - %s", __FUNCTION__, dev->bus_id);	usb_kill_urb(port->read_urb);	usb_free_urb(port->read_urb);	usb_kill_urb(port->write_urb);	usb_free_urb(port->write_urb);	usb_kill_urb(port->interrupt_in_urb);	usb_free_urb(port->interrupt_in_urb);	usb_kill_urb(port->interrupt_out_urb);	usb_free_urb(port->interrupt_out_urb);	kfree(port->bulk_in_buffer);	kfree(port->bulk_out_buffer);	kfree(port->interrupt_in_buffer);	kfree(port->interrupt_out_buffer);	kfree(port);}static struct usb_serial * create_serial (struct usb_device *dev, 					  struct usb_interface *interface,					  struct usb_serial_driver *driver){	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 = driver;	serial->interface = interface;	kref_init(&serial->kref);	return serial;}static struct usb_serial_driver *search_serial_device(struct usb_interface *iface){	struct list_head *p;	const struct usb_device_id *id;	struct usb_serial_driver *t;	/* List trough know devices and see if the usb id matches */	list_for_each(p, &usb_serial_driver_list) {		t = list_entry(p, struct usb_serial_driver, driver_list);		id = usb_match_id(iface, t->id_table);		if (id != NULL) {			dbg("descriptor matches");			return t;		}	}	return NULL;}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 *interrupt_out_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_driver *type = NULL;	int retval;	int minor;	int buffer_size;	int i;	int num_interrupt_in = 0;	int num_interrupt_out = 0;	int num_bulk_in = 0;	int num_bulk_out = 0;	int num_ports = 0;	int max_endpoints;	type = search_serial_device(interface);	if (!type) {		dbg("none matched");		return -ENODEV;	}	serial = create_serial (dev, interface, type);	if (!serial) {		dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);		return -ENOMEM;	}	/* if this device type has a probe function, call it */	if (type->probe) {		const struct usb_device_id *id;		if (!try_module_get(type->driver.owner)) {			dev_err(&interface->dev, "module get failed, exiting\n");			kfree (serial);			return -EIO;		}		id = usb_match_id(interface, type->id_table);		retval = type->probe(serial, id);		module_put(type->driver.owner);		if (retval) {			dbg ("sub driver rejected device");			kfree (serial);			return retval;		}	}	/* descriptor matches, let's find the endpoints needed */	/* check out the endpoints */	iface_desc = interface->cur_altsetting;	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {		endpoint = &iface_desc->endpoint[i].desc;				if ((endpoint->bEndpointAddress & 0x80) &&		    ((endpoint->bmAttributes & 3) == 0x02)) {			/* we found a bulk in endpoint */			dbg("found bulk in on endpoint %d", i);			bulk_in_endpoint[num_bulk_in] = endpoint;			++num_bulk_in;		}		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&		    ((endpoint->bmAttributes & 3) == 0x02)) {			/* we found a bulk out endpoint */			dbg("found bulk out on endpoint %d", i);			bulk_out_endpoint[num_bulk_out] = endpoint;			++num_bulk_out;		}				if ((endpoint->bEndpointAddress & 0x80) &&		    ((endpoint->bmAttributes & 3) == 0x03)) {			/* we found a interrupt in endpoint */			dbg("found interrupt in on endpoint %d", i);			interrupt_in_endpoint[num_interrupt_in] = endpoint;			++num_interrupt_in;		}		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&		    ((endpoint->bmAttributes & 3) == 0x03)) {			/* we found an interrupt out endpoint */			dbg("found interrupt out on endpoint %d", i);			interrupt_out_endpoint[num_interrupt_out] = endpoint;			++num_interrupt_out;		}	}#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)	/* BEGIN HORRIBLE HACK FOR PL2303 */ 	/* this is needed due to the looney way its endpoints are set up */	if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&	     (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||	    ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&	     (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) {		if (interface != dev->actconfig->interface[0]) {			/* check out the endpoints of the other interface*/			iface_desc = dev->actconfig->interface[0]->cur_altsetting;			for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {				endpoint = &iface_desc->endpoint[i].desc;				if ((endpoint->bEndpointAddress & 0x80) &&				    ((endpoint->bmAttributes & 3) == 0x03)) {					/* we found a interrupt in endpoint */					dbg("found interrupt in for Prolific device on separate interface");					interrupt_in_endpoint[num_interrupt_in] = endpoint;					++num_interrupt_in;				}			}		}		/* Now make sure the PL-2303 is configured correctly.		 * If not, give up now and hope this hack will work		 * properly during a later invocation of usb_serial_probe		 */		if (num_bulk_in == 0 || num_bulk_out == 0) {			dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");			kfree (serial);			return -ENODEV;		}	}	/* END HORRIBLE HACK FOR PL2303 */#endif	/* found all that we need */	dev_info(&interface->dev, "%s converter detected\n", type->description);#ifdef CONFIG_USB_SERIAL_GENERIC	if (type == &usb_serial_generic_device) {		num_ports = num_bulk_out;		if (num_ports == 0) {			dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");			kfree (serial);			return -EIO;		}	}#endif	if (!num_ports) {		/* if this device type has a calc_num_ports function, call it */		if (type->calc_num_ports) {			if (!try_module_get(type->driver.owner)) {				dev_err(&interface->dev, "module get failed, exiting\n");				kfree (serial);				return -EIO;			}			num_ports = type->calc_num_ports (serial);			module_put(type->driver.owner);		}		if (!num_ports)			num_ports = type->num_ports;	}	if (get_free_serial (serial, num_ports, &minor) == NULL) {		dev_err(&interface->dev, "No more free serial devices\n");		kfree (serial);		return -ENOMEM;	}	serial->minor = minor;	serial->num_ports = num_ports;	serial->num_bulk_in = num_bulk_in;	serial->num_bulk_out = num_bulk_out;	serial->num_interrupt_in = num_interrupt_in;	serial->num_interrupt_out = num_interrupt_out;	/* create our ports, we need as many as the max endpoints */	/* we don't use num_ports here cauz some devices have more endpoint pairs than ports */	max_endpoints = max(num_bulk_in, num_bulk_out);	max_endpoints = max(max_endpoints, num_interrupt_in);	max_endpoints = max(max_endpoints, num_interrupt_out);	max_endpoints = max(max_endpoints, (int)serial->num_ports);	serial->num_port_pointers = max_endpoints;	dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);	for (i = 0; i < max_endpoints; ++i) {		port = kmalloc(sizeof(struct usb_serial_port), GFP_KERNEL);		if (!port)			goto probe_error;		memset(port, 0x00, sizeof(struct usb_serial_port));		port->number = i + serial->minor;		port->serial = serial;		spin_lock_init(&port->lock);		INIT_WORK(&port->work, usb_serial_port_softint, port);		serial->port[i] = port;	}	/* set up the endpoint information */	for (i = 0; i < num_bulk_in; ++i) {		endpoint = bulk_in_endpoint[i];		port = serial->port[i];		port->read_urb = usb_alloc_urb (0, GFP_KERNEL);		if (!port->read_urb) {			dev_err(&interface->dev, "No free urbs available\n");			goto probe_error;

⌨️ 快捷键说明

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