summaryrefslogtreecommitdiffstats
path: root/commandline/library
diff options
context:
space:
mode:
Diffstat (limited to 'commandline/library')
-rw-r--r--commandline/library/micronucleus_lib.c111
-rw-r--r--commandline/library/micronucleus_lib.h43
-rw-r--r--commandline/library/opendevice.c203
-rw-r--r--commandline/library/opendevice.h82
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__ */