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

📄 usbserial.c

📁 USB接口转换成RS232接口驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
   cause the "hotplug" program to pull in whatever module is necessary
   via modprobe, and modprobe will load usbserial because the serial
   drivers depend on it.
*/
static int                            serial_refcount;
static struct tty_driver              serial_tty_driver;
static struct tty_struct              *serial_tty[SERIAL_TTY_MINORS];
static struct termios                 *serial_termios[SERIAL_TTY_MINORS];
static struct termios                 *serial_termios_locked[SERIAL_TTY_MINORS];
static struct usb_serial              *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */

LIST_HEAD(usb_serial_driver_list);

static struct usb_serial *get_serial_by_minor(int minor)
{
  return serial_table[minor];
}

static struct usb_serial *get_free_serial(int num_ports, int *minor)
{
  struct usb_serial *serial = NULL;
  int               i, j;
  int               good_spot;

  dbg(__FUNCTION__ " %d", num_ports);

  *minor = 0;
  for(i = 0; i < SERIAL_TTY_MINORS; ++i) {
    if(serial_table[i])
      continue;

    good_spot = 1;
    for(j = 1; j <= num_ports - 1; ++j)
      if(serial_table[i + j])
        good_spot = 0;
    if(good_spot == 0)
      continue;

    if(!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) {
      err(__FUNCTION__ " - Out of memory");
      return NULL;
    }

    memset(serial, 0, sizeof(struct usb_serial));
    serial->magic = USB_SERIAL_MAGIC;
    serial_table[i] = serial;
    *minor = i;
    dbg(__FUNCTION__ " - minor base = %d", *minor);
    for(i = *minor + 1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
      serial_table[i] = serial;
    return serial;
  }

  return NULL;
}

static void return_serial(struct usb_serial *serial)
{
  int i;

  dbg(__FUNCTION__);

  if(serial == NULL)
    return;

  for(i = 0; i < serial->num_ports; ++i) {
    serial_table[serial->minor + i] = NULL;
  }

  return;
}

#ifdef USES_EZUSB_FUNCTIONS

/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92

int ezusb_writememory(struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
{
  int           result;
  unsigned char *transfer_buffer = kmalloc(length, GFP_KERNEL);

  //	dbg("ezusb_writememory %x, %d", address, length);
  if(!transfer_buffer) {
    err(__FUNCTION__ " - kmalloc(%d) failed.", length);
    return -ENOMEM;
  }

  memcpy(transfer_buffer, data, length);
  result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer,
                           length, 300);
  kfree(transfer_buffer);
  return result;
}

int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
{
  int response;
  dbg(__FUNCTION__ " - %d", reset_bit);
  response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
  if(response < 0) {
    err(__FUNCTION__ "- %d failed", reset_bit);
  }

  return response;
}
#endif /* USES_EZUSB_FUNCTIONS */

/*****************************************************************************
 * Driver tty interface functions
 *****************************************************************************/
static int serial_open(struct tty_struct *tty, struct file *filp)
{
  struct usb_serial       *serial;
  struct usb_serial_port  *port;
  int                     portNumber;

  dbg(__FUNCTION__);

  /* initialize the pointer incase something fails */
  tty->driver_data = NULL;

  /* get the serial object associated with this tty pointer */
  serial = get_serial_by_minor(MINOR(tty->device));

  if(serial_paranoia_check(serial, __FUNCTION__)) {
    return -ENODEV;
  }

  MOD_INC_USE_COUNT;

  /* set up our port structure making the tty driver remember our port object, and us it */
  portNumber = MINOR(tty->device) - serial->minor;
  port = &serial->port[portNumber];
  tty->driver_data = port;
  port->tty = tty;

  /* pass on to the driver specific version of this function if it is available */
  if(serial->type->open) {
    return(serial->type->open(port, filp));
  }
  else {
    return(generic_open(port, filp));
  }
}

static void serial_close(struct tty_struct *tty, struct file *filp)
{
  struct usb_serial_port  *port = (struct usb_serial_port *)tty->driver_data;
  struct usb_serial       *serial = get_usb_serial(port, __FUNCTION__);

  if(!serial) {
    return;
  }

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not opened");
    return;
  }

  /* pass on to the driver specific version of this function if it is available */
  if(serial->type->close) {
    serial->type->close(port, filp);
  }
  else {
    generic_close(port, filp);
  }

  MOD_DEC_USE_COUNT;
}

static int serial_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
{
  struct usb_serial_port  *port = (struct usb_serial_port *)tty->driver_data;
  struct usb_serial       *serial = get_usb_serial(port, __FUNCTION__);

  if(!serial) {
    return -ENODEV;
  }

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not opened");
    return -EINVAL;
  }

  /* pass on to the driver specific version of this function if it is available */
  if(serial->type->write) {
    return(serial->type->write(port, from_user, buf, count));
  }
  else {
    return(generic_write(port, from_user, buf, count));
  }
}

static int serial_write_room(struct tty_struct *tty)
{
  struct usb_serial_port  *port = (struct usb_serial_port *)tty->driver_data;
  struct usb_serial       *serial = get_usb_serial(port, __FUNCTION__);

  if(!serial) {
    return -ENODEV;
  }

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return -EINVAL;
  }

  /* pass on to the driver specific version of this function if it is available */
  if(serial->type->write_room) {
    return(serial->type->write_room(port));
  }
  else {
    return(generic_write_room(port));
  }
}

static int serial_chars_in_buffer(struct tty_struct *tty)
{
  struct usb_serial_port  *port = (struct usb_serial_port *)tty->driver_data;
  struct usb_serial       *serial = get_usb_serial(port, __FUNCTION__);

  if(!serial) {
    return -ENODEV;
  }

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return -EINVAL;
  }

  /* pass on to the driver specific version of this function if it is available */
  if(serial->type->chars_in_buffer) {
    return(serial->type->chars_in_buffer(port));
  }
  else {
    return(generic_chars_in_buffer(port));
  }
}

static void serial_throttle(struct tty_struct *tty)
{
  struct usb_serial_port  *port = (struct usb_serial_port *)tty->driver_data;
  struct usb_serial       *serial = get_usb_serial(port, __FUNCTION__);

  if(!serial) {
    return;
  }

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return;
  }

  /* pass on to the driver specific version of this function */
  if(serial->type->throttle) {
    serial->type->throttle(port);
  }

  return;
}

static void serial_unthrottle(struct tty_struct *tty)
{
  struct usb_serial_port  *port = (struct usb_serial_port *)tty->driver_data;
  struct usb_serial       *serial = get_usb_serial(port, __FUNCTION__);

  if(!serial) {
    return;
  }

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return;
  }

  /* pass on to the driver specific version of this function */
  if(serial->type->unthrottle) {
    serial->type->unthrottle(port);
  }

  return;
}

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__);

  if(!serial) {
    return -ENODEV;
  }

  dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return -ENODEV;
  }

  /* pass on to the driver specific version of this function if it is available */
  if(serial->type->ioctl) {
    return(serial->type->ioctl(port, file, cmd, arg));
  }
  else {
    return -ENOIOCTLCMD;
  }
}

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

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return;
  }

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

  return;
}

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

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

  if(!port->active) {
    dbg(__FUNCTION__ " - port not open");
    return;
  }

⌨️ 快捷键说明

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