📄 usbserial.c
字号:
((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ dbg("found bulk in"); 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"); 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"); interrupt_in_endpoint[num_interrupt_in] = endpoint; ++num_interrupt_in; } }#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 (((dev->descriptor.idVendor == PL2303_VENDOR_ID) && (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) || ((dev->descriptor.idVendor == ATEN_VENDOR_ID) && (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) { if (ifnum == 1) { /* check out the endpoints of the other interface*/ struct usb_interface *other_iface; other_iface = &dev->actconfig->interface[ifnum ^ 1]; iface_desc = &other_iface->altsetting[0]; for (i = 0; i < iface_desc->bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i]; 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) { info("PL-2303 hack: descriptors matched but endpoints did not"); return NULL; } } /* END HORRIBLE HACK FOR PL2303 */#endif /* found all that we need */ info("%s converter detected", type->name);#ifdef CONFIG_USB_SERIAL_GENERIC if (type == &generic_device) { num_ports = num_bulk_out; if (num_ports == 0) { err("Generic device with no bulk out, not allowed."); return NULL; } } else#endif num_ports = type->num_ports; serial = get_free_serial (num_ports, &minor); if (serial == NULL) { err("No more free serial devices"); return NULL; } serial->dev = dev; serial->type = type; serial->interface = interface; 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->vendor = dev->descriptor.idVendor; serial->product = dev->descriptor.idProduct; /* 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); if (!port->read_urb) { err("No free urbs available"); goto probe_error; } buffer_size = endpoint->wMaxPacketSize; port->bulk_in_endpointAddress = endpoint->bEndpointAddress; port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!port->bulk_in_buffer) { err("Couldn't allocate bulk_in_buffer"); goto probe_error; } usb_fill_bulk_urb (port->read_urb, dev, usb_rcvbulkpipe (dev, endpoint->bEndpointAddress), port->bulk_in_buffer, buffer_size, ((serial->type->read_bulk_callback) ? serial->type->read_bulk_callback : generic_read_bulk_callback), port); } for (i = 0; i < num_bulk_out; ++i) { endpoint = bulk_out_endpoint[i]; port = &serial->port[i]; port->write_urb = usb_alloc_urb(0); if (!port->write_urb) { err("No free urbs available"); goto probe_error; } buffer_size = endpoint->wMaxPacketSize; port->bulk_out_size = buffer_size; port->bulk_out_endpointAddress = endpoint->bEndpointAddress; port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!port->bulk_out_buffer) { err("Couldn't allocate bulk_out_buffer"); goto probe_error; } usb_fill_bulk_urb (port->write_urb, dev, usb_sndbulkpipe (dev, endpoint->bEndpointAddress), port->bulk_out_buffer, buffer_size, ((serial->type->write_bulk_callback) ? serial->type->write_bulk_callback : generic_write_bulk_callback), port); } for (i = 0; i < num_interrupt_in; ++i) { endpoint = interrupt_in_endpoint[i]; port = &serial->port[i]; port->interrupt_in_urb = usb_alloc_urb(0); if (!port->interrupt_in_urb) { err("No free urbs available"); goto probe_error; } buffer_size = endpoint->wMaxPacketSize; port->interrupt_in_endpointAddress = endpoint->bEndpointAddress; port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!port->interrupt_in_buffer) { err("Couldn't allocate interrupt_in_buffer"); goto probe_error; } usb_fill_int_urb (port->interrupt_in_urb, dev, usb_rcvintpipe (dev, endpoint->bEndpointAddress), port->interrupt_in_buffer, buffer_size, serial->type->read_int_callback, port, endpoint->bInterval); } /* initialize some parts of the port structures */ /* 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, (int)serial->num_ports); dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = &serial->port[i]; port->number = i + serial->minor; port->serial = serial; port->magic = USB_SERIAL_PORT_MAGIC; port->tqueue.routine = port_softint; port->tqueue.data = port; init_MUTEX (&port->sem); } spin_lock_irqsave(&post_lock, flags); serial->ref = 1; spin_unlock_irqrestore(&post_lock, flags); /* if this device type has a startup function, call it */ if (type->startup) { i = type->startup (serial); if (i < 0) goto startup_error; if (i > 0) return serial; } /* initialize the devfs nodes for this device and let the user know what ports we are bound to */ for (i = 0; i < serial->num_ports; ++i) { tty_register_devfs (&serial_tty_driver, 0, serial->port[i].number); info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)", type->name, serial->port[i].number, serial->port[i].number); } return serial; /* success */startup_error: spin_lock_irqsave(&post_lock, flags); if (serial->ref != 1) { err("bug in component startup: ref %d\n", serial->ref); } spin_unlock_irqrestore(&post_lock, flags);probe_error: for (i = 0; i < num_bulk_in; ++i) { port = &serial->port[i]; if (port->read_urb) usb_free_urb (port->read_urb); if (port->bulk_in_buffer) kfree (port->bulk_in_buffer); } for (i = 0; i < num_bulk_out; ++i) { port = &serial->port[i]; if (port->write_urb) usb_free_urb (port->write_urb); if (port->bulk_out_buffer) kfree (port->bulk_out_buffer); } for (i = 0; i < num_interrupt_in; ++i) { port = &serial->port[i]; if (port->interrupt_in_urb) usb_free_urb (port->interrupt_in_urb); if (port->interrupt_in_buffer) kfree (port->interrupt_in_buffer); } /* return the minor range that this device had */ return_serial (serial); /* free up any memory that we allocated */ kfree (serial); return NULL;}static void usb_serial_disconnect(struct usb_device *dev, void *ptr){ struct usb_serial *serial = (struct usb_serial *) ptr; struct usb_serial_port *port; unsigned long flags; int i; dbg ("%s", __FUNCTION__); if (serial) { /* fail all future close/read/write/ioctl/etc calls */ for (i = 0; i < serial->num_ports; ++i) { port = &serial->port[i]; down (&port->sem); if (port->tty != NULL) while (port->open_count > 0) __serial_close(port, NULL); up (&port->sem); } serial->dev = NULL; serial_shutdown (serial); for (i = 0; i < serial->num_ports; ++i) serial->port[i].open_count = 0; for (i = 0; i < serial->num_bulk_in; ++i) { port = &serial->port[i]; if (port->read_urb) { usb_unlink_urb (port->read_urb); usb_free_urb (port->read_urb); } if (port->bulk_in_buffer) kfree (port->bulk_in_buffer); } for (i = 0; i < serial->num_bulk_out; ++i) { port = &serial->port[i]; if (port->write_urb) { usb_unlink_urb (port->write_urb); usb_free_urb (port->write_urb); } if (port->bulk_out_buffer) kfree (port->bulk_out_buffer); } for (i = 0; i < serial->num_interrupt_in; ++i) { port = &serial->port[i]; if (port->interrupt_in_urb) { usb_unlink_urb (port->interrupt_in_urb); usb_free_urb (port->interrupt_in_urb); } if (port->interrupt_in_buffer) kfree (port->interrupt_in_buffer); } for (i = 0; i < serial->num_ports; ++i) { tty_unregister_devfs (&serial_tty_driver, serial->port[i].number); info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->port[i].number); } /* return the minor range that this device had */ return_serial (serial); /* free up any memory that we allocated */ spin_lock_irqsave(&post_lock, flags); if (--serial->ref == 0) kfree(serial); spin_unlock_irqrestore(&post_lock, flags); } else { info("device disconnected"); }}static struct tty_driver serial_tty_driver = { .magic = TTY_DRIVER_MAGIC, .driver_name = "usb-serial",#ifndef CONFIG_DEVFS_FS .name = "ttyUSB",#else .name = "usb/tts/%d",#endif .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, .write = serial_write, .write_room = serial_write_room, .ioctl = serial_ioctl, .set_termios = serial_set_termios, .throttle = serial_throttle, .unthrottle = serial_unthrottle, .break_ctl = serial_break, .chars_in_buffer = serial_chars_in_buffer, .read_proc = serial_read_proc,};static int __init usb_serial_init(void){ int i; int result; /* Initalize our global data */ for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial_table[i] = NULL; } post_task.routine = post_helper; /* register the tty driver */ serial_tty_driver.init_termios = tty_std_termios; serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; if (tty_register_driver (&serial_tty_driver)) { err("%s - failed to register tty driver", __FUNCTION__); return -1; } /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { tty_unregister_driver(&serial_tty_driver); err("usb_register failed for the usb-serial driver. Error number %d", result); return -1; }#ifdef CONFIG_USB_SERIAL_GENERIC generic_device_ids[0].idVendor = vendor; generic_device_ids[0].idProduct = product; generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; /* register our generic driver with ourselves */ usb_serial_register (&generic_device);#endif info(DRIVER_DESC " " DRIVER_VERSION); return 0;}static void __exit usb_serial_exit(void){#ifdef CONFIG_USB_SERIAL_GENERIC /* remove our generic driver */ usb_serial_deregister (&generic_device);#endif usb_deregister(&usb_serial_driver); tty_unregister_driver(&serial_tty_driver);}module_init(usb_serial_init);module_exit(usb_serial_exit);int usb_serial_register(struct usb_serial_device_type *new_device){ /* Add this device to our list of devices */ list_add(&new_device->driver_list, &usb_serial_driver_list); info ("USB Serial support registered for %s", new_device->name); usb_scan_devices(); return 0;}void usb_serial_deregister(struct usb_serial_device_type *device){ struct usb_serial *serial; int i; info("USB Serial deregistering driver %s", device->name); /* clear out the serial_table if the device is attached to a port */ for(i = 0; i < SERIAL_TTY_MINORS; ++i) { serial = serial_table[i]; if ((serial != NULL) && (serial->type == device)) { usb_driver_release_interface (&usb_serial_driver, serial->interface); usb_serial_disconnect (NULL, serial); } } list_del(&device->driver_list);}/* If the usb-serial core is built into the core, the usb-serial drivers need these symbols to load properly as modules. */EXPORT_SYMBOL(usb_serial_register);EXPORT_SYMBOL(usb_serial_deregister);#ifdef USES_EZUSB_FUNCTIONS EXPORT_SYMBOL(ezusb_writememory); EXPORT_SYMBOL(ezusb_set_reset);#endif/* Module information */MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");#ifdef CONFIG_USB_SERIAL_GENERICMODULE_PARM(vendor, "h");MODULE_PARM_DESC(vendor, "User specified USB idVendor");MODULE_PARM(product, "h");MODULE_PARM_DESC(product, "User specified USB idProduct");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -