1
0
mirror of https://github.com/mik3y/usb-serial-for-android synced 2025-06-07 16:06:10 +00:00

unify open() error handling, more tests, minor cleanup

This commit is contained in:
kai-morich 2019-11-02 13:03:11 +01:00
parent 6869eff88a
commit 18b5b6e648
8 changed files with 618 additions and 507 deletions

View File

@ -229,7 +229,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
private byte[] telnetRead(int expectedLength) throws Exception { private byte[] telnetRead(int expectedLength) throws Exception {
long end = System.currentTimeMillis() + TELNET_READ_WAIT; long end = System.currentTimeMillis() + TELNET_READ_WAIT;
ByteBuffer buf = ByteBuffer.allocate(4096); ByteBuffer buf = ByteBuffer.allocate(8192);
while(System.currentTimeMillis() < end) { while(System.currentTimeMillis() < end) {
if(telnetReadStream.available() > 0) { if(telnetReadStream.available() > 0) {
buf.put((byte) telnetReadStream.read()); buf.put((byte) telnetReadStream.read());
@ -498,23 +498,21 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
doReadWrite(""); doReadWrite("");
usbClose(); usbClose();
usbSerialPort = usbSerialDriver.getPorts().get(test_device_port);
try { try {
usbSerialPort.close(); usbSerialPort.close();
fail("already closed expected"); fail("already closed expected");
} catch (IOException ignored) { } catch (IOException ignored) {
} catch (NullPointerException ignored) {
} }
try { try {
usbWrite(new byte[]{0x00}); usbWrite(new byte[]{0x00});
fail("write error expected"); fail("write error expected");
} catch (IOException ignored) { } catch (IOException ignored) {
} catch (NullPointerException ignored) {
} }
try { try {
usbRead(1); usbRead(1);
//fail("read error expected"); fail("read error expected");
} catch (IOException ignored) { } catch (IOException ignored) {
} catch (NullPointerException ignored) {
} }
try { try {
usbParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE); usbParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
@ -522,11 +520,22 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
} catch (IOException ignored) { } catch (IOException ignored) {
} catch (NullPointerException ignored) { } catch (NullPointerException ignored) {
} }
usbSerialPort = null;
usbOpen(true); usbOpen(true);
telnetParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE); telnetParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE); usbParameters(9600, 8, 1, UsbSerialPort.PARITY_NONE);
doReadWrite(""); doReadWrite("");
// close before iomanager
assertEquals(SerialInputOutputManager.State.RUNNING, usbIoManager.getState());
usbSerialPort.close();
for (int i = 0; i < 1000; i++) {
if (usbIoManager.getState() == SerialInputOutputManager.State.STOPPED)
break;
Thread.sleep(1);
}
assertEquals(SerialInputOutputManager.State.STOPPED, usbIoManager.getState());
} }
@Test @Test
@ -684,21 +693,21 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
telnetParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE); telnetParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE);
telnetWrite(new byte[] {0x00}); telnetWrite(new byte[] {0x00});
Thread.sleep(1); // one bit is 0.05 milliseconds long, wait >> stop bit Thread.sleep(10); // one bit is 0.05 milliseconds long, wait >> stop bit
telnetWrite(new byte[] {(byte)0xff}); telnetWrite(new byte[] {(byte)0xff});
data = usbRead(2); data = usbRead(2);
assertThat("19200/7N1", data, equalTo(new byte[] {(byte)0x80, (byte)0xff})); assertThat("19200/7N1", data, equalTo(new byte[] {(byte)0x80, (byte)0xff}));
telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE); telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
telnetWrite(new byte[] {0x00}); telnetWrite(new byte[] {0x00});
Thread.sleep(1); Thread.sleep(10);
telnetWrite(new byte[] {(byte)0xff}); telnetWrite(new byte[] {(byte)0xff});
data = usbRead(2); data = usbRead(2);
assertThat("19000/6N1", data, equalTo(new byte[] {(byte)0xc0, (byte)0xff})); assertThat("19000/6N1", data, equalTo(new byte[] {(byte)0xc0, (byte)0xff}));
telnetParameters(19200, 5, 1, UsbSerialPort.PARITY_NONE); telnetParameters(19200, 5, 1, UsbSerialPort.PARITY_NONE);
telnetWrite(new byte[] {0x00}); telnetWrite(new byte[] {0x00});
Thread.sleep(1); Thread.sleep(10);
telnetWrite(new byte[] {(byte)0xff}); telnetWrite(new byte[] {(byte)0xff});
data = usbRead(2); data = usbRead(2);
assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff})); assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff}));
@ -708,7 +717,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE); usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[]{0x00}); usbWrite(new byte[]{0x00});
Thread.sleep(1); Thread.sleep(10);
usbWrite(new byte[]{(byte) 0xff}); usbWrite(new byte[]{(byte) 0xff});
data = telnetRead(2); data = telnetRead(2);
assertThat("19000/7N1", data, equalTo(new byte[]{(byte) 0x80, (byte) 0xff})); assertThat("19000/7N1", data, equalTo(new byte[]{(byte) 0x80, (byte) 0xff}));
@ -719,7 +728,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
try { try {
usbParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE); usbParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[]{0x00}); usbWrite(new byte[]{0x00});
Thread.sleep(1); Thread.sleep(10);
usbWrite(new byte[]{(byte) 0xff}); usbWrite(new byte[]{(byte) 0xff});
data = telnetRead(2); data = telnetRead(2);
assertThat("19000/6N1", data, equalTo(new byte[]{(byte) 0xc0, (byte) 0xff})); assertThat("19000/6N1", data, equalTo(new byte[]{(byte) 0xc0, (byte) 0xff}));
@ -730,7 +739,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
try { try {
usbParameters(19200, 5, 1, UsbSerialPort.PARITY_NONE); usbParameters(19200, 5, 1, UsbSerialPort.PARITY_NONE);
usbWrite(new byte[] {0x00}); usbWrite(new byte[] {0x00});
Thread.sleep(1); Thread.sleep(5);
usbWrite(new byte[] {(byte)0xff}); usbWrite(new byte[] {(byte)0xff});
data = telnetRead(2); data = telnetRead(2);
assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff})); assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff}));
@ -1218,4 +1227,108 @@ public class DeviceTest implements SerialInputOutputManager.Listener {
Thread.sleep(1); Thread.sleep(1);
} }
} }
@Test
public void wrongDriver() throws Exception {
UsbDeviceConnection wrongDeviceConnection;
UsbSerialDriver wrongSerialDriver;
UsbSerialPort wrongSerialPort;
if(!(usbSerialDriver instanceof CdcAcmSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new CdcAcmSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
wrongSerialPort.setParameters(115200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // ch340 fails here
wrongSerialPort.write(new byte[]{1}, 1000); // pl2302 does not fail, but sends with wrong baud rate
if(!(usbSerialDriver instanceof ProlificSerialDriver))
fail("error expected");
} catch (IOException ignored) {
}
try {
if(usbSerialDriver instanceof ProlificSerialDriver) {
assertNotEquals(new byte[]{1}, telnetRead());
}
wrongSerialPort.close();
if(!(usbSerialDriver instanceof Ch34xSerialDriver |
usbSerialDriver instanceof ProlificSerialDriver))
fail("error expected");
} catch (IOException ignored) {
}
}
if(!(usbSerialDriver instanceof Ch34xSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new Ch34xSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
fail("error expected");
} catch (IOException ignored) {
}
}
// FTDI only recovers from Cp21xx control commands with power toggle, so skip this combination!
if(!(usbSerialDriver instanceof Cp21xxSerialDriver | usbSerialDriver instanceof FtdiSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new Cp21xxSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
//if(usbSerialDriver instanceof FtdiSerialDriver)
// wrongSerialPort.setParameters(115200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // ch340 fails here
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
//if(!(usbSerialDriver instanceof FtdiSerialDriver))
// fail("error expected");
} catch (IOException ignored) {
}
}
if(!(usbSerialDriver instanceof FtdiSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new FtdiSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
if(usbSerialDriver instanceof Cp21xxSerialDriver)
wrongSerialPort.setParameters(115200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); // ch340 fails here
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
if(!(usbSerialDriver instanceof Cp21xxSerialDriver))
fail("error expected");
} catch (IOException ignored) {
}
}
if(!(usbSerialDriver instanceof ProlificSerialDriver)) {
wrongDeviceConnection = usbManager.openDevice(usbSerialDriver.getDevice());
wrongSerialDriver = new ProlificSerialDriver(usbSerialDriver.getDevice());
wrongSerialPort = wrongSerialDriver.getPorts().get(0);
try {
wrongSerialPort.open(wrongDeviceConnection);
fail("error expected");
} catch (IOException ignored) {
}
try {
wrongSerialPort.close();
fail("error expected");
} catch (IOException ignored) {
}
}
// test that device recovers from wrong commands
usbOpen(true);
telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
doReadWrite("");
}
} }

View File

@ -107,7 +107,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
mConnection = connection; mConnection = connection;
boolean opened = false; boolean opened = false;
try { try {
if (1 == mDevice.getInterfaceCount()) { if (1 == mDevice.getInterfaceCount()) {
Log.d(TAG,"device might be castrated ACM device, trying single interface logic"); Log.d(TAG,"device might be castrated ACM device, trying single interface logic");
openSingleInterface(); openSingleInterface();
@ -115,15 +114,10 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
Log.d(TAG,"trying default interface logic"); Log.d(TAG,"trying default interface logic");
openInterface(); openInterface();
} }
opened = true; opened = true;
} finally { } finally {
if (!opened) { if (!opened) {
mConnection = null; close();
// just to be on the save side
mControlEndpoint = null;
mReadEndpoint = null;
mWriteEndpoint = null;
} }
} }
} }
@ -258,6 +252,9 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
if (mUsbRequest != null) if (mUsbRequest != null)
mUsbRequest.cancel(); mUsbRequest.cancel();
} }
mControlEndpoint = null;
mReadEndpoint = null;
mWriteEndpoint = null;
try { try {
mConnection.releaseInterface(mControlInterface); mConnection.releaseInterface(mControlInterface);
mConnection.releaseInterface(mDataInterface); mConnection.releaseInterface(mDataInterface);
@ -271,10 +268,11 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
@Override @Override
public int read(byte[] dest, int timeoutMillis) throws IOException { public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest(); final UsbRequest request = new UsbRequest();
try { try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint); request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest); final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) { if (!request.queue(buf, dest.length)) {
@ -307,6 +305,9 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
// TODO(mikey): Nearly identical to FtdiSerial write. Refactor. // TODO(mikey): Nearly identical to FtdiSerial write. Refactor.
int offset = 0; int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) { while (offset < src.length) {
final int writeLength; final int writeLength;
final int amtWritten; final int amtWritten;

View File

@ -130,11 +130,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
opened = true; opened = true;
} finally { } finally {
if (!opened) { if (!opened) {
try {
close(); close();
} catch (IOException e) {
// Ignore IOExceptions during close()
}
} }
} }
} }
@ -162,10 +158,11 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
@Override @Override
public int read(byte[] dest, int timeoutMillis) throws IOException { public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest(); final UsbRequest request = new UsbRequest();
try { try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint); request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest); final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) { if (!request.queue(buf, dest.length)) {
@ -197,6 +194,9 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
public int write(byte[] src, int timeoutMillis) throws IOException { public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0; int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) { while (offset < src.length) {
final int writeLength; final int writeLength;
final int amtWritten; final int amtWritten;

View File

@ -123,9 +123,13 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
return Cp21xxSerialDriver.this; return Cp21xxSerialDriver.this;
} }
private int setConfigSingle(int request, int value) { private int setConfigSingle(int request, int value) throws IOException {
return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value, int result = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
mPortNumber, null, 0, USB_WRITE_TIMEOUT_MILLIS); mPortNumber, null, 0, USB_WRITE_TIMEOUT_MILLIS);
if (result != 0) {
throw new IOException("Setting baudrate failed: result=" + result);
}
return result;
} }
@Override @Override
@ -163,11 +167,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
opened = true; opened = true;
} finally { } finally {
if (!opened) { if (!opened) {
try {
close(); close();
} catch (IOException e) {
// Ignore IOExceptions during close()
}
} }
} }
} }
@ -197,10 +197,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
@Override @Override
public int read(byte[] dest, int timeoutMillis) throws IOException { public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest(); final UsbRequest request = new UsbRequest();
try { try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint); request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest); final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) { if (!request.queue(buf, dest.length)) {
@ -232,6 +233,9 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
public int write(byte[] src, int timeoutMillis) throws IOException { public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0; int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) { while (offset < src.length) {
final int writeLength; final int writeLength;
final int amtWritten; final int amtWritten;

View File

@ -257,7 +257,6 @@ public class FtdiSerialDriver implements UsbSerialDriver {
} finally { } finally {
if (!opened) { if (!opened) {
close(); close();
mConnection = null;
} }
} }
} }
@ -279,12 +278,13 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override @Override
public int read(byte[] dest, int timeoutMillis) throws IOException { public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0); final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0);
final UsbRequest request = new UsbRequest(); final UsbRequest request = new UsbRequest();
final ByteBuffer buf = ByteBuffer.wrap(dest); final ByteBuffer buf = ByteBuffer.wrap(dest);
try { try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, endpoint); request.initialize(mConnection, endpoint);
if (!request.queue(buf, dest.length)) { if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request."); throw new IOException("Error queueing request.");
@ -308,6 +308,9 @@ public class FtdiSerialDriver implements UsbSerialDriver {
@Override @Override
public int write(byte[] src, int timeoutMillis) throws IOException { public int write(byte[] src, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(1); final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(1);
int offset = 0; int offset = 0;

View File

@ -65,25 +65,19 @@ public class ProbeTable {
try { try {
method = driverClass.getMethod("getSupportedDevices"); method = driverClass.getMethod("getSupportedDevices");
} catch (SecurityException e) { } catch (SecurityException | NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
final Map<Integer, int[]> devices; final Map<Integer, int[]> devices;
try { try {
devices = (Map<Integer, int[]>) method.invoke(null); devices = (Map<Integer, int[]>) method.invoke(null);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
for (Map.Entry<Integer, int[]> entry : devices.entrySet()) { for (Map.Entry<Integer, int[]> entry : devices.entrySet()) {
final int vendorId = entry.getKey().intValue(); final int vendorId = entry.getKey();
for (int productId : entry.getValue()) { for (int productId : entry.getValue()) {
addProduct(vendorId, productId, driverClass); addProduct(vendorId, productId, driverClass);
} }

View File

@ -336,8 +336,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
opened = true; opened = true;
} finally { } finally {
if (!opened) { if (!opened) {
mConnection = null; close();
connection.releaseInterface(usbInterface);
} }
} }
} }
@ -373,10 +372,11 @@ public class ProlificSerialDriver implements UsbSerialDriver {
@Override @Override
public int read(byte[] dest, int timeoutMillis) throws IOException { public int read(byte[] dest, int timeoutMillis) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final UsbRequest request = new UsbRequest(); final UsbRequest request = new UsbRequest();
try { try {
if(mConnection == null)
throw new IOException("Connection closed");
request.initialize(mConnection, mReadEndpoint); request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest); final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) { if (!request.queue(buf, dest.length)) {
@ -404,6 +404,9 @@ public class ProlificSerialDriver implements UsbSerialDriver {
public int write(byte[] src, int timeoutMillis) throws IOException { public int write(byte[] src, int timeoutMillis) throws IOException {
int offset = 0; int offset = 0;
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) { while (offset < src.length) {
final int writeLength; final int writeLength;
final int amtWritten; final int amtWritten;

View File

@ -95,15 +95,8 @@ public class UsbSerialProber {
final Constructor<? extends UsbSerialDriver> ctor = final Constructor<? extends UsbSerialDriver> ctor =
driverClass.getConstructor(UsbDevice.class); driverClass.getConstructor(UsbDevice.class);
driver = ctor.newInstance(usbDevice); driver = ctor.newInstance(usbDevice);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException |
throw new RuntimeException(e); IllegalAccessException | InvocationTargetException e) {
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return driver; return driver;