Reply by t_chinzei December 1, 20082008-12-01
If you call the buffer read out routine below just from the ISR
(Interrupt Service Routine) of the bulk OUT endpoint, no more
interrupt for this ISR occurs, when the routine leaves the endpoint
buffer unread because of full RX buffer. The USB engine evokes
endpoint interrupt just when a new OUT transaction is ACKed and the
OUT endpoint buffer is refreshed. It doesn't occur while the endpoint
buffer is occupied.

Then, the firmware should have another supervisor task, which watches
both of the RX buffer and the OUT endpoint periodically, and which
invokes the buffer read out routine. The SOF (FRAME) ISR is one of the
candidates to implement this supervisor task, but any other periodical
(repeated) task will do. Such as a timer ISR, polling on the
superloop, etc. The period is mainly determined by the required speed.
I've shown SOF in above post, just because it's handy. If the firmware
can process the data on the RX buffer faster, a timer interrupt of
shorter than SOF is applied.

IN/OUT endpoint interrupts are the events caused by the host side. On
the device side, however, there are another events caused by the
device processes. For example, RX buffer full/ TX buffer empty, finish
of a process, user's key-in, etc. These device side events occur
independently from the USB events. The supervisor task watches the
events (status) of both sides, and it schedules the transfer between
the endpoint buffer and the firmware buffer.

When this supervisor task cooperates with the endpoint interrupts, the
response latency for the host events (complete of new IN/OUT
transaction) decreases, and the transfer speed increases. However, it
doesn't mean this supervisor task is not required at all. Without this
supervisor task, endpoint interrupt causes data drop (overwrite) on
the firmware buffer for OUT EP, extra packets for IN EP.

No firmware handler for bulk/ interrupt/ control transfer goes without
this supervisor, though it may be in a simplified shape. Not just for
CDC-ACM.

It has been improved recently a little, but still many USB examples
lack the supervisor, examples from KEIL, IAR, STMicro, Atmel, SiLabs,
Microchip, LPCUSB, etc. I discussed on this issue with Bertrik on
LPCUSB once on this forum; He tries to implement this supervisor using
NAK interrupt, and it isn't a good way. Unfortunately, as my
explanation was not so sophisticated in those days, I couldn't get him
to convinced. He sticks to the USB interrupts so much, and drops the
view point of the device side events, and the arbitration of both
side. But I believe he'll come to this insight soon :-)

Tsuneo

--- In l..., Wojciech Kromer
wrote:
> > This is the standard way. Maybe some trouble occurs on the firmware.
> > Call this subroutine from the interrupt handler of the bulk OUT
> > endpoint AND SOF (FRAME) interrupt handler. This subroutine is easily
> > made modifying the routine which reads out an endpoint.
> >
> > - Call "Select Endpoint" command and get Full/Empty (FE) bit
> > - - if the EP buffer is empty, return
> > - Get the packet size on the OUT EP
> > - - set RD_EN bit and logical address to USBCtrl register
> > - - wait for PKT_RDY bit on USBRxPLen register
> > - - mask USBRxPLen and get PKT_LNGTH
> > - If the space on the RX buffer is less than packet size,
> > - - clear USBCtrl register
> > - - return
> > - Read out all data to the RX buffer from USBRxData register
> > - Clear USBCtrl register
> > - Call "Clear Buffer" command
> > - Repeat above entire sequence again (for double buffer)
> >
> > Tsuneo
> >
> Thank you very much for details.
> That's almost i'm doing except reading packet size and clearing USBCtrl
> when there is no data.
> What about next OUT SOF interrupt with? Will LPC repeat it?
>

An Engineer's Guide to the LPC2100 Series

Reply by Wojciech Kromer December 1, 20082008-12-01
> This is the standard way. Maybe some trouble occurs on the firmware.
> Call this subroutine from the interrupt handler of the bulk OUT
> endpoint AND SOF (FRAME) interrupt handler. This subroutine is easily
> made modifying the routine which reads out an endpoint.
>
> - Call "Select Endpoint" command and get Full/Empty (FE) bit
> - - if the EP buffer is empty, return
> - Get the packet size on the OUT EP
> - - set RD_EN bit and logical address to USBCtrl register
> - - wait for PKT_RDY bit on USBRxPLen register
> - - mask USBRxPLen and get PKT_LNGTH
> - If the space on the RX buffer is less than packet size,
> - - clear USBCtrl register
> - - return
> - Read out all data to the RX buffer from USBRxData register
> - Clear USBCtrl register
> - Call "Clear Buffer" command
> - Repeat above entire sequence again (for double buffer)
>
> Tsuneo
>
Thank you very much for details.
That's almost i'm doing except reading packet size and clearing USBCtrl
when there is no data.
What about next OUT SOF interrupt with? Will LPC repeat it?

Reply by t_chinzei November 28, 20082008-11-28
> I believe there are two levels of flow control that you might deal with.

Splendid!!
You got a good view point which closes to the USB class essence.
Most of USB classes are designed to carry other protocols [*1]. For
CDC-ACM, USB carries RS232 signaling. CDC-ACM supposes that a MODEM
(UART) is attached to the other end. Therefore, the flow control of
RS232 (DTR-DSR, Xon-Xoff etc) doesn't concern to the USB side
directly. The MODEM does the flow control with an external device
connected to the MODEM. USB just carries the handshake signaling [*2].
Of course, we can connect any other peripheral to CDC-ACM instead of
MODEM. Or, we can connect some virtual device which is made up just on
the firmware. In these cases also, CDC-ACM supposes a virtual MODEM there.

Other than this protocol-level flow control, there is a USB
hardware-level flow control - NAKing. NAKing is an intrinsic flow
control of USB. NAKing is applied to Bulk, Interrupt and data stage of
Control transfer, to match the transfer speed between USB host and device.

The Wojciech problem is solved by NAKing.
Wojciech > What is correct way to stop transmission from HOST to DEVICE?

While the RX buffer on the firmware is full, don't read out data from
the bulk OUT endpoint. Just when there is enough space on the RX
buffer, read it out. While the OUT endpoint buffer is occupied, the
device USB engine returns NAK on OUT transaction. Host controller
repeats OUT transactions of the last contents until the engine ACKs,
unless the device driver stops it on timeout (SetCommTimeouts). In
this way, the data stream pauses without any data loss.

[*1] Protocols carried by USB class
Audio class: PCM, MPEG, AC-3, MIDI, etc
CCID class: Smart Card
Mass storage - BOT class: SCSI
Printer class: IEEE P1284
Still Image class: PTP (PIMA 15740)
USBTMC: VISA
Video: MPEG, H.264, DV, etc.

[*2] RS232 handshake carried by CDC-ACM
SetControlLineState request - RTS, DTR
SerialState notification - RI, DSR, DCD
-- note: CTS is not counted in CDC-ACM

Tsuneo

--- In l..., "thirdshoedrops" wrote:
>
> --- In l..., Wojciech Kromer
> wrote:
> > I mean how to stop HOST sending data being a DEVICE.
> > I'm trying to run on a device typical flow control, and send from
DEVICE
> > to HOST something
> > like 'hey do not send me data now', and of course 'send it now'.
>
> I have made very little progress with my USB projects, but I believe
> there are two levels of flow control that you might deal with. The
> first is USB host-device flow control, and the second is flow control
> that higher-level code on the host and device agree to perform. For
> USB-level flow control, I think what happens is that when the host
> wants to send data, it first sends an "OUT" transaction setup
> sequence, then the device acknowledges it, and then the host sends the
> data. If the device isn't ready to accept data, it NAKs (or maybe
> STALLs?) and the host waits to send. I think this is the most
> reliable way for a USB device to do flow control.
>
> The other way, with a CDC-ACM device, is for the device to send
> (Interrupt?) packets to notify the host that one of the control lines
> has changed state. Normally, the USB device would also have a UART,
> and the USB part would report UART state to the host, but if you're
> doing a pseudo-serial device, you could fake the UART modem control
> signals however you want. If the host software is configured to honor
> hardware flow control indications, then the device could report "CTS
> off" when it wanted the host to stop sending. However, if the host
> software doesn't respect the flow control indications, then the USB
> layer will happily send the data.
>
> So, depending on which parts of the system you're working on (and have
> access to the code for), you may decide to use USB or modem-control
> flow control.
>

Reply by t_chinzei November 28, 20082008-11-28
>What is correct way to stop transmission from HOST to DEVICE?
> b) not reading data from EP causes NAK (it's OK) but it seems some
data are lost wit this way

This is the standard way. Maybe some trouble occurs on the firmware.
Call this subroutine from the interrupt handler of the bulk OUT
endpoint AND SOF (FRAME) interrupt handler. This subroutine is easily
made modifying the routine which reads out an endpoint.

- Call "Select Endpoint" command and get Full/Empty (FE) bit
- - if the EP buffer is empty, return
- Get the packet size on the OUT EP
- - set RD_EN bit and logical address to USBCtrl register
- - wait for PKT_RDY bit on USBRxPLen register
- - mask USBRxPLen and get PKT_LNGTH
- If the space on the RX buffer is less than packet size,
- - clear USBCtrl register
- - return
- Read out all data to the RX buffer from USBRxData register
- Clear USBCtrl register
- Call "Clear Buffer" command
- Repeat above entire sequence again (for double buffer)

Tsuneo

--- In l..., Wojciech Kromer
wrote:
>
> Hello.
>
> I'm trying to use my own LPC2148 USB stack, and getting sick with
> usbser.sys.
> What is correct way to stop transmission from HOST to DEVICE?
>
> a) sending USB_CDC_NOTIFY_SERIAL_STATE with DSR off is not working with
> usbser.sys
> b) not reading data from EP causes NAK (it's OK) but it seems some data
> are lost wit this way
> c) stall-in EP, causes ERROR on USB
>
> Any suggestions?
> Some tricks with .inf file?
> Another CDC-ACM driver for windows?
>
> Regards.
>

Reply by Wojciech Kromer November 28, 20082008-11-28
Bruce Paterson pisze:
> This is the old "windows CDC" issues again.
>
> The windows implementation of CDC (usbser.sys) does not handle
> handshaking signals reliably. I believe the Linux one does, as do most
> of the 3rd party drivers to go with prolific or FTTI chipsets.
>
> That said, I'm not sure if any actually implement flow control using
> CTS/RTS. The other controls signals such as DTR/DST/DCD/RI etc should be
> handled correctly and passed through as notify control, but flow control
> would be better handled by the NAK process.
>
> Since you are using CDC, and you probably want to handle connecting to a
> Windows box, there really is only 1 choice left anyway.
>
Is there any other way to force NAK, except not reading EP data after
OUT interrupt?

Reply by Bruce Paterson November 27, 20082008-11-27
This is the old "windows CDC" issues again.

The windows implementation of CDC (usbser.sys) does not handle
handshaking signals reliably. I believe the Linux one does, as do most
of the 3rd party drivers to go with prolific or FTTI chipsets.

That said, I'm not sure if any actually implement flow control using
CTS/RTS. The other controls signals such as DTR/DST/DCD/RI etc should be
handled correctly and passed through as notify control, but flow control
would be better handled by the NAK process.

Since you are using CDC, and you probably want to handle connecting to a
Windows box, there really is only 1 choice left anyway.

Cheers,
Bruce
-----Original Message-----
From: l... [mailto:l...] On Behalf
Of thirdshoedrops
Sent: Friday, 28 November 2008 8:49 AM
To: l...
Subject: [lpc2000] Re: LPC2148 and USB CDC-ACM flow control with
usbser.sys

--- In l..., Wojciech Kromer
wrote:
> I mean how to stop HOST sending data being a DEVICE.
> I'm trying to run on a device typical flow control, and send from
DEVICE
> to HOST something
> like 'hey do not send me data now', and of course 'send it now'.

I have made very little progress with my USB projects, but I believe
there are two levels of flow control that you might deal with. The
first is USB host-device flow control, and the second is flow control
that higher-level code on the host and device agree to perform. For
USB-level flow control, I think what happens is that when the host
wants to send data, it first sends an "OUT" transaction setup
sequence, then the device acknowledges it, and then the host sends the
data. If the device isn't ready to accept data, it NAKs (or maybe
STALLs?) and the host waits to send. I think this is the most
reliable way for a USB device to do flow control.

The other way, with a CDC-ACM device, is for the device to send
(Interrupt?) packets to notify the host that one of the control lines
has changed state. Normally, the USB device would also have a UART,
and the USB part would report UART state to the host, but if you're
doing a pseudo-serial device, you could fake the UART modem control
signals however you want. If the host software is configured to honor
hardware flow control indications, then the device could report "CTS
off" when it wanted the host to stop sending. However, if the host
software doesn't respect the flow control indications, then the USB
layer will happily send the data.

So, depending on which parts of the system you're working on (and have
access to the code for), you may decide to use USB or modem-control
flow control.
Reply by thirdshoedrops November 27, 20082008-11-27
--- In l..., Wojciech Kromer
wrote:
> I mean how to stop HOST sending data being a DEVICE.
> I'm trying to run on a device typical flow control, and send from DEVICE
> to HOST something
> like 'hey do not send me data now', and of course 'send it now'.

I have made very little progress with my USB projects, but I believe
there are two levels of flow control that you might deal with. The
first is USB host-device flow control, and the second is flow control
that higher-level code on the host and device agree to perform. For
USB-level flow control, I think what happens is that when the host
wants to send data, it first sends an "OUT" transaction setup
sequence, then the device acknowledges it, and then the host sends the
data. If the device isn't ready to accept data, it NAKs (or maybe
STALLs?) and the host waits to send. I think this is the most
reliable way for a USB device to do flow control.

The other way, with a CDC-ACM device, is for the device to send
(Interrupt?) packets to notify the host that one of the control lines
has changed state. Normally, the USB device would also have a UART,
and the USB part would report UART state to the host, but if you're
doing a pseudo-serial device, you could fake the UART modem control
signals however you want. If the host software is configured to honor
hardware flow control indications, then the device could report "CTS
off" when it wanted the host to stop sending. However, if the host
software doesn't respect the flow control indications, then the USB
layer will happily send the data.

So, depending on which parts of the system you're working on (and have
access to the code for), you may decide to use USB or modem-control
flow control.
Reply by Wojciech Kromer November 27, 20082008-11-27
> Are you sure this is a usbser.sys problem? The program that uses the
> connection (HyperTerm, for example), has to honor hardware flow control,
> just like when using a real UART.
>
>
I'm using FreeSerialPortMonitor to see all control "leds".
The seems not to change on clearing DSR bit after sending
USB_CDC_NOTIFY_SERIAL_STATE

Hyperterminal is not a good tool for testing. Problem appears with ppp
dialup.
I'm testing it on XP-SP3.

What I need to say, that with linux cdc_acm driver it works fine.

Regards.
Reply by "J.C. Wren" November 27, 20082008-11-27
Are you sure this is a usbser.sys problem? The program that uses the
connection (HyperTerm, for example), has to honor hardware flow control,
just like when using a real UART.

--jc

Reply by Wojciech Kromer November 27, 20082008-11-27
>> I'm trying to use my own LPC2148 USB stack, and getting sick with
>> usbser.sys.
>> What is correct way to stop transmission from HOST to DEVICE?
>>
>
> Just close the handle?
>
>
I mean how to stop HOST sending data being a DEVICE.
I'm trying to run on a device typical flow control, and send from DEVICE
to HOST something
like 'hey do not send me data now', and of course 'send it now'.
>> a) sending USB_CDC_NOTIFY_SERIAL_STATE with DSR off is not working with
>> usbser.sys
>> b) not reading data from EP causes NAK (it's OK) but it seems some data
>> are lost wit this way
>> c) stall-in EP, causes ERROR on USB
>>
>> Any suggestions?
>>
> This might help.
> http://www.cygnal.org/ubb/Forum9/HTML/000945.html
>
>

>> Some tricks with .inf file?
>>
> What is your inf file?
>
Here it is:

[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}

Provider=%DGT%
LayoutFile=layout.inf
DriverVer/04/2004,5.1.2600.2180

[Manufacturer]
%DGT%=DGT

[DGT]
%XXX%= XXX,USB\VID_1BB7&PID_0002
[DestinationDirs]
FakeModemCopyFileSection
DefaultDestDir = 12

[XXX.NT]
include=mdmcpq.inf
CopyFileseModemCopyFileSection
AddReg=XXX.NT.AddReg

[XXX.NT.Services]
AddService = usbser, 0x00000002, Service_Inst

[Service_Inst]
DisplayName = %Serial.SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\usbser.sys
LoadOrderGroup = Base

[XXX.NT.AddReg]
HKR,,NTMPDriver,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
HKR,,PortSubClass,1,01

[Strings]
DGT = "DGT"
XXX = "XXX"
Serial.SvcDesc = "XXX USB Driver"

>
>> Another CDC-ACM driver for windows?
>>
> Why do you want to use CDC-ACM? Why not HID?
>
>
I'm implementing a kind of modem.

Regards.