ULINK driver: port from libusb-0.1 to libusb-1.0 API
[fw/openocd] / src / jtag / drivers / usb_blaster / ublast_access_ftd2xx.c
1 /*
2  *   Driver for USB-JTAG, Altera USB-Blaster and compatibles
3  *
4  *   Inspired from original code from Kolja Waschk's USB-JTAG project
5  *   (http://www.ixo.de/info/usb_jtag/), and from openocd project.
6  *
7  *   Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
8  *   Copyright (C) 2011 Ali Lown ali@lown.me.uk
9  *   Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
10  *   Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
11  *
12  *   This program is free software; you can redistribute it and/or modify
13  *   it under the terms of the GNU General Public License as published by
14  *   the Free Software Foundation; either version 2 of the License, or
15  *   (at your option) any later version.
16  *
17  *   This program is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 #include <jtag/interface.h>
28 #include <jtag/commands.h>
29
30 #include "ublast_access.h"
31
32 #include <ftd2xx.h>
33 #include "jtag/drivers/ftd2xx_common.h"
34
35 static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low)
36 {
37         return low->priv;
38 }
39
40 static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
41                               uint32_t *bytes_written)
42 {
43         FT_STATUS status;
44         DWORD dw_bytes_written;
45         FT_HANDLE *ftdih = ublast_getftdih(low);
46
47         status = FT_Write(*ftdih, buf, size, &dw_bytes_written);
48         if (status != FT_OK) {
49                 *bytes_written = dw_bytes_written;
50                 LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status));
51                 return ERROR_JTAG_DEVICE_ERROR;
52         }
53         *bytes_written = dw_bytes_written;
54         return ERROR_OK;
55 }
56
57 static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf,
58                              unsigned size, uint32_t *bytes_read)
59 {
60         DWORD dw_bytes_read;
61         FT_STATUS status;
62         FT_HANDLE *ftdih = ublast_getftdih(low);
63
64         status = FT_Read(*ftdih, buf, size, &dw_bytes_read);
65         if (status != FT_OK) {
66                 *bytes_read = dw_bytes_read;
67                 LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status));
68                 return ERROR_JTAG_DEVICE_ERROR;
69         }
70         *bytes_read = dw_bytes_read;
71         return ERROR_OK;
72 }
73
74 static int ublast_ftd2xx_init(struct ublast_lowlevel *low)
75 {
76         FT_STATUS status;
77         FT_HANDLE *ftdih = ublast_getftdih(low);
78         uint8_t latency_timer;
79
80         LOG_INFO("usb blaster interface using FTD2XX");
81         /* Open by device description */
82         if (low->ublast_device_desc == NULL) {
83                 LOG_WARNING("no usb blaster device description specified, "
84                             "using default 'USB-Blaster'");
85                 low->ublast_device_desc = "USB-Blaster";
86         }
87
88 #if IS_WIN32 == 0
89         /* Add non-standard Vid/Pid to the linux driver */
90         status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid);
91         if (status != FT_OK) {
92                 LOG_WARNING("couldn't add %4.4x:%4.4x",
93                             low->ublast_vid, low->ublast_pid);
94         }
95 #endif
96         status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION,
97                            ftdih);
98         if (status != FT_OK) {
99                 DWORD num_devices;
100
101                 LOG_ERROR("unable to open ftdi device: %s",
102                           ftd2xx_status_string(status));
103                 status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
104                 if (status == FT_OK) {
105                         char **desc_array =
106                                 malloc(sizeof(char *) * (num_devices + 1));
107                         unsigned int i;
108
109                         for (i = 0; i < num_devices; i++)
110                                 desc_array[i] = malloc(64);
111                         desc_array[num_devices] = NULL;
112
113                         status = FT_ListDevices(desc_array, &num_devices,
114                                                 FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
115
116                         if (status == FT_OK) {
117                                 LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices);
118                                 for (i = 0; i < num_devices; i++)
119                                         LOG_ERROR("%i: %s", i, desc_array[i]);
120                         }
121
122                         for (i = 0; i < num_devices; i++)
123                                 free(desc_array[i]);
124                         free(desc_array);
125                 } else {
126                         printf("ListDevices: NONE\n");
127                 }
128                 return ERROR_JTAG_INIT_FAILED;
129         }
130
131         status = FT_SetLatencyTimer(*ftdih, 2);
132         if (status != FT_OK) {
133                 LOG_ERROR("unable to set latency timer: %s",
134                                 ftd2xx_status_string(status));
135                 return ERROR_JTAG_INIT_FAILED;
136         }
137
138         status = FT_GetLatencyTimer(*ftdih, &latency_timer);
139         if (status != FT_OK) {
140                 LOG_ERROR("unable to get latency timer: %s",
141                                 ftd2xx_status_string(status));
142                 return ERROR_JTAG_INIT_FAILED;
143         }
144         LOG_DEBUG("current latency timer: %i", latency_timer);
145
146         status = FT_SetBitMode(*ftdih, 0x00, 0);
147         if (status != FT_OK) {
148                 LOG_ERROR("unable to disable bit i/o mode: %s",
149                                 ftd2xx_status_string(status));
150                 return ERROR_JTAG_INIT_FAILED;
151         }
152         return ERROR_OK;
153 }
154
155 static int ublast_ftd2xx_quit(struct ublast_lowlevel *low)
156 {
157         FT_HANDLE *ftdih = ublast_getftdih(low);
158
159         FT_Close(*ftdih);
160         return ERROR_OK;
161 }
162
163 static struct ublast_lowlevel_priv {
164         FT_HANDLE ftdih;
165 } info;
166
167 static struct ublast_lowlevel low = {
168         .open = ublast_ftd2xx_init,
169         .close = ublast_ftd2xx_quit,
170         .read = ublast_ftd2xx_read,
171         .write = ublast_ftd2xx_write,
172         .priv = &info,
173 };
174
175 struct ublast_lowlevel *ublast_register_ftd2xx(void)
176 {
177         return &low;
178 }