@@ -645,7 +645,13 @@ public void dataBits() throws Exception {
645645 Thread .sleep (10 );
646646 usb .write (new byte []{(byte ) 0xff });
647647 data = telnet .read (2 );
648- assertThat ("19000/7N1" , data , equalTo (new byte []{(byte ) 0x80 , (byte ) 0xff }));
648+ if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
649+ // not supported by MCP2221, other CDC devices might support it
650+ assertThat ("19000/7N1" , data , equalTo (new byte []{(byte ) 0x00 , (byte ) 0xff }));
651+ return ;
652+ } else {
653+ assertThat ("19000/7N1" , data , equalTo (new byte []{(byte ) 0x80 , (byte ) 0xff }));
654+ }
649655 } catch (UnsupportedOperationException e ) {
650656 if (!usb .isCp21xxRestrictedPort )
651657 throw e ;
@@ -718,18 +724,17 @@ public void parity() throws Exception {
718724 usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_ODD );
719725 usb .write (_8n1 );
720726 data = telnet .read (4 );
721- assertThat ("19200/7O1" , data , equalTo (_7o1 ));
722-
723- usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_EVEN );
724- usb .write (_8n1 );
725- data = telnet .read (4 );
726- assertThat ("19200/7E1" , data , equalTo (_7e1 ));
727-
728727 if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
729- // not supported by arduino_leonardo_bridge.ino, other devices might support it
730- usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_MARK );
731- usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_SPACE );
728+ // not supported by MCP2221, other CDC devices might support it
729+ assertThat ("19200/8N1" , data , equalTo (_8n1 ));
732730 } else {
731+ assertThat ("19200/7O1" , data , equalTo (_7o1 ));
732+
733+ usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_EVEN );
734+ usb .write (_8n1 );
735+ data = telnet .read (4 );
736+ assertThat ("19200/7E1" , data , equalTo (_7e1 ));
737+
733738 usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_MARK );
734739 usb .write (_8n1 );
735740 data = telnet .read (4 );
@@ -758,19 +763,19 @@ public void parity() throws Exception {
758763 data = usb .read (4 );
759764 assertThat ("19200/7E1" , data , equalTo (_7e1 ));
760765
761- if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
762- // not supported by arduino_leonardo_bridge.ino, other devices might support it
763- } else {
764- telnet .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_MARK );
765- telnet .write (_8n1 );
766- data = usb .read (4 );
767- assertThat ("19200/7M1" , data , equalTo (_7m1 ));
766+ telnet .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_MARK );
767+ telnet .write (_8n1 );
768+ data = usb .read (4 );
769+ assertThat ("19200/7M1" , data , equalTo (_7m1 ));
768770
769- telnet .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_SPACE );
770- telnet .write (_8n1 );
771- data = usb .read (4 );
772- assertThat ("19200/7S1" , data , equalTo (_7s1 ));
771+ telnet .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_SPACE );
772+ telnet .write (_8n1 );
773+ data = usb .read (4 );
774+ assertThat ("19200/7S1" , data , equalTo (_7s1 ));
773775
776+ if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
777+ ; // not supported by MCP2221, other CDC devices might support it
778+ } else {
774779 usb .setParameters (19200 , 7 , 1 , UsbSerialPort .PARITY_ODD );
775780 telnet .setParameters (19200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
776781 telnet .write (_8n1 );
@@ -792,45 +797,44 @@ public void stopBits() throws Exception {
792797 }
793798 }
794799
800+ // shift stopbits into next byte, by using different databits
801+ // a - start bit (0)
802+ // o - stop bit (1)
803+ // d - data bit
804+
805+ // out 8N2: addddddd doaddddddddo
806+ // 1000001 0 10001111
807+ // in 6N1: addddddo addddddo
808+ // 100000 101000
809+ usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_1 , UsbSerialPort .PARITY_NONE );
810+ telnet .setParameters (19200 , 6 , 1 , UsbSerialPort .PARITY_NONE );
811+ usb .write (new byte []{(byte )0x41 , (byte )0xf1 });
812+ data = telnet .read (2 );
795813 if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
796- usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_1_5 , UsbSerialPort .PARITY_NONE );
797- // software based bridge in arduino_leonardo_bridge.ino is to slow for real test, other devices might support it
798- } else {
799- // shift stopbits into next byte, by using different databits
800- // a - start bit (0)
801- // o - stop bit (1)
802- // d - data bit
803-
804- // out 8N2: addddddd doaddddddddo
805- // 1000001 0 10001111
806- // in 6N1: addddddo addddddo
807- // 100000 101000
808- usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_1 , UsbSerialPort .PARITY_NONE );
809- telnet .setParameters (19200 , 6 , 1 , UsbSerialPort .PARITY_NONE );
810- usb .write (new byte []{(byte )0x41 , (byte )0xf1 });
811- data = telnet .read (2 );
814+ // MCP2221 slightly slower, looks like 2 stop bits. could be different for other CDC devices
815+ assertThat ("19200/8N1" , data , equalTo (new byte []{1 , 11 }));
816+ } else
812817 assertThat ("19200/8N1" , data , equalTo (new byte []{1 , 5 }));
813818
814- // out 8N2: addddddd dooaddddddddoo
815- // 1000001 0 10011111
816- // in 6N1: addddddo addddddo
817- // 100000 110100
818- try {
819- usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_2 , UsbSerialPort .PARITY_NONE );
820- telnet .setParameters (19200 , 6 , 1 , UsbSerialPort .PARITY_NONE );
821- usb .write (new byte []{(byte ) 0x41 , (byte ) 0xf9 });
822- data = telnet .read (2 );
823- assertThat ("19200/8N1" , data , equalTo (new byte []{1 , 11 }));
824- } catch (UnsupportedOperationException e ) {
825- if (!usb .isCp21xxRestrictedPort )
826- throw e ;
827- }
828- try {
829- usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_1_5 , UsbSerialPort .PARITY_NONE );
830- // todo: could create similar test for 1.5 stopbits, by reading at double speed
831- // but only some devices support 1.5 stopbits and it is basically not used any more
832- } catch (UnsupportedOperationException ignored ) {
833- }
819+ // out 8N2: addddddd dooaddddddddoo
820+ // 1000001 0 10011111
821+ // in 6N1: addddddo addddddo
822+ // 100000 110100
823+ try {
824+ usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_2 , UsbSerialPort .PARITY_NONE );
825+ telnet .setParameters (19200 , 6 , 1 , UsbSerialPort .PARITY_NONE );
826+ usb .write (new byte []{(byte ) 0x41 , (byte ) 0xf9 });
827+ data = telnet .read (2 );
828+ assertThat ("19200/8N1" , data , equalTo (new byte []{1 , 11 }));
829+ } catch (UnsupportedOperationException e ) {
830+ if (!usb .isCp21xxRestrictedPort )
831+ throw e ;
832+ }
833+ try {
834+ usb .setParameters (19200 , 8 , UsbSerialPort .STOPBITS_1_5 , UsbSerialPort .PARITY_NONE );
835+ // todo: could create similar test for 1.5 stopbits, by reading at double speed
836+ // but only some devices support 1.5 stopbits and it is basically not used any more
837+ } catch (UnsupportedOperationException ignored ) {
834838 }
835839 }
836840
@@ -883,8 +887,6 @@ public void writeSizes() throws Exception {
883887 usb .setParameters (baudRate , 8 , 1 , UsbSerialPort .PARITY_NONE );
884888 telnet .setParameters (baudRate , 8 , 1 , UsbSerialPort .PARITY_NONE );
885889 int purgeTimeout = 250 ;
886- if (usb .serialDriver instanceof CdcAcmSerialDriver )
887- purgeTimeout = 500 ;
888890 purgeWriteBuffer (purgeTimeout );
889891
890892 // determine write buffer size
@@ -1055,18 +1057,17 @@ public void writeFragments() throws Exception {
10551057
10561058 @ Test
10571059 public void readBufferSize () throws Exception {
1058- // looks like devices perform USB read with full mReadEndpoint.getMaxPacketSize() size (32, 64, 512)
1060+ // looks like devices perform USB read with full mReadEndpoint.getMaxPacketSize() size (16, 32, 64, 512)
10591061 // if the buffer is smaller than the received result, it is silently lost
10601062 //
10611063 // for buffer > packet size, but not multiple of packet size, the same issue happens, but typically
10621064 // only the last (partly filled) packet is lost.
1063- if (usb .serialDriver instanceof CdcAcmSerialDriver )
1064- return ; // arduino sends each byte individually, so not testable here
10651065 byte [] data ;
10661066 boolean purge = true ;
10671067
10681068 usb .open (EnumSet .of (UsbWrapper .OpenCloseFlags .NO_IOMANAGER_START ));
1069- usb .ioManager .setReadBufferSize (8 );
1069+ int len = Math .min (16 , usb .serialPort .getReadEndpoint ().getMaxPacketSize ()/2 ); // 8 for MCP2221, else 16
1070+ usb .ioManager .setReadBufferSize (len /2 );
10701071 usb .ioManager .start ();
10711072 usb .setParameters (115200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
10721073 telnet .setParameters (115200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
@@ -1075,13 +1076,15 @@ public void readBufferSize() throws Exception {
10751076 telnet .write ("1aaa" .getBytes ());
10761077 data = usb .read (4 );
10771078 assertThat (data , equalTo ("1aaa" .getBytes ()));
1078- telnet .write (new byte [16 ]);
1079+
1080+ telnet .write (new byte [len ]);
10791081 try {
1080- data = usb .read (16 );
1082+ data = usb .read (len );
10811083 if (usb .serialDriver instanceof Cp21xxSerialDriver && usb .serialDriver .getPorts ().size () == 1 )
10821084 assertNotEquals (0 , data .length ); // can be shorter or full length
1083- else if (usb .serialDriver instanceof ProlificSerialDriver )
1084- assertTrue ("expected > 0 and < 16 byte, got " + data .length , data .length > 0 && data .length < 16 );
1085+ else if (usb .serialDriver instanceof CdcAcmSerialDriver ||
1086+ usb .serialDriver instanceof ProlificSerialDriver )
1087+ assertTrue ("expected > 0 and < " +len +" byte, got " + data .length , data .length > 0 && data .length < len );
10851088 else // ftdi, ch340, cp2105
10861089 assertEquals (0 , data .length );
10871090 } catch (IOException ignored ) {
@@ -1121,12 +1124,13 @@ else if (usb.serialDriver instanceof ProlificSerialDriver)
11211124 telnet .write ("2aaa" .getBytes ());
11221125 data = usb .read (4 , 8 );
11231126 assertThat (data , equalTo ("2aaa" .getBytes ()));
1124- telnet .write (new byte [16 ]);
1125- data = usb .read (16 , 8 );
1127+ telnet .write (new byte [len ]);
1128+ data = usb .read (len , len / 2 );
11261129 if (usb .serialDriver instanceof Cp21xxSerialDriver && usb .serialDriver .getPorts ().size () == 1 )
11271130 assertNotEquals (0 , data .length ); // can be shorter or full length
1128- else if (usb .serialDriver instanceof ProlificSerialDriver )
1129- assertTrue ("sporadic issue! expected > 0 and < 16 byte, got " + data .length , data .length > 0 && data .length < 16 );
1131+ else if (usb .serialDriver instanceof CdcAcmSerialDriver ||
1132+ usb .serialDriver instanceof ProlificSerialDriver )
1133+ assertTrue ("sporadic issue! expected > 0 and < " +len +" byte, got " + data .length , data .length > 0 && data .length < len );
11301134 else // ftdi, ch340, cp2105
11311135 assertEquals (0 , data .length );
11321136 telnet .write ("2ccc" .getBytes ());
@@ -1146,8 +1150,6 @@ else if (usb.serialDriver instanceof ProlificSerialDriver)
11461150 @ Test
11471151 // provoke data loss, when data is not read fast enough
11481152 public void readBufferOverflow () throws Exception {
1149- if (usb .serialDriver instanceof CdcAcmSerialDriver )
1150- telnet .writeDelay = 10 ; // arduino_leonardo_bridge.ino sends each byte in own USB packet, which is horribly slow
11511153 usb .open ();
11521154 usb .setParameters (115200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
11531155 telnet .setParameters (115200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
@@ -1220,8 +1222,6 @@ private int readSpeedInt(int writeSeconds, int readBufferSize, int readTimeout)
12201222 if (usb .serialDriver instanceof Ch34xSerialDriver )
12211223 baudrate = 38400 ;
12221224 int writeAhead = 5 *baudrate /10 ; // write ahead for another 5 second read
1223- if (usb .serialDriver instanceof CdcAcmSerialDriver )
1224- writeAhead = 50 ;
12251225
12261226 usb .open (EnumSet .of (UsbWrapper .OpenCloseFlags .NO_IOMANAGER_START ));
12271227 usb .ioManager .setReadTimeout (readTimeout );
@@ -1270,16 +1270,10 @@ private int readSpeedInt(int writeSeconds, int readBufferSize, int readTimeout)
12701270
12711271 @ Test
12721272 public void writeSpeed () throws Exception {
1273- // see logcat for performance results
1274- //
1275- // CDC arduino_leonardo_bridge.ino has transfer speed ~ 100 byte/sec
1276- // all other devices can get near physical limit:
1277- // longlines=true:, speed is near physical limit at 11.5k
1278- // longlines=false: speed is 3-4k for all devices, as more USB packets are required
1273+ // see logcat for performance results, speed is near physical limit at 11.5k
12791274 usb .open ();
12801275 usb .setParameters (115200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
12811276 telnet .setParameters (115200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
1282- boolean longlines = !(usb .serialDriver instanceof CdcAcmSerialDriver );
12831277
12841278 int linenr = 0 ;
12851279 String line ="" ;
@@ -1292,10 +1286,7 @@ public void writeSpeed() throws Exception {
12921286 for (int seconds =1 ; seconds <=5 ; seconds ++) {
12931287 next += 1000 ;
12941288 while (System .currentTimeMillis () < next ) {
1295- if (longlines )
1296- line = String .format ("%060d," , linenr ++);
1297- else
1298- line = String .format ("%07d," , linenr ++);
1289+ line = String .format ("%060d," , linenr ++);
12991290 usb .write (line .getBytes ());
13001291 expected .append (line );
13011292 data .append (new String (telnet .read (0 )));
@@ -1576,34 +1567,32 @@ public void readTimeout() throws Exception {
15761567 }
15771568 Log .i (TAG , "average time per read " + (System .currentTimeMillis ()-time )/i + " msec" );
15781569
1579- if (!(usb .serialDriver instanceof CdcAcmSerialDriver )) {
1580- int diffLen ;
1581- usb .close ();
1582- // no issue with high transfer rate and long read timeout
1583- diffLen = readSpeedInt (5 , -1 , longTimeout );
1584- if (usb .serialDriver instanceof Ch34xSerialDriver && diffLen == -1 )
1585- diffLen = 0 ; // todo: investigate last packet loss
1586- assertEquals (0 , diffLen );
1587- usb .close ();
1588- // date loss with high transfer rate and short read timeout !!!
1589- diffLen = readSpeedInt (5 , -1 , shortTimeout );
1590-
1591- assertNotEquals ("sporadic issue!" , 0 , diffLen );
1592-
1593- // data loss observed with read timeout up to 200 msec, e.g.
1594- // difference at 181 len 64
1595- // got 000020,0000021,0000030,0000031,0000032,0
1596- // expected 000020,0000021,0000022,0000023,0000024,0
1597- // difference at 341 len 128
1598- // got 000048,0000049,0000066,0000067,0000068,0
1599- // expected 000048,0000049,0000050,0000051,0000052,0
1600- // difference at 724 len 704
1601- // got 0000112,0000113,0000202,0000203,0000204,
1602- // expected 0000112,0000113,0000114,0000115,0000116,
1603- // difference at 974 len 8
1604- // got 00231,0000232,0000234,0000235,0000236,00
1605- // expected 00231,0000232,0000233,0000234,0000235,00
1606- }
1570+ int diffLen ;
1571+ usb .close ();
1572+ // no issue with high transfer rate and long read timeout
1573+ diffLen = readSpeedInt (5 , -1 , longTimeout );
1574+ if (usb .serialDriver instanceof Ch34xSerialDriver && diffLen == -1 )
1575+ diffLen = 0 ; // todo: investigate last packet loss
1576+ assertEquals (0 , diffLen );
1577+ usb .close ();
1578+ // date loss with high transfer rate and short read timeout !!!
1579+ diffLen = readSpeedInt (5 , -1 , shortTimeout );
1580+
1581+ assertNotEquals ("sporadic issue!" , 0 , diffLen );
1582+
1583+ // data loss observed with read timeout up to 200 msec, e.g.
1584+ // difference at 181 len 64
1585+ // got 000020,0000021,0000030,0000031,0000032,0
1586+ // expected 000020,0000021,0000022,0000023,0000024,0
1587+ // difference at 341 len 128
1588+ // got 000048,0000049,0000066,0000067,0000068,0
1589+ // expected 000048,0000049,0000050,0000051,0000052,0
1590+ // difference at 724 len 704
1591+ // got 0000112,0000113,0000202,0000203,0000204,
1592+ // expected 0000112,0000113,0000114,0000115,0000116,
1593+ // difference at 974 len 8
1594+ // got 00231,0000232,0000234,0000235,0000236,00
1595+ // expected 00231,0000232,0000233,0000234,0000235,00
16071596 }
16081597
16091598 @ Test
@@ -1808,12 +1797,7 @@ public void controlLines() throws Exception {
18081797 assertThat (usb .getControlLine (usb .serialPort ::getCD ), equalTo (inputLineFalse ));
18091798 assertThat (usb .getControlLine (usb .serialPort ::getRI ), equalTo (usb .inputLinesOnlyRtsCts ? Boolean .FALSE : inputLineTrue ));
18101799 telnet .write (data );
1811- if (usb .serialDriver instanceof CdcAcmSerialDriver )
1812- // arduino: control line feedback as serial_state notification is not implemented.
1813- // It does not send w/o RTS or DTR, so these control lines can be partly checked here.
1814- assertEquals (0 , usb .read ().length );
1815- else
1816- assertThat (Arrays .toString (data ), usb .read (4 ), equalTo (data ));
1800+ assertThat (Arrays .toString (data ), usb .read (4 ), equalTo (data ));
18171801 usb .write (data );
18181802 assertThat (Arrays .toString (data ), telnet .read (4 ), equalTo (data ));
18191803
@@ -2312,20 +2296,25 @@ void run() throws Exception {
23122296 @ Test
23132297 public void setBreak () throws Exception {
23142298 usb .open ();
2299+ if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
2300+ // not supported by MCP2221, other CDC devices might support it
2301+ try {
2302+ usb .serialPort .setBreak (true );
2303+ fail ("setBreak error expected" );
2304+ } catch (IOException ignored ) {
2305+ }
2306+ return ;
2307+ }
23152308 telnet .setParameters (19200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
23162309 usb .setParameters (19200 , 8 , 1 , UsbSerialPort .PARITY_NONE );
23172310 doReadWrite ("" );
2318- usb .serialPort .setBreak (true );
23192311 Thread .sleep (100 );
23202312 usb .serialPort .setBreak (false );
23212313 // RFC2217 has SET_CONTROL + REQ_BREAK_STATE request, but this is not supported by pyserial
23222314 // as there is no easy notification on <break> condition. By default break is returned as
23232315 // 0 byte on Linux, see https://man7.org/linux/man-pages/man3/termios.3.html -> BRKINT
23242316 byte [] data = telnet .read (1 );
2325- if (usb .serialDriver instanceof CdcAcmSerialDriver ) {
2326- // BREAK forwarding not implemented by arduino_leonardo_bridge.ino
2327- assertThat ("<break>" , data , equalTo (new byte []{}));
2328- } else if (usb .isCp21xxRestrictedPort ) {
2317+ if (usb .isCp21xxRestrictedPort ) {
23292318 assertThat ("<break>" , data , equalTo (new byte []{0x55 })); // send the last byte again?
23302319 } else {
23312320 assertThat ("<break>" , data , equalTo (new byte []{0 }));
0 commit comments