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