diff options
Diffstat (limited to 'commandline/library')
-rw-r--r-- | commandline/library/micronucleus_lib.c | 111 | ||||
-rw-r--r-- | commandline/library/micronucleus_lib.h | 43 | ||||
-rw-r--r-- | commandline/library/opendevice.c | 203 | ||||
-rw-r--r-- | commandline/library/opendevice.h | 82 |
4 files changed, 101 insertions, 338 deletions
diff --git a/commandline/library/micronucleus_lib.c b/commandline/library/micronucleus_lib.c index 8e01427..a719690 100644 --- a/commandline/library/micronucleus_lib.c +++ b/commandline/library/micronucleus_lib.c @@ -29,60 +29,98 @@ micronucleus* micronucleus_connect() { - micronucleus *tempHandle = NULL; - + micronucleus *nucleus = NULL; + struct usb_bus *busses; + + // intialise usb and find micronucleus device usb_init(); - usbOpenDevice(&tempHandle, VENDOR_ID, "*", PRODUCT_ID, "*", "*", NULL, NULL ); + usb_find_busses(); + usb_find_devices(); + + busses = usb_get_busses(); + struct usb_bus *bus; + for (bus = busses; bus; bus = bus->next) + { + struct usb_device *dev; + + for (dev = bus->devices; dev; dev = dev->next) + { + /* Check if this device is a micronucleus */ + if (dev->descriptor.idVendor == MICRONUCLEUS_VENDOR_ID && dev->descriptor.idProduct == MICRONUCLEUS_PRODUCT_ID) + { + nucleus = malloc(sizeof(micronucleus)); + nucleus->version.major = (dev->descriptor.bcdUSB >> 8) & 0xFF; + nucleus->version.minor = dev->descriptor.bcdUSB & 0xFF; + nucleus->device = usb_open(dev); + + // get nucleus info + unsigned char buffer[4]; + int res = usb_control_msg(nucleus->device, 0xC0, 0, 0, 0, buffer, 4, MICRONUCLEUS_USB_TIMEOUT); + assert(res == 4); + + nucleus->flash_size = (buffer[0]<<8) + buffer[1]; + nucleus->page_size = buffer[2]; + nucleus->pages = (nucleus->flash_size / nucleus->page_size); + if (nucleus->pages * nucleus->page_size < nucleus->flash_size) nucleus->pages += 1; + nucleus->write_sleep = buffer[3]; + nucleus->erase_sleep = nucleus->write_sleep * nucleus->pages; + } + } + } - return tempHandle; + return nucleus; } -int micronucleus_getDeviceInfo(micronucleus* deviceHandle, unsigned int* availableMemory, unsigned char* deviceSize, unsigned char* sleepAmount) +int micronucleus_eraseFlash(micronucleus* deviceHandle) { int res; - res = usb_control_msg(deviceHandle, 0xC0, 0, 0, 0, rxBuffer, 4, USB_TIMEOUT); - - if(res!=4) - return -1; + res = usb_control_msg(deviceHandle->device, 0xC0, 2, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT); - *availableMemory = (rxBuffer[0]<<8) + rxBuffer[1]; - *deviceSize = rxBuffer[2]; - *sleepAmount = rxBuffer[3]; + // give microcontroller enough time to erase all writable pages and come back online + delay(deviceHandle->erase_sleep); - return 0; -} - -int micronucleus_eraseFlash(micronucleus* deviceHandle, unsigned int sleepAmount) -{ - int res; - res = usb_control_msg(deviceHandle, 0xC0, 2, 0, 0, rxBuffer, 0, USB_TIMEOUT); - delay(sleepAmount); if(res!=0) return -1; else return 0; } -int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int startAddress, unsigned int endAddress, unsigned char* buffer, unsigned char sleepAmount) +int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_size, unsigned char* program) { - unsigned char tempBuffer[64]; - unsigned int i; - unsigned int k; - unsigned int res; + unsigned char page_length = deviceHandle->page_size; + unsigned char page_buffer[page_length]; + unsigned int address; // overall flash memory address + unsigned int page_address; // address within this page when copying buffer + unsigned int res; - for(i=startAddress;i<(endAddress);i+=64) - { - for(k=0;k<64;k++) - tempBuffer[k]=buffer[i+k]; + for (address = 0; address < deviceHandle->flash_size; address += deviceHandle->page_size) { + // work around a bug in older bootloader versions + if (deviceHandle->version.major == 1 && deviceHandle->version.minor <= 2 + && address / deviceHandle->page_size == deviceHandle->pages - 1) { + page_length = deviceHandle->flash_size % deviceHandle->page_size; + } - res = usb_control_msg(deviceHandle, + // copy in bytes from user program + for (page_address = 0; page_address < page_length; page_address += 1) { + if (address + page_address > program_size) { + page_buffer[page_address] = 0xFF; // pad out remainder with unprogrammed bytes + } else { + page_buffer[page_address] = program[address + page_address]; // load from user program + } + } + + // ask microcontroller to write this page's data + res = usb_control_msg(deviceHandle->device, USB_ENDPOINT_OUT| USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, - 64,i, - tempBuffer, 64, - USB_TIMEOUT); - delay(sleepAmount); - if(res!=64) return -1; + page_length, address, + page_buffer, page_length, + MICRONUCLEUS_USB_TIMEOUT); + + // give microcontroller enough time to write this page and come back online + delay(deviceHandle->write_sleep); + + if (res != 64) return -1; } return 0; @@ -91,7 +129,8 @@ int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int startAddres int micronucleus_startApp(micronucleus* deviceHandle) { int res; - res = usb_control_msg(deviceHandle, 0xC0, 4, 0, 0, rxBuffer, 0, USB_TIMEOUT); + res = usb_control_msg(deviceHandle->device, 0xC0, 4, 0, 0, NULL, 0, MICRONUCLEUS_USB_TIMEOUT); + if(res!=0) return -1; else diff --git a/commandline/library/micronucleus_lib.h b/commandline/library/micronucleus_lib.h index b724a60..dcbac83 100644 --- a/commandline/library/micronucleus_lib.h +++ b/commandline/library/micronucleus_lib.h @@ -32,25 +32,40 @@ #else #include <usb.h> // this is libusb, see http://libusb.sourceforge.net/ #endif -#include "opendevice.h" // common code moved to separate module +//#include "opendevice.h" // common code moved to separate module +#include <assert.h> /*******************************************************************************/ /******************************************************************************** * USB details ********************************************************************************/ -#define VENDOR_ID 0x16D0 -#define PRODUCT_ID 0x0753 -#define USB_TIMEOUT 0xFFFF -#define RX_BUFFER_SIZE 64 -#define TX_BUFFER_SIZE 64 +#define MICRONUCLEUS_VENDOR_ID 0x16D0 +#define MICRONUCLEUS_PRODUCT_ID 0x0753 +#define MICRONUCLEUS_USB_TIMEOUT 0xFFFF /*******************************************************************************/ /******************************************************************************** * Declearations ********************************************************************************/ -typedef usb_dev_handle micronucleus; -unsigned char rxBuffer[RX_BUFFER_SIZE]; /* This has to be unsigned for the data's sake */ -unsigned char tBuffer[TX_BUFFER_SIZE]; /* This has to be unsigned for the data's sake */ +//typedef usb_dev_handle micronucleus; +// representing version number of micronucleus device +typedef struct _micronucleus_version { + unsigned char major; + unsigned char minor; +} micronucleus_version; + +// handle representing one micronucleus device +typedef struct _micronucleus { + usb_dev_handle *device; + // general information about device + micronucleus_version version; + unsigned int flash_size; // programmable size (in bytes) of progmem + unsigned int page_size; // size (in bytes) of page + unsigned int pages; // total number of pages to program + unsigned int write_sleep; // milliseconds + unsigned int erase_sleep; // milliseconds +} micronucleus; + /*******************************************************************************/ /******************************************************************************** @@ -61,21 +76,15 @@ micronucleus* micronucleus_connect(); /*******************************************************************************/ /******************************************************************************** -* Get the device info -********************************************************************************/ -int micronucleus_getDeviceInfo(micronucleus* deviceHandle, unsigned int* availableMemory, unsigned char* deviceSize, unsigned char* sleepAmount); -/*******************************************************************************/ - -/******************************************************************************** * Erase the flash memory ********************************************************************************/ -int micronucleus_eraseFlash(micronucleus* deviceHandle,unsigned int sleepAmount); +int micronucleus_eraseFlash(micronucleus* deviceHandle); /*******************************************************************************/ /******************************************************************************** * Write the flash memory ********************************************************************************/ -int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int startAddress, unsigned int endAddress, unsigned char* buffer, unsigned char sleepAmount); +int micronucleus_writeFlash(micronucleus* deviceHandle, unsigned int program_length, unsigned char* program); /*******************************************************************************/ /******************************************************************************** diff --git a/commandline/library/opendevice.c b/commandline/library/opendevice.c deleted file mode 100644 index 137f50c..0000000 --- a/commandline/library/opendevice.c +++ /dev/null @@ -1,203 +0,0 @@ -/* 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; -} - -/* ------------------------------------------------------------------------- */ diff --git a/commandline/library/opendevice.h b/commandline/library/opendevice.h deleted file mode 100644 index f687ccd..0000000 --- a/commandline/library/opendevice.h +++ /dev/null @@ -1,82 +0,0 @@ -/* 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 755 2009-08-03 17:01:21Z 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__ - -#if defined WIN - #include <lusb0_usb.h> // this is libusb, see http://libusb.sourceforge.net/ -#else - #include <usb.h> // this is libusb, see http://libusb.sourceforge.net/ -#endif - -#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 USB-IDs-for-free.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__ */ |