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

📄 usb-serial.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
{	struct usb_serial *serial;	struct usb_serial_port *port;	unsigned int portNumber;	int retval;		dbg("%s", __FUNCTION__);	/* get the serial object associated with this tty pointer */	serial = usb_serial_get_by_index(tty->index);	if (!serial) {		tty->driver_data = NULL;		return -ENODEV;	}	portNumber = tty->index - serial->minor;	port = serial->port[portNumber];	 	++port->open_count;	if (port->open_count == 1) {		/* set up our port structure making the tty driver		 * remember our port object, and us it */		tty->driver_data = port;		port->tty = tty;		/* lock this module before we call it		 * this may fail, which means we must bail out,		 * safe because we are called with BKL held */		if (!try_module_get(serial->type->owner)) {			retval = -ENODEV;			goto bailout_kref_put;		}		/* only call the device specific open if this 		 * is the first time the port is opened */		retval = serial->type->open(port, filp);		if (retval)			goto bailout_module_put;	}	return 0;bailout_module_put:	module_put(serial->type->owner);bailout_kref_put:	kref_put(&serial->kref, destroy_serial);	port->open_count = 0;	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);	if (port->open_count == 0)		return;	--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);		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, destroy_serial);}static int serial_write (struct tty_struct * tty, 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, 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__);		return;	}	/* pass on to the driver specific version of this function */	if (port->serial->type->throttle)		port->serial->type->throttle(port);}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__);		return;	}	/* pass on to the driver specific version of this function */	if (port->serial->type->unthrottle)		port->serial->type->unthrottle(port);}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__);		return;	}	/* 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);}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__);		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:%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", 				   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 = (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;	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_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;	kref_init(&serial->kref);	return serial;}static struct usb_serial_device_type *search_serial_device(struct usb_interface *iface){	struct list_head *p;	const struct usb_device_id *id;	struct usb_serial_device_type *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_device_type, 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_device_type *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->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->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;		}	}

⌨️ 快捷键说明

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