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

📄 usbserial.c

📁 USB接口转换成RS232接口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
  ) {
    /* nope, they don't match what we expected */
    info("descriptors matched, but endpoints did not");
    return NULL;
  }

  /* 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;

  /* if this device type has a startup function, call it */
  if(type->startup) {
    if(type->startup(serial)) {
      goto probe_error;
    }
  }

  /* 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;
    }

    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;
    }

    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;
    }

    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);
  dbg(__FUNCTION__ " - setting up %d port structures for this device", 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;
    spin_lock_init(&port->port_lock);
  }

  /* 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 */

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;
  int                     i;

  if(serial) {
    /* fail all future close/read/write/ioctl/etc calls */
    for(i = 0; i < serial->num_ports; ++i) {
      if(serial->port[i].tty != NULL)
        serial->port[i].tty->driver_data = NULL;
    }

    if(serial->type->shutdown)
      serial->type->shutdown(serial);

    for(i = 0; i < serial->num_ports; ++i)
      serial->port[i].active = 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 */
    kfree(serial);
  }
  else {
    info("device disconnected");
  }
}

static struct tty_driver  serial_tty_driver =
{
magic:
  TTY_DRIVER_MAGIC,
  driver_name : "usb-serial",
  name : "usb/tts/%d",
  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,
};

int usb_serial_init(void)
{
  int i;
  int result;

  /* Initalize our global data */
  for(i = 0; i < SERIAL_TTY_MINORS; ++i) {
    serial_table[i] = NULL;
  }

  /* 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(__FUNCTION__ " - failed to register tty driver");
    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
  /* 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;
  }

  return 0;
}

void 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 build 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

⌨️ 快捷键说明

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