libftdi: (tomj) implemented read
[libftdi] / ftdi / ftdi.c
CommitLineData
a3da1d95
GE
1/***************************************************************************
2 ftdi.c - description
3 -------------------
4 begin : Fri Apr 4 2003
5 copyright : (C) 2003 by Intra2net AG
6 email : info@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
21int 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
34void 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*/
49int 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
96int 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
106/* ftdi_usb_close return codes
107 0: all fine
108 -1: usb_release failed
109 -2: usb_close failed
110*/
111int ftdi_usb_close(struct ftdi_context *ftdi) {
112 int rtn = 0;
113
114 if (usb_release_interface(ftdi->usb_dev, 0) != 0)
115 rtn = -1;
116
117 if (usb_close (ftdi->usb_dev) != 0)
118 rtn = -2;
119
120 return rtn;
121}
122
123
124/*
125 ftdi_set_baudrate return codes:
126 0: all fine
127 -1: invalid baudrate
128 -2: setting baudrate failed
129*/
130int ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate) {
131 unsigned short ftdi_baudrate;
132
133 if (ftdi->bitbang_enabled) {
134 baudrate = baudrate*4;
135 }
136
137 switch (baudrate) {
138 case 300:
139 ftdi_baudrate = 0x2710;
140 break;
141 case 600:
142 ftdi_baudrate = 0x1388;
143 break;
144 case 1200:
145 ftdi_baudrate = 0x09C4;
146 break;
147 case 2400:
148 ftdi_baudrate = 0x04E2;
149 break;
150 case 4800:
151 ftdi_baudrate = 0x0271;
152 break;
153 case 9600:
154 ftdi_baudrate = 0x4138;
155 break;
156 case 19200:
157 ftdi_baudrate = 0x809C;
158 break;
159 case 38400:
160 ftdi_baudrate = 0xC04E;
161 break;
162 case 57600:
163 ftdi_baudrate = 0x0034;
164 break;
165 case 115200:
166 ftdi_baudrate = 0x001A;
167 break;
168 case 230400:
169 ftdi_baudrate = 0x000D;
170 break;
171 case 460800:
172 ftdi_baudrate = 0x4006;
173 break;
174 case 921600:
175 ftdi_baudrate = 0x8003;
176 break;
177 default:
178 ftdi->error_str = "Unknown baudrate. Note: bitbang baudrates are automatically multiplied by 4";
179 return -1;
180 }
181
182 if (usb_control_msg(ftdi->usb_dev, 0x40, 3, ftdi_baudrate, 0, NULL, 0, ftdi->usb_timeout) != 0) {
183 ftdi->error_str = "Setting new baudrate failed";
184 return -2;
185 }
186
187 ftdi->baudrate = baudrate;
188 return 0;
189}
190
191
be5d7eec 192int ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
a3da1d95
GE
193 int ret;
194 int offset = 0;
195 while (offset < size) {
196 int write_size = 64;
197
198 if (offset+write_size > size)
199 write_size = size-offset;
200
201 ret=usb_bulk_write(ftdi->usb_dev, 2, buf+offset, write_size, ftdi->usb_timeout);
cbabb7d3
TJ
202 if (ret == -1) {
203 ftdi->error_str = "bulk write failed";
a3da1d95 204 return -1;
cbabb7d3 205 }
a3da1d95
GE
206
207 offset += write_size;
208 }
209
210 return 0;
211}
212
213
be5d7eec 214int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) {
cbabb7d3
TJ
215 static unsigned char readbuf[64];
216 int ret = 1;
217 int offset = 0;
218
219 while (offset < size && ret > 0) {
220 ret = usb_bulk_read (ftdi->usb_dev, 0x81, readbuf, 64, ftdi->usb_timeout);
221 // Skip FTDI status bytes
222 if (ret >= 2)
223 ret-=2;
224
225 if (ret > 0) {
226 memcpy (buf+offset, readbuf+2, ret);
227 }
228
229 if (ret == -1) {
230 ftdi->error_str = "bulk read failed";
231 return -1;
232 }
233
234 offset += ret;
235 }
236
237 return offset;
a3da1d95
GE
238}
239
240
241int ftdi_enable_bitbang(struct ftdi_context *ftdi, unsigned char bitmask) {
242 unsigned short usb_val;
243
244 usb_val = bitmask; // low byte: bitmask
245 usb_val += 1 << 8; // high byte: enable flag
246 if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, usb_val, 0, NULL, 0, ftdi->usb_timeout) != 0) {
247 ftdi->error_str = "Unable to enter bitbang mode. Perhaps not a BM type chip?";
248 return -1;
249 }
250
251 ftdi->bitbang_enabled = 1;
252 return 0;
253}
254
255
256int ftdi_disable_bitbang(struct ftdi_context *ftdi) {
257 if (usb_control_msg(ftdi->usb_dev, 0x40, 0x0B, 0, 0, NULL, 0, ftdi->usb_timeout) != 0) {
258 ftdi->error_str = "Unable to leave bitbang mode. Perhaps not a BM type chip?";
259 return -1;
260 }
261
262 ftdi->bitbang_enabled = 0;
263 return 0;
264}
265
266
267int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins) {
268 unsigned short usb_val;
269 if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x0C, 0, 0, (char *)&usb_val, 1, ftdi->usb_timeout) != 1) {
270 ftdi->error_str = "Read pins failed";
271 return -1;
272 }
273
274 *pins = (unsigned char)usb_val;
275 return 0;
276}
277
278
279int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) {
280 unsigned short usb_val;
281
282 if (latency < 1) {
283 ftdi->error_str = "Latency out of range. Only valid for 1-255";
284 return -1;
285 }
286
287 if (usb_control_msg(ftdi->usb_dev, 0x40, 0x09, usb_val, 0, NULL, 0, ftdi->usb_timeout) != 0) {
288 ftdi->error_str = "Unable to set latency timer";
289 return -2;
290 }
291 return 0;
292}
293
294
295int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency) {
296 unsigned short usb_val;
297 if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x09, 0, 0, (char *)&usb_val, 1, ftdi->usb_timeout) != 1) {
298 ftdi->error_str = "Reading latency timer failed";
299 return -1;
300 }
301
302 *latency = (unsigned char)usb_val;
303 return 0;
304}
305
306
b8aa7b35
TJ
307void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) {
308 eeprom->vendor_id = 0403;
309 eeprom->product_id = 6001;
310
311 eeprom->self_powered = 1;
312 eeprom->remote_wakeup = 1;
313 eeprom->BM_type_chip = 1;
314
315 eeprom->in_is_isochronous = 0;
316 eeprom->out_is_isochronous = 0;
317 eeprom->suspend_pull_downs = 0;
318
319 eeprom->use_serial = 0;
320 eeprom->change_usb_version = 0;
321 eeprom->usb_version = 200;
322 eeprom->max_power = 0;
323
324 eeprom->manufacturer = NULL;
325 eeprom->product = NULL;
326 eeprom->serial = NULL;
327}
328
329
330/*
331 ftdi_eeprom_build return codes:
8ed61121 332 positive value: used eeprom size
b8aa7b35
TJ
333 -1: eeprom size (128 bytes) exceeded by custom strings
334*/
335int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) {
336 unsigned char i, j;
337 unsigned short checksum, value;
338 unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
339 int size_check;
340
341 if (eeprom->manufacturer != NULL)
342 manufacturer_size = strlen(eeprom->manufacturer);
343 if (eeprom->product != NULL)
344 product_size = strlen(eeprom->product);
345 if (eeprom->serial != NULL)
346 serial_size = strlen(eeprom->serial);
347
348 size_check = 128; // eeprom is 128 bytes
349 size_check -= 28; // 28 are always in use (fixed)
350 size_check -= manufacturer_size*2;
351 size_check -= product_size*2;
352 size_check -= serial_size*2;
353
354 // eeprom size exceeded?
355 if (size_check < 0)
356 return (-1);
357
358 // empty eeprom
359 memset (output, 0, 128);
360
361 // Addr 00: Stay 00 00
362 // Addr 02: Vendor ID
363 output[0x02] = eeprom->vendor_id;
364 output[0x03] = eeprom->vendor_id >> 8;
365
366 // Addr 04: Product ID
367 output[0x04] = eeprom->product_id;
368 output[0x05] = eeprom->product_id >> 8;
369
370 // Addr 06: Device release number (0400h for BM features)
371 output[0x06] = 0x00;
372
373 if (eeprom->BM_type_chip == 1)
374 output[0x07] = 0x04;
375 else
376 output[0x07] = 0x02;
377
378 // Addr 08: Config descriptor
379 // Bit 1: remote wakeup if 1
380 // Bit 0: self powered if 1
381 //
382 j = 0;
383 if (eeprom->self_powered == 1)
384 j = j | 1;
385 if (eeprom->remote_wakeup == 1)
386 j = j | 2;
387 output[0x08] = j;
388
389 // Addr 09: Max power consumption: max power = value * 2 mA
390 output[0x09] = eeprom->max_power;;
391
392 // Addr 0A: Chip configuration
393 // Bit 7: 0 - reserved
394 // Bit 6: 0 - reserved
395 // Bit 5: 0 - reserved
396 // Bit 4: 1 - Change USB version
397 // Bit 3: 1 - Use the serial number string
398 // Bit 2: 1 - Enable suspend pull downs for lower power
399 // Bit 1: 1 - Out EndPoint is Isochronous
400 // Bit 0: 1 - In EndPoint is Isochronous
401 //
402 j = 0;
403 if (eeprom->in_is_isochronous == 1)
404 j = j | 1;
405 if (eeprom->out_is_isochronous == 1)
406 j = j | 2;
407 if (eeprom->suspend_pull_downs == 1)
408 j = j | 4;
409 if (eeprom->use_serial == 1)
410 j = j | 8;
411 if (eeprom->change_usb_version == 1)
412 j = j | 16;
413 output[0x0A] = j;
414
415 // Addr 0B: reserved
416 output[0x0B] = 0x00;
417
418 // Addr 0C: USB version low byte when 0x0A bit 4 is set
419 // Addr 0D: USB version high byte when 0x0A bit 4 is set
420 if (eeprom->change_usb_version == 1) {
421 output[0x0C] = eeprom->usb_version;
422 output[0x0D] = eeprom->usb_version >> 8;
423 }
424
425
426 // Addr 0E: Offset of the manufacturer string + 0x80
427 output[0x0E] = 0x14 + 0x80;
428
429 // Addr 0F: Length of manufacturer string
430 output[0x0F] = manufacturer_size*2 + 2;
431
432 // Addr 10: Offset of the product string + 0x80, calculated later
433 // Addr 11: Length of product string
434 output[0x11] = product_size*2 + 2;
435
436 // Addr 12: Offset of the serial string + 0x80, calculated later
437 // Addr 13: Length of serial string
438 output[0x13] = serial_size*2 + 2;
439
440 // Dynamic content
441 output[0x14] = manufacturer_size;
442 output[0x15] = 0x03; // type: string
443
444 i = 0x16, j = 0;
445
446 // Output manufacturer
447 for (j = 0; j < manufacturer_size; j++) {
448 output[i] = eeprom->manufacturer[j], i++;
449 output[i] = 0x00, i++;
450 }
451
452 // Output product name
453 output[0x10] = i + 0x80; // calculate offset
454 output[i] = product_size*2 + 2, i++;
455 output[i] = 0x03, i++;
456 for (j = 0; j < product_size; j++) {
457 output[i] = eeprom->product[j], i++;
458 output[i] = 0x00, i++;
459 }
460
461 // Output serial
462 output[0x12] = i + 0x80; // calculate offset
463 output[i] = serial_size*2 + 2, i++;
464 output[i] = 0x03, i++;
465 for (j = 0; j < serial_size; j++) {
466 output[i] = eeprom->serial[j], i++;
467 output[i] = 0x00, i++;
468 }
469
470 // calculate checksum
471 checksum = 0xAAAA;
472
473 for (i = 0; i < 63; i++) {
474 value = output[i*2];
475 value += output[(i*2)+1] << 8;
476
477 checksum = value^checksum;
478 checksum = (checksum << 1) | (checksum >> 15);
479 }
480
481 output[0x7E] = checksum;
482 output[0x7F] = checksum >> 8;
483
8ed61121 484 return size_check;
b8aa7b35
TJ
485}
486
487
be5d7eec 488int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) {
a3da1d95
GE
489 int i;
490
491 for (i = 0; i < 64; i++) {
492 if (usb_control_msg(ftdi->usb_dev, 0xC0, 0x90, 0, i, eeprom+(i*2), 2, ftdi->usb_timeout) != 2) {
493 ftdi->error_str = "Reading eeprom failed";
494 return -1;
495 }
496 }
497
498 return 0;
499}
500
501
be5d7eec 502int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) {
a3da1d95
GE
503 unsigned short usb_val;
504 int i;
505
506 for (i = 0; i < 64; i++) {
507 usb_val = eeprom[i*2];
508 usb_val += eeprom[(i*2)+1] << 8;
509 if (usb_control_msg(ftdi->usb_dev, 0x40, 0x91, usb_val, i, NULL, 0, ftdi->usb_timeout) != 0) {
510 ftdi->error_str = "Unable to write eeprom";
511 return -1;
512 }
513 }
514
515 return 0;
516}
517
518
519int ftdi_erase_eeprom(struct ftdi_context *ftdi) {
520 if (usb_control_msg(ftdi->usb_dev, 0x40, 0x92, 0, 0, NULL, 0, ftdi->usb_timeout) != 0) {
521 ftdi->error_str = "Unable to erase eeprom";
522 return -1;
523 }
524
525 return 0;
526}
cbabb7d3 527