From 55de8c6373c79fb457b436a15e6b2901800a54e2 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Thu, 11 Jun 2015 10:01:12 +0200 Subject: [PATCH] atusb-eui64: add utility to read/write and EUI64 from/to the device EEPROM Together with the new fw version (starting with version 0.3) it is now possible to set a permament EUI64 address into the devices EEPROM. The Linux driver will get updated to choose this address, if available, instead of using a randomly generated address. --- tools/Makefile | 3 +- tools/atusb-eui64/Makefile | 16 +++ tools/atusb-eui64/atusb-eui64.c | 238 ++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 tools/atusb-eui64/Makefile create mode 100644 tools/atusb-eui64/atusb-eui64.c diff --git a/tools/Makefile b/tools/Makefile index 0ebc31b..99fa39b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -12,7 +12,8 @@ BEN_DIRS=atrf-gpio atrf-id atrf-path atrf-proxy atrf-reset \ - atrf-rssi atrf-trim atrf-txrx atrf-xmit atrf-xtal + atrf-rssi atrf-trim atrf-txrx atrf-xmit atrf-xtal \ + atusb-eui64 ifneq ($(wildcard ../install/lowpan-tools-0.2.2/include/ieee802154.h),) DIRTPAN := dirtpan diff --git a/tools/atusb-eui64/Makefile b/tools/atusb-eui64/Makefile new file mode 100644 index 0000000..30bbcfe --- /dev/null +++ b/tools/atusb-eui64/Makefile @@ -0,0 +1,16 @@ +# +# atusb-eui64/Makefile - Build the ATUSB EUI64 EEPROM writing and readin utility +# +# Written 2015 by Stefan Schmidt +# Copyright 2015 Stefan Schmidt +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + + +MAIN = atusb-eui64 + +include ../Makefile.common diff --git a/tools/atusb-eui64/atusb-eui64.c b/tools/atusb-eui64/atusb-eui64.c new file mode 100644 index 0000000..f92ef70 --- /dev/null +++ b/tools/atusb-eui64/atusb-eui64.c @@ -0,0 +1,238 @@ +#ifdef HAVE_USB +/* + * atusb-eui64/atusb-eui64.c - Read and write EUI64 address from/to EEPROM + * + * Written 2015, 2016 by Stefan Schmidt + * Copyright 2015, 2016 Stefan Schmidt + * + * Based on atrf-id with following copyright: + * Written 2010-2011, 2013 by Werner Almesberger + * Copyright 2010-2011, 2013 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include + +#include "atusb/ep0.h" +#include "atrf.h" + +#define FROM_DEV ATUSB_FROM_DEV(0) +#define TO_DEV ATUSB_TO_DEV(0) + +#define EUI64_LEN 8 +#define BUF_SIZE 256 + +static int get_eui64(usb_dev_handle *dev, void *data, int size) +{ + int res; + + res = usb_control_msg(dev, FROM_DEV, ATUSB_EUI64_READ, 0, 0, data, + size, 1000); + if (res < 0) + fprintf(stderr, "ATUSB_EUI64_READ: %s\n", usb_strerror()); + return res; +} + +static int set_eui64(usb_dev_handle *dev, void *data, int size) +{ + int res; + + res = usb_control_msg(dev, TO_DEV, ATUSB_EUI64_WRITE, 0, 0, data, size, + 1000); + if (res < 0) + fprintf(stderr, "ATUSB_EUI64_WRITE: %s\n", usb_strerror()); + return res; +} + +static int get_id(usb_dev_handle *dev, void *data, int size) +{ + int res; + + res = usb_control_msg(dev, FROM_DEV, ATUSB_ID, 0, 0, data, size, 1000); + if (res < 0) + fprintf(stderr, "ATUSB_ID: %s\n", usb_strerror()); + return res; +} + +static int get_protocol(usb_dev_handle *dev, uint8_t *major, uint8_t *minor, + uint8_t *target) +{ + uint8_t ids[3]; + + if (get_id(dev, ids, 3) < 0) + return -1; + if (major) + *major = ids[0]; + if (minor) + *minor = ids[1]; + if (target) + *target = ids[2]; + + return 0; +} + +static int get_build(usb_dev_handle *dev, char *buf, size_t size) +{ + int res; + + res = usb_control_msg(dev, FROM_DEV, ATUSB_BUILD, 0, 0, buf, size, + 1000); + if (res < 0) + fprintf(stderr, "ATUSB_BUILD: %s\n", usb_strerror()); + return res; +} + +static void show_usb_info(struct atrf_dsc *dsc, unsigned char *mac, int write) +{ + usb_dev_handle *dev; + const struct usb_device *device; + uint8_t major, minor, target; + const char *mcu; + char buf[BUF_SIZE+1]; /* +1 for terminating \0 */ + char serial[BUF_SIZE]; + int len, i; + uint8_t eui64[EUI64_LEN]; + + dev = atrf_usb_handle(dsc); + if (!dev) + return; + device = usb_device(dev); + + printf("Found ATUSB device (%04x:%04x) ", + device->descriptor.idVendor, device->descriptor.idProduct); + + if (device->descriptor.iSerialNumber > 0) + usb_get_string_simple(dev, device->descriptor.iSerialNumber, + serial, BUF_SIZE); + + printf("with serial number %s\n", serial); + + if (get_protocol(dev, &major, &minor, &target) < 0) + exit(1); + switch (target) { + case HW_TYPE_100813: + case HW_TYPE_101216: + mcu = "C8051F326"; + break; + case HW_TYPE_110131: + mcu = "ATmega32U2"; + break; + default: + mcu = "???"; + } + printf("Firmware version %u.%u on hw %u (%s) ", major, minor, target, + mcu); + + len = get_build(dev, buf, sizeof(buf)-1); + if (len < 0) + exit(1); + buf[len] = 0; + printf("build: %s\n", buf); + + if (target != HW_TYPE_110131) { + printf("Firmware not able to set EUI64 on %s\n", mcu); + exit(1); + } + + if (major == 0 && minor < 3) { + printf("Firmware to old. You need at least version 0.3\n"); + exit(1); + } + + /* No new EUI64 is given, just read out */ + if (!write) { + get_eui64(dev, eui64, EUI64_LEN); + printf("Current EUI64 address from EEPROM: "); + for (i = 0; i < EUI64_LEN; i++) { + printf("%02x", eui64[EUI64_LEN - 1 - i]); + if (i < EUI64_LEN -1) + printf(":"); + } + printf("\n"); + } + /* We got a new EUI64 as argument, write it */ + if (write) { + printf("Writing EUI64 address "); + for (i = 0; i < EUI64_LEN; i++) { + printf("%02x", mac[EUI64_LEN - 1 - i]); + if (i < EUI64_LEN -1) + printf(":"); + } + printf(" to EEPROM\n"); + set_eui64(dev, mac, EUI64_LEN); + } +} + +/* Taken from wpan-tools/src/interface.c which is BSD licensed and written + * by Alexander Aring + */ +static int extendedaddr_a2n(unsigned char *mac_addr, char *arg) +{ + int i; + + for (i = 0; i < EUI64_LEN ; i++) { + int temp; + char *cp = strchr(arg, ':'); + if (cp) { + *cp = 0; + cp++; + } + if (sscanf(arg, "%x", &temp) != 1) + return -1; + if (temp < 0 || temp > 255) + return -1; + + mac_addr[EUI64_LEN - 1 - i] = temp; + if (!cp) + break; + arg = cp; + } + if (i < EUI64_LEN - 1) + return -3; + + return 0; +} + +static void usage(const char *name) +{ + fprintf(stderr, "usage: %s [-a 00:11:22:33:44:55:66:77]\n", name); + exit(1); +} + +int main(int argc, char *const *argv) +{ + uint8_t mac[EUI64_LEN]; + struct atrf_dsc *dsc; + int c; + int write = 0; + + while ((c = getopt(argc, argv, "a:")) != EOF) + switch (c) { + case 'a': + extendedaddr_a2n(mac, optarg); + write = 1; + break; + default: + usage(*argv); + } + + dsc = atrf_open(NULL); + if (!dsc) + return 1; + + show_usb_info(dsc, mac, write); + + atrf_close(dsc); + + return 0; +} +#endif /* HAVE_USB */