mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
Delay writing to the serial port to make the kermit protocol works (it slow down the transfer).
This commit is contained in:
parent
0be3e7dea6
commit
567bd3a12c
8 changed files with 71 additions and 9 deletions
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue