require 'pty' SOH = 0x01 EOT = 0x04 ACK = 0x06 NAK = 0x15 SUB = 0x1A BLOCKSIZE = 128 infile, outfile = ARGV File.open(infile, 'rb') do |f| PTY.spawn('rx', '-b', outfile) do |stdout, stdin, _pid| loop do break if stdout.readbyte == NAK end block = '' blocknum = 1 loop do block = f.read(BLOCKSIZE) break unless block block += SUB.chr * (BLOCKSIZE - block.size) if block.size < BLOCKSIZE loop do inv_blocknum = 0xFF - blocknum stdin.putc(SOH) stdin.putc(blocknum) stdin.putc(inv_blocknum) checksum = block.bytes.reduce(0, &:+) & 0xFF stdin.print(block) stdin.putc(checksum) control = stdout.readbyte break if control == ACK raise('unexpected byte') unless control == NAK end blocknum = (blocknum + 1) & 0xFF end stdin.putc(EOT) control = stdout.readbyte control == ACK || raise('transmission error') end end