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

📄 usbserial.c

📁 USB接口转换成RS232接口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:

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

/*****************************************************************************
 * generic devices specific driver functions
 *****************************************************************************/
static int generic_open(struct usb_serial_port *port, struct file *filp)
{
  struct usb_serial *serial = port->serial;
  unsigned long     flags;
  int               result;

  if(port_paranoia_check(port, __FUNCTION__))
    return -ENODEV;

  MOD_INC_USE_COUNT;

  dbg(__FUNCTION__ " - port %d", port->number);

  spin_lock_irqsave(&port->port_lock, flags);

  ++port->open_count;

  if(!port->active) {
    port->active = 1;

    /* 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. */
    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 */
      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(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
    }
  }

  spin_unlock_irqrestore(&port->port_lock, flags);

  return 0;
}

static void generic_close(struct usb_serial_port *port, struct file *filp)
{
  struct usb_serial *serial = port->serial;
  unsigned long     flags;

  dbg(__FUNCTION__ " - port %d", port->number);

  spin_lock_irqsave(&port->port_lock, flags);

  --port->open_count;

  if(port->open_count <= 0) {
    /* 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);

    port->active = 0;
    port->open_count = 0;
  }

  spin_unlock_irqrestore(&port->port_lock, flags);
  MOD_DEC_USE_COUNT;
}

static int generic_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
  struct usb_serial *serial = port->serial;
  unsigned long     flags;
  int               result;

  dbg(__FUNCTION__ " - port %d", port->number);

  if(count == 0) {
    dbg(__FUNCTION__ " - write request of 0 bytes");
    return(0);
  }

  /* only do something if we have a bulk out endpoint */
  if(serial->num_bulk_out) {
    if(port->write_urb->status == -EINPROGRESS) {
      dbg(__FUNCTION__ " - already writing");
      return(0);
    }

    spin_lock_irqsave(&port->port_lock, flags);
    count = (count > port->bulk_out_size) ? port->bulk_out_size : count;

    usb_serial_debug_data(__FILE__, __FUNCTION__, count, buf);

    if(from_user) {
      copy_from_user(port->write_urb->transfer_buffer, buf, count);
    }
    else {
      memcpy(port->write_urb->transfer_buffer, buf, count);
    }

    /* set up our urb */
    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 */
    result = usb_submit_urb(port->write_urb);
    if(result) {
      err(__FUNCTION__ " - failed submitting write urb, error %d", result);
      spin_unlock_irqrestore(&port->port_lock, flags);
      return 0;
    }

    spin_unlock_irqrestore(&port->port_lock, flags);
    return(count);
  }

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

  dbg(__FUNCTION__ " - port %d", port->number);

  if(serial->num_bulk_out)
    if(port->write_urb->status != -EINPROGRESS)
      room = port->bulk_out_size;

  dbg(__FUNCTION__ " - returns %d", room);
  return(room);
}

static int generic_chars_in_buffer(struct usb_serial_port *port)
{
  struct usb_serial *serial = port->serial;
  int               chars = 0;

  dbg(__FUNCTION__ " - port %d", port->number);

  if(serial->num_bulk_out)
    if(port->write_urb->status == -EINPROGRESS)
      chars = port->write_urb->transfer_buffer_length;

  dbg(__FUNCTION__ " - returns %d", 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(__FUNCTION__ " - port %d", port->number);

  if(!serial) {
    dbg(__FUNCTION__ " - bad serial pointer, exiting");
    return;
  }

  if(urb->status) {
    dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
    return;
  }

  usb_serial_debug_data(__FILE__, __FUNCTION__, urb->actual_length, data);

  tty = port->tty;
  if(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  */
  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(__FUNCTION__ " - failed resubmitting read urb, error %d", 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(__FUNCTION__ " - port %d", port->number);

  if(!serial) {
    dbg(__FUNCTION__ " - bad serial pointer, exiting");
    return;
  }

  if(urb->status) {
    dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
    return;
  }

  queue_task(&port->tqueue, &tq_immediate);
  mark_bh(IMMEDIATE_BH);

  return;
}

#ifdef CONFIG_USB_SERIAL_GENERIC
static void generic_shutdown(struct usb_serial *serial)
{
  int i;

  dbg(__FUNCTION__);

  /* stop reads and writes on all ports */
  for(i = 0; i < serial->num_ports; ++i) {
    while(serial->port[i].open_count > 0) {
      generic_close(&serial->port[i], NULL);
    }
  }
}
#endif
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;

  dbg(__FUNCTION__ " - port %d", port->number);

  if(!serial) {
    return;
  }

  tty = port->tty;
  if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
    dbg(__FUNCTION__ " - write wakeup call.");
    (tty->ldisc.write_wakeup) (tty);
  }

  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;
  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;
  int                             num_ports;
  int                             max_endpoints;
  const struct usb_device_id      *id_pattern = NULL;

  /* 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 */
  interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;

  /* 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) && ((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)
    )

⌨️ 快捷键说明

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