2017-10-12 23:06:59 -04:00
|
|
|
/* USB EHCI Host for Teensy 3.6
|
|
|
|
* Copyright 2017 Paul Stoffregen (paul@pjrc.com)
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
*
|
|
|
|
* Note: special thanks to the Linux kernel for the CH341's method of operation, particularly how the baud rate is encoded.
|
2017-10-12 23:06:59 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include "USBHost_t36.h" // Read this header first for key info
|
|
|
|
|
2017-10-15 16:11:46 -04:00
|
|
|
#define print USBHost::print_
|
|
|
|
#define println USBHost::println_
|
2017-10-15 07:28:07 -04:00
|
|
|
|
2017-11-10 19:37:12 -05:00
|
|
|
//#define ENABLE_DEBUG_PINS
|
|
|
|
|
|
|
|
#ifdef ENABLE_DEBUG_PINS
|
|
|
|
#define debugDigitalToggle(pin) {digitalWriteFast(pin, !digitalReadFast(pin));}
|
|
|
|
#define debugDigitalWrite(pin, state) {digitalWriteFast(pin, state);}
|
|
|
|
#else
|
|
|
|
#define debugDigitalToggle(pin) {;}
|
|
|
|
#define debugDigitalWrite(pin, state) {;}
|
|
|
|
#endif
|
|
|
|
|
2017-10-27 12:35:46 -04:00
|
|
|
/************************************************************/
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
// Define mapping VID/PID - to Serial Device type.
|
2017-10-27 12:35:46 -04:00
|
|
|
/************************************************************/
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
USBSerial::product_vendor_mapping_t USBSerial::pid_vid_mapping[] = {
|
|
|
|
// FTDI mappings.
|
|
|
|
{0x0403, 0x6001, USBSerial::FTDI},
|
|
|
|
|
|
|
|
// PL2303
|
|
|
|
{0x67B,0x2303, USBSerial::PL2303},
|
|
|
|
|
|
|
|
// CH341
|
|
|
|
{0x4348, 0x5523, USBSerial::CH341 },
|
|
|
|
{0x1a86, 0x7523, USBSerial::CH341 },
|
2017-11-05 19:25:59 -05:00
|
|
|
{0x1a86, 0x5523, USBSerial::CH341 },
|
|
|
|
|
|
|
|
// Silex CP210...
|
|
|
|
{0x10c4, 0xea60, USBSerial::CP210X }
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
};
|
|
|
|
|
2017-10-27 12:35:46 -04:00
|
|
|
|
2017-10-15 07:28:07 -04:00
|
|
|
/************************************************************/
|
|
|
|
// Initialization and claiming of devices & interfaces
|
|
|
|
/************************************************************/
|
|
|
|
|
2017-10-12 23:06:59 -04:00
|
|
|
void USBSerial::init()
|
|
|
|
{
|
|
|
|
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
|
|
|
|
contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t));
|
2017-10-19 17:57:52 -04:00
|
|
|
contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t));
|
2017-10-12 23:06:59 -04:00
|
|
|
driver_ready_for_device(this);
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
format_ = USBHOST_SERIAL_8N1;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
|
|
|
|
{
|
|
|
|
// only claim at interface level
|
|
|
|
println("USBSerial claim this=", (uint32_t)this, HEX);
|
|
|
|
print("vid=", dev->idVendor, HEX);
|
2017-10-27 12:35:46 -04:00
|
|
|
print(", pid=", dev->idProduct, HEX);
|
|
|
|
print(", bDeviceClass = ", dev->bDeviceClass);
|
|
|
|
print(", bDeviceSubClass = ", dev->bDeviceSubClass);
|
|
|
|
println(", bDeviceProtocol = ", dev->bDeviceProtocol);
|
|
|
|
print_hexbytes(descriptors, len);
|
2017-10-12 23:06:59 -04:00
|
|
|
if (type == 0) {
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
//---------------------------------------------------------------------
|
|
|
|
// CDCACM
|
|
|
|
if ((dev->bDeviceClass == 2) && (dev->bDeviceSubClass == 0)) {
|
2017-10-27 12:35:46 -04:00
|
|
|
// It is a communication device see if we can extract the data...
|
|
|
|
// Try some ttyACM types?
|
|
|
|
// This code may be similar to MIDI code.
|
|
|
|
// But first pass see if we can simply look at the interface...
|
|
|
|
// Lets walk through end points and see if we
|
|
|
|
// can find an RX and TX bulk transfer end point.
|
|
|
|
// 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 *4 5 6 7 *8 9 20 1 2 *3 4 5 6 7 8 9*30 1 2 3 4 5 6 7 8 *9 40 1 2 3 4 5 *6 7 8 9 50 1 2
|
|
|
|
// USB2AX
|
|
|
|
//09 04 00 00 01 02 02 01 00 05 24 00 10 01 04 24 02 06 05 24 06 00 01 07 05 82 03 08 00 FF 09 04 01 00 02 0A 00 00 00 07 05 04 02 10 00 01 07 05 83 02 10 00 01
|
|
|
|
//09 04 01 00 02 0A 00 00 00 07 05 04 02 10 00 01 07 05 83 02 10 00 01
|
|
|
|
// Teensy 3.6
|
|
|
|
//09 04 00 00 01 02 02 01 00 05 24 00 10 01 05 24 01 01 01 04 24 02 06 05 24 06 00 01 07 05 82 03 10 00 40 09 04 01 00 02 0A 00 00 00 07 05 03 02 40 00 00 07 05 84 02 40 00 00
|
|
|
|
//09 04 01 00 02 0A 00 00 00 07 05 03 02 40 00 00 07 05 84 02 40 00 00
|
|
|
|
const uint8_t *p = descriptors;
|
|
|
|
const uint8_t *end = p + len;
|
|
|
|
|
|
|
|
if (p[0] != 9 || p[1] != 4) return false; // interface descriptor
|
|
|
|
//println(" bInterfaceClass=", p[5]);
|
|
|
|
//println(" bInterfaceSubClass=", p[6]);
|
|
|
|
if (p[5] != 2) return false; // bInterfaceClass: 2 Communications
|
|
|
|
if (p[6] != 2) return false; // bInterfaceSubClass: 2 serial
|
|
|
|
p += 9;
|
|
|
|
println(" Interface is Serial");
|
|
|
|
uint8_t rx_ep = 0;
|
|
|
|
uint8_t tx_ep = 0;
|
|
|
|
uint16_t rx_size = 0;
|
|
|
|
uint16_t tx_size = 0;
|
|
|
|
interface = 0; // clear out any interface numbers passed in.
|
|
|
|
|
|
|
|
while (p < end) {
|
|
|
|
len = *p;
|
|
|
|
if (len < 4) return false;
|
|
|
|
if (p + len > end) return false; // reject if beyond end of data
|
|
|
|
uint32_t type = p[1];
|
|
|
|
//println("type: ", type);
|
|
|
|
// Unlike Audio, we need to look at Interface as our endpoints are after them...
|
|
|
|
if (type == 4 ) { // Interface - lets remember it's number...
|
|
|
|
interface = p[2];
|
|
|
|
println(" Interface: ", interface);
|
|
|
|
}
|
|
|
|
else if (type == 0x24) { // 0x24 = CS_INTERFACE,
|
|
|
|
uint32_t subtype = p[2];
|
|
|
|
print(" CS_INTERFACE - subtype: ", subtype);
|
|
|
|
if (len >= 4) print(" ", p[3], HEX);
|
|
|
|
if (len >= 5) print(" ", p[4], HEX);
|
|
|
|
if (len >= 6) print(" ", p[5], HEX);
|
|
|
|
switch (subtype) {
|
|
|
|
case 0: println(" - Header Functional Descriptor"); break;
|
|
|
|
case 1: println(" - Call Management Functional"); break;
|
|
|
|
case 2: println(" - Abstract Control Management"); break;
|
|
|
|
case 4: println(" - Telephone Ringer"); break;
|
|
|
|
case 6: println(" - union Functional"); break;
|
|
|
|
default: println(" - ??? other"); break;
|
|
|
|
}
|
|
|
|
// First pass ignore...
|
|
|
|
} else if (type == 5) {
|
|
|
|
// endpoint descriptor
|
|
|
|
if (p[0] < 7) return false; // at least 7 bytes
|
|
|
|
if (p[3] == 2) { // First try ignore the first one which is interrupt...
|
|
|
|
println(" Endpoint: ", p[2], HEX);
|
|
|
|
switch (p[2] & 0xF0) {
|
|
|
|
case 0x80:
|
|
|
|
// IN endpoint
|
|
|
|
if (rx_ep == 0) {
|
|
|
|
rx_ep = p[2] & 0x0F;
|
|
|
|
rx_size = p[4] | (p[5] << 8);
|
|
|
|
println(" rx_size = ", rx_size);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x00:
|
|
|
|
// OUT endpoint
|
|
|
|
if (tx_ep == 0) {
|
|
|
|
tx_ep = p[2];
|
|
|
|
tx_size = p[4] | (p[5] << 8);
|
|
|
|
println(" tx_size = ", tx_size);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
println(" invalid end point: ", p[2]);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
println(" Unknown type: ", type);
|
|
|
|
return false; // unknown
|
|
|
|
}
|
|
|
|
p += len;
|
|
|
|
}
|
|
|
|
print(" exited loop rx:", rx_ep);
|
|
|
|
println(", tx:", tx_ep);
|
|
|
|
if (!rx_ep || !tx_ep) return false; // did not get our two end points
|
|
|
|
if (!init_buffers(rx_size, tx_size)) return false;
|
2017-11-10 19:37:12 -05:00
|
|
|
println(" rx buffer size:", rxsize);
|
|
|
|
println(" tx buffer size:", txsize);
|
2017-10-27 12:35:46 -04:00
|
|
|
rxpipe = new_Pipe(dev, 2, rx_ep & 15, 1, rx_size);
|
|
|
|
if (!rxpipe) return false;
|
|
|
|
txpipe = new_Pipe(dev, 2, tx_ep, 0, tx_size);
|
|
|
|
if (!txpipe) {
|
|
|
|
// TODO: free rxpipe
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sertype = CDCACM;
|
|
|
|
rxpipe->callback_function = rx_callback;
|
|
|
|
queue_Data_Transfer(rxpipe, rx1, (rx_size < 64)? rx_size : 64, this);
|
|
|
|
rxstate = 1;
|
|
|
|
if (rx_size > 128) {
|
|
|
|
queue_Data_Transfer(rxpipe, rx2, rx_size, this);
|
|
|
|
rxstate = 3;
|
|
|
|
}
|
|
|
|
txstate = 0;
|
|
|
|
txpipe->callback_function = tx_callback;
|
|
|
|
baudrate = 115200;
|
|
|
|
// Wish I could just call Control to do the output... Maybe can defer until the user calls begin()
|
|
|
|
// control requires that device is setup which is not until this call completes...
|
|
|
|
println("Control - CDCACM DTR...");
|
|
|
|
// Need to setup the data the line coding data
|
|
|
|
mk_setup(setup, 0x21, 0x22, 3, 0, 0);
|
|
|
|
queue_Control_Transfer(dev, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
pending_control = 0x0; // Maybe don't need to do...
|
|
|
|
return true;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
2017-10-31 18:11:52 -04:00
|
|
|
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
// See if the vendor_id:product_id is in our list of products.
|
|
|
|
sertype = UNKNOWN;
|
|
|
|
for (uint8_t i = 0; i < (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0])); i++) {
|
|
|
|
if ((dev->idVendor == pid_vid_mapping[i].idVendor) && (dev->idProduct == pid_vid_mapping[i].idProduct)) {
|
|
|
|
sertype = pid_vid_mapping[i].sertype;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-11-10 19:37:12 -05:00
|
|
|
if (sertype == UNKNOWN) return false; // not one of ours
|
|
|
|
|
|
|
|
// Lets try to locate the end points. Code is common across these devices
|
|
|
|
println("len = ", len);
|
|
|
|
uint8_t count_end_points = descriptors[4];
|
|
|
|
if (count_end_points < 2) return false; // not enough end points
|
|
|
|
if (len < 23) return false;
|
|
|
|
if (descriptors[0] != 9) return false; // length 9
|
|
|
|
|
|
|
|
// Lets walk through end points and see if we
|
|
|
|
// can find an RX and TX bulk transfer end point.
|
|
|
|
//Example vid=67B, pid=2303
|
|
|
|
// 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9
|
|
|
|
//09 04 00 00 03 FF 00 00 00 07 05 81 03 0A 00 01 07 05 02 02 40 00 00 07 05 83 02 40 00 00
|
|
|
|
uint32_t rxep = 0;
|
|
|
|
uint32_t txep = 0;
|
|
|
|
uint16_t rx_size = 0;
|
|
|
|
uint16_t tx_size = 0;
|
|
|
|
uint32_t descriptor_index = 9;
|
|
|
|
while (count_end_points-- && ((rxep == 0) || txep == 0)) {
|
|
|
|
if (descriptors[descriptor_index] != 7) return false; // length 7
|
|
|
|
if (descriptors[descriptor_index+1] != 5) return false; // ep desc
|
|
|
|
if ((descriptors[descriptor_index+3] == 2)
|
|
|
|
&& (descriptors[descriptor_index+4] <= 64)
|
|
|
|
&& (descriptors[descriptor_index+5] == 0)) {
|
|
|
|
// have a bulk EP size
|
|
|
|
if (descriptors[descriptor_index+2] & 0x80 ) {
|
|
|
|
rxep = descriptors[descriptor_index+2];
|
|
|
|
rx_size = descriptors[descriptor_index+4];
|
|
|
|
} else {
|
|
|
|
txep = descriptors[descriptor_index+2];
|
|
|
|
tx_size = descriptors[descriptor_index+4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
descriptor_index += 7; // setup to look at next one...
|
|
|
|
}
|
|
|
|
// Try to verify the end points.
|
|
|
|
if (!check_rxtx_ep(rxep, txep)) return false;
|
|
|
|
print("USBSerial, rxep=", rxep & 15);
|
|
|
|
print("(", rx_size);
|
|
|
|
print("), txep=", txep);
|
|
|
|
print("(", tx_size);
|
|
|
|
println(")");
|
|
|
|
|
|
|
|
if (!init_buffers(rx_size, tx_size)) return false;
|
|
|
|
println(" rx buffer size:", rxsize);
|
|
|
|
println(" tx buffer size:", txsize);
|
|
|
|
|
|
|
|
rxpipe = new_Pipe(dev, 2, rxep & 15, 1, rx_size);
|
|
|
|
if (!rxpipe) return false;
|
|
|
|
txpipe = new_Pipe(dev, 2, txep, 0, tx_size);
|
|
|
|
if (!txpipe) {
|
|
|
|
//free_Pipe(rxpipe);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
rxpipe->callback_function = rx_callback;
|
|
|
|
queue_Data_Transfer(rxpipe, rx1, rx_size, this);
|
|
|
|
rxstate = 1;
|
|
|
|
txstate = 0;
|
|
|
|
txpipe->callback_function = tx_callback;
|
|
|
|
baudrate = 115200;
|
|
|
|
|
|
|
|
// Now do specific setup per type
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
switch (sertype) {
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
// FTDI
|
|
|
|
case FTDI:
|
|
|
|
{
|
|
|
|
pending_control = 0x0F;
|
|
|
|
mk_setup(setup, 0x40, 0, 0, 0, 0); // reset port
|
|
|
|
queue_Control_Transfer(dev, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Prolific
|
2017-10-31 18:11:52 -04:00
|
|
|
// TODO: Note: there are probably more vendor/product pairs.. Maybe should create table of them
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
case PL2303:
|
|
|
|
{
|
2017-11-05 19:25:59 -05:00
|
|
|
// First attempt keep it simple...
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
println("PL2303: readRegister(0x04)");
|
|
|
|
// Need to setup the data the line coding data
|
|
|
|
mk_setup(setup, 0xC0, 0x1, 0x8484, 0, 1);
|
|
|
|
queue_Control_Transfer(dev, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 1; // We are at step one of setup...
|
|
|
|
pending_control = 0x3f;
|
|
|
|
return true;
|
2017-10-27 12:35:46 -04:00
|
|
|
}
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// CH341
|
|
|
|
case CH341:
|
|
|
|
{
|
|
|
|
println("CH341: 0xC0, 0x5f, 0, 0, 8");
|
|
|
|
// Need to setup the data the line coding data
|
|
|
|
mk_setup(setup, 0xC0, 0x5f, 0, 0, sizeof(setupdata));
|
|
|
|
queue_Control_Transfer(dev, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 1; // We are at step one of setup...
|
|
|
|
pending_control = 0x7f;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
2017-11-05 19:25:59 -05:00
|
|
|
// CP210X
|
|
|
|
case CP210X:
|
|
|
|
{
|
|
|
|
println("CP210X: 0x41, 0x11, 0, 0, 0 - reset port");
|
|
|
|
// Need to setup the data the line coding data
|
|
|
|
mk_setup(setup, 0x41, 0x11, 0, 0, 0);
|
|
|
|
queue_Control_Transfer(dev, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 1; // We are at step one of setup...
|
|
|
|
pending_control = 0xf;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
// PID:VID - not in our product list.
|
|
|
|
default:
|
|
|
|
return false;
|
2017-10-27 12:35:46 -04:00
|
|
|
}
|
|
|
|
} else if (type != 1) return false;
|
2017-10-31 18:11:52 -04:00
|
|
|
// TTYACM: <Composit device>
|
|
|
|
//
|
|
|
|
// We first tried to claim a simple ttyACM device like a teensy who is configured
|
|
|
|
// only as Serial at the device level like what was done for midi
|
|
|
|
//
|
|
|
|
// However some devices are a compisit of multiple Interfaces, so see if this Interface
|
|
|
|
// is of the CDC Interface class and 0 for SubClass and protocol
|
|
|
|
// Todo: some of this can maybe be combined with the Whole device code above.
|
|
|
|
|
2017-10-27 12:35:46 -04:00
|
|
|
if (descriptors[0] != 9 || descriptors[1] != 4) return false; // interface descriptor
|
|
|
|
if (descriptors[4] < 2) return false; // less than 2 end points
|
|
|
|
if (descriptors[5] != 0xA) return false; // bInterfaceClass, 0xa = CDC data
|
|
|
|
if (descriptors[6] != 0) return false; // bInterfaceSubClass
|
2017-10-31 18:11:52 -04:00
|
|
|
if (descriptors[7] != 0) return false; // bInterfaceProtocol
|
2017-10-27 12:35:46 -04:00
|
|
|
|
|
|
|
if (descriptors[9] != 7) return false; // length 7
|
|
|
|
if (descriptors[10] != 5) return false; // ep desc
|
|
|
|
uint32_t txep = descriptors[11];
|
|
|
|
uint32_t txsize = descriptors[13];
|
|
|
|
if (descriptors[12] != 2) return false; // bulk type
|
|
|
|
if (descriptors[13] > 64) return false; // size 64 Max
|
|
|
|
if (descriptors[14] != 0) return false;
|
|
|
|
|
|
|
|
if (descriptors[16] != 7) return false; // length 7
|
|
|
|
if (descriptors[17] != 5) return false; // ep desc
|
|
|
|
uint32_t rxep = descriptors[18];
|
|
|
|
uint32_t rxsize = descriptors[20];
|
|
|
|
if (descriptors[19] != 2) return false; // bulk type
|
|
|
|
if (descriptors[20] > 64) return false; // size 64 Max
|
|
|
|
if (descriptors[21] != 0) return false;
|
|
|
|
if (!check_rxtx_ep(rxep, txep)) return false;
|
|
|
|
interface = descriptors[2];
|
|
|
|
|
|
|
|
print("CDC, rxep=", rxep & 15);
|
|
|
|
println(", txep=", txep);
|
|
|
|
if (!init_buffers(rxsize, txsize)) return false;
|
|
|
|
rxpipe = new_Pipe(dev, 2, rxep & 15, 1, rxsize);
|
|
|
|
if (!rxpipe) return false;
|
|
|
|
txpipe = new_Pipe(dev, 2, txep, 0, txsize);
|
|
|
|
if (!txpipe) {
|
|
|
|
// TODO: free rxpipe
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sertype = CDCACM;
|
|
|
|
rxpipe->callback_function = rx_callback;
|
|
|
|
queue_Data_Transfer(rxpipe, rx1, 64, this);
|
|
|
|
rxstate = 1;
|
|
|
|
if (rxsize > 128) {
|
|
|
|
queue_Data_Transfer(rxpipe, rx2, 64, this);
|
|
|
|
rxstate = 3;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
2017-10-27 12:35:46 -04:00
|
|
|
txstate = 0;
|
|
|
|
txpipe->callback_function = tx_callback;
|
|
|
|
|
|
|
|
// See if we can do just the inteface...
|
|
|
|
baudrate = 115200;
|
|
|
|
println("Control - CDCACM LINE_CODING");
|
|
|
|
setupdata[0] = 0; // Setup baud rate 115200 - 0x1C200
|
|
|
|
setupdata[1] = 0xc2;
|
|
|
|
setupdata[2] = 0x1;
|
|
|
|
setupdata[3] = 0;
|
|
|
|
setupdata[4] = 0; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
|
|
|
|
setupdata[5] = 0; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
|
|
|
|
setupdata[6] = 8; // Data bits (5, 6, 7, 8 or 16)
|
|
|
|
mk_setup(setup, 0x21, 0x20, 0, 0, 7);
|
|
|
|
queue_Control_Transfer(dev, &setup, setupdata, this);
|
|
|
|
pending_control = 0x04; // Maybe don't need to do...
|
|
|
|
control_queued = true;
|
|
|
|
return true;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// check if two legal endpoints, 1 receive & 1 transmit
|
|
|
|
bool USBSerial::check_rxtx_ep(uint32_t &rxep, uint32_t &txep)
|
|
|
|
{
|
|
|
|
if ((rxep & 0x0F) == 0) return false;
|
|
|
|
if ((txep & 0x0F) == 0) return false;
|
|
|
|
uint32_t rxdir = rxep & 0xF0;
|
|
|
|
uint32_t txdir = txep & 0xF0;
|
|
|
|
if (rxdir == 0x80 && txdir == 0x00) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (rxdir == 0x00 && txdir == 0x80) {
|
|
|
|
std::swap(rxep, txep);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// initialize buffer sizes and pointers
|
|
|
|
bool USBSerial::init_buffers(uint32_t rsize, uint32_t tsize)
|
|
|
|
{
|
2017-10-27 12:35:46 -04:00
|
|
|
// buffer must be able to hold 2 of each packet, plus buffer
|
|
|
|
// space to hold RX and TX data.
|
2017-10-12 23:06:59 -04:00
|
|
|
if (sizeof(bigbuffer) < (rsize + tsize) * 3 + 2) return false;
|
|
|
|
rx1 = (uint8_t *)bigbuffer;
|
|
|
|
rx2 = rx1 + rsize;
|
|
|
|
tx1 = rx2 + rsize;
|
|
|
|
tx2 = tx1 + tsize;
|
|
|
|
rxbuf = tx2 + tsize;
|
|
|
|
// FIXME: this assume 50-50 split - not true when rsize != tsize
|
|
|
|
rxsize = (sizeof(bigbuffer) - (rsize + tsize) * 2) / 2;
|
|
|
|
txsize = rxsize;
|
|
|
|
txbuf = rxbuf + rxsize;
|
|
|
|
rxhead = 0;
|
|
|
|
rxtail = 0;
|
|
|
|
txhead = 0;
|
|
|
|
txtail = 0;
|
|
|
|
rxstate = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-13 08:56:18 -04:00
|
|
|
void USBSerial::disconnect()
|
|
|
|
{
|
|
|
|
}
|
2017-10-12 23:06:59 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-10-13 08:56:18 -04:00
|
|
|
void USBSerial::control(const Transfer_t *transfer)
|
|
|
|
{
|
2017-10-27 12:35:46 -04:00
|
|
|
println("control callback (serial) ", pending_control, HEX);
|
2017-10-14 08:12:52 -04:00
|
|
|
control_queued = false;
|
2017-10-13 08:56:18 -04:00
|
|
|
|
2017-10-28 15:57:02 -04:00
|
|
|
// We will split this up by Serial type, maybe different functions?
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// First FTDI
|
|
|
|
if (sertype == FTDI) {
|
|
|
|
if (pending_control & 1) {
|
|
|
|
pending_control &= ~1;
|
|
|
|
// set data format
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
uint16_t ftdi_format = format_ & 0xf; // This should give us the number of bits.
|
|
|
|
|
|
|
|
// now lets extract the parity from our encoding
|
|
|
|
ftdi_format |= (format_ & 0xe0) << 3; // they encode bits 9-11
|
|
|
|
|
|
|
|
// See if two stop bits
|
|
|
|
if (format_ & 0x100) ftdi_format |= (0x2 << 11);
|
|
|
|
|
|
|
|
mk_setup(setup, 0x40, 4, ftdi_format, 0, 0); // data format 8N1
|
2017-10-28 15:57:02 -04:00
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// set baud rate
|
|
|
|
if (pending_control & 2) {
|
|
|
|
pending_control &= ~2;
|
2017-10-27 12:35:46 -04:00
|
|
|
uint32_t baudval = 3000000 / baudrate;
|
|
|
|
mk_setup(setup, 0x40, 3, baudval, 0, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
2017-10-28 15:57:02 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// configure flow control
|
|
|
|
if (pending_control & 4) {
|
|
|
|
pending_control &= ~4;
|
|
|
|
mk_setup(setup, 0x40, 2, 0, 1, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// set DTR
|
|
|
|
if (pending_control & 8) {
|
|
|
|
pending_control &= ~8;
|
|
|
|
mk_setup(setup, 0x40, 1, 0x0101, 0, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
// clear DTR
|
|
|
|
if (pending_control & 0x80) {
|
|
|
|
pending_control &= ~0x80;
|
|
|
|
println("FTDI clear DTR");
|
|
|
|
mk_setup(setup, 0x40, 1, 0x0100, 0, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
2017-10-27 12:35:46 -04:00
|
|
|
|
2017-10-28 15:57:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Now CDCACM
|
|
|
|
if (sertype == CDCACM) {
|
|
|
|
if (pending_control & 2) {
|
|
|
|
pending_control &= ~2;
|
2017-10-27 12:35:46 -04:00
|
|
|
// Should probably use data structure, but that may depend on byte ordering...
|
|
|
|
setupdata[0] = (baudrate) & 0xff; // Setup baud rate 115200 - 0x1C200
|
|
|
|
setupdata[1] = (baudrate >> 8) & 0xff;
|
|
|
|
setupdata[2] = (baudrate >> 16) & 0xff;
|
|
|
|
setupdata[3] = (baudrate >> 24) & 0xff;
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
setupdata[4] = (format_ & 0x100)? 2 : 0; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
|
|
|
|
setupdata[5] = (format_ & 0xe0) >> 5; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
|
|
|
|
setupdata[6] = format_ & 0x1f; // Data bits (5, 6, 7, 8 or 16)
|
2017-10-27 12:35:46 -04:00
|
|
|
print("CDCACM setup: ");
|
|
|
|
print_hexbytes(&setupdata, 7);
|
|
|
|
mk_setup(setup, 0x21, 0x20, 0, 0, 7);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
2017-10-28 15:57:02 -04:00
|
|
|
return;
|
2017-10-27 12:35:46 -04:00
|
|
|
}
|
2017-10-28 15:57:02 -04:00
|
|
|
// configure flow control
|
|
|
|
if (pending_control & 4) {
|
|
|
|
pending_control &= ~4;
|
|
|
|
println("Control - 0x21,0x22, 0x3");
|
2017-10-27 12:35:46 -04:00
|
|
|
// Need to setup the data the line coding data
|
2017-10-28 15:57:02 -04:00
|
|
|
mk_setup(setup, 0x21, 0x22, 3, 0, 0);
|
2017-10-27 12:35:46 -04:00
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
if (pending_control & 0x80) {
|
|
|
|
pending_control &= ~0x80;
|
|
|
|
println("Control - 0x21,0x22, 0x0 - clear DTR");
|
|
|
|
// Need to setup the data the line coding data
|
|
|
|
mk_setup(setup, 0x21, 0x22, 0, 0, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
2017-10-13 08:56:18 -04:00
|
|
|
}
|
2017-10-28 15:57:02 -04:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Now PL2303 - Which appears to be a little more complicated
|
|
|
|
if (sertype == PL2303) {
|
|
|
|
if (pending_control & 1) {
|
|
|
|
// Still in larger setup state mode
|
|
|
|
switch (setup_state) {
|
|
|
|
case 1:
|
|
|
|
println("PL2303: writeRegister(0x04, 0x00)");
|
|
|
|
mk_setup(setup, 0x40, 1, 0x0404, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 2;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 2:
|
|
|
|
println("PL2303: readRegister(0x04)");
|
|
|
|
mk_setup(setup, 0xC0, 0x1, 0x8484, 0, 1);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 3;
|
|
|
|
return;
|
|
|
|
case 3:
|
|
|
|
println("PL2303: v1 = readRegister(0x03)");
|
|
|
|
mk_setup(setup, 0xC0, 0x1, 0x8383, 0, 1);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 4;
|
|
|
|
return;
|
|
|
|
case 4:
|
|
|
|
println("PL2303: readRegister(0x04)");
|
|
|
|
// Do we need this value long term or we could just leave in setup data?
|
|
|
|
pl2303_v1 = setupdata[0]; // save the first bye of version
|
|
|
|
mk_setup(setup, 0xC0, 0x1, 0x8484, 0, 1);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 5;
|
|
|
|
return;
|
|
|
|
case 5:
|
|
|
|
println("PL2303: writeRegister(0x04, 0x01)");
|
|
|
|
mk_setup(setup, 0x40, 1, 0x0404, 1, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 6;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 6:
|
|
|
|
println("PL2303: readRegister(0x04)");
|
|
|
|
mk_setup(setup, 0xC0, 0x1, 0x8484, 0, 1);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 7;
|
|
|
|
return;
|
|
|
|
case 7:
|
|
|
|
println("PL2303: v2 = readRegister(0x03)");
|
|
|
|
mk_setup(setup, 0xC0, 0x1, 0x8383, 0, 1);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 8;
|
|
|
|
return;
|
|
|
|
case 8:
|
|
|
|
pl2303_v2 = setupdata[0]; // save the first bye of version
|
|
|
|
print(" PL2303 Version ", pl2303_v1, HEX);
|
|
|
|
println(":", pl2303_v2, HEX);
|
|
|
|
println("PL2303: writeRegister(0, 1)");
|
|
|
|
mk_setup(setup, 0x40, 1, 0, 1, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 9;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 9:
|
|
|
|
println("PL2303: writeRegister(1, 0)");
|
|
|
|
mk_setup(setup, 0x40, 1, 1, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 10;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 10:
|
|
|
|
println("PL2303: writeRegister(2, 44)");
|
|
|
|
mk_setup(setup, 0x40, 1, 2, 0x44, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 11;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 11:
|
|
|
|
println("PL2303: writeRegister(8, 0)");
|
|
|
|
mk_setup(setup, 0x40, 1, 8, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 12;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 12:
|
|
|
|
println("PL2303: writeRegister(9, 0)");
|
|
|
|
mk_setup(setup, 0x40, 1, 9, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 13;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 13:
|
|
|
|
println("PL2303: Read current Baud/control");
|
|
|
|
mk_setup(setup, 0xA1, 0x21, 0, 0, 7);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pending_control &= ~1; // We are finally going to leave this list and join the rest
|
|
|
|
if (control_queued) return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set baud rate
|
|
|
|
if (pending_control & 2) {
|
|
|
|
pending_control &= ~2;
|
|
|
|
// See what the read returned earlier
|
|
|
|
print("PL2303: Returned configuration data: ");
|
|
|
|
print_hexbytes(setupdata, 7);
|
|
|
|
|
|
|
|
// Should probably use data structure, but that may depend on byte ordering...
|
|
|
|
setupdata[0] = (baudrate) & 0xff; // Setup baud rate 115200 - 0x1C200
|
|
|
|
setupdata[1] = (baudrate >> 8) & 0xff;
|
|
|
|
setupdata[2] = (baudrate >> 16) & 0xff;
|
|
|
|
setupdata[3] = (baudrate >> 24) & 0xff;
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
setupdata[4] = (format_ & 0x100)? 2 : 0; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
|
|
|
|
setupdata[5] = (format_ & 0xe0) >> 5; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
|
|
|
|
setupdata[6] = format_ & 0x1f; // Data bits (5, 6, 7, 8 or 16)
|
2017-10-28 15:57:02 -04:00
|
|
|
print("PL2303: Set baud/control: ", baudrate, HEX);
|
|
|
|
print(" = ");
|
|
|
|
print_hexbytes(&setupdata, 7);
|
|
|
|
mk_setup(setup, 0x21, 0x20, 0, 0, 7);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (pending_control & 4) {
|
|
|
|
pending_control &= ~4;
|
|
|
|
println("PL2303: writeRegister(0, 0)");
|
|
|
|
mk_setup(setup, 0x40, 1, 0, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (pending_control & 8) {
|
|
|
|
pending_control &= ~8;
|
|
|
|
println("PL2303: Read current Baud/control");
|
|
|
|
memset(setupdata, 0, sizeof(setupdata)); // clear it to see if we read it...
|
|
|
|
mk_setup(setup, 0xA1, 0x21, 0, 0, 7);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
}
|
|
|
|
if (pending_control & 0x10) {
|
|
|
|
pending_control &= ~0x10;
|
|
|
|
print("PL2303: Returned configuration data: ");
|
|
|
|
print_hexbytes(setupdata, 7);
|
|
|
|
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
// This sets the control lines (0x1=DTR, 0x2=RTS)
|
2017-10-28 15:57:02 -04:00
|
|
|
println("PL2303: 0x21, 0x22, 0x3");
|
|
|
|
mk_setup(setup, 0x21, 0x22, 3, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
if (pending_control & 0x20) {
|
|
|
|
pending_control &= ~0x20;
|
2017-10-28 15:57:02 -04:00
|
|
|
println("PL2303: 0x21, 0x22, 0x3");
|
|
|
|
mk_setup(setup, 0x21, 0x22, 3, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
}
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
if (pending_control & 0x80) {
|
|
|
|
pending_control &= ~0x80;
|
|
|
|
println("PL2303: 0x21, 0x22, 0x0"); // Clear DTR/RTS
|
|
|
|
mk_setup(setup, 0x21, 0x22, 0, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sertype == CH341) {
|
|
|
|
#if 0
|
|
|
|
print(" Transfer: ");
|
|
|
|
print_hexbytes(&transfer->setup, sizeof(setup_t));
|
|
|
|
if (transfer->length) {
|
|
|
|
print(" data: ");
|
|
|
|
print_hexbytes(transfer->buffer, transfer->length);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (pending_control & 1) {
|
|
|
|
// Still in larger setup state mode
|
|
|
|
switch (setup_state) {
|
|
|
|
case 1:
|
|
|
|
print(" Returned: ");
|
|
|
|
print_hexbytes(transfer->buffer, transfer->length);
|
|
|
|
println("CH341: 40, a1, 0, 0, 0");
|
|
|
|
mk_setup(setup, 0x40, 0xa1, 0, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 2;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 2:
|
|
|
|
ch341_setBaud(0); // send the first byte of the baud rate
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 3;
|
|
|
|
return;
|
|
|
|
case 3:
|
|
|
|
ch341_setBaud(1); // send the second byte of the baud rate
|
|
|
|
control_queued = true;
|
|
|
|
setup_state = 4;
|
|
|
|
return;
|
|
|
|
case 4:
|
|
|
|
println("CH341: c0, 95, 2518, 0, 8");
|
|
|
|
mk_setup(setup, 0xc0, 0x95, 0x2518, 0, sizeof(setup)); //
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
setup_state = 5;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 5:
|
|
|
|
print(" Returned: ");
|
|
|
|
print_hexbytes(transfer->buffer, transfer->length);
|
|
|
|
println("CH341: 40, 0x9a, 0x2518, 0x0050, 0");
|
|
|
|
mk_setup(setup, 0x40, 0x9a, 0x2518, 0x0050, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 6;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 6:
|
|
|
|
println("CH341: c0, 95, 0x706, 0, 8 - get status");
|
|
|
|
mk_setup(setup, 0xc0, 0x95, 0x706, 0, sizeof(setup)); //
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
setup_state = 7;
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
case 7:
|
|
|
|
print(" Returned: ");
|
|
|
|
print_hexbytes(transfer->buffer, transfer->length);
|
|
|
|
println("CH341: 40, 0xa1, 0x501f, 0xd90a, 0");
|
|
|
|
mk_setup(setup, 0x40, 0xa1, 0x501f, 0xd90a, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
setup_state = 8;
|
|
|
|
control_queued = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pending_control &= ~1; // We are finally going to leave this list and join the rest
|
|
|
|
if (control_queued) return;
|
|
|
|
}
|
|
|
|
// set baud rate
|
|
|
|
if (pending_control & 2) {
|
|
|
|
pending_control &= ~2;
|
|
|
|
ch341_setBaud(0); // send the first byte of the baud rate
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (pending_control & 4) {
|
|
|
|
pending_control &= ~4;
|
|
|
|
ch341_setBaud(1); // send the first byte of the baud rate
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pending_control & 8) {
|
|
|
|
pending_control &= ~8;
|
|
|
|
uint16_t ch341_format;
|
|
|
|
switch (format_) {
|
|
|
|
default:
|
|
|
|
// These values were observed when used on PC... Need to flush out others.
|
|
|
|
case USBHOST_SERIAL_8N1: ch341_format = 0xc3; break;
|
|
|
|
case USBHOST_SERIAL_7E1: ch341_format = 0xda; break;
|
|
|
|
case USBHOST_SERIAL_7O1: ch341_format = 0xca; break;
|
|
|
|
case USBHOST_SERIAL_8N2: ch341_format = 0xc7; break;
|
|
|
|
}
|
|
|
|
println("CH341: 40, 0x9a, 0x2518: ", ch341_format, HEX);
|
|
|
|
mk_setup(setup, 0x40, 0x9a, 0x2518, ch341_format, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (pending_control & 0x10) {
|
|
|
|
pending_control &= ~0x10;
|
|
|
|
// This is setting handshake need to figure out what...
|
|
|
|
// 0x20=DTR, 0x40=RTS send ~ of values.
|
|
|
|
println("CH341: 0x40, 0xa4, 0xff9f, 0, 0 - Handshake");
|
|
|
|
mk_setup(setup, 0x40, 0xa4, 0xff9f, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (pending_control & 0x20) {
|
|
|
|
pending_control &= ~0x20;
|
|
|
|
// This is setting handshake need to figure out what...
|
|
|
|
println("CH341: c0, 95, 0x706, 0, 8 - get status");
|
|
|
|
mk_setup(setup, 0xc0, 0x95, 0x706, 0, sizeof(setup)); //
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (pending_control & 0x40) {
|
|
|
|
pending_control &= ~0x40;
|
|
|
|
print(" Returned: ");
|
|
|
|
print_hexbytes(transfer->buffer, transfer->length);
|
|
|
|
println("CH341: 0x40, 0x9a, 0x2727, 0, 0");
|
|
|
|
mk_setup(setup, 0x40, 0x9a, 0x2727, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pending_control & 0x80) {
|
|
|
|
pending_control &= ~0x80;
|
|
|
|
println("CH341: 0x40, 0xa4, 0xffff, 0, 0 - Handshake");
|
|
|
|
mk_setup(setup, 0x40, 0xa4, 0xffff, 0, 0); //
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
2017-10-13 08:56:18 -04:00
|
|
|
}
|
2017-11-05 19:25:59 -05:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// First CP210X
|
|
|
|
if (sertype == CP210X) {
|
|
|
|
if (pending_control & 1) {
|
|
|
|
pending_control &= ~1;
|
|
|
|
// set data format
|
|
|
|
uint16_t cp210x_format = (format_ & 0xf) << 8; // This should give us the number of bits.
|
|
|
|
|
|
|
|
// now lets extract the parity from our encoding bits 5-7 and in theres 4-7
|
|
|
|
cp210x_format |= (format_ & 0xe0) >> 1; // they encode bits 9-11
|
|
|
|
|
|
|
|
// See if two stop bits
|
|
|
|
if (format_ & 0x100) cp210x_format |= 2;
|
|
|
|
|
|
|
|
mk_setup(setup, 0x41, 3, cp210x_format, 0, 0); // data format 8N1
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// set baud rate
|
|
|
|
if (pending_control & 2) {
|
|
|
|
pending_control &= ~2;
|
|
|
|
setupdata[0] = (baudrate) & 0xff; // Setup baud rate 115200 - 0x1C200
|
|
|
|
setupdata[1] = (baudrate >> 8) & 0xff;
|
|
|
|
setupdata[2] = (baudrate >> 16) & 0xff;
|
|
|
|
setupdata[3] = (baudrate >> 24) & 0xff;
|
|
|
|
mk_setup(setup, 0x40, 0x1e, 0, 0, 4);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// configure flow control
|
|
|
|
if (pending_control & 4) {
|
|
|
|
pending_control &= ~4;
|
|
|
|
memset(setupdata, 0, sizeof(setupdata)); // clear out the data
|
|
|
|
setupdata[0] = 1; // Set dtr active?
|
|
|
|
mk_setup(setup, 0x41, 13, 0, 0, 0x10);
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// set DTR
|
|
|
|
if (pending_control & 8) {
|
|
|
|
pending_control &= ~8;
|
|
|
|
mk_setup(setup, 0x41, 7, 0x0101, 0, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// clear DTR
|
|
|
|
if (pending_control & 0x80) {
|
|
|
|
pending_control &= ~0x80;
|
|
|
|
println("CP210x clear DTR");
|
|
|
|
mk_setup(setup, 0x40, 1, 0x0100, 0, 0);
|
|
|
|
queue_Control_Transfer(device, &setup, NULL, this);
|
|
|
|
control_queued = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-10-13 08:56:18 -04:00
|
|
|
}
|
2017-10-12 23:06:59 -04:00
|
|
|
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
#define CH341_BAUDBASE_FACTOR 1532620800
|
|
|
|
#define CH341_BAUDBASE_DIVMAX 3
|
|
|
|
void USBSerial::ch341_setBaud(uint8_t byte_index) {
|
|
|
|
if (byte_index == 0) {
|
|
|
|
uint32_t factor;
|
|
|
|
uint16_t divisor;
|
|
|
|
|
|
|
|
factor = (CH341_BAUDBASE_FACTOR / baudrate);
|
|
|
|
divisor = CH341_BAUDBASE_DIVMAX;
|
|
|
|
|
|
|
|
while ((factor > 0xfff0) && divisor) {
|
|
|
|
factor >>= 3;
|
|
|
|
divisor--;
|
|
|
|
}
|
|
|
|
|
|
|
|
factor = 0x10000 - factor;
|
|
|
|
|
|
|
|
factor = (factor & 0xff00) | divisor;
|
|
|
|
setupdata[0] = factor & 0xff; // save away the low byte for 2nd message
|
|
|
|
|
|
|
|
|
|
|
|
println("CH341: 40, 0x9a, 0x1312... (Baud word 0):", factor, HEX);
|
|
|
|
mk_setup(setup, 0x40, 0x9a, 0x1312, factor, 0); //
|
|
|
|
} else {
|
|
|
|
// Second packet use the byte we saved away during the calculation above
|
|
|
|
println("CH341: 40, 0x9a, 0x0f2c... (Baud word 1):", setupdata[0], HEX);
|
|
|
|
mk_setup(setup, 0x40, 0x9a, 0x0f2c, setupdata[0], 0); //
|
|
|
|
}
|
|
|
|
queue_Control_Transfer(device, &setup, setupdata, this);
|
|
|
|
control_queued = true;
|
|
|
|
}
|
|
|
|
|
2017-10-15 07:28:07 -04:00
|
|
|
|
|
|
|
/************************************************************/
|
|
|
|
// Interrupt-based Data Movement
|
|
|
|
/************************************************************/
|
|
|
|
|
2017-10-12 23:06:59 -04:00
|
|
|
void USBSerial::rx_callback(const Transfer_t *transfer)
|
|
|
|
{
|
|
|
|
if (!transfer->driver) return;
|
|
|
|
((USBSerial *)(transfer->driver))->rx_data(transfer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void USBSerial::tx_callback(const Transfer_t *transfer)
|
|
|
|
{
|
|
|
|
if (!transfer->driver) return;
|
|
|
|
((USBSerial *)(transfer->driver))->tx_data(transfer);
|
|
|
|
}
|
|
|
|
|
2017-10-28 15:57:02 -04:00
|
|
|
|
2017-10-12 23:06:59 -04:00
|
|
|
void USBSerial::rx_data(const Transfer_t *transfer)
|
|
|
|
{
|
|
|
|
uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
|
|
|
|
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalToggle(6);
|
2017-10-13 08:56:18 -04:00
|
|
|
// first update rxstate bitmask, since buffer is no longer queued
|
2017-10-12 23:06:59 -04:00
|
|
|
if (transfer->buffer == rx1) {
|
|
|
|
rxstate &= 0xFE;
|
|
|
|
} else if (transfer->buffer == rx2) {
|
|
|
|
rxstate &= 0xFD;
|
|
|
|
}
|
|
|
|
// get start of data and actual length
|
|
|
|
const uint8_t *p = (const uint8_t *)transfer->buffer;
|
2017-10-13 08:56:18 -04:00
|
|
|
if (sertype == FTDI) {
|
2017-10-12 23:06:59 -04:00
|
|
|
if (len >= 2) {
|
|
|
|
p += 2;
|
|
|
|
len -= 2;
|
|
|
|
} else {
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
}
|
2017-10-27 12:35:46 -04:00
|
|
|
if (len > 0) {
|
2017-11-10 19:37:12 -05:00
|
|
|
print("rx token: ", transfer->qtd.token, HEX);
|
|
|
|
print(" transfer length: ", transfer->length, DEC);
|
|
|
|
print(" len:", len, DEC);
|
|
|
|
print(" - ", *p, HEX);
|
|
|
|
println(" ", *(p+1), HEX);
|
2017-10-27 12:35:46 -04:00
|
|
|
print("rx: ");
|
|
|
|
print_hexbytes(p, len);
|
|
|
|
}
|
2017-10-13 08:56:18 -04:00
|
|
|
// Copy data from packet buffer to circular buffer.
|
|
|
|
// Assume the buffer will always have space, since we
|
|
|
|
// check before queuing the buffers
|
2017-10-12 23:06:59 -04:00
|
|
|
uint32_t head = rxhead;
|
|
|
|
uint32_t tail = rxtail;
|
2017-10-14 08:12:52 -04:00
|
|
|
if (++head >= rxsize) head = 0;
|
2017-10-13 08:56:18 -04:00
|
|
|
uint32_t avail;
|
|
|
|
if (len > 0) {
|
2017-10-14 08:12:52 -04:00
|
|
|
//print("head=", head);
|
|
|
|
//print(", tail=", tail);
|
2017-10-13 08:56:18 -04:00
|
|
|
avail = rxsize - head;
|
2017-10-14 08:12:52 -04:00
|
|
|
//print(", avail=", avail);
|
|
|
|
//println(", rxsize=", rxsize);
|
2017-10-13 08:56:18 -04:00
|
|
|
if (avail > len) avail = len;
|
|
|
|
memcpy(rxbuf + head, p, avail);
|
|
|
|
if (len <= avail) {
|
2017-10-14 08:12:52 -04:00
|
|
|
head += avail - 1;
|
2017-10-13 08:56:18 -04:00
|
|
|
if (head >= rxsize) head = 0;
|
|
|
|
} else {
|
2017-10-14 08:12:52 -04:00
|
|
|
head = len - avail - 1;
|
|
|
|
memcpy(rxbuf, p + avail, head + 1);
|
2017-10-13 08:56:18 -04:00
|
|
|
}
|
|
|
|
rxhead = head;
|
|
|
|
}
|
2017-10-15 05:39:36 -04:00
|
|
|
// TODO: can be this more efficient? We know from above which
|
|
|
|
// buffer is no longer queued, so possible skip most of this work?
|
2017-10-14 08:12:52 -04:00
|
|
|
rx_queue_packets(head, tail);
|
|
|
|
}
|
|
|
|
|
|
|
|
// re-queue packet buffer(s) if possible
|
|
|
|
void USBSerial::rx_queue_packets(uint32_t head, uint32_t tail)
|
|
|
|
{
|
|
|
|
uint32_t avail;
|
2017-10-12 23:06:59 -04:00
|
|
|
if (head >= tail) {
|
2017-10-13 08:56:18 -04:00
|
|
|
avail = rxsize - 1 - head + tail;
|
2017-10-12 23:06:59 -04:00
|
|
|
} else {
|
2017-10-13 08:56:18 -04:00
|
|
|
avail = tail - head - 1;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
uint32_t packetsize = rx2 - rx1;
|
|
|
|
if (avail >= packetsize) {
|
|
|
|
if ((rxstate & 0x01) == 0) {
|
|
|
|
queue_Data_Transfer(rxpipe, rx1, packetsize, this);
|
|
|
|
rxstate |= 0x01;
|
|
|
|
} else if ((rxstate & 0x02) == 0) {
|
|
|
|
queue_Data_Transfer(rxpipe, rx2, packetsize, this);
|
|
|
|
rxstate |= 0x02;
|
|
|
|
}
|
|
|
|
if ((rxstate & 0x03) != 0x03 && avail >= packetsize * 2) {
|
|
|
|
if ((rxstate & 0x01) == 0) {
|
|
|
|
queue_Data_Transfer(rxpipe, rx1, packetsize, this);
|
|
|
|
rxstate |= 0x01;
|
|
|
|
} else if ((rxstate & 0x02) == 0) {
|
|
|
|
queue_Data_Transfer(rxpipe, rx2, packetsize, this);
|
|
|
|
rxstate |= 0x02;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void USBSerial::tx_data(const Transfer_t *transfer)
|
|
|
|
{
|
2017-10-15 09:00:53 -04:00
|
|
|
uint32_t mask;
|
|
|
|
uint8_t *p = (uint8_t *)transfer->buffer;
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(5, HIGH);
|
2017-10-15 09:00:53 -04:00
|
|
|
if (p == tx1) {
|
2017-10-15 05:39:36 -04:00
|
|
|
println("tx1:");
|
2017-10-15 09:00:53 -04:00
|
|
|
mask = 1;
|
|
|
|
//txstate &= 0xFE;
|
|
|
|
} else if (p == tx2) {
|
2017-10-15 05:39:36 -04:00
|
|
|
println("tx2:");
|
2017-10-15 09:00:53 -04:00
|
|
|
mask = 2;
|
|
|
|
//txstate &= 0xFD;
|
|
|
|
} else {
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(5, LOW);
|
2017-10-15 09:00:53 -04:00
|
|
|
return; // should never happen
|
|
|
|
}
|
|
|
|
// check how much more data remains in the transmit buffer
|
|
|
|
uint32_t head = txhead;
|
|
|
|
uint32_t tail = txtail;
|
|
|
|
uint32_t count;
|
|
|
|
if (head >= tail) {
|
|
|
|
count = head - tail;
|
|
|
|
} else {
|
|
|
|
count = txsize + head - tail;
|
|
|
|
}
|
|
|
|
uint32_t packetsize = tx2 - tx1;
|
2017-11-10 19:37:12 -05:00
|
|
|
// Only output full packets unless the flush bit was set.
|
|
|
|
if ((count == 0) || ((count < packetsize) && ((txstate & 0x4) == 0) )) {
|
2017-10-15 09:00:53 -04:00
|
|
|
// not enough data in buffer to fill a full packet
|
2017-11-10 19:37:12 -05:00
|
|
|
txstate &= ~(mask | 4); // turn off that transfer and make sure the flush bit is not set
|
|
|
|
debugDigitalWrite(5, LOW);
|
2017-10-15 09:00:53 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// immediately transmit another full packet, if we have enough data
|
2017-11-10 19:37:12 -05:00
|
|
|
if (count >= packetsize) count = packetsize;
|
|
|
|
else txstate &= ~(mask | 4); // This packet will complete any outstanding flush
|
|
|
|
|
2017-10-15 09:00:53 -04:00
|
|
|
println("TX:moar data!!!!");
|
|
|
|
if (++tail >= txsize) tail = 0;
|
|
|
|
uint32_t n = txsize - tail;
|
2017-11-10 19:37:12 -05:00
|
|
|
if (n > count) n = count;
|
2017-10-15 09:00:53 -04:00
|
|
|
memcpy(p, txbuf + tail, n);
|
2017-11-10 19:37:12 -05:00
|
|
|
if (n >= count) {
|
2017-10-15 09:00:53 -04:00
|
|
|
tail += n - 1;
|
|
|
|
if (tail >= txsize) tail = 0;
|
|
|
|
} else {
|
2017-11-10 19:37:12 -05:00
|
|
|
uint32_t len = count - n;
|
2017-10-15 09:00:53 -04:00
|
|
|
memcpy(p + n, txbuf, len);
|
|
|
|
tail = len - 1;
|
2017-10-15 05:39:36 -04:00
|
|
|
}
|
2017-10-15 09:00:53 -04:00
|
|
|
txtail = tail;
|
2017-11-10 19:37:12 -05:00
|
|
|
queue_Data_Transfer(txpipe, p, count, this);
|
|
|
|
debugDigitalWrite(5, LOW);
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
2017-11-10 19:37:12 -05:00
|
|
|
void USBSerial::flush()
|
|
|
|
{
|
|
|
|
print("USBSerial::flush");
|
|
|
|
if (txhead == txtail) {
|
|
|
|
println(" - Empty");
|
|
|
|
return; // empty.
|
|
|
|
}
|
|
|
|
debugDigitalWrite(32, HIGH);
|
|
|
|
NVIC_DISABLE_IRQ(IRQ_USBHS);
|
|
|
|
txtimer.stop(); // Stop longer timer.
|
|
|
|
txtimer.start(100); // Start a mimimal timeout
|
|
|
|
// timer_event(nullptr); // Try calling direct - fails to work
|
|
|
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
|
|
|
while (txstate & 3) ; // wait for all of the USB packets to be sent.
|
|
|
|
println(" completed");
|
|
|
|
debugDigitalWrite(32, LOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-12 23:06:59 -04:00
|
|
|
|
2017-10-15 07:28:07 -04:00
|
|
|
void USBSerial::timer_event(USBDriverTimer *whichTimer)
|
|
|
|
{
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(7, HIGH);
|
2017-10-15 07:28:07 -04:00
|
|
|
println("txtimer");
|
|
|
|
uint32_t count;
|
|
|
|
uint32_t head = txhead;
|
|
|
|
uint32_t tail = txtail;
|
|
|
|
if (head == tail) {
|
2017-10-27 12:35:46 -04:00
|
|
|
println(" *** Empty ***");
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(7, LOW);
|
2017-10-15 07:28:07 -04:00
|
|
|
return; // nothing to transmit
|
|
|
|
} else if (head > tail) {
|
|
|
|
count = head - tail;
|
|
|
|
} else {
|
|
|
|
count = txsize + head - tail;
|
|
|
|
}
|
2017-11-10 19:37:12 -05:00
|
|
|
|
2017-10-15 07:28:07 -04:00
|
|
|
uint8_t *p;
|
|
|
|
if ((txstate & 0x01) == 0) {
|
|
|
|
p = tx1;
|
|
|
|
txstate |= 0x01;
|
|
|
|
} else if ((txstate & 0x02) == 0) {
|
|
|
|
p = tx2;
|
|
|
|
txstate |= 0x02;
|
|
|
|
} else {
|
2017-11-10 19:37:12 -05:00
|
|
|
txstate |= 4; // Tell the TX code to do flush code.
|
2017-10-27 12:35:46 -04:00
|
|
|
println(" *** No buffers ***");
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(7, LOW);
|
2017-10-15 07:28:07 -04:00
|
|
|
return; // no outgoing buffers available, try again later
|
|
|
|
}
|
2017-11-10 19:37:12 -05:00
|
|
|
|
|
|
|
uint32_t packetsize = tx2 - tx1;
|
|
|
|
|
|
|
|
// Possible for remaining ? packet size and not have both?
|
|
|
|
if (count > packetsize) {
|
|
|
|
txstate |= 4; // One of the active transfers will handle the remaining parts
|
|
|
|
count = packetsize;
|
|
|
|
}
|
|
|
|
|
2017-10-15 07:28:07 -04:00
|
|
|
if (++tail >= txsize) tail = 0;
|
|
|
|
uint32_t n = txsize - tail;
|
|
|
|
if (n > count) n = count;
|
|
|
|
memcpy(p, txbuf + tail, n);
|
|
|
|
if (n >= count) {
|
|
|
|
tail += n - 1;
|
|
|
|
if (tail >= txsize) tail = 0;
|
|
|
|
} else {
|
|
|
|
uint32_t len = count - n;
|
|
|
|
memcpy(p + n, txbuf, len);
|
|
|
|
tail = len - 1;
|
|
|
|
}
|
|
|
|
txtail = tail;
|
2017-10-27 12:35:46 -04:00
|
|
|
print(" TX data (", count);
|
|
|
|
print(") ");
|
|
|
|
print_hexbytes(p, count);
|
2017-10-15 07:28:07 -04:00
|
|
|
queue_Data_Transfer(txpipe, p, count, this);
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(7, LOW);
|
2017-10-15 07:28:07 -04:00
|
|
|
}
|
2017-10-12 23:06:59 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-10-15 07:28:07 -04:00
|
|
|
/************************************************************/
|
|
|
|
// User Functions - must disable USBHQ IRQ for EHCI access
|
|
|
|
/************************************************************/
|
2017-10-12 23:06:59 -04:00
|
|
|
|
|
|
|
void USBSerial::begin(uint32_t baud, uint32_t format)
|
|
|
|
{
|
2017-10-14 08:12:52 -04:00
|
|
|
NVIC_DISABLE_IRQ(IRQ_USBHS);
|
|
|
|
baudrate = baud;
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
bool format_changed = format != format_;
|
|
|
|
format_ = format;
|
|
|
|
switch (sertype) {
|
|
|
|
default:
|
|
|
|
case CDCACM: pending_control |= 0x6; break;
|
|
|
|
case FTDI: pending_control |= (format_changed? 0xf : 0xe); break; // Set BAUD, FLOW, DTR
|
|
|
|
case PL2303: pending_control |= 0x1e; break; // set more stuff...
|
|
|
|
case CH341: pending_control |= 0x1e; break;
|
2017-11-05 19:25:59 -05:00
|
|
|
case CP210X: pending_control |= 0xf; break;
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
}
|
2017-10-14 08:12:52 -04:00
|
|
|
if (!control_queued) control(NULL);
|
|
|
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
// Wait until all packets have been queued before we return to caller.
|
|
|
|
while (pending_control) {
|
|
|
|
yield(); // not sure if we want to yield or what?
|
|
|
|
}
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void USBSerial::end(void)
|
|
|
|
{
|
This commit has a few different parts. It is still a WIP
This commit adds support for at least some of the Serial boards with the
CH341 chipset, tested using a board from sparkfun as well as one from
Amazon.com
The code was rearranged some of the Claim code and added a VID:DID to Serial Type table that I use to map, such that I know some of these devices have multiple valid setups.
Support Begin/End/Begin - Change baud
Added code to support switching baud rates, or more particular be able to call end() and then call begin(...) with same or different baud rate.
Hopefully some support for also releasing DTR when the end is called.
WIP - Start support for the begin(baud, format)
Adding some support to the code to handle some of the different possible format capabilities.
In particualar trying to handle the parity, number of bits and number of stop bits.
hacked up test app, such that if you type in command line like:
"#9600, 7e1"
It will extract the 9600 as the new baud and try to use format 7e1. I only hard coded a few of these in the test app (8n1, 7e1, 7e2, 8n2)...
Again work in progress. Took me awhile tofigure out how to do this for ch341 boards as I did not see any documents or code that handled this. So had to deduce it from differences in USB packets.
2017-11-01 19:41:54 -04:00
|
|
|
NVIC_DISABLE_IRQ(IRQ_USBHS);
|
|
|
|
switch (sertype) {
|
|
|
|
default:
|
|
|
|
case CDCACM: pending_control |= 0x80; break;
|
|
|
|
case FTDI: pending_control |= 0x80; break; // clear DTR
|
|
|
|
case PL2303: pending_control |= 0x80; break;
|
|
|
|
case CH341: pending_control |= 0x80; break;
|
|
|
|
}
|
|
|
|
if (!control_queued) control(NULL);
|
|
|
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
|
|
|
|
|
|
|
// Wait until all packets have been queued before we return to caller.
|
|
|
|
while (pending_control) {
|
|
|
|
yield(); // not sure if we want to yield or what?
|
|
|
|
}
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int USBSerial::available(void)
|
|
|
|
{
|
2017-10-13 08:56:18 -04:00
|
|
|
if (!device) return 0;
|
|
|
|
uint32_t head = rxhead;
|
|
|
|
uint32_t tail = rxtail;
|
|
|
|
if (head >= tail) return head - tail;
|
2017-10-14 08:12:52 -04:00
|
|
|
return rxsize + head - tail;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int USBSerial::peek(void)
|
|
|
|
{
|
2017-10-13 08:56:18 -04:00
|
|
|
if (!device) return -1;
|
|
|
|
uint32_t head = rxhead;
|
|
|
|
uint32_t tail = rxtail;
|
|
|
|
if (head == tail) return -1;
|
|
|
|
if (++tail >= rxsize) tail = 0;
|
|
|
|
return rxbuf[tail];
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int USBSerial::read(void)
|
|
|
|
{
|
2017-10-13 08:56:18 -04:00
|
|
|
if (!device) return -1;
|
|
|
|
uint32_t head = rxhead;
|
|
|
|
uint32_t tail = rxtail;
|
|
|
|
if (head == tail) return -1;
|
|
|
|
if (++tail >= rxsize) tail = 0;
|
|
|
|
int c = rxbuf[tail];
|
|
|
|
rxtail = tail;
|
2017-10-14 08:12:52 -04:00
|
|
|
if ((rxstate & 0x03) != 0x03) {
|
|
|
|
NVIC_DISABLE_IRQ(IRQ_USBHS);
|
|
|
|
rx_queue_packets(head, tail);
|
|
|
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
|
|
|
}
|
2017-10-13 08:56:18 -04:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int USBSerial::availableForWrite()
|
|
|
|
{
|
|
|
|
if (!device) return 0;
|
|
|
|
uint32_t head = txhead;
|
|
|
|
uint32_t tail = txtail;
|
|
|
|
if (head >= tail) return txsize - 1 - head + tail;
|
|
|
|
return tail - head - 1;
|
2017-10-12 23:06:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t USBSerial::write(uint8_t c)
|
|
|
|
{
|
2017-10-13 08:56:18 -04:00
|
|
|
if (!device) return 0;
|
|
|
|
uint32_t head = txhead;
|
|
|
|
if (++head >= txsize) head = 0;
|
|
|
|
while (txtail == head) {
|
|
|
|
// wait...
|
|
|
|
}
|
|
|
|
txbuf[head] = c;
|
|
|
|
txhead = head;
|
2017-10-15 05:39:36 -04:00
|
|
|
//print("head=", head);
|
|
|
|
//println(", tail=", txtail);
|
|
|
|
|
|
|
|
// if full packet in buffer and tx packet ready, queue it
|
|
|
|
NVIC_DISABLE_IRQ(IRQ_USBHS);
|
|
|
|
uint32_t tail = txtail;
|
|
|
|
if ((txstate & 0x03) != 0x03) {
|
|
|
|
// at least one packet buffer is ready to transmit
|
|
|
|
uint32_t count;
|
|
|
|
if (head >= tail) {
|
|
|
|
count = head - tail;
|
|
|
|
} else {
|
|
|
|
count = txsize + head - tail;
|
|
|
|
}
|
|
|
|
uint32_t packetsize = tx2 - tx1;
|
|
|
|
if (count >= packetsize) {
|
|
|
|
//println("txsize=", txsize);
|
|
|
|
uint8_t *p;
|
|
|
|
if ((txstate & 0x01) == 0) {
|
|
|
|
p = tx1;
|
|
|
|
txstate |= 0x01;
|
|
|
|
} else /* if ((txstate & 0x02) == 0) */ {
|
|
|
|
p = tx2;
|
|
|
|
txstate |= 0x02;
|
|
|
|
}
|
|
|
|
// copy data to packet buffer
|
|
|
|
if (++tail >= txsize) tail = 0;
|
|
|
|
uint32_t n = txsize - tail;
|
|
|
|
if (n > packetsize) n = packetsize;
|
|
|
|
//print("memcpy, offset=", tail);
|
|
|
|
//println(", len=", n);
|
|
|
|
memcpy(p, txbuf + tail, n);
|
|
|
|
if (n >= packetsize) {
|
|
|
|
tail += n - 1;
|
|
|
|
if (tail >= txsize) tail = 0;
|
|
|
|
} else {
|
|
|
|
//n = txsize - n;
|
|
|
|
uint32_t len = packetsize - n;
|
|
|
|
//println("memcpy, offset=0, len=", len);
|
|
|
|
memcpy(p + n, txbuf, len);
|
|
|
|
tail = len - 1;
|
|
|
|
}
|
|
|
|
txtail = tail;
|
|
|
|
//println("queue tx packet, newtail=", tail);
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(7, HIGH);
|
2017-10-15 05:39:36 -04:00
|
|
|
queue_Data_Transfer(txpipe, p, packetsize, this);
|
2017-11-10 19:37:12 -05:00
|
|
|
debugDigitalWrite(7, LOW);
|
2017-10-15 05:39:36 -04:00
|
|
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2017-10-15 07:28:07 -04:00
|
|
|
// otherwise, set a latency timer to later transmit partial packet
|
|
|
|
txtimer.stop();
|
2017-11-10 19:37:12 -05:00
|
|
|
txtimer.start(write_timeout_);
|
2017-10-15 05:39:36 -04:00
|
|
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
2017-10-12 23:06:59 -04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|