📄 usb-serial.c
字号:
usb_unlink_urb (&serial->write_urb); usb_unlink_urb (&serial->read_urb); serial->active = 0;}static void visor_throttle (struct tty_struct * tty){/* struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */ dbg("visor_throttle"); /* Change the control signals */ /* FIXME!!! */ return;}static void visor_unthrottle (struct tty_struct * tty){/* struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */ dbg("visor_unthrottle"); /* Change the control signals */ /* FIXME!!! */ return;}#endif /* CONFIG_USB_SERIAL_VISOR*//***************************************************************************** * generic devices specific driver functions *****************************************************************************/static int generic_serial_open (struct tty_struct *tty, struct file *filp){ struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; dbg("generic_serial_open"); if (!serial->present) { dbg("no device registered"); return -EINVAL; } if (serial->active) { dbg ("device already open"); return -EINVAL; } serial->active = 1; /* if we have a bulk interrupt, start reading from it */ if (serial->num_bulk_in) { /*Start reading from the device*/ if (usb_submit_urb(&serial->read_urb)) dbg("usb_submit_urb(read bulk) failed"); } return (0);}static void generic_serial_close(struct tty_struct *tty, struct file * filp){ struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; dbg("generic_serial_close"); /* shutdown any bulk reads that might be going on */ if (serial->num_bulk_out) { usb_unlink_urb (&serial->write_urb); } if (serial->num_bulk_in) { usb_unlink_urb (&serial->read_urb); } serial->active = 0;}static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; dbg("generic_serial_write"); if (count == 0) { dbg("write request of 0 bytes"); return (0); } /* only do something if we have a bulk out endpoint */ if (serial->num_bulk_out) { if (serial->write_urb.status == -EINPROGRESS) { dbg ("already writing"); return (0); } count = (count > serial->bulk_out_size[0]) ? serial->bulk_out_size[0] : count; if (from_user) { copy_from_user(serial->write_urb.transfer_buffer, buf, count); } else { memcpy (serial->write_urb.transfer_buffer, buf, count); } /* send the data out the bulk port */ serial->write_urb.transfer_buffer_length = count; if (usb_submit_urb(&serial->write_urb)) dbg("usb_submit_urb(write bulk) failed"); return (count); } /* no bulk out, so return 0 bytes written */ return (0);} static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch){ struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; dbg("generic_serial_put_char"); /* if we have a bulk out endpoint, then shove a character out it */ if (serial->num_bulk_out) { /* send the single character out the bulk port */ memcpy (serial->write_urb.transfer_buffer, &ch, 1); serial->write_urb.transfer_buffer_length = 1; if (usb_submit_urb(&serial->write_urb)) dbg("usb_submit_urb(write bulk) failed"); } return;}static int generic_write_room (struct tty_struct *tty) { struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; int room; dbg("generic_write_room"); if (serial->num_bulk_out) { if (serial->write_urb.status == -EINPROGRESS) room = 0; else room = serial->bulk_out_size[0]; dbg("generic_write_room returns %d", room); return (room); } return (0);}static int generic_chars_in_buffer (struct tty_struct *tty) { struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; dbg("generic_chars_in_buffer"); if (serial->num_bulk_out) { if (serial->write_urb.status == -EINPROGRESS) { return (serial->bulk_out_size[0]); } } return (0);}static int Get_Free_Serial (void){ int i; for (i=0; i < NUM_PORTS; ++i) { if (!serial_state_table[i].present) return (i); } return (-1);}static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum){ struct usb_serial_state *serial = NULL; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_ENDPOINTS]; struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_ENDPOINTS]; struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_ENDPOINTS]; struct usb_serial_device_type *type; int device_num; int serial_num; int i; char interrupt_pipe; char bulk_in_pipe; char bulk_out_pipe; int num_interrupt_in = 0; int num_bulk_in = 0; int num_bulk_out = 0; /* loop through our list of known serial converters, and see if this device matches */ device_num = 0; while (usb_serial_devices[device_num] != NULL) { type = usb_serial_devices[device_num]; dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct)); /* look at the device descriptor */ if ((dev->descriptor.idVendor == *(type->idVendor)) && (dev->descriptor.idProduct == *(type->idProduct))) { dbg("descriptor matches...looking at the endpoints"); /* descriptor matches, let's try to find the endpoints needed */ interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT; /* check out the endpoints */ interface = &dev->actconfig->interface[ifnum].altsetting[0]; for (i = 0; i < interface->bNumEndpoints; ++i) { endpoint = &interface->endpoint[i]; if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ dbg("found bulk in"); bulk_in_pipe = HAS; 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_pipe = HAS; 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_pipe = HAS; interrupt_in_endpoint[num_interrupt_in] = endpoint; ++num_interrupt_in; } } /* verify that we found all of the endpoints that we need */ if ((interrupt_pipe & type->needs_interrupt_in) && (bulk_in_pipe & type->needs_bulk_in) && (bulk_out_pipe & type->needs_bulk_out)) { /* found all that we need */ info("%s converter detected", type->name); if (0>(serial_num = Get_Free_Serial())) { dbg("Too many devices connected"); return NULL; } serial = &serial_state_table[serial_num]; memset(serial, 0, sizeof(struct usb_serial_state)); serial->dev = dev; serial->type = type; serial->number = serial_num; serial->num_bulk_in = num_bulk_in; serial->num_bulk_out = num_bulk_out; serial->num_interrupt_in = num_interrupt_in; /* if this device type has a startup function, call it */ if (type->startup) { if (type->startup (serial)) return NULL; } /* set up the endpoint information */ for (i = 0; i < num_bulk_in; ++i) { serial->bulk_in_endpoint[i] = bulk_in_endpoint[i]->bEndpointAddress; serial->bulk_in_size[i] = bulk_in_endpoint[i]->wMaxPacketSize; serial->bulk_in_interval[i] = bulk_in_endpoint[i]->bInterval; serial->bulk_in_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[i]); serial->bulk_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL); if (!serial->bulk_in_buffer[i]) { err("Couldn't allocate bulk_in_buffer"); goto probe_error; } } if (num_bulk_in) FILL_BULK_URB(&serial->read_urb, dev, usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[0]), serial->bulk_in_buffer[0], serial->bulk_in_size[0], serial_read_bulk, serial); for (i = 0; i < num_bulk_out; ++i) { serial->bulk_out_endpoint[i] = bulk_out_endpoint[i]->bEndpointAddress; serial->bulk_out_size[i] = bulk_out_endpoint[i]->wMaxPacketSize; serial->bulk_out_interval[i] = bulk_out_endpoint[i]->bInterval; serial->bulk_out_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint[i]); serial->bulk_out_buffer[i] = kmalloc (serial->bulk_out_size[i], GFP_KERNEL); if (!serial->bulk_out_buffer[i]) { err("Couldn't allocate bulk_out_buffer"); goto probe_error; } } if (num_bulk_out) FILL_BULK_URB(&serial->write_urb, dev, usb_sndbulkpipe (dev, serial->bulk_in_endpoint[0]), serial->bulk_in_buffer[0], serial->bulk_in_size[0], serial_write_bulk, serial); for (i = 0; i < num_interrupt_in; ++i) { serial->interrupt_in_inuse = 0; serial->interrupt_in_endpoint[i] = interrupt_in_endpoint[i]->bEndpointAddress; serial->interrupt_in_size[i] = interrupt_in_endpoint[i]->wMaxPacketSize; serial->interrupt_in_interval[i] = interrupt_in_endpoint[i]->bInterval; /* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */ serial->interrupt_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL); if (!serial->interrupt_in_buffer[i]) { err("Couldn't allocate interrupt_in_buffer"); goto probe_error; } } #if 0 /* set up an interrupt for out bulk in pipe */ /* ask for a bulk read */ serial->bulk_in_inuse = 1; serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); /* set up our interrupt to be the time for the bulk in read */ ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle); if (ret) { info("failed usb_request_irq (0x%x)", ret); goto probe_error; } #endif serial->present = 1; MOD_INC_USE_COUNT; info("%s converter now attached to ttyUSB%d", type->name, serial_num); return serial; } else { info("descriptors matched, but endpoints did not"); } } /* look at the next type in our list */ ++device_num; }probe_error: if (serial) { for (i = 0; i < num_bulk_in; ++i) if (serial->bulk_in_buffer[i]) kfree (serial->bulk_in_buffer[i]); for (i = 0; i < num_bulk_out; ++i) if (serial->bulk_out_buffer[i]) kfree (serial->bulk_out_buffer[i]); for (i = 0; i < num_interrupt_in; ++i) if (serial->interrupt_in_buffer[i]) kfree (serial->interrupt_in_buffer[i]); } return NULL;}static void usb_serial_disconnect(struct usb_device *dev, void *ptr){ struct usb_serial_state *serial = (struct usb_serial_state *) ptr; int i; if (serial) { if (!serial->present) { /* something strange is going on */ dbg("disconnect but not present?"); return; } /* need to stop any transfers...*/ usb_unlink_urb (&serial->write_urb); usb_unlink_urb (&serial->read_urb); /* free up any memory that we allocated */ for (i = 0; i < serial->num_bulk_in; ++i) if (serial->bulk_in_buffer[i]) kfree (serial->bulk_in_buffer[i]); for (i = 0; i < serial->num_bulk_out; ++i) if (serial->bulk_out_buffer[i]) kfree (serial->bulk_out_buffer[i]); for (i = 0; i < serial->num_interrupt_in; ++i) if (serial->interrupt_in_buffer[i]) kfree (serial->interrupt_in_buffer[i]); serial->present = 0; serial->active = 0; info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->number); } else { info("device disconnected"); } MOD_DEC_USE_COUNT;}static struct tty_driver serial_tty_driver = { magic: TTY_DRIVER_MAGIC, driver_name: "usb", name: "ttyUSB", major: SERIAL_MAJOR, minor_start: 0, num: NUM_PORTS, type: TTY_DRIVER_TYPE_SERIAL, subtype: SERIAL_TYPE_NORMAL, flags: TTY_DRIVER_REAL_RAW, refcount: &serial_refcount, table: serial_tty, proc_entry: NULL, other: NULL, termios: serial_termios, termios_locked: serial_termios_locked, open: serial_open, close: serial_close, write: serial_write, put_char: serial_put_char, flush_chars: NULL, write_room: serial_write_room, ioctl: NULL, set_termios: NULL, set_ldisc: NULL, throttle: serial_throttle, unthrottle: serial_unthrottle, stop: NULL, start: NULL, hangup: NULL, break_ctl: NULL, wait_until_sent: NULL, send_xchar: NULL, read_proc: NULL, chars_in_buffer: serial_chars_in_buffer, flush_buffer: NULL};int usb_serial_init(void){ int i; /* Initalize our global data */ for (i = 0; i < NUM_PORTS; ++i) { memset(&serial_state_table[i], 0x00, sizeof(struct usb_serial_state)); } /* 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("failed to register tty driver"); return -EPERM; } /* register the USB driver */ if (usb_register(&usb_serial_driver) < 0) { tty_unregister_driver(&serial_tty_driver); return -1; } info("support registered"); return 0;}#ifdef MODULEint init_module(void){ return usb_serial_init();}void cleanup_module(void){ tty_unregister_driver(&serial_tty_driver); usb_deregister(&usb_serial_driver);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -