Skip to content

Commit c393d0e

Browse files
committed
Auto-detect Freebeat Android UART port
1 parent 11ac7fe commit c393d0e

2 files changed

Lines changed: 123 additions & 2 deletions

File tree

src/android/src/Usbserial.java

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import android.hardware.usb.UsbDevice;
99
import android.hardware.usb.UsbDeviceConnection;
1010
import android.hardware.usb.UsbManager;
11+
import android.system.ErrnoException;
12+
import android.system.Os;
13+
import android.system.OsConstants;
14+
import android.system.StructPollfd;
1115
import org.cagnulen.qdomyoszwift.QLog;
1216
import android.app.Service;
1317
import android.media.RingtoneManager;
@@ -39,15 +43,35 @@
3943
public class Usbserial {
4044

4145
static UsbSerialPort port = null;
46+
static java.io.FileDescriptor localSerialFd = null;
47+
static boolean localSerialMode = false;
4248
static byte[] receiveData = new byte[4096];
4349
static int lastReadLen = 0;
50+
static final String[] localSerialCandidates = {
51+
"/dev/ttyS4",
52+
"/dev/ttyS0",
53+
"/dev/ttyS1",
54+
"/dev/ttyS2",
55+
"/dev/ttyS3"
56+
};
4457

4558
public static void open(Context context) {
4659
open(context, 2400); // Default baud rate for Computrainer
4760
}
4861

4962
public static void open(Context context, int baudRate) {
63+
open(context, baudRate, "");
64+
}
65+
66+
public static void open(Context context, int baudRate, String devicePath) {
67+
if (devicePath != null && (devicePath.startsWith("/dev/") || devicePath.equalsIgnoreCase("auto"))) {
68+
openLocalSerial(devicePath, baudRate);
69+
return;
70+
}
71+
5072
QLog.d("QZ","UsbSerial open with baud rate: " + baudRate);
73+
localSerialMode = false;
74+
localSerialFd = null;
5175
// Find all available drivers from attached devices.
5276
UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
5377
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
@@ -110,7 +134,76 @@ public void onReceive(Context context, Intent intent) {
110134
}
111135
}
112136

137+
private static void openLocalSerial(String devicePath, int baudRate) {
138+
QLog.d("QZ","UsbSerial local serial open " + devicePath + " with baud rate: " + baudRate);
139+
port = null;
140+
localSerialFd = null;
141+
localSerialMode = false;
142+
lastReadLen = 0;
143+
144+
if (devicePath.equalsIgnoreCase("auto")) {
145+
for (String candidate : localSerialCandidates) {
146+
if (openLocalSerialPath(candidate, baudRate)) {
147+
return;
148+
}
149+
}
150+
QLog.d("QZ","UsbSerial local serial auto open failed");
151+
return;
152+
}
153+
154+
openLocalSerialPath(devicePath, baudRate);
155+
}
156+
157+
private static boolean openLocalSerialPath(String devicePath, int baudRate) {
158+
try {
159+
configureLocalSerial(devicePath, baudRate);
160+
localSerialFd = Os.open(devicePath, OsConstants.O_RDWR | OsConstants.O_NOCTTY | OsConstants.O_NONBLOCK, 0);
161+
localSerialMode = true;
162+
QLog.d("QZ","UsbSerial local serial opened successfully: " + devicePath);
163+
return true;
164+
}
165+
catch (ErrnoException e) {
166+
QLog.d("QZ","UsbSerial local serial open failed: " + e.getMessage());
167+
return false;
168+
}
169+
}
170+
171+
private static void configureLocalSerial(String devicePath, int baudRate) {
172+
try {
173+
String[] command = {
174+
"stty",
175+
"-F",
176+
devicePath,
177+
String.valueOf(baudRate),
178+
"cs8",
179+
"-cstopb",
180+
"-parenb",
181+
"raw",
182+
"-echo"
183+
};
184+
Process process = Runtime.getRuntime().exec(command);
185+
int rc = process.waitFor();
186+
QLog.d("QZ","UsbSerial local serial stty exit code: " + rc);
187+
}
188+
catch (Exception e) {
189+
QLog.d("QZ","UsbSerial local serial stty failed: " + e.getMessage());
190+
}
191+
}
192+
113193
public static void write (byte[] bytes) {
194+
if(localSerialMode) {
195+
if(localSerialFd == null)
196+
return;
197+
198+
try {
199+
Os.write(localSerialFd, bytes, 0, bytes.length);
200+
}
201+
catch (ErrnoException | IOException e) {
202+
QLog.d("QZ","UsbSerial local serial write failed: " + e.getMessage());
203+
}
204+
return;
205+
}
206+
114207
if(port == null)
115208
return;
116209

@@ -128,6 +221,32 @@ public static int readLen() {
128221
}
129222

130223
public static byte[] read() {
224+
if(localSerialMode) {
225+
if(localSerialFd == null) {
226+
lastReadLen = 0;
227+
return receiveData;
228+
}
229+
230+
try {
231+
StructPollfd pollFd = new StructPollfd();
232+
pollFd.fd = localSerialFd;
233+
pollFd.events = (short)OsConstants.POLLIN;
234+
int ready = Os.poll(new StructPollfd[]{pollFd}, 0);
235+
if(ready <= 0) {
236+
lastReadLen = 0;
237+
return receiveData;
238+
}
239+
240+
lastReadLen = Os.read(localSerialFd, receiveData, 0, receiveData.length);
241+
QLog.d("QZ","UsbSerial local serial reading " + lastReadLen);
242+
}
243+
catch (ErrnoException | IOException e) {
244+
lastReadLen = 0;
245+
QLog.d("QZ","UsbSerial local serial read failed: " + e.getMessage());
246+
}
247+
return receiveData;
248+
}
249+
131250
if(port == null) {
132251
lastReadLen = 0;
133252
return receiveData;

src/devices/freebeatbike/FreebeatUSB.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,12 @@ int FreebeatUSB::rawRead(char *buf, int maxLen, int timeoutMs) {
257257
* ---------------------------------------------------------------------- */
258258
int FreebeatUSB::openPort() {
259259
#ifdef Q_OS_ANDROID
260+
QAndroidJniObject portName = QAndroidJniObject::fromString(QStringLiteral("auto"));
260261
QAndroidJniObject::callStaticMethod<void>("org/cagnulen/qdomyoszwift/Usbserial", "open",
261-
"(Landroid/content/Context;I)V",
262+
"(Landroid/content/Context;ILjava/lang/String;)V",
262263
QtAndroid::androidContext().object(),
263-
baudrate);
264+
baudrate,
265+
portName.object<jstring>());
264266
return 0;
265267
#elif defined(WIN32)
266268
COMMTIMEOUTS timeouts;

0 commit comments

Comments
 (0)