1 /*
2  * avrdude - A Downloader/Uploader for AVR device programmers
3  * Copyright (C) 2007 Dick Streefland, adapted for 5.4 by Limor Fried
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * Driver for "usbtiny"-type programmers
21  * Please see http://www.xs4all.nl/~dicks/avr/usbtiny/
22  *        and http://www.ladyada.net/make/usbtinyisp/
23  * For example schematics and detailed documentation
24  */
25 
26 #include "ac_cfg.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/time.h>
33 #include <unistd.h>
34 
35 #include "avrdude.h"
36 #include "libavrdude.h"
37 
38 #include "usbtiny.h"
39 #include "usbdevs.h"
40 
41 #if defined(HAVE_LIBUSB)      // we use LIBUSB to talk to the board
42 #if defined(HAVE_USB_H)
43 #  include <usb.h>
44 #elif defined(HAVE_LUSB0_USB_H)
45 #  include <lusb0_usb.h>
46 #else
47 #  error "libusb needs either <usb.h> or <lusb0_usb.h>"
48 #endif
49 
50 #ifndef HAVE_UINT_T
51 typedef	unsigned int	uint_t;
52 #endif
53 #ifndef HAVE_ULONG_T
54 typedef	unsigned long	ulong_t;
55 #endif
56 
57 extern int avr_write_byte_default ( PROGRAMMER* pgm, AVRPART* p,
58 				    AVRMEM* mem, ulong_t addr,
59 				    unsigned char data );
60 /*
61  * Private data for this programmer.
62  */
63 struct pdata
64 {
65   usb_dev_handle *usb_handle;
66   int sck_period;
67   int chunk_size;
68   int retries;
69 };
70 
71 #define PDATA(pgm) ((struct pdata *)(pgm->cookie))
72 
73 // ----------------------------------------------------------------------
74 
usbtiny_setup(PROGRAMMER * pgm)75 static void usbtiny_setup(PROGRAMMER * pgm)
76 {
77   if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
78     avrdude_message(MSG_INFO, "%s: usbtiny_setup(): Out of memory allocating private data\n",
79                     progname);
80     exit(1);
81   }
82   memset(pgm->cookie, 0, sizeof(struct pdata));
83 }
84 
usbtiny_teardown(PROGRAMMER * pgm)85 static void usbtiny_teardown(PROGRAMMER * pgm)
86 {
87   free(pgm->cookie);
88 }
89 
90 // Wrapper for simple usb_control_msg messages
usb_control(PROGRAMMER * pgm,unsigned int requestid,unsigned int val,unsigned int index)91 static int usb_control (PROGRAMMER * pgm,
92 			unsigned int requestid, unsigned int val, unsigned int index )
93 {
94   int nbytes;
95   nbytes = usb_control_msg( PDATA(pgm)->usb_handle,
96 			    USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
97 			    requestid,
98 			    val, index,           // 2 bytes each of data
99 			    NULL, 0,              // no data buffer in control messge
100 			    USB_TIMEOUT );        // default timeout
101   if(nbytes < 0){
102     avrdude_message(MSG_INFO, "\n%s: error: usbtiny_transmit: %s\n", progname, usb_strerror());
103     return -1;
104   }
105 
106   return nbytes;
107 }
108 
109 // Wrapper for simple usb_control_msg messages to receive data from programmer
usb_in(PROGRAMMER * pgm,unsigned int requestid,unsigned int val,unsigned int index,unsigned char * buffer,int buflen,int bitclk)110 static int usb_in (PROGRAMMER * pgm,
111 		   unsigned int requestid, unsigned int val, unsigned int index,
112 		   unsigned char* buffer, int buflen, int bitclk )
113 {
114   int nbytes;
115   int timeout;
116   int i;
117 
118   // calculate the amout of time we expect the process to take by
119   // figuring the bit-clock time and buffer size and adding to the standard USB timeout.
120   timeout = USB_TIMEOUT + (buflen * bitclk) / 1000;
121 
122   for (i = 0; i < 10; i++) {
123     nbytes = usb_control_msg( PDATA(pgm)->usb_handle,
124 			      USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
125 			      requestid,
126 			      val, index,
127 			      (char *)buffer, buflen,
128 			      timeout);
129     if (nbytes == buflen) {
130       return nbytes;
131     }
132     PDATA(pgm)->retries++;
133   }
134   avrdude_message(MSG_INFO, "\n%s: error: usbtiny_receive: %s (expected %d, got %d)\n",
135           progname, usb_strerror(), buflen, nbytes);
136   return -1;
137 }
138 
139 // Report the number of retries, and reset the counter.
check_retries(PROGRAMMER * pgm,const char * operation)140 static void check_retries (PROGRAMMER * pgm, const char* operation)
141 {
142   if (PDATA(pgm)->retries > 0 && quell_progress < 2) {
143     avrdude_message(MSG_INFO, "%s: %d retries during %s\n", progname,
144            PDATA(pgm)->retries, operation);
145   }
146   PDATA(pgm)->retries = 0;
147 }
148 
149 // Wrapper for simple usb_control_msg messages to send data to programmer
usb_out(PROGRAMMER * pgm,unsigned int requestid,unsigned int val,unsigned int index,unsigned char * buffer,int buflen,int bitclk)150 static int usb_out (PROGRAMMER * pgm,
151 		    unsigned int requestid, unsigned int val, unsigned int index,
152 		    unsigned char* buffer, int buflen, int bitclk )
153 {
154   int nbytes;
155   int timeout;
156 
157   // calculate the amout of time we expect the process to take by
158   // figuring the bit-clock time and buffer size and adding to the standard USB timeout.
159   timeout = USB_TIMEOUT + (buflen * bitclk) / 1000;
160 
161   nbytes = usb_control_msg( PDATA(pgm)->usb_handle,
162 			    USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
163 			    requestid,
164 			    val, index,
165 			    (char *)buffer, buflen,
166 			    timeout);
167   if (nbytes != buflen) {
168     avrdude_message(MSG_INFO, "\n%s: error: usbtiny_send: %s (expected %d, got %d)\n",
169 	    progname, usb_strerror(), buflen, nbytes);
170     return -1;
171   }
172 
173   return nbytes;
174 }
175 
176 // Sometimes we just need to know the SPI command for the part to perform
177 // a function. Here we wrap this request for an operation so that we
178 // can just specify the part and operation and it'll do the right stuff
179 // to get the information from AvrDude and send to the USBtiny
usbtiny_avr_op(PROGRAMMER * pgm,AVRPART * p,int op,unsigned char * res)180 static int usbtiny_avr_op (PROGRAMMER * pgm, AVRPART * p,
181 			   int op,
182 			   unsigned char *res)
183 {
184   unsigned char	cmd[4];
185 
186   if (p->op[op] == NULL) {
187     avrdude_message(MSG_INFO, "Operation %d not defined for this chip!\n", op );
188     return -1;
189   }
190   memset(cmd, 0, sizeof(cmd));
191   avr_set_bits(p->op[op], cmd);
192 
193   return pgm->cmd(pgm, cmd, res);
194 }
195 
196 // ----------------------------------------------------------------------
197 
198 /* Find a device with the correct VID/PID match for USBtiny */
199 
usbtiny_open(PROGRAMMER * pgm,char * name)200 static	int	usbtiny_open(PROGRAMMER* pgm, char* name)
201 {
202   struct usb_bus      *bus;
203   struct usb_device   *dev = 0;
204   char *bus_name = NULL;
205   char *dev_name = NULL;
206   int vid, pid;
207 
208   // if no -P was given or '-P usb' was given
209   if(strcmp(name, "usb") == 0)
210     name = NULL;
211   else {
212     // calculate bus and device names from -P option
213     const size_t usb_len = strlen("usb");
214     if(strncmp(name, "usb", usb_len) == 0 && ':' == name[usb_len]) {
215         bus_name = name + usb_len + 1;
216         dev_name = strchr(bus_name, ':');
217         if(NULL != dev_name)
218           *dev_name++ = '\0';
219     }
220   }
221 
222   usb_init();                    // initialize the libusb system
223   usb_find_busses();             // have libusb scan all the usb busses available
224   usb_find_devices();            // have libusb scan all the usb devices available
225 
226   PDATA(pgm)->usb_handle = NULL;
227 
228   if (pgm->usbvid)
229     vid = pgm->usbvid;
230   else
231     vid = USBTINY_VENDOR_DEFAULT;
232 
233   LNODEID usbpid = lfirst(pgm->usbpid);
234   if (usbpid) {
235     pid = *(int *)(ldata(usbpid));
236     if (lnext(usbpid))
237       avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
238                       progname, pid);
239   } else {
240     pid = USBTINY_PRODUCT_DEFAULT;
241   }
242 
243 
244   // now we iterate through all the busses and devices
245   for ( bus = usb_busses; bus; bus = bus->next ) {
246     for	( dev = bus->devices; dev; dev = dev->next ) {
247       if (dev->descriptor.idVendor == vid
248 	  && dev->descriptor.idProduct == pid ) {   // found match?
249     avrdude_message(MSG_NOTICE, "%s: usbdev_open(): Found USBtinyISP, bus:device: %s:%s\n",
250                       progname, bus->dirname, dev->filename);
251     // if -P was given, match device by device name and bus name
252     if(name != NULL &&
253       (NULL == dev_name ||
254        strcmp(bus->dirname, bus_name) ||
255        strcmp(dev->filename, dev_name)))
256       continue;
257 	PDATA(pgm)->usb_handle = usb_open(dev);           // attempt to connect to device
258 
259 	// wrong permissions or something?
260 	if (!PDATA(pgm)->usb_handle) {
261 	  avrdude_message(MSG_INFO, "%s: Warning: cannot open USB device: %s\n",
262 		  progname, usb_strerror());
263 	  continue;
264 	}
265       }
266     }
267   }
268 
269   if(NULL != name && NULL == dev_name) {
270     avrdude_message(MSG_INFO, "%s: Error: Invalid -P value: '%s'\n", progname, name);
271     avrdude_message(MSG_INFO, "%sUse -P usb:bus:device\n", progbuf);
272     return -1;
273   }
274   if (!PDATA(pgm)->usb_handle) {
275     avrdude_message(MSG_INFO, "%s: Error: Could not find USBtiny device (0x%x/0x%x)\n",
276 	     progname, vid, pid );
277     return -1;
278   }
279 
280   return 0;                  // If we got here, we must have found a good USB device
281 }
282 
283 /* Clean up the handle for the usbtiny */
usbtiny_close(PROGRAMMER * pgm)284 static	void usbtiny_close ( PROGRAMMER* pgm )
285 {
286   if (! PDATA(pgm)->usb_handle) {
287     return;                // not a valid handle, bail!
288   }
289   usb_close(PDATA(pgm)->usb_handle);   // ask libusb to clean up
290   PDATA(pgm)->usb_handle = NULL;
291 }
292 
293 /* A simple calculator function determines the maximum size of data we can
294    shove through a USB connection without getting errors */
usbtiny_set_chunk_size(PROGRAMMER * pgm,int period)295 static void usbtiny_set_chunk_size (PROGRAMMER * pgm, int period)
296 {
297   PDATA(pgm)->chunk_size = CHUNK_SIZE;       // start with the maximum (default)
298   while	(PDATA(pgm)->chunk_size > 8 && period > 16) {
299     // Reduce the chunk size for a slow SCK to reduce
300     // the maximum time of a single USB transfer.
301     PDATA(pgm)->chunk_size >>= 1;
302     period >>= 1;
303   }
304 }
305 
306 /* Given a SCK bit-clock speed (in useconds) we verify its an OK speed and tell the
307    USBtiny to update itself to the new frequency */
usbtiny_set_sck_period(PROGRAMMER * pgm,double v)308 static int usbtiny_set_sck_period (PROGRAMMER *pgm, double v)
309 {
310   PDATA(pgm)->sck_period = (int)(v * 1e6 + 0.5);   // convert from us to 'int', the 0.5 is for rounding up
311 
312   // Make sure its not 0, as that will confuse the usbtiny
313   if (PDATA(pgm)->sck_period < SCK_MIN)
314     PDATA(pgm)->sck_period = SCK_MIN;
315 
316   // We can't go slower, due to the byte-size of the clock variable
317   if  (PDATA(pgm)->sck_period > SCK_MAX)
318     PDATA(pgm)->sck_period = SCK_MAX;
319 
320   avrdude_message(MSG_NOTICE, "%s: Setting SCK period to %d usec\n", progname,
321 	    PDATA(pgm)->sck_period );
322 
323   // send the command to the usbtiny device.
324   // MEME: for at90's fix resetstate?
325   if (usb_control(pgm, USBTINY_POWERUP, PDATA(pgm)->sck_period, RESET_LOW) < 0)
326     return -1;
327 
328   // with the new speed, we'll have to update how much data we send per usb transfer
329   usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period);
330   return 0;
331 }
332 
333 
usbtiny_initialize(PROGRAMMER * pgm,AVRPART * p)334 static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p )
335 {
336   unsigned char res[4];        // store the response from usbtinyisp
337 
338   // Check for bit-clock and tell the usbtiny to adjust itself
339   if (pgm->bitclock > 0.0) {
340     // -B option specified: convert to valid range for sck_period
341     usbtiny_set_sck_period(pgm, pgm->bitclock);
342   } else {
343     // -B option not specified: use default
344     PDATA(pgm)->sck_period = SCK_DEFAULT;
345     avrdude_message(MSG_NOTICE, "%s: Using SCK period of %d usec\n",
346 	      progname, PDATA(pgm)->sck_period );
347     if (usb_control(pgm,  USBTINY_POWERUP,
348 		    PDATA(pgm)->sck_period, RESET_LOW ) < 0)
349       return -1;
350     usbtiny_set_chunk_size(pgm, PDATA(pgm)->sck_period);
351   }
352 
353   // Let the device wake up.
354   usleep(50000);
355 
356   // Attempt to use the underlying avrdude methods to connect (MEME: is this kosher?)
357   if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) {
358     // no response, RESET and try again
359     if (usb_control(pgm, USBTINY_POWERUP,
360 		    PDATA(pgm)->sck_period, RESET_HIGH) < 0 ||
361 	usb_control(pgm, USBTINY_POWERUP,
362 		    PDATA(pgm)->sck_period, RESET_LOW) < 0)
363       return -1;
364     usleep(50000);
365     if	( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) {
366       // give up
367       return -1;
368     }
369   }
370   return 0;
371 }
372 
373 /* Tell the USBtiny to release the output pins, etc */
usbtiny_powerdown(PROGRAMMER * pgm)374 static void usbtiny_powerdown(PROGRAMMER * pgm)
375 {
376   if (!PDATA(pgm)->usb_handle) {
377     return;                 // wasn't connected in the first place
378   }
379   usb_control(pgm, USBTINY_POWERDOWN, 0, 0);      // Send USB control command to device
380 }
381 
382 /* Send a 4-byte SPI command to the USBtinyISP for execution
383    This procedure is used by higher-level Avrdude procedures */
usbtiny_cmd(PROGRAMMER * pgm,const unsigned char * cmd,unsigned char * res)384 static int usbtiny_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char *res)
385 {
386   int nbytes;
387 
388   // Make sure its empty so we don't read previous calls if it fails
389   memset(res, '\0', 4 );
390 
391   nbytes = usb_in( pgm, USBTINY_SPI,
392 		   (cmd[1] << 8) | cmd[0],  // convert to 16-bit words
393 		   (cmd[3] << 8) | cmd[2],  //  "
394 			res, 4, 8 * PDATA(pgm)->sck_period );
395   if (nbytes < 0)
396     return -1;
397   check_retries(pgm, "SPI command");
398   // print out the data we sent and received
399   avrdude_message(MSG_NOTICE2, "CMD: [%02x %02x %02x %02x] [%02x %02x %02x %02x]\n",
400 	    cmd[0], cmd[1], cmd[2], cmd[3],
401 	    res[0], res[1], res[2], res[3] );
402   return ((nbytes == 4) &&      // should have read 4 bytes
403 	  res[2] == cmd[1]);              // AVR's do a delayed-echo thing
404 }
405 
406 /* Send the chip-erase command */
usbtiny_chip_erase(PROGRAMMER * pgm,AVRPART * p)407 static int usbtiny_chip_erase(PROGRAMMER * pgm, AVRPART * p)
408 {
409   unsigned char res[4];
410 
411   if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
412     avrdude_message(MSG_INFO, "Chip erase instruction not defined for part \"%s\"\n",
413             p->desc);
414     return -1;
415   }
416 
417   // get the command for erasing this chip and transmit to avrdude
418   if (! usbtiny_avr_op( pgm, p, AVR_OP_CHIP_ERASE, res )) {
419     return -1;
420   }
421   usleep( p->chip_erase_delay );
422 
423   // prepare for further instruction
424   pgm->initialize(pgm, p);
425 
426   return 0;
427 }
428 
429 // These are required functions but don't actually do anything
usbtiny_enable(PROGRAMMER * pgm)430 static	void	usbtiny_enable ( PROGRAMMER* pgm ) {}
431 
usbtiny_disable(PROGRAMMER * pgm)432 static void usbtiny_disable ( PROGRAMMER* pgm ) {}
433 
434 
435 /* To speed up programming and reading, we do a 'chunked' read.
436  *  We request just the data itself and the USBtiny uses the SPI function
437  *  given to read in the data. Much faster than sending a 4-byte SPI request
438  *  per byte
439 */
usbtiny_paged_load(PROGRAMMER * pgm,AVRPART * p,AVRMEM * m,unsigned int page_size,unsigned int addr,unsigned int n_bytes)440 static int usbtiny_paged_load (PROGRAMMER * pgm, AVRPART * p, AVRMEM* m,
441                                unsigned int page_size,
442                                unsigned int addr, unsigned int n_bytes)
443 {
444   unsigned int maxaddr = addr + n_bytes;
445   int chunk;
446   int function;
447 
448 
449   // First determine what we're doing
450   if (strcmp( m->desc, "flash" ) == 0) {
451     function = USBTINY_FLASH_READ;
452   } else {
453     function = USBTINY_EEPROM_READ;
454   }
455 
456   for (; addr < maxaddr; addr += chunk) {
457     chunk = PDATA(pgm)->chunk_size;         // start with the maximum chunk size possible
458 
459     // Send the chunk of data to the USBtiny with the function we want
460     // to perform
461     if (usb_in(pgm,
462 	       function,          // EEPROM or flash
463 	       0,                 // delay between SPI commands
464 	       addr,              // address in memory
465 	       m->buf + addr,     // pointer to where we store data
466 	       chunk,             // number of bytes
467 	       32 * PDATA(pgm)->sck_period)  // each byte gets turned into a 4-byte SPI cmd
468 	< 0) {
469                               // usb_in() multiplies this per byte.
470       return -1;
471     }
472   }
473 
474   check_retries(pgm, "read");
475   return n_bytes;
476 }
477 
478 /* To speed up programming and reading, we do a 'chunked' write.
479  *  We send just the data itself and the USBtiny uses the SPI function
480  *  given to write the data. Much faster than sending a 4-byte SPI request
481  *  per byte.
482 */
usbtiny_paged_write(PROGRAMMER * pgm,AVRPART * p,AVRMEM * m,unsigned int page_size,unsigned int addr,unsigned int n_bytes)483 static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
484                                unsigned int page_size,
485                                unsigned int addr, unsigned int n_bytes)
486 {
487   unsigned int maxaddr = addr + n_bytes;
488   int chunk;        // Size of data to write at once
489   int next;
490   int function;     // which SPI command to use
491   int delay;        // delay required between SPI commands
492 
493   // First determine what we're doing
494   if (strcmp( m->desc, "flash" ) == 0) {
495     function = USBTINY_FLASH_WRITE;
496   } else {
497     function = USBTINY_EEPROM_WRITE;
498   }
499 
500   delay = 0;
501   if (! m->paged) {
502     unsigned int poll_value;
503     // Does this chip not support paged writes?
504     poll_value = (m->readback[1] << 8) | m->readback[0];
505     if (usb_control(pgm, USBTINY_POLL_BYTES, poll_value, 0 ) < 0)
506       return -1;
507     delay = m->max_write_delay;
508   }
509 
510   for (; addr < maxaddr; addr += chunk) {
511     // start with the max chunk size
512     chunk = PDATA(pgm)->chunk_size;
513 
514     // we can only write a page at a time anyways
515     if (m->paged && chunk > page_size)
516       chunk = page_size;
517 
518     if (usb_out(pgm,
519 		function,       // Flash or EEPROM
520 		delay,          // How much to wait between each byte
521 		addr,           // Address in memory
522 		m->buf + addr,  // Pointer to data
523 		chunk,          // Number of bytes to write
524 		32 * PDATA(pgm)->sck_period + delay  // each byte gets turned into a
525 	                             // 4-byte SPI cmd  usb_out() multiplies
526 	                             // this per byte. Then add the cmd-delay
527 		) < 0) {
528       return -1;
529     }
530 
531     next = addr + chunk;       // Calculate what address we're at now
532     if (m->paged
533 	&& ((next % page_size) == 0 || next == maxaddr) ) {
534       // If we're at a page boundary, send the SPI command to flush it.
535       avr_write_page(pgm, p, m, (unsigned long) addr);
536     }
537   }
538   return n_bytes;
539 }
540 
usbtiny_initpgm(PROGRAMMER * pgm)541 void usbtiny_initpgm ( PROGRAMMER* pgm )
542 {
543   strcpy(pgm->type, "USBtiny");
544 
545   /* Mandatory Functions */
546   pgm->initialize	= usbtiny_initialize;
547   pgm->enable	        = usbtiny_enable;
548   pgm->disable	        = usbtiny_disable;
549   pgm->program_enable	= NULL;
550   pgm->chip_erase	= usbtiny_chip_erase;
551   pgm->cmd		= usbtiny_cmd;
552   pgm->open		= usbtiny_open;
553   pgm->close		= usbtiny_close;
554   pgm->read_byte        = avr_read_byte_default;
555   pgm->write_byte       = avr_write_byte_default;
556 
557   /* Optional Functions */
558   pgm->powerup	        = NULL;
559   pgm->powerdown	= usbtiny_powerdown;
560   pgm->paged_load	= usbtiny_paged_load;
561   pgm->paged_write	= usbtiny_paged_write;
562   pgm->set_sck_period	= usbtiny_set_sck_period;
563   pgm->setup            = usbtiny_setup;
564   pgm->teardown         = usbtiny_teardown;
565 }
566 
567 #else  /* !HAVE_LIBUSB */
568 
569 // Give a proper error if we were not compiled with libusb
570 
usbtiny_nousb_open(struct programmer_t * pgm,char * name)571 static int usbtiny_nousb_open(struct programmer_t *pgm, char * name)
572 {
573   avrdude_message(MSG_INFO, "%s: error: no usb support. Please compile again with libusb installed.\n",
574 	  progname);
575 
576   return -1;
577 }
578 
usbtiny_initpgm(PROGRAMMER * pgm)579 void usbtiny_initpgm(PROGRAMMER * pgm)
580 {
581   strcpy(pgm->type, "usbtiny");
582 
583   pgm->open = usbtiny_nousb_open;
584 }
585 
586 #endif /* HAVE_LIBUSB */
587 
588 const char usbtiny_desc[] = "Driver for \"usbtiny\"-type programmers";
589 
590