blackmagic/upgrade/main.c

180 lines
4.6 KiB
C

/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#ifdef WIN32
# include <lusb0_usb.h>
#else
# include <usb.h>
#endif
#include <assert.h>
#include "dfu.h"
#include "stm32mem.h"
#include "bindata.h"
#define VERSION "1.0"
#define LOAD_ADDRESS 0x8002000
void banner(void)
{
puts("\nBlack Magic Probe -- Firmware Upgrade Utility -- Version " VERSION);
puts("Copyright (C) 2022 Black Magic Debug Project");
puts("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
}
struct usb_device * find_dev(void)
{
struct usb_bus *bus;
struct usb_device *dev;
struct usb_dev_handle *handle;
char man[40];
char prod[40];
usb_find_busses();
usb_find_devices();
for(bus = usb_get_busses(); bus; bus = bus->next) {
for(dev = bus->devices; dev; dev = dev->next) {
/* Check for ST Microelectronics vendor ID */
if ((dev->descriptor.idVendor != 0x483) &&
(dev->descriptor.idVendor != 0x1d50))
continue;
handle = usb_open(dev);
usb_get_string_simple(handle, dev->descriptor.iManufacturer, man,
sizeof(man));
usb_get_string_simple(handle, dev->descriptor.iProduct, prod,
sizeof(prod));
#if 0
printf("%s:%s [%04X:%04X] %s : %s\n", bus->dirname, dev->filename,
dev->descriptor.idVendor, dev->descriptor.idProduct, man, prod);
#endif
usb_close(handle);
if (((dev->descriptor.idProduct == 0x5740) ||
(dev->descriptor.idProduct == 0x6018)) &&
(!strcmp(man, "Black Sphere Technologies") ||
!strcmp(man, "Black Magic Debug") ||
!strcmp(man, "1BitSquared")))
return dev;
if (((dev->descriptor.idProduct == 0xDF11) ||
(dev->descriptor.idProduct == 0x6017)) &&
(!strcmp(man, "Black Sphere Technologies") ||
!strcmp(man, "Black Magic Debug") ||
!strcmp(man, "1BitSquared")))
return dev;
}
}
return NULL;
}
usb_dev_handle * get_dfu_interface(struct usb_device *dev, uint16_t *interface)
{
int i, j, k;
struct usb_config_descriptor *config;
struct usb_interface_descriptor *iface;
usb_dev_handle *handle;
for(i = 0; i < dev->descriptor.bNumConfigurations; i++) {
config = &dev->config[i];
for(j = 0; j < config->bNumInterfaces; j++) {
for(k = 0; k < config->interface[j].num_altsetting; k++) {
iface = &config->interface[j].altsetting[k];
if((iface->bInterfaceClass == 0xFE) &&
(iface->bInterfaceSubClass = 0x01)) {
handle = usb_open(dev);
//usb_set_configuration(handle, i);
usb_claim_interface(handle, j);
//usb_set_altinterface(handle, k);
//*interface = j;
*interface = iface->bInterfaceNumber;
return handle;
}
}
}
}
return NULL;
}
int main(void)
{
struct usb_device *dev;
usb_dev_handle *handle;
uint16_t iface;
int state;
uint32_t offset;
banner();
usb_init();
retry:
if(!(dev = find_dev()) || !(handle = get_dfu_interface(dev, &iface))) {
puts("FATAL: No compatible device found!\n");
#ifdef WIN32
system("pause");
#endif
return -1;
}
state = dfu_getstate(handle, iface);
if((state < 0) || (state == STATE_APP_IDLE)) {
puts("Resetting device in firmware upgrade mode...");
dfu_detach(handle, iface, 1000);
usb_release_interface(handle, iface);
usb_close(handle);
#ifdef WIN32
Sleep(5000);
#else
sleep(5);
#endif
goto retry;
}
printf("Found device at %s:%s\n", dev->bus->dirname, dev->filename);
dfu_makeidle(handle, iface);
for(offset = 0; offset < bindatalen; offset += 1024) {
printf("Progress: %d%%\r", (offset*100)/bindatalen);
fflush(stdout);
assert(stm32_mem_erase(handle, iface, LOAD_ADDRESS + offset) == 0);
stm32_mem_write(handle, iface, (void*)&bindata[offset], 1024, LOAD_ADDRESS + offset);
}
stm32_mem_manifest(handle, iface);
usb_release_interface(handle, iface);
usb_close(handle);
puts("All operations complete!\n");
#ifdef WIN32
system("pause");
#endif
return 0;
}