📄 kl5kusb105.c
字号:
* oopses. */ /* usb_unlink_urb(write_urbs[j]); */ if (write_urbs[j]->transfer_buffer) kfree(write_urbs[j]->transfer_buffer); usb_free_urb (write_urbs[j]); } } spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); kfree(serial->port[i].private); } }} /* klsi_105_shutdown */static int klsi_105_open (struct usb_serial_port *port, struct file *filp){ struct usb_serial *serial = port->serial; struct klsi_105_private *priv = (struct klsi_105_private *)port->private; int retval = 0; dbg(__FUNCTION__" port %d", port->number); down (&port->sem); ++port->open_count; MOD_INC_USE_COUNT; if (!port->active) { int rc; int i; unsigned long line_state; port->active = 1; /* force low_latency on so that our tty_push actually forces * the data through * port->tty->low_latency = 1; */ /* Do a defined restart: * Set up sane default baud rate and send the 'READ_ON' * vendor command. * FIXME: set modem line control (how?) * Then read the modem line control and store values in * priv->line_state. */ priv->cfg.pktlen = 5; priv->cfg.baudrate = kl5kusb105a_sio_b9600; priv->cfg.databits = kl5kusb105a_dtb_8; priv->cfg.unknown1 = 0; priv->cfg.unknown2 = 1; klsi_105_chg_port_settings(serial, &(priv->cfg)); /* set up termios structure */ priv->termios.c_iflag = port->tty->termios->c_iflag; priv->termios.c_oflag = port->tty->termios->c_oflag; priv->termios.c_cflag = port->tty->termios->c_cflag; priv->termios.c_lflag = port->tty->termios->c_lflag; for (i=0; i<NCCS; i++) priv->termios.c_cc[i] = port->tty->termios->c_cc[i]; /* READ_ON and urb submission */ 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, klsi_105_read_bulk_callback, port); port->read_urb->transfer_flags |= USB_QUEUE_BULK; rc = usb_submit_urb(port->read_urb); if (rc) { err(__FUNCTION__ " - failed submitting read urb, error %d", rc); retval = rc; goto exit; } rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), KL5KUSB105A_SIO_CONFIGURE, USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE, KL5KUSB105A_SIO_CONFIGURE_READ_ON, 0, /* index */ NULL, 0, KLSI_TIMEOUT); if (rc < 0) { err("Enabling read failed (error = %d)", rc); retval = rc; } else dbg(__FUNCTION__ " - enabled reading"); rc = klsi_105_get_line_state(serial, &line_state); if (rc >= 0) { priv->line_state = line_state; dbg(__FUNCTION__ " - read line state 0x%lx", line_state); retval = 0; } else retval = rc; }exit: up (&port->sem); return retval;} /* klsi_105_open */static void klsi_105_close (struct usb_serial_port *port, struct file *filp){ struct usb_serial *serial; struct klsi_105_private *priv = (struct klsi_105_private *)port->private; dbg(__FUNCTION__" port %d", port->number); serial = get_usb_serial (port, __FUNCTION__); if(!serial) return; down (&port->sem); --port->open_count; if (port->open_count <= 0) { /* send READ_OFF */ int rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), KL5KUSB105A_SIO_CONFIGURE, USB_TYPE_VENDOR | USB_DIR_OUT, KL5KUSB105A_SIO_CONFIGURE_READ_OFF, 0, /* index */ NULL, 0, KLSI_TIMEOUT); if (rc < 0) err("Disabling read failed (error = %d)", rc); /* shutdown our bulk reads and writes */ usb_unlink_urb (port->write_urb); usb_unlink_urb (port->read_urb); /* unlink our write pool */ /* FIXME */ /* wgg - do I need this? I think so. */ usb_unlink_urb (port->interrupt_in_urb); port->active = 0; info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out); } up (&port->sem); MOD_DEC_USE_COUNT;} /* klsi_105_close *//* We need to write a complete 64-byte data block and encode the * number actually sent in the first double-byte, LSB-order. That * leaves at most 62 bytes of payload. */#define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */static int klsi_105_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count){ struct usb_serial *serial = port->serial; struct klsi_105_private *priv = (struct klsi_105_private*) port->private; int result, size; int bytes_sent=0; dbg(__FUNCTION__ " - port %d", port->number); down (&port->sem); /* to lock against someone else trying to take an URB we just selected from the pool */ while (count > 0) { /* try to find a free urb (write 0 bytes if none) */ struct urb *urb = NULL; unsigned long flags; int i; /* since the pool is per-port we might not need the spin lock !? */ spin_lock_irqsave (&priv->write_urb_pool_lock, flags); for (i=0; i<NUM_URBS; i++) { if (priv->write_urb_pool[i]->status != -EINPROGRESS) { urb = priv->write_urb_pool[i]; dbg(__FUNCTION__ " - using pool URB %d", i); break; } } spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); if (urb==NULL) { dbg (__FUNCTION__ " - no more free urbs"); goto exit; } if (urb->transfer_buffer == NULL) { urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { err(__FUNCTION__ " - no more kernel memory..."); goto exit; } } size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET); size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET); if (from_user) { if (copy_from_user(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size)) { up (&port->sem); return -EFAULT; } } else { memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); } /* write payload size into transfer buffer */ ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); ((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8); /* set up our urb */ FILL_BULK_URB(urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), urb->transfer_buffer, URB_TRANSFER_BUFFER_SIZE, klsi_105_write_bulk_callback, port); urb->transfer_flags |= USB_QUEUE_BULK; /* send the data out the bulk port */ result = usb_submit_urb(urb); if (result) { err(__FUNCTION__ " - failed submitting write urb, error %d", result); goto exit; } buf += size; bytes_sent += size; count -= size; }exit: up (&port->sem); priv->bytes_out+=bytes_sent; return bytes_sent; /* that's how much we wrote */} /* klsi_105_write */static void klsi_105_write_bulk_callback ( struct urb *urb){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; 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; } /* from generic_write_bulk_callback */ queue_task(&port->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); return;} /* klsi_105_write_bulk_completion_callback *//* return number of characters currently in the writing process */static int klsi_105_chars_in_buffer (struct usb_serial_port *port){ int chars = 0; int i; unsigned long flags; struct klsi_105_private *priv = (struct klsi_105_private*) port->private; spin_lock_irqsave (&priv->write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (priv->write_urb_pool[i]->status == -EINPROGRESS) { chars += URB_TRANSFER_BUFFER_SIZE; } } spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); dbg (__FUNCTION__ " - returns %d", chars); return (chars);}static int klsi_105_write_room (struct usb_serial_port *port){ unsigned long flags; int i; int room = 0; struct klsi_105_private *priv = (struct klsi_105_private*) port->private; spin_lock_irqsave (&priv->write_urb_pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { if (priv->write_urb_pool[i]->status != -EINPROGRESS) { room += URB_TRANSFER_BUFFER_SIZE; } } spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); dbg(__FUNCTION__ " - returns %d", room); return (room);}static void klsi_105_read_bulk_callback (struct urb *urb){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; struct klsi_105_private *priv = (struct klsi_105_private*) port->private; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int rc; dbg(__FUNCTION__ " - port %d", port->number); /* The urb might have been killed. */ if (urb->status) { dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); return; } if (!serial) { dbg(__FUNCTION__ " - bad serial pointer, exiting"); return; } /* The data received is again preceded by a length double-byte in LSB- * first order (see klsi_105_write() ) */ if (urb->actual_length == 0) { /* empty urbs seem to happen, we ignore them */ /* dbg(__FUNCTION__ " - emtpy URB"); */ ; } else if (urb->actual_length <= 2) { dbg(__FUNCTION__ " - size %d URB not understood", urb->actual_length); usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); } else { int i; int bytes_sent = ((__u8 *) data)[0] + ((unsigned int) ((__u8 *) data)[1] << 8); tty = port->tty; /* we should immediately resubmit the URB, before attempting * to pass the data on to the tty layer. But that needs locking * against re-entry an then mixed-up data because of * intermixed tty_flip_buffer_push()s * FIXME */ usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); if (bytes_sent + 2 > urb->actual_length) { dbg(__FUNCTION__ " - trying to read more data than available" " (%d vs. %d)", bytes_sent+2, urb->actual_length); /* cap at implied limit */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -