📄 usbserial.c
字号:
/* 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 + -