2004-10-20 18:49:45

by Thomas Stewart

[permalink] [raw]
Subject: belkin usb serial converter (mct_u232), break not working

Hi,

I'm having trouble with a Belkin USB serial adapter, I can't get it to send a
break down the serial cable to a console.

I made a quick program to send a break to a port (mostly ripped off from
minicom).

porttest.c:
#include <sys/fcntl.h>
#include <sys/ioctl.h>
main () {
int fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY);
ioctl(fd, TCSBRK, 0);
close(fd);
}

Both minicom and my program send a break fine to a regular pc serial port (eg
ttyS0). In this case it drops my sun box to an "ok" prompt.

However if I use the usb serial adapter both minicom and my program are unable
to send breaks, they just seem to get ignored.

I loaded the modules with debugging information turned on:-
modprobe usbserial debug=1
modprobe mct_u232 debug=1

$ sudo tail -f /var/log/syslog &
$ ./porttest
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/usb-serial.c: serial_open
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: mct_u232_open
port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: set_modem_ctrl:
state=0x6 ==> mcr=0xb
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: set_line_ctrl:
0x3
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: get_modem_stat:
0x30
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: msr_to_state:
msr=0x30 ==> state=0x126
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/usb-serial.c:
serial_chars_in_buffer = port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/generic.c:
usb_serial_generic_chars_in_buffer - port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/generic.c:
usb_serial_generic_chars_in_buffer - returns 0
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/usb-serial.c: serial_break -
port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c:
mct_u232_break_ctlstate=-1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: set_line_ctrl:
0x43
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/usb-serial.c: serial_break -
port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c:
mct_u232_break_ctlstate=0
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: set_line_ctrl:
0x3
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/usb-serial.c: serial_close -
port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c: mct_u232_close
port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c:
mct_u232_read_int_callback - port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c:
mct_u232_read_int_callback - urb shutting down with status: -2
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c:
mct_u232_read_int_callback - port 1
Oct 20 15:45:42 hydra kernel: drivers/usb/serial/mct_u232.c:
mct_u232_read_int_callback - urb shutting down with status: -2

set_line_ctrl gets changed from 0x3 to 0x43 and back to 0x3. According to
mct_u232.h the 6th bit of the line control register is the "set break" bit.
So It looks like it thinks its sending a break, but as far as I can tell it
is not actually sending it (because my sun box is not dropped to an ok
prompt)

Anyone got any ideas about how to get it to work? (Or an alternative?)

(Can replies be CC'ed to me as I'm not subscribed. Thanks)

Regards
--
Tom

PGP Fingerprint [DCCD 7DCB A74A 3E3B 60D5 DF4C FC1D 1ECA 68A7 0C48]
PGP Publickey [http://www.stewarts.org.uk/public-key.asc]
PGP ID [0x68A70C48]


2004-10-20 21:32:33

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wed, 2004-10-20 at 13:46, Thomas Stewart wrote:
> I'm having trouble with a Belkin USB serial adapter, I can't get it to send a
> break down the serial cable to a console.
>
> I made a quick program to send a break to a port (mostly ripped off from
> minicom).
>
> porttest.c:
> #include <sys/fcntl.h>
> #include <sys/ioctl.h>
> main () {
> int fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY);
> ioctl(fd, TCSBRK, 0);
> close(fd);
> }
>
> Both minicom and my program send a break fine to a regular pc serial port (eg
> ttyS0). In this case it drops my sun box to an "ok" prompt.
>
> However if I use the usb serial adapter both minicom and my program are unable
> to send breaks, they just seem to get ignored.

I was too quick (and wrong!) on my previous response.
I was thinking of TIOCSBRK (turn on break and leave on),
not TCSBRK (turn on break for ~250ms).

My suggestion about timing may still be valid.

Try replacing ioctl(fd, TCSBRK, 0) with
ioctl(fd, TCSBRKP, duration)
duration is in 100ms units, so try 10 or 20.

Or you can use tcsendbreak(fd, duration);
I'm not sure of the units for this function on Linux
manpage says 'implementation defined',
a book I have says 250ms units in Linux.

--
Paul Fulghum
[email protected]

2004-10-20 20:59:40

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wed, 2004-10-20 at 13:46, Thomas Stewart wrote:
> Hi,
>
> I'm having trouble with a Belkin USB serial adapter, I can't get it to send a
> break down the serial cable to a console.
>
> I made a quick program to send a break to a port (mostly ripped off from
> minicom).
>
> porttest.c:
> #include <sys/fcntl.h>
> #include <sys/ioctl.h>
> main () {
> int fd = open("/dev/ttyS0", O_RDWR|O_NOCTTY);
> ioctl(fd, TCSBRK, 0);
> close(fd);
> }
>
> Both minicom and my program send a break fine to a regular pc serial port (eg
> ttyS0). In this case it drops my sun box to an "ok" prompt.
>
> However if I use the usb serial adapter both minicom and my program are unable
> to send breaks, they just seem to get ignored.

Could this be a simple matter of timing?

The Sun box may require a break for a certain period
which by chance is met on a standard UART but not
the USB serial adapter.

Try adding a sleep() after the ioctl call to delay
before clearing the break condition.

--
Paul Fulghum
[email protected]

2004-10-20 22:59:59

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wed, 2004-10-20 at 17:08, Thomas Stewart wrote:

> take porttest.c:
> #include <sys/fcntl.h>
> #include <sys/ioctl.h>
> main(int argc, char ** argv) {
> int fd = open(argv[1], O_RDWR|O_NOCTTY);
> ioctl(fd, TCSBRKP, 20);
> close(fd);
> }
>
> $ time ./porttest /dev/ttyS0
> real 0m2.001s
> user 0m0.001s
> sys 0m0.000s
>
> A standard serial port with a 2 second break (20*100ms), takes as expected
> just over 2 seconds.
>
> $ time ./porttest /dev/ttyUSB1
> real 0m0.004s
> user 0m0.000s
> sys 0m0.001s
>
> However with the USB converter instead, it takes 5 ms to complete. Much
> shorter than expected.
>
> Is it a driver issue?

Can you record and display the return code from the ioctl()?

Thanks

--
Paul Fulghum
[email protected]


2004-10-20 23:22:53

by Thomas Stewart

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wednesday 20 October 2004 23:21, you wrote:
> What kernel version are you running?

2.6.8.1

Well, a stock debian one out of sarge, kernel-image-2.6.8-1-686-smp, configs
at http://www.stewarts.org.uk/stuff/config-2.6.8-1-686. There is not much
difference between a stock 2.6.8.1 and the debian 2.6.8:-
http://www.stewarts.org.uk/stuff/debian.2.6.8.patch

On Wednesday 20 October 2004 23:27, you wrote:
> Can you record and display the return code from the ioctl()?

porttest.c:
#include <sys/fcntl.h>
#include <sys/ioctl.h>
main(int argc, char ** argv) {
int r, fd = open(argv[1], O_RDWR|O_NOCTTY);
r=ioctl(fd, TCSBRKP, 20);
printf("%d\n", r);
close(fd);
}

$ ./porttest /dev/ttyS0
0
$ ./porttest /dev/ttyUSB0
0

Regards
--
Tom

PGP Fingerprint [DCCD 7DCB A74A 3E3B 60D5 DF4C FC1D 1ECA 68A7 0C48]
PGP Publickey [http://www.stewarts.org.uk/public-key.asc]
PGP ID [0x68A70C48]

2004-10-21 02:45:57

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wed, 2004-10-20 at 18:04, Thomas Stewart wrote:
> porttest.c:
> #include <sys/fcntl.h>
> #include <sys/ioctl.h>
> main(int argc, char ** argv) {
> int r, fd = open(argv[1], O_RDWR|O_NOCTTY);
> r=ioctl(fd, TCSBRKP, 20);
> printf("%d\n", r);
> close(fd);
> }
>
> $ ./porttest /dev/ttyS0
> 0
> $ ./porttest /dev/ttyUSB0
> 0

OK, this is a kernel problem with send_break() in tty_io.c

Original:

static int send_break(struct tty_struct *tty, int duration)
{
set_current_state(TASK_INTERRUPTIBLE);

tty->driver->break_ctl(tty, -1);
if (!signal_pending(current))
schedule_timeout(duration);
tty->driver->break_ctl(tty, 0);
if (signal_pending(current))
return -EINTR;
return 0;
}

The USB serial driver break_ctl() sends a URB which does
a sleep and wakeup changing the task state back to TASK_RUNNING.
Because of this, schedule_timeout() above gets short circuited
and the break condition is not maintained long enough.

The normal serial driver break_ctl() leaves the task state
as TASK_INTERRUPTIBLE so you get the proper delay.

Thomas: try the patch below and let me know the results.

--
Paul Fulghum
[email protected]

--- linux-2.6.8/drivers/char/tty_io.c 2004-08-14 00:37:15.000000000 -0500
+++ b/drivers/char/tty_io.c 2004-10-20 21:31:55.000000000 -0500
@@ -1703,11 +1703,11 @@ static int tiocsetd(struct tty_struct *t

static int send_break(struct tty_struct *tty, int duration)
{
- set_current_state(TASK_INTERRUPTIBLE);
-
tty->driver->break_ctl(tty, -1);
- if (!signal_pending(current))
+ if (!signal_pending(current)) {
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(duration);
+ }
tty->driver->break_ctl(tty, 0);
if (signal_pending(current))
return -EINTR;


2004-10-20 22:59:55

by Thomas Stewart

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wednesday 20 October 2004 22:22, you wrote:
> Try replacing ioctl(fd, TCSBRK, 0) with
> ioctl(fd, TCSBRKP, duration)
> duration is in 100ms units, so try 10 or 20.
>
> Or you can use tcsendbreak(fd, duration);
> I'm not sure of the units for this function on Linux
> manpage says 'implementation defined',
> a book I have says 250ms units in Linux.

I've tyred various combinations of ioctl(fd, TCSBRKP, x) and tcsendbreak(fd,
x), where x is 2, 5, 10, 20 and 200.

One thing I did notice is that no mater what the value I use, it always
finishes very quickly, there does not appear to be any duration.

take porttest.c:
#include <sys/fcntl.h>
#include <sys/ioctl.h>
main(int argc, char ** argv) {
int fd = open(argv[1], O_RDWR|O_NOCTTY);
ioctl(fd, TCSBRKP, 20);
close(fd);
}

$ time ./porttest /dev/ttyS0
real 0m2.001s
user 0m0.001s
sys 0m0.000s

A standard serial port with a 2 second break (20*100ms), takes as expected
just over 2 seconds.

$ time ./porttest /dev/ttyUSB1
real 0m0.004s
user 0m0.000s
sys 0m0.001s

However with the USB converter instead, it takes 5 ms to complete. Much
shorter than expected.

Is it a driver issue?

Regards
--
Tom

PGP Fingerprint [DCCD 7DCB A74A 3E3B 60D5 DF4C FC1D 1ECA 68A7 0C48]
PGP Publickey [http://www.stewarts.org.uk/public-key.asc]
PGP ID [0x68A70C48]

2004-10-20 22:29:58

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

Thomas Stewart wrote:

>I've tyred various combinations of ioctl(fd, TCSBRKP, x) and tcsendbreak(fd,
>x), where x is 2, 5, 10, 20 and 200.
>
>One thing I did notice is that no mater what the value I use, it always
>finishes very quickly, there does not appear to be any duration.
>
>take porttest.c:
>#include <sys/fcntl.h>
>#include <sys/ioctl.h>
>main(int argc, char ** argv) {
> int fd = open(argv[1], O_RDWR|O_NOCTTY);
> ioctl(fd, TCSBRKP, 20);
> close(fd);
>}
>
>$ time ./porttest /dev/ttyS0
>real 0m2.001s
>user 0m0.001s
>sys 0m0.000s
>
>A standard serial port with a 2 second break (20*100ms), takes as expected
>just over 2 seconds.
>
>$ time ./porttest /dev/ttyUSB1
>real 0m0.004s
>user 0m0.000s
>sys 0m0.001s
>
>However with the USB converter instead, it takes 5 ms to complete. Much
>shorter than expected.
>
>Is it a driver issue?
>
>
Could be.
That test gives me more information.
I will look closer at the code and see if anything pops out.

Thanks,
Paul

--
Paul Fulghum
[email protected]


2004-10-20 22:29:55

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wed, 2004-10-20 at 17:08, Thomas Stewart wrote:
> Is it a driver issue?

What kernel version are you running?

--
Paul Fulghum
[email protected]


2004-10-21 10:11:47

by Thomas Stewart

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Wed, Oct 20, 2004 at 09:37:58PM -0500, Paul Fulghum wrote:
> static int send_break(struct tty_struct *tty, int duration)
> {
> set_current_state(TASK_INTERRUPTIBLE);
>
> tty->driver->break_ctl(tty, -1);
> if (!signal_pending(current))
> schedule_timeout(duration);
> tty->driver->break_ctl(tty, 0);
> if (signal_pending(current))
> return -EINTR;
> return 0;
> }
>
> The USB serial driver break_ctl() sends a URB which does
> a sleep and wakeup changing the task state back to TASK_RUNNING.
> Because of this, schedule_timeout() above gets short circuited
> and the break condition is not maintained long enough.
>
> The normal serial driver break_ctl() leaves the task state
> as TASK_INTERRUPTIBLE so you get the proper delay.
>
> Thomas: try the patch below and let me know the results.

I tryed again with your patch applyed, with both minicom and porttest

porttest.c:
#include <sys/fcntl.h>
#include <sys/ioctl.h>
main(int argc, char ** argv) {
int r, fd = open(argv[1], O_RDWR|O_NOCTTY);
r=ioctl(fd, TCSBRKP, 20);
printf("%d\n", r);
close(fd);
}

$ time ./porttest /dev/ttyS0
0

real 0m2.001s
user 0m0.000s
sys 0m0.001s
$ time ./porttest /dev/ttyUSB0
0

real 0m2.003s
user 0m0.000s
sys 0m0.001s

As you can see, this time there is the correct pause. However
it still does not send the break.

To add the mix, I dug about and found a differnt type of USB serial
converter, a no-brand one that uses the pl2303 module. Both minicom
and porttest with either stock 2.6.8.1 or 2.6.8.1 with your patch
send the break fine with this different converter.

This makes me think it is a problem with the mct_u232 driver?

Regards
--
Tom

PGP Fingerprint [DCCD 7DCB A74A 3E3B 60D5 DF4C FC1D 1ECA 68A7 0C48]
PGP Publickey [http://www.stewarts.org.uk/public-key.asc]
PGP ID [0x68A70C48]

2004-10-21 12:56:15

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Thu, 2004-10-21 at 05:06, Thomas Stewart wrote:
> I tryed again with your patch applyed, with both minicom and porttest
>
> porttest.c:
> #include <sys/fcntl.h>
> #include <sys/ioctl.h>
> main(int argc, char ** argv) {
> int r, fd = open(argv[1], O_RDWR|O_NOCTTY);
> r=ioctl(fd, TCSBRKP, 20);
> printf("%d\n", r);
> close(fd);
> }
>
> $ time ./porttest /dev/ttyS0
> 0
>
> real 0m2.001s
> user 0m0.000s
> sys 0m0.001s
> $ time ./porttest /dev/ttyUSB0
> 0
>
> real 0m2.003s
> user 0m0.000s
> sys 0m0.001s
>
> As you can see, this time there is the correct pause. However
> it still does not send the break.
>
> To add the mix, I dug about and found a differnt type of USB serial
> converter, a no-brand one that uses the pl2303 module. Both minicom
> and porttest with either stock 2.6.8.1 or 2.6.8.1 with your patch
> send the break fine with this different converter.
>
> This makes me think it is a problem with the mct_u232 driver?

OK. This problem has multiple parts.

The change to tty_io.c is necessary to get the proper delay
between setting and clearing break. I will submit that
patch for inclusion.

Now it is a matter of figuring why the device is not
sending the break. The device break_ctl() gets called,
and the URB to set the line control is sent successfully.

Maybe the comments are wrong on the line control bits
or possibly the Belkin device requires some other setup
to send breaks.

I'll see if I can figure anything out.

--
Paul Fulghum
[email protected]

2004-10-21 19:57:43

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Thu, 2004-10-21 at 07:41, Paul Fulghum wrote:
> On Thu, 2004-10-21 at 05:06, Thomas Stewart wrote:
> > As you can see, this time there is the correct pause. However
> > it still does not send the break.
> >
> > To add the mix, I dug about and found a differnt type of USB serial
> > converter, a no-brand one that uses the pl2303 module. Both minicom
> > and porttest with either stock 2.6.8.1 or 2.6.8.1 with your patch
> > send the break fine with this different converter.
> >
> > This makes me think it is a problem with the mct_u232 driver?
>
> OK. This problem has multiple parts.
>
> The change to tty_io.c is necessary to get the proper delay
> between setting and clearing break. I will submit that
> patch for inclusion.
>
> Now it is a matter of figuring why the device is not
> sending the break. The device break_ctl() gets called,
> and the URB to set the line control is sent successfully.
>
> Maybe the comments are wrong on the line control bits
> or possibly the Belkin device requires some other setup
> to send breaks.

I looked at mct_232.h and noticed the comment:

"There seem to be two bugs in the Win98 driver:
the break does not work (bit 6 is not asserted) and the
stick parity bit is not cleared when set once."
The driver was reverse engineered from the Win98 driver.

Even though the LCR for this device is similar to
the LCR of a 16550 UART, some bits work differently.

This suggests to me that either the device does not
properly support break, or that the break is
controlled through a different USB request and not
through MCT_U232_SET_LINE_CTRL_REQUEST

The Linux and FreeBSD drivers do the same thing
for setting break, so no new info there.
I don't have access to the device or manufacturer docs.

The only thing I can suggest is if you have
access to a Windows 2000/XP machine, try and generate
a break with the manufacturer provided drivers.
If you can't, then the device does not support break.
If you can, then maybe you can use USB sniffer
software to look at the USB requests going to the device.

--
Paul Fulghum
[email protected]

2004-11-04 18:28:56

by Thomas Stewart

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Thursday 21 October 2004 20:44, Paul Fulghum wrote:
> I looked at mct_232.h and noticed the comment:
>
> "There seem to be two bugs in the Win98 driver:
> the break does not work (bit 6 is not asserted) and the
> stick parity bit is not cleared when set once."
> The driver was reverse engineered from the Win98 driver.
>
> Even though the LCR for this device is similar to
> the LCR of a 16550 UART, some bits work differently.
>
> This suggests to me that either the device does not
> properly support break, or that the break is
> controlled through a different USB request and not
> through MCT_U232_SET_LINE_CTRL_REQUEST
>
> The Linux and FreeBSD drivers do the same thing
> for setting break, so no new info there.
> I don't have access to the device or manufacturer docs.
>
> The only thing I can suggest is if you have
> access to a Windows 2000/XP machine, try and generate
> a break with the manufacturer provided drivers.
> If you can't, then the device does not support break.
> If you can, then maybe you can use USB sniffer
> software to look at the USB requests going to the device.

I tried the converter on a XP machine and unfortunately while using the
manufacturer provided drivers I was unable to produce a break :-(

As a last resort I tried Belkins tech support line. The first time I called I
was told the product (F5U109ea) was designed for PDA use only and it would
generate breaks fine if connected to them. Admittedly it is marketed as such
(http://catalog.belkin.com/IWCatProductPage.process?Product_Id=103226). I was
told to buy a F5U103 instead
(http://catalog.belkin.com/IWCatProductPage.process?Product_Id=66002). Not
happy with this I rang back to talk to another person, this time I was not
fobbed off as quickly and although the tech support guy did not know what a
break was, he offered to look into it and call me back. I've not heard back
(yet), but I'm not too surprised.

Interestingly I got my hands on a F5U103 and it works fine (uses another chip
and consequently module). However they are so much more bulky I don't think
I'm going to bother changing over.

Thanks for all the help :-)

Regards
--
Tom

PGP Fingerprint [DCCD 7DCB A74A 3E3B 60D5 DF4C FC1D 1ECA 68A7 0C48]
PGP Publickey [http://www.stewarts.org.uk/public-key.asc]
PGP ID [0x68A70C48]

2004-11-04 19:37:59

by Paul Fulghum

[permalink] [raw]
Subject: Re: belkin usb serial converter (mct_u232), break not working

On Thu, 2004-11-04 at 12:20, Thomas Stewart wrote:
> I tried the converter on a XP machine and unfortunately while using the
> manufacturer provided drivers I was unable to produce a break :-(

That seems consistent with the code, comments,
and observed behavior.

I doubt this device can generate a break.

> was told the product (F5U109ea) was designed for PDA use only and it would
> generate breaks fine if connected to them.

Sounds like garbage (industry standard for phone support) to me.

I can't see how the bit pattern generated on TxD is dependent
on the attached device. The support person probably
has no idea what a break pattern is.

> Interestingly I got my hands on a F5U103 and it works fine (uses another chip
> and consequently module).

This all looks like a missing/non-functioning feature
for the F5U109.

--
Paul Fulghum
[email protected]