ftdi_sio.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,815 行 · 第 1/5 页
C
1,815 行
if ((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) { if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) port->tty->alt_speed = 57600; else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) port->tty->alt_speed = 115200; else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) port->tty->alt_speed = 230400; else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) port->tty->alt_speed = 460800; else port->tty->alt_speed = 0; } if (((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) || (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (old_priv.custom_divisor != priv->custom_divisor))) { change_speed(port); } return (0);} /* set_serial_info *//* * *************************************************************************** * FTDI driver specific functions * *************************************************************************** *//* Common startup subroutine *//* Called from ftdi_SIO_startup, etc. */static int ftdi_common_startup (struct usb_serial *serial){ struct usb_serial_port *port = serial->port[0]; struct ftdi_private *priv; dbg("%s",__FUNCTION__); priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); if (!priv){ err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); return -ENOMEM; } memset(priv, 0, sizeof(*priv)); spin_lock_init(&priv->rx_lock); init_waitqueue_head(&priv->delta_msr_wait); /* This will push the characters through immediately rather than queue a task to deliver them */ priv->flags = ASYNC_LOW_LATENCY; /* Increase the size of read buffers */ if (port->bulk_in_buffer) { kfree (port->bulk_in_buffer); } port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); if (!port->bulk_in_buffer) { kfree (priv); return -ENOMEM; } if (port->read_urb) { port->read_urb->transfer_buffer = port->bulk_in_buffer; port->read_urb->transfer_buffer_length = BUFSZ; } /* Free port's existing write urb and transfer buffer. */ if (port->write_urb) { usb_free_urb (port->write_urb); port->write_urb = NULL; } if (port->bulk_out_buffer) { kfree (port->bulk_out_buffer); port->bulk_out_buffer = NULL; } usb_set_serial_port_data(serial->port[0], priv); return (0);}/* Startup for the SIO chip *//* Called from usbserial:serial_probe */static int ftdi_SIO_startup (struct usb_serial *serial){ struct ftdi_private *priv; int err; dbg("%s",__FUNCTION__); err = ftdi_common_startup(serial); if (err){ return (err); } priv = usb_get_serial_port_data(serial->port[0]); priv->chip_type = SIO; priv->baud_base = 12000000 / 16; priv->write_offset = 1; return (0);}/* Startup for the 8U232AM chip *//* Called from usbserial:serial_probe */static int ftdi_8U232AM_startup (struct usb_serial *serial){ /* ftdi_8U232AM_startup */ struct ftdi_private *priv; int err; dbg("%s",__FUNCTION__); err = ftdi_common_startup(serial); if (err){ return (err); } priv = usb_get_serial_port_data(serial->port[0]); priv->chip_type = FT8U232AM; priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */ return (0);} /* ftdi_8U232AM_startup *//* Startup for the FT232BM chip *//* Called from usbserial:serial_probe */static int ftdi_FT232BM_startup (struct usb_serial *serial){ /* ftdi_FT232BM_startup */ struct ftdi_private *priv; int err; dbg("%s",__FUNCTION__); err = ftdi_common_startup(serial); if (err){ return (err); } priv = usb_get_serial_port_data(serial->port[0]); priv->chip_type = FT232BM; priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */ return (0);} /* ftdi_FT232BM_startup *//* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) *//* Called from usbserial:serial_probe */static int ftdi_USB_UIRT_startup (struct usb_serial *serial){ /* ftdi_USB_UIRT_startup */ struct ftdi_private *priv; int err; dbg("%s",__FUNCTION__); err = ftdi_8U232AM_startup(serial); if (err){ return (err); } priv = usb_get_serial_port_data(serial->port[0]); priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 77; priv->force_baud = B38400; return (0);} /* ftdi_USB_UIRT_startup *//* Startup for the HE-TIRA1 device, which requires hardwired * baudrate (38400 gets mapped to 100000) */static int ftdi_HE_TIRA1_startup (struct usb_serial *serial){ /* ftdi_HE_TIRA1_startup */ struct ftdi_private *priv; int err; dbg("%s",__FUNCTION__); err = ftdi_FT232BM_startup(serial); if (err){ return (err); } priv = usb_get_serial_port_data(serial->port[0]); priv->flags |= ASYNC_SPD_CUST; priv->custom_divisor = 240; priv->force_baud = B38400; priv->force_rtscts = 1; return (0);} /* ftdi_HE_TIRA1_startup *//* ftdi_shutdown is called from usbserial:usb_serial_disconnect * it is called when the usb device is disconnected * * usbserial:usb_serial_disconnect * calls __serial_close for each open of the port * shutdown is called then (ie ftdi_shutdown) */static void ftdi_shutdown (struct usb_serial *serial){ /* ftdi_shutdown */ struct usb_serial_port *port = serial->port[0]; struct ftdi_private *priv = usb_get_serial_port_data(port); dbg("%s", __FUNCTION__); /* all open ports are closed at this point * (by usbserial.c:__serial_close, which calls ftdi_close) */ if (priv) { usb_set_serial_port_data(port, NULL); kfree(priv); }} /* ftdi_shutdown */static int ftdi_open (struct usb_serial_port *port, struct file *filp){ /* ftdi_open */ struct termios tmp_termios; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result = 0; char buf[1]; /* Needed for the usb_control_msg I think */ dbg("%s", __FUNCTION__); port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, 0, buf, 0, WDR_TIMEOUT); /* Termios defaults are set by usb_serial_init. We don't change port->tty->termios - this would loose speed settings, etc. This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ ftdi_set_termios(port, &tmp_termios); /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ /* Turn on RTS and DTR since we are not flow controlling by default */ if (set_dtr(port, HIGH) < 0) { err("%s Error from DTR HIGH urb", __FUNCTION__); } if (set_rts(port, HIGH) < 0){ err("%s Error from RTS HIGH urb", __FUNCTION__); } /* Not throttled */ spin_lock_irqsave(&priv->rx_lock, flags); priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); spin_unlock_irqrestore(&priv->rx_lock, flags); /* Start reading from the device */ usb_fill_bulk_urb(port->read_urb, dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, ftdi_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) err("%s - failed submitting read urb, error %d", __FUNCTION__, result); return result;} /* ftdi_open *//* * usbserial:__serial_close only calls ftdi_close if the point is open * * This only gets called when it is the last close * * */static void ftdi_close (struct usb_serial_port *port, struct file *filp){ /* ftdi_close */ unsigned int c_cflag = port->tty->termios->c_cflag; char buf[1]; dbg("%s", __FUNCTION__); if (c_cflag & HUPCL){ /* Disable flow control */ if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, 0, buf, 0, WDR_TIMEOUT) < 0) { err("error from flowcontrol urb"); } /* drop DTR */ if (set_dtr(port, LOW) < 0){ err("Error from DTR LOW urb"); } /* drop RTS */ if (set_rts(port, LOW) < 0) { err("Error from RTS LOW urb"); } } /* Note change no line if hupcl is off */ /* shutdown our bulk read */ if (port->read_urb) { if (usb_unlink_urb (port->read_urb) < 0) { /* Generally, this isn't an error. If the previous read bulk callback occurred (or is about to occur) while the port was being closed or was throtted (and is still throttled), the read urb will not have been submitted. */ dbg("%s - failed to unlink read urb (generally not an error)", __FUNCTION__); } }} /* ftdi_close */ /* The SIO requires the first byte to have: * B0 1 * B1 0 * B2..7 length of message excluding byte 0 * * The new devices do not require this byte */static int ftdi_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count){ /* ftdi_write */ struct ftdi_private *priv = usb_get_serial_port_data(port); struct urb *urb; unsigned char *buffer; int data_offset ; /* will be 1 for the SIO and 0 otherwise */ int status; int transfer_size; dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count); if (count == 0) { err("write request of 0 bytes"); return 0; } data_offset = priv->write_offset; dbg("data_offset set to %d",data_offset); /* Determine total transfer size */ transfer_size = count; if (data_offset > 0) { /* Original sio needs control bytes too... */ transfer_size += (data_offset * ((count + (PKTSZ - 1 - data_offset)) / (PKTSZ - data_offset))); } buffer = kmalloc (transfer_size, GFP_ATOMIC); if (!buffer) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?