#!/usr/bin/env ruby
# encoding: utf-8
# ruby: 1.9.1

# phones to control
phones = []
phones << {:port => "/dev/ttyO1", :gpio => 117, :l2 => "/tmp/l2_phone1"}


# to flash the phones
OSOMOCON = "/root/osmocom/osmocom-bb/src/host/osmocon/osmocon"
FIRMWARE = "/root/osmocom/osmocom-bb/src/target/firmware/board/compal_e88/layer1.compalram.bin"

# to power the phones
GPIO = "/sys/class/gpio/"

# verify the motoserial cape has been loaded
SLOTS = "/sys/devices/bone_capemgr.9/slots"
unless IO.read(SLOTS).include? "cape-motoserial" then
  puts "loading motoserial cape"
  File.open(SLOTS,"w") do |file|
    file.puts "cape-motoserial"
  end
end
raise "could not load motoserial cape" unless IO.read(SLOTS).include? "cape-motoserial"

def phone_power(phone,power)
  File.open(GPIO+"/gpio#{phone[:gpio]}/value","w") do |file|
    file.puts (power ? "1" : "0")
  end
end

def reset(phone)
  puts "restarting phone on #{phone[:port]}"
  phone_power(phone,false)
  sleep 3
  phone_power(phone,true)
end

threads = []
Thread.abort_on_exception = true
phones.each do |phone|
  threads << Thread.new do
    puts "configuring phone on #{phone[:port]}"
    File.open(GPIO+"/export","w") do |file|
      file.puts phone[:gpio].to_s
    end unless File.exist? GPIO+"/gpio#{phone[:gpio]}"
    File.open(GPIO+"/gpio#{phone[:gpio]}/direction","w") do |file|
      file.puts "out"
    end
    phone_power(phone,false)

    puts "flashing phone on #{phone[:port]}"
    phone[:osmocon] = IO.popen("#{OSOMOCON} -p #{phone[:port]} -s #{phone[:l2]} -m c123xor #{FIRMWARE} 2>&1")
    in_buffer = ""
    reset(phone)
    while true do
      activity = IO.select([phone[:osmocon]],[],[],30)
      if activity and activity[0][0] then
        in_buffer += activity[0][0].readpartial(1024)
        lines = in_buffer.split "\n"
        if in_buffer.end_with? "\n" then
          in_buffer = ""
        else
          in_buffer = lines.pop
        end
        lines.each do |line|
          puts line
          case line
          when "Received FTMTOOL from phone, ramloader has aborted"
            puts "flashing phone on #{phone[:port]} failed"
            reset(phone)
          end
        end
      else # phone is not reacting
        puts "no activity on phone #{phone[:port]}"
        reset(phone)
      end
    end
  end
end
threads.each {|thr| thr.join}

puts "bye bye"
