123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- package main
-
- import (
- "flag"
- "fmt"
- "os"
- )
-
- func main() {
-
- var serial, option, value int
- var valueStr string
- var listOptions bool
-
- flag.BoolVar(&listOptions, "l", false, "list options and exit")
- flag.IntVar(&serial, "s", 0, "serial number of receiver")
- flag.IntVar(&option, "o", 0, "option number (use -l to list)")
- flag.StringVar(&valueStr, "v", "", "option value in hex (typically 00 = enable, FF = disable)")
-
- flag.Parse()
-
- if listOptions {
- for i, name := range optionNames {
- if name == "" {
- continue
- }
- fmt.Printf("Option %2d = %s\n", i, name)
- }
- os.Exit(0)
- }
-
- if serial == 0 || option == 0 || valueStr == "" {
- flag.PrintDefaults()
- os.Exit(1)
-
- }
-
- if option < 0 || option > 59 {
- fmt.Printf("Option number %d is out of range (allowed: 0-59)\n", option)
- os.Exit(1)
- }
-
- n, err := fmt.Sscanf(valueStr, "%2x", &value)
-
- if n == 0 || err != nil {
- fmt.Println("Unable to parse option value.")
- os.Exit(1)
- }
-
- e := encrypt(serial, option, value)
-
- fmt.Printf("Receiver Serial Number: %d\n", serial)
- if option < len(optionNames) {
- fmt.Printf("Option Number: %d (%s)\n", option, optionNames[option])
- } else {
- fmt.Printf("Option Number: %d (out of range)\n", option)
- }
- fmt.Printf("Option Value: %02X\n", value)
- fmt.Printf("Code: %s\n", e)
-
- return
-
- }
-
- func encrypt(serialNumber, feature, value int) string {
-
- passwordStr := fmt.Sprintf("%05d%02d%02X", serialNumber, feature, value)
-
- password := []byte(passwordStr)
-
- fromASCII(password)
-
- sn := byte(serialNumber) & 0xF
- secret := []byte{7, 7, 5, 5, 9, 8, 1, 4, 2}
-
- encrypted := make([]byte, 10)
-
- for x := 0; x < 9; x++ {
- encrypted[8-x] = sn ^ secret[8-x] ^ reverseBits(password[x])
- }
-
- encrypted[9] = calculateCheck(encrypted)
-
- toASCII(encrypted)
-
- return string(encrypted)
-
- }
-
- func decrypt(serialNumber int, passwordStr string) (int, int, int, error) {
-
- if len(passwordStr) != 10 {
- return 0, 0, 0, fmt.Errorf("password must be 10 characters long")
- }
- password := []byte(passwordStr)
-
- fromASCII(password)
-
- sum := calculateCheck(password)
- if password[9] != sum {
- return 0, 0, 0, fmt.Errorf("bad checksum")
- }
-
- sn := byte(serialNumber) & 0xF
- secret := []byte{7, 7, 5, 5, 9, 8, 1, 4, 2}
-
- decrypted := make([]byte, 9)
-
- for x := 0; x < 9; x++ {
- decrypted[8-x] = reverseBits(sn ^ secret[x] ^ password[x])
- }
-
- toASCII(decrypted)
-
- var serial, option, value int
-
- _, err := fmt.Sscanf(string(decrypted), "%5d%2d%2X", &serial, &option, &value)
- if err != nil {
- return 0, 0, 0, err
- }
- return serial, option, value, nil
-
- }
-
- func calculateCheck(password []byte) byte {
- sum := 0
-
- for i := 8; i >= 0; i-- {
- for j := 3; j >= 0; j-- {
- sum += int(password[i]) >> j & 1
- }
- }
-
- return byte(sum & 0xF)
- }
-
- func reverseBits(in byte) byte {
- var out byte
- for i := 0; i < 4; i++ {
- if in&(1<<i) != 0 {
- out |= 1 << (3 - i)
- }
- }
- return out
- }
-
- func fromASCII(s []byte) {
- for i, b := range s {
- if b > '9' {
- s[i] -= '7'
- } else {
- s[i] -= '0'
- }
- }
- }
-
- func toASCII(s []byte) {
- for i, b := range s {
- if b > 9 {
- s[i] += '7'
- } else {
- s[i] += '0'
- }
- }
- }
-
- var optionNames = []string{
- "POWER UP PORT SETTINGS",
- "POWER UP OUTPUT MSGS",
- "LOCATOR",
- "POWER UP NV ERASE",
- "RTCM ASCII",
- "CYCLE PRINT",
- "POSITION STATISTICS",
- "TAILBOUY",
- "PATHFINDER",
- "LANDSEIS",
- "RTCM NETWORK INPUT",
- "CARRIER PHASE",
- "HALF CYCLE L2",
- "MAXWELL L1 ONLY",
- "REMOTE DOWNLOAD",
- "DEMO EQUIPMENT ONLY",
- "",
- "RT SURVEY DATA",
- "LOCAL DATUMS",
- "RSIM INTERFACE",
- "DUAL FREQ / MULTI-BIT",
- "RS-232 PORTS",
- "MULTIPLE DATUMS",
- "EXTERNAL TIMEBASE",
- "EVENT MARKER",
- "1 PPS",
- "",
- "FIRMWARE UPDATE",
- "RTCM INPUTS",
- "RTCM OUTPUTS",
- "SYNC INTERVAL",
- "NMEA-0183",
- "SV SWAPPING",
- "KEYBOARD TYPE",
- "NAVIGATION",
- "LctrCrPh",
- "KINEMATIC",
- "CONFIGURED",
- "DATA LOGGING SIZE",
- "SURVEY TYPE",
- "RTK OTF CAPABILITIES",
- "IONO-FREE POSITIONING",
- "",
- "I/O DRIVERS",
- "",
- "CMR TYPE2 RATE",
- "RTK SPECIALS",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- }
|