Переглянути джерело

o Added qdips - still nonworking so far

Tobias Pflug 14 роки тому
батько
коміт
297b10ccf7
5 змінених файлів з 731 додано та 0 видалено
  1. 23 0
      tools/qdips/Makefile
  2. 286 0
      tools/qdips/opendevice.c
  3. 77 0
      tools/qdips/opendevice.h
  4. 286 0
      tools/qdips/qdips.c
  5. 59 0
      tools/qdips/qdips.h

+ 23 - 0
tools/qdips/Makefile

@@ -0,0 +1,23 @@
+USBFLAGS = `libusb-config --cflags`
+USBLIBS = `libusb-config --libs`
+
+CC	= llvm-gcc
+CFLAGS	= $(CPPFLAGS) $(USBFLAGS) -O -g -Wall -D_GNU_SOURCE --std=c99
+LIBS	= $(USBLIBS)
+
+NAME = qdips
+OBJECTS = opendevice.o $(NAME).o
+
+
+PROGRAM = $(NAME)$(EXE_SUFFIX)
+
+
+all: $(PROGRAM)
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+$(PROGRAM): $(OBJECTS)
+	$(CC) -o $(PROGRAM) $(OBJECTS) $(LIBS)
+clean:
+	rm -f *.o $(PROGRAM)

+ 286 - 0
tools/qdips/opendevice.c

@@ -0,0 +1,286 @@
+/*
+ * Name: opendevice.c Project: V-USB host-side library Author: Christian
+ * Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c) 2008 by
+ * OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see License.txt),
+ * GNU GPL v3 or proprietary (CommercialLicense.txt) This Revision: $Id:
+ * opendevice.c 740 2009-04-13 18:23:31Z cs $ 
+ */
+
+/*
+ * General Description: The functions in this module can be used to find and
+ * open a device based on libusb or libusb-win32. 
+ */
+
+
+#include <stdio.h>
+#include "opendevice.h"
+
+/*
+ * ------------------------------------------------------------------------- 
+ */
+
+#define MATCH_SUCCESS			1
+#define MATCH_FAILED			0
+#define MATCH_ABORT				-1
+
+/*
+ * private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or
+ * MATCH_ABORT. 
+ */
+static int _shellStyleMatch(char *text, char *p)
+{
+    int last,
+     matched,
+     reverse;
+
+    for (; *p; text++, p++) {
+        if (*text == 0 && *p != '*')
+            return MATCH_ABORT;
+        switch (*p) {
+        case '\\':
+            /*
+             * Literal match with following character. 
+             */
+            p++;
+            /*
+             * FALLTHROUGH 
+             */
+        default:
+            if (*text != *p)
+                return MATCH_FAILED;
+            continue;
+        case '?':
+            /*
+             * Match anything. 
+             */
+            continue;
+        case '*':
+            while (*++p == '*')
+                /*
+                 * Consecutive stars act just like one. 
+                 */
+                continue;
+            if (*p == 0)
+                /*
+                 * Trailing star matches everything. 
+                 */
+                return MATCH_SUCCESS;
+            while (*text)
+                if ((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
+                    return matched;
+            return MATCH_ABORT;
+        case '[':
+            reverse = p[1] == '^';
+            if (reverse)        /* Inverted character class. */
+                p++;
+            matched = MATCH_FAILED;
+            if (p[1] == ']' || p[1] == '-')
+                if (*++p == *text)
+                    matched = MATCH_SUCCESS;
+            for (last = *p; *++p && *p != ']'; last = *p)
+                if (*p == '-' && p[1] != ']' ? *text <= *++p
+                    && *text >= last : *text == *p)
+                    matched = MATCH_SUCCESS;
+            if (matched == reverse)
+                return MATCH_FAILED;
+            continue;
+        }
+    }
+    return *text == 0;
+}
+
+/*
+ * public interface for shell style matching: returns 0 if fails, 1 if matches 
+ */
+static int shellStyleMatch(char *text, char *pattern)
+{
+    if (pattern == NULL)        /* NULL pattern is synonymous to "*" */
+        return 1;
+    return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
+}
+
+/*
+ * ------------------------------------------------------------------------- 
+ */
+
+int usbGetStringAscii(usb_dev_handle * dev, int index, char *buf, int buflen)
+{
+    char buffer[256];
+    int rval,
+     i;
+
+    if ((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0)   /* use
+                                                                         * libusb 
+                                                                         * version 
+                                                                         * if
+                                                                         * it
+                                                                         * works 
+                                                                         */
+        return rval;
+    if ((rval =
+         usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
+                         (USB_DT_STRING << 8) + index, 0x0409, buffer,
+                         sizeof(buffer), 5000)) < 0)
+        return rval;
+    if (buffer[1] != USB_DT_STRING) {
+        *buf = 0;
+        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;
+}
+
+/*
+ * ------------------------------------------------------------------------- 
+ */
+
+int usbOpenDevice(usb_dev_handle ** device, int vendorID,
+                  char *vendorNamePattern, int productID,
+                  char *productNamePattern, char *serialNamePattern,
+                  FILE * printMatchingDevicesFp, FILE * warningsFp)
+{
+    struct usb_bus *bus;
+    struct usb_device *dev;
+    usb_dev_handle *handle = NULL;
+    int errorCode = USBOPEN_ERR_NOTFOUND;
+
+    usb_find_busses();
+    usb_find_devices();
+    for (bus = usb_get_busses(); bus; bus = bus->next) {
+        for (dev = bus->devices; dev; dev = dev->next) {        /* iterate over 
+                                                                 * all devices
+                                                                 * on all
+                                                                 * busses */
+            if ((vendorID == 0 || dev->descriptor.idVendor == vendorID)
+                && (productID == 0 || dev->descriptor.idProduct == productID)) {
+                char vendor[256],
+                 product[256],
+                 serial[256];
+                int len;
+                handle = usb_open(dev); /* we need to open the device in order
+                                         * to query strings */
+                if (!handle) {
+                    errorCode = USBOPEN_ERR_ACCESS;
+                    if (warningsFp != NULL)
+                        fprintf(warningsFp,
+                                "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n",
+                                dev->descriptor.idVendor,
+                                dev->descriptor.idProduct, usb_strerror());
+                    continue;
+                }
+                /*
+                 * now check whether the names match: 
+                 */
+                len = vendor[0] = 0;
+                if (dev->descriptor.iManufacturer > 0) {
+                    len =
+                        usbGetStringAscii(handle, dev->descriptor.iManufacturer,
+                                          vendor, sizeof(vendor));
+                }
+                if (len < 0) {
+                    errorCode = USBOPEN_ERR_ACCESS;
+                    if (warningsFp != NULL)
+                        fprintf(warningsFp,
+                                "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n",
+                                dev->descriptor.idVendor,
+                                dev->descriptor.idProduct, usb_strerror());
+                } else {
+                    errorCode = USBOPEN_ERR_NOTFOUND;
+                    /*
+                     * printf("seen device from vendor ->%s<-\n", vendor); 
+                     */
+                    if (shellStyleMatch(vendor, vendorNamePattern)) {
+                        len = product[0] = 0;
+                        if (dev->descriptor.iProduct > 0) {
+                            len =
+                                usbGetStringAscii(handle,
+                                                  dev->descriptor.iProduct,
+                                                  product, sizeof(product));
+                        }
+                        if (len < 0) {
+                            errorCode = USBOPEN_ERR_ACCESS;
+                            if (warningsFp != NULL)
+                                fprintf(warningsFp,
+                                        "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n",
+                                        dev->descriptor.idVendor,
+                                        dev->descriptor.idProduct,
+                                        usb_strerror());
+                        } else {
+                            errorCode = USBOPEN_ERR_NOTFOUND;
+                            /*
+                             * printf("seen product ->%s<-\n", product); 
+                             */
+                            if (shellStyleMatch(product, productNamePattern)) {
+                                len = serial[0] = 0;
+                                if (dev->descriptor.iSerialNumber > 0) {
+                                    len =
+                                        usbGetStringAscii(handle,
+                                                          dev->descriptor.
+                                                          iSerialNumber, serial,
+                                                          sizeof(serial));
+                                }
+                                if (len < 0) {
+                                    errorCode = USBOPEN_ERR_ACCESS;
+                                    if (warningsFp != NULL)
+                                        fprintf(warningsFp,
+                                                "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n",
+                                                dev->descriptor.idVendor,
+                                                dev->descriptor.idProduct,
+                                                usb_strerror());
+                                }
+                                if (shellStyleMatch(serial, serialNamePattern)) {
+                                    if (printMatchingDevicesFp != NULL) {
+                                        if (serial[0] == 0) {
+                                            fprintf(printMatchingDevicesFp,
+                                                    "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n",
+                                                    dev->descriptor.idVendor,
+                                                    dev->descriptor.idProduct,
+                                                    vendor, product);
+                                        } else {
+                                            fprintf(printMatchingDevicesFp,
+                                                    "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n",
+                                                    dev->descriptor.idVendor,
+                                                    dev->descriptor.idProduct,
+                                                    vendor, product, serial);
+                                        }
+                                    } else {
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                usb_close(handle);
+                handle = NULL;
+            }
+        }
+        if (handle)             /* we have found a deice */
+            break;
+    }
+    if (handle != NULL) {
+        errorCode = 0;
+        *device = handle;
+    }
+    if (printMatchingDevicesFp != NULL) /* never return an error for listing
+                                         * only */
+        errorCode = 0;
+    return errorCode;
+}
+
+/*
+ * ------------------------------------------------------------------------- 
+ */

+ 77 - 0
tools/qdips/opendevice.h

@@ -0,0 +1,77 @@
+/* Name: opendevice.h
+ * Project: V-USB host-side library
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-10
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: opendevice.h 740 2009-04-13 18:23:31Z cs $
+ */
+
+/*
+General Description:
+This module offers additional functionality for host side drivers based on
+libusb or libusb-win32. It includes a function to find and open a device
+based on numeric IDs and textual description. It also includes a function to
+obtain textual descriptions from a device.
+
+To use this functionality, simply copy opendevice.c and opendevice.h into your
+project and add them to your Makefile. You may modify and redistribute these
+files according to the GNU General Public License (GPL) version 2 or 3.
+*/
+
+#ifndef __OPENDEVICE_H_INCLUDED__
+#define __OPENDEVICE_H_INCLUDED__
+
+#include <usb.h>    /* this is libusb, see http://libusb.sourceforge.net/ */
+#include <stdio.h>
+
+int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen);
+/* This function gets a string descriptor from the device. 'index' is the
+ * string descriptor index. The string is returned in ISO Latin 1 encoding in
+ * 'buf' and it is terminated with a 0-character. The buffer size must be
+ * passed in 'buflen' to prevent buffer overflows. A libusb device handle
+ * must be given in 'dev'.
+ * Returns: The length of the string (excluding the terminating 0) or
+ * a negative number in case of an error. If there was an error, use
+ * usb_strerror() to obtain the error message.
+ */
+
+int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp);
+/* This function iterates over all devices on all USB busses and searches for
+ * a device. Matching is done first by means of Vendor- and Product-ID (passed
+ * in 'vendorID' and 'productID'. An ID of 0 matches any numeric ID (wildcard).
+ * When a device matches by its IDs, matching by names is performed. Name
+ * matching can be done on textual vendor name ('vendorNamePattern'), product
+ * name ('productNamePattern') and serial number ('serialNamePattern'). A
+ * device matches only if all non-null pattern match. If you don't care about
+ * a string, pass NULL for the pattern. Patterns are Unix shell style pattern:
+ * '*' stands for 0 or more characters, '?' for one single character, a list
+ * of characters in square brackets for a single character from the list
+ * (dashes are allowed to specify a range) and if the lis of characters begins
+ * with a caret ('^'), it matches one character which is NOT in the list.
+ * Other parameters to the function: If 'warningsFp' is not NULL, warning
+ * messages are printed to this file descriptor with fprintf(). If
+ * 'printMatchingDevicesFp' is not NULL, no device is opened but matching
+ * devices are printed to the given file descriptor with fprintf().
+ * If a device is opened, the resulting USB handle is stored in '*device'. A
+ * pointer to a "usb_dev_handle *" type variable must be passed here.
+ * Returns: 0 on success, an error code (see defines below) on failure.
+ */
+
+/* usbOpenDevice() error codes: */
+#define USBOPEN_SUCCESS         0   /* no error */
+#define USBOPEN_ERR_ACCESS      1   /* not enough permissions to open device */
+#define USBOPEN_ERR_IO          2   /* I/O error */
+#define USBOPEN_ERR_NOTFOUND    3   /* device not found */
+
+
+/* Obdev's free USB IDs, see USBID-License.txt for details */
+
+#define USB_VID_OBDEV_SHARED        5824    /* obdev's shared vendor ID */
+#define USB_PID_OBDEV_SHARED_CUSTOM 1500    /* shared PID for custom class devices */
+#define USB_PID_OBDEV_SHARED_HID    1503    /* shared PID for HIDs except mice & keyboards */
+#define USB_PID_OBDEV_SHARED_CDCACM 1505    /* shared PID for CDC Modem devices */
+#define USB_PID_OBDEV_SHARED_MIDI   1508    /* shared PID for MIDI class devices */
+
+#endif /* __OPENDEVICE_H_INCLUDED__ */

+ 286 - 0
tools/qdips/qdips.c

@@ -0,0 +1,286 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <usb.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "opendevice.h"
+#include "qdips.h"
+
+
+#define _16MBIT 0x200000
+
+#define HIROM_BANK_SIZE_SHIFT  16
+#define LOROM_BANK_SIZE_SHIFT  15
+#define HIROM_BANK_COUNT_SHIFT 32
+#define LOROM_BANK_COUNT_SHIFT 64
+
+#define IPS_MAGIC "PATCH"
+#define EOF_TAG   0x454f46
+#define PATCH_END 1
+#define PATCH_ERR 2
+#define PATCH_CHUNKS_MAX 512
+
+#define QD16_MAX_TX_LEN 128
+#define QD16_CMD_TIMEOUT 5000
+
+
+#define QD16_SEND_DATA(__addr_hi,__addr_lo,__src,__len)\
+    usb_control_msg(handle,\
+            USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,\
+            USB_BULK_UPLOAD_NEXT,\
+            __addr_hi, __addr_lo,\
+            (char*)__src, __len,\
+            QD16_CMD_TIMEOUT);
+
+#define QD16_SEND_ADDR(__addr_hi,__addr_lo,__src,__len)\
+    usb_control_msg(handle,\
+            USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,\
+            USB_BULK_UPLOAD_ADDR,\
+            __addr_hi,__addr_lo,\
+            (char*)__src,__len,\
+            QD16_CMD_TIMEOUT);
+
+
+typedef struct _ips_tag {
+    uint32_t ofs;     /* offset in file to patch */
+    uint16_t len;    /* number of bytes in this chunk */
+    uint8_t* data;         /* chunk data */
+} ips_tag_t;
+
+int qd16_apply_ips_chunk(ips_tag_t* ips_tag);
+int ips_read_next_tag(FILE* patch_file, ips_tag_t* tag);
+int qd16_init(void);
+void qd16_finish(void);
+void usage(void);
+
+usb_dev_handle *handle = NULL;
+const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = { USB_CFG_DEVICE_ID};
+char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = { USB_CFG_DEVICE_NAME, 0};
+int cnt, vid, pid;
+
+int hirom = 0;
+int header = 0;
+int init = 0;
+int quiet = 0;
+
+uint8_t dummy[128];
+
+void usage(void)
+{
+    fprintf(stderr, "Usage: qdips [option] <patchfile>\n\n\
+            Options:\n\
+            -s\tSkip ROM header\n\
+            -q\tBe quiet\n\
+            -h\tForce HiROM mode\n\n");
+
+    exit(1);
+}
+
+int main(int argc, char * argv[])
+{
+    FILE* patch_file;
+    char * fname = 0;
+    int opt = 0;
+
+    char magic[6];
+    ips_tag_t ips_tags[PATCH_CHUNKS_MAX];
+    int chunk_index = 0;
+
+    if (argc==1)
+        usage();
+
+    while ((opt = getopt(argc,argv,"qish")) != -1){
+        switch (opt) {
+            case 'i':
+                init = 1;
+                break;
+            case 's':
+                header = 1;
+                break;
+            case 'h':
+                hirom = 1;
+                break;
+            case 'q':
+                quiet = 1;
+                break;
+            default:
+                usage();
+        }
+    }
+
+
+    if (optind >= argc) {
+        usage();
+    }
+
+    int ret = qd16_init();
+    if (ret != 0){
+        fprintf(stderr,"Error during init. Exiting!\n");
+        exit(1);
+    }
+    qd16_finish();
+    exit(0);
+
+    fname = argv[optind];
+    patch_file = fopen(fname,"rb");
+    if (patch_file == 0) {
+        fprintf(stderr,"Failed to open file '%s'!\n",fname);
+        exit(1);
+    }
+
+    if (fgets(magic,strlen(IPS_MAGIC)+1,patch_file) == NULL) {
+        fprintf(stderr,"Error reading from file %s\n",fname);
+        fclose(patch_file);
+        exit(1);
+    }
+
+    if (strcmp(magic,IPS_MAGIC) != 0){
+        fprintf(stderr,"Patch is not in ips format!\n");
+    }
+
+    int patch_error = 0;
+
+    while (!feof(patch_file) && chunk_index < PATCH_CHUNKS_MAX) {
+
+        printf(".");
+
+        int ret = ips_read_next_tag(patch_file,&ips_tags[chunk_index]);
+
+        if (ret == PATCH_END)
+            break;
+        else if (ret == PATCH_ERR) {
+            patch_error = 1;
+            break;
+        }
+
+        chunk_index++;
+    }
+
+    fclose(patch_file);
+
+    for (int i=0; i<chunk_index; i++){
+
+        printf("uploading chunk %d ..\n",i);
+
+        int ret = qd16_apply_ips_chunk(&ips_tags[i]);
+        if (ret!=0){
+            printf("failed applying chunk %d !\n",i);
+        }
+    }
+
+    qd16_finish();
+
+    return 0;
+}
+
+int qd16_apply_ips_chunk(ips_tag_t* ips_tag)
+{
+    return 0;
+    int addr_hi = (ips_tag->ofs)>>16;
+    int addr_lo = (ips_tag->ofs)&0xffff;
+
+    printf("hi:%x lo:%x\n",addr_hi,addr_lo);
+
+    int ret = QD16_SEND_ADDR(addr_hi,addr_lo,ips_tag->data,ips_tag->len);
+    /*int ret = QD16_SEND_ADDR(addr_hi,addr_lo,dummy,128);*/
+    if (ret<0){
+        printf("error executing command!:%s\n",usb_strerror());
+    }
+
+    ret = QD16_SEND_DATA(addr_hi,addr_lo,ips_tag->data,ips_tag->len);
+    /*int ret = QD16_SEND_ADDR(addr_hi,addr_lo,dummy,128);*/
+    if (ret<0){
+        printf("error executing command!:%s\n",usb_strerror());
+    }
+
+    return 0;
+}
+
+void qd16_finish(void)
+{
+#if 0
+    cnt = usb_control_msg(handle,
+        USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+        USB_ENDPOINT_OUT, USB_BULK_UPLOAD_END, 0, 0, NULL,
+        0, 5000);
+
+    if (cnt<0) {
+        printf("USB_BULK_UPLOAD_END failed: %s\n",usb_strerror());
+    }
+#endif
+          cnt = usb_control_msg(handle,
+        USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+        USB_ENDPOINT_OUT, USB_SET_LOADER, 0, 0, NULL,
+        0, 5000); 
+  
+    cnt = usb_control_msg(handle,
+        USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+        USB_ENDPOINT_OUT, USB_MODE_SNES, 0, 0, NULL,
+        0, 5000);
+    if (cnt<0) {
+        printf("USB_MODE_SNES failed: %s\n",usb_strerror());
+    }
+
+}
+
+int qd16_init(void)
+{
+    usb_init();
+
+    vid = rawVid[1] * 256 + rawVid[0];
+    pid = rawPid[1] * 256 + rawPid[0];
+
+    if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0) {
+        fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
+        return 1;
+    }
+
+
+    cnt = usb_control_msg(handle,
+            USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+            USB_ENDPOINT_OUT, USB_MODE_AVR, 0, 0, NULL,
+            0, 5000);  
+
+    if (cnt<0) {
+        printf("USB_MODE_AVR failed: %s\n",usb_strerror());
+    }
+
+    usleep(500000);
+
+#if 0
+    cnt = usb_control_msg(handle,
+        USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
+        USB_BULK_UPLOAD_INIT, 
+        (hirom ? HIROM_BANK_SIZE_SHIFT : LOROM_BANK_SIZE_SHIFT) , 
+        (hirom ? HIROM_BANK_COUNT_SHIFT : LOROM_BANK_COUNT_SHIFT), 
+        NULL, 0, 5000);
+
+    if (cnt<0) {
+        printf("USB_BULK_UPLOAD_INIT failed: %s\n",usb_strerror());
+    }
+#endif
+
+    return 0;
+}
+
+int ips_read_next_tag(FILE* patch_file, ips_tag_t* tag)
+{
+
+    tag->ofs = getc(patch_file)<<16 | getc(patch_file)<<8 | getc(patch_file);
+
+    if (tag->ofs == EOF_TAG)
+        return PATCH_END;
+    if (tag->ofs > _16MBIT)
+        return PATCH_ERR;
+
+    tag->len = getc(patch_file)<<8 | getc(patch_file);
+    tag->data = malloc(tag->len);
+
+    size_t ret = fread(tag->data,1,tag->len,patch_file);
+    if (ret != tag->len)
+        return PATCH_ERR;
+
+    return 0;
+}

+ 59 - 0
tools/qdips/qdips.h

@@ -0,0 +1,59 @@
+#ifndef __QDINC_H__
+#define __QDINC_H__
+
+#define QDINC_RANGE 96
+#define QDINC_SIZE 254
+
+/* quickdev protocol defines */
+
+#define USB_UPLOAD_INIT         0
+#define USB_UPLOAD_ADDR         1
+
+#define USB_DOWNLOAD_INIT       2
+#define USB_DOWNLOAD_ADDR       3
+
+#define USB_CRC                 4
+#define USB_CRC_ADDR            5
+
+#define USB_BULK_UPLOAD_INIT    6
+#define USB_BULK_UPLOAD_ADDR    7
+#define USB_BULK_UPLOAD_NEXT    8
+#define USB_BULK_UPLOAD_END     9
+#define USB_MODE_SNES           10
+#define USB_MODE_AVR            11
+#define USB_AVR_RESET           12
+#define USB_SET_LOADER          13
+
+/* -------------------------- Device Description --------------------------- */
+
+#define  USB_CFG_VENDOR_ID       0xc0, 0x16
+/* USB vendor ID for the device, low byte first. If you have registered your
+ * own Vendor ID, define it here. Otherwise you use one of obdev's free shared
+ * VID/PID pairs. Be sure to read USBID-License.txt for rules!
+ */
+#define  USB_CFG_DEVICE_ID       0xdd, 0x05
+/* This is the ID of the product, low byte first. It is interpreted in the
+ * scope of the vendor ID. If you have registered your own VID with usb.org
+ * or if you have licensed a PID from somebody else, define it here. Otherwise
+ * you use obdev's free shared VID/PID pair. Be sure to read the rules in
+ * USBID-License.txt!
+ */
+#define USB_CFG_DEVICE_VERSION  0x00, 0x01
+/* Version number of the device: Minor number first, then major number.
+ */
+#define USB_CFG_VENDOR_NAME     'o', 'p', 't', 'i', 'x', 'x', '.', 'o', 'r', 'g'
+#define USB_CFG_VENDOR_NAME_LEN 10
+/* These two values define the vendor name returned by the USB device. The name
+ * must be given as a list of characters under single quotes. The characters
+ * are interpreted as Unicode (UTF-16) entities.
+ * If you don't want a vendor name string, undefine these macros.
+ * ALWAYS define a vendor name containing your Internet domain name if you use
+ * obdev's free shared VID/PID pair. See the file USBID-License.txt for
+ * details.
+ */
+#define USB_CFG_DEVICE_NAME     'Q', 'U', 'I', 'C', 'K', 'D', 'E', 'V', '1', '6'
+#define USB_CFG_DEVICE_NAME_LEN 10
+
+/* end of quickdev protocol defines */
+
+#endif