Prolific PL2303 driver
Rick Murray (539) 13840 posts |
Steve: It is interesting writing code for a device on the expectation that it will fail… Well, when talking to a device, the usual expectation is that the device will respond unless it is broken. Not that it may respond if it feels so inclined, and might decide to get bored of you partway into the discussion and walk away pointing at random trees… ;-)
Tell me. I think I owe somebody a beer. I think, also, that I have sorted out the problem of people who have crashy Windows that bluescreens all the time…they’re using Prolific drivers. That must be it! On behalf of my weather station, I have implemented the checksumming and hardened the transmit/receive handlers. I’ve also removed the &06 byte to reset the command sequence, this is only really necessary if the device gets itself in a muddle. Some other optimisations and tightening up the delay timeouts (easier now the code bails if stuff looks iffy so it can have another go at it) mean that I’ve got the data reception down from about 43 seconds to about five seconds. Whee. :-) What is online now is far from finished (it doesn’t record any history, and I want to break apart the data fetch and data parsing) but I wanted to get the early v2 version up asap to get going with the hardened data fetcher routine. |
Dave Higton (1515) 3526 posts |
Does anyone know for certain how to specify the “word format” to/from a serial blockdriver (function 15)? I suspect it’s the same as for OS_SerialOp 1 (paper PRM 2-464), but I’d appreciate help from anyone with knowledge. |
Rick Murray (539) 13840 posts |
The Internal32 driver does this:
So it looks like -1 reads the current word format, and a positive value sets it in the same format as the SerialOp SWI. The only difference is that -1 reads a local copy (held in the driver) instead of asking SerialOp. Hmmm… |
Ronald May (387) 407 posts |
Does anyone know for certain how to specify the “word format” to/from a serial blockdriver Inside the Hugo Fiennes Blockdriver download there is a BASIC example which might help you. |
Colin (478) 2433 posts |
If anyone would like to try, my SerialUSB drivers are available here |
Matthew Phillips (473) 721 posts |
This looks interesting! If you have a serial USB device, is there an easy way to find out whether it is based on one of the supported chipsets (CP210x, PL2303, CH340)? Does !USBinfo give this information? I ask because at the Wakefield Show last year someone asked us whether we could support a GPS device that used serial USB in order to feed current location information to RiscOSM for maps. It would be excellent to be able to support this. If it’s straight-forward to identify the type of devices, I would like to get in touch with the user with instructions o how to check. Thanks! |
Rick Murray (539) 13840 posts |
…if you have the serial device, and you have the driver module… …then plug in the device, run the module, and then enter: Filer_OpenDir Devices:$ and see if there is a SerialUSB device present. If it exists, then the module recognises the device. If it is not recognised, then it may be worth looking in USBInfo to see what the device identifies itself as. If it is an FTDI interface, there is an FTDI driver here: http://www.thomas-milius.privat.t-online.de/English/Computer/ |
Colin (478) 2433 posts |
or
and you get a textural description of any devices recognised.
If it wasn’t supported if you sent me the output from !USBDescriptors from my ftpc site with it plugged in I can tell you the odds of getting it to work. |
Chris Evans (457) 1614 posts |
!USBinfo reports what the device is programmed to report. This most of the time is enough to tell you the chip set used. In our experience some USB devices give nothing useful and a few lie! But it is an easy thing to try so worth trying. |
Ronald May (387) 407 posts |
Colin, my Prolific is recognised by your driver and terminal, I have to do some hw connections to the leads before I can go further. A later thought on the Prolific USB Serial with the flying leads (Tx/Rx 3v +gnd and a 5V supply) |
Ronald May (387) 407 posts |
Hmmm, 2 postings instead of one, not caused by editting this time. |
Colin (478) 2433 posts |
The link didn’t work. Just email the descriptors to my address on the FTPc page |
Neil Fazakerley (464) 124 posts |
@Colin and Dave. Would either of you have a vaguely usable pre-release version of your PL2303 modules you could send me to test on a BB-xM? I’ve acquired a couple of those ubiquitous PL2303 USB dongles with alledgedly fully wired RS232 DB9 sockets and I have a good real-world test to try them on (i.e. hacking a cnc machinetool’s serial protocol with a view to converting it to run under Risc OS): serial att anf dott nildram dott co dott uk Cheers. |
Colin (478) 2433 posts |
I’ve just updated SerialUSB to include FTDI. It may need polishing put it seems ok at the moment. I’d be interested if anyone can test it with an FTDI dongle. Note the read performance of FTDI is not as good as PL2303 of CP2102 as the silly read endpoint format slows things down. It runs at about half the speed of PL2303 and CP2102 – CH340 has similar read performance problems for a different reason. Neil. The above module will do PL2303 |
Rick Murray (539) 13840 posts |
Thanks good news. A one-size-fits-all module. Nice job. ;-) |
Dave Higton (1515) 3526 posts |
Colin: I can’t see any evidence that the PL2303 supports XON/XOFF handshaking inherently; is that your understanding? If I’m right, that means that some layer of software has to provide it. I’m thinking that it should be in the module, so that the user’s app doesn’t have to provide it. A quick search through your code hasn’t thrown up any such handling, although I may not have hit on the correct search terms. |
Rick Murray (539) 13840 posts |
Most of the standard traditional UARTs do not support this, it was introduced with the 16750, possibly due to the fact that you simply can’t have a sensible software flow control with a ~32 byte buffer (if you need to rely on a buffer that size you probably aren’t answering in time to notice the rate of buffer fill to get an Xoff sent and acted upon before data loss occurs). Also software flow control is not eight bit clean; which means the end program needs to be aware that this is in use to avoid accidently sending Xoff/Xon bytes. Long story short, if the USB devices are pretending to be akin to a standard 16550 UART, it probably won’t do software flow control by itself. |
Dave Higton (1515) 3526 posts |
The way I see it: if the calling programme configures the blockdriver to use software flow control, it expects the blockdriver to implement it, and may or may not receive XON or XOFF; if it does, it will ignore tham. If the calling programme wants to implement its own software flow control, then it should configure the blockdriver to use no flow control. The practical difficulty comes in the timing. If XOFF is not sent and acted upon quickly enough, buffers may overflow. The module does the transmission and reception nearest to real time, so is in the best position to implement the handshake. The calling programme may or may not have control at the vital moment. I’m not concerned with emulating a particular hardware device; I’m concerned with implementing something that has all the features in the serial blockdriver specification. In this particular case, see function 16. |
Colin (478) 2433 posts |
To set the Xon Xoff chars use
This sets Xoff to 0×13 and Xon to 0×11 – the standard values To set Xon Xoff handshaking use
|
Dave Higton (1515) 3526 posts |
Thanks, Colin. Where did you get that information from? I assume there has to be more to it than that (apart from how to disable it again…) I can only imagine that working on the serial out direction, i.e. in response to XOFF on the serial in, it will stop sending on serial out. But what happens then? You can’t just keep pouring data into the USB bulk out endpoint, because the PL2303’s buffer is finite. So how does it prevent you from doing it? Does it stall the endpoint, or what? Also, I can’t see how it can work in the other direction (serial in), because the PL2303 has no idea of how big the buffers are in the host system, so it can’t know when to send XOFF/XON – unless the PL2303 has an internal buffer considerably larger than the bulk packet size. |
Colin (478) 2433 posts |
A packet sniffer. I just run a serial terminal on a pc set the various options and inspected the packets produced. You have to figure that they all work in a similar way so for example there must be a command to set the different handshake options as it’s impossible to do it in software over usb. The PL2303 is basically a USB CDC device. The CDC specification doesn’t include handshaking so handshaking is added as a vendor specific command (0×40) with a value of 0. I don’t know why the bRequest is always 1 but it may be a port number.
Switches off handshaking though an index of 0 also switches it off. Index 0×0021 looks like RTS handshaking – though I can’t test that. I’ve sent for another dongle so I can test hardware handshaking. The program I’m using doesn’t seem to set DTR handshaking so I’ll need to experiment more to see if it does that.
Handshaking is about stopping the other end transmitting. USB dongles have about 512 bytes of memory split between in and out. When tx is too fast the other end will Send Xoff, set RTS low or set DTR low. The device will then stop the USB transmission and nak the USB transfer. Note data doesn’t leave the USB tx buffer until the whole transfer has been acknowleged as being received by the device. A receiving dongle will offload packet sized chunks back to the computer, or a short packet when data arrives slowly, and if it can’t move them fast enough it sends Xoff, RTS low or DTR low until the backlog clears when it sends Xon, RTS high or DTR high. So everything is done on the device. Note the buffer that you use to receive data does not fill up gradually. For example if you start with an empty usb receive buffer. USB will request 1 buffer full of data. If the data is coming fast you only get data in the USB buffer when the whole transfer request is complete which may be when a buffer full of data is received so DeviceFS buffer thresholds don’t help. |
Dave Higton (1515) 3526 posts |
Thanks again, Colin. That works as well as expected. Currently I have a second buffer for bulk in. When there is a DeviceDataPresent UpCall for the bulk in endpoint, I copy the data from the USB bulk in buffer to the second buffer. But, if the calling app requests a lot of data and doesn’t take them fast enough, the second buffer can fill up, and bytes can be lost. How can I prevent this? What happens if I don’t remove the data from the first buffer when processing the UpCall? |
Colin (478) 2433 posts |
I only move data from the usb rx buffer if there is room in the filing system buffer – your second buffer. What I can’t move is left in the USB rx buffer. When the usb rx buffer free space is less than 1 packet usb stops requesting data so you have the situation where the usb buffer contains data and the filing system buffer is full and USB isn’t requesting any more data. As the filing system buffer empties DeviceFS issues a resume entry call which is called from the filing system’s buffer buffer emptying upcall – so you would use the buffer emptying upcall of your second buffer. When you receive this upcall you move any data you can from the usb buffer to the second buffer and use the WakeUpRX Device call with a large number – like you do already – to kick usb rx back into life. If the free space in the USB rx buffer is now >= 1 packet more data will be requested from the device. |
Ronald May (387) 407 posts |
Colin said CH340 has similar read performance problems for a different reason.An article in the March Linux Voice mag about a lua programmable arduino/nodejs WiFi module caught my eye, and looking at an ebay add found quote “NodeMCU has built-in USB-TTL serial with super reliable industrial strength CH340 for superior stability on all supported platforms.” It is very cheap, dont know if it could provide internet or not. Obviously it would need to be able to connect to a hot spot, I think there is a script for getting an ip address as an example there. |
john Smith (3056) 2 posts |
I am having irql_not_less_or_equal problem in my Pc. |