kern/70523: umct sending/receiving wrong characters

Brian Candler B.Candler at pobox.com
Sun Jul 3 00:36:48 GMT 2005


The following reply was made to PR kern/70523; it has been noted by GNATS.

From: Brian Candler <B.Candler at pobox.com>
To: FreeBSD-gnats-submit at FreeBSD.org, freebsd-bugs at FreeBSD.org
Cc: sanpei at freebsd.org
Subject: Re: kern/70523: umct sending/receiving wrong characters
Date: Sat, 21 Aug 2004 21:21:46 +0100

 This device worked correctly under Linux, and I have now made a patch
 [attached below] so that it works under FreeBSD too.
 
 Looking at linux-2.4.27/drivers/usb/serial/mct_u232.[ch], you'll see that
 there are two different ways of calculating the baud rate divider, depending
 on which type of device you have. FreeBSD only implemented one of these, and
 unfortunately I had the other sort of device.
 
 I wasn't sure if there was an easy way to access the 'uaa' structure in the
 middle of umct_calc_baud, so instead I added an extra structure member to
 'sc' to flag which divider constants to use. If there's a way of doing this
 without having to store this extra state then please do so.
 
 I notice a new entry USB_PRODUCT_BELKIN_F5U409 has recently been added to
 umct.c (but is not in the Linux driver); someone needs to check which way it
 works.
 
 Aside: Something else the Linux driver does is to send commands 11 and 12
 (constants MCT_U232_SET_UNKNOWN1_REQUEST and MCT_U232_SET_UNKNOWN2_REQUEST)
 after setting the baud rate. The comment says:
 
         /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
            always sends two extra USB 'device request' messages after the
            'baud rate change' message.  The actual functionality of the
            request codes in these messages is not fully understood but these
            particular codes are never seen in any operation besides a baud
            rate change.  Both of these messages send a single byte of data
            whose value is always zero.  The second of these two extra messages
            is required in order for data to be properly written to an RS-232
            device which does not assert the 'CTS' signal. */
 
 I tried making the FreeBSD driver do this too, but on my hardware it just
 gave timeouts:
 
   /kernel: ucom0: ubsa_request: TIMEOUT
 
 So I guess it's not needed for the device I have, and I've taken it out.
 (That debug message should have said "umct_request", and the patch below
 also fixes that)
 
 Regards,
 
 Brian Candler.
 
 --- sys/dev/usb/umct.c.orig	Tue Apr 13 04:39:16 2004
 +++ sys/dev/usb/umct.c	Sat Aug 21 21:17:07 2004
 @@ -81,6 +81,7 @@
  	uint8_t			sc_msr;
  	uint8_t			sc_lcr;
  	uint8_t			sc_mcr;
 +	uint8_t			sc_divider_type;
  #if __FreeBSD_version >= 500000
  	void			*sc_swicookie;
  #endif
 @@ -193,6 +194,10 @@
  	sc->sc_intr_number = -1;
  	sc->sc_intr_pipe = NULL;
  
 +	if (uaa->product == USB_PRODUCT_MCT_SITECOM_USB232 ||
 +	    uaa->product == USB_PRODUCT_BELKIN_F5U109)
 +		sc->sc_divider_type = 1;
 +	
  	err = usbd_set_config_index(dev, UMCT_CONFIG_INDEX, 1);
  	if (err) {
  		printf("%s: failed to set configuration: %s\n",
 @@ -328,7 +333,7 @@
  
  	err = usbd_do_request(sc->sc_ucom.sc_udev, &req, oval);
  	if (err)
 -		printf("%s: ubsa_request: %s\n",
 +		printf("%s: umct_request: %s\n",
  		    USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
  	return (err);
  }
 @@ -418,22 +423,34 @@
  }
  
  Static int
 -umct_calc_baud(u_int baud)
 +umct_calc_baud(struct umct_softc *sc, u_int baud)
  {
 -	switch(baud) {
 -	case B300: return (0x1);
 -	case B600: return (0x2);
 -	case B1200: return (0x3);
 -	case B2400: return (0x4);
 -	case B4800: return (0x6);
 -	case B9600: return (0x8);
 -	case B19200: return (0x9);
 -	case B38400: return (0xa);
 -	case B57600: return (0xb);
 -	case 115200: return (0xc);
 -	case B0:
 -	default:
 -		break;
 +	if (sc->sc_divider_type == 1) {
 +		switch(baud) {
 +		case B300: return (0x1);
 +		case B600: return (0x2);
 +		case B1200: return (0x3);
 +		case B2400: return (0x4);
 +		case B4800: return (0x6);
 +		case B9600: return (0x8);
 +		case B19200: return (0x9);
 +		case B38400: return (0xa);
 +		case B57600: return (0xb);
 +		case 115200: return (0xc);
 +		}
 +	} else {
 +		switch(baud) {
 +		case B300: return 115200/300;
 +		case B600: return 115200/600;
 +		case B1200: return 115200/1200;
 +		case B2400: return 115200/2400;
 +		case B4800: return 115200/4800;
 +		case B9600: return 115200/9600;
 +		case B19200: return 115200/19200;
 +		case B38400: return 115200/38400;
 +		case B57600: return 115200/57600;
 +		case 115200: return 115200/115200;
 +		}
  	}
  
  	return (0x0);
 @@ -446,7 +463,8 @@
  	uint32_t value;
  
  	sc = addr;
 -	value = umct_calc_baud(ti->c_ospeed);
 +	value = umct_calc_baud(sc, ti->c_ospeed);
 +	if (value == 0) return (EIO);
  	umct_request(sc, UMCT_SET_BAUD, UMCT_SET_BAUD_SIZE, value);
  
  	value = sc->sc_lcr & 0x40;
 _______________________________________________
 freebsd-bugs at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
 To unsubscribe, send any mail to "freebsd-bugs-unsubscribe at freebsd.org"
 


More information about the freebsd-usb mailing list