diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index bdf856d..94c7423 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -17,6 +17,7 @@ cmake_minimum_required(VERSION 3.4.1)
#add_compile_options(-DDEBUG_ANDROID_PAINT)
#add_compile_options(-DDEBUG_ANDROID_THREAD)
#add_compile_options(-DDEBUG_ANDROID_FILE)
+#add_compile_options(-DDEBUG_ANDROID_SERIAL)
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
diff --git a/app/build.gradle b/app/build.gradle
index 4a63b74..000cf43 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -28,11 +28,11 @@ if (keystorePropertiesFile.exists()) {
}
android {
- compileSdkVersion 29
+ compileSdkVersion 30
defaultConfig {
applicationId "org.emulator.forty.eight"
minSdkVersion 19
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 20
versionName "2.2"
setProperty("archivesBaseName", "Emu48-v$versionName")
diff --git a/app/src/main/cpp/win32-layer.c b/app/src/main/cpp/win32-layer.c
index 26d65bc..192b34b 100644
--- a/app/src/main/cpp/win32-layer.c
+++ b/app/src/main/cpp/win32-layer.c
@@ -143,6 +143,8 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
}
pthread_mutex_unlock(&commsLock);
+ SERIAL_LOGD("CreateFile(lpFileName: \"%s\", ...) commId: %d, commIndex: %d", lpFileName, handle->commId, handle->commIndex);
+
return handle;
} else
return (HANDLE) INVALID_HANDLE_VALUE;
@@ -279,6 +281,27 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
return (HANDLE) INVALID_HANDLE_VALUE;
}
+char * dumpToHexAscii(char * buffer, int inputSize, int charWidth) {
+ int numLines = 1 + inputSize / charWidth;
+ char * hexAsciiDump = malloc(4 * inputSize + 3 * numLines + 10);
+ unsigned char * pBuff = (unsigned char *)buffer;
+ char * pDump = hexAsciiDump;
+ for (int l = 0, n = 0; l < numLines; ++l) {
+ *pDump++ = (char)'\t';
+ for (int c = 0; c < charWidth && n + c < inputSize; ++c) {
+ sprintf((char *const)pDump, "%02X ", pBuff[c]);
+ pDump += 3;
+ }
+ for (int c = 0; c < charWidth && n + c < inputSize; ++c)
+ *pDump++ = isprint(pBuff[c]) ? ((char *)pBuff)[c] : '.';
+ *pDump++ = '\n';
+ pBuff += charWidth;
+ n += charWidth;
+ }
+ *pDump++ = '\0';
+ return hexAsciiDump;
+}
+
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
FILE_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d)", hFile, lpBuffer, nNumberOfBytesToRead);
DWORD readByteCount = 0;
@@ -288,6 +311,11 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD
readByteCount = (DWORD) AAsset_read(hFile->fileAsset, lpBuffer, nNumberOfBytesToRead);
} else if(hFile->handleType == HANDLE_TYPE_COM) {
readByteCount = (DWORD) readSerialPort(hFile->commId, lpBuffer, nNumberOfBytesToRead);
+#if defined DEBUG_ANDROID_SERIAL
+ char * hexAsciiDump = dumpToHexAscii(lpBuffer, readByteCount, 8);
+ SERIAL_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d) -> %d bytes\n%s", hFile, lpBuffer, nNumberOfBytesToRead, readByteCount, hexAsciiDump);
+ free(hexAsciiDump);
+#endif
}
if(lpNumberOfBytesRead)
*lpNumberOfBytesRead = readByteCount;
@@ -302,7 +330,13 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,LPDWO
*lpNumberOfBytesWritten = (DWORD) writenByteCount;
return writenByteCount >= 0;
} else if(hFile->handleType == HANDLE_TYPE_COM) {
+ Sleep(4); // Seems to be needed else the kermit packet does not fully reach the genuine calculator.
ssize_t writenByteCount = writeSerialPort(hFile->commId, lpBuffer, nNumberOfBytesToWrite);
+#if defined DEBUG_ANDROID_SERIAL
+ char * hexAsciiDump = dumpToHexAscii(lpBuffer, writenByteCount, 8);
+ SERIAL_LOGD("WriteFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToWrite: %d) -> %d bytes\n%s", hFile, lpBuffer, nNumberOfBytesToWrite, writenByteCount, hexAsciiDump);
+ free(hexAsciiDump);
+#endif
commEvent(hFile->commId, EV_TXEMPTY); // Not sure about that (not the same thread)!
if(lpNumberOfBytesWritten)
*lpNumberOfBytesWritten = (DWORD) writenByteCount;
@@ -785,7 +819,7 @@ BOOL WINAPI CloseHandle(HANDLE hObject) {
free(hObject);
return TRUE;
case HANDLE_TYPE_COM: {
- FILE_LOGD("CloseHandle() HANDLE_TYPE_COM");
+ SERIAL_LOGD("CloseHandle(hObject: %p) for HANDLE_TYPE_COM", hObject);
closeSerialPort(hObject->commId);
hObject->commId = 0;
@@ -3043,6 +3077,8 @@ BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumb
// This is not a win32 API
void commEvent(int commId, int eventMask) {
+ SERIAL_LOGD("commEvent(commId: %d, eventMask: 0x%08x)", commId, eventMask);
+
HANDLE commHandleFound = NULL;
pthread_mutex_lock(&commsLock);
for(int i = 0; i < MAX_CREATED_COMM; i++) {
@@ -3060,8 +3096,11 @@ void commEvent(int commId, int eventMask) {
}
BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
+ SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p)", hFile, lpEvtMask);
if(hFile && hFile->handleType == HANDLE_TYPE_COM) {
+ SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject locking", hFile, lpEvtMask);
WaitForSingleObject(hFile->commEvent, INFINITE);
+ SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject unlocked", hFile, lpEvtMask);
pthread_mutex_lock(&commsLock);
if(lpEvtMask && hFile->commEventMask) {
*lpEvtMask = hFile->commEventMask; //EV_RXCHAR | EV_TXEMPTY | EV_ERR
@@ -3073,18 +3112,22 @@ BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
return FALSE;
}
BOOL ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
+ SERIAL_LOGD("ClearCommError(hFile: %p, lpErrors: %p, lpStat: %p) TODO", hFile, lpErrors, lpStat);
//TODO
return FALSE;
}
BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
+ SERIAL_LOGD("SetCommTimeouts(hFile: %p, lpCommTimeouts: %p) TODO", hFile, lpCommTimeouts);
//TODO
return FALSE;
}
BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) {
+ SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) TODO", hFile, dwEvtMask);
//TODO
if(hFile && hFile->handleType == HANDLE_TYPE_COM) {
if(dwEvtMask == 0) {
// When 0, clear all events and force WaitCommEvent to return.
+ SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) SetEvent(hEvent: %p)", hFile, dwEvtMask, hFile->commEvent);
SetEvent(hFile->commEvent);
return TRUE;
}
@@ -3092,6 +3135,7 @@ BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) {
return FALSE;
}
BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) {
+ SERIAL_LOGD("SetCommState(hFile: %p, lpDCB: %p)", hFile, lpDCB);
if(hFile && hFile->handleType == HANDLE_TYPE_COM && lpDCB) {
int result = setSerialPortParameters(hFile->commId, lpDCB->BaudRate); //TODO 2 stop bits?
if(result > 0) {
@@ -3105,15 +3149,18 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) {
return FALSE;
}
BOOL PurgeComm(HANDLE hFile, DWORD dwFlags) {
+ SERIAL_LOGD("SetCommState(hFile: %p, dwFlags: 0x%08X) TODO", hFile, dwFlags);
//TODO
return FALSE;
}
BOOL SetCommBreak(HANDLE hFile) {
+ SERIAL_LOGD("SetCommBreak(hFile: %p)", hFile);
if(hFile && hFile->handleType == HANDLE_TYPE_COM)
return serialPortSetBreak(hFile->commId);
return FALSE;
}
BOOL ClearCommBreak(HANDLE hFile) {
+ SERIAL_LOGD("ClearCommBreak(hFile: %p)", hFile);
if(hFile && hFile->handleType == HANDLE_TYPE_COM)
return serialPortClearBreak(hFile->commId);
return FALSE;
diff --git a/app/src/main/cpp/win32-layer.h b/app/src/main/cpp/win32-layer.h
index bdb095a..634fb9d 100644
--- a/app/src/main/cpp/win32-layer.h
+++ b/app/src/main/cpp/win32-layer.h
@@ -59,6 +59,11 @@
# define FILE_LOGD(...)
#endif
+#if defined DEBUG_ANDROID_SERIAL
+# define SERIAL_LOGD(...) LOGD(__VA_ARGS__)
+#else
+# define SERIAL_LOGD(...)
+#endif
#define _MSC_VER 1914
#define GetWindowLongPtr GetWindowLong
diff --git a/app/src/main/java/org/emulator/calculator/Serial.java b/app/src/main/java/org/emulator/calculator/Serial.java
index ec88a4f..3abb1bf 100644
--- a/app/src/main/java/org/emulator/calculator/Serial.java
+++ b/app/src/main/java/org/emulator/calculator/Serial.java
@@ -26,7 +26,7 @@ import java.util.regex.Pattern;
public class Serial {
private static final String TAG = "Serial";
- private final boolean debug = true;
+ private final boolean debug = false;
private final Context context;
private final int serialPortId;
@@ -136,6 +136,7 @@ public class Serial {
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
if(debug) Log.d(TAG, "Request permission");
+ connectionStatus = "serial_connection_failed_user_has_not_given_permission";
return false;
}
if(usbConnection == null) {
diff --git a/app/src/main/java/org/emulator/forty/eight/MainActivity.java b/app/src/main/java/org/emulator/forty/eight/MainActivity.java
index cf11b96..c52df29 100644
--- a/app/src/main/java/org/emulator/forty/eight/MainActivity.java
+++ b/app/src/main/java/org/emulator/forty/eight/MainActivity.java
@@ -243,6 +243,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
try {
// FileOpen auto-open.
onFileOpen(documentToOpenUrl, intent, null);
+ } catch (SecurityException e) {
+ showAlert(getString(R.string.message_open_security_open_last_document), true);
+ if(debug && e.getMessage() != null) Log.e(TAG, e.getMessage());
} catch (Exception e) {
if(debug && e.getMessage() != null) Log.e(TAG, e.getMessage());
}
@@ -2045,10 +2048,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
serialIndex++;
return serialPortId;
} else {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(MainActivity.this, Utils.resId(MainActivity.this, "string", serial.getConnectionStatus()), Toast.LENGTH_LONG).show();
+ runOnUiThread(() -> {
+ String connectionStatus = serial.getConnectionStatus();
+ try {
+ int resId = Utils.resId(MainActivity.this, "string", connectionStatus);
+ Toast.makeText(MainActivity.this, resId, Toast.LENGTH_LONG).show();
+ } catch (Exception ex) {
+ Log.e(TAG, ex.getMessage());
+ Toast.makeText(MainActivity.this, "Unknown error, connectionStatus: " + connectionStatus, Toast.LENGTH_LONG).show();
}
});
return 0;
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bf616af..27bd4fd 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -90,6 +90,7 @@
Cannot load the Flash ROM. Reset to the default Flash ROM (from the current KML script). Please, try to load it again from the menu.
Permission Denied
+ Permission denied to open the last calculator state file.
For security reason, you must select the folder where are the KML and ROM files, please.
Please, open again
I hope now you could open again the state file.
diff --git a/build.gradle b/build.gradle
index 2a669de..f694bca 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.1'
+ classpath 'com.android.tools.build:gradle:4.1.3'
// NOTE: Do not place your application dependencies here; they belong