rb-blink1 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
File without changes
data/README.rdoc ADDED
@@ -0,0 +1 @@
1
+ = blink1.rb
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'rake/testtask'
2
+ require 'rake/clean'
3
+
4
+ NAME = 'blink1'
5
+
@@ -0,0 +1,552 @@
1
+ /*
2
+ * blink(1) C library --
3
+ *
4
+ *
5
+ * 2012, Tod E. Kurt, http://todbot.com/blog/ , http://thingm.com/
6
+ *
7
+ */
8
+
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+ #include <ctype.h> // for toupper()
13
+
14
+ #ifdef _WIN32
15
+ #include <windows.h>
16
+ #else
17
+ #include <unistd.h> // for usleep()
18
+ #endif
19
+
20
+ #include "blink1-lib.h"
21
+
22
+
23
+ #ifdef DEBUG_PRINTF
24
+ #define LOG(...) fprintf(stderr, __VA_ARGS__)
25
+ #else
26
+ #define LOG(...) do {} while (0)
27
+ #endif
28
+
29
+ #define blink1_report_id 1
30
+
31
+ // addresses in EEPROM
32
+ #define blink1_eeaddr_osccal 0
33
+ #define blink1_eeaddr_bootmode 1
34
+ #define blink1_eeaddr_serialnum 2
35
+ #define blink1_serialnum_len 4
36
+ #define blink1_eeaddr_patternstart (blink1_eeaddr_serialnum + blink1_serialnum_len)
37
+
38
+ #define pathmax 16
39
+ #define pathstrmax 128
40
+ #define serialmax (8 + 1)
41
+
42
+
43
+ // FIXME: use hid_device_info instead with custom sorter on serial or path
44
+ static char blink1_cached_paths[pathmax][pathstrmax];
45
+ static int blink1_cached_count = 0;
46
+ static wchar_t blink1_cached_serials[pathmax][serialmax];
47
+
48
+ static int blink1_enable_degamma = 1;
49
+
50
+ //----------------------------------------------------------------------------
51
+
52
+ //
53
+ int blink1_enumerate(void)
54
+ {
55
+ return blink1_enumerateByVidPid( blink1_vid(), blink1_pid() );
56
+ }
57
+
58
+ // get all matching devices by VID/PID pair
59
+ int blink1_enumerateByVidPid(int vid, int pid)
60
+ {
61
+ struct hid_device_info *devs, *cur_dev;
62
+
63
+ int p = 0;
64
+ devs = hid_enumerate(vid, pid);
65
+ cur_dev = devs;
66
+ while (cur_dev) {
67
+ if( (cur_dev->vendor_id != 0 && cur_dev->product_id != 0) &&
68
+ (cur_dev->vendor_id == vid && cur_dev->product_id == pid) ) {
69
+ if( cur_dev->serial_number != NULL ) { // can happen if not root
70
+ strcpy( blink1_cached_paths[p], cur_dev->path );
71
+ wcscpy( blink1_cached_serials[p], cur_dev->serial_number );
72
+ p++;
73
+ }
74
+ }
75
+ cur_dev = cur_dev->next;
76
+ }
77
+ hid_free_enumeration(devs);
78
+
79
+ blink1_cached_count = p;
80
+
81
+ blink1_sortSerials();
82
+
83
+ return p;
84
+ }
85
+
86
+ //
87
+ int blink1_getCachedCount(void)
88
+ {
89
+ return blink1_cached_count;
90
+ }
91
+
92
+ //
93
+ const char* blink1_getCachedPath(int i)
94
+ {
95
+ return blink1_cached_paths[i];
96
+ }
97
+ //
98
+ const wchar_t* blink1_getCachedSerial(int i)
99
+ {
100
+ return blink1_cached_serials[i];
101
+ }
102
+
103
+ //
104
+ hid_device* blink1_openByPath(const char* path)
105
+ {
106
+ if( path == NULL || strlen(path) == 0 ) return NULL;
107
+ hid_device* handle = hid_open_path( path );
108
+ return handle;
109
+ }
110
+
111
+ //
112
+ hid_device* blink1_openBySerial(const wchar_t* serial)
113
+ {
114
+ if( serial == NULL || wcslen(serial) == 0 ) return NULL;
115
+ int vid = blink1_vid();
116
+ int pid = blink1_pid();
117
+
118
+ LOG("opening %ls at vid/pid %x/%x\n", serial, vid,pid);
119
+ hid_device* handle = hid_open(vid,pid, serial );
120
+ return handle;
121
+ }
122
+
123
+ //
124
+ hid_device* blink1_openById( int i )
125
+ {
126
+ //return blink1_openByPath( blink1_getCachedPath(i) );
127
+ return blink1_openBySerial( blink1_getCachedSerial(i) );
128
+ }
129
+
130
+ //
131
+ hid_device* blink1_open(void)
132
+ {
133
+ int vid = blink1_vid();
134
+ int pid = blink1_pid();
135
+
136
+ hid_device* handle = hid_open(vid,pid, NULL); // FIXME?
137
+
138
+ return handle;
139
+ }
140
+
141
+ //
142
+ // FIXME: search through blink1s list to zot it too?
143
+ void blink1_close( hid_device* dev )
144
+ {
145
+ if( dev != NULL )
146
+ hid_close(dev);
147
+ dev = NULL;
148
+ hid_exit(); // FIXME: this cleans up libusb in a way that hid_close doesn't
149
+ }
150
+
151
+ //
152
+ int blink1_write( hid_device* dev, void* buf, int len)
153
+ {
154
+ if( dev==NULL ) {
155
+ return -1; // BLINK1_ERR_NOTOPEN;
156
+ }
157
+ int rc = hid_send_feature_report( dev, buf, len );
158
+ return rc;
159
+ }
160
+
161
+ // len should contain length of buf
162
+ // after call, len will contain actual len of buf read
163
+ int blink1_read( hid_device* dev, void* buf, int len)
164
+ {
165
+ if( dev==NULL ) {
166
+ return -1; // BLINK1_ERR_NOTOPEN;
167
+ }
168
+ int rc = hid_send_feature_report(dev, buf, len); // FIXME: check rc
169
+
170
+ if( (rc = hid_get_feature_report(dev, buf, len) == -1) ) {
171
+ LOG("error reading data: %s\n",blink1_error_msg(rc));
172
+ }
173
+ return rc;
174
+ }
175
+
176
+
177
+ // -------------------------------------------------------------------------
178
+ // everything below here doesn't need to know about USB details
179
+ // except for a "hid_device*"
180
+ // -------------------------------------------------------------------------
181
+
182
+ #include <unistd.h>
183
+
184
+ //
185
+ int blink1_getSerialNumber(hid_device *dev, char* buf)
186
+ {
187
+ if( dev == NULL ) return -1;
188
+ /*
189
+ wchar_t* wbuf = dev->serial_number;
190
+ int i=0;
191
+ while( wbuf ) {
192
+ buf[i++] = *wbuf;
193
+ }
194
+ return i;
195
+ */
196
+ return -1;
197
+ }
198
+
199
+ //
200
+ int blink1_getVersion(hid_device *dev)
201
+ {
202
+ char buf[9] = {blink1_report_id, 'v' };
203
+ int len = sizeof(buf);
204
+
205
+ //hid_set_nonblocking(dev, 0);
206
+ int rc = blink1_write(dev, buf, sizeof(buf));
207
+ blink1_sleep( 50 ); //FIXME:
208
+ if( rc != -1 ) // no error
209
+ rc = blink1_read(dev, buf, len);
210
+ if( rc != -1 ) // also no error
211
+ rc = ((buf[3]-'0') * 100) + (buf[4]-'0');
212
+ // rc is now version number or error
213
+ // FIXME: we don't know vals of errcodes
214
+ return rc;
215
+ }
216
+
217
+ //
218
+ int blink1_eeread(hid_device *dev, uint16_t addr, uint8_t* val)
219
+ {
220
+ char buf[9] = {blink1_report_id, 'e', addr };
221
+ int len = sizeof(buf);
222
+
223
+ int rc = blink1_write(dev, buf, len );
224
+ blink1_sleep( 50 ); // FIXME:
225
+ if( rc != -1 ) // no error
226
+ rc = blink1_read(dev, buf, len );
227
+ if( rc != -1 )
228
+ *val = buf[3];
229
+ return rc;
230
+ }
231
+
232
+ //
233
+ int blink1_eewrite(hid_device *dev, uint16_t addr, uint8_t val)
234
+ {
235
+ char buf[9] = {blink1_report_id, 'E', addr, val };
236
+
237
+ int rc = blink1_write(dev, buf, sizeof(buf) );
238
+
239
+ return rc;
240
+ }
241
+
242
+ // FIXME: this doesn't work
243
+ int blink1_serialnumread(hid_device *dev, uint8_t** serialnum)
244
+ {
245
+ int rc = 0;
246
+ for( int i=0; i<blink1_serialnum_len; i++ ) { // serial num is 8 chars long
247
+ //blink1_eeread( dev, blink1_eeaddr_serialnum+i, (serialnum+i) );
248
+ }
249
+ return rc;
250
+ }
251
+
252
+ //
253
+ static uint8_t parseHex(char c)
254
+ {
255
+ c = toupper(c);
256
+ if (c >= '0' && c <= '9') return (c - '0');
257
+ if (c >= 'A' && c <= 'F') return (c - 'A')+10;
258
+ return 0;
259
+ }
260
+
261
+ // serialnum comes in as an ascii set of 8 characters representing
262
+ // 4-bytes
263
+ int blink1_serialnumwrite(hid_device *dev, uint8_t* serialnumstr)
264
+ {
265
+ uint8_t serialnum[4];
266
+ serialnum[0] = parseHex( serialnumstr[0] )*16 + parseHex( serialnumstr[1] );
267
+ serialnum[1] = parseHex( serialnumstr[2] )*16 + parseHex( serialnumstr[3] );
268
+ serialnum[2] = parseHex( serialnumstr[4] )*16 + parseHex( serialnumstr[5] );
269
+ serialnum[3] = parseHex( serialnumstr[6] )*16 + parseHex( serialnumstr[7] );
270
+
271
+ int rc = 0;
272
+ for( int i=0; i<blink1_serialnum_len; i++ ) { // serialnum is 4 chars long
273
+ blink1_sleep(50); //FIXME:
274
+ uint8_t v = serialnum[i];
275
+ int rc = blink1_eewrite( dev, blink1_eeaddr_serialnum+i, v);
276
+ if( rc == -1 ) { // try again
277
+ LOG("blink1_serialwrite: oops, trying again on char %d\n",i);
278
+ rc = blink1_eewrite(dev,blink1_eeaddr_serialnum+i, v);
279
+ if( rc == -1 ) {
280
+ LOG("blink1_serialwrite: error on try again\n");
281
+ break;
282
+ }
283
+ }
284
+
285
+ }
286
+ return rc;
287
+ }
288
+
289
+
290
+ //
291
+ int blink1_fadeToRGB(hid_device *dev, uint16_t fadeMillis,
292
+ uint8_t r, uint8_t g, uint8_t b)
293
+ {
294
+ int dms = fadeMillis/10; // millis_divided_by_10
295
+
296
+ char buf[9];
297
+
298
+ buf[0] = blink1_report_id; // report id
299
+ buf[1] = 'c'; // command code for 'fade to rgb'
300
+ buf[2] = ((blink1_enable_degamma) ? blink1_degamma(r) : r );
301
+ buf[3] = ((blink1_enable_degamma) ? blink1_degamma(g) : g );
302
+ buf[4] = ((blink1_enable_degamma) ? blink1_degamma(b) : b );
303
+ buf[5] = (dms >> 8);
304
+ buf[6] = dms % 0xff;
305
+
306
+ int rc = blink1_write(dev, buf, sizeof(buf) );
307
+
308
+ return rc;
309
+ }
310
+
311
+ //
312
+ int blink1_setRGB(hid_device *dev, uint8_t r, uint8_t g, uint8_t b )
313
+ {
314
+ char buf[9];
315
+
316
+ buf[0] = blink1_report_id; // report id
317
+ buf[1] = 'n'; // command code for "set rgb now"
318
+ buf[2] = ((blink1_enable_degamma) ? blink1_degamma(r) : r ); // red
319
+ buf[3] = ((blink1_enable_degamma) ? blink1_degamma(g) : g ); // grn
320
+ buf[4] = ((blink1_enable_degamma) ? blink1_degamma(b) : b ); // blu
321
+
322
+ int rc = blink1_write(dev, buf, sizeof(buf) );
323
+
324
+ return rc;
325
+ }
326
+
327
+
328
+ //
329
+ int blink1_serverdown(hid_device *dev, uint8_t on, uint16_t millis)
330
+ {
331
+ int dms = millis/10; // millis_divided_by_10
332
+
333
+ char buf[9] = {blink1_report_id, 'D', on, (dms>>8), (dms % 0xff) };
334
+
335
+ int rc = blink1_write(dev, buf, sizeof(buf) );
336
+ return rc;
337
+ }
338
+
339
+ //
340
+ int blink1_play(hid_device *dev, uint8_t play, uint8_t pos)
341
+ {
342
+ char buf[9] = {blink1_report_id, 'p', play, pos };
343
+ int rc = blink1_write(dev, buf, sizeof(buf) );
344
+ return rc;
345
+ }
346
+
347
+ //
348
+ int blink1_writePatternLine(hid_device *dev, uint16_t fadeMillis,
349
+ uint8_t r, uint8_t g, uint8_t b,
350
+ uint8_t pos)
351
+ {
352
+ int dms = fadeMillis/10; // millis_divided_by_10
353
+ r = (blink1_enable_degamma) ? blink1_degamma(r) : r ;
354
+ g = (blink1_enable_degamma) ? blink1_degamma(g) : g ;
355
+ b = (blink1_enable_degamma) ? blink1_degamma(b) : b ;
356
+ char buf[9] = {blink1_report_id, 'P', r,g,b, (dms>>8), (dms % 0xff), pos };
357
+ int rc = blink1_write(dev, buf, sizeof(buf) );
358
+ return rc;
359
+ }
360
+
361
+ //
362
+ int blink1_readPatternLine(hid_device *dev, uint16_t* fadeMillis,
363
+ uint8_t* r, uint8_t* g, uint8_t* b,
364
+ uint8_t pos)
365
+ {
366
+ char buf[9] = {blink1_report_id, 'R', 0,0,0, 0,0, pos };
367
+ int rc = blink1_write(dev, buf, sizeof(buf) );
368
+ blink1_sleep( 50 ); // FIXME:
369
+ if( rc != -1 ) // no error
370
+ rc = blink1_read(dev, buf, sizeof(buf) );
371
+ if( rc != -1 ) {
372
+ *r = buf[2];
373
+ *g = buf[3];
374
+ *b = buf[4];
375
+ *fadeMillis = ((buf[5]<<8) + (buf[6] &0xff)) * 10;
376
+ }
377
+ return rc;
378
+ }
379
+
380
+
381
+ // FIXME:
382
+ int readUUID( hid_device* dev, uint8_t** uuid )
383
+ {
384
+ return -1;
385
+ }
386
+ // FIXME:
387
+ int setUUID( hid_device* dev, uint8_t* uuid )
388
+ {
389
+ return -1;
390
+ }
391
+
392
+
393
+ /* ------------------------------------------------------------------------- */
394
+
395
+ // FIXME: this is wrong
396
+ // FIXME: provide function that generated this
397
+ uint8_t degamma_lookup[256] = {
398
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
399
+ 1,1,1,1,1,1,2,2,2,2,2,3,3,3,3,4,
400
+ 4,4,4,5,5,5,5,6,6,6,7,7,7,8,8,9,
401
+ 9,9,10,10,11,11,11,12,12,13,13,14,14,15,15,16,
402
+ 16,17,17,18,18,19,19,20,20,21,22,22,23,23,24,25,
403
+ 25,26,27,27,28,29,29,30,31,31,32,33,33,34,35,36,
404
+ 36,37,38,39,40,40,41,42,43,44,44,45,46,47,48,49,
405
+ 50,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
406
+ 65,66,67,68,69,70,71,72,73,74,75,76,77,79,80,81,
407
+ 82,83,84,85,87,88,89,90,91,93,94,95,96,97,99,100,
408
+ 101,102,104,105,106,108,109,110,112,113,114,116,117,118,120,121,
409
+ 122,124,125,127,128,129,131,132,134,135,137,138,140,141,143,144,
410
+ 146,147,149,150,152,153,155,156,158,160,161,163,164,166,168,169,
411
+ 171,172,174,176,177,179,181,182,184,186,188,189,191,193,195,196,
412
+ 198,200,202,203,205,207,209,211,212,214,216,218,220,222,224,225,
413
+ 227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,255,
414
+ };
415
+
416
+ void blink1_enableDegamma()
417
+ {
418
+ blink1_enable_degamma = 1;
419
+ }
420
+ void blink1_disableDegamma()
421
+ {
422
+ blink1_enable_degamma = 0;
423
+ }
424
+
425
+ // a simple logarithmic -> linear mapping as a sort of gamma correction
426
+ // maps from 0-255 to 0-255
427
+ static int blink1_degamma_log2lin( int n )
428
+ {
429
+ //return (int)(1.0* (n * 0.707 )); // 1/sqrt(2)
430
+ return (((1<<(n/32))-1) + ((1<<(n/32))*((n%32)+1)+15)/32);
431
+ }
432
+
433
+ //
434
+ int blink1_degamma( int n )
435
+ {
436
+ //return degamma_lookup[n];
437
+ return blink1_degamma_log2lin(n);
438
+ }
439
+
440
+
441
+ // qsort C-string comparison function
442
+ int cmp_path(const void *a, const void *b)
443
+ {
444
+ return strncmp( (const char *)a, (const char *)b, pathstrmax);
445
+ }
446
+ // qsort wchar_t string comparison function
447
+ int cmp_serial(const void *a, const void *b)
448
+ {
449
+ return wcsncmp( (const wchar_t *)a, (const wchar_t *)b, serialmax);
450
+ }
451
+
452
+ //
453
+ void blink1_sortPaths(void)
454
+ {
455
+ size_t elemsize = sizeof( blink1_cached_paths[0] ); // 128
456
+ //size_t count = sizeof(blink1_cached_paths) / elemsize; // 16
457
+
458
+ return qsort( blink1_cached_paths, blink1_cached_count,elemsize,cmp_path);
459
+ }
460
+
461
+ //
462
+ void blink1_sortSerials(void)
463
+ {
464
+ size_t elemsize = sizeof( blink1_cached_serials[0] ); //
465
+ //size_t count = sizeof(blink1_cached_serials) / elemsize; //
466
+
467
+ qsort( blink1_cached_serials,
468
+ blink1_cached_count,
469
+ elemsize,
470
+ cmp_serial);
471
+ }
472
+
473
+ //
474
+ int blink1_vid(void)
475
+ {
476
+ uint8_t rawVid[2] = {USB_CFG_VENDOR_ID};
477
+ int vid = rawVid[0] + 256 * rawVid[1];
478
+ return vid;
479
+ }
480
+ //
481
+ int blink1_pid(void)
482
+ {
483
+ uint8_t rawPid[2] = {USB_CFG_DEVICE_ID};
484
+ int pid = rawPid[0] + 256 * rawPid[1];
485
+ return pid;
486
+ }
487
+
488
+ // simple cross-platform millis sleep func
489
+ void blink1_sleep(uint16_t millis)
490
+ {
491
+ #ifdef WIN32
492
+ Sleep(millis);
493
+ #else
494
+ usleep( millis * 1000);
495
+ #endif
496
+ }
497
+
498
+ //
499
+ char *blink1_error_msg(int errCode)
500
+ {
501
+ /*
502
+ static char buf[80];
503
+
504
+ switch(errCode){
505
+ case USBOPEN_ERR_ACCESS: return "Access to device denied";
506
+ case USBOPEN_ERR_NOTFOUND: return "The specified device was not found";
507
+ case USBOPEN_ERR_IO: return "Communication error with device";
508
+ default:
509
+ sprintf(buf, "Unknown USB error %d", errCode);
510
+ return buf;
511
+ }
512
+ */
513
+ return NULL; /* not reached */
514
+ }
515
+
516
+
517
+ /*
518
+
519
+ //
520
+ int blink1_nightlight(hid_device *dev, uint8_t on)
521
+ {
522
+ char buf[9] = { blink1_report_id, 'N', on };
523
+
524
+ int rc = blink1_write(dev, buf, sizeof(buf) );
525
+
526
+ return rc;
527
+ }
528
+
529
+
530
+ //
531
+ int blink1_command(hid_device* dev, int num_send, int num_recv,
532
+ uint8_t* buf_send, uint8_t* buf_recv )
533
+ {
534
+ if( dev==NULL ) {
535
+ return -1; // BLINK1_ERR_NOTOPEN;
536
+ }
537
+ int err = 0;
538
+ if( (err = usbhidSetReport(dev, (char*)buf_send, num_send)) != 0) {
539
+ fprintf(stderr,"error writing data: %s\n",blink1_error_msg(err));
540
+ return err;
541
+ }
542
+
543
+ if( num_recv > 0 ) {
544
+ int len = num_recv;
545
+ if((err = usbhidGetReport(dev, 0, (char*)buf_recv, &len)) != 0) {
546
+ fprintf(stderr,"error reading data: %s\n",blink1_error_msg(err));
547
+ } else { // it was good
548
+ }
549
+ }
550
+ return err;
551
+ }
552
+ */
@@ -0,0 +1,83 @@
1
+ /*
2
+ * blink(1) C library --
3
+ *
4
+ * 2012, Tod E. Kurt, http://todbot.com/blog/ , http://thingm.com/
5
+ *
6
+ */
7
+
8
+
9
+ #ifndef __BLINK1_LIB_H__
10
+ #define __BLINK1_LIB_H__
11
+
12
+ #include <stdint.h>
13
+
14
+ #include "hidapi.h"
15
+ #include "usbconfig.h" // from firmware, for VID,PID,vendor name & product name
16
+
17
+ #ifdef __cplusplus
18
+ extern "C" {
19
+ #endif
20
+
21
+ #define blink1_max_devices 16
22
+
23
+
24
+ int blink1_vid(void);
25
+ int blink1_pid(void);
26
+ void blink1_sortPaths(void);
27
+ void blink1_sortSerials(void);
28
+
29
+ int blink1_enumerate();
30
+ int blink1_enumerateByVidPid(int vid, int pid);
31
+ const char* blink1_getCachedPath(int i);
32
+ const wchar_t* blink1_getCachedSerial(int i);
33
+ int blink1_getCachedCount(void);
34
+
35
+ hid_device* blink1_open(void);
36
+ hid_device* blink1_openByPath(const char* path);
37
+ hid_device* blink1_openBySerial(const wchar_t* serial);
38
+ hid_device* blink1_openById( int i );
39
+
40
+ void blink1_close( hid_device* dev );
41
+
42
+ int blink1_write( hid_device* dev, void* buf, int len);
43
+ int blink1_read( hid_device* dev, void* buf, int len);
44
+
45
+ int blink1_getSerialNumber(hid_device *dev, char* buf);
46
+ int blink1_getVersion(hid_device *dev);
47
+
48
+ int blink1_fadeToRGB(hid_device *dev, uint16_t fadeMillis,
49
+ uint8_t r, uint8_t g, uint8_t b );
50
+
51
+ int blink1_setRGB(hid_device *dev, uint8_t r, uint8_t g, uint8_t b );
52
+
53
+ int blink1_eeread(hid_device *dev, uint16_t addr, uint8_t* val);
54
+ int blink1_eewrite(hid_device *dev, uint16_t addr, uint8_t val);
55
+
56
+ int blink1_serialnumread(hid_device *dev, uint8_t** serialnumstr);
57
+ int blink1_serialnumwrite(hid_device *dev, uint8_t* serialnumstr);
58
+
59
+ //int blink1_nightlight(hid_device *dev, uint8_t on);
60
+ int blink1_serverdown(hid_device *dev, uint8_t on, uint16_t millis);
61
+
62
+ int blink1_play(hid_device *dev, uint8_t play, uint8_t pos);
63
+ int blink1_writePatternLine(hid_device *dev, uint16_t fadeMillis,
64
+ uint8_t r, uint8_t g, uint8_t b,
65
+ uint8_t pos);
66
+ int blink1_readPatternLine(hid_device *dev, uint16_t* fadeMillis,
67
+ uint8_t* r, uint8_t* g, uint8_t* b,
68
+ uint8_t pos);
69
+ //int blink1_playPattern(hid_device *dev,,);
70
+
71
+ char *blink1_error_msg(int errCode);
72
+
73
+ void blink1_enableDegamma();
74
+ void blink1_disableDegamma();
75
+ int blink1_degamma(int n);
76
+
77
+ void blink1_sleep(uint16_t delayMillis);
78
+
79
+ #ifdef __cplusplus
80
+ }
81
+ #endif
82
+
83
+ #endif