drivers: libusb1_common code cleanup
[openocd.git] / src / jtag / drivers / usb_blaster / ublast2_access_libusb.c
1 /*
2 * Driver for USB-JTAG, Altera USB-Blaster II and compatibles
3 *
4 * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <jtag/interface.h>
25 #include <jtag/commands.h>
26 #include <libusb_common.h>
27 #include <target/image.h>
28
29 #include "ublast_access.h"
30
31 #define USBBLASTER_CTRL_READ_REV 0x94
32 #define USBBLASTER_CTRL_LOAD_FIRM 0xA0
33 #define USBBLASTER_EPOUT 4
34 #define USBBLASTER_EPIN 8
35
36 #define EZUSB_CPUCS 0xe600
37 #define CPU_RESET 1
38
39 /** Maximum size of a single firmware section. Entire EZ-USB code space = 16kB */
40 #define SECTION_BUFFERSIZE 16384
41
42 static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf,
43 unsigned size, uint32_t *bytes_read)
44 {
45 int ret, tmp = 0;
46
47 ret = jtag_libusb_bulk_read(low->libusb_dev,
48 USBBLASTER_EPIN | \
49 LIBUSB_ENDPOINT_IN,
50 (char *)buf,
51 size,
52 100, &tmp);
53 *bytes_read = tmp;
54
55 return ret;
56 }
57
58 static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf,
59 int size, uint32_t *bytes_written)
60 {
61 int ret, tmp = 0;
62
63 ret = jtag_libusb_bulk_write(low->libusb_dev,
64 USBBLASTER_EPOUT | \
65 LIBUSB_ENDPOINT_OUT,
66 (char *)buf,
67 size,
68 100, &tmp);
69 *bytes_written = tmp;
70
71 return ret;
72
73 }
74
75 static int ublast2_write_firmware_section(struct libusb_device_handle *libusb_dev,
76 struct image *firmware_image, int section_index)
77 {
78 uint16_t chunk_size;
79 uint8_t data[SECTION_BUFFERSIZE];
80 uint8_t *data_ptr = data;
81 size_t size_read;
82
83 uint16_t size = (uint16_t)firmware_image->sections[section_index].size;
84 uint16_t addr = (uint16_t)firmware_image->sections[section_index].base_address;
85
86 LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr,
87 size);
88
89 /* Copy section contents to local buffer */
90 int ret = image_read_section(firmware_image, section_index, 0, size, data,
91 &size_read);
92
93 if ((ret != ERROR_OK) || (size_read != size)) {
94 /* Propagating the return code would return '0' (misleadingly indicating
95 * successful execution of the function) if only the size check fails. */
96 return ERROR_FAIL;
97 }
98
99 uint16_t bytes_remaining = size;
100
101 /* Send section data in chunks of up to 64 bytes to ULINK */
102 while (bytes_remaining > 0) {
103 if (bytes_remaining > 64)
104 chunk_size = 64;
105 else
106 chunk_size = bytes_remaining;
107
108 jtag_libusb_control_transfer(libusb_dev,
109 LIBUSB_REQUEST_TYPE_VENDOR | \
110 LIBUSB_ENDPOINT_OUT,
111 USBBLASTER_CTRL_LOAD_FIRM,
112 addr,
113 0,
114 (char *)data_ptr,
115 chunk_size,
116 100);
117
118 bytes_remaining -= chunk_size;
119 addr += chunk_size;
120 data_ptr += chunk_size;
121 }
122
123 return ERROR_OK;
124 }
125
126 static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
127 struct ublast_lowlevel *low)
128 {
129 struct image ublast2_firmware_image;
130
131 if (!low->firmware_path) {
132 LOG_ERROR("No firmware path specified");
133 return ERROR_FAIL;
134 }
135
136 ublast2_firmware_image.base_address = 0;
137 ublast2_firmware_image.base_address_set = 0;
138
139 int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex");
140 if (ret != ERROR_OK) {
141 LOG_ERROR("Could not load firmware image");
142 return ret;
143 }
144
145 /** A host loader program must write 0x01 to the CPUCS register
146 * to put the CPU into RESET, load all or part of the EZUSB
147 * RAM with firmware, then reload the CPUCS register
148 * with ‘0’ to take the CPU out of RESET. The CPUCS register
149 * (at 0xE600) is the only EZ-USB register that can be written
150 * using the Firmware Download command.
151 */
152
153 char value = CPU_RESET;
154 jtag_libusb_control_transfer(libusb_dev,
155 LIBUSB_REQUEST_TYPE_VENDOR | \
156 LIBUSB_ENDPOINT_OUT,
157 USBBLASTER_CTRL_LOAD_FIRM,
158 EZUSB_CPUCS,
159 0,
160 &value,
161 1,
162 100);
163
164 /* Download all sections in the image to ULINK */
165 for (int i = 0; i < ublast2_firmware_image.num_sections; i++) {
166 ret = ublast2_write_firmware_section(libusb_dev,
167 &ublast2_firmware_image, i);
168 if (ret != ERROR_OK) {
169 LOG_ERROR("Error while downloading the firmware");
170 return ret;
171 }
172 }
173
174 value = !CPU_RESET;
175 jtag_libusb_control_transfer(libusb_dev,
176 LIBUSB_REQUEST_TYPE_VENDOR | \
177 LIBUSB_ENDPOINT_OUT,
178 USBBLASTER_CTRL_LOAD_FIRM,
179 EZUSB_CPUCS,
180 0,
181 &value,
182 1,
183 100);
184
185 image_close(&ublast2_firmware_image);
186
187 return ERROR_OK;
188 }
189
190 static int ublast2_libusb_init(struct ublast_lowlevel *low)
191 {
192 const uint16_t vids[] = { low->ublast_vid_uninit, 0 };
193 const uint16_t pids[] = { low->ublast_pid_uninit, 0 };
194 struct libusb_device_handle *temp;
195 bool renumeration = false;
196 int ret;
197
198 if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) {
199 LOG_INFO("Altera USB-Blaster II (uninitialized) found");
200 LOG_INFO("Loading firmware...");
201 ret = load_usb_blaster_firmware(temp, low);
202 jtag_libusb_close(temp);
203 if (ret != ERROR_OK)
204 return ret;
205 renumeration = true;
206 }
207
208 const uint16_t vids_renum[] = { low->ublast_vid, 0 };
209 const uint16_t pids_renum[] = { low->ublast_pid, 0 };
210
211 if (renumeration == false) {
212 if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) {
213 LOG_ERROR("Altera USB-Blaster II not found");
214 return ERROR_FAIL;
215 }
216 } else {
217 int retry = 10;
218 while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) {
219 usleep(1000000);
220 LOG_INFO("Waiting for renumerate...");
221 }
222
223 if (!retry) {
224 LOG_ERROR("Altera USB-Blaster II not found");
225 return ERROR_FAIL;
226 }
227 }
228
229 char buffer[5];
230 jtag_libusb_control_transfer(low->libusb_dev,
231 LIBUSB_REQUEST_TYPE_VENDOR | \
232 LIBUSB_ENDPOINT_IN,
233 USBBLASTER_CTRL_READ_REV,
234 0,
235 0,
236 buffer,
237 5,
238 100);
239
240 LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer);
241
242 return ERROR_OK;
243 }
244
245 static int ublast2_libusb_quit(struct ublast_lowlevel *low)
246 {
247 jtag_libusb_close(low->libusb_dev);
248 return ERROR_OK;
249 };
250
251 static struct ublast_lowlevel low = {
252 .open = ublast2_libusb_init,
253 .close = ublast2_libusb_quit,
254 .read = ublast2_libusb_read,
255 .write = ublast2_libusb_write,
256 .flags = COPY_TDO_BUFFER,
257 };
258
259 struct ublast_lowlevel *ublast2_register_libusb(void)
260 {
261 return &low;
262 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)