libftdi, ftdi_eeprom: (tomj) changed all email addresses to opensource@intra2net.com
[libftdi] / ftdi / ftdi.c
1 /***************************************************************************
2                           ftdi.c  -  description
3                              -------------------
4     begin                : Fri Apr 4 2003
5     copyright            : (C) 2003 by Intra2net AG
6     email                : opensource@intra2net.com
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU Lesser General Public License           *
13  *   version 2.1 as published by the Free Software Foundation;             *
14  *                                                                         *
15  ***************************************************************************/
16
17 #include <usb.h>
18  
19 #include "ftdi.h"
20
21 int ftdi_init(struct ftdi_context *ftdi) {
22     ftdi->usb_dev = NULL;
23     ftdi->usb_timeout = 5000;
24
25     ftdi->baudrate = -1;
26     ftdi->bitbang_enabled = 0;
27
28     ftdi->error_str = NULL;
29
30     return 0;
31 }
32
33
34 void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usb) {
35     ftdi->usb_dev = usb;
36 }
37
38
39 /* ftdi_usb_open return codes:
40    0: all fine
41   -1: usb_find_busses() failed
42   -2: usb_find_devices() failed
43   -3: usb device not found
44   -4: unable to open device
45   -5: unable to claim device
46   -6: reset failed
47   -7: set baudrate failed
48 */
49 int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product) {
50     struct usb_bus *bus;
51     struct usb_device *dev;
52
53     usb_init();
54
55     if (usb_find_busses() < 0) {
56         ftdi->error_str = "usb_find_busses() failed";
57         return -1;
58     }
59
60     if (usb_find_devices() < 0) {
61         ftdi->error_str = "usb_find_devices() failed";
62         return -2;
63     }
64
65     for (bus = usb_busses; bus; bus = bus->next) {
66         for (dev = bus->devices; dev; dev = dev->next) {
67             if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
68                 ftdi->usb_dev = usb_open(dev);
69                 if (ftdi->usb_dev) {
70                     if (usb_claim_interface(ftdi->usb_dev, 0) != 0) {
71                         ftdi->error_str = "unable to claim usb device. You can still use it though...";
72                         return -5;
73                     }
74
75                     if (ftdi_usb_reset (ftdi) != 0)
76                        return -6;
77
78                     if (ftdi_set_baudrate (ftdi, 9600) != 0)
79                        return -7;
80
81                     return 0;
82                 } else {
83                     ftdi->error_str = "usb_open() failed";
84                     return -4;
85                 }
86             }
87         }
88
89     }
90
91     // device not found
92     return -3;
93 }
94
95
96 int ftdi_usb_reset(struct ftdi_context *ftdi) {
97     if (usb_control_msg(ftdi->usb_dev, 0x40, 0, 0, 0, NULL, 0, ftdi->usb_timeout) != 0) {
98         ftdi->error_str = "FTDI reset failed";
99         return -1;
100     }
101
102     return 0;
103 }
104
105 int ftdi_usb_purge_buffers(struct ftdi_context *ftdi) {
106     if (usb_control_msg(ftdi->usb_dev, 0x40, 0, 1, 0, NULL, 0, ftdi->usb_timeout) != 0) {
107         ftdi->error_str = "FTDI purge of RX buffer failed";
108         return -1;
109     }
110
111     if (usb_control_msg(ftdi->usb_dev, 0x40, 0, 2, 0, NULL, 0, ftdi->usb_timeout) != 0) {
112         ftdi->error_str = "FTDI purge of TX buffer failed";
113         return -1;
114     }
115
116     return 0;
117 }
118
119 /* ftdi_usb_close return codes
120     0: all fine
121    -1: usb_release failed
122    -2: usb_close failed
123 */
124 int ftdi_usb_close(struct ftdi_context *ftdi) {
125     int rtn = 0;
126
127     if (usb_release_interface(ftdi->usb_dev, 0) != 0)
128         rtn = -1;
129
130     if (usb_close (ftdi->usb_dev) != 0)
131         rtn = -2;
132
133     return rtn;
134 }
135
136
137 /*
138     ftdi_set_baudrate return codes:
139      0: all fine
140     -1: invalid baudrate
141     -2: setting baudrate failed
142 */
143 int ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate) {
144     unsigned short ftdi_baudrate;
145
146     if (ftdi->bitbang_enabled) {
147         baudrate = baudrate*4;
148     }
149
150     switch (baudrate) {
151     case 300:
152         ftdi_baudrate = 0x2710;
153         break;
154     case 600:
155         ftdi_baudrate = 0x1388;
156         break;
157     case 1200:
158         ftdi_baudrate = 0x09C4;
159         break;
160     case 2400:
161         ftdi_baudrate = 0x04E2;
162         break;
163     case 4800:
164         ftdi_baudrate = 0x0271;
165         break;
166     case 9600:
167         ftdi_baudrate = 0x4138;
168         break;
169     case 19200:
170         ftdi_baudrate = 0x809C;
171         break;
172     case 38400:
173         ftdi_baudrate = 0xC04E;
174         break;
175     case 57600:
176         ftdi_baudrate = 0x0034;
177         break;
178     case 115200:
179         ftdi_baudrate = 0x001A;
180         break;
181     case 230400:
182         ftdi_baudrate = 0x000D;
183         break;
184     case 460800:
185         ftdi_baudrate = 0x4006;
186         break;
187     case 921600:
188         ftdi_baudrate = 0x8003;
189         break;
190     default:
191         ftdi->error_str = "Unknown baudrate. Note: bitbang baudrates are automatically multiplied by 4";
192         return -1;
193     }
194
195     if (usb_control_msg(ftdi->usb_dev, 0x40, 3, ftdi_baudrate, 0, NULL, 0, ftdi->usb_timeout) != 0) {
196         ftdi->error_str = "Setting new baudrate failed";
197         return -2;
198     }
199
200     ftdi->baudrate = baudrate;
201     return 0;
202 }
203
204
205 int ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
206     int ret;
207     int offset = 0;
208     while (offset < size) {
209         int write_size = 64;
210
211         if (offset+write_size > size)
212             write_size = size-offset;
213
214         ret=usb_bulk_write(ftdi->usb_dev, 2, buf+offset, write_size, ftdi->usb_timeout);
215         if (ret == -1) {
216             ftdi->error_str = "bulk write failed";
217             return -1;
218         }
219
220         offset += write_size;
221     }
222
223     return 0;
224 }
225
226
227 int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
228     static unsigned char readbuf[64];
229     int ret = 1;
230     int offset = 0;
231
232     if (size != 0 && size % 64 != 0) {
233             ftdi->error_str = "Sorry, read buffer size must currently be a multiple (1x, 2x, 3x...) of 64";
234             return -2;
235     }
236
237     while (offset < size && ret > 0) {
238         ret = usb_bulk_read (ftdi->usb_dev, 0x81, readbuf, 64, ftdi->usb_timeout);
239         // Skip FTDI status bytes
240         if (ret >= 2)
241             ret-=2;
242         
243         if (ret > 0) {
244             memcpy (buf+offset, readbuf+2, ret);
245         }
246
247         if (ret == -1) {
248             ftdi->error_str = "bulk read failed";
249             return -1;
250         }
251
252         offset += ret;
253     }
254
255     return offset;
256 }
257
258
259 int ftdi_enable_bitbang(struct ftdi_context *ftdi, unsigned char bitmask) {
260     unsigned short usb_val;
261
262     usb_val = bitmask;  // low byte: bitmask
263     usb_val += 1 << 8;  // high byte: enable flag
264     if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, usb_val, 0, NULL, 0, ftdi->usb_timeout) != 0) {
265         ftdi->error_str = "Unable to enter bitbang mode. Perhaps not a BM type chip?";
266         return -1;
267     }
268
269     ftdi->bitbang_enabled = 1;
270     return 0;
271 }
272
273
274 int ftdi_disable_bitbang(struct ftdi_context *ftdi) {
275     if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, 0, 0, NULL, 0, ftdi->usb_timeout) != 0) {
276         ftdi->error_str = "Unable to leave bitbang mode. Perhaps not a BM type chip?";
277         return -1;
278     }
279
280     ftdi->bitbang_enabled = 0;
281     return 0;
282 }
283
284
285 int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins) {
286     unsigned short usb_val;
287     if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x0C, 0, 0, (char *)&usb_val, 1, ftdi->usb_timeout) != 1) {
288         ftdi->error_str = "Read pins failed";
289         return -1;
290     }
291
292     *pins = (unsigned char)usb_val;
293     return 0;
294 }
295
296
297 int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) {
298     unsigned short usb_val;
299
300     if (latency < 1) {
301        ftdi->error_str = "Latency out of range. Only valid for 1-255";
302        return -1;
303     }
304
305     usb_val = latency;
306     if (usb_control_msg(ftdi->usb_dev, 0x40, 0x09, usb_val, 0, NULL, 0, ftdi->usb_timeout) != 0) {
307        ftdi->error_str = "Unable to set latency timer";
308        return -2;
309     }
310     return 0;
311 }
312
313
314 int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency) {
315     unsigned short usb_val;
316     if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x0A, 0, 0, (char *)&usb_val, 1, ftdi->usb_timeout) != 1) {
317         ftdi->error_str = "Reading latency timer failed";
318         return -1;
319     }
320
321     *latency = (unsigned char)usb_val;
322     return 0;
323 }
324
325
326 void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) {
327     eeprom->vendor_id = 0403;
328     eeprom->product_id = 6001;
329     
330     eeprom->self_powered = 1;
331     eeprom->remote_wakeup = 1;
332     eeprom->BM_type_chip = 1;
333     
334     eeprom->in_is_isochronous = 0;
335     eeprom->out_is_isochronous = 0;
336     eeprom->suspend_pull_downs = 0;
337     
338     eeprom->use_serial = 0;
339     eeprom->change_usb_version = 0;
340     eeprom->usb_version = 200;
341     eeprom->max_power = 0;
342     
343     eeprom->manufacturer = NULL;
344     eeprom->product = NULL;
345     eeprom->serial = NULL;
346 }
347
348
349 /*
350     ftdi_eeprom_build return codes:
351     positive value: used eeprom size
352     -1: eeprom size (128 bytes) exceeded by custom strings
353 */
354 int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) {
355     unsigned char i, j;
356     unsigned short checksum, value;
357     unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
358     int size_check;
359
360     if (eeprom->manufacturer != NULL)
361         manufacturer_size = strlen(eeprom->manufacturer);
362     if (eeprom->product != NULL)
363         product_size = strlen(eeprom->product);
364     if (eeprom->serial != NULL)
365         serial_size = strlen(eeprom->serial);
366
367     size_check = 128;   // eeprom is 128 bytes
368     size_check -= 28;   // 28 are always in use (fixed)
369     size_check -= manufacturer_size*2;
370     size_check -= product_size*2;
371     size_check -= serial_size*2;
372
373     // eeprom size exceeded?
374     if (size_check < 0)
375         return (-1);
376
377     // empty eeprom
378     memset (output, 0, 128);
379
380     // Addr 00: Stay 00 00
381     // Addr 02: Vendor ID
382     output[0x02] = eeprom->vendor_id;
383     output[0x03] = eeprom->vendor_id >> 8;
384
385     // Addr 04: Product ID
386     output[0x04] = eeprom->product_id;
387     output[0x05] = eeprom->product_id >> 8;
388
389     // Addr 06: Device release number (0400h for BM features)
390     output[0x06] = 0x00;
391     
392     if (eeprom->BM_type_chip == 1)
393         output[0x07] = 0x04;
394     else
395         output[0x07] = 0x02;
396
397     // Addr 08: Config descriptor
398     // Bit 1: remote wakeup if 1
399     // Bit 0: self powered if 1
400     //
401     j = 0;
402     if (eeprom->self_powered == 1)
403         j = j | 1;
404     if (eeprom->remote_wakeup == 1)
405         j = j | 2;
406     output[0x08] = j;
407
408     // Addr 09: Max power consumption: max power = value * 2 mA
409     output[0x09] = eeprom->max_power;;
410     
411     // Addr 0A: Chip configuration
412     // Bit 7: 0 - reserved
413     // Bit 6: 0 - reserved
414     // Bit 5: 0 - reserved
415     // Bit 4: 1 - Change USB version
416     // Bit 3: 1 - Use the serial number string
417     // Bit 2: 1 - Enable suspend pull downs for lower power
418     // Bit 1: 1 - Out EndPoint is Isochronous
419     // Bit 0: 1 - In EndPoint is Isochronous
420     //
421     j = 0;
422     if (eeprom->in_is_isochronous == 1)
423         j = j | 1;
424     if (eeprom->out_is_isochronous == 1)
425         j = j | 2;
426     if (eeprom->suspend_pull_downs == 1)
427         j = j | 4;
428     if (eeprom->use_serial == 1)
429         j = j | 8;
430     if (eeprom->change_usb_version == 1)
431         j = j | 16;
432     output[0x0A] = j;
433     
434     // Addr 0B: reserved
435     output[0x0B] = 0x00;
436     
437     // Addr 0C: USB version low byte when 0x0A bit 4 is set
438     // Addr 0D: USB version high byte when 0x0A bit 4 is set
439     if (eeprom->change_usb_version == 1) {
440         output[0x0C] = eeprom->usb_version;
441         output[0x0D] = eeprom->usb_version >> 8;
442     }
443
444
445     // Addr 0E: Offset of the manufacturer string + 0x80
446     output[0x0E] = 0x14 + 0x80;
447
448     // Addr 0F: Length of manufacturer string
449     output[0x0F] = manufacturer_size*2 + 2;
450
451     // Addr 10: Offset of the product string + 0x80, calculated later
452     // Addr 11: Length of product string
453     output[0x11] = product_size*2 + 2;
454
455     // Addr 12: Offset of the serial string + 0x80, calculated later
456     // Addr 13: Length of serial string
457     output[0x13] = serial_size*2 + 2;
458
459     // Dynamic content
460     output[0x14] = manufacturer_size*2 + 2;
461     output[0x15] = 0x03;        // type: string
462     
463     i = 0x16, j = 0;
464     
465     // Output manufacturer
466     for (j = 0; j < manufacturer_size; j++) {
467         output[i] = eeprom->manufacturer[j], i++;
468         output[i] = 0x00, i++;
469     }
470
471     // Output product name
472     output[0x10] = i + 0x80;    // calculate offset
473     output[i] = product_size*2 + 2, i++;
474     output[i] = 0x03, i++;
475     for (j = 0; j < product_size; j++) {
476         output[i] = eeprom->product[j], i++;
477         output[i] = 0x00, i++;
478     }
479     
480     // Output serial
481     output[0x12] = i + 0x80;    // calculate offset
482     output[i] = serial_size*2 + 2, i++;
483     output[i] = 0x03, i++;
484     for (j = 0; j < serial_size; j++) {
485         output[i] = eeprom->serial[j], i++;
486         output[i] = 0x00, i++;
487     }
488
489     // calculate checksum
490     checksum = 0xAAAA;
491     
492     for (i = 0; i < 63; i++) {
493         value = output[i*2];
494         value += output[(i*2)+1] << 8;
495
496         checksum = value^checksum;
497         checksum = (checksum << 1) | (checksum >> 15);  
498     }
499
500     output[0x7E] = checksum;
501     output[0x7F] = checksum >> 8;    
502
503     return size_check;
504 }
505
506
507 int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) {
508     int i;
509
510     for (i = 0; i < 64; i++) {
511         if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x90, 0, i, eeprom+(i*2), 2, ftdi->usb_timeout) != 2) {
512            ftdi->error_str = "Reading eeprom failed";
513            return -1;
514         }
515     }
516
517     return 0;
518 }
519
520
521 int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) {
522     unsigned short usb_val;
523     int i;
524
525     for (i = 0; i < 64; i++) {
526        usb_val = eeprom[i*2];
527        usb_val += eeprom[(i*2)+1] << 8;
528        if (usb_control_msg(ftdi->usb_dev, 0x40, 0x91, usb_val, i, NULL, 0, ftdi->usb_timeout) != 0) {
529           ftdi->error_str = "Unable to write eeprom";
530           return -1;
531        }
532     }
533
534     return 0;
535 }
536
537
538 int ftdi_erase_eeprom(struct ftdi_context *ftdi) {
539     if (usb_control_msg(ftdi->usb_dev, 0x40, 0x92, 0, 0, NULL, 0, ftdi->usb_timeout) != 0) {
540         ftdi->error_str = "Unable to erase eeprom";
541         return -1;
542     }
543
544     return 0;
545 }