From 421bf33d6a1bd1b9b891ef613af59b1b83b81e1a Mon Sep 17 00:00:00 2001 From: Torsten Harenberg Date: Mon, 20 Dec 2021 14:21:43 +0100 Subject: [PATCH] first running version --- main.go | 35 ++++++++++++++++++--- update/update.go | 79 +++++++++++++++++++++++++++++++++++++----------- usb/usb.go | 2 ++ 3 files changed, 94 insertions(+), 22 deletions(-) diff --git a/main.go b/main.go index 559e057..c04cbd9 100644 --- a/main.go +++ b/main.go @@ -14,9 +14,10 @@ import ( func main() { parser := argparse.NewParser("go-scsupdate", "Update Firmware of SCS PACTOR modems") serialDevice := parser.String("s", "serialDevice", &argparse.Options{Required: false, Help: "(optional) serial device the modem is attached to, e.g. /dev/ttyUSB0. If not set, go-scsupdate will search for SCS modems."}) - _ = parser.String("b", "baudrate", &argparse.Options{Required: false, Help: "(optional) sets the serial baudrate, e.g. 115200"}) + brate := parser.Int("b", "baudrate", &argparse.Options{Required: false, Help: "(optional, required when -s is set) sets the serial baudrate, e.g. 115200"}) f := parser.String("f", "file", &argparse.Options{Required: true, Help: "(required) the file to flash, e.g. profi41r.pro"}) debug := parser.Flag("d", "debug", &argparse.Options{Required: false, Help: "(optional) enable debug logs"}) + dryrun := parser.Flag("n", "dryrun", &argparse.Options{Required: false, Help: "(optional) drying: if set, modem will detected but no firmware being written"}) err := parser.Parse(os.Args) cLog := console.New(true) if *debug { @@ -25,6 +26,10 @@ func main() { } else { log.AddHandler(cLog, log.InfoLevel, log.ErrorLevel, log.AlertLevel, log.WarnLevel, log.NoticeLevel, log.PanicLevel) } + + if *serialDevice != "" && *brate == 0 { + log.Fatal("ERROR: if you specify a device, you need to specify a baud rate as well. Cannot continue") + } if err != nil { log.Fatal(parser.Usage(err)) os.Exit(1) @@ -41,10 +46,14 @@ func main() { msg += fmt.Sprintf("Port: %30s : Name: %s\n", p.Port, p.Name) } log.Fatal(msg) + } else { // exactly one modem found, that's how we like it :-) + log.Infof("Found %s modem at port %s. Default baud rate is: %d", ports[0].Name, ports[0].Port, ports[0].Baudrate) } } else { log.Fatal("Error while seaching SCS modems: ", err) } + } else { + log.Notice("Using given device! Will not check if firmware fits your modem!") } if !firmware.FwExists(*f) { @@ -58,9 +67,27 @@ func main() { log.Debug("checks passed") } - err = update.Update("/dev/ttyUSB0", 829400, *f) - if err != nil { - log.Panic(err) + baudrate := 0 + if *brate != 0 { + baudrate = *brate + log.Infof("Using given baudrate of %d", baudrate) + } else { + baudrate = ports[0].Baudrate + log.Infof("Using default baudrate of %d", baudrate) + } + + if *dryrun != true { + var err error + if *serialDevice != "" { + err = update.Update(*serialDevice, baudrate, *f) + } else { + err = update.Update(ports[0].Port, baudrate, *f) + } + if err != nil { + log.Panic(err) + } + } else { + log.Info("Dryrun requested, no firmware written!") } } diff --git a/update/update.go b/update/update.go index bb4c51c..8939c43 100644 --- a/update/update.go +++ b/update/update.go @@ -2,6 +2,7 @@ package update import ( "encoding/binary" + "encoding/hex" "errors" "fmt" "github.com/albenik/go-serial/v2" @@ -26,8 +27,8 @@ func initmodem(serport string, baudrate int) (*modem, error) { serial.WithDataBits(8), serial.WithParity(serial.NoParity), serial.WithStopBits(serial.OneStopBit), - serial.WithReadTimeout(1000), - serial.WithWriteTimeout(1000)) + serial.WithReadTimeout(70), + serial.WithWriteTimeout(70)) // 50 was not stable, bump to 70 if err != nil { fmt.Printf("ERROR: File %s could not be opened\n", serport) return nil, err @@ -40,11 +41,20 @@ func (m *modem) write(out string, nolog ...bool) ([]byte, error) { if len(nolog) == 0 { log.Debug("Sending " + out) } else { - log.Debugf("Sending %d byte(s)", len(out)) + if len(out) < 200 { // in other cases it's the firmware! + log.Debugf("Sending %d byte(s)", len(out)) + } + } + _, err := m.port.Write([]byte(out)) + if err != nil { + log.Errorf("ERROR while sending serial command: %s\n", out) + log.Error(err) + return []byte(""), err } - m.port.Write([]byte(out)) buff := make([]byte, 1024) - time.Sleep(100 * time.Millisecond) // give the PTC some time to answer + if len(nolog) == 0 { + time.Sleep(50 * time.Millisecond) // give the PTC some time to answer, no needed with binary + } n, err := m.port.Read(buff) // fmt.Printf("Read %d bytes\n", n) if err != nil { @@ -63,7 +73,6 @@ func (m *modem) getSerNum() (string, error) { } re := regexp.MustCompile(`Serial number: \w{2,16}`) sn := strings.ReplaceAll(string(re.Find(answer)), "Serial number: ", "") - log.Infof("Serial Number is: %s", sn) return sn, nil } @@ -94,11 +103,7 @@ func (m *modem) writeUpdate(fwfile string) error { _, _ = m.write("\033", true) // send ESC to cancel the update return err } - // TODO: remove that once write process is established - _, err = m.write("\033", true) - if err != nil { - return err - } + log.Infof("flash stamp: % X", binary.LittleEndian.Uint32(answer[2:6])) flashId := binary.LittleEndian.Uint16(answer[0:2]) log.Infof("flash id: % X", flashId) @@ -113,9 +118,9 @@ func (m *modem) writeUpdate(fwfile string) error { } fstat, _ := r.Stat() fsize := fstat.Size() - r.Close() + _ = r.Close() - _, err = ioutil.ReadFile(fwfile) + fwblob, err := ioutil.ReadFile(fwfile) if err != nil { _, _ = m.write("\033", true) // send ESC to cancel the update return err @@ -126,13 +131,44 @@ func (m *modem) writeUpdate(fwfile string) error { chunks++ } - // a := make([]byte, 2) - // binary.BigEndian.PutUint16(a, chunks) + // send ACK + _, err = m.write("\006", true) + if err != nil { + _, _ = m.write("\033", true) // send ESC to cancel the update + return err + } + + // send number of chunks + a := make([]byte, 2) + binary.BigEndian.PutUint16(a, chunks) + res, err := m.write(string(a), true) + if err != nil || string(res) != "\006" { //no ACK + _, _ = m.write("\033", true) // send ESC to cancel the update + return err + } bar := progressbar.Default(int64(chunks), "flashing chunk") + var sendbuff string = "" for i := 0; i < int(chunks); i++ { - bar.Add(1) - time.Sleep(3 * time.Millisecond) + _ = bar.Add(1) + //log.Debugf("Sending chunk %d", i) + if i*CHUNKSIZE+CHUNKSIZE > len(fwblob) { + nullbytes := make([]byte, CHUNKSIZE-len(fwblob[(i*CHUNKSIZE):])) + sendbuff = string(append(fwblob[(i*CHUNKSIZE):], nullbytes...)) + } else { + sendbuff = string(fwblob[i*CHUNKSIZE : i*CHUNKSIZE+CHUNKSIZE]) + } + res, err = m.write(sendbuff, true) + if err != nil || string(res) != "\006" { //no ACK + _, _ = m.write("\033", true) // send ESC to cancel the update + log.Errorf("Error in Handshake! Rx: %s", hex.EncodeToString(res)) + return err + } + } + log.Infof("Firmware file %s successfully written", fwfile) + _, err = m.write("\r", true) + if err != nil { + log.Error("Error in Handshake: cannot send final cr") } return nil } @@ -143,7 +179,14 @@ func Update(serport string, baudrate int, fwfile string) error { if err != nil { return errors.New("FEHLER in Update") } - _, _ = m.getSerNum() + sn, err := m.getSerNum() + if len(sn) < 6 { + // can't be a valid serial number, something's wrong, bump out here + log.Errorf("ERROR: got invalid serial number: %s", sn) + return err + } else { + log.Infof("Serial number of your modem is: %s", sn) + } if m.setDateTime() != nil { return err } diff --git a/usb/usb.go b/usb/usb.go index bfecf46..98f19a5 100644 --- a/usb/usb.go +++ b/usb/usb.go @@ -40,7 +40,9 @@ var scsbaudrates map[string]int = map[string]int{ func FindSCS() ([]Scsid, error) { foundids := []Scsid{} + ports, err := enumerator2.GetDetailedPortsList() + if err != nil { return nil, err }