altosui: write USB serial number string while flashing
authorKeith Packard <keithp@keithp.com>
Tue, 24 Aug 2010 11:02:27 +0000 (04:02 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 24 Aug 2010 11:02:27 +0000 (04:02 -0700)
USB serial number is encoded in UCS2 as a part of the string
descriptors. Place those right after the other rom config bits so that
altosui can find it. altosui is changed to write the serial number there.

Signed-off-by: Keith Packard <keithp@keithp.com>
ao-tools/altosui/AltosRomconfig.java
ao-tools/altosui/AltosRomconfigUI.java
src/ao.h
src/ao_product.c

index 844da7c4b7aad021b969453a01616b2ed86fb0f1..8c9cb27aa1207971ee21218ce058c9b02bc02652 100644 (file)
@@ -47,14 +47,57 @@ public class AltosRomconfig {
                }
        }
 
+       static void put_string(String value, byte[] bytes, int start) {
+               for (int i = 0; i < value.length(); i++)
+                       bytes[start + i] = (byte) value.charAt(i);
+       }
+
+       static final int AO_USB_DESC_STRING     = 3;
+
+       static void put_usb_serial(int value, byte[] bytes, int start) {
+               int offset = start + 0xa;
+               int string_num = 0;
+               System.out.printf("Put usb serial %d\n", value);
+
+               while (offset < bytes.length && bytes[offset] != 0) {
+                       if (bytes[offset + 1] == AO_USB_DESC_STRING) {
+                               ++string_num;
+                               if (string_num == 4)
+                                       break;
+                       }
+                       offset += ((int) bytes[offset]) & 0xff;
+               }
+               System.out.printf("offset %d content %d\n",
+                                 offset, bytes[offset]);
+               if (offset >= bytes.length || bytes[offset] == 0)
+                       return;
+               int len = ((((int) bytes[offset]) & 0xff) - 2) / 2;
+               String fmt = String.format("%%0%dd", len);
+               System.out.printf("existing serial length %d format %s\n", len, fmt);
+
+               String s = String.format(fmt, value);
+               if (s.length() != len) {
+                       System.out.printf("weird usb length issue %s isn't %d\n",
+                                         s, len);
+                       return;
+               }
+               for (int i = 0; i < len; i++) {
+                       bytes[offset + 2 + i*2] = (byte) s.charAt(i);
+                       bytes[offset + 2 + i*2+1] = 0;
+               }
+       }
+
        public AltosRomconfig(byte[] bytes, int offset) {
                version = get_int(bytes, offset + 0, 2);
                check = get_int(bytes, offset + 2, 2);
+               System.out.printf("version %d check %d\n", version, check);
                if (check == (~version & 0xffff)) {
                        switch (version) {
+                       case 2:
                        case 1:
                                serial_number = get_int(bytes, offset + 4, 2);
                                radio_calibration = get_int(bytes, offset + 6, 4);
+                               System.out.printf("serial %d cal %d\n", serial_number, radio_calibration);
                                valid = true;
                                break;
                        }
@@ -77,6 +120,8 @@ public class AltosRomconfig {
                        throw new IOException("image does not contain existing rom config");
 
                switch (existing.version) {
+               case 2:
+                       put_usb_serial(serial_number, bytes, offset);
                case 1:
                        put_int(serial_number, bytes, offset + 4, 2);
                        put_int(radio_calibration, bytes, offset + 6, 4);
@@ -86,7 +131,9 @@ public class AltosRomconfig {
 
        public void write (AltosHexfile hexfile) throws IOException {
                write(hexfile.data, 0xa0 - hexfile.address);
-               new AltosRomconfig(hexfile);
+               AltosRomconfig check = new AltosRomconfig(hexfile);
+               if (!check.valid())
+                       throw new IOException("writing new rom config failed\n");
        }
 
        public AltosRomconfig(int in_serial_number, int in_radio_calibration) {
index 21c34ef442546bd2bea560c593e87c55ce1d1a62..bc511865a552c48c261ed2be2996cbc70b09993e 100644 (file)
@@ -143,12 +143,31 @@ public class AltosRomconfigUI
                return Integer.parseInt(serial_value.getText());
        }
 
+       void set_serial(int serial) {
+               serial_value.setText(String.format("%d", serial));
+       }
+
        int radio_calibration() {
                return Integer.parseInt(radio_calibration_value.getText());
        }
 
+       void set_radio_calibration(int calibration) {
+               radio_calibration_value.setText(String.format("%d", calibration));
+       }
+
+       public void set(AltosRomconfig config) {
+               if (config != null && config.valid()) {
+                       set_serial(config.serial_number);
+                       set_radio_calibration(config.radio_calibration);
+               }
+       }
+
        public AltosRomconfig romconfig() {
-               return new AltosRomconfig(serial(), radio_calibration());
+               try {
+                       return new AltosRomconfig(serial(), radio_calibration());
+               } catch (NumberFormatException ne) {
+                       return null;
+               }
        }
 
        public AltosRomconfig showDialog() {
index 9c418db2e804298f04335062dd6e14d9f150be71..d289ced1adf8b9abac41e116dc46e77f6cae4cde 100644 (file)
--- a/src/ao.h
+++ b/src/ao.h
@@ -293,12 +293,13 @@ ao_led_init(uint8_t enable);
  * ao_romconfig.c
  */
 
-#define AO_ROMCONFIG_VERSION   1
+#define AO_ROMCONFIG_VERSION   2
 
 extern __code __at (0x00a0) uint16_t ao_romconfig_version;
 extern __code __at (0x00a2) uint16_t ao_romconfig_check;
 extern __code __at (0x00a4) uint16_t ao_serial_number;
 extern __code __at (0x00a6) uint32_t ao_radio_cal;
+extern __code __at (0x00aa) uint8_t ao_usb_descriptors [];
 
 /*
  * ao_usb.c
@@ -1008,7 +1009,7 @@ ao_rssi_init(uint8_t rssi_led);
  * each instance of a product
  */
 
-extern const uint8_t ao_usb_descriptors [];
+extern __code __at(0x00aa) uint8_t ao_usb_descriptors [];
 extern const char ao_version[];
 extern const char ao_manufacturer[];
 extern const char ao_product[];
index f0eb4c07afc0e2286ced7324836d90da70d15060..82d6298f2dbe4751b6de6bd496ea6412f1c9a2d8 100644 (file)
@@ -28,7 +28,7 @@ const char ao_product[] = AO_iProduct_STRING;
 #define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
 
 /* USB descriptors in one giant block of bytes */
-const uint8_t ao_usb_descriptors [] =
+__code __at(0x00aa) uint8_t ao_usb_descriptors [] =
 {
        /* Device descriptor */
        0x12,