Delay writing to the serial port to make the kermit protocol works (it slow down the transfer).

This commit is contained in:
dgis 2021-05-09 15:40:08 +02:00
parent 0be3e7dea6
commit 567bd3a12c
8 changed files with 71 additions and 9 deletions

View file

@ -17,6 +17,7 @@ cmake_minimum_required(VERSION 3.4.1)
#add_compile_options(-DDEBUG_ANDROID_PAINT) #add_compile_options(-DDEBUG_ANDROID_PAINT)
#add_compile_options(-DDEBUG_ANDROID_THREAD) #add_compile_options(-DDEBUG_ANDROID_THREAD)
#add_compile_options(-DDEBUG_ANDROID_FILE) #add_compile_options(-DDEBUG_ANDROID_FILE)
#add_compile_options(-DDEBUG_ANDROID_SERIAL)
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE) #add_compile_options(-DNEW_WIN32_SOUND_ENGINE)

View file

@ -28,11 +28,11 @@ if (keystorePropertiesFile.exists()) {
} }
android { android {
compileSdkVersion 29 compileSdkVersion 30
defaultConfig { defaultConfig {
applicationId "org.emulator.forty.eight" applicationId "org.emulator.forty.eight"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 29 targetSdkVersion 30
versionCode 20 versionCode 20
versionName "2.2" versionName "2.2"
setProperty("archivesBaseName", "Emu48-v$versionName") setProperty("archivesBaseName", "Emu48-v$versionName")

View file

@ -143,6 +143,8 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
} }
pthread_mutex_unlock(&commsLock); pthread_mutex_unlock(&commsLock);
SERIAL_LOGD("CreateFile(lpFileName: \"%s\", ...) commId: %d, commIndex: %d", lpFileName, handle->commId, handle->commIndex);
return handle; return handle;
} else } else
return (HANDLE) INVALID_HANDLE_VALUE; return (HANDLE) INVALID_HANDLE_VALUE;
@ -279,6 +281,27 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
return (HANDLE) INVALID_HANDLE_VALUE; 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) { 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); FILE_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d)", hFile, lpBuffer, nNumberOfBytesToRead);
DWORD readByteCount = 0; DWORD readByteCount = 0;
@ -288,6 +311,11 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD
readByteCount = (DWORD) AAsset_read(hFile->fileAsset, lpBuffer, nNumberOfBytesToRead); readByteCount = (DWORD) AAsset_read(hFile->fileAsset, lpBuffer, nNumberOfBytesToRead);
} else if(hFile->handleType == HANDLE_TYPE_COM) { } else if(hFile->handleType == HANDLE_TYPE_COM) {
readByteCount = (DWORD) readSerialPort(hFile->commId, lpBuffer, nNumberOfBytesToRead); 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) if(lpNumberOfBytesRead)
*lpNumberOfBytesRead = readByteCount; *lpNumberOfBytesRead = readByteCount;
@ -302,7 +330,13 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,LPDWO
*lpNumberOfBytesWritten = (DWORD) writenByteCount; *lpNumberOfBytesWritten = (DWORD) writenByteCount;
return writenByteCount >= 0; return writenByteCount >= 0;
} else if(hFile->handleType == HANDLE_TYPE_COM) { } 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); 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)! commEvent(hFile->commId, EV_TXEMPTY); // Not sure about that (not the same thread)!
if(lpNumberOfBytesWritten) if(lpNumberOfBytesWritten)
*lpNumberOfBytesWritten = (DWORD) writenByteCount; *lpNumberOfBytesWritten = (DWORD) writenByteCount;
@ -785,7 +819,7 @@ BOOL WINAPI CloseHandle(HANDLE hObject) {
free(hObject); free(hObject);
return TRUE; return TRUE;
case HANDLE_TYPE_COM: { case HANDLE_TYPE_COM: {
FILE_LOGD("CloseHandle() HANDLE_TYPE_COM"); SERIAL_LOGD("CloseHandle(hObject: %p) for HANDLE_TYPE_COM", hObject);
closeSerialPort(hObject->commId); closeSerialPort(hObject->commId);
hObject->commId = 0; hObject->commId = 0;
@ -3043,6 +3077,8 @@ BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumb
// This is not a win32 API // This is not a win32 API
void commEvent(int commId, int eventMask) { void commEvent(int commId, int eventMask) {
SERIAL_LOGD("commEvent(commId: %d, eventMask: 0x%08x)", commId, eventMask);
HANDLE commHandleFound = NULL; HANDLE commHandleFound = NULL;
pthread_mutex_lock(&commsLock); pthread_mutex_lock(&commsLock);
for(int i = 0; i < MAX_CREATED_COMM; i++) { 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) { BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p)", hFile, lpEvtMask);
if(hFile && hFile->handleType == HANDLE_TYPE_COM) { if(hFile && hFile->handleType == HANDLE_TYPE_COM) {
SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject locking", hFile, lpEvtMask);
WaitForSingleObject(hFile->commEvent, INFINITE); WaitForSingleObject(hFile->commEvent, INFINITE);
SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject unlocked", hFile, lpEvtMask);
pthread_mutex_lock(&commsLock); pthread_mutex_lock(&commsLock);
if(lpEvtMask && hFile->commEventMask) { if(lpEvtMask && hFile->commEventMask) {
*lpEvtMask = hFile->commEventMask; //EV_RXCHAR | EV_TXEMPTY | EV_ERR *lpEvtMask = hFile->commEventMask; //EV_RXCHAR | EV_TXEMPTY | EV_ERR
@ -3073,18 +3112,22 @@ BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
return FALSE; return FALSE;
} }
BOOL ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) { BOOL ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
SERIAL_LOGD("ClearCommError(hFile: %p, lpErrors: %p, lpStat: %p) TODO", hFile, lpErrors, lpStat);
//TODO //TODO
return FALSE; return FALSE;
} }
BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
SERIAL_LOGD("SetCommTimeouts(hFile: %p, lpCommTimeouts: %p) TODO", hFile, lpCommTimeouts);
//TODO //TODO
return FALSE; return FALSE;
} }
BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) { BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) {
SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) TODO", hFile, dwEvtMask);
//TODO //TODO
if(hFile && hFile->handleType == HANDLE_TYPE_COM) { if(hFile && hFile->handleType == HANDLE_TYPE_COM) {
if(dwEvtMask == 0) { if(dwEvtMask == 0) {
// When 0, clear all events and force WaitCommEvent to return. // 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); SetEvent(hFile->commEvent);
return TRUE; return TRUE;
} }
@ -3092,6 +3135,7 @@ BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) {
return FALSE; return FALSE;
} }
BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) { BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) {
SERIAL_LOGD("SetCommState(hFile: %p, lpDCB: %p)", hFile, lpDCB);
if(hFile && hFile->handleType == HANDLE_TYPE_COM && lpDCB) { if(hFile && hFile->handleType == HANDLE_TYPE_COM && lpDCB) {
int result = setSerialPortParameters(hFile->commId, lpDCB->BaudRate); //TODO 2 stop bits? int result = setSerialPortParameters(hFile->commId, lpDCB->BaudRate); //TODO 2 stop bits?
if(result > 0) { if(result > 0) {
@ -3105,15 +3149,18 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) {
return FALSE; return FALSE;
} }
BOOL PurgeComm(HANDLE hFile, DWORD dwFlags) { BOOL PurgeComm(HANDLE hFile, DWORD dwFlags) {
SERIAL_LOGD("SetCommState(hFile: %p, dwFlags: 0x%08X) TODO", hFile, dwFlags);
//TODO //TODO
return FALSE; return FALSE;
} }
BOOL SetCommBreak(HANDLE hFile) { BOOL SetCommBreak(HANDLE hFile) {
SERIAL_LOGD("SetCommBreak(hFile: %p)", hFile);
if(hFile && hFile->handleType == HANDLE_TYPE_COM) if(hFile && hFile->handleType == HANDLE_TYPE_COM)
return serialPortSetBreak(hFile->commId); return serialPortSetBreak(hFile->commId);
return FALSE; return FALSE;
} }
BOOL ClearCommBreak(HANDLE hFile) { BOOL ClearCommBreak(HANDLE hFile) {
SERIAL_LOGD("ClearCommBreak(hFile: %p)", hFile);
if(hFile && hFile->handleType == HANDLE_TYPE_COM) if(hFile && hFile->handleType == HANDLE_TYPE_COM)
return serialPortClearBreak(hFile->commId); return serialPortClearBreak(hFile->commId);
return FALSE; return FALSE;

View file

@ -59,6 +59,11 @@
# define FILE_LOGD(...) # define FILE_LOGD(...)
#endif #endif
#if defined DEBUG_ANDROID_SERIAL
# define SERIAL_LOGD(...) LOGD(__VA_ARGS__)
#else
# define SERIAL_LOGD(...)
#endif
#define _MSC_VER 1914 #define _MSC_VER 1914
#define GetWindowLongPtr GetWindowLong #define GetWindowLongPtr GetWindowLong

View file

@ -26,7 +26,7 @@ import java.util.regex.Pattern;
public class Serial { public class Serial {
private static final String TAG = "Serial"; private static final String TAG = "Serial";
private final boolean debug = true; private final boolean debug = false;
private final Context context; private final Context context;
private final int serialPortId; private final int serialPortId;
@ -136,6 +136,7 @@ public class Serial {
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(INTENT_ACTION_GRANT_USB), 0); PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
usbManager.requestPermission(driver.getDevice(), usbPermissionIntent); usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
if(debug) Log.d(TAG, "Request permission"); if(debug) Log.d(TAG, "Request permission");
connectionStatus = "serial_connection_failed_user_has_not_given_permission";
return false; return false;
} }
if(usbConnection == null) { if(usbConnection == null) {

View file

@ -243,6 +243,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
try { try {
// FileOpen auto-open. // FileOpen auto-open.
onFileOpen(documentToOpenUrl, intent, null); 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) { } catch (Exception e) {
if(debug && e.getMessage() != null) Log.e(TAG, e.getMessage()); if(debug && e.getMessage() != null) Log.e(TAG, e.getMessage());
} }
@ -2045,10 +2048,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
serialIndex++; serialIndex++;
return serialPortId; return serialPortId;
} else { } else {
runOnUiThread(new Runnable() { runOnUiThread(() -> {
@Override String connectionStatus = serial.getConnectionStatus();
public void run() { try {
Toast.makeText(MainActivity.this, Utils.resId(MainActivity.this, "string", serial.getConnectionStatus()), Toast.LENGTH_LONG).show(); 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; return 0;

View file

@ -90,6 +90,7 @@
<string name="alert_load_flash_rom_error_message">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.</string> <string name="alert_load_flash_rom_error_message">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.</string>
<string name="message_open_security">Permission Denied</string> <string name="message_open_security">Permission Denied</string>
<string name="message_open_security_open_last_document">Permission denied to open the last calculator state file.</string>
<string name="message_open_security_description">For security reason, you must select the folder where are the KML and ROM files, please.</string> <string name="message_open_security_description">For security reason, you must select the folder where are the KML and ROM files, please.</string>
<string name="message_open_security_retry">Please, open again</string> <string name="message_open_security_retry">Please, open again</string>
<string name="message_open_security_retry_description">I hope now you could open again the state file.</string> <string name="message_open_security_retry_description">I hope now you could open again the state file.</string>

View file

@ -7,7 +7,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { 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 // NOTE: Do not place your application dependencies here; they belong