diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3f8dbc9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,97 @@ +name: CI +on: + workflow_dispatch: + schedule: + - cron: "0 5 * * 3" # At 05:00 on Wednesday # https://crontab.guru/#0_5_*_*_3 + push: + branches: + - master + tags: + - "*.*.*" + pull_request: + types: [opened, synchronize] + branches: + - "*" +permissions: + contents: read + +jobs: + rcd_build: + name: build gem + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.4" + + - name: Build ffi.gem + run: | + bundle install + bundle exec rake gem + + - name: Upload binary gem + uses: actions/upload-artifact@v4 + with: + name: gem + path: pkg/*-*.gem + + job_test_native: + name: native test + needs: rcd_build + strategy: + fail-fast: false + matrix: + os: + - windows-latest + - macos-13 + - macos-latest + - ubuntu-latest + - windows-11-arm + ruby: + - "head" + - "3.4" + - "3.3" + - "3.2" + - "3.1" + - "3.0" + - "2.7" + - "2.6" + - "2.5" + exclude: + - os: macos-latest + ruby: "2.5" + - os: windows-11-arm + ruby: "3.3" + - os: windows-11-arm + ruby: "3.2" + - os: windows-11-arm + ruby: "3.1" + - os: windows-11-arm + ruby: "3.0" + - os: windows-11-arm + ruby: "2.7" + - os: windows-11-arm + ruby: "2.6" + - os: windows-11-arm + ruby: "2.5" + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - run: ruby --version + - name: Download gem + uses: actions/download-artifact@v4 + with: + name: gem + - name: Install gem + run: gem install --local *.gem --verbose + - name: Run tests + run: | + bundle install + ruby -rserialport -S rake test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 00f7828..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: ruby -script: "bundle exec rake test" -rvm: - - 1.8.7 - - 1.9.2 - - 1.9.3 - - 2.0.0 -compiler: - - clang - - gcc -before_script: - - rake compile diff --git a/CHANGELOG b/CHANGELOG index cc7cc6b..44e499e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,14 @@ +1.4.0 => 16-06-2025: [FIXED] Fix compatibility with ruby-3.4. [#79](https://github.com/hparra/ruby-serialport/pull/79) + [FIXED] Replace ancient K&R function declarations by ANSI style. + [FIXED] Fixed various compiler warnings. + [FIXED] Avoid deprecated access to fptr->fd + [CHANGED] New repository link and add Lars Kanis as new author. + [CHANGED] Move CI from Travis to Github + [CHANGED] Use autoload for SerialPort::VERSION + [REMOVED] Remove compatibility to ruby < 2.5 + +1.3.2 => 29-09-2021: [FIXED] Remove calls to rb_secure because it is deprecated and removed in Ruby 3. + 1.3.1 => 07/26/2014: [FIXED] Ruby 2.2 support [NEW] UNIX MARK/SPACE parity (CMSPAR) support diff --git a/Gemfile b/Gemfile index e5dc77e..b4e2a20 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ source "https://rubygems.org/" -source "http://gems.github.com/" + gemspec diff --git a/MANIFEST b/MANIFEST deleted file mode 100644 index 2566ee1..0000000 --- a/MANIFEST +++ /dev/null @@ -1,12 +0,0 @@ -CHANGELOG -MANIFEST -README.md -Rakefile -serialport.gemspec -ext/native/extconf.rb -ext/native/posix_serialport_impl.c -ext/native/serialport.c -ext/native/serialport.h -ext/native/win_serialport_impl.c -lib/serialport.rb -test/miniterm.rb \ No newline at end of file diff --git a/README.md b/README.md index ee29a40..f5f8bfc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ # Ruby/SerialPort -[![Build Status](https://travis-ci.org/hparra/ruby-serialport.png?branch=v1.2.2)](https://travis-ci.org/hparra/ruby-serialport) +[![CI](https://github.com/larskanis/ruby-serialport/actions/workflows/ci.yml/badge.svg)](https://github.com/larskanis/ruby-serialport/actions/workflows/ci.yml) ## Description Ruby/SerialPort is a Ruby library that provides a class for using RS-232 serial ports. This class also contains low-level functions to check and set the current state of the signals on the line. -The native Windows version of this library supports the Microsoft Visual C++, Borland C++, and MinGW compilers. - There is an alternative gem with MRI, JRuby, and Rubinius support. See below. ## Installation @@ -41,3 +39,4 @@ GPL * Tobin Richard * Hector Parra * Ryan C. Payne +* Lars Kanis diff --git a/ext/native/extconf.rb b/ext/native/extconf.rb index 02a8d8b..df36284 100644 --- a/ext/native/extconf.rb +++ b/ext/native/extconf.rb @@ -10,4 +10,7 @@ exit(1) if not have_header("termios.h") or not have_header("unistd.h") end +have_func("rb_io_descriptor") # ruby-3.1+ +have_func("rb_io_open_descriptor") # ruby-3.3+ + create_makefile('serialport') diff --git a/ext/native/posix_serialport_impl.c b/ext/native/posix_serialport_impl.c index 2f9325e..1d8d6b7 100644 --- a/ext/native/posix_serialport_impl.c +++ b/ext/native/posix_serialport_impl.c @@ -61,35 +61,23 @@ static char sTcsetattr[] = "tcsetattr"; static char sIoctl[] = "ioctl"; -int get_fd_helper(obj) - VALUE obj; +int get_fd_helper(VALUE io) { -#ifdef HAVE_RUBY_IO_H - rb_io_t *fptr; +#ifdef HAVE_RB_IO_DESCRIPTOR + return rb_io_descriptor(io); #else - OpenFile *fptr; -#endif - GetOpenFile(obj, fptr); -#ifdef HAVE_RUBY_IO_H - return (fptr->fd); -#else - return (fileno(fptr->f)); + rb_io_t* fp; + GetOpenFile(io, fp); + return fp->fd; #endif } -VALUE sp_create_impl(class, _port) - VALUE class, _port; +VALUE sp_create_impl(VALUE class, VALUE _port) { -#ifdef HAVE_RUBY_IO_H - rb_io_t *fp; -#else - OpenFile *fp; -#endif - int fd; - int num_port; - char *port; - char *ports[] = { + long num_port; + const char *port; + const char *ports[] = { #if defined(OS_LINUX) || defined(OS_CYGWIN) "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyS6", "/dev/ttyS7" @@ -108,16 +96,13 @@ VALUE sp_create_impl(class, _port) #endif }; struct termios params; - - NEWOBJ(sp, struct RFile); - OBJSETUP(sp, class, T_FILE); - MakeOpenFile((VALUE) sp, fp); + VALUE sp; switch(TYPE(_port)) { case T_FIXNUM: - num_port = FIX2INT(_port); - if (num_port < 0 || num_port > sizeof(ports) / sizeof(ports[0])) + num_port = FIX2LONG(_port); + if (num_port < 0 || num_port > (long)(sizeof(ports) / sizeof(ports[0]))) { rb_raise(rb_eArgError, "illegal port number"); } @@ -166,19 +151,12 @@ VALUE sp_create_impl(class, _port) rb_sys_fail(sTcsetattr); } -#ifdef HAVE_RUBY_IO_H - fp->fd = fd; -#else - fp->f = rb_fdopen(fd, "r+"); -#endif - fp->mode = FMODE_READWRITE | FMODE_SYNC; + sp = rb_io_open_descriptor(class, fd, FMODE_READWRITE | FMODE_SYNC, Qnil, Qnil, NULL); - return (VALUE) sp; + return sp; } -VALUE sp_set_modem_params_impl(argc, argv, self) - int argc; - VALUE *argv, self; +VALUE sp_set_modem_params_impl(int argc, VALUE *argv, VALUE self) { int fd; struct termios params; @@ -262,7 +240,21 @@ VALUE sp_set_modem_params_impl(argc, argv, self) #ifdef B1000000 case 1000000: data_rate = B1000000; break; #endif - +#ifdef B1500000 + case 1500000: data_rate = B1500000; break; +#endif +#ifdef B2000000 + case 2000000: data_rate = B2000000; break; +#endif +#ifdef B3000000 + case 3000000: data_rate = B3000000; break; +#endif +#ifdef B3500000 + case 3500000: data_rate = B3500000; break; +#endif +#ifdef B4000000 + case 4000000: data_rate = B4000000; break; +#endif default: rb_raise(rb_eArgError, "unknown baud rate"); break; @@ -399,9 +391,7 @@ VALUE sp_set_modem_params_impl(argc, argv, self) return argv[0]; } -void get_modem_params_impl(self, mp) - VALUE self; - struct modem_params *mp; +void get_modem_params_impl(VALUE self, struct modem_params *mp) { int fd; struct termios params; @@ -493,8 +483,7 @@ void get_modem_params_impl(self, mp) } } -VALUE sp_set_flow_control_impl(self, val) - VALUE self, val; +VALUE sp_set_flow_control_impl(VALUE self, VALUE val) { int fd; int flowc; @@ -540,8 +529,7 @@ VALUE sp_set_flow_control_impl(self, val) return val; } -VALUE sp_get_flow_control_impl(self) - VALUE self; +VALUE sp_get_flow_control_impl(VALUE self) { int ret; int fd; @@ -570,8 +558,7 @@ VALUE sp_get_flow_control_impl(self) return INT2FIX(ret); } -VALUE sp_set_read_timeout_impl(self, val) - VALUE self, val; +VALUE sp_set_read_timeout_impl(VALUE self, VALUE val) { int timeout; int fd; @@ -610,8 +597,7 @@ VALUE sp_set_read_timeout_impl(self, val) return val; } -VALUE sp_get_read_timeout_impl(self) - VALUE self; +VALUE sp_get_read_timeout_impl(VALUE self) { int fd; struct termios params; @@ -630,22 +616,17 @@ VALUE sp_get_read_timeout_impl(self) return INT2FIX(params.c_cc[VTIME] * 100); } -VALUE sp_set_write_timeout_impl(self, val) - VALUE self, val; +NORETURN(VALUE sp_set_write_timeout_impl(VALUE self, VALUE val)) { rb_notimplement(); - return self; } -VALUE sp_get_write_timeout_impl(self) - VALUE self; +NORETURN(VALUE sp_get_write_timeout_impl(VALUE self)) { rb_notimplement(); - return self; } -VALUE sp_break_impl(self, time) - VALUE self, time; +VALUE sp_break_impl(VALUE self, VALUE time) { int fd; @@ -661,9 +642,7 @@ VALUE sp_break_impl(self, time) return Qnil; } -void get_line_signals_helper_impl(obj, ls) - VALUE obj; - struct line_signals *ls; +void get_line_signals_helper_impl(VALUE obj, struct line_signals *ls) { int fd, status; @@ -682,9 +661,7 @@ void get_line_signals_helper_impl(obj, ls) ls->ri = (status & TIOCM_RI ? 1 : 0); } -VALUE set_signal_impl(obj, val, sig) - VALUE obj,val; - int sig; +VALUE set_signal_impl(VALUE obj, VALUE val, int sig) { int status; int fd; @@ -721,20 +698,17 @@ VALUE set_signal_impl(obj, val, sig) return val; } -VALUE sp_set_rts_impl(self, val) - VALUE self, val; +VALUE sp_set_rts_impl(VALUE self, VALUE val) { return set_signal_impl(self, val, TIOCM_RTS); } -VALUE sp_set_dtr_impl(self, val) - VALUE self, val; +VALUE sp_set_dtr_impl(VALUE self, VALUE val) { return set_signal_impl(self, val, TIOCM_DTR); } -VALUE sp_get_rts_impl(self) - VALUE self; +VALUE sp_get_rts_impl(VALUE self) { struct line_signals ls; @@ -742,8 +716,7 @@ VALUE sp_get_rts_impl(self) return INT2FIX(ls.rts); } -VALUE sp_get_dtr_impl(self) - VALUE self; +VALUE sp_get_dtr_impl(VALUE self) { struct line_signals ls; @@ -752,8 +725,7 @@ VALUE sp_get_dtr_impl(self) return INT2FIX(ls.dtr); } -VALUE sp_flush_input_data_impl(self) -VALUE self; +VALUE sp_flush_input_data_impl(VALUE self) { int fd; int ret; @@ -768,8 +740,7 @@ VALUE self; return Qtrue; } -VALUE sp_flush_output_data_impl(self) -VALUE self; +VALUE sp_flush_output_data_impl(VALUE self) { int fd; int ret; diff --git a/ext/native/serialport.c b/ext/native/serialport.c index 88ca9a2..a5850ff 100644 --- a/ext/native/serialport.c +++ b/ext/native/serialport.c @@ -20,14 +20,34 @@ VALUE cSerialPort; /* serial port class */ VALUE sBaud, sDataBits, sStopBits, sParity; /* strings */ VALUE sRts, sDtr, sCts, sDsr, sDcd, sRi; + +#ifndef HAVE_RB_IO_OPEN_DESCRIPTOR +VALUE +io_open_descriptor_fallback(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, void *encoding) +{ + VALUE arguments[2] = { + (rb_update_max_fd(descriptor), INT2NUM(descriptor)), + INT2FIX(mode), + }; + + VALUE self = rb_class_new_instance(2, arguments, klass); + + rb_io_t *fptr; + GetOpenFile(self, fptr); + fptr->pathv = path; + fptr->mode |= mode; + + return self; +} +#endif + /* * @api private * * @see SerialPort#new * @see SerialPort#open */ -static VALUE sp_create(class, _port) - VALUE class, _port; +static VALUE sp_create(VALUE class, VALUE _port) { return sp_create_impl(class, _port); } @@ -47,7 +67,7 @@ static VALUE sp_create(class, _port) * (baud, data_bits = 8, stop_bits = 1, parity = (previous_databits == 8 ? NONE : EVEN)) * A baudrate of nil will keep the old value. * The default parity depends on the number of databits configured before this function call. - * + * * @overload set_modem_params(baud, data_bits, stop_bits, parity) * @param baud [Integer] the baud rate * @param data_bits [Integer] the number of data bits @@ -59,9 +79,7 @@ static VALUE sp_create(class, _port) * @return [Hash] the original paramters * @raise [ArgumentError] if values are invalide or unsupported */ -static VALUE sp_set_modem_params(argc, argv, self) - int argc; - VALUE *argv, self; +static VALUE sp_set_modem_params(int argc, VALUE *argv, VALUE self) { return sp_set_modem_params_impl(argc, argv, self); } @@ -73,20 +91,18 @@ static VALUE sp_set_modem_params(argc, argv, self) * @return [nil] * @note (POSIX) this value is very approximate */ -static VALUE sp_break(self, time) - VALUE self, time; +static VALUE sp_break(VALUE self, VALUE time) { return sp_break_impl(self, time); } /* - * Get the state of the DTR line + * Get the state of the DTR line * * @note (Windows) DTR is not available * @return [Integer] the state of DTR line, 0 or 1 */ -static VALUE sp_get_dtr(self) - VALUE self; +static VALUE sp_get_dtr(VALUE self) { return sp_get_dtr_impl(self); } @@ -97,8 +113,7 @@ static VALUE sp_get_dtr(self) * @return [Integer] the flow control flag * @see SerialPort#set_flow_control */ -static VALUE sp_get_flow_control(self) - VALUE self; +static VALUE sp_get_flow_control(VALUE self) { return sp_get_flow_control_impl(self); } @@ -109,8 +124,7 @@ static VALUE sp_get_flow_control(self) * @return [Integer] the read timeout, in milliseconds * @see SerialPort#set_read_timeout */ -static VALUE sp_get_read_timeout(self) - VALUE self; +static VALUE sp_get_read_timeout(VALUE self) { return sp_get_read_timeout_impl(self); } @@ -121,8 +135,7 @@ static VALUE sp_get_read_timeout(self) * @return [Integer] the state of RTS line, 0 or 1 * @note (Windows) RTS is not available */ -static VALUE sp_get_rts(self) - VALUE self; +static VALUE sp_get_rts(VALUE self) { return sp_get_rts_impl(self); } @@ -133,8 +146,7 @@ static VALUE sp_get_rts(self) * @return [Integer] the write timeout, in milliseconds * @note (POSIX) write timeouts are not implemented */ -static VALUE sp_get_write_timeout(self) - VALUE self; +static VALUE sp_get_write_timeout(VALUE self) { return sp_get_write_timeout_impl(self); } @@ -145,8 +157,7 @@ static VALUE sp_get_write_timeout(self) * @param val [Integer] the desired state of the DTR line, 0 or 1 * @return [Integer] the original +val+ parameter */ -static VALUE sp_set_dtr(self, val) - VALUE self, val; +static VALUE sp_set_dtr(VALUE self, VALUE val) { return sp_set_dtr_impl(self, val); } @@ -161,8 +172,7 @@ static VALUE sp_set_dtr(self, val) * @note SerialPort::HARD uses RTS/CTS handshaking. * DSR/DTR is not supported. */ -static VALUE sp_set_flow_control(self, val) - VALUE self, val; +static VALUE sp_set_flow_control(VALUE self, VALUE val) { return sp_set_flow_control_impl(self, val); } @@ -179,8 +189,7 @@ static VALUE sp_set_flow_control(self, val) * @return [Integer] the original +timeout+ parameter * @note Read timeouts don't mix well with multi-threading */ -static VALUE sp_set_read_timeout(self, val) - VALUE self, val; +static VALUE sp_set_read_timeout(VALUE self, VALUE val) { return sp_set_read_timeout_impl(self, val); } @@ -191,8 +200,7 @@ static VALUE sp_set_read_timeout(self, val) * @param val [Integer] the state of RTS line, 0 or 1 * @return [Integer] the original +val+ parameter */ -static VALUE sp_set_rts(self, val) - VALUE self, val; +static VALUE sp_set_rts(VALUE self, VALUE val) { return sp_set_rts_impl(self, val); } @@ -204,8 +212,7 @@ static VALUE sp_set_rts(self, val) * @return [Integer] the original +val+ parameter * @note (POSIX) write timeouts are not implemented */ -static VALUE sp_set_write_timeout(self, val) - VALUE self, val; +static VALUE sp_set_write_timeout(VALUE self, VALUE val) { return sp_set_write_timeout_impl(self, val); } @@ -213,9 +220,7 @@ static VALUE sp_set_write_timeout(self, val) /* * @private helper */ -static void get_modem_params(self, mp) - VALUE self; - struct modem_params *mp; +static void get_modem_params(VALUE self, struct modem_params *mp) { get_modem_params_impl(self, mp); } @@ -227,8 +232,7 @@ static void get_modem_params(self, mp) * @return [Integer] the original +data_rate+ parameter * @see SerialPort#set_modem_params */ -static VALUE sp_set_data_rate(self, data_rate) - VALUE self, data_rate; +static VALUE sp_set_data_rate(VALUE self, VALUE data_rate) { VALUE argv[4]; @@ -246,8 +250,7 @@ static VALUE sp_set_data_rate(self, data_rate) * @return [Integer] the original +data_bits+ parameter * @see SerialPort#set_modem_params */ -static VALUE sp_set_data_bits(self, data_bits) - VALUE self, data_bits; +static VALUE sp_set_data_bits(VALUE self, VALUE data_bits) { VALUE argv[4]; @@ -265,8 +268,7 @@ static VALUE sp_set_data_bits(self, data_bits) * @return [Integer] the original +stop_bits+ parameter * @see SerialPort#set_modem_params */ -static VALUE sp_set_stop_bits(self, stop_bits) - VALUE self, stop_bits; +static VALUE sp_set_stop_bits(VALUE self, VALUE stop_bits) { VALUE argv[4]; @@ -284,8 +286,7 @@ static VALUE sp_set_stop_bits(self, stop_bits) * @return [Integer] the original +parity+ parameter * @see SerialPort#set_modem_params */ -static VALUE sp_set_parity(self, parity) - VALUE self, parity; +static VALUE sp_set_parity(VALUE self, VALUE parity) { VALUE argv[4]; @@ -302,8 +303,7 @@ static VALUE sp_set_parity(self, parity) * @return [Integer] the current baud rate * @see SerialPort#set_modem_params */ -static VALUE sp_get_data_rate(self) - VALUE self; +static VALUE sp_get_data_rate(VALUE self) { struct modem_params mp; @@ -318,8 +318,7 @@ static VALUE sp_get_data_rate(self) * @return [Integer] the current number of data bits * @see SerialPort#set_modem_params */ -static VALUE sp_get_data_bits(self) - VALUE self; +static VALUE sp_get_data_bits(VALUE self) { struct modem_params mp; @@ -334,8 +333,7 @@ static VALUE sp_get_data_bits(self) * @return [Integer] the current number of stop bits * @see SerialPort#set_modem_params for details */ -static VALUE sp_get_stop_bits(self) - VALUE self; +static VALUE sp_get_stop_bits(VALUE self) { struct modem_params mp; @@ -350,8 +348,7 @@ static VALUE sp_get_stop_bits(self) * @return [Integer] the current parity * @see SerialPort#set_modem_params */ -static VALUE sp_get_parity(self) - VALUE self; +static VALUE sp_get_parity(VALUE self) { struct modem_params mp; @@ -366,8 +363,7 @@ static VALUE sp_get_parity(self) * @return [Hash] the serial port configuration * @see SerialPort#set_modem_params */ -static VALUE sp_get_modem_params(self) - VALUE self; +static VALUE sp_get_modem_params(VALUE self) { struct modem_params mp; VALUE hash; @@ -387,9 +383,7 @@ static VALUE sp_get_modem_params(self) /* * @api private */ -void get_line_signals_helper(obj, ls) - VALUE obj; - struct line_signals *ls; +void get_line_signals_helper(VALUE obj, struct line_signals *ls) { get_line_signals_helper_impl(obj, ls); } @@ -400,8 +394,7 @@ void get_line_signals_helper(obj, ls) * @return [Integer] the state of the CTS line, 0 or 1 * @see SerialPort#get_signals */ -static VALUE sp_get_cts(self) - VALUE self; +static VALUE sp_get_cts(VALUE self) { struct line_signals ls; @@ -416,8 +409,7 @@ static VALUE sp_get_cts(self) * @return [Integer] the state of the DSR line, 0 or 1 * @see SerialPort#get_signals */ -static VALUE sp_get_dsr(self) - VALUE self; +static VALUE sp_get_dsr(VALUE self) { struct line_signals ls; @@ -432,8 +424,7 @@ static VALUE sp_get_dsr(self) * @return [Integer] the state of the DCD line, 0 or 1 * @see SerialPort#get_signals */ -static VALUE sp_get_dcd(self) - VALUE self; +static VALUE sp_get_dcd(VALUE self) { struct line_signals ls; @@ -448,8 +439,7 @@ static VALUE sp_get_dcd(self) * @return [Integer] the state of the RI line, 0 or 1 * @see SerialPort#get_signals */ -static VALUE sp_get_ri(self) - VALUE self; +static VALUE sp_get_ri(VALUE self) { struct line_signals ls; @@ -467,8 +457,7 @@ static VALUE sp_get_ri(self) * @note (Windows) the rts and dtr values are not included * @note This method is implemented as both SerialPort#signals and SerialPort#get_signals */ -static VALUE sp_signals(self) - VALUE self; +static VALUE sp_signals(VALUE self) { struct line_signals ls; VALUE hash; @@ -494,8 +483,7 @@ static VALUE sp_signals(self) * * @return [Boolean] true on success or false if an error occurs. */ -static VALUE sp_flush_input_data(self) - VALUE self; +static VALUE sp_flush_input_data(VALUE self) { return sp_flush_input_data_impl(self); } @@ -505,14 +493,13 @@ static VALUE sp_flush_input_data(self) * * @return [Boolean] true on success or false if an error occurs. */ -static VALUE sp_flush_output_data(self) - VALUE self; +static VALUE sp_flush_output_data(VALUE self) { return sp_flush_output_data_impl(self); } -void Init_serialport() +void Init_serialport(void) { sBaud = rb_str_new2("baud"); sDataBits = rb_str_new2("data_bits"); diff --git a/ext/native/serialport.h b/ext/native/serialport.h index 6aceaf2..8c51412 100644 --- a/ext/native/serialport.h +++ b/ext/native/serialport.h @@ -22,10 +22,11 @@ #define _RUBY_SERIAL_PORT_H_ #include /* ruby inclusion */ -#ifdef HAVE_RUBY_IO_H /* ruby io inclusion */ - #include -#else - #include +#include + +#ifndef HAVE_RB_IO_OPEN_DESCRIPTOR +VALUE io_open_descriptor_fallback(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, void *encoding); +#define rb_io_open_descriptor io_open_descriptor_fallback #endif struct modem_params @@ -56,14 +57,7 @@ struct line_signals #define EVEN EVENPARITY #define ODD ODDPARITY - #ifndef RB_SERIAL_EXPORT - #ifndef HAVE_RUBY_IO_H - #define RB_SERIAL_EXPORT __declspec(dllexport) - #else - #define RB_SERIAL_EXPORT - #endif - #endif - + #define RB_SERIAL_EXPORT #else #define EVEN 1 #define ODD 2 diff --git a/ext/native/win_serialport_impl.c b/ext/native/win_serialport_impl.c index 7ad3910..1f1037d 100644 --- a/ext/native/win_serialport_impl.c +++ b/ext/native/win_serialport_impl.c @@ -33,52 +33,37 @@ static char sGetCommTimeouts[] = "GetCommTimeouts"; static char sSetCommTimeouts[] = "SetCommTimeouts"; -static HANDLE get_handle_helper(obj) - VALUE obj; +static HANDLE get_handle_helper(VALUE io) { -#ifdef HAVE_RUBY_IO_H - rb_io_t *fptr; +#ifdef HAVE_RB_IO_DESCRIPTOR + return (HANDLE) _get_osfhandle(rb_io_descriptor(io)); #else - OpenFile *fptr; -#endif - - GetOpenFile(obj, fptr); -#ifdef HAVE_RUBY_IO_H - return (HANDLE) _get_osfhandle(fptr->fd); -#else - return (HANDLE) _get_osfhandle(fileno(fptr->f)); + rb_io_t* fp; + GetOpenFile(io, fp); + return (HANDLE) _get_osfhandle(fp->fd); #endif } /* hack to work around the fact that Ruby doesn't use GetLastError? */ -static void _rb_win32_fail(const char *function_call) { +static NORETURN( void _rb_win32_fail(const char *function_call) { rb_raise( - rb_eRuntimeError, - "%s failed: GetLastError returns %d", + rb_eRuntimeError, + "%s failed: GetLastError returns %lu", function_call, GetLastError( ) ); -} +}) -VALUE RB_SERIAL_EXPORT sp_create_impl(class, _port) - VALUE class, _port; +VALUE RB_SERIAL_EXPORT sp_create_impl(VALUE class, VALUE _port) { -#ifdef HAVE_RUBY_IO_H - rb_io_t *fp; -#else - OpenFile *fp; -#endif int fd; HANDLE fh; int num_port; char *str_port; char port[260]; /* Windows XP MAX_PATH. See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx */ + VALUE sp; DCB dcb; - NEWOBJ(sp, struct RFile); - OBJSETUP(sp, class, T_FILE); - MakeOpenFile((VALUE) sp, fp); - switch(TYPE(_port)) { case T_FIXNUM: @@ -148,18 +133,11 @@ VALUE RB_SERIAL_EXPORT sp_create_impl(class, _port) } errno = 0; - fp->mode = FMODE_READWRITE | FMODE_BINMODE | FMODE_SYNC; -#ifdef HAVE_RUBY_IO_H - fp->fd = fd; -#else - fp->f = fdopen(fd, "rb+"); -#endif - return (VALUE) sp; + sp = rb_io_open_descriptor(class, fd, FMODE_READWRITE | FMODE_BINMODE | FMODE_SYNC, Qnil, Qnil, NULL); + return sp; } -VALUE RB_SERIAL_EXPORT sp_set_modem_params_impl(argc, argv, self) - int argc; - VALUE *argv, self; +VALUE RB_SERIAL_EXPORT sp_set_modem_params_impl(int argc, VALUE *argv, VALUE self) { HANDLE fh; DCB dcb; @@ -294,9 +272,7 @@ VALUE RB_SERIAL_EXPORT sp_set_modem_params_impl(argc, argv, self) return argv[0]; } -void RB_SERIAL_EXPORT get_modem_params_impl(self, mp) - VALUE self; - struct modem_params *mp; +void RB_SERIAL_EXPORT get_modem_params_impl(VALUE self, struct modem_params *mp) { HANDLE fh; DCB dcb; @@ -314,8 +290,7 @@ void RB_SERIAL_EXPORT get_modem_params_impl(self, mp) mp->parity = dcb.Parity; } -VALUE RB_SERIAL_EXPORT sp_set_flow_control_impl(self, val) - VALUE self, val; +VALUE RB_SERIAL_EXPORT sp_set_flow_control_impl(VALUE self, VALUE val) { HANDLE fh; int flowc; @@ -359,8 +334,7 @@ VALUE RB_SERIAL_EXPORT sp_set_flow_control_impl(self, val) return val; } -VALUE RB_SERIAL_EXPORT sp_get_flow_control_impl(self) - VALUE self; +VALUE RB_SERIAL_EXPORT sp_get_flow_control_impl(VALUE self) { HANDLE fh; int ret; @@ -387,8 +361,7 @@ VALUE RB_SERIAL_EXPORT sp_get_flow_control_impl(self) return INT2FIX(ret); } -VALUE RB_SERIAL_EXPORT sp_set_read_timeout_impl(self, val) - VALUE self, val; +VALUE RB_SERIAL_EXPORT sp_set_read_timeout_impl(VALUE self, VALUE val) { int timeout; HANDLE fh; @@ -430,8 +403,7 @@ VALUE RB_SERIAL_EXPORT sp_set_read_timeout_impl(self, val) return val; } -VALUE RB_SERIAL_EXPORT sp_get_read_timeout_impl(self) - VALUE self; +VALUE RB_SERIAL_EXPORT sp_get_read_timeout_impl(VALUE self) { HANDLE fh; COMMTIMEOUTS ctout; @@ -453,8 +425,7 @@ VALUE RB_SERIAL_EXPORT sp_get_read_timeout_impl(self) return INT2FIX(ctout.ReadTotalTimeoutConstant); } -VALUE RB_SERIAL_EXPORT sp_set_write_timeout_impl(self, val) - VALUE self, val; +VALUE RB_SERIAL_EXPORT sp_set_write_timeout_impl(VALUE self, VALUE val) { int timeout; HANDLE fh; @@ -488,8 +459,7 @@ VALUE RB_SERIAL_EXPORT sp_set_write_timeout_impl(self, val) return val; } -VALUE RB_SERIAL_EXPORT sp_get_write_timeout_impl(self) - VALUE self; +VALUE RB_SERIAL_EXPORT sp_get_write_timeout_impl(VALUE self) { HANDLE fh; COMMTIMEOUTS ctout; @@ -503,8 +473,7 @@ VALUE RB_SERIAL_EXPORT sp_get_write_timeout_impl(self) return INT2FIX(ctout.WriteTotalTimeoutMultiplier); } -static void delay_ms(time) - int time; +static void delay_ms(int time) { HANDLE ev; @@ -522,8 +491,7 @@ static void delay_ms(time) CloseHandle(ev); } -VALUE RB_SERIAL_EXPORT sp_break_impl(self, time) - VALUE self, time; +VALUE RB_SERIAL_EXPORT sp_break_impl(VALUE self, VALUE time) { HANDLE fh; @@ -541,9 +509,7 @@ VALUE RB_SERIAL_EXPORT sp_break_impl(self, time) return Qnil; } -void RB_SERIAL_EXPORT get_line_signals_helper_impl(obj, ls) - VALUE obj; - struct line_signals *ls; +void RB_SERIAL_EXPORT get_line_signals_helper_impl(VALUE obj, struct line_signals *ls) { HANDLE fh; unsigned long status; /* DWORD */ @@ -560,9 +526,7 @@ void RB_SERIAL_EXPORT get_line_signals_helper_impl(obj, ls) ls->ri = (status & MS_RING_ON ? 1 : 0); } -static VALUE set_signal(obj, val, sigoff, sigon) - VALUE obj,val; - int sigoff, sigon; +static VALUE set_signal(VALUE obj, VALUE val, int sigoff, int sigon) { HANDLE fh; int set, sig; @@ -592,36 +556,35 @@ static VALUE set_signal(obj, val, sigoff, sigon) return val; } -VALUE RB_SERIAL_EXPORT sp_set_rts_impl(self, val) - VALUE self, val; +VALUE RB_SERIAL_EXPORT sp_set_rts_impl(VALUE self, VALUE val) { return set_signal(self, val, CLRRTS, SETRTS); } -VALUE RB_SERIAL_EXPORT sp_set_dtr_impl(self, val) - VALUE self, val; +VALUE RB_SERIAL_EXPORT sp_set_dtr_impl(VALUE self, VALUE val) { return set_signal(self, val, CLRDTR, SETDTR); } -VALUE RB_SERIAL_EXPORT sp_get_rts_impl(self) - VALUE self; +VALUE RB_SERIAL_EXPORT sp_get_rts_impl(VALUE self) { rb_notimplement(); return self; } -VALUE RB_SERIAL_EXPORT sp_get_dtr_impl(self) - VALUE self; +VALUE RB_SERIAL_EXPORT sp_get_dtr_impl(VALUE self) { rb_notimplement(); return self; } +#ifndef PURGE_RXABORT #define PURGE_RXABORT 0x02 +#endif +#ifndef PURGE_RXCLEAR #define PURGE_RXCLEAR 0x08 -VALUE RB_SERIAL_EXPORT sp_flush_input_data_impl(self) - VALUE self; +#endif +VALUE RB_SERIAL_EXPORT sp_flush_input_data_impl(VALUE self) { BOOL ret; HANDLE fh; @@ -635,10 +598,13 @@ VALUE RB_SERIAL_EXPORT sp_flush_input_data_impl(self) return Qtrue; } +#ifndef PURGE_TXABORT #define PURGE_TXABORT 0x01 +#endif +#ifndef PURGE_TXCLEAR #define PURGE_TXCLEAR 0x04 -VALUE RB_SERIAL_EXPORT sp_flush_output_data_impl(self) - VALUE self; +#endif +VALUE RB_SERIAL_EXPORT sp_flush_output_data_impl(VALUE self) { BOOL ret; HANDLE fh; diff --git a/lib/serialport.rb b/lib/serialport.rb index 8062770..4b83349 100644 --- a/lib/serialport.rb +++ b/lib/serialport.rb @@ -1,5 +1,4 @@ require 'serialport.so' -require 'serialport/version' # This class is used for communication over a serial port. @@ -7,7 +6,9 @@ # # @see http://rubydoc.info/stdlib/core/IO Ruby IO class # @see http://www.cmrr.umn.edu/~strupp/serial.html "Serial Programming Guide for POSIX Operating Systems" -class SerialPort +class SerialPort < IO + autoload :VERSION, 'serialport/version' + private_class_method(:create) # Creates a serial port object. diff --git a/lib/serialport/version.rb b/lib/serialport/version.rb index 718c16c..ab5d5e1 100644 --- a/lib/serialport/version.rb +++ b/lib/serialport/version.rb @@ -1,3 +1,3 @@ -class SerialPort - VERSION = "1.3.2" +class SerialPort < IO + VERSION = "1.4.0" end diff --git a/serialport.gemspec b/serialport.gemspec index dc574a9..0addaba 100644 --- a/serialport.gemspec +++ b/serialport.gemspec @@ -1,16 +1,18 @@ # -*- encoding: utf-8 -*- -require File.expand_path('../lib/serialport/version', __FILE__) +$: << "lib" +require "serialport/version" Gem::Specification.new do |s| s.name = "serialport" s.license = "GPL-2" s.version = SerialPort::VERSION - s.authors = ["Guillaume Pierronnet", "Alan Stern", "Daniel E. Shipton", "Tobin Richard", "Hector Parra", "Ryan C. Payne"] + s.authors = ["Guillaume Pierronnet", "Alan Stern", "Daniel E. Shipton", "Tobin Richard", "Hector Parra", "Ryan C. Payne", "Lars Kanis"] s.summary = "Library for using RS-232 serial ports." s.description = "Ruby/SerialPort is a Ruby library that provides a class for using RS-232 serial ports." - s.email = "hector@hectorparra.com" - s.homepage = "http://github.com/hparra/ruby-serialport/" + s.email = "lars@greiz-reinsdorf.de" + s.homepage = "http://github.com/larskanis/ruby-serialport/" + s.required_ruby_version = '>= 2.5' s.add_development_dependency "bundler" s.add_development_dependency "rake" s.add_development_dependency "rake-compiler", ">= 0.4.1"