📄 ftdi_sio.c
字号:
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, 0, buf, 0, WDR_TIMEOUT); /* Setup termios defaults. According to tty_io.c the settings are driver specific */ port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; /* ftdi_sio_set_termios will send usb control messages */ ftdi_sio_set_termios(port, &tmp_termios); /* Turn on RTS and DTR since we are not flow controlling by default */ if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) { err(__FUNCTION__ " Error from DTR HIGH urb"); } if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){ err(__FUNCTION__ " Error from RTS HIGH urb"); } /* 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, ftdi_sio_read_bulk_callback, port); result = usb_submit_urb(port->read_urb); if (result) err(__FUNCTION__ " - failed submitting read urb, error %d", result); } up (&port->sem); return result;} /* ftdi_sio_open */static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp){ /* ftdi_sio_close */ struct usb_serial *serial = port->serial; /* Checked in usbserial.c */ unsigned int c_cflag = port->tty->termios->c_cflag; char buf[1]; dbg( __FUNCTION__); down (&port->sem); --port->open_count; if (port->open_count <= 0) { if (serial->dev) { if (c_cflag & HUPCL){ /* Disable flow control */ if (usb_control_msg(serial->dev, usb_sndctrlpipe(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(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){ err("Error from DTR LOW urb"); } /* drop RTS */ if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) { err("Error from RTS LOW urb"); } } /* Note change no line is hupcl is off */ /* shutdown our bulk reads and writes */ /* ***CHECK*** behaviour when there is nothing queued */ usb_unlink_urb (port->write_urb); usb_unlink_urb (port->read_urb); } port->active = 0; port->open_count = 0; } else { /* Send a HUP if necessary */ if (!(port->tty->termios->c_cflag & CLOCAL)){ tty_hangup(port->tty); } } up (&port->sem); MOD_DEC_USE_COUNT;} /* ftdi_sio_close */ /* The ftdi_sio requires the first byte to have: * B0 1 * B1 0 * B2..7 length of message excluding byte 0 */static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count){ /* ftdi_sio_write */ struct usb_serial *serial = port->serial; struct ftdi_private *priv = (struct ftdi_private *)port->private; unsigned char *first_byte = port->write_urb->transfer_buffer; int data_offset ; int result; dbg(__FUNCTION__ " port %d, %d bytes", 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); if (port->write_urb->status == -EINPROGRESS) { dbg (__FUNCTION__ " - already writing"); return (0); } down(&port->sem); count += data_offset; count = (count > port->bulk_out_size) ? port->bulk_out_size : count; /* Copy in the data to send */ if (from_user) { if (copy_from_user(port->write_urb->transfer_buffer + data_offset, buf, count - data_offset )){ up (&port->sem); return -EFAULT; } } else { memcpy(port->write_urb->transfer_buffer + data_offset, buf, count - data_offset ); } first_byte = port->write_urb->transfer_buffer; if (data_offset > 0){ /* Write the control byte at the front of the packet*/ *first_byte = 1 | ((count-data_offset) << 2) ; } dbg(__FUNCTION__ " Bytes: %d, First Byte: 0x%02x",count, first_byte[0]); usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte); /* send the data out the bulk port */ FILL_BULK_URB(port->write_urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, count, ftdi_sio_write_bulk_callback, port); result = usb_submit_urb(port->write_urb); if (result) { err(__FUNCTION__ " - failed submitting write urb, error %d", result); up (&port->sem); return 0; } up (&port->sem); dbg(__FUNCTION__ " write returning: %d", count - data_offset); return (count - data_offset);} /* ftdi_sio_write */static void ftdi_sio_write_bulk_callback (struct urb *urb){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial; dbg("ftdi_sio_write_bulk_callback"); if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) { return; } serial = port->serial; if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) { return; } if (urb->status) { dbg("nonzero write bulk status received: %d", urb->status); return; } queue_task(&port->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); return;} /* ftdi_sio_write_bulk_callback */static int ftdi_sio_write_room( struct usb_serial_port *port ){ struct ftdi_private *priv = (struct ftdi_private *)port->private; int room; if ( port->write_urb->status == -EINPROGRESS) { /* There is a race here with the _write routines but it won't hurt */ room = 0; } else { room = port->bulk_out_size - priv->write_offset; } return(room);} /* ftdi_sio_write_room */static void ftdi_sio_read_bulk_callback (struct urb *urb){ /* ftdi_sio_serial_buld_callback */ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial; struct tty_struct *tty = port->tty ; char error_flag; unsigned char *data = urb->transfer_buffer; const int data_offset = 2; int i; int result; dbg(__FUNCTION__ " - port %d", port->number); if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) { return; } serial = port->serial; if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) { return; } if (urb->status) { /* This will happen at close every time so it is a dbg not an err */ dbg("nonzero read bulk status received: %d", urb->status); return; } if (urb->actual_length > 2) { usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); } else { dbg("Just status 0o%03o0o%03o",data[0],data[1]); } /* TO DO -- check for hung up line and handle appropriately: */ /* send hangup */ /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ /* if CD is dropped and the line is not CLOCAL then we should hangup */ /* Handle errors and break */ error_flag = TTY_NORMAL; /* Although the device uses a bitmask and hence can have multiple */ /* errors on a packet - the order here sets the priority the */ /* error is returned to the tty layer */ if ( data[1] & FTDI_RS_OE ) { error_flag = TTY_OVERRUN; dbg("OVERRRUN error"); } if ( data[1] & FTDI_RS_BI ) { error_flag = TTY_BREAK; dbg("BREAK received"); } if ( data[1] & FTDI_RS_PE ) { error_flag = TTY_PARITY; dbg("PARITY error"); } if ( data[1] & FTDI_RS_FE ) { error_flag = TTY_FRAME; dbg("FRAMING error"); } if (urb->actual_length > data_offset) { for (i = data_offset ; i < urb->actual_length ; ++i) { /* have to make sure we don't overflow the buffer with tty_insert_flip_char's */ if(tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); } /* Note that the error flag is duplicated for every character received since we don't know which character it applied to */ tty_insert_flip_char(tty, data[i], error_flag); } tty_flip_buffer_push(tty); } #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW /* if a parity error is detected you get status packets forever until a character is sent without a parity error. This doesn't work well since the application receives a never ending stream of bad data - even though new data hasn't been sent. Therefore I (bill) have taken this out. However - this might make sense for framing errors and so on so I am leaving the code in for now. */ else { if (error_flag != TTY_NORMAL){ dbg("error_flag is not normal"); /* In this case it is just status - if that is an error send a bad character */ if(tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); } tty_insert_flip_char(tty, 0xff, error_flag); tty_flip_buffer_push(tty); } }#endif /* 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, ftdi_sio_read_bulk_callback, port); result = usb_submit_urb(port->read_urb); if (result) err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); return;} /* ftdi_sio_serial_read_bulk_callback */static __u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type) { /* translate_baudrate_to_ftdi */ __u16 urb_value = ftdi_sio_b9600; if (ftdi_type == sio){ switch(cflag & CBAUD){ case B0: break; /* ignored by this */ case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break; case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break; case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break; case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break; case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break; case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -