diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..c500c9f
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,92 @@
+name: Build Binarys
+
+on:
+ push:
+ paths:
+ - 'src/**'
+ - '.github/workflows/build.yml'
+
+env:
+ # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+ BUILD_TYPE: Release
+
+jobs:
+ build_linux:
+ name: Build linux binaries
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Configure CMake
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+ - name: Build
+ run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: linux-binary
+ path: ${{github.workspace}}/build/src/libserialport.so
+
+ build_windows:
+ name: Build win64 binaries
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Configure CMake
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+ - name: Build
+ run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: windows-binary
+ path: ${{github.workspace}}\build\src\Release\serialport.dll
+
+ commit:
+ needs: [build_windows, build_linux]
+ name: Commit binaries
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
+ fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
+
+ - name: Download artifact
+ uses: actions/download-artifact@v3
+ with:
+ path: ${{github.workspace}}/tmp
+
+ - name: Create bin folder if it does not exist
+ run: mkdir -p ${{github.workspace}}/lib/bin
+
+ - name: Move and rename linux binary
+ run: mv ${{github.workspace}}/tmp/linux-binary/libserialport.so ${{github.workspace}}/lib/bin/linux.so
+
+ - name: Move and rename windows binary
+ run: mv ${{github.workspace}}/tmp/windows-binary/serialport.dll ${{github.workspace}}/lib/bin/windows.dll
+
+ - name: Configure Git
+ run: |
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
+ git config --local user.name "github-actions[bot]"
+
+ - name: Commit binaries
+ run: |
+ git add ${{github.workspace}}/lib/bin/*
+ git diff-index --quiet HEAD || git commit -m "Commited compiled binaries"
+
+ - name: Push changes
+ uses: ad-m/github-push-action@master
+ with:
+ github_token: ${{ secrets.RELEASE_TOKEN }}
+ branch: ${{ github.ref }}
+
diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml
deleted file mode 100644
index d6245a4..0000000
--- a/.github/workflows/build_linux.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-name: Build Linux SO
-
-on:
- push:
- branches: [ "main" ]
- paths:
- - 'include/**'
- - 'src/**'
- - '.github/workflows/build_linux.yml'
- pull_request:
- branches: [ "main" ]
- paths:
- - 'include/**'
- - 'src/**'
-
-env:
- # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
- BUILD_TYPE: Release
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Configure CMake
- run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-
- - name: Build
- run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
-
- - name: Move compiled file
- run: mv ${{github.workspace}}/build/libserialport.so ${{github.workspace}}/lib/dls/
-
- # - name: Commit artifact changes
- # run: |
- # git config --local user.email "action@github.com"
- # git config --local user.name "GitHub Action"
- # git add lib/dls/*
- # git commit -m "Add artifact"
- # git push
-
- - name: Archive artifact
- uses: actions/upload-artifact@v3
- with:
- name: Compiled-Binary
- path: ${{github.workspace}}/lib/dls/
diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml
deleted file mode 100644
index 8b837a4..0000000
--- a/.github/workflows/build_windows.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: Build Win32 DLL
-
-on:
- push:
- branches: [ "main" ]
- paths:
- - 'include/**'
- - 'src/**'
- - '.github/workflows/build_windows.yml'
- pull_request:
- branches: [ "main" ]
- paths:
- - 'include/**'
- - 'src/**'
-
-env:
- # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
- BUILD_TYPE: Release
-
-jobs:
- build:
- runs-on: windows-latest
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Configure CMake
- run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-
- - name: Build
- run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
-
- - name: Move compiled file
- run: move ${{github.workspace}}\build\Release\serialport.dll ${{github.workspace}}\lib\dls\
-
- - name: Archive artifact
- uses: actions/upload-artifact@v3
- with:
- name: Compiled-Binary
- path: ${{github.workspace}}/lib/dls/
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 43ae51f..db7cb61 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -2,17 +2,11 @@
name: "Pre-Release"
on:
- push:
- branches: [ "main" ]
- paths:
- - 'include/**'
- - 'src/**'
- - '.github/workflows/release.yml'
pull_request:
branches: [ "main" ]
paths:
- - 'include/**'
- 'src/**'
+ - '.github/workflows/release.yml'
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
@@ -69,18 +63,18 @@ jobs:
path: ${{github.workspace}}/tmp
- name: Rename linux Binary
- run: mv ${{github.workspace}}/tmp/linux-binary/libserialport.so ${{github.workspace}}/lib/dls/linux.so
+ run: mv ${{github.workspace}}/tmp/linux-binary/libserialport.so ${{github.workspace}}/lib/bin/linux.so
- name: Rename windows Binary
- run: mv ${{github.workspace}}/tmp/windows-binary/serialport.dll ${{github.workspace}}/lib/dls/windows.dll
+ run: mv ${{github.workspace}}/tmp/windows-binary/serialport.dll ${{github.workspace}}/lib/bin/windows.dll
- run: cd ${{github.workspace}}
- name: make .tar.gz file
- run: tar -czvf lib.tar.gz ./lib
+ run: tar -czvf SerialLink-lib.tar.gz ./lib
- name: make .zip
- run: zip -r lib.zip ./lib
+ run: zip -r SerialLink-lib.zip ./lib
- uses: "marvinpinto/action-automatic-releases@latest"
with:
@@ -89,5 +83,5 @@ jobs:
prerelease: true
title: "Development Build"
files: |
- lib.tar.gz
- lib.zip
+ SerialLink-lib.tar.gz
+ SerialLink-lib.zip
diff --git a/.gitignore b/.gitignore
index dc7956b..22d9298 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
#directories
.vscode/
.cache/
-.github/
build/
test/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b28c4b..90d3fa3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.22)
set(PROJECT_N serialport)
project(${PROJECT_N} VERSION 1.0)
@@ -6,41 +6,6 @@ project(${PROJECT_N} VERSION 1.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
-set(LIB true)
-
-file(GLOB_RECURSE SRCS ${PROJECT_SOURCE_DIR}/src/*.cpp)
-
-# a macro that gets all of the header containing directories.
-MACRO(header_directories return_list includes_base_folder extention )
- FILE(GLOB_RECURSE new_list ${includes_base_folder}/*.${extention})
- SET(dir_list "")
- FOREACH(file_path ${new_list})
- GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
- SET(dir_list ${dir_list} ${dir_path})
- ENDFOREACH()
- LIST(REMOVE_DUPLICATES dir_list)
- SET(${return_list} ${dir_list})
-ENDMACRO()
-
-# using said macro.
-header_directories(INCLUDES ${PROJECT_SOURCE_DIR}/include/ hpp)
-
-message("src files:")
-foreach(file ${SRCS})
- message(STATUS ${file})
-endforeach()
-
-message("include directories:")
-foreach(dir ${INCLUDES})
- message(STATUS ${dir})
-endforeach()
-
-if(LIB)
- add_library(${PROJECT_N} SHARED ${SRCS})
-else()
- add_executable(${PROJECT_N} ${SRCS})
-endif(LIB)
+add_subdirectory(src)
target_include_directories(${PROJECT_N} PUBLIC include)
-
-# set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-shared -fPIC -Wall")
diff --git a/README.md b/README.md
index 549fee3..4e7f66a 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,9 @@
-[Build Win32 DLL]: https://img.shields.io/github/actions/workflow/status/TypeScriptPlayground/Serial/build_windows.yml?label=Build%20Win32%20DLL&labelColor=343b42&logo=github&logoColor=959DA5 'Win32 Build'
-[Build Linux SO]: https://img.shields.io/github/actions/workflow/status/TypeScriptPlayground/Serial/build_linux.yml?label=Build%20Linux%20SO&labelColor=343b42&logo=github&logoColor=959DA5 'Linux Build'
+[Build binaries]: https://img.shields.io/github/actions/workflow/status/TypeScriptPlayground/Serial/build_windows.yml?label=Build%20binaries&labelColor=343b42&logo=github&logoColor=959DA5 'Build binaries'
[Release Downloads]: https://img.shields.io/github/downloads/TypeScriptPlayground/Serial/total?label=Downloads%20&labelColor=343b42&logo=docusign&logoColor=959DA5 'Total Release Downloads'
# Serial
-[![Build Win32 DLL]](https://github.com/TypeScriptPlayground/Serial/actions/workflows/build_windows.yml)
-[![Build Linux SO]](https://github.com/TypeScriptPlayground/Serial/actions/workflows/build_linux.yml)
+[![Build binaries]](https://github.com/TypeScriptPlayground/Serial/actions/workflows/build.yml)
[![Release Downloads]](https://github.com/TypeScriptPlayground/Serial/releases)
@@ -33,10 +31,10 @@ This library provides an interface for the communication with serial devices and
- Works on different operating systems (check [compatibility](#compatibility) for mor info).
## Compatibility
-| OS | Tested version | Current state |
-|---------|------------------|---------------|
-| Windows | Windows 10 (x64) | implemented |
-| Linux | - | in progress |
+| OS | Tested version | Current state |
+|---------|-------------------------|---------------|
+| Windows | Windows 10 (x64) | implemented |
+| Linux | Ubuntu Server 22.04 LTS | implemented |
## Possible/Known issues
- What happens if you open multiple connections from the same instance.
@@ -45,6 +43,10 @@ This library provides an interface for the communication with serial devices and
- Linux write currently not working
## Examples - How to use
+To use this library you need the following flags to run it:
+- `--unstable`
+- `--allow-ffi`
+
### Ports
Get a list with all serial ports and their info that are currently available on your system.
@@ -77,17 +79,17 @@ Send data to a serial device. For exampe to an [Arduino](https://www.arduino.cc/
`main.ts`
```typescript
-import { Serial } from "./mod.ts";
+import { Serial, baudrate } from "./mod.ts";
// create new instance of a serial object
const serial = new Serial();
// open the connection
-serial.open();
+serial.open('COM1', baudrate.B9600);
// encode the message to a Uint8Array
-const textToSend = 'Hello from TypeScript!'
-const encodedTextToSend = new TextEncoder().encode(textToSend)
+const textToSend = 'Hello from TypeScript!';
+const encodedTextToSend = new TextEncoder().encode(textToSend);
// send the message
serial.send(encodedTextToSend, encodedTextToSend.length);
@@ -113,13 +115,13 @@ void loop() {
`main.ts`
```typescript
-import { Serial } from "./mod.ts";
+import { Serial, baudrate } from "./mod.ts";
// create new instance of a serial object
const serial = new Serial();
// open the connection
-serial.open();
+serial.open('COM1', baudrate.B9600);
// create a new buffer to store incoming bytes,
// in this example we want to read a maximum of 100 bytes
diff --git a/include/serial.h b/include/serial.h
deleted file mode 100644
index 687047e..0000000
--- a/include/serial.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#pragma once
-
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-# ifdef SERIALPORT_EXPORTS
-# define MODULE_API __declspec(dllexport)
-# else
-# define MODULE_API __declspec(dllimport)
-# endif
-#else
-# define MODULE_API
-#endif
-
-// Windows
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-# include "serial_windows.h"
-# define systemOpen(port, baudrate, dataBits, parity, stopBits) windowsSystemOpen(port, baudrate, dataBits, parity, stopBits)
-# define systemClose() windowsSystemClose()
-# define systemRead(buffer, bufferSize, timeout, multiplier) windowsSystemRead(buffer, bufferSize, timeout, multiplier)
-# define systemReadUntil(buffer, bufferSize, timeout, multiplier, untilChar) windowsSystemReadUntil(buffer, bufferSize, timeout, multiplier, untilChar)
-# define systemWrite(buffer, bufferSize, timeout, multiplier) windowsSystemWrite(buffer, bufferSize, timeout, multiplier)
-# define systemGetAvailablePorts(buffer, bufferSize, separator) windowsSystemGetAvailablePorts(buffer, bufferSize, separator)
-#endif
-
-// Linux, Apple
-#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
-# include "serial_unix.h"
-# define systemOpen(port, baudrate, dataBits, parity, stopBits) unixSystemOpen(port, baudrate, dataBits, parity, stopBits)
-# define systemClose() unixSystemClose()
-# define systemRead(buffer, bufferSize, timeout, multiplier) unixSystemRead(buffer, bufferSize, timeout, multiplier)
-# define systemReadUntil(buffer, bufferSize, timeout, multiplier, untilChar) unixSystemReadUntil(buffer, bufferSize, timeout, multiplier, untilChar)
-# define systemWrite(buffer, bufferSize, timeout, multiplier) unixSystemWrite(buffer, bufferSize, timeout, multiplier)
-# define systemGetAvailablePorts(buffer, bufferSize, separator) unixSystemGetAvailablePorts(buffer, bufferSize, separator)
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
- MODULE_API auto serialOpen(
- void* port,
- const int baudrate,
- const int dataBits,
- const int parity = 0,
- const int stopBits = 0
- ) -> int;
-
- MODULE_API auto serialClose() -> int;
-
- MODULE_API auto serialRead(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
- ) -> int;
-
- MODULE_API auto serialReadUntil(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier,
- void* untilChar
- ) -> int;
-
- MODULE_API auto serialWrite(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
- ) -> int;
-
- MODULE_API auto serialGetAvailablePorts(
- void* buffer,
- const int bufferSize,
- void* separator
- ) -> int;
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/serial_unix.h b/include/serial_unix.h
deleted file mode 100644
index f33647e..0000000
--- a/include/serial_unix.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
-
-#include // String function definitions
-#include // UNIX standard function definitions
-#include // File control definitions
-#include // Used for TCGETS2, which is required for custom baud rates
-#include
-#include
-// #include
-
-#include "status_codes.h"
-
-extern int hSerialPort;
-extern termios2 tty;
-
-auto unixSystemOpen(
- void* port,
- const int baudrate,
- const int dataBits,
- const int parity = 0,
- const int stopBits = 0
-) -> int;
-
-auto unixSystemClose() -> int;
-
-auto unixSystemRead(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int;
-
-auto unixSystemReadUntil(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier,
- void* untilChar
-) -> int;
-
-auto unixSystemWrite(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int;
-
-auto unixSystemGetAvailablePorts(
- void* buffer,
- const int bufferSize,
- void* separator
-) -> int;
-
-#endif
diff --git a/include/serial_windows.h b/include/serial_windows.h
deleted file mode 100644
index 0b5f7d8..0000000
--- a/include/serial_windows.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-
-#include
-#include
-#include
-#include "status_codes.h"
-
-extern HANDLE hSerialPort;
-extern DCB dcbSerialParams;
-extern COMMTIMEOUTS timeouts;
-
-auto windowsSystemOpen(
- void* port,
- const int baudrate,
- const int dataBits,
- const int parity = 0,
- const int stopBits = 0
-) -> int;
-
-auto windowsSystemClose() -> int;
-
-auto windowsSystemRead(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int;
-
-auto windowsSystemReadUntil(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier,
- void* untilChar
-) -> int;
-
-auto windowsSystemWrite(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int;
-
-auto windowsSystemGetAvailablePorts(
- void* buffer,
- const int bufferSize,
- void* separator
-) -> int;
-
-#endif
diff --git a/lib/Serial.ts b/lib/Serial.ts
index 2e3df82..8bb631a 100644
--- a/lib/Serial.ts
+++ b/lib/Serial.ts
@@ -1,12 +1,16 @@
import { checkForErrorCode } from "./check_for_error_code.ts";
+import { Baudrate } from "./constants/baudrates.ts";
import { dataBits } from "./constants/data_bits.ts";
import { parity } from "./constants/parity.ts";
import { stopBits } from "./constants/stop_bits.ts";
import { decode } from "./decode.ts";
+import { encode } from "./encode.ts";
import { Ports } from "./interfaces/ports.ts";
import { SerialFunctions } from "./interfaces/serial_functions.d.ts";
import { SerialOptions } from "./interfaces/serial_options.d.ts";
-import { loadDL } from "./load_dl.ts";
+import { loadBinaryForOS } from "./load_binary_for_os.ts";
+
+const pathToBinariesDirectory = './lib/bin';
export class Serial {
private _isOpen : boolean;
@@ -17,7 +21,18 @@ export class Serial {
*/
constructor() {
this._isOpen = false;
- this._dl = loadDL('./lib/dls', Deno.build.os);
+ this._dl = loadBinaryForOS(pathToBinariesDirectory, Deno.build.os);
+ this._dl.onError((code) => {
+ throw new Error(`An error has occurred. Error code: ${code}`);
+ });
+
+ this._dl.onRead((bytes) => {
+ console.log('onRead():', bytes);
+
+ })
+ this._dl.onWrite((bytes) => {
+ console.log('onWrite():', bytes);
+ })
}
/**
@@ -30,50 +45,42 @@ export class Serial {
/**
* Opens the serial connection.
- * @param {string} port The port to connect
- * @param {number} baudrate The baudrate
- * @param {SerialOptions} serialOptions Additional options for the serial connection (`data bits`, `parity`, `stop bits`)
+ * @param port The port to connect
+ * @param baudrate The baudrate
+ * @param serialOptions Additional options for the serial connection (`data bits`, `parity`, `stop bits`)
*/
open(
port : string,
- baudrate : number,
+ baudrate : Baudrate,
serialOptions? : SerialOptions
- ) : number {
- const status = this._dl.open(
- port,
+ ) : void {
+ this._dl.open(
+ encode(port + '\0'),
baudrate,
serialOptions?.dataBits || dataBits.EIGHT,
serialOptions?.parity || parity.NONE,
serialOptions?.stopBits || stopBits.ONE
);
-
- checkForErrorCode(status);
this._isOpen = true;
-
- return status;
}
/**
* Closes the serial connection.
*/
- close() : number {
- const status = this._dl.close();
-
- checkForErrorCode(status);
+ close() {
+ this._dl.close();
this._isOpen = false;
-
- return status;
}
/**
* Read data from serial connection.
- * @param {Uint8Array} buffer Buffer to read the bytes into
- * @param {number} bytes The number of bytes to read
- * @param {number} timeout The timeout in `ms`
- * @param {number} multiplier The timeout between reading individual bytes in `ms`
- * @returns {number} Returns number of bytes read
+ * @param buffer Buffer to read the bytes into
+ * @param bytes The number of bytes to read
+ * @param timeout The timeout in `ms`
+ * @param multiplier The timeout between reading individual bytes in `ms`
+ * @returns The number of bytes read
*/
read(
buffer : Uint8Array,
@@ -81,26 +88,26 @@ export class Serial {
timeout = 0,
multiplier = 10
) : number {
- const status = this._dl.read(
+ const result = this._dl.read(
buffer,
bytes,
timeout,
multiplier
);
- checkForErrorCode(status);
+ checkForErrorCode(result);
- return status;
+ return result;
}
/**
- * Read data from serial connection until a linebreak (`\n`) gets send.
- * @param {Uint8Array} buffer Buffer to read the bytes into
- * @param {number} bytes The number of bytes to read
- * @param {number} timeout The timeout in `ms`
- * @param {number} multiplier The timeout between reading individual bytes in `ms`
- * @param {string} searchString A string to search for
- * @returns {number} Returns number of bytes read
+ * Read data from serial connection until the specified `searchString` is found.
+ * @param buffer Buffer to read the bytes into
+ * @param bytes The number of bytes to read
+ * @param timeout The timeout in `ms`
+ * @param multiplier The timeout between reading individual bytes in `ms`
+ * @param searchString A string to search for
+ * @returns The number of bytes read
*/
readUntil(
buffer : Uint8Array,
@@ -109,25 +116,25 @@ export class Serial {
multiplier = 10,
searchString = '',
) : number {
- const status = this._dl.readUntil(
+ const result = this._dl.readUntil(
buffer,
bytes,
timeout,
multiplier,
- searchString
+ encode(searchString + '\0')
)
- checkForErrorCode(status);
+ checkForErrorCode(result);
- return status
+ return result
}
/**
* Write data to serial connection.
- * @param {Uint8Array} buffer The data to write/send
- * @param {number} bytes The number of bytes to read
- * @param {number} timeout The timeout in `ms`
- * @param {number} multiplier The timeout between reading individual bytes in `ms`
- * @returns {number} Returns number of bytes written
+ * @param buffer The data to write/send
+ * @param bytes The number of bytes to read
+ * @param timeout The timeout in `ms`
+ * @param multiplier The timeout between reading individual bytes in `ms`
+ * @returns The number of bytes written
*/
write(
buffer : Uint8Array,
@@ -135,16 +142,16 @@ export class Serial {
timeout = 0,
multiplier = 10
) : number {
- const status = this._dl.write(
+ const result = this._dl.write(
buffer,
bytes,
timeout,
multiplier
)
- checkForErrorCode(status);
+ checkForErrorCode(result);
- return status
+ return result
}
/**
@@ -152,16 +159,16 @@ export class Serial {
* @returns {Ports[]} Returns a list of ports info
*/
getPortsInfo() : Ports[] {
- const buffer = new Uint8Array(1024);
- const status = this._dl.getAvailablePorts(
+ const buffer = new Uint8Array(2048);
+ const result = this._dl.getPortsInfo(
buffer,
buffer.length,
- ','
+ encode(',' + '\0')
)
- checkForErrorCode(status);
+ checkForErrorCode(result);
- const ports = decode(buffer).replaceAll('\x00','').split(',').map((port) => {
+ const ports = decode(buffer).replaceAll('\0','').split(',').map((port) => {
return {
name: port
};
diff --git a/lib/bin/linux.so b/lib/bin/linux.so
new file mode 100644
index 0000000..f78d8af
Binary files /dev/null and b/lib/bin/linux.so differ
diff --git a/lib/bin/windows.dll b/lib/bin/windows.dll
new file mode 100644
index 0000000..420ffef
Binary files /dev/null and b/lib/bin/windows.dll differ
diff --git a/lib/check_for_error_code.ts b/lib/check_for_error_code.ts
index 625a511..b12c634 100644
--- a/lib/check_for_error_code.ts
+++ b/lib/check_for_error_code.ts
@@ -1,5 +1,10 @@
import { ErrorCode } from "./errors/error_code.ts";
+/**
+ * This function is used to check for an error code. If the code is below 0 an error is thrown
+ * @param code Error code
+ * @throws The error with the code
+ */
export function checkForErrorCode(code : number) {
if (code >= 0) {
return;
diff --git a/lib/constants/baudrate.ts b/lib/constants/baudrate.ts
deleted file mode 100644
index 6914ce1..0000000
--- a/lib/constants/baudrate.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-interface Baudrate {
- B1200: 1200,
- B2400: 2400,
- B9600: 9600,
- B19200: 19200,
- B38400: 38400,
- B57600: 57600,
- B74880: 74880,
- B115200: 115200,
- B230400: 230400,
- B250000: 250000
-}
-
-export const baudrate : Baudrate = {
- B1200: 1200,
- B2400: 2400,
- B9600: 9600,
- B19200: 19200,
- B38400: 38400,
- B57600: 57600,
- B74880: 74880,
- B115200: 115200,
- B230400: 230400,
- B250000: 250000
-}
diff --git a/lib/constants/baudrates.ts b/lib/constants/baudrates.ts
new file mode 100644
index 0000000..38bdee3
--- /dev/null
+++ b/lib/constants/baudrates.ts
@@ -0,0 +1,16 @@
+import { ObjectValuesMap } from "../types/object_values_map.ts";
+
+export const baudrates = {
+ B1200: 1200,
+ B2400: 2400,
+ B9600: 9600,
+ B19200: 19200,
+ B38400: 38400,
+ B57600: 57600,
+ B74880: 74880,
+ B115200: 115200,
+ B230400: 230400,
+ B250000: 250000
+} as const;
+
+export type Baudrate = ObjectValuesMap
diff --git a/lib/constants/binary_extensions.ts b/lib/constants/binary_extensions.ts
new file mode 100644
index 0000000..7929e76
--- /dev/null
+++ b/lib/constants/binary_extensions.ts
@@ -0,0 +1,11 @@
+export const binaryExtensions : {[key : string] : string} = {
+ windows: 'dll',
+ linux: 'so',
+ darwin: '',
+ freebsd: '',
+ netbsd: '',
+ aix: '',
+ solaris: '',
+ illumos: ''
+} as const;
+
diff --git a/lib/constants/data_bits.ts b/lib/constants/data_bits.ts
index 67993e8..6270834 100644
--- a/lib/constants/data_bits.ts
+++ b/lib/constants/data_bits.ts
@@ -1,13 +1,10 @@
-interface DataBits {
- FIVE: 5,
- SIX: 6,
- SEVEN: 7,
- EIGHT: 8,
-}
+import { ObjectValuesMap } from "../types/object_values_map.ts";
-export const dataBits : DataBits = {
+export const dataBits = {
FIVE: 5,
SIX: 6,
SEVEN: 7,
EIGHT: 8,
-}
+} as const;
+
+export type DataBits = ObjectValuesMap
diff --git a/lib/constants/parity.ts b/lib/constants/parity.ts
index 218afc7..3de4ca7 100644
--- a/lib/constants/parity.ts
+++ b/lib/constants/parity.ts
@@ -1,14 +1,11 @@
-interface Parity {
+import { ObjectValuesMap } from "../types/object_values_map.ts";
+
+export const parity = {
NONE: 0,
ODD: 1,
EVEN: 2,
MARK: 3,
SPACE: 4
-}
-export const parity : Parity = {
- NONE: 0,
- ODD: 1,
- EVEN: 2,
- MARK: 3,
- SPACE: 4
-}
+} as const;
+
+export type Parity = ObjectValuesMap
diff --git a/lib/constants/status_codes.ts b/lib/constants/status_codes.ts
index 9f54f4c..f8acf17 100644
--- a/lib/constants/status_codes.ts
+++ b/lib/constants/status_codes.ts
@@ -1,17 +1,6 @@
-interface StatusCodes {
- SUCCESS: 0,
- CLOSE_HANDLE_ERROR: -1,
- INVALID_HANDLE_ERROR: -2,
- READ_ERROR: -3,
- WRITE_ERROR: -4,
- GET_PROPERTY_ERROR: -5,
- SET_PROPERTY_ERROR: -6,
- SET_TIMEOUT_ERROR: -7,
- BUFFER_ERROR: -8,
- NOT_FOUND_ERROR: -9
-}
+import { ObjectValuesMap } from "../types/object_values_map.ts";
-export const statusCodes : StatusCodes = {
+export const statusCodes = {
SUCCESS: 0,
CLOSE_HANDLE_ERROR: -1,
INVALID_HANDLE_ERROR: -2,
@@ -22,4 +11,6 @@ export const statusCodes : StatusCodes = {
SET_TIMEOUT_ERROR: -7,
BUFFER_ERROR: -8,
NOT_FOUND_ERROR: -9
-}
+} as const;
+
+export type StatusCode = ObjectValuesMap
diff --git a/lib/constants/stop_bits.ts b/lib/constants/stop_bits.ts
index 64f4a6c..73b41e9 100644
--- a/lib/constants/stop_bits.ts
+++ b/lib/constants/stop_bits.ts
@@ -1,10 +1,9 @@
-interface StopBits {
+import { ObjectValuesMap } from "../types/object_values_map.ts"
+
+export const stopBits = {
ONE: 0,
ONE_DOT_FIVE: 1,
TWO: 2
-}
-export const stopBits : StopBits = {
- ONE: 0,
- ONE_DOT_FIVE: 1,
- TWO: 2
-}
+} as const;
+
+export type StopBits = ObjectValuesMap
diff --git a/lib/decode.ts b/lib/decode.ts
index e26e737..e46746b 100644
--- a/lib/decode.ts
+++ b/lib/decode.ts
@@ -1 +1,8 @@
-export const decode = (buffer : Uint8Array) => new TextDecoder().decode(buffer);
+const textDecoder = new TextDecoder()
+
+/**
+ * This function is used as a wrapper for the default text decoder.
+ * @param buffer Data to decode
+ * @returns The decoded data
+ */
+export const decode = (buffer : Uint8Array) : string => textDecoder.decode(buffer);
diff --git a/lib/dls/windows.dll b/lib/dls/windows.dll
deleted file mode 100644
index b0d598b..0000000
Binary files a/lib/dls/windows.dll and /dev/null differ
diff --git a/lib/encode.ts b/lib/encode.ts
index 0c7aa5b..49f7675 100644
--- a/lib/encode.ts
+++ b/lib/encode.ts
@@ -1 +1,8 @@
-export const encode = (string : string) => new TextEncoder().encode(string);
+const textEncoder = new TextEncoder()
+
+/**
+ * This function is used as a wrapper for the default text encoder
+ * @param buffer Data to encode
+ * @returns The encoded data
+ */
+export const encode = (string : string) => textEncoder.encode(string);
diff --git a/lib/errors/error_code.ts b/lib/errors/error_code.ts
index 88aabb3..97f5645 100644
--- a/lib/errors/error_code.ts
+++ b/lib/errors/error_code.ts
@@ -1,8 +1,8 @@
-import { statusCodes } from "../constants/status_codes.ts";
-
export class ErrorCode extends Error {
+ code : number
+
constructor(code : number) {
- const errorCodeKey = Object.keys(statusCodes).find(key => statusCodes[key] === code);
- super(`An error has occurred. Error code: ${errorCodeKey} (${code})`);
+ super(`An error has occurred. Error code: ${code}`);
+ this.code = code;
}
}
diff --git a/lib/interfaces/serial_functions.d.ts b/lib/interfaces/serial_functions.d.ts
index 6cd483b..890b9c4 100644
--- a/lib/interfaces/serial_functions.d.ts
+++ b/lib/interfaces/serial_functions.d.ts
@@ -1,36 +1,48 @@
-import { parity } from "../constants/parity.ts";
+import { Baudrate } from "../constants/baudrates.ts";
+import { DataBits } from "../constants/data_bits.ts";
+import { Parity } from "../constants/parity.ts";
+import { StopBits } from "../constants/stop_bits.ts";
export interface SerialFunctions {
- open: (
- port : string,
- baudrate : number,
- dataBits : number,
- parity : parity,
- stopBits : number
- ) => number,
- close: () => number,
- read: (
+ open : (
+ port : Uint8Array,
+ baudrate : Baudrate,
+ dataBits : DataBits,
+ parity : Parity,
+ stopBits : StopBits
+ ) => void,
+ close : () => void,
+ read : (
buffer : Uint8Array,
bufferSize : number,
timeout : number,
multiplier : number
) => number,
- readUntil: (
+ readUntil : (
buffer : Uint8Array,
bufferSize : number,
timeout : number,
multiplier : number,
- searchString : string
+ searchString : Uint8Array
) => number,
- write: (
+ write : (
buffer : Uint8Array,
bufferSize : number,
timeout : number,
multiplier : number
) => number,
- getAvailablePorts: (
+ getPortsInfo : (
buffer : Uint8Array,
bufferSize : number,
- separator : string
- ) => number
+ separator : Uint8Array
+ ) => number,
+ onError : (callback : (
+ code : number
+ ) => void) => void,
+ onRead : (callback : (
+ bytes : number
+ ) => void) => void,
+ onWrite : (callback : (
+ bytes : number
+ ) => void) => void
}
diff --git a/lib/interfaces/serial_options.d.ts b/lib/interfaces/serial_options.d.ts
index 3495589..306b4e4 100644
--- a/lib/interfaces/serial_options.d.ts
+++ b/lib/interfaces/serial_options.d.ts
@@ -1,9 +1,9 @@
-import { dataBits } from "../constants/data_bits.ts";
-import { parity } from "../constants/parity.ts";
-import { stopBits } from "../constants/stop_bits.ts";
+import { DataBits } from "../constants/data_bits.ts";
+import { Parity } from "../constants/parity.ts";
+import { StopBits } from "../constants/stop_bits.ts";
export interface SerialOptions {
- dataBits? : dataBits,
- parity? : parity,
- stopBits? : stopBits
+ dataBits? : DataBits,
+ parity? : Parity,
+ stopBits? : StopBits
}
diff --git a/lib/load_binary_for_os.ts b/lib/load_binary_for_os.ts
new file mode 100644
index 0000000..8169ee5
--- /dev/null
+++ b/lib/load_binary_for_os.ts
@@ -0,0 +1,27 @@
+import { binaryExtensions } from "./constants/binary_extensions.ts";
+import { SerialFunctions } from "./interfaces/serial_functions.d.ts";
+import { registerSerialFunctions } from "./register_serial_functions.ts";
+
+/**
+ * This function is used to load the specific binary based on the current os.
+ * @param path The default path to the binaries directory
+ * @param os The current OS
+ * @returns A serial functions object with all the functions from the binary
+ */
+export function loadBinaryForOS(path : string, os : string) : SerialFunctions {
+ if (!binaryExtensions[os]) {
+ throw new Error(
+ `There is currently no implementation for this operating system.
+ We are currently working on an implementation for all missing operating systems.
+ Current stage:
+
+ - Windows (implemented)
+ - Linux (in progress)
+
+ For more information feel free to check out the repository:
+ https://github.com/TypeScriptPlayground/Serial#compatibility`
+ );
+ }
+
+ return registerSerialFunctions(path, os, binaryExtensions[os]);
+}
diff --git a/lib/load_dl.ts b/lib/load_dl.ts
deleted file mode 100644
index 7c01e97..0000000
--- a/lib/load_dl.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { SerialFunctions } from "./interfaces/serial_functions.d.ts";
-import { registerSerialFunctions } from "./register_serial_functions.ts";
-
-export function loadDL(path : string, os : string) : SerialFunctions {
- let libSuffix = '';
-
- switch(os) {
- case 'windows': {
- libSuffix = 'dll';
- break;
- }
-
- case 'linux':
- case 'darwin':
- case 'freebsd':
- case 'netbsd':
- case 'aix':
- case 'solaris':
- case 'illumos': {
- throw new Error(
- `There is currently no implementation for this operating system.
- We are currently working on an implementation for all missing operating systems.
- Current stage:
-
- - Windows (implemented)
- - Linux (in progress)
- - MacOS (planned)
-
- For more information feel free to check out the repository:
- https://github.com/TypeScriptPlayground/Serial`
- );
- }
-
- default: {
- break;
- }
- }
-
- return registerSerialFunctions(path, os, libSuffix);
-}
diff --git a/lib/register_serial_functions.ts b/lib/register_serial_functions.ts
index 99c2e63..94e6351 100644
--- a/lib/register_serial_functions.ts
+++ b/lib/register_serial_functions.ts
@@ -1,6 +1,4 @@
import { SerialFunctions } from "./interfaces/serial_functions.d.ts";
-import { encode } from "./encode.ts";
-import { parity } from "./constants/parity.ts";
export function registerSerialFunctions(
path : string,
@@ -8,7 +6,7 @@ export function registerSerialFunctions(
libSuffix : string
) : SerialFunctions {
const serialFunctions = Deno.dlopen(`${path}/${os}.${libSuffix}`, {
- 'open': {
+ 'serialOpen': {
parameters: [
// Port
'buffer',
@@ -22,14 +20,14 @@ export function registerSerialFunctions(
'i32'
],
// Status code
- result: 'i32'
+ result: 'void'
},
- 'close': {
+ 'serialClose': {
parameters: [],
// Status code
result: 'i32'
},
- 'read': {
+ 'serialRead': {
parameters: [
// Buffer
'buffer',
@@ -40,10 +38,10 @@ export function registerSerialFunctions(
// Multiplier
'i32'
],
- // Status code/Bytes read
+ // Bytes read
result: 'i32'
},
- 'readUntil': {
+ 'serialReadUntil': {
parameters: [
// Buffer
'buffer',
@@ -56,10 +54,10 @@ export function registerSerialFunctions(
// SearchString
'buffer'
],
- // Status code/Bytes read
+ // Bytes read
result: 'i32'
},
- 'write': {
+ 'serialWrite': {
parameters: [
// Buffer
'buffer',
@@ -70,10 +68,10 @@ export function registerSerialFunctions(
// Multiplier
'i32'
],
- // Status code/Bytes written
+ // Bytes written
result: 'i32'
},
- 'getAvailablePorts': {
+ 'serialGetPortsInfo': {
parameters: [
// Buffer
'buffer',
@@ -82,69 +80,54 @@ export function registerSerialFunctions(
// Separator
'buffer'
],
- // Status code/Amount of ports
+ // Amount of ports
result: 'i32'
+ },
+ 'serialOnError': {
+ // on error callback function
+ parameters: ['function'],
+ result: 'void'
+ },
+ 'serialOnRead': {
+ // on error callback function
+ parameters: ['function'],
+ result: 'void'
+ },
+ 'serialOnWrite': {
+ // on error callback function
+ parameters: ['function'],
+ result: 'void'
}
}).symbols
-
+
return {
- open: (
- port : string,
- baudrate : number,
- dataBits : number,
- parity : parity,
- stopBits : number
- ) : number => serialFunctions.open(
- encode(port + '\0'),
- baudrate,
- dataBits,
- parity,
- stopBits
- ),
- close: () : number => serialFunctions.close(),
- read: (
- buffer : Uint8Array,
- bytes : number,
- timeout : number,
- multiplier : number
- ) : number => serialFunctions.read(
- buffer,
- bytes,
- timeout,
- multiplier
- ),
- readUntil: (
- buffer : Uint8Array,
- bytes : number,
- timeout : number,
- multiplier : number,
- searchString : string
- ) : number => serialFunctions.readUntil(
- buffer,
- bytes,
- timeout,
- multiplier,
- encode(searchString + '\0')
- ),
- write: (
- buffer : Uint8Array,
- bytes : number,
- timeout : number,
- multiplier : number
- ) : number => serialFunctions.write(
- buffer,
- bytes,
- timeout,
- multiplier
- ),
- getAvailablePorts: (
- buffer : Uint8Array,
- bytes : number,
- separator : string
- ) : number => serialFunctions.getAvailablePorts(
- buffer,
- bytes,
- encode(separator + '\0')
- )
+ open: serialFunctions.serialOpen,
+ close: serialFunctions.serialClose,
+ read: serialFunctions.serialRead,
+ readUntil: serialFunctions.serialReadUntil,
+ write: serialFunctions.serialWrite,
+ getPortsInfo: serialFunctions.serialGetPortsInfo,
+ onError: (callback) => {
+ serialFunctions.serialOnError(new Deno.UnsafeCallback({
+ parameters: ['i32'],
+ result: "void",
+ } as const,
+ (errorCode) => {callback(errorCode)}).pointer)
+ },
+ onRead: (callback) => {
+ serialFunctions.serialOnRead(new Deno.UnsafeCallback({
+ parameters: ['i32'],
+ result: "void",
+ } as const,
+ (bytes) => {callback(bytes)}).pointer)
+ },
+ onWrite: (callback) => {
+ serialFunctions.serialOnWrite(new Deno.UnsafeCallback({
+ parameters: ['i32'],
+ result: "void",
+ } as const,
+ (bytes) => {callback(bytes)}).pointer)
+ }
}
}
+
diff --git a/lib/types/object_values_map.ts b/lib/types/object_values_map.ts
new file mode 100644
index 0000000..643ed22
--- /dev/null
+++ b/lib/types/object_values_map.ts
@@ -0,0 +1 @@
+export type ObjectValuesMap = ObjectType[keyof ObjectType]
diff --git a/mod.ts b/mod.ts
index a643f41..57749b1 100644
--- a/mod.ts
+++ b/mod.ts
@@ -1,5 +1,5 @@
export { Serial } from './lib/Serial.ts';
-export { baudrate } from './lib/constants/baudrate.ts';
+export { baudrates } from './lib/constants/baudrates.ts';
export { dataBits } from './lib/constants/data_bits.ts';
export { parity } from './lib/constants/parity.ts';
export { stopBits } from './lib/constants/stop_bits.ts';
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..6329d11
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,46 @@
+cmake_minimum_required(VERSION 3.22)
+
+set(PROJECT_N serialport)
+project(${PROJECT_N} VERSION 1.0)
+
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+include_directories(${PROJECT_N} PUBLIC include)
+
+set(LIB true)
+
+file(GLOB_RECURSE SRCS ${PROJECT_SOURCE_DIR}/src/*.cpp)
+
+# a macro that gets all of the header containing directories.
+MACRO(header_directories return_list includes_base_folder extention )
+ FILE(GLOB_RECURSE new_list ${includes_base_folder}/*.${extention})
+ SET(dir_list "")
+ FOREACH(file_path ${new_list})
+ GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
+ SET(dir_list ${dir_list} ${dir_path})
+ ENDFOREACH()
+ LIST(REMOVE_DUPLICATES dir_list)
+ SET(${return_list} ${dir_list})
+ENDMACRO()
+
+# using said macro.
+header_directories(INCLUDES ${PROJECT_SOURCE_DIR}/src/include/ h)
+
+message("src files:")
+foreach(file ${SRCS})
+ message(STATUS ${file})
+endforeach()
+
+message("include directories:")
+foreach(dir ${INCLUDES})
+ message(STATUS ${dir})
+endforeach()
+
+if(LIB)
+ add_library(${PROJECT_N} SHARED ${SRCS})
+else()
+ add_executable(${PROJECT_N} ${SRCS})
+endif(LIB)
+
+# set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-shared -fPIC -Wall")
diff --git a/src/include/serial.h b/src/include/serial.h
new file mode 100644
index 0000000..6eded48
--- /dev/null
+++ b/src/include/serial.h
@@ -0,0 +1,71 @@
+#pragma once
+#include
+
+#include "status_codes.h"
+
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# ifdef SERIALPORT_EXPORTS
+# define MODULE_API __declspec(dllexport)
+# else
+# define MODULE_API __declspec(dllimport)
+# endif
+#else
+# define MODULE_API
+#endif
+
+extern void (*errorCallback)(int errorCode);
+extern void (*readCallback)(int bytes);
+extern void (*writeCallback)(int bytes);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ MODULE_API void serialOpen(
+ void* port,
+ const int baudrate,
+ const int dataBits,
+ const int parity = 0,
+ const int stopBits = 0
+ );
+
+ MODULE_API void serialClose();
+
+ MODULE_API auto serialRead(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier
+ ) -> int;
+
+ MODULE_API auto serialReadUntil(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier,
+ void* untilChar
+ ) -> int;
+
+ MODULE_API auto serialWrite(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier
+ ) -> int;
+
+ MODULE_API auto serialGetPortsInfo(
+ void* buffer,
+ const int bufferSize,
+ void* separator
+ ) -> int;
+
+ MODULE_API auto serialOnError(void (*func)(int code)) -> void;
+
+ MODULE_API auto serialOnRead(void (*func)(int bytes)) -> void;
+
+ MODULE_API auto serialOnWrite(void (*func)(int bytes)) -> void;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/status_codes.h b/src/include/status_codes.h
similarity index 81%
rename from include/status_codes.h
rename to src/include/status_codes.h
index 0569e3f..83eb667 100644
--- a/include/status_codes.h
+++ b/src/include/status_codes.h
@@ -11,4 +11,4 @@ enum class StatusCodes {
NOT_FOUND_ERROR = -9
};
-#define returnStatus(status) return static_cast(status)
+#define status(status) static_cast(status)
diff --git a/src/serial.cpp b/src/serial.cpp
deleted file mode 100644
index 19f7224..0000000
--- a/src/serial.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "serial.h"
-
-auto serialOpen(
- void* port,
- const int baudrate,
- const int dataBits,
- const int parity,
- const int stopBits
-) -> int {
- return systemOpen(port, baudrate, dataBits, parity, stopBits);
-}
-
-auto serialClose() -> int {
- return systemClose();
-}
-
-auto serialRead(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int {
- return systemRead(buffer, bufferSize, timeout, multiplier);
-}
-
-auto serialReadUntil(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier,
- void* untilChar
-) -> int {
- return systemReadUntil(buffer, bufferSize, timeout, multiplier, untilChar);
-}
-
-auto serialWrite(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int {
- return systemWrite(buffer, bufferSize, timeout, multiplier);
-}
-
-auto serialGetAvailablePorts(
- void* buffer,
- const int bufferSize,
- void* separator
-) -> int {
- return systemGetAvailablePorts(buffer, bufferSize, separator);
-}
\ No newline at end of file
diff --git a/src/serial_unix.cpp b/src/serial_unix.cpp
deleted file mode 100644
index 9373752..0000000
--- a/src/serial_unix.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
-#include "serial_unix.h"
-
-// namespace fs = std::filesystem;
-
-int hSerialPort;
-termios2 tty;
-
-auto unixSystemOpen(
- void* port,
- const int baudrate,
- const int dataBits,
- const int parity,
- const int stopBits
-) -> int {
- char *portName = static_cast(port);
- // Open new serial connection
- hSerialPort = open(portName, O_RDWR);
-
- // Error if open fails
- ioctl(hSerialPort, TCGETS2, &tty);
- // if (tcgetattr(hSerialPort, &tty) != 0) {
- // returnStatus(StatusCodes::INVALID_HANDLE_ERROR);
- // }
-
- tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
- tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
- tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
- tty.c_cflag |= CS8; // 8 bits per byte (most common)
- tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
- tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
-
- tty.c_lflag &= ~ICANON;
- tty.c_lflag &= ~ECHO; // Disable echo
- tty.c_lflag &= ~ECHOE; // Disable erasure
- tty.c_lflag &= ~ECHONL; // Disable new-line echo
- tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
- tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
- tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
- tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
- tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
-
- tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
- tty.c_cc[VMIN] = 0;
-
- // Set in/out baud rate to be 9600
- // cfsetispeed(&tty, B9600);
- // cfsetospeed(&tty, B9600);
- tty.c_ispeed = baudrate;
- tty.c_ospeed = baudrate;
-
-
- // Data bits
- tty.c_cflag &= ~CSIZE; // CSIZE is a mask for the number of bits per character
- switch(dataBits) {
- case 5:
- tty.c_cflag |= CS5;
- break;
- case 6:
- tty.c_cflag |= CS6;
- break;
- case 7:
- tty.c_cflag |= CS7;
- break;
- default:
- tty.c_cflag |= CS8;
- break;
- }
-
-
- // parity
- switch(parity) {
- case 0:
- tty.c_cflag &= ~PARENB;
- break;
- case 1:
- tty.c_cflag |= PARENB;
- tty.c_cflag &= ~PARODD; // Clearing PARODD makes the parity even
- break;
- case 2:
- tty.c_cflag |= PARENB;
- tty.c_cflag |= PARODD;
- break;
- }
-
- // stop bits
- // Set num. stop bits
- switch(stopBits) {
- case 0:
- tty.c_cflag &= ~CSTOPB;
- break;
- // TODO case 1: 1.5 would break the code
- case 2:
- tty.c_cflag |= CSTOPB;
- break;
- }
-
- // Save tty settings, also checking for error
- ioctl(hSerialPort, TCSETS2, &tty);
-
- returnStatus(StatusCodes::SUCCESS);
-}
-
-auto unixSystemClose() -> int {
- return close(hSerialPort);
-}
-
-auto unixSystemRead(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int {
- return read(hSerialPort, static_cast(buffer), bufferSize);
-}
-
-auto unixSystemReadUntil(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier,
- void* searchString
-) -> int {
- return 0;
-}
-
-auto unixSystemWrite(
- void* buffer,
- const int bufferSize,
- const int timeout,
- const int multiplier
-) -> int {
-
- std::string tmp(static_cast(buffer), bufferSize);
-
- return write(hSerialPort, tmp.c_str(), tmp.length() + 1);
-}
-
-// auto unixSystemGetAvailablePorts(
-// void* buffer,
-// const int bufferSize,
-// void* separator
-// ) -> int {
-// std::string result;
-
-// int portsCounter = 0;
-
-// fs::path p("/dev/serial/by-id");
-
-// try {
-// if (!exists(p)) {
-// returnStatus(StatusCodes::NOT_FOUND_ERROR);
-// }
-
-// else {
-// for (auto de : fs::directory_iterator(p)) {
-// if (is_symlink(de.symlink_status())) {
-// fs::path symlink_points_at = read_symlink(de);
-// fs::path canonical_path = fs::canonical(p / symlink_points_at);
-// result += canonical_path.generic_string().append(std::string(static_cast(separator)));
-// portsCounter++;
-// }
-// }
-// }
-// } catch (const fs::filesystem_error &exeption) {
-// }
-
-// if (result.length() + 1 <= bufferSize){
-// memcpy(buffer, result.c_str(), result.length() + 1);
-// } else {
-// returnStatus(StatusCodes::BUFFER_ERROR);
-// }
-// return portsCounter;
-// }
-
-#endif
diff --git a/src/src/serial_unix.cpp b/src/src/serial_unix.cpp
new file mode 100644
index 0000000..7fca11b
--- /dev/null
+++ b/src/src/serial_unix.cpp
@@ -0,0 +1,276 @@
+#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
+#include "serial.h"
+#include
+#include // UNIX standard function definitions
+#include // File control definitions
+#include // Used for TCGETS2, which is required for custom baud rates
+#include
+#include
+#include
+#include
+
+int hSerialPort;
+termios2 tty;
+std::string data;
+
+void (*errorCallback)(int errorCode);
+void (*readCallback)(int bytes);
+void (*writeCallback)(int bytes);
+
+void serialOpen(
+ void* port,
+ const int baudrate,
+ const int dataBits,
+ const int parity,
+ const int stopBits
+) {
+ char *portName = static_cast(port);
+ // Open new serial connection
+ hSerialPort = open(portName, O_RDWR);
+
+ // Error if open fails
+ if(hSerialPort == -1){
+ errorCallback(status(StatusCodes::INVALID_HANDLE_ERROR));
+ return;
+ }
+
+ // Get the current com configuration
+ if(ioctl(hSerialPort, TCGETS2, &tty) == -1){
+ errorCallback(status(StatusCodes::GET_STATE_ERROR));
+ return;
+ }
+
+ tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
+ tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
+ tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
+ tty.c_cflag |= CS8; // 8 bits per byte (most common)
+ tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
+ tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
+
+ tty.c_lflag &= ~ICANON;
+ tty.c_lflag &= ~ECHO; // Disable echo
+ tty.c_lflag &= ~ECHOE; // Disable erasure
+ tty.c_lflag &= ~ECHONL; // Disable new-line echo
+ tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
+ tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
+ tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
+ tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
+ tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
+
+ tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
+ tty.c_cc[VMIN] = 0;
+
+ // Set in/out baud rate to be 9600
+ // cfsetispeed(&tty, B9600);
+ // cfsetospeed(&tty, B9600);
+ tty.c_ispeed = baudrate;
+ tty.c_ospeed = baudrate;
+
+ // Data bits
+ tty.c_cflag &= ~CSIZE; // CSIZE is a mask for the number of bits per character
+
+ switch(dataBits) {
+ case 5:
+ tty.c_cflag |= CS5;
+ break;
+ case 6:
+ tty.c_cflag |= CS6;
+ break;
+ case 7:
+ tty.c_cflag |= CS7;
+ break;
+ default:
+ tty.c_cflag |= CS8;
+ break;
+ }
+
+ // parity
+ switch(parity) {
+ case 0:
+ tty.c_cflag &= ~PARENB;
+ break;
+ case 1:
+ tty.c_cflag |= PARENB;
+ tty.c_cflag &= ~PARODD; // Clearing PARODD makes the parity even
+ break;
+ case 2:
+ tty.c_cflag |= PARENB;
+ tty.c_cflag |= PARODD;
+ break;
+ }
+
+ // stop bits
+ // Set num. stop bits
+ switch(stopBits) {
+ case 0:
+ tty.c_cflag &= ~CSTOPB;
+ break;
+ // TODO case 1: 1.5 would break the code
+ case 2:
+ tty.c_cflag |= CSTOPB;
+ break;
+ }
+
+ // Save tty settings, also checking for error
+ if (ioctl(hSerialPort, TCSETS2, &tty) == -1){
+ errorCallback(status(StatusCodes::SET_STATE_ERROR));
+ return;
+ }
+
+ return;
+}
+
+void serialClose() {
+ // Error if close fails
+ if (close(hSerialPort) == -1) {
+ errorCallback(status(StatusCodes::CLOSE_HANDLE_ERROR));
+ return;
+ }
+
+ return;
+}
+
+auto serialRead(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier
+) -> int {
+
+ if (ioctl(hSerialPort, TCGETS2, &tty) == -1){
+ errorCallback(status(StatusCodes::SET_STATE_ERROR));
+ return 0;
+ }
+
+ if (timeout > 0 && timeout < 100) {
+ tty.c_cc[VTIME] = 1;
+ } else {
+ tty.c_cc[VTIME] = timeout / 100;
+ }
+
+ tty.c_cc[VMIN] = bufferSize;
+
+ if (ioctl(hSerialPort, TCSETS2, &tty) == -1) {
+ errorCallback(status(StatusCodes::SET_STATE_ERROR));
+ return 0;
+ }
+
+ int bytesRead = read(hSerialPort, static_cast(buffer), bufferSize);
+
+ if (bytesRead >= 0){
+ return bytesRead;
+ }
+
+ errorCallback(status(StatusCodes::READ_ERROR));
+ return 0;
+}
+
+auto serialReadUntil(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier,
+ void* searchString
+) -> int {
+
+ data = "";
+
+ for (int i{0}; i < bufferSize && data.find(std::string(static_cast(searchString))) == std::string::npos; i++) {
+ char bufferChar[1];
+
+ // Error if read fails
+ int bytesRead = read(hSerialPort, static_cast(bufferChar), 1);
+ if (bytesRead == -1) {
+ errorCallback(status(StatusCodes::READ_ERROR));
+ return 0;
+ }
+
+ if (bytesRead == 0) {
+ break;
+ }
+
+ data.append(std::string(bufferChar, bytesRead));
+ }
+
+ memcpy(buffer, data.c_str(), data.length() + 1);
+
+ readCallback(data.length());
+
+ return data.length();
+}
+
+auto serialWrite(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier
+) -> int {
+
+ const char* tmp = static_cast(buffer);
+
+ int bytesWritten = write(hSerialPort, tmp, bufferSize);
+
+ if (bytesWritten == -1) {
+ errorCallback(status(StatusCodes::WRITE_ERROR));
+ return 0;
+ }
+
+ writeCallback(bytesWritten);
+ return bytesWritten;
+}
+
+auto serialOnError(void (*func)(int code)) -> void {
+ errorCallback = func;
+};
+
+auto serialOnRead(void (*func)(int bytes)) -> void {
+ readCallback = func;
+};
+
+auto serialOnWrite(void (*func)(int bytes)) -> void {
+ writeCallback = func;
+};
+
+auto serialGetPortsInfo(void *buffer, const int bufferSize, void *separator) -> int {
+ std::string result = "";
+
+ int portsCounter = 0;
+
+ DIR* dir = opendir("/dev/serial/by-id");
+ if (dir == nullptr) {
+ // Handle directory not found error
+ return -1; // Return an appropriate error code or define your own
+ }
+
+ struct dirent* entry;
+ while ((entry = readdir(dir)) != nullptr) {
+ if (entry->d_type == DT_LNK) {
+ std::string symlinkPath = "/dev/serial/by-id/";
+ symlinkPath += entry->d_name;
+
+ char canonicalPath[PATH_MAX];
+ if (realpath(symlinkPath.c_str(), canonicalPath) != nullptr) {
+ result += std::string(canonicalPath) + std::string(static_cast(separator));
+ portsCounter++;
+ }
+ }
+ }
+
+ closedir(dir);
+
+ // Remove last trailing comma
+ if (result.length() > 0) {
+ result.erase(result.length() - 1);
+ }
+
+ if (result.length() + 1 <= bufferSize) {
+ memcpy(buffer, result.c_str(), result.length() + 1);
+ } else {
+ errorCallback(status(StatusCodes::BUFFER_ERROR));
+ return 0;
+ }
+
+ return portsCounter;
+}
+
+#endif
diff --git a/src/serial_windows.cpp b/src/src/serial_windows.cpp
similarity index 50%
rename from src/serial_windows.cpp
rename to src/src/serial_windows.cpp
index 479ec09..1044cbb 100644
--- a/src/serial_windows.cpp
+++ b/src/src/serial_windows.cpp
@@ -1,5 +1,7 @@
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-#include "serial_windows.h"
+#include
+
+#include "serial.h"
HANDLE hSerialPort;
@@ -7,23 +9,17 @@ DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
std::string data;
-/**
-* @fn auto open(void* port, const int baudrate, const int dataBits, const int parity, const int stopBits) -> int
-* @brief Opens the specified connection to a serial device.
-* @param port The port to open the serial connection to
-* @param baudrate The baudrate for the serial connection when reading/writing
-* @param dataBits The data bits
-* @param parity The parity bits
-* @param stopBits The stop bits
-* @return Returns the current status code
-*/
-auto windowsSystemOpen(
+void (*errorCallback)(int errorCode);
+void (*readCallback)(int bytes);
+void (*writeCallback)(int bytes);
+
+void serialOpen(
void* port,
const int baudrate,
const int dataBits,
const int parity,
const int stopBits
-) -> int {
+) {
char *portName = static_cast(port);
@@ -41,13 +37,21 @@ auto windowsSystemOpen(
// Error if open fails
if (hSerialPort == INVALID_HANDLE_VALUE) {
- returnStatus(StatusCodes::INVALID_HANDLE_ERROR);
+ errorCallback(status(StatusCodes::INVALID_HANDLE_ERROR));
+ return;
}
// Error if configuration get fails
if (!GetCommState(hSerialPort, &dcbSerialParams)) {
- CloseHandle(hSerialPort);
- returnStatus(StatusCodes::GET_STATE_ERROR);
+ // Error if close fails
+ if (!CloseHandle(hSerialPort)) {
+ errorCallback(status(StatusCodes::CLOSE_HANDLE_ERROR));
+ return;
+ }
+
+ errorCallback(status(StatusCodes::GET_STATE_ERROR));
+
+ return;
}
dcbSerialParams.BaudRate = baudrate;
@@ -57,8 +61,14 @@ auto windowsSystemOpen(
// Error if configuration set fails
if (!SetCommState(hSerialPort, &dcbSerialParams)) {
- CloseHandle(hSerialPort);
- returnStatus(StatusCodes::SET_STATE_ERROR);
+ // Error if close fails
+ if (!CloseHandle(hSerialPort)) {
+ errorCallback(status(StatusCodes::CLOSE_HANDLE_ERROR));
+ return;
+ }
+
+ errorCallback(status(StatusCodes::SET_STATE_ERROR));
+ return;
}
timeouts.ReadIntervalTimeout = 50;
@@ -69,43 +79,32 @@ auto windowsSystemOpen(
// Error if timeout set fails
if (!SetCommTimeouts(hSerialPort, &timeouts)) {
- CloseHandle(hSerialPort);
- returnStatus(StatusCodes::SET_TIMEOUT_ERROR);
- }
+ // Error if close fails
+ if (!CloseHandle(hSerialPort)) {
+ errorCallback(status(StatusCodes::CLOSE_HANDLE_ERROR));
+ return;
+ }
- returnStatus(StatusCodes::SUCCESS);
+ errorCallback(status(StatusCodes::SET_TIMEOUT_ERROR));
+ return;
+ }
}
-/**
-* @fn auto close() -> int
-* @brief Closes the specified connection to a serial device.
-* @return Returns the current status code
-*/
-auto windowsSystemClose() -> int {
+void serialClose() {
// Error if handle is invalid
if (hSerialPort == INVALID_HANDLE_VALUE) {
- returnStatus(StatusCodes::INVALID_HANDLE_ERROR);
+ errorCallback(status(StatusCodes::INVALID_HANDLE_ERROR));
+ return;
}
// Error if close fails
if (!CloseHandle(hSerialPort)) {
- returnStatus(StatusCodes::CLOSE_HANDLE_ERROR);
+ errorCallback(status(StatusCodes::CLOSE_HANDLE_ERROR));
+ return;
}
-
- returnStatus(StatusCodes::SUCCESS);
}
-/**
-* @fn auto read(void* buffer, const int bufferSize, const int timeout, const int multiplier) -> int
-* @brief Reads the specified number of bytes into the buffer.
-* **It is not guaranteed that the complete buffer will be fully read.**
-* @param buffer The buffer in which the bytes should be read into
-* @param bufferSize The size of the buffer
-* @param timeout Timeout to cancel the read
-* @param multiplier The time multiplier between reading
-* @return Returns the current status code (negative) or number of bytes read
-*/
-auto windowsSystemRead(
+auto serialRead(
void* buffer,
const int bufferSize,
const int timeout,
@@ -113,7 +112,8 @@ auto windowsSystemRead(
) -> int {
// Error if handle is invalid
if (hSerialPort == INVALID_HANDLE_VALUE) {
- returnStatus(StatusCodes::INVALID_HANDLE_ERROR);
+ errorCallback(status(StatusCodes::INVALID_HANDLE_ERROR));
+ return 0;
}
timeouts.ReadIntervalTimeout = timeout;
@@ -122,40 +122,33 @@ auto windowsSystemRead(
// Error if timeout set fails
if (!SetCommTimeouts(hSerialPort, &timeouts)) {
- returnStatus(StatusCodes::SET_TIMEOUT_ERROR);
+ errorCallback(status(StatusCodes::SET_TIMEOUT_ERROR));
+ return 0;
}
- DWORD bytesRead;
+ DWORD bytesRead = 0;
// Error if read fails
if (!ReadFile(hSerialPort, buffer, bufferSize, &bytesRead, NULL)) {
- returnStatus(StatusCodes::READ_ERROR);
+ errorCallback(status(StatusCodes::READ_ERROR));
+ return 0;
}
+ readCallback(bytesRead);
return bytesRead;
}
-/**
-* @fn auto readUntil(void* buffer, const int bufferSize, const int timeout, const int mutilplier, void* searchString) -> int
-* @brief Reads until the specified string is found. If the specified string is not found, the buffer is read full until there are no more bytes to read.
-* **It is not guaranteed that the complete buffer will be fully read.**
-* @param buffer The buffer in which the bytes should be read into
-* @param bufferSize The size of the buffer
-* @param timeout Timeout to cancel the read
-* @param multiplier The time multiplier between reading
-* @param searchString The string to search for
-* @return Returns the current status code (negative) or number of bytes read
-*/
-auto windowsSystemReadUntil(
+auto serialReadUntil(
void* buffer,
const int bufferSize,
const int timeout,
const int multiplier,
void* searchString
) -> int {
-
+ // Error if handle is invalid
if (hSerialPort == INVALID_HANDLE_VALUE) {
- returnStatus(StatusCodes::INVALID_HANDLE_ERROR);
+ errorCallback(status(StatusCodes::INVALID_HANDLE_ERROR));
+ return 0;
}
timeouts.ReadIntervalTimeout = timeout;
@@ -164,7 +157,8 @@ auto windowsSystemReadUntil(
// Error if timeout set fails
if (!SetCommTimeouts(hSerialPort, &timeouts)) {
- returnStatus(StatusCodes::SET_TIMEOUT_ERROR);
+ errorCallback(status(StatusCodes::SET_TIMEOUT_ERROR));
+ return 0;
}
data = "";
@@ -175,7 +169,8 @@ auto windowsSystemReadUntil(
// Error if read fails
if (!ReadFile(hSerialPort, bufferChar, sizeof(bufferChar), &bytesRead, NULL)) {
- returnStatus(StatusCodes::READ_ERROR);
+ errorCallback(status(StatusCodes::READ_ERROR));
+ return 0;
}
if (bytesRead == 0) {
@@ -187,47 +182,39 @@ auto windowsSystemReadUntil(
memcpy(buffer, data.c_str(), data.length() + 1);
+ readCallback(data.length());
return data.length();
}
-/**
-* @fn auto write(void* buffer, const int bufferSize, const int timeout, const int multiplier) -> int
-* @brief Writes the buffer to the serial device.
-* **It is not guaranteed that the complete buffer will be fully written.**
-* @param buffer The buffer in which the bytes should be read into
-* @param bufferSize The size of the buffer
-* @param timeout Timeout to cancel the read
-* @param multiplieer The time multiplier between writing
-* @return Returns the current status code (negative) or number of bytes written
-*/
-auto windowsSystemWrite(void* buffer, const int bufferSize, const int timeout, const int multiplier) -> int {
- DWORD bytesWritten;
+auto serialWrite(
+ void* buffer,
+ const int bufferSize,
+ const int timeout,
+ const int multiplier
+) -> int {
+
+ DWORD bytesWritten = 0;
timeouts.WriteTotalTimeoutConstant = timeout;
timeouts.WriteTotalTimeoutMultiplier = multiplier;
// Error if timeout set fails
if (!SetCommTimeouts(hSerialPort, &timeouts)) {
- returnStatus(StatusCodes::SET_TIMEOUT_ERROR);
+ errorCallback(status(StatusCodes::SET_TIMEOUT_ERROR));
+ return 0;
}
// Error if write fails
if (!WriteFile(hSerialPort, buffer, bufferSize, &bytesWritten, NULL)) {
- returnStatus(StatusCodes::WRITE_ERROR);
+ errorCallback(status(StatusCodes::WRITE_ERROR));
+ return 0;
}
+ writeCallback(bytesWritten);
return bytesWritten;
}
-/**
-* @fn auto getAvailablePorts(void* buffer, const int bufferSize, void* separator) -> int
-* @brief Get all the available serial ports.
-* @param buffer The buffer in which the bytes should be read into
-* @param bufferSize The size of the buffer
-* @param separator The separator for the array buffer
-* @return Returns the current status code (negative) or number of ports found
-*/
-auto windowsSystemGetAvailablePorts(
+auto serialGetPortsInfo(
void* buffer,
const int bufferSize,
void* separator
@@ -242,7 +229,7 @@ auto windowsSystemGetAvailablePorts(
// Error if open fails
if (hPort == INVALID_HANDLE_VALUE) {
CloseHandle(hPort);
- returnStatus(StatusCodes::INVALID_HANDLE_ERROR);
+ continue;
}
portsCounter++;
@@ -250,9 +237,16 @@ auto windowsSystemGetAvailablePorts(
CloseHandle(hPort);
}
+
+ // Remove last trailing comma
+ if (result.length() > 0) {
+ result.erase(result.length() - 1);
+ }
+
// Error if buffer size is to small
if (result.length() + 1 > bufferSize) {
- returnStatus(StatusCodes::BUFFER_ERROR);
+ errorCallback(status(StatusCodes::BUFFER_ERROR));
+ return 0;
}
memcpy(buffer, result.c_str(), result.length() + 1);
@@ -260,4 +254,16 @@ auto windowsSystemGetAvailablePorts(
return portsCounter;
}
+auto serialOnError(void (*func)(int code)) -> void {
+ errorCallback = func;
+};
+
+auto serialOnRead(void (*func)(int bytes)) -> void {
+ readCallback = func;
+};
+
+auto serialOnWrite(void (*func)(int bytes)) -> void {
+ writeCallback = func;
+};
+
#endif