Added buffered writes as well as non-native unbuffered reads.
Change-Id: I3577746ed8215844e02601608f4a9173d1639aa1
# Visual Studio 2013\r
VisualStudioVersion = 12.0.31101.0\r
MinimumVisualStudioVersion = 10.0.40219.1\r
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serial", "serial\serial.vcxproj", "{2E2DB53A-62BE-4690-8FCB-209885DD9B3C}"\r
-EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winreg", "winreg\winreg.vcxproj", "{4CA57EA3-42F2-4CC1-8E95-5C707A8E7363}"\r
EndProject\r
Global\r
Release|x64 = Release|x64\r
EndGlobalSection\r
GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Debug|Mixed Platforms.Build.0 = Debug|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Debug|Win32.ActiveCfg = Debug|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Debug|Win32.Build.0 = Debug|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Debug|x64.ActiveCfg = Debug|x64\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Debug|x64.Build.0 = Debug|x64\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Release|Mixed Platforms.ActiveCfg = Release|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Release|Mixed Platforms.Build.0 = Release|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Release|Win32.ActiveCfg = Release|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Release|Win32.Build.0 = Release|Win32\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Release|x64.ActiveCfg = Release|x64\r
- {2E2DB53A-62BE-4690-8FCB-209885DD9B3C}.Release|x64.Build.0 = Release|x64\r
{4CA57EA3-42F2-4CC1-8E95-5C707A8E7363}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32\r
{4CA57EA3-42F2-4CC1-8E95-5C707A8E7363}.Debug|Mixed Platforms.Build.0 = Debug|Win32\r
{4CA57EA3-42F2-4CC1-8E95-5C707A8E7363}.Debug|Win32.ActiveCfg = Debug|Win32\r
+++ /dev/null
-/serial.tlog/
-/serial.vcxproj.user
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2015 QNX Software Systems and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * QNX Software Systems - Initial API and implementation\r
- *******************************************************************************/\r
-#include "stdafx.h"\r
-\r
-BOOL APIENTRY DllMain( HMODULE hModule,\r
- DWORD ul_reason_for_call,\r
- LPVOID lpReserved\r
- )\r
-{\r
- switch (ul_reason_for_call)\r
- {\r
- case DLL_PROCESS_ATTACH:\r
- case DLL_THREAD_ATTACH:\r
- case DLL_THREAD_DETACH:\r
- case DLL_PROCESS_DETACH:\r
- break;\r
- }\r
- return TRUE;\r
-}\r
-\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2015 QNX Software Systems and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * QNX Software Systems - Initial API and implementation\r
- *******************************************************************************/\r
-#include "stdafx.h"\r
-\r
-extern "C"\r
-JNIEXPORT jlong JNICALL Java_org_eclipse_cdt_utils_serial_SerialPort_open0\r
-(JNIEnv *env, jobject jobj, jstring portName, jint baudRate, jint byteSize, jint parity, jint stopBits)\r
-{\r
- const wchar_t * cportName = (const wchar_t *) env->GetStringChars(portName, NULL);\r
- HANDLE handle = CreateFile(cportName,\r
- GENERIC_READ | GENERIC_WRITE,\r
- 0,\r
- NULL,\r
- OPEN_EXISTING,\r
- FILE_FLAG_OVERLAPPED,\r
- NULL);\r
-\r
- if (handle != INVALID_HANDLE_VALUE) {\r
- DCB dcb = { 0 };\r
-\r
- if (!GetCommState(handle, &dcb)) {\r
- fprintf(stderr, "Error getting DCB: %S\n", cportName);\r
- return -1;\r
- }\r
-\r
- dcb.BaudRate = baudRate;\r
- dcb.ByteSize = (BYTE) byteSize;\r
-\r
- switch (parity) {\r
- case 0: // None\r
- dcb.fParity = FALSE;\r
- break;\r
- case 1: // Even\r
- dcb.fParity = TRUE;\r
- dcb.Parity = EVENPARITY;\r
- break;\r
- case 2: // Odd\r
- dcb.fParity = TRUE;\r
- dcb.Parity = ODDPARITY;\r
- break;\r
- }\r
- \r
- switch (stopBits) {\r
- case 0:\r
- dcb.StopBits = ONESTOPBIT;\r
- break;\r
- case 1:\r
- dcb.StopBits = TWOSTOPBITS;\r
- break;\r
- }\r
-\r
- if (!SetCommState(handle, &dcb)) {\r
- fprintf(stderr, "Error setting DCB: %S\n", cportName);\r
- return -1;\r
- }\r
- }\r
-\r
- return (jlong) handle;\r
-}\r
-\r
-extern "C"\r
-JNIEXPORT void JNICALL Java_org_eclipse_cdt_utils_serial_SerialPort_close0\r
-(JNIEnv *env, jobject jobj, jlong handle)\r
-{\r
- CloseHandle((HANDLE) handle);\r
-}\r
-\r
-extern "C"\r
-JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_serial_SerialPort_read0\r
-(JNIEnv *env, jobject jobj, jlong jhandle)\r
-{\r
- OVERLAPPED olp = { 0 };\r
-\r
- olp.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
- if (olp.hEvent == NULL) {\r
- fprintf(stderr, "Error creating event\n");\r
- fflush(stderr);\r
- return -1;\r
- }\r
-\r
- char buff;\r
- DWORD nwritten;\r
- HANDLE handle = (HANDLE)jhandle;\r
-\r
- if (!ReadFile(handle, &buff, sizeof(buff), &nwritten, &olp)) {\r
- if (GetLastError() != ERROR_IO_PENDING) {\r
- fprintf(stderr, "Error reading from port: %d\n", GetLastError());\r
- fflush(stderr);\r
- return -1;\r
- }\r
- else {\r
- switch (WaitForSingleObject(olp.hEvent, INFINITE)) {\r
- case WAIT_OBJECT_0:\r
- if (!GetOverlappedResult(handle, &olp, &nwritten, FALSE)) {\r
- if (GetLastError() != ERROR_OPERATION_ABORTED) {\r
- fprintf(stderr, "Error waiting for read: %d\n", GetLastError());\r
- fflush(stderr);\r
- }\r
- return -1;\r
- }\r
- break;\r
- }\r
- }\r
- }\r
-\r
- CloseHandle(olp.hEvent);\r
- return buff;\r
-}\r
-\r
-extern "C"\r
-JNIEXPORT void JNICALL Java_org_eclipse_cdt_utils_serial_SerialPort_write0\r
-(JNIEnv *env, jobject jobj, jlong jhandle, jint b)\r
-{\r
- OVERLAPPED olp = { 0 };\r
-\r
- olp.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
- if (olp.hEvent == NULL) {\r
- fprintf(stderr, "Error creating event\n");\r
- return;\r
- }\r
-\r
- char buff = (char) b;\r
- DWORD nwritten;\r
- HANDLE handle = (HANDLE) jhandle;\r
-\r
- if (!WriteFile(handle, &buff, sizeof(buff), &nwritten, &olp)) {\r
- if (GetLastError() != ERROR_IO_PENDING) {\r
- fprintf(stderr, "Error writing to port\n");\r
- }\r
- else {\r
- switch (WaitForSingleObject(olp.hEvent, INFINITE)) {\r
- case WAIT_OBJECT_0:\r
- if (!GetOverlappedResult(handle, &olp, &nwritten, FALSE)) {\r
- fprintf(stderr, "Error waiting for write\n");\r
- }\r
- }\r
- }\r
- }\r
-\r
- CloseHandle(olp.hEvent);\r
-}\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2015 QNX Software Systems and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * QNX Software Systems - Initial API and implementation\r
- *******************************************************************************/\r
-#include "stdafx.h"\r
-\r
-// TODO: reference any additional headers you need in STDAFX.H\r
-// and not in this file\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2015 QNX Software Systems and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * QNX Software Systems - Initial API and implementation\r
- *******************************************************************************/\r
-#pragma once\r
-\r
-#include "targetver.h"\r
-\r
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\r
-// Windows Header Files:\r
-#include <windows.h>\r
-#include <jni.h>\r
-\r
-\r
-\r
-// TODO: reference additional headers your program requires here\r
+++ /dev/null
-/*******************************************************************************\r
- * Copyright (c) 2015 QNX Software Systems and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * QNX Software Systems - Initial API and implementation\r
- *******************************************************************************/\r
-#pragma once\r
-\r
-// Including SDKDDKVer.h defines the highest available Windows platform.\r
-\r
-// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and\r
-// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.\r
-\r
-#include <SDKDDKVer.h>\r
# Alex Blewitt - MacOSX with a 64-bit vm
#*******************************************************************************/
-JAVA_HOME = $(shell echo /Library/Java/JavaVirtualMachines/jdk1.8.0_*.jdk/Contents/Home)
UNAME = $(shell uname)
# Defaults which can be overridden.
ifeq ($(UNAME),Darwin)
+JAVA_HOME = $(shell echo /Library/Java/JavaVirtualMachines/jdk1.8.0_*.jdk/Contents/Home)
OS = macosx
+JNI_OS = darwin
ARCHS = x86_64
+ARCH_FLAG_X86 = -arch i386
+ARCH_FLAG_X86_64 = -arch x86_64
+LDFLAGS = -dynamiclib
+LIBEXT = jnilib
+else
+ifeq ($(UNAME),Linux)
+JAVA_HOME = /usr/lib/jvm/java-8-oracle
+OS = linux
+JNI_OS = linux
+ARCHS = x86 x86_64
+ARCH_FLAG_X86 = -m32
+ARCH_FLAG_X86_64 = -m64
+LDFLAGS = -shared
+LIBEXT = so
+endif
endif
ARCH_X86 = x86
CC=gcc
LD=libtool
-CPPFLAGS = -I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/darwin
+CPPFLAGS = -I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(JNI_OS)
CFLAGS +=-fPIC -D_REENTRANT
-ARCH_FLAG_X86 = -arch i386
-ARCH_FLAG_X86_64 = -arch x86_64
-
INSTALL_DIR_X86 = ../../os/$(OS)/$(ARCH_X86)
INSTALL_DIR_X86_64 = ../../os/$(OS)/$(ARCH_X86_64)
-LIB_NAME_FULL_SERIAL_X86 = $(INSTALL_DIR_X86)/libserial.jnilib
-LIB_NAME_FULL_SERIAL_X86_64 = $(INSTALL_DIR_X86_64)/libserial.jnilib
+LIB_NAME_FULL_SERIAL_X86 = $(INSTALL_DIR_X86)/libserial.$(LIBEXT)
+LIB_NAME_FULL_SERIAL_X86_64 = $(INSTALL_DIR_X86_64)/libserial.$(LIBEXT)
OBJS_SERIAL_X86 = serial_$(ARCH_X86).o
OBJS_SERIAL_X86_64 = serial_$(ARCH_X86_64).o
$(LIB_NAME_FULL_SERIAL_X86): $(OBJS_SERIAL_X86)
mkdir -p $(INSTALL_DIR_X86)
- $(CC) -dynamiclib $(ARCH_FLAG_X86) -o $(LIB_NAME_FULL_SERIAL_X86) $(OBJS_SERIAL_X86) -lc -framework JavaVM
+ $(CC) $(LDFLAGS) $(ARCH_FLAG_X86) -o $(LIB_NAME_FULL_SERIAL_X86) $(OBJS_SERIAL_X86)
$(LIB_NAME_FULL_SERIAL_X86_64): $(OBJS_SERIAL_X86_64)
mkdir -p $(INSTALL_DIR_X86_64)
- $(CC) -dynamiclib $(ARCH_FLAG_X86_64) -o $(LIB_NAME_FULL_SERIAL_X86_64) $(OBJS_SERIAL_X86_64) -lc -framework JavaVM
+ $(CC) $(LDFLAGS) $(ARCH_FLAG_X86_64) -o $(LIB_NAME_FULL_SERIAL_X86_64) $(OBJS_SERIAL_X86_64)
serial_$(ARCH_X86).o: serial.c
$(CC) $(CFLAGS) $(ARCH_FLAG_X86) $(CPPFLAGS) -c -o $@ serial.c
* Contributors:
* QNX Software Systems - initial API and implementation
*******************************************************************************/
+#ifdef __APPLE__
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
+#endif
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
const char * cportName = (*env)->GetStringUTFChars(env, portName, NULL);
int fd = open(cportName, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
+ perror(cportName);
return fd;
}
options.c_iflag |= IGNPAR;
options.c_cc[VMIN] = 0; // min chars to read
- options.c_cc[VTIME] = 10; // 10ths second timeout
+ options.c_cc[VTIME] = 2; // 10ths second timeout
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
}
JNIEXPORT void JNICALL FUNC(close0)(JNIEnv *env, jobject jobj, jlong handle)
- {
+{
close(handle);
- }
-
-JNIEXPORT jint JNICALL FUNC(read0)(JNIEnv *env, jobject jobj, jlong handle)
- {
- char buff;
- int res = read(handle, &buff, 1);
- return res < 0 ? -1 : buff;
- }
+}
-JNIEXPORT jint JNICALL FUNC(read1)(JNIEnv * env, jobject jobj, jlong handle, jbyteArray bytes, jint offset, jint size) {
+JNIEXPORT jint JNICALL FUNC(read1)(JNIEnv * env, jobject jobj, jlong handle, jbyteArray bytes, jint offset, jint size)
+{
jbyte buff[256];
int n = size < sizeof(buff) ? size : sizeof(buff);
n = read(handle, buff, n);
}
JNIEXPORT void JNICALL FUNC(write0)(JNIEnv *env, jobject jobj, jlong handle, jint b)
- {
+{
char buff = b;
write(handle, &buff, 1);
+}
+
+JNIEXPORT void JNICALL FUNC(write1)(JNIEnv *env, jobject jobj, jlong handle, jbyteArray bytes, jint offset, jint size)
+{
+ while (size > 0) {
+ jbyte buff[256];
+ int n = size < sizeof(buff) ? size : sizeof(buff);
+ (*env)->GetByteArrayRegion(env, bytes, offset, n, buff);
+ n = write(handle, buff, n);
+ if (n < 0) {
+ return;
}
+ size -= n;
+ offset += n;
+ }
+}
--- /dev/null
+/ipch/
+/Release/
+/x64/
+/serial.opensdf
+/serial.sdf
+/serial.v12.suo
--- /dev/null
+// dllmain.cpp : Defines the entry point for the DLL application.\r
+#include "stdafx.h"\r
+\r
+BOOL APIENTRY DllMain( HMODULE hModule,\r
+ DWORD ul_reason_for_call,\r
+ LPVOID lpReserved\r
+ )\r
+{\r
+ switch (ul_reason_for_call)\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+ case DLL_THREAD_ATTACH:\r
+ case DLL_THREAD_DETACH:\r
+ case DLL_PROCESS_DETACH:\r
+ break;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
--- /dev/null
+/*******************************************************************************\r
+* Copyright (c) 2015 QNX Software Systems and others.\r
+* All rights reserved. This program and the accompanying materials\r
+* are made available under the terms of the Eclipse Public License v1.0\r
+* which accompanies this distribution, and is available at\r
+* http://www.eclipse.org/legal/epl-v10.html\r
+*\r
+* Contributors:\r
+* QNX Software Systems - Initial API and implementation\r
+*******************************************************************************/\r
+#include "stdafx.h"\r
+\r
+#define FUNC(x) Java_org_eclipse_cdt_serial_SerialPort_ ## x\r
+\r
+static void throwIOException(JNIEnv *env, char *msg) {\r
+ char buff[256];\r
+ sprintf_s(buff, sizeof(buff), "%s: %d", msg, GetLastError());\r
+ jclass cls = env->FindClass("java/io/IOException");\r
+ env->ThrowNew(cls, buff);\r
+}\r
+\r
+extern "C"\r
+JNIEXPORT jlong JNICALL FUNC(open0)(JNIEnv *env, jobject jobj, jstring portName, jint baudRate, jint byteSize, jint parity, jint stopBits)\r
+{\r
+ const wchar_t * cportName = (const wchar_t *)env->GetStringChars(portName, NULL);\r
+ HANDLE handle = CreateFile(cportName,\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ 0,\r
+ NULL,\r
+ OPEN_EXISTING,\r
+ FILE_FLAG_OVERLAPPED,\r
+ NULL);\r
+\r
+ if (handle == INVALID_HANDLE_VALUE) {\r
+ throwIOException(env, "Error opening serial port");\r
+ return -1;\r
+ }\r
+ \r
+ DCB dcb = { 0 };\r
+\r
+ if (!GetCommState(handle, &dcb)) {\r
+ throwIOException(env, "Error getting DCB");\r
+ return -1;\r
+ }\r
+\r
+ dcb.BaudRate = baudRate;\r
+ dcb.ByteSize = (BYTE)byteSize;\r
+\r
+ switch (parity) {\r
+ case 0: // None\r
+ dcb.fParity = FALSE;\r
+ break;\r
+ case 1: // Even\r
+ dcb.fParity = TRUE;\r
+ dcb.Parity = EVENPARITY;\r
+ break;\r
+ case 2: // Odd\r
+ dcb.fParity = TRUE;\r
+ dcb.Parity = ODDPARITY;\r
+ break;\r
+ }\r
+\r
+ switch (stopBits) {\r
+ case 0:\r
+ dcb.StopBits = ONESTOPBIT;\r
+ break;\r
+ case 1:\r
+ dcb.StopBits = TWOSTOPBITS;\r
+ break;\r
+ }\r
+\r
+ if (!SetCommState(handle, &dcb)) {\r
+ throwIOException(env, "Error setting DCB");\r
+ return -1;\r
+ }\r
+\r
+ COMMTIMEOUTS timeouts = { 0 };\r
+ timeouts.ReadIntervalTimeout = MAXDWORD;\r
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;\r
+ timeouts.ReadTotalTimeoutConstant = 200;\r
+ if (!SetCommTimeouts(handle, &timeouts)) {\r
+ throwIOException(env, "Error setting timeouts");\r
+ return -1;\r
+ }\r
+\r
+ return (jlong)handle;\r
+}\r
+\r
+extern "C"\r
+JNIEXPORT void JNICALL FUNC(close0)(JNIEnv *env, jobject jobj, jlong handle)\r
+{\r
+ CloseHandle((HANDLE)handle);\r
+}\r
+\r
+extern "C"\r
+JNIEXPORT jint JNICALL FUNC(read1)(JNIEnv * env, jobject jobj, jlong jhandle, jbyteArray bytes, jint offset, jint size)\r
+{\r
+ OVERLAPPED olp = { 0 };\r
+\r
+ olp.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+ if (olp.hEvent == NULL) {\r
+ throwIOException(env, "Error creating event");\r
+ return -1;\r
+ }\r
+\r
+ char buff[256];\r
+ DWORD nread = sizeof(buff) < size ? sizeof(buff) : size;\r
+ HANDLE handle = (HANDLE)jhandle;\r
+\r
+ if (!ReadFile(handle, buff, sizeof(buff), &nread, &olp)) {\r
+ if (GetLastError() != ERROR_IO_PENDING) {\r
+ throwIOException(env, "Error reading from port");\r
+ CloseHandle(olp.hEvent);\r
+ return -1;\r
+ }\r
+ else {\r
+ switch (WaitForSingleObject(olp.hEvent, INFINITE)) {\r
+ case WAIT_OBJECT_0:\r
+ if (!GetOverlappedResult(handle, &olp, &nread, FALSE)) {\r
+ if (GetLastError() != ERROR_OPERATION_ABORTED) {\r
+ throwIOException(env, "Error waiting for read");\r
+ }\r
+ CloseHandle(olp.hEvent);\r
+ return -1;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (nread > 0) {\r
+ env->SetByteArrayRegion(bytes, offset, nread, (jbyte *)buff);\r
+ }\r
+ CloseHandle(olp.hEvent);\r
+ return nread;\r
+}\r
+\r
+extern "C"\r
+JNIEXPORT void JNICALL FUNC(write0)(JNIEnv *env, jobject jobj, jlong jhandle, jint b)\r
+{\r
+ OVERLAPPED olp = { 0 };\r
+\r
+ olp.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+ if (olp.hEvent == NULL) {\r
+ throwIOException(env, "Error creating event");\r
+ return;\r
+ }\r
+\r
+ char buff = (char)b;\r
+ DWORD nwritten;\r
+ HANDLE handle = (HANDLE)jhandle;\r
+\r
+ if (!WriteFile(handle, &buff, sizeof(buff), &nwritten, &olp)) {\r
+ if (GetLastError() != ERROR_IO_PENDING) {\r
+ throwIOException(env, "Error writing to port");\r
+ }\r
+ else {\r
+ switch (WaitForSingleObject(olp.hEvent, INFINITE)) {\r
+ case WAIT_OBJECT_0:\r
+ if (!GetOverlappedResult(handle, &olp, &nwritten, FALSE)) {\r
+ throwIOException(env, "Error waiting for write");\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ CloseHandle(olp.hEvent);\r
+}\r
+\r
+extern "C"\r
+JNIEXPORT void JNICALL FUNC(write1)(JNIEnv *env, jobject jobj, jlong jhandle, jbyteArray bytes, jint offset, jint size)\r
+{\r
+ OVERLAPPED olp = { 0 };\r
+\r
+ olp.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+ if (olp.hEvent == NULL) {\r
+ throwIOException(env, "Error creating event");\r
+ return;\r
+ }\r
+\r
+ while (size > 0) {\r
+ char buff[256];\r
+ DWORD nwritten = sizeof(buff) < size ? sizeof(buff) : size;\r
+ env->GetByteArrayRegion(bytes, offset, nwritten, (jbyte *)buff);\r
+ HANDLE handle = (HANDLE)jhandle;\r
+\r
+ if (!WriteFile(handle, buff, nwritten, &nwritten, &olp)) {\r
+ if (GetLastError() != ERROR_IO_PENDING) {\r
+ throwIOException(env, "Error writing to port");\r
+ return;\r
+ }\r
+ else {\r
+ switch (WaitForSingleObject(olp.hEvent, INFINITE)) {\r
+ case WAIT_OBJECT_0:\r
+ if (!GetOverlappedResult(handle, &olp, &nwritten, FALSE)) {\r
+ throwIOException(env, "Error waiting for write");\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ size -= nwritten;\r
+ offset += nwritten;\r
+ }\r
+\r
+ CloseHandle(olp.hEvent);\r
+}\r
+\r
+extern "C"\r
+JNIEXPORT jstring FUNC(getPortName)(JNIEnv *env, jclass cls, jint i)\r
+{\r
+ HKEY key;\r
+\r
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ, &key) != ERROR_SUCCESS) {\r
+ throwIOException(env, "Can not find registry key");\r
+ return NULL;\r
+ }\r
+\r
+ wchar_t name[256];\r
+ DWORD len = sizeof(name);\r
+ LONG rc = RegEnumValue(key, (DWORD)i, name, &len, NULL, NULL, NULL, NULL);\r
+ if (rc != ERROR_SUCCESS) {\r
+ if (rc != ERROR_NO_MORE_ITEMS) {\r
+ throwIOException(env, "Can not enum value");\r
+ }\r
+ RegCloseKey(key);\r
+ return NULL;\r
+ }\r
+\r
+ wchar_t value[256];\r
+ DWORD type;\r
+ len = sizeof(value);\r
+ if (RegQueryValueEx(key, name, NULL, &type, (BYTE *)value, &len) != ERROR_SUCCESS) {\r
+ throwIOException(env, "Can not query value");\r
+ RegCloseKey(key);\r
+ return NULL;\r
+ }\r
+\r
+ jstring result = env->NewString((jchar *)value, (jsize) wcslen(value));\r
+ RegCloseKey(key);\r
+ return result;\r
+}\r
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 2013\r
+VisualStudioVersion = 12.0.31101.0\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "serial", "serial.vcxproj", "{48ED88D3-77CF-4E77-9554-10719E633142}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|Win32 = Debug|Win32\r
+ Debug|x64 = Debug|x64\r
+ Release|Win32 = Release|Win32\r
+ Release|x64 = Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Debug|Win32.Build.0 = Debug|Win32\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Debug|x64.ActiveCfg = Debug|x64\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Debug|x64.Build.0 = Debug|x64\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Release|Win32.ActiveCfg = Release|Win32\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Release|Win32.Build.0 = Release|Win32\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Release|x64.ActiveCfg = Release|x64\r
+ {48ED88D3-77CF-4E77-9554-10719E633142}.Release|x64.Build.0 = Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
</ProjectConfiguration>\r
</ItemGroup>\r
<PropertyGroup Label="Globals">\r
- <ProjectGuid>{2E2DB53A-62BE-4690-8FCB-209885DD9B3C}</ProjectGuid>\r
+ <ProjectGuid>{48ED88D3-77CF-4E77-9554-10719E633142}</ProjectGuid>\r
<Keyword>Win32Proj</Keyword>\r
<RootNamespace>serial</RootNamespace>\r
</PropertyGroup>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
<LinkIncremental>false</LinkIncremental>\r
- <OutDir>$(SolutionDir)..\..\org.eclipse.cdt.core.win32.x86\os\win32\x86\</OutDir>\r
- <IntDir />\r
+ <OutDir>$(SolutionDir)..\..\..\os\win32\x86\</OutDir>\r
</PropertyGroup>\r
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
<LinkIncremental>false</LinkIncremental>\r
- <OutDir>$(SolutionDir)..\..\org.eclipse.cdt.core.win32.x86_64\os\win32\x86_64\</OutDir>\r
- <IntDir />\r
+ <OutDir>$(SolutionDir)..\..\..\os\win32\x86_64\</OutDir>\r
</PropertyGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
<ClCompile>\r
<WarningLevel>Level3</WarningLevel>\r
<Optimization>Disabled</Optimization>\r
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SERIAL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
- <SDLCheck>true</SDLCheck>\r
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
</ClCompile>\r
<Link>\r
<SubSystem>Windows</SubSystem>\r
<WarningLevel>Level3</WarningLevel>\r
<Optimization>Disabled</Optimization>\r
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SERIAL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
- <SDLCheck>true</SDLCheck>\r
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
</ClCompile>\r
<Link>\r
<SubSystem>Windows</SubSystem>\r
<FunctionLevelLinking>true</FunctionLevelLinking>\r
<IntrinsicFunctions>true</IntrinsicFunctions>\r
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SERIAL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
- <SDLCheck>true</SDLCheck>\r
- <AdditionalIncludeDirectories>C:\Program Files\Java\jdk1.8.0_31\include;C:\Program Files\Java\jdk1.8.0_31\include\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ <AdditionalIncludeDirectories>C:\Program Files\Java\jdk1.8.0_31\include\win32;C:\Program Files\Java\jdk1.8.0_31\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
</ClCompile>\r
<Link>\r
<FunctionLevelLinking>true</FunctionLevelLinking>\r
<IntrinsicFunctions>true</IntrinsicFunctions>\r
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SERIAL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
- <AdditionalIncludeDirectories>C:\Program Files\Java\jdk1.8.0_31\include;C:\Program Files\Java\jdk1.8.0_31\include\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+ <AdditionalIncludeDirectories>C:\Program Files\Java\jdk1.8.0_31\include\win32;C:\Program Files\Java\jdk1.8.0_31\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
</ClCompile>\r
<Link>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
+ <Text Include="ReadMe.txt" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
<ClInclude Include="stdafx.h" />\r
<ClInclude Include="targetver.h" />\r
</ItemGroup>\r
</Filter>\r
</ItemGroup>\r
<ItemGroup>\r
+ <Text Include="ReadMe.txt" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
<ClInclude Include="stdafx.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
--- /dev/null
+// stdafx.cpp : source file that includes just the standard includes\r
+// serial.pch will be the pre-compiled header\r
+// stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
--- /dev/null
+// stdafx.h : include file for standard system include files,\r
+// or project specific include files that are used frequently, but\r
+// are changed infrequently\r
+//\r
+\r
+#pragma once\r
+\r
+#include "targetver.h"\r
+\r
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\r
+// Windows Header Files:\r
+#include <windows.h>\r
+\r
+\r
+\r
+// TODO: reference additional headers your program requires here\r
+#include <jni.h>\r
--- /dev/null
+#pragma once\r
+\r
+// Including SDKDDKVer.h defines the highest available Windows platform.\r
+\r
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and\r
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.\r
+\r
+#include <SDKDDKVer.h>\r
--- /dev/null
+/serial.exp
+/serial.lib
+/serial.pdb
--- /dev/null
+/serial.exp
+/serial.lib
+/serial.pdb
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
import java.util.regex.Pattern;
import org.eclipse.cdt.serial.internal.Messages;
private StopBits stopBits = StopBits.S1;
private long handle;
- private static final String SERIAL_KEY = "HARDWARE\\DEVICEMAP\\SERIALCOMM"; //$NON-NLS-1$
private static final String PORT_OPEN = Messages.getString("SerialPort.PortIsOpen"); //$NON-NLS-1$
static {
}
private InputStream inputStream = new InputStream() {
+ private byte[] rbuff = new byte[256];
+ private int rpos = 0;
+ private int rlen = 0;
+
@Override
public int read() throws IOException {
if (isOpen()) {
- return read0(handle);
+ if (rpos >= rlen) {
+ while (true) {
+ rlen = read1(handle, rbuff, 0, rbuff.length);
+ if (rlen < 0) {
+ return -1;
+ } else if (rlen > 0) {
+ break;
+ }
+ }
+ }
+ return rbuff[rpos++];
} else {
return -1;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (isOpen()) {
- return read1(handle, b, off, len);
+ int n = rlen - rpos;
+ if (n > 0) {
+ if (len < n) {
+ n = len;
+ }
+ System.arraycopy(rbuff, rpos, b, off, n);
+ rpos += n;
+ return n;
+ } else {
+ return read1(handle, b, off, len);
+ }
} else {
return -1;
}
}
@Override
+ public void write(byte[] buff, int off, int len) throws IOException {
+ if (isOpen()) {
+ write1(handle, buff, off, len);
+ }
+ }
+
+ @Override
public void close() throws IOException {
SerialPort.this.close();
}
this.portName = portName;
}
+ private native long open0(String portName, int baudRate, int byteSize, int parity, int stopBits) throws IOException;
+
+ private native void close0(long handle) throws IOException;
+
+ private native int read1(long handle, byte[] b, int off, int len) throws IOException;
+
+ private native void write0(long handle, int b) throws IOException;
+
+ private native void write1(long handle, byte[] b, int off, int len) throws IOException;
+
+ private static native String getPortName(int i) throws IOException;
+
+ private static String[] listDevs(final Pattern pattern) {
+ File dev = new File("/dev"); //$NON-NLS-1$
+ File[] files = dev.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return pattern.matcher(name).matches();
+ }
+ });
+
+ if (files == null) {
+ return new String[0];
+ }
+
+ String[] names = new String[files.length];
+ for (int i = 0; i < files.length; i++) {
+ names[i] = files[i].getAbsolutePath();
+ }
+ return names;
+ }
+
/**
* List the available serial ports.
*
* @return serial ports
*/
- public static String[] list() {
- if (System.getProperty("os.name").equals("Mac OS X")) { //$NON-NLS-1$//$NON-NLS-2$
- File dev = new File("/dev"); //$NON-NLS-1$
- final Pattern pattern = Pattern.compile("tty\\.(usbserial|usbmodem).*"); //$NON-NLS-1$
- File[] files = dev.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return pattern.matcher(name).matches();
- }
- });
-
- if (files == null) {
- return new String[0];
+ public static String[] list() throws IOException {
+ String osName = System.getProperty("os.name"); //$NON-NLS-1$
+ if (osName.equals("Mac OS X")) { //$NON-NLS-1$
+ return listDevs(Pattern.compile("tty\\.(usbserial|usbmodem).*")); //$NON-NLS-1$
+ } else if (osName.equals("Linux")) { //$NON-NLS-1$
+ return listDevs(Pattern.compile("ttyUSB.*")); //$NON-NLS-1$
+ } else if (osName.startsWith("Windows")) { //$NON-NLS-1$
+ List<String> ports = new ArrayList<>();
+ int i = 0;
+ for (String name = getPortName(i++); name != null; name = getPortName(i++)) {
+ ports.add(name);
}
- String[] names = new String[files.length];
- for (int i = 0; i < files.length; i++) {
- names[i] = files[i].getAbsolutePath();
- }
- return names;
- } else if (System.getProperty("os.name").equals("Windows NT")) { //$NON-NLS-1$//$NON-NLS-2$
-// WindowsRegistry reg = WindowsRegistry.getRegistry();
-// if (reg != null) {
-// List<String> ports = new ArrayList<>();
-// int i = 0;
-// String name = reg.getLocalMachineValueName(SERIAL_KEY, i);
-// while (name != null) {
-// String value = reg.getLocalMachineValue(SERIAL_KEY, name);
-// ports.add(value);
-// i++;
-// name = reg.getLocalMachineValueName(SERIAL_KEY, i);
-// }
-// return ports.toArray(new String[ports.size()]);
-// } else {
-// return new String[0];
-// }
- return new String[0];
+ return ports.toArray(new String[ports.size()]);
} else {
return new String[0];
}
}
- private native long open0(String portName, int baudRate, int byteSize, int parity, int stopBits) throws IOException;
-
- private native void close0(long handle) throws IOException;
-
- private native int read0(long handle) throws IOException;
-
- private native int read1(long handle, byte[] b, int off, int len);
-
- private native void write0(long handle, int b) throws IOException;
-
/**
* Return the name for this serial port.
*