Skip to content

Commit

Permalink
device spy test
Browse files Browse the repository at this point in the history
  • Loading branch information
lhoward committed Jan 11, 2024
1 parent b228885 commit 0b11897
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
69 changes: 69 additions & 0 deletions Examples/IORingDeviceSpy/IORingDeviceSpy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Copyright (c) 2024 PADL Software Pty Ltd
//
// Licensed under the Apache License, Version 2.0 (the License);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Glibc
import IORing
import IORingUtils

@main
public struct IORingDeviceSpy {
private let blockSize: Int
private let ring: IORing

public static func main() async throws {
if CommandLine.arguments.count < 2 {
print("Usage: \(CommandLine.arguments[0]) [device] <[block_size]>")
exit(1)
}

let blockSize: Int

if CommandLine.arguments.count > 2 {
blockSize = Int(CommandLine.arguments[2])!
} else {
blockSize = 1
}

let spy = try await IORingDeviceSpy(blockSize: blockSize)
let device = CommandLine.arguments[1]

try await spy.spy(device: device)
}

init(blockSize: Int = 1) async throws {
ring = IORing.shared
self.blockSize = blockSize

try await ring.registerFixedBuffers(count: 1, size: blockSize)
}

func spy(device: String) async throws {
let fd = try FileHandle(fileDescriptor: open(device, O_RDONLY), closeOnDealloc: true)

try fd.setBlocking(false)
if fd.isATty {
var tty = try fd.getTty()
try tty.setN81(speed: 115_200)
try fd.set(tty: tty)
}

repeat {
try await ring.readFixed(count: blockSize, bufferIndex: 0, from: fd) {
print($0.map { String(format: "%02x", $0) }.joined())
}
} while !Task.isCancelled
}
}
6 changes: 6 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ let package = Package(
path: "Examples/IORingUDPServer",
linkerSettings: [] + ASANLinkerSettings
),
.executableTarget(
name: "IORingDeviceSpy",
dependencies: ["IORing", "IORingUtils"],
path: "Examples/IORingDeviceSpy",
linkerSettings: [] + ASANLinkerSettings
),
],
cLanguageStandard: .c18,
cxxLanguageStandard: .cxx20
Expand Down
107 changes: 107 additions & 0 deletions Sources/IORingUtils/Tty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//
// Copyright (c) 2024 PADL Software Pty Ltd
//
// Licensed under the Apache License, Version 2.0 (the License);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Glibc
import IORing

public enum Parity {
case none
case odd
case even
}

public enum StopBits {
case one
case two
}

public enum DataBits {
case seven
case eight
}

public extension termios {
mutating func setN81(speed: UInt32) throws {
try makeRaw()
try set(speed: speed)
set(parity: .none)
set(stopBits: .one)
set(dataBits: .eight)
}

mutating func makeRaw() throws {
cfmakeraw(&self)
}

mutating func set(speed: UInt32) throws {
var tty = self
try Errno.throwingErrno {
cfsetspeed(&tty, speed)
}
self = tty
}

mutating func set(parity: Parity) {
switch parity {
case .none:
c_cflag &= ~tcflag_t(PARENB | PARODD)
case .odd:
c_cflag |= tcflag_t(PARENB | PARODD)
case .even:
c_cflag |= tcflag_t(PARENB)
c_cflag &= ~tcflag_t(PARODD)
}
}

mutating func set(stopBits: StopBits) {
switch stopBits {
case .two:
c_cflag |= tcflag_t(CSTOPB)
case .one:
c_cflag &= ~tcflag_t(CSTOPB)
}
}

mutating func set(dataBits: DataBits) {
switch dataBits {
case .eight:
c_cflag |= tcflag_t(CS8)
case .seven:
c_cflag |= tcflag_t(CS7)
}
}
}

public extension FileDescriptorRepresentable {
func set(tty: termios) throws {
var tty = tty
try Errno.throwingErrno {
tcsetattr(self.fileDescriptor, TCSANOW, &tty)
}
}

func getTty() throws -> termios {
var tty = termios()
try Errno.throwingErrno {
tcgetattr(self.fileDescriptor, &tty)
}
return tty
}

var isATty: Bool {
isatty(fileDescriptor) != 0
}
}

0 comments on commit 0b11897

Please sign in to comment.