Author Topic: How do I change hardware handshake lines in USB CDC?  (Read 28692 times)

Offline Chuck

  • Newbie
  • *
  • Posts: 9
    • View Profile
How do I change hardware handshake lines in USB CDC?
« on: January 06, 2010, 12:42:52 AM »
Hi Mark,

I use USB CDC for serial communication emulation with 52259. It works great so far, and I want to have more control on hardware handshake lines for flow control. I can see how to update RTS and DTR lines from the host in control_callback function.

How can I send changes in CTS and DSR lines to the host? What do I write into USB_control end point?

Chuck

« Last Edit: January 06, 2010, 01:01:42 AM by Chuck »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3243
    • View Profile
    • uTasker
Re: How do I change hardware handshake lines in USB CDC?
« Reply #1 on: January 06, 2010, 01:23:11 AM »
Hi Chuck

Unfortunately I don't have an complete answer ready for this question.

In the one direction this a standard procedure in the "Abstract Control Model" of CDC. This is specified in the PSTN subclass. As you already known the OUT command 0x22 (SET_CONTROL_LINE_STATE) is used which contains the RTS and DTR states.

I would have expected to find an IN command specified in this document (the class and sub-class documents can be downloaded from ww.usb.org - if you don't have them you need to go to the 'developers' section and hunt around in the document section) but I never identified them. When I used an analyser to see what USB cables do then seem to send a proprietary code or something, which then is probably only understood by the driver that they install...

However I just checked again and do in fact find something for DCD and DSR (but not CTS). Take a look at the "CDC PSTN sub-class document Rev. 1.2 from February 9, 2007". Section 6.5.4 "SerialState". The actual command values are however defined in the CDC document... SerialState has the IN value 0x20. Then the bit map of the control signals is given which may help get started on this!

Regards

Mark

PS: I wonder whether they left out the CTS since flow control is automatically handled by the USB when the receiver stops reading(?)
« Last Edit: January 06, 2010, 01:24:42 AM by mark »

Offline Chuck

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: How do I change hardware handshake lines in USB CDC?
« Reply #2 on: January 06, 2010, 09:37:30 PM »
Your answer helps  a lot.

It looks like I have to implement a callback function for the interrupt endpoint to send a notification for SERIAL_STATE. Is it right? 

Thank you.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3243
    • View Profile
    • uTasker
Re: How do I change hardware handshake lines in USB CDC?
« Reply #3 on: January 08, 2010, 11:25:12 PM »
Hi Chuck

Did you make any progress here?

The CDC example is already sending its serial port setting using:
fnWrite(USB_control, (unsigned char *)&uart_setting, sizeof(uart_setting));

This is performed as a consequence of the host's request GET_LINE_CODING, but supposedly could be sent at any time.
A write to the USB control handle of the message type that you would like to send would involve changing the sent contents.

I don't know the operation of the control channel - possibly the device is polled with fast enough that the message will not have to be delayed too long. The host controls the polling and it may be sped up by changing the polling value in the endpoint configuration:

    {                                                                    // interrupt endpoint descriptor for first interface
    DESCRIPTOR_TYPE_ENDPOINT_LENGTH,                                     // descriptor size in bytes (0x07)
    DESCRIPTOR_TYPE_ENDPOINT,                                            // end point descriptor (0x05)
    (IN_ENDPOINT | 0x03),                                                // direction and address of endpoint
    ENDPOINT_INTERRUPT,                                                  // endpoint attributes
    {LITTLE_SHORT_WORD_BYTES(64)},                                       // endpoint FIFO size (little-endian)
    10                                                                   // polling interval in ms
    },                                                                   // end of endpoint descriptor


Regards

Mark



Offline Chuck

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: How do I change hardware handshake lines in USB CDC?
« Reply #4 on: January 15, 2010, 02:30:19 AM »
Hi Mark,

You were right about the CTS line. It is not specified in CDC class. It does not seems changeable, without a customized driver. I hope at least I can control DSR line, because the program I want to use needs it.

Things are more complicated than I expected.
To send a notification to the host, the interrupt endpoint has to be activated.
When I looked in the USB interrupt sevice routine, static __interrupt__ void _usb_otg_isr(void),
I found that interrupt PID is not serviced and the endpoint is set stalled.

To add interrupt PID handler, I found I have to deal with low level USB  details that I am not familliar with. And then I can make it send SERIAL_STATE notification back to the host.
 
We will see if I can get 10 ms polling, if it is implemented.
Your help will be really appreciated.
 
Chuck

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3243
    • View Profile
    • uTasker
Re: How do I change hardware handshake lines in USB CDC?
« Reply #5 on: January 18, 2010, 02:30:23 AM »
Hi Chuck

I don't know of an interrupt PID in USB 2.0. An interrupt endpoint is a transfer mode, using IN PIDs like a bulk endpoint also does.

An interrupt endpoint is different to a bulk endpoint in that its transfer slot is reserved - it will be requested by the host at the interrupt rate; the fastest interrupt rate is however 1ms (one request per frame) - slower interrupt rates are possible as defined in the endpoints configuration.

Interrupt mode is in fact polling mode. A device can not initiate a transfer itself, but only wait for the host to poll it. An endpoint in bulk mode can transfer more data and also several IN tokens in a single 1ms frame - but its bandwidth is not guarantied. That means that it may have to wait several frames before it can send - meaning that it actually has lower priority that an interrupt endpoint which has guarantied time slot, but can send more when it does get the chance to do so.

Can you explain more about the interrupt PID that you referenced?

Regards

Mark


Offline Chuck

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: How do I change hardware handshake lines in USB CDC?
« Reply #6 on: January 18, 2010, 03:18:20 AM »
Hi Mark,

I don't think I clearly understand what has to be done for the interrupt. What I meant with interrupt PID was interrupt IN PID. If the interrupt endpoint has nothing to send when polled, it is supposed to respond with NAK. If not, I guess the host will wait until timeout. It is not clear that USB ISR sends NAK if the buffer is empty, since it is pretty complicated for me to read. Can I just write into the interrupt IN endpoint when a notification needs to send, otherwise the NAK is sent?

Chuck

 

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3243
    • View Profile
    • uTasker
Re: How do I change hardware handshake lines in USB CDC?
« Reply #7 on: January 18, 2010, 12:36:36 PM »
Hi Chuck

The USB controller HW is responsible for sending NAKs when there is no data to be sent. This means that it takes place automatically without any software interaction (no interrupt occurs when an IN token is received).

When there is data queued it will automatically be sent when the IN token is received, after which an interrupt occurs which is used to acknowledge the transmission of the first data block and send following date from the tx queue (if one is used).

What this means for you is that you can simply put a message into the output buffer and it will be sent the next time the host polls the interrupt endpoint.

Regards

Mark

Offline Chuck

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: How do I change hardware handshake lines in USB CDC?
« Reply #8 on: January 26, 2010, 08:26:25 PM »

Good news

It works! When I write 10 bytes SERIA_STATE notification into the interrupt IN endpoint, it sets DSR asserted in my application. According to a USB analyzer, the latency is less than 10 ms, as set in the interrupt endpoint description.

I send SERIAL_STATE notifications, depending on DTR state in Control Line State request sent by the host. It works like a charm.

I was worried how the Windows driver (usbser.sys) would handle the interrupt notification. Well, it handles DSR properly.


Bad news

With Codesourcery G++ lite complier, I was not able to make fnwrite into USBPortID_interrupt_3 work reliably. The USB analyzer shows notification is delivered sometimes OK, but sometimes no transmission or wrong string to the host.

I could not figure out what is wrong. I tried Codeworrior, and everything works fine.

I suspect something is not right with USB fnWrite if complied with the GNU complier.
My wild guess is it maybe be interrupt-related.

I also had problems in fnwrite into the data IN enpoint.
With continous sending data to the host, it crashes in hours. And it depends on the size of TxQueueSiz. The bigger queue size, the long it lasts before it stops.
At first I suspect the windows driver is faulty. But if complied with CodeWarrior, it works without problems.

I guess this is a issue you have to look into.

I always appreciate your dedication to uTasker.

Chuck