o add gnususb as reference bootloader
o refactor boot loader cpde o
This commit is contained in:
315
tools/gnusb/bootloader/software/snesram_bootuploader.c
Normal file
315
tools/gnusb/bootloader/software/snesram_bootuploader.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: snesram_bootuploader.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 05/06/2009 03:06:26 PM
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: David Voswinkel (DV), david@optixx.org
|
||||
* Company: Optixx
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "../usb_cmds.h"
|
||||
|
||||
#define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */
|
||||
#define USBDEV_SHARED_PRODUCT 0x05DC /* Obdev's free shared PID */
|
||||
#define USB_VENDORSTRING "www.optixx.org"
|
||||
#define USB_BOOTLOADERNAME "gnusboot"
|
||||
#define USB_PRODUCTNAME "gnusb"
|
||||
#define RETRIES 6
|
||||
|
||||
usb_dev_handle *handle = NULL;
|
||||
unsigned char buffer[8];
|
||||
int nBytes;
|
||||
int tries;
|
||||
|
||||
static int usbGetStringAscii(usb_dev_handle * dev, int index, int langid, char *buf, int buflen)
|
||||
{
|
||||
char buffer[256];
|
||||
int rval, i;
|
||||
|
||||
if ((rval =
|
||||
usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||
(USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
|
||||
return rval;
|
||||
if (buffer[1] != USB_DT_STRING)
|
||||
return 0;
|
||||
if ((unsigned char)buffer[0] < rval)
|
||||
rval = (unsigned char)buffer[0];
|
||||
rval /= 2;
|
||||
/*
|
||||
* lossy conversion to ISO Latin1
|
||||
*/
|
||||
for (i = 1; i < rval; i++) {
|
||||
if (i > buflen) /* destination buffer overflow */
|
||||
break;
|
||||
buf[i - 1] = buffer[2 * i];
|
||||
if (buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||
buf[i - 1] = '?';
|
||||
}
|
||||
buf[i - 1] = 0;
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
static usb_dev_handle *findDevice(char *thedevice)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = 0;
|
||||
tries++;
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for (bus = usb_busses; bus; bus = bus->next) {
|
||||
for (dev = bus->devices; dev; dev = dev->next) {
|
||||
if (dev->descriptor.idVendor == USBDEV_SHARED_VENDOR && dev->descriptor.idProduct == USBDEV_SHARED_PRODUCT) {
|
||||
char string[256];
|
||||
int len;
|
||||
handle = usb_open(dev); /* we need to open the device in
|
||||
* order to query strings */
|
||||
if (!handle) {
|
||||
fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* now find out whether the device actually is obdev's
|
||||
* Remote Sensor:
|
||||
*/
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string));
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "warning: cannot query manufacturer for device: %s\n", usb_strerror());
|
||||
goto skipDevice;
|
||||
}
|
||||
/*
|
||||
* fprintf(stderr, "seen device from vendor ->%s<-\n",
|
||||
* string);
|
||||
*/
|
||||
if (strcmp(string, USB_VENDORSTRING) != 0)
|
||||
goto skipDevice;
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string));
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "warning: cannot query product for device: %s\n", usb_strerror());
|
||||
goto skipDevice;
|
||||
}
|
||||
/*
|
||||
* fprintf(stderr, "seen product ->%s<-\n", string);
|
||||
*/
|
||||
if (strcmp(string, thedevice) == 0)
|
||||
break;
|
||||
skipDevice:
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if (handle)
|
||||
break;
|
||||
}
|
||||
if (!handle) {
|
||||
if (tries < RETRIES) {
|
||||
handle = findDevice(thedevice);
|
||||
} else {
|
||||
fprintf(stderr, "Could not find USB device %s/%s\n", USB_VENDORSTRING, thedevice);
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
static int hextobin(unsigned char c)
|
||||
{
|
||||
/*
|
||||
* http://www.scit.wlv.ac.uk/~jphb/sst/c/cgisd.html Function to
|
||||
* convert hex character to binary. Returns value or -1 if there is
|
||||
* any error.
|
||||
*/
|
||||
if (isdigit(c))
|
||||
return c - '0';
|
||||
else if (isxdigit(c))
|
||||
return tolower(c) - 'a' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "\nusage:\n");
|
||||
fprintf(stderr, " %s -upload file_to_upload.hex upload hex file\n", name);
|
||||
fprintf(stderr,
|
||||
" %s -version print version number of both the bootloader and the command line tool\n", name);
|
||||
fprintf(stderr, " %s -leave leave bootloader and start application\n", name);
|
||||
fprintf(stderr, " %s -clear_flag clear softjumper\n", name);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
}
|
||||
|
||||
static void save_send_word(unsigned int to_send)
|
||||
{
|
||||
unsigned int result;
|
||||
unsigned int ok;
|
||||
|
||||
ok = 0;
|
||||
|
||||
while (!ok) {
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_IN, SNESRAM_BOOT_CMD_STATUS, 0, 0, (char *)buffer, sizeof(buffer), 100);
|
||||
if (nBytes == 1)
|
||||
ok = buffer[0];
|
||||
printf(".");
|
||||
}
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
ok = 0;
|
||||
|
||||
// while(!ok) {
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_IN, SNESRAM_BOOT_CMD_WRITE, to_send, 0, (char *)buffer, sizeof(buffer), 5000);
|
||||
if (nBytes == 2) {
|
||||
result = buffer[0] | (buffer[1] << 8);
|
||||
if (result != to_send)
|
||||
printf("COMMUNICATION ERROR: Sent %i but received %i\n", to_send, result);
|
||||
} else
|
||||
printf("COMMUNICATION ERROR: Only %i bytes received\n", nBytes);
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
static void send_file(char *filepath)
|
||||
{
|
||||
int char_count, i, send_bytes = 0;
|
||||
int c; // Character read from the file.
|
||||
unsigned int sendWord = 0; // word to send to uDMX
|
||||
FILE *fp; // Pointer to the file.
|
||||
|
||||
// Open the file
|
||||
if ((fp = fopen(filepath, "rb")) == NULL) {
|
||||
printf("File %s open failed!\n", filepath);
|
||||
exit(1);
|
||||
};
|
||||
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, SNESRAM_BOOT_CMD_START, 0, 0, (char *)buffer, sizeof(buffer), 100);
|
||||
|
||||
i = 0;
|
||||
// Read one character at a time
|
||||
while ((c = fgetc(fp)) != EOF) {
|
||||
// hex file lines start with ':'
|
||||
if (c == ':') {
|
||||
|
||||
char_count = 0;
|
||||
send_bytes = 0;
|
||||
|
||||
} else {
|
||||
char_count++;
|
||||
printf("%c", c);
|
||||
|
||||
// first two characters hold length of data
|
||||
if (char_count < 3) {
|
||||
send_bytes += hextobin(c) << ((2 - char_count) * 4);
|
||||
}
|
||||
// check if line holds data (record type = 00)
|
||||
if (char_count == 8) {
|
||||
if (c != '0')
|
||||
send_bytes = 0;
|
||||
printf(" ");
|
||||
}
|
||||
// ignore adress part of every line in hex file
|
||||
if (char_count > 8) {
|
||||
if (send_bytes) {
|
||||
sendWord += hextobin(c) << ((3 - i) * 4);
|
||||
|
||||
if (i == 3) {
|
||||
|
||||
i = -1;
|
||||
send_bytes -= 2;
|
||||
printf(" ");
|
||||
save_send_word(sendWord); // send word over
|
||||
// USB
|
||||
sendWord = 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write last page to flash if there is anything left over
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, SNESRAM_BOOT_CMD_FINISH, 0, 0, (char *)buffer, sizeof(buffer), 100);
|
||||
|
||||
fclose(fp); /* Close the file. */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (argc < 2) {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *productName;
|
||||
|
||||
// usb_set_debug(1);
|
||||
|
||||
usb_init();
|
||||
productName = USB_PRODUCTNAME;
|
||||
if (argc > 2) {
|
||||
if (strcmp(argv[2], "-device") == 0)
|
||||
productName = argv[3];
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "-upload") == 0) {
|
||||
|
||||
if ((handle = findDevice(USB_BOOTLOADERNAME)) != NULL)
|
||||
send_file(argv[2]);
|
||||
|
||||
} else if (strcmp(argv[1], "-version") == 0) {
|
||||
printf("Not implemented\n");
|
||||
|
||||
} else if (strcmp(argv[1], "-leave") == 0) {
|
||||
if ((handle = findDevice(USB_BOOTLOADERNAME)) != NULL) {
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, SNESRAM_BOOT_CMD_LEAVE, 0, 0, (char *)buffer, sizeof(buffer), 100);
|
||||
}
|
||||
} else if (strcmp(argv[1], "-enter") == 0) {
|
||||
if ((handle = findDevice(productName)) != NULL)
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, SNESRAM_BOOT_CMD_ENTER, 0, 0, (char *)buffer, sizeof(buffer), 100);
|
||||
} else if (strcmp(argv[1], "-clear_flag") == 0) {
|
||||
if ((handle = findDevice(USB_BOOTLOADERNAME)) != NULL)
|
||||
nBytes =
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT,
|
||||
SNESRAM_BOOT_CMD_CLEAR_FLAG, 0, 0, (char *)buffer, sizeof(buffer), 100);
|
||||
} else
|
||||
usage(argv[0]);
|
||||
|
||||
usb_close(handle);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user