diff --git a/.travis.yml b/.travis.yml index 4f21a80..c71f59b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ language: ruby -env: CODECLIMATE_REPO_TOKEN=ea524e4acf0abd2a5d396cc239710de238314e5bfe3af472baca56a88f7b7ec1 +env: CODECLIMATE_REPO_TOKEN=ea524e4acf0abd2a5d396cc239710de238314e5bfe3af472baca56a88f7b7ec1 SPEC_OPTS='--format documentation' rvm: - "1.9.3" - - rbx-19mode + - "2.0.0" + - "2.1.0" before_install: - sudo apt-get install -qq gcc-avr avr-libc - sudo apt-get install -qq libusb-1.0-0-dev diff --git a/ext/blink1/blink1-lib.c b/ext/blink1/blink1-lib.c old mode 100644 new mode 100755 index d6020d4..1e5d1b0 --- a/ext/blink1/blink1-lib.c +++ b/ext/blink1/blink1-lib.c @@ -1,8 +1,10 @@ -/* - * blink(1) C library -- +/** + * blink(1) C library -- aka "blink1-lib" * + * Part of the blink(1) open source hardware project + * See https://github.com/todbot/blink1 for details * - * 2012, Tod E. Kurt, http://todbot.com/blog/ , http://thingm.com/ + * 2012-2014, Tod E. Kurt, http://todbot.com/blog/ , http://thingm.com/ * */ @@ -10,80 +12,65 @@ #include #include #include // for toupper() +#include #ifdef _WIN32 #include +#define swprintf _snwprintf #else -#include // for usleep() +//#include // for usleep() #endif #include "blink1-lib.h" +// blink1 copy of some hid_device_info and other bits. +// this seems kinda dumb, though. is there a better way? +typedef struct blink1_info_ { + blink1_device* dev; // device, if opened, NULL otherwise + char path[pathstrmax]; // platform-specific device path + char serial[serialstrmax]; + int type; // from blink1types +} blink1_info; + +static blink1_info blink1_infos[cache_max]; +static int blink1_cached_count = 0; // number of cached entities +static int blink1_enable_degamma = 1; + +// set in Makefile to debug HIDAPI stuff #ifdef DEBUG_PRINTF #define LOG(...) fprintf(stderr, __VA_ARGS__) #else #define LOG(...) do {} while (0) #endif -#define blink1_report_id 1 -#define blink1_report_size 8 -#define blink1_buf_size (blink1_report_size+1) - -// addresses in EEPROM +// addresses in EEPROM for mk1 blink(1) devices #define blink1_eeaddr_osccal 0 #define blink1_eeaddr_bootmode 1 #define blink1_eeaddr_serialnum 2 #define blink1_serialnum_len 4 #define blink1_eeaddr_patternstart (blink1_eeaddr_serialnum + blink1_serialnum_len) -#define pathmax 16 -#define pathstrmax 128 -#define serialmax (8 + 1) +void blink1_sortCache(void); -// FIXME: use hid_device_info instead with custom sorter on serial or path -static char blink1_cached_paths[pathmax][pathstrmax]; -static int blink1_cached_count = 0; -static wchar_t blink1_cached_serials[pathmax][serialmax]; - -static int blink1_enable_degamma = 1; - //---------------------------------------------------------------------------- +// implementation-varying code -// -int blink1_enumerate(void) -{ - return blink1_enumerateByVidPid( blink1_vid(), blink1_pid() ); -} - -// get all matching devices by VID/PID pair -int blink1_enumerateByVidPid(int vid, int pid) -{ - struct hid_device_info *devs, *cur_dev; - - int p = 0; - devs = hid_enumerate(vid, pid); - cur_dev = devs; - while (cur_dev) { - if( (cur_dev->vendor_id != 0 && cur_dev->product_id != 0) && - (cur_dev->vendor_id == vid && cur_dev->product_id == pid) ) { - if( cur_dev->serial_number != NULL ) { // can happen if not root - strcpy( blink1_cached_paths[p], cur_dev->path ); - wcscpy( blink1_cached_serials[p], cur_dev->serial_number ); - p++; - } - } - cur_dev = cur_dev->next; - } - hid_free_enumeration(devs); +#if USE_HIDAPI +#include "blink1-lib-lowlevel-hidapi.h" +#elif USE_HIDDATA +#include "blink1-lib-lowlevel-hiddata.h" +#else +#error "Need to define USE_HIDAPI or USE_HIDDATA" +#endif - blink1_cached_count = p; - blink1_sortSerials(); - return p; -} +// ------------------------------------------------------------------------- +// everything below here doesn't need to know about USB details +// except for a "blink1_device*" +// ------------------------------------------------------------------------- // int blink1_getCachedCount(void) @@ -94,116 +81,66 @@ int blink1_getCachedCount(void) // const char* blink1_getCachedPath(int i) { - return blink1_cached_paths[i]; + return blink1_infos[i].path; } // -const wchar_t* blink1_getCachedSerial(int i) +const char* blink1_getCachedSerial(int i) { - return blink1_cached_serials[i]; + return blink1_infos[i].serial; } -// -hid_device* blink1_openByPath(const char* path) +int blink1_getCacheIndexByPath( const char* path ) { - if( path == NULL || strlen(path) == 0 ) return NULL; - hid_device* handle = hid_open_path( path ); - return handle; + for( int i=0; i< cache_max; i++ ) { + if( strcmp( blink1_infos[i].path, (const char*) path ) == 0 ) return i; + } + return -1; } -// -hid_device* blink1_openBySerial(const wchar_t* serial) +int blink1_getCacheIndexBySerial( const char* serial ) { - if( serial == NULL || wcslen(serial) == 0 ) return NULL; - int vid = blink1_vid(); - int pid = blink1_pid(); - - LOG("opening %ls at vid/pid %x/%x\n", serial, vid,pid); - hid_device* handle = hid_open(vid,pid, serial ); - return handle; + for( int i=0; i< cache_max; i++ ) { + if( strcmp( blink1_infos[i].serial, serial ) == 0 ) return i; + } + return -1; } -// -hid_device* blink1_openById( int i ) +int blink1_getCacheIndexByDev( blink1_device* dev ) { - //return blink1_openByPath( blink1_getCachedPath(i) ); - return blink1_openBySerial( blink1_getCachedSerial(i) ); + for( int i=0; i< cache_max; i++ ) { + if( blink1_infos[i].dev == dev ) return i; + } + return -1; } -// -hid_device* blink1_open(void) +const char* blink1_getSerialForDev(blink1_device* dev) { - int vid = blink1_vid(); - int pid = blink1_pid(); - - hid_device* handle = hid_open(vid,pid, NULL); // FIXME? - - return handle; + int i = blink1_getCacheIndexByDev( dev ); + if( i>=0 ) return blink1_infos[i].serial; + return NULL; } -// -// FIXME: search through blink1s list to zot it too? -void blink1_close( hid_device* dev ) +int blink1_clearCacheDev( blink1_device* dev ) { - if( dev != NULL ) - hid_close(dev); - dev = NULL; - hid_exit(); // FIXME: this cleans up libusb in a way that hid_close doesn't + int i = blink1_getCacheIndexByDev( dev ); + if( i>=0 ) blink1_infos[i].dev = NULL; // FIXME: hmmmm + return i; } -// -int blink1_write( hid_device* dev, void* buf, int len) +int blink1_isMk2ById( int i ) { - if( dev==NULL ) { - return -1; // BLINK1_ERR_NOTOPEN; - } - int rc = hid_send_feature_report( dev, buf, len ); - // FIXME: put this in an ifdef? - if( rc==-1 ) { - fprintf(stderr, "blink1_write error: %ls\n", hid_error(dev)); - } - return rc; + if( i>=0 && blink1_infos[i].type == BLINK1_MK2 ) return 1; + return 0; } -// len should contain length of buf -// after call, len will contain actual len of buf read -int blink1_read( hid_device* dev, void* buf, int len) +int blink1_isMk2( blink1_device* dev ) { - if( dev==NULL ) { - return -1; // BLINK1_ERR_NOTOPEN; - } - int rc = hid_send_feature_report(dev, buf, len); // FIXME: check rc - - if( (rc = hid_get_feature_report(dev, buf, len) == -1) ) { - LOG("error reading data: %s\n",blink1_error_msg(rc)); - } - return rc; + return blink1_isMk2ById( blink1_getCacheIndexByDev(dev) ); } -// ------------------------------------------------------------------------- -// everything below here doesn't need to know about USB details -// except for a "hid_device*" -// ------------------------------------------------------------------------- - -#include - -// -int blink1_getSerialNumber(hid_device *dev, char* buf) -{ - if( dev == NULL ) return -1; - /* - wchar_t* wbuf = dev->serial_number; - int i=0; - while( wbuf ) { - buf[i++] = *wbuf; - } - return i; - */ - return -1; -} - // -int blink1_getVersion(hid_device *dev) +int blink1_getVersion(blink1_device *dev) { char buf[blink1_buf_size] = {blink1_report_id, 'v' }; int len = sizeof(buf); @@ -214,14 +151,14 @@ int blink1_getVersion(hid_device *dev) if( rc != -1 ) // no error rc = blink1_read(dev, buf, len); if( rc != -1 ) // also no error - rc = ((buf[3]-'0') * 100) + (buf[4]-'0'); - // rc is now version number or error + rc = ((buf[3]-'0') * 100) + (buf[4]-'0'); + // rc is now version number or error // FIXME: we don't know vals of errcodes return rc; } // -int blink1_eeread(hid_device *dev, uint16_t addr, uint8_t* val) +int blink1_eeread(blink1_device *dev, uint16_t addr, uint8_t* val) { char buf[blink1_buf_size] = {blink1_report_id, 'e', addr }; int len = sizeof(buf); @@ -230,23 +167,23 @@ int blink1_eeread(hid_device *dev, uint16_t addr, uint8_t* val) blink1_sleep( 50 ); // FIXME: if( rc != -1 ) // no error rc = blink1_read(dev, buf, len ); - if( rc != -1 ) + if( rc != -1 ) *val = buf[3]; return rc; } // -int blink1_eewrite(hid_device *dev, uint16_t addr, uint8_t val) +int blink1_eewrite(blink1_device *dev, uint16_t addr, uint8_t val) { char buf[blink1_buf_size] = {blink1_report_id, 'E', addr, val }; int rc = blink1_write(dev, buf, sizeof(buf) ); - + return rc; } // FIXME: this doesn't work -int blink1_serialnumread(hid_device *dev, uint8_t** serialnum) +int blink1_serialnumread(blink1_device *dev, uint8_t** serialnum) { int rc = 0; for( int i=0; i= '0' && c <= '9') return (c - '0'); @@ -265,8 +202,8 @@ static uint8_t parseHex(char c) } // serialnum comes in as an ascii set of 8 characters representing -// 4-bytes -int blink1_serialnumwrite(hid_device *dev, uint8_t* serialnumstr) +// 4-bytes +int blink1_serialnumwrite(blink1_device *dev, uint8_t* serialnumstr) { uint8_t serialnum[4]; serialnum[0] = parseHex( serialnumstr[0] )*16 + parseHex( serialnumstr[1] ); @@ -276,13 +213,13 @@ int blink1_serialnumwrite(hid_device *dev, uint8_t* serialnumstr) int rc = 0; for( int i=0; i>8), (dms % 0xff) }; + uint8_t buf[blink1_buf_size]; + buf[0] = blink1_report_id; + buf[1] = 'D'; + buf[2] = on; + buf[3] = (dms>>8); + buf[4] = (dms % 0xff); + buf[5] = st; // mk2 only + buf[6] = 0; + buf[7] = 0; int rc = blink1_write(dev, buf, sizeof(buf) ); return rc; } // -int blink1_play(hid_device *dev, uint8_t play, uint8_t pos) +int blink1_play(blink1_device *dev, uint8_t play, uint8_t startpos) +{ + return blink1_playloop(dev, play, startpos, 0,0); +} + +// mk2 devices only +int blink1_playloop(blink1_device *dev, uint8_t play, uint8_t startpos,uint8_t endpos, uint8_t count) { - char buf[blink1_buf_size] = {blink1_report_id, 'p', play, pos }; + uint8_t buf[blink1_buf_size]; + buf[0] = blink1_report_id; + buf[1] = 'p'; + buf[2] = play; + buf[3] = startpos; + buf[4] = endpos; + buf[5] = count; + buf[6] = 0; + buf[7] = 0; + int rc = blink1_write(dev, buf, sizeof(buf) ); return rc; } + +// mk2 devices only +int blink1_readPlayState(blink1_device *dev, uint8_t* playing, + uint8_t* playstart, uint8_t* playend, + uint8_t* playcount, uint8_t* playpos) +{ + uint8_t buf[blink1_buf_size] = { blink1_report_id, 'S', 0,0,0, 0,0,0 }; + + int rc = blink1_write(dev, buf, sizeof(buf) ); + blink1_sleep( 50 ); // FIXME: + if( rc != -1 ) // no error + rc = blink1_read(dev, buf, sizeof(buf) ); + if( rc != -1 ) { + *playing = buf[2]; + *playstart = buf[3]; + *playend = buf[4]; + *playcount = buf[5]; + *playpos = buf[6]; + } + return rc; +} + // -int blink1_writePatternLine(hid_device *dev, uint16_t fadeMillis, - uint8_t r, uint8_t g, uint8_t b, +int blink1_writePatternLine(blink1_device *dev, uint16_t fadeMillis, + uint8_t r, uint8_t g, uint8_t b, uint8_t pos) { int dms = fadeMillis/10; // millis_divided_by_10 @@ -385,17 +394,19 @@ int blink1_writePatternLine(hid_device *dev, uint16_t fadeMillis, g = (blink1_enable_degamma) ? blink1_degamma(g) : g ; b = (blink1_enable_degamma) ? blink1_degamma(b) : b ; - char buf[blink1_buf_size] = {blink1_report_id, 'P', r,g,b, (dms>>8), (dms % 0xff), pos }; + uint8_t buf[blink1_buf_size] = + {blink1_report_id, 'P', r,g,b, (dms>>8), (dms % 0xff), pos }; int rc = blink1_write(dev, buf, sizeof(buf) ); return rc; } // -int blink1_readPatternLine(hid_device *dev, uint16_t* fadeMillis, - uint8_t* r, uint8_t* g, uint8_t* b, +int blink1_readPatternLine(blink1_device *dev, uint16_t* fadeMillis, + uint8_t* r, uint8_t* g, uint8_t* b, uint8_t pos) { - char buf[blink1_buf_size] = {blink1_report_id, 'R', 0,0,0, 0,0, pos }; + uint8_t buf[blink1_buf_size] = { blink1_report_id, 'R', 0,0,0, 0,0, pos }; + int rc = blink1_write(dev, buf, sizeof(buf) ); blink1_sleep( 50 ); // FIXME: if( rc != -1 ) // no error @@ -409,41 +420,48 @@ int blink1_readPatternLine(hid_device *dev, uint16_t* fadeMillis, return rc; } - -// FIXME: -int readUUID( hid_device* dev, uint8_t** uuid ) +// mk2 devices only, mk1 devices save on each writePatternLine() +int blink1_savePattern( blink1_device *dev ) { - return -1; + uint8_t buf[blink1_buf_size]; + + buf[0] = blink1_report_id; // report id + buf[1] = 'W'; // command code for "write pattern to flash" + buf[2] = 0xBE; + buf[3] = 0xEF; + buf[4] = 0xCA; + buf[5] = 0xFE; + buf[6] = 0x00; + buf[7] = 0x00; + int rc = blink1_write(dev, buf, sizeof(buf) ); + // note rc will always return -1 + // because of issue with flash programming timing out USB + return 0; // assume success } -// FIXME: -int setUUID( hid_device* dev, uint8_t* uuid ) + +// +int blink1_testtest( blink1_device *dev) { - return -1; + uint8_t buf[blink1_buf_size] = { blink1_report_id, '!', 0,0,0, 0,0,0 }; + + int rc = blink1_write(dev, buf, sizeof(buf) ); + blink1_sleep( 50 ); //FIXME: + if( rc != -1 ) { // no error + rc = blink1_read(dev, buf, sizeof(buf)); + for( int i=0; i linear mapping as a sort of gamma correction // maps from 0-255 to 0-255 -static int blink1_degamma_log2lin( int n ) +static int blink1_degamma_log2lin( int n ) { //return (int)(1.0* (n * 0.707 )); // 1/sqrt(2) - return (((1<<(n/32))-1) + ((1<<(n/32))*((n%32)+1)+15)/32); + return (((1<<(n/32))-1) + ((1<<(n/32))*((n%32)+1)+15)/32); } - +// from http://rgb-123.com/ws2812-color-output/ +// GammaE=255*(res/255).^(1/.45) // -int blink1_degamma( int n ) +uint8_t GammaE[] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, +2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, +6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, +11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, +19, 19, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, +29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40, +40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, +55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, +71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89, +90, 91, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,110, +111,113,114,116,117,119,120,121,123,124,126,128,129,131,132,134, +135,137,138,140,142,143,145,146,148,150,151,153,155,157,158,160, +162,163,165,167,169,170,172,174,176,178,179,181,183,185,187,189, +191,193,194,196,198,200,202,204,206,208,210,212,214,216,218,220, +222,224,227,229,231,233,235,237,239,241,244,246,248,250,252,255}; +// +static int blink1_degamma_better( int n ) { - //return degamma_lookup[n]; - return blink1_degamma_log2lin(n); + return GammaE[n]; } - -// qsort C-string comparison function -int cmp_path(const void *a, const void *b) -{ - return strncmp( (const char *)a, (const char *)b, pathstrmax); -} -// qsort wchar_t string comparison function -int cmp_serial(const void *a, const void *b) -{ - return wcsncmp( (const wchar_t *)a, (const wchar_t *)b, serialmax); +// +int blink1_degamma( int n ) +{ + //return blink1_degamma_log2lin(n); + return blink1_degamma_better(n); } -// -void blink1_sortPaths(void) -{ - size_t elemsize = sizeof( blink1_cached_paths[0] ); // 128 - //size_t count = sizeof(blink1_cached_paths) / elemsize; // 16 +// qsort char* string comparison function +int cmp_blink1_info_serial(const void *a, const void *b) +{ + blink1_info* bia = (blink1_info*) a; + blink1_info* bib = (blink1_info*) b; - return qsort( blink1_cached_paths, blink1_cached_count,elemsize,cmp_path); -} + return strncmp( bia->serial, + bib->serial, + serialstrmax); +} -// -void blink1_sortSerials(void) +void blink1_sortCache(void) { - size_t elemsize = sizeof( blink1_cached_serials[0] ); // - //size_t count = sizeof(blink1_cached_serials) / elemsize; // - - qsort( blink1_cached_serials, - blink1_cached_count, - elemsize, - cmp_serial); + size_t elemsize = sizeof( blink1_info ); // + + qsort( blink1_infos, + blink1_cached_count, + elemsize, + cmp_blink1_info_serial); } + // int blink1_vid(void) { - uint8_t rawVid[2] = {USB_CFG_VENDOR_ID}; - int vid = rawVid[0] + 256 * rawVid[1]; - return vid; + //uint8_t rawVid[2] = {USB_CFG_VENDOR_ID}; + //int vid = rawVid[0] + 256 * rawVid[1]; + return BLINK1_VENDOR_ID; } // int blink1_pid(void) { - uint8_t rawPid[2] = {USB_CFG_DEVICE_ID}; - int pid = rawPid[0] + 256 * rawPid[1]; - return pid; + //uint8_t rawPid[2] = {USB_CFG_DEVICE_ID}; + //int pid = rawPid[0] + 256 * rawPid[1]; + return BLINK1_DEVICE_ID; } // simple cross-platform millis sleep func @@ -522,63 +554,9 @@ void blink1_sleep(uint16_t millis) { #ifdef WIN32 Sleep(millis); -#else +#else usleep( millis * 1000); #endif } -// -char *blink1_error_msg(int errCode) -{ - /* - static char buf[80]; - - switch(errCode){ - case USBOPEN_ERR_ACCESS: return "Access to device denied"; - case USBOPEN_ERR_NOTFOUND: return "The specified device was not found"; - case USBOPEN_ERR_IO: return "Communication error with device"; - default: - sprintf(buf, "Unknown USB error %d", errCode); - return buf; - } - */ - return NULL; /* not reached */ -} - - -/* - -// -int blink1_nightlight(hid_device *dev, uint8_t on) -{ - char buf[8] = { blink1_report_id, 'N', on }; - - int rc = blink1_write(dev, buf, sizeof(buf) ); - - return rc; -} - -// -int blink1_command(hid_device* dev, int num_send, int num_recv, - uint8_t* buf_send, uint8_t* buf_recv ) -{ - if( dev==NULL ) { - return -1; // BLINK1_ERR_NOTOPEN; - } - int err = 0; - if( (err = usbhidSetReport(dev, (char*)buf_send, num_send)) != 0) { - fprintf(stderr,"error writing data: %s\n",blink1_error_msg(err)); - return err; - } - - if( num_recv > 0 ) { - int len = num_recv; - if((err = usbhidGetReport(dev, 0, (char*)buf_recv, &len)) != 0) { - fprintf(stderr,"error reading data: %s\n",blink1_error_msg(err)); - } else { // it was good - } - } - return err; -} -*/ \ No newline at end of file diff --git a/ext/blink1/blink1-lib.h b/ext/blink1/blink1-lib.h old mode 100644 new mode 100755 index df6fa2a..f6e7700 --- a/ext/blink1/blink1-lib.h +++ b/ext/blink1/blink1-lib.h @@ -1,7 +1,10 @@ -/* - * blink(1) C library -- +/** + * blink(1) C library -- aka "blink1-lib" + * + * Part of the blink(1) open source hardware project + * See https://github.com/todbot/blink1 for details * - * 2012, Tod E. Kurt, http://todbot.com/blog/ , http://thingm.com/ + * 2012-2014, Tod E. Kurt, http://todbot.com/blog/ , http://thingm.com/ * */ @@ -11,75 +14,382 @@ #include -#include "hidapi.h" -#include "usbconfig.h" // from firmware, for VID,PID,vendor name & product name - #ifdef __cplusplus extern "C" { #endif #define blink1_max_devices 16 +#define cache_max 16 +#define serialstrmax (8 + 1) +#define pathstrmax 128 + +#define blink1mk2_serialstart 0x20000000 + +#define BLINK1_VENDOR_ID 0x27B8 /* = 0x27B8 = 10168 = thingm */ +#define BLINK1_DEVICE_ID 0x01ED /* = 0x01ED */ -int blink1_vid(void); -int blink1_pid(void); -void blink1_sortPaths(void); -void blink1_sortSerials(void); +#define blink1_report_id 1 +#define blink1_report_size 8 +#define blink1_buf_size (blink1_report_size+1) -int blink1_enumerate(); -int blink1_enumerateByVidPid(int vid, int pid); -const char* blink1_getCachedPath(int i); -const wchar_t* blink1_getCachedSerial(int i); -int blink1_getCachedCount(void); +enum { + BLINK1_UNKNOWN = 0, + BLINK1_MK1, // the original one from the kickstarter + BLINK1_MK2 // the updated one +}; -hid_device* blink1_open(void); -hid_device* blink1_openByPath(const char* path); -hid_device* blink1_openBySerial(const wchar_t* serial); -hid_device* blink1_openById( int i ); +struct blink1_device_; + +#if USE_HIDAPI +typedef struct hid_device_ blink1_device; /**< opaque blink1 structure */ +#elif USE_HIDDATA +typedef struct usbDevice blink1_device; /**< opaque blink1 structure */ +#else +#warning "USE_HIDAPI or USE_HIDDATA wasn't defined, defaulting to USE_HIDAPI" +typedef struct hid_device_ blink1_device; /**< opaque blink1 structure */ +#endif -void blink1_close( hid_device* dev ); -int blink1_write( hid_device* dev, void* buf, int len); -int blink1_read( hid_device* dev, void* buf, int len); +// +// -------- BEGIN PUBLIC API ---------- +// -int blink1_getSerialNumber(hid_device *dev, char* buf); -int blink1_getVersion(hid_device *dev); +/** + * Scan USB for blink(1) devices. + * @return number of devices found + */ +int blink1_enumerate(); + +/** + * Scan USB for devices by given VID,PID. + * @param vid vendor ID + * @param pid product ID + * @return number of devices found + */ +int blink1_enumerateByVidPid(int vid, int pid); -int blink1_fadeToRGB(hid_device *dev, uint16_t fadeMillis, +/** + * Open first found blink(1) device. + * @return pointer to opened blink1_device or NULL if no blink1 found + */ +blink1_device* blink1_open(void); + +/** + * Open blink(1) by USB path. + * note: this is platform-specific, and port-specific. + * @param path string of platform-specific path to blink1 + * @return blink1_device or NULL if no blink1 found + */ +blink1_device* blink1_openByPath(const char* path); + +/** + * Open blink(1) by 8-digit serial number. + * @param serial 8-hex digit serial number + * @return blink1_device or NULL if no blink1 found + */ +blink1_device* blink1_openBySerial(const char* serial); + +/** + * Open by "id", which if from 0-blink1_max_devices is index + * or if >blink1_max_devices, is numerical representation of serial number + * @param id ordinal 0-15 id of blink1 or numerical rep of 8-hex digit serial + * @return blink1_device or NULL if no blink1 found + */ +blink1_device* blink1_openById( uint32_t id ); + +/** + * Close opened blink1 device. + * Safe to call blink1_close on already closed device. + * @param dev blink1_device + */ +void blink1_close( blink1_device* dev ); + +/** + * Low-level write to blink1 device. + * Used internally by blink1-lib + */ +int blink1_write( blink1_device* dev, void* buf, int len); +/** + * Low-level read from blink1 device. + * Used internally by blink1-lib + */ +int blink1_read( blink1_device* dev, void* buf, int len); + +/** + * Get blink1 firmware version. + * @param dev opened blink1 device + * @return version as scaled int number (e.g. "v1.1" = 101) + */ +int blink1_getVersion(blink1_device *dev); + +/** + * Fade blink1 to given RGB color over specified time. + * @param dev blink1 device to command + * @param fadeMillis time to fade in milliseconds + * @param r red part of RGB color + * @param g green part of RGB color + * @param b blue part of RGB color + * @return -1 on error, 0 on success + */ +int blink1_fadeToRGB(blink1_device *dev, uint16_t fadeMillis, uint8_t r, uint8_t g, uint8_t b ); -int blink1_fadeToRGBN(hid_device *dev, uint16_t fadeMillis, + +/** + * Fade specific LED on blink1mk2 to given RGB color over specified time. + * @note For mk2 devices. + * @param dev blink1 device to command + * @param fadeMillis time to fade in milliseconds + * @param r red part of RGB color + * @param g green part of RGB color + * @param b blue part of RGB color + * @param n which LED to address (0=all, 1=1st LED, 2=2nd LED) + * @return -1 on error, 0 on success + */ +int blink1_fadeToRGBN(blink1_device *dev, uint16_t fadeMillis, uint8_t r, uint8_t g, uint8_t b, uint8_t n ); +/** + * Set blink1 immediately to a specific RGB color. + * @note If mk2, sets all LEDs immediately + * @param dev blink1 device to command + * @param r red part of RGB color + * @param g green part of RGB color + * @param b blue part of RGB color + * @return -1 on error, 0 on success + */ +int blink1_setRGB(blink1_device *dev, uint8_t r, uint8_t g, uint8_t b ); -int blink1_setRGB(hid_device *dev, uint8_t r, uint8_t g, uint8_t b ); +/** + * Read current RGB value on specified LED. + * @note For mk2 devices only. + * @param dev blink1 device to command + * @param r pointer to red part of RGB color + * @param g pointer to green part of RGB color + * @param b pointer to blue part of RGB color + * @param n which LED to get (0=1st, 1=1st LED, 2=2nd LED) + * @return -1 on error, 0 on success + */ +int blink1_readRGB(blink1_device *dev, uint16_t* fadeMillis, + uint8_t* r, uint8_t* g, uint8_t* b, + uint8_t ledn); +/** + * Attempt to read current RGB value for mk1 devices. + * @note Called by blink1_setRGB() if device is mk1. + * @note Does not always work. + * @param dev blink1 device to command + * @param r pointer to red part of RGB color + * @param g pointer to green part of RGB color + * @param b pointer to blue part of RGB color + * @return -1 on error, 0 on success + */ +int blink1_readRGB_mk1(blink1_device *dev, uint16_t* fadeMillis, + uint8_t* r, uint8_t* g, uint8_t* b); -int blink1_eeread(hid_device *dev, uint16_t addr, uint8_t* val); -int blink1_eewrite(hid_device *dev, uint16_t addr, uint8_t val); +/** + * Read eeprom on mk1 devices + * @note For mk1 devices only + */ +int blink1_eeread(blink1_device *dev, uint16_t addr, uint8_t* val); +/** + * Write eeprom on mk1 devices + * @note For mk1 devices only + */ +int blink1_eewrite(blink1_device *dev, uint16_t addr, uint8_t val); -int blink1_serialnumread(hid_device *dev, uint8_t** serialnumstr); -int blink1_serialnumwrite(hid_device *dev, uint8_t* serialnumstr); +/** + * Read serial number from mk1 device. Does not work. + * @note Use USB descriptor serial number instead. + * @note for mk1 devices only. + * @note does not work. + */ +int blink1_serialnumread(blink1_device *dev, uint8_t** serialnumstr); +/** + * Write serial number to mk1 device. Does not work. + * @note for mk1 devices only. + * @note does not work. + */ +int blink1_serialnumwrite(blink1_device *dev, uint8_t* serialnumstr); -//int blink1_nightlight(hid_device *dev, uint8_t on); -int blink1_serverdown(hid_device *dev, uint8_t on, uint16_t millis); +/** + * Tickle blink1 serverdown functionality. + * @note 'st' param for mk2 firmware only + * @param on enable or disable: enable=1, disable=0 + * @param millis milliseconds to wait until triggering + * @param stay lit (st=1) or set off() (st=0) + */ +int blink1_serverdown(blink1_device *dev, uint8_t on, uint16_t millis, + uint8_t st); -int blink1_play(hid_device *dev, uint8_t play, uint8_t pos); -int blink1_writePatternLine(hid_device *dev, uint16_t fadeMillis, +/** + * Play color pattern stored in blink1. + * @param dev blink1 device to command + * @param play boolean: 1=play, 0=stop + * @param pos position to start playing from + * @return -1 on error, 0 on success + */ +int blink1_play(blink1_device *dev, uint8_t play, uint8_t pos); + +/** + * Play color pattern stored in blink1mk2. + * @note For mk2 devices only. + * @param dev blink1 device to command + * @param play boolean: 1=play, 0=stop + * @param startpos position to start playing from + * @param endpos position to end playing + * @param count number of times to play (0=forever) + * @return -1 on error, 0 on success + */ +int blink1_playloop(blink1_device *dev, uint8_t play, uint8_t startpos, uint8_t endpos, uint8_t count); + +/** + * Read the current state of a playing pattern. + * @note For mk2 devices only. + * @param dev blink1 device to command + * @param playing pointer to play/stop boolean + * @param playstart pointer to start position + * @param playend pointer to end position + * @param playcount pointer to count left + * @param playpos pointer to play position + * @return -1 on error, 0 on success + */ +int blink1_readPlayState(blink1_device *dev, uint8_t* playing, + uint8_t* playstart, uint8_t* playend, + uint8_t* playcount, uint8_t* playpos); + +/** + * Write a color pattern line to blink1. + * @note on mk1 devices, this saves the pattern line to nonvolatile storage. + * @note on mk2 devices, this only saves to RAM (see savePattern() for nonvol) + * @param dev blink1 device to command + * @param r red part of RGB color + * @param g green part of RGB color + * @param b blue part of RGB color + * @param pos pattern line number 0-max_patt (FIXME: put note about this) + * @return -1 on error, 0 on success + */ +int blink1_writePatternLine(blink1_device *dev, uint16_t fadeMillis, uint8_t r, uint8_t g, uint8_t b, uint8_t pos); -int blink1_readPatternLine(hid_device *dev, uint16_t* fadeMillis, +/** + * Write a color pattern line to blink1. + * @param dev blink1 device to command + * @param fadeMillis pointer to milliseconds to fade to RGB color + * @return -1 on error, 0 on success + */ +int blink1_readPatternLine(blink1_device *dev, uint16_t* fadeMillis, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t pos); -//int blink1_playPattern(hid_device *dev,,); +/** + * Save color pattern in RAM to nonvolatile storage. + * @note For mk2 devices only. + * @note this doesn't actually return a proper return value, as the + * time it takes to write to flash actually exceeds USB timeout + * @param dev blink1 device to command + * @return -1 on error, 0 on success + */ +int blink1_savePattern(blink1_device *dev); + +int blink1_testtest(blink1_device *dev); char *blink1_error_msg(int errCode); +/* + * Enable blink1-lib gamma curve. + */ void blink1_enableDegamma(); + +/* + * Disable blink1-lib gamma curve. + * @note should probably always have it disabled + */ void blink1_disableDegamma(); int blink1_degamma(int n); +/** + * Simple wrapper for cross-platform millisecond delay. + * @param delayMillis number of milliseconds to wait + */ void blink1_sleep(uint16_t delayMillis); +/** + * Vendor ID for blink1 devices. + * @return blink1 VID + */ +int blink1_vid(void); // return VID for blink(1) +/** + * Product ID for blink1 devices. + * @return blink1 PID + */ +int blink1_pid(void); // return PID for blink(1) + + +/** + * Return platform-specific USB path for given cache index. + * @param i cache index + * @return path string + */ +const char* blink1_getCachedPath(int i); +/** + * Return bilnk1 serial number for given cache index. + * @param i cache index + * @return 8-hexdigit serial number as string + */ +const char* blink1_getCachedSerial(int i); +/** + * Return cache index for a given platform-specific USB path. + * @param path platform-specific path string + * @return cache index or -1 if not found + */ +int blink1_getCacheIndexByPath( const char* path ); +/** + * Return cache index for a given blink1 serial number. + * @param path platform-specific path string + * @return cache index or -1 if not found + */ +int blink1_getCacheIndexBySerial( const char* serial ); +/** + * Return cache index for a given blink1_device object. + * @param dev blink1 device to lookup + * @return cache index or -1 if not found + */ +int blink1_getCacheIndexByDev( blink1_device* dev ); +/** + * Clear the blink1 device cache for a given device. + * @param dev blink1 device + * @return cache index that was cleared, or -1 if not found + */ +int blink1_clearCacheDev( blink1_device* dev ); + +/** + * Return serial number string for give blink1 device. + * @param dev blink device to lookup + * @return 8-hexdigit serial number string + */ +const char* blink1_getSerialForDev(blink1_device* dev); +/** + * Return number of entries in blink1 device cache. + * @note This is the number of devices found with blink1_enumerate() + * @return number of cache entries + */ +int blink1_getCachedCount(void); + +/** + * Returns if device at cache index i is a mk2 + * + * @return mk2=1, mk1=0 + */ +int blink1_isMk2ById(int i); + +/** + * Returns if given blink1_device is a mk2 or not + * @param dev blink1 device to check + * @return mk2=1, mk1=0 + */ +int blink1_isMk2(blink1_device* dev); + + #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/ext/blink1/color_funcs.h b/ext/blink1/color_funcs.h old mode 100644 new mode 100755 diff --git a/ext/blink1/hid.c.libusb b/ext/blink1/hid.c.libusb old mode 100644 new mode 100755 index 3295fc8..6c1d247 --- a/ext/blink1/hid.c.libusb +++ b/ext/blink1/hid.c.libusb @@ -14,7 +14,7 @@ At the discretion of the user of this library, this software may be licensed under the terms of the - GNU Public License v3, a BSD-Style license, or the + GNU General Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. @@ -105,6 +105,7 @@ struct hid_device_ { pthread_cond_t condition; pthread_barrier_t barrier; /* Ensures correct startup sequence */ int shutdown_thread; + int cancelled; struct libusb_transfer *transfer; /* List of received input reports. */ @@ -683,10 +684,12 @@ static void read_callback(struct libusb_transfer *transfer) } else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { dev->shutdown_thread = 1; + dev->cancelled = 1; return; } else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { dev->shutdown_thread = 1; + dev->cancelled = 1; return; } else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { @@ -701,6 +704,7 @@ static void read_callback(struct libusb_transfer *transfer) if (res != 0) { LOG("Unable to submit URB. libusb error code: %d\n", res); dev->shutdown_thread = 1; + dev->cancelled = 1; } } @@ -750,10 +754,10 @@ static void *read_thread(void *param) /* Cancel any transfer that may be pending. This call will fail if no transfers are pending, but that's OK. */ - if (libusb_cancel_transfer(dev->transfer) == 0) { - /* The transfer was cancelled, so wait for its completion. */ - libusb_handle_events(usb_context); - } + libusb_cancel_transfer(dev->transfer); + + while (!dev->cancelled) + libusb_handle_events_completed(usb_context, &dev->cancelled); /* Now that the read thread is stopping, Wake any threads which are waiting on data (in hid_read_timeout()). Do this under a mutex to @@ -786,11 +790,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) int d = 0; int good_open = 0; - dev = new_hid_device(); - if(hid_init() < 0) return NULL; + dev = new_hid_device(); + libusb_get_device_list(usb_context, &devs); while ((usb_dev = devs[d++]) != NULL) { struct libusb_device_descriptor desc; @@ -1420,4 +1424,4 @@ uint16_t get_usb_code_for_current_locale(void) #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/ext/blink1/hid.c.mac b/ext/blink1/hid.c.mac old mode 100644 new mode 100755 index 044f8ac..38bb635 --- a/ext/blink1/hid.c.mac +++ b/ext/blink1/hid.c.mac @@ -11,7 +11,7 @@ At the discretion of the user of this library, this software may be licensed under the terms of the - GNU Public License v3, a BSD-Style license, or the + GNU General Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. @@ -420,6 +420,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, process_pending_events(); /* Get a list of the Devices */ + IOHIDManagerSetDeviceMatching(hid_mgr, NULL); CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); /* Convert the list into a C array so we can iterate easily. */ @@ -1108,4 +1109,4 @@ int main(void) return 0; } -#endif \ No newline at end of file +#endif diff --git a/ext/blink1/hid.c.windows b/ext/blink1/hid.c.windows index d47bc94..3dee05b 100755 --- a/ext/blink1/hid.c.windows +++ b/ext/blink1/hid.c.windows @@ -8,10 +8,10 @@ 8/22/2009 Copyright 2009, All Rights Reserved. - + At the discretion of the user of this library, this software may be licensed under the terms of the - GNU Public License v3, a BSD-Style license, or the + GNU General Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. @@ -172,7 +172,7 @@ static void register_error(hid_device *device, const char *op) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPVOID)&msg, 0/*sz*/, NULL); - + /* Get rid of the CR and LF that FormatMessage() sticks at the end of the message. Thanks Microsoft! */ ptr = msg; @@ -284,9 +284,9 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - + /* Iterate over each device in the HID class, looking for the right one. */ - + for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; @@ -297,7 +297,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor &InterfaceClassGuid, device_index, &device_interface_data); - + if (!res) { /* A return of FALSE from this function means that there are no more devices. */ @@ -369,7 +369,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; - } + } /* Get the Vendor ID and Product ID for this device. */ @@ -413,7 +413,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor HidD_FreePreparsedData(pp_data); } - + /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; @@ -513,7 +513,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; - + devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { @@ -539,7 +539,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi } hid_free_enumeration(devs); - + return handle; } @@ -575,7 +575,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) } nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res != HIDP_STATUS_SUCCESS) { - register_error(dev, "HidP_GetCaps"); + register_error(dev, "HidP_GetCaps"); goto err_pp_data; } dev->output_report_length = caps.OutputReportByteLength; @@ -588,7 +588,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) err_pp_data: HidD_FreePreparsedData(pp_data); -err: +err: free_hid_device(dev); return NULL; } @@ -621,7 +621,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * } res = WriteFile(dev->device_handle, buf, length, NULL, &ol); - + if (!res) { if (GetLastError() != ERROR_IO_PENDING) { /* WriteFile() failed. Return error. */ @@ -663,7 +663,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char memset(dev->read_buf, 0, dev->input_report_length); ResetEvent(ev); res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); - + if (!res) { if (GetLastError() != ERROR_IO_PENDING) { /* ReadFile() has failed. @@ -689,7 +689,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char we are in non-blocking mode. Get the number of bytes read. The actual data has been copied to the data[] array which was passed to ReadFile(). */ res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); - + /* Set pending back to false, even if GetOverlappedResult() returned error. */ dev->read_pending = FALSE; @@ -710,13 +710,13 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char memcpy(data, dev->read_buf, copy_len); } } - + end_of_function: if (!res) { register_error(dev, "GetOverlappedResult"); return -1; } - + return bytes_read; } @@ -855,7 +855,7 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) /*#define PICPGM*/ /*#define S11*/ #define P32 -#ifdef S11 +#ifdef S11 unsigned short VendorID = 0xa0a0; unsigned short ProductID = 0x0001; #endif @@ -885,7 +885,7 @@ int __cdecl main(int argc, char* argv[]) memset(buf,0x00,sizeof(buf)); buf[0] = 0; buf[1] = 0x81; - + /* Open the device. */ int handle = open(VendorID, ProductID, L"12345"); @@ -920,4 +920,4 @@ int __cdecl main(int argc, char* argv[]) #ifdef __cplusplus } /* extern "C" */ -#endif \ No newline at end of file +#endif diff --git a/ext/blink1/hidapi.h b/ext/blink1/hidapi.h old mode 100644 new mode 100755 index 88c6c3e..5730f86 --- a/ext/blink1/hidapi.h +++ b/ext/blink1/hidapi.h @@ -11,7 +11,7 @@ At the discretion of the user of this library, this software may be licensed under the terms of the - GNU Public License v3, a BSD-Style license, or the + GNU General Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. @@ -87,7 +87,7 @@ extern "C" { needed. This function should be called at the beginning of execution however, if there is a chance of HIDAPI handles being opened by different threads simultaneously. - + @ingroup API @returns @@ -218,7 +218,8 @@ extern "C" { @returns This function returns the actual number of bytes read and - -1 on error. + -1 on error. If no packet was available to be read within + the timeout period, this function returns 0. */ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); @@ -237,7 +238,8 @@ extern "C" { @returns This function returns the actual number of bytes read and - -1 on error. + -1 on error. If no packet was available to be read and + the handle is in non-blocking mode, this function returns 0. */ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); @@ -382,3 +384,4 @@ extern "C" { #endif #endif + diff --git a/ext/blink1/osccal.h b/ext/blink1/osccal.h old mode 100644 new mode 100755 index 6a3e8a3..d64ef91 --- a/ext/blink1/osccal.h +++ b/ext/blink1/osccal.h @@ -14,8 +14,8 @@ const uint8_t EEPROM_ADDR_OSCCAL = 0; static void calibrationLoad(void) { uint8_t calibrationValue; - // calibration value from last time - calibrationValue = eeprom_read_byte(EEPROM_ADDR_OSCCAL); + // calibration value from last time + calibrationValue = eeprom_read_byte(EEPROM_ADDR_OSCCAL); if(calibrationValue != 0xff){ OSCCAL = calibrationValue; } @@ -42,8 +42,8 @@ static void calibrateOscillator(void) /* do a binary search: */ do{ OSCCAL = trialValue + step; - x = usbMeasureFrameLength(); // proportional to current real frequency - if(x < targetValue) // frequency still too low + x = usbMeasureFrameLength(); // proportional to current real frequency + if(x < targetValue) // frequency still too low trialValue += step; step >>= 1; }while(step > 0); @@ -76,10 +76,10 @@ both regions. void usbEventResetReady(void) { calibrateOscillator(); - // store the calibrated value in EEPROM + // store the calibrated value in EEPROM eeprom_write_byte(EEPROM_ADDR_OSCCAL, OSCCAL); - + usbHasBeenSetup++; } -#endif \ No newline at end of file +#endif diff --git a/ext/blink1/usbconfig.h b/ext/blink1/usbconfig.h old mode 100644 new mode 100755 index 8dace59..8f09b72 --- a/ext/blink1/usbconfig.h +++ b/ext/blink1/usbconfig.h @@ -269,8 +269,8 @@ extern void usbEventResetReady(void); */ /*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ /*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ -#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 't','h','i','n','g' -#define USB_CFG_SERIAL_NUMBER_LEN 8 +#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 't','h','i','n','g' +#define USB_CFG_SERIAL_NUMBER_LEN 8 /* Same as above for the serial number. If you don't want a serial number, * undefine the macros. * It may be useful to provide the serial number through other means than at @@ -385,4 +385,4 @@ extern void usbEventResetReady(void); /* #define USB_INTR_PENDING_BIT INTF0 */ /* #define USB_INTR_VECTOR INT0_vect */ -#endif /* __usbconfig_h_included__ */ \ No newline at end of file +#endif /* __usbconfig_h_included__ */ diff --git a/spec/blink1_spec.rb b/spec/blink1_spec.rb index 1409c79..08ec1e8 100644 --- a/spec/blink1_spec.rb +++ b/spec/blink1_spec.rb @@ -2,22 +2,36 @@ describe Blink1 do - context 'native extention methods' do + describe 'native extention methods' do - it 'returns vendor_id' do - Blink1.vendor_id.should eql(10168) + describe 'vendor_id' do + subject { Blink1.vendor_id } + it { should be 10168 } end - it 'returns product_id' do - Blink1.product_id.should eql(493) + describe 'product_id' do + subject { Blink1.product_id } + it { should be 493 } end end context 'class methods', :device => true do - it 'returns list' do - Blink1.list.is_a?(Array).should be_true + describe 'list' do + subject { Blink1.list } + it { should be_a_kind_of Array } + end + + describe 'random' do + subject { + ret = nil + Blink1.open do|b1| + ret = b1.random 20 + end + ret + } + it { should be_a_kind_of Fixnum } end end