Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented ioctl call to set custom baud rate on OSX #48

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/rubyserial/osx_constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module Posix
CCTS_OFLOW = 0x00010000 # Clearing this disables RTS AND CTS.
TCSANOW = 0
NCCS = 20
IOSSIOSPEED = 0x80045402 # ioctl request for OSX custom baud rate

DATA_BITS = {
5 => 0x00000000,
Expand Down Expand Up @@ -188,6 +189,7 @@ class Termios < FFI::Struct

attach_function :tcsetattr, [ :int, :int, RubySerial::Posix::Termios ], :int, blocking: true
attach_function :fcntl, [:int, :int, :varargs], :int, blocking: true
attach_function :ioctl, [:int, :ulong, :pointer], :int, blocking: true
attach_function :open, [:pointer, :int], :int, blocking: true
attach_function :close, [:int], :int, blocking: true
attach_function :write, [:int, :pointer, :int],:int, blocking: true
Expand Down
43 changes: 35 additions & 8 deletions lib/rubyserial/posix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ def initialize(address, baude_rate=9600, data_bits=8, parity=:none, stop_bits=1)
raise RubySerial::Error, RubySerial::Posix::ERROR_CODES[FFI.errno]
end

@config = build_config(baude_rate, data_bits, parity, stop_bits)

err = RubySerial::Posix.tcsetattr(@fd, RubySerial::Posix::TCSANOW, @config)
if err == -1
raise RubySerial::Error, RubySerial::Posix::ERROR_CODES[FFI.errno]
end
set_termios_attrs(baude_rate, data_bits, parity, stop_bits)
end

def closed?
Expand Down Expand Up @@ -108,12 +103,29 @@ def get_until_sep(sep, limit)
bytes.map { |e| e.chr }.join
end

def set_termios_attrs(baude_rate, data_bits, parity, stop_bits)
@config = build_config(baude_rate, data_bits, parity, stop_bits)

err = RubySerial::Posix.tcsetattr(@fd, RubySerial::Posix::TCSANOW, @config)
if err == -1
raise RubySerial::Error, RubySerial::Posix::ERROR_CODES[FFI.errno]
end

set_custom_baud_rate(baude_rate) if osx_custom_speed?(baude_rate)
end

def build_config(baude_rate, data_bits, parity, stop_bits)
config = RubySerial::Posix::Termios.new

# Use a standard speed of 9600 for tcsetattr config if we are on OSX
# and trying to set non-standard speed value. We can later set it using ioctl
tc_baude_rate = RubySerial::Posix::BAUDE_RATES[
osx_custom_speed?(baude_rate) ? 9600 : baude_rate
]

config[:c_iflag] = RubySerial::Posix::IGNPAR
config[:c_ispeed] = RubySerial::Posix::BAUDE_RATES[baude_rate]
config[:c_ospeed] = RubySerial::Posix::BAUDE_RATES[baude_rate]
config[:c_ispeed] = tc_baude_rate
config[:c_ospeed] = tc_baude_rate
config[:c_cflag] = RubySerial::Posix::DATA_BITS[data_bits] |
RubySerial::Posix::CREAD |
RubySerial::Posix::CLOCAL |
Expand All @@ -129,4 +141,19 @@ def build_config(baude_rate, data_bits, parity, stop_bits)

config
end

def osx_custom_speed?(baude_rate)
!RubySerial::ON_LINUX && !RubySerial::Posix::BAUDE_RATES[baude_rate]
end

def set_custom_baud_rate(baude_rate)
rate_pointer = FFI::MemoryPointer.new(:uint, 1)
rate_pointer.put(:uint, 0, baude_rate)

err = RubySerial::Posix.ioctl(@fd, RubySerial::Posix::IOSSIOSPEED, rate_pointer)

if err == -1
raise RubySerial::Error, RubySerial::Posix::ERROR_CODES[FFI.errno]
end
end
end