mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-18 06:08:31 +03:00
this adds the DFU as application, allowing to flash the bootloader. a USB DFU alternative is added to flash the bootloader partition. when the DFU is started as bootloader, the partition/alternative to flash the bootloader is marked as "not available", and ineffective. the same happens for the application partition when DFU is started as application. this distinction is make at compile time, not at runtime, because of size restrictions (the bootloader was already close to the 16 kB limit). *_dfu_flash.bin should not be mixed with *_dfu_dfu.bin. *_dfu_dfu.bin should be flashed as application using the already existing DFU bootloader. once this images is started (as application), the *_dfu_flash.bin should be flashed as bootloader using the DFU application. once the DFU bootloader has been flashed, soft resetting (not re-powering) will cause the bootloader to start, allowing to flash the application with a normal image (e.g. not DFU), replacing the DFU application. this switch to DFU only happens after downloading (e.g. flashing). it is planned to have the DFU application erase itself after flashing, but this is currently not implemented. Change-Id: Ic273bb593a7669111b0219fe301d7897419167c8
265 lines
8.3 KiB
C
265 lines
8.3 KiB
C
/* DFU related USB Descriptors */
|
|
/* (C) 2006-2017 Harald Welte <hwelte@hmw-consulting.de> */
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "board.h"
|
|
#include "utils.h"
|
|
|
|
#include <usb/include/USBDescriptors.h>
|
|
|
|
#include <usb/include/USBDDriver.h>
|
|
|
|
#include <usb/common/dfu/usb_dfu.h>
|
|
#include <usb/device/dfu/dfu.h>
|
|
|
|
#include "usb_strings_generated.h"
|
|
|
|
enum {
|
|
STR_MANUF = 1,
|
|
STR_PROD,
|
|
STR_CONFIG,
|
|
// strings for the first alternate interface (e.g. DFU)
|
|
_STR_FIRST_ALT,
|
|
// serial string
|
|
STR_SERIAL = (_STR_FIRST_ALT + BOARD_DFU_NUM_IF),
|
|
// version string (on additional interface)
|
|
VERSION_CONF_STR,
|
|
VERSION_STR,
|
|
// count
|
|
STRING_DESC_CNT,
|
|
};
|
|
|
|
/* string used to replace one of both DFU flash partition atlsettings */
|
|
static const unsigned char usb_string_notavailable[] = {
|
|
USBStringDescriptor_LENGTH(13),
|
|
USBGenericDescriptor_STRING,
|
|
USBStringDescriptor_UNICODE('n'),
|
|
USBStringDescriptor_UNICODE('o'),
|
|
USBStringDescriptor_UNICODE('t'),
|
|
USBStringDescriptor_UNICODE(' '),
|
|
USBStringDescriptor_UNICODE('a'),
|
|
USBStringDescriptor_UNICODE('v'),
|
|
USBStringDescriptor_UNICODE('a'),
|
|
USBStringDescriptor_UNICODE('i'),
|
|
USBStringDescriptor_UNICODE('l'),
|
|
USBStringDescriptor_UNICODE('a'),
|
|
USBStringDescriptor_UNICODE('b'),
|
|
USBStringDescriptor_UNICODE('l'),
|
|
USBStringDescriptor_UNICODE('e'),
|
|
};
|
|
|
|
/* USB string for the serial (using 128-bit device ID) */
|
|
static unsigned char usb_string_serial[] = {
|
|
USBStringDescriptor_LENGTH(32),
|
|
USBGenericDescriptor_STRING,
|
|
USBStringDescriptor_UNICODE('0'),
|
|
USBStringDescriptor_UNICODE('0'),
|
|
USBStringDescriptor_UNICODE('1'),
|
|
USBStringDescriptor_UNICODE('1'),
|
|
USBStringDescriptor_UNICODE('2'),
|
|
USBStringDescriptor_UNICODE('2'),
|
|
USBStringDescriptor_UNICODE('3'),
|
|
USBStringDescriptor_UNICODE('3'),
|
|
USBStringDescriptor_UNICODE('4'),
|
|
USBStringDescriptor_UNICODE('4'),
|
|
USBStringDescriptor_UNICODE('5'),
|
|
USBStringDescriptor_UNICODE('5'),
|
|
USBStringDescriptor_UNICODE('6'),
|
|
USBStringDescriptor_UNICODE('6'),
|
|
USBStringDescriptor_UNICODE('7'),
|
|
USBStringDescriptor_UNICODE('7'),
|
|
USBStringDescriptor_UNICODE('8'),
|
|
USBStringDescriptor_UNICODE('8'),
|
|
USBStringDescriptor_UNICODE('9'),
|
|
USBStringDescriptor_UNICODE('9'),
|
|
USBStringDescriptor_UNICODE('a'),
|
|
USBStringDescriptor_UNICODE('a'),
|
|
USBStringDescriptor_UNICODE('b'),
|
|
USBStringDescriptor_UNICODE('b'),
|
|
USBStringDescriptor_UNICODE('c'),
|
|
USBStringDescriptor_UNICODE('c'),
|
|
USBStringDescriptor_UNICODE('d'),
|
|
USBStringDescriptor_UNICODE('d'),
|
|
USBStringDescriptor_UNICODE('e'),
|
|
USBStringDescriptor_UNICODE('e'),
|
|
USBStringDescriptor_UNICODE('f'),
|
|
USBStringDescriptor_UNICODE('f'),
|
|
};
|
|
|
|
/* USB string for the version */
|
|
static const unsigned char usb_string_version_conf[] = {
|
|
USBStringDescriptor_LENGTH(16),
|
|
USBGenericDescriptor_STRING,
|
|
USBStringDescriptor_UNICODE('f'),
|
|
USBStringDescriptor_UNICODE('i'),
|
|
USBStringDescriptor_UNICODE('r'),
|
|
USBStringDescriptor_UNICODE('m'),
|
|
USBStringDescriptor_UNICODE('w'),
|
|
USBStringDescriptor_UNICODE('a'),
|
|
USBStringDescriptor_UNICODE('r'),
|
|
USBStringDescriptor_UNICODE('e'),
|
|
USBStringDescriptor_UNICODE(' '),
|
|
USBStringDescriptor_UNICODE('v'),
|
|
USBStringDescriptor_UNICODE('e'),
|
|
USBStringDescriptor_UNICODE('r'),
|
|
USBStringDescriptor_UNICODE('s'),
|
|
USBStringDescriptor_UNICODE('i'),
|
|
USBStringDescriptor_UNICODE('o'),
|
|
USBStringDescriptor_UNICODE('n'),
|
|
};
|
|
|
|
static const char git_version[] = GIT_VERSION;
|
|
static unsigned char usb_string_version[2 + ARRAY_SIZE(git_version) * 2 - 2];
|
|
/** array of static (from usb_strings) and runtime (serial, version) USB strings */
|
|
static const unsigned char *usb_strings_extended[STRING_DESC_CNT];
|
|
|
|
static const USBDeviceDescriptor fsDevice = {
|
|
.bLength = sizeof(USBDeviceDescriptor),
|
|
.bDescriptorType = USBGenericDescriptor_DEVICE,
|
|
.bcdUSB = USBDeviceDescriptor_USB2_00,
|
|
.bDeviceClass = 0,
|
|
.bDeviceSubClass = 0,
|
|
.bDeviceProtocol = 0,
|
|
.bMaxPacketSize0 = USBEndpointDescriptor_MAXCTRLSIZE_FS,
|
|
.idVendor = BOARD_USB_VENDOR_ID,
|
|
.idProduct = BOARD_DFU_USB_PRODUCT_ID,
|
|
.bcdDevice = BOARD_USB_RELEASE,
|
|
.iManufacturer = STR_MANUF,
|
|
.iProduct = STR_PROD,
|
|
.iSerialNumber = STR_SERIAL,
|
|
.bNumConfigurations = 2, // DFU + version configurations
|
|
};
|
|
|
|
/* Alternate Interface Descriptor, we use one per partition/memory type */
|
|
#define DFU_IF(ALT) \
|
|
{ \
|
|
.bLength = sizeof(USBInterfaceDescriptor), \
|
|
.bDescriptorType = USBGenericDescriptor_INTERFACE, \
|
|
.bInterfaceNumber = 0, \
|
|
.bAlternateSetting = ALT, \
|
|
.bNumEndpoints = 0, \
|
|
.bInterfaceClass = 0xfe, \
|
|
.bInterfaceSubClass = 1, \
|
|
.iInterface = (_STR_FIRST_ALT + ALT), \
|
|
.bInterfaceProtocol = 2, \
|
|
}
|
|
|
|
/* overall descriptor for the DFU configuration, including all
|
|
* descriptors for alternate interfaces */
|
|
const struct dfu_desc dfu_cfg_descriptor = {
|
|
.ucfg = {
|
|
.bLength = sizeof(USBConfigurationDescriptor),
|
|
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
|
|
.wTotalLength = sizeof(struct dfu_desc),
|
|
.bNumInterfaces = 1,
|
|
.bConfigurationValue = 1,
|
|
.iConfiguration = STR_CONFIG,
|
|
.bmAttributes = BOARD_USB_BMATTRIBUTES,
|
|
.bMaxPower = 100,
|
|
},
|
|
.uif[0] = DFU_IF(0),
|
|
#if BOARD_DFU_NUM_IF > 1
|
|
.uif[1] = DFU_IF(1),
|
|
#endif
|
|
#if BOARD_DFU_NUM_IF > 2
|
|
.uif[2] = DFU_IF(2),
|
|
#endif
|
|
#if BOARD_DFU_NUM_IF > 3
|
|
.uif[3] = DFU_IF(3),
|
|
#endif
|
|
#if BOARD_DFU_NUM_IF > 4
|
|
.uif[4] = DFU_IF(4),
|
|
#endif
|
|
.func_dfu = DFU_FUNC_DESC
|
|
};
|
|
|
|
void set_usb_serial_str(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
// put device ID into USB serial number description
|
|
unsigned int device_id[4];
|
|
EEFC_ReadUniqueID(device_id);
|
|
char device_id_string[32 + 1];
|
|
snprintf(device_id_string, ARRAY_SIZE(device_id_string), "%08x%08x%08x%08x",
|
|
device_id[0], device_id[1], device_id[2], device_id[3]);
|
|
for (i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
|
|
usb_string_serial[2 + 2 * i] = device_id_string[i];
|
|
}
|
|
|
|
// put version into USB string
|
|
usb_string_version[0] = USBStringDescriptor_LENGTH(ARRAY_SIZE(git_version) - 1);
|
|
usb_string_version[1] = USBGenericDescriptor_STRING;
|
|
for (i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
|
|
usb_string_version[2 + i * 2 + 0] = git_version[i];
|
|
usb_string_version[2 + i * 2 + 1] = 0;
|
|
}
|
|
|
|
// fill extended USB strings
|
|
for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
|
|
usb_strings_extended[i] = usb_strings[i];
|
|
}
|
|
#if defined(ENVIRONMENT_dfu)
|
|
usb_strings_extended[_STR_FIRST_ALT + 1] = usb_string_notavailable;
|
|
#elif defined(ENVIRONMENT_flash)
|
|
usb_strings_extended[_STR_FIRST_ALT + 2] = usb_string_notavailable;
|
|
#endif
|
|
usb_strings_extended[STR_SERIAL] = usb_string_serial;
|
|
usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf;
|
|
usb_strings_extended[VERSION_STR] = usb_string_version;
|
|
}
|
|
|
|
/* USB descriptor just to show the version */
|
|
typedef struct _SIMTraceDriverConfigurationDescriptorVersion {
|
|
/** Standard configuration descriptor. */
|
|
USBConfigurationDescriptor configuration;
|
|
USBInterfaceDescriptor version;
|
|
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorVersion;
|
|
|
|
static const SIMTraceDriverConfigurationDescriptorVersion
|
|
configurationDescriptorVersion = {
|
|
/* Standard configuration descriptor for the interface descriptor*/
|
|
.configuration = {
|
|
.bLength = sizeof(USBConfigurationDescriptor),
|
|
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
|
|
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorVersion),
|
|
.bNumInterfaces = 1,
|
|
.bConfigurationValue = 2,
|
|
.iConfiguration = VERSION_CONF_STR,
|
|
.bmAttributes = USBD_BMATTRIBUTES,
|
|
.bMaxPower = USBConfigurationDescriptor_POWER(100),
|
|
},
|
|
/* Interface standard descriptor just holding the version information */
|
|
.version = {
|
|
.bLength = sizeof(USBInterfaceDescriptor),
|
|
.bDescriptorType = USBGenericDescriptor_INTERFACE,
|
|
.bInterfaceNumber = 0,
|
|
.bAlternateSetting = 0,
|
|
.bNumEndpoints = 0,
|
|
.bInterfaceClass = USB_CLASS_PROPRIETARY,
|
|
.bInterfaceSubClass = 0xff,
|
|
.bInterfaceProtocol = 0,
|
|
.iInterface = VERSION_STR,
|
|
},
|
|
};
|
|
|
|
static const USBConfigurationDescriptor *conf_desc_arr[] = {
|
|
&dfu_cfg_descriptor.ucfg,
|
|
&configurationDescriptorVersion.configuration,
|
|
};
|
|
|
|
const USBDDriverDescriptors dfu_descriptors = {
|
|
.pFsDevice = &fsDevice,
|
|
.pFsConfiguration = (const USBConfigurationDescriptor **)&conf_desc_arr,
|
|
/* DFU only supports FS for now */
|
|
.pFsQualifier = NULL,
|
|
.pFsOtherSpeed = NULL,
|
|
.pHsDevice = NULL,
|
|
.pHsConfiguration = NULL,
|
|
.pHsQualifier = NULL,
|
|
.pHsOtherSpeed = NULL,
|
|
.pStrings = usb_strings_extended,
|
|
.numStrings = ARRAY_SIZE(usb_strings_extended),
|
|
};
|