vsllink: Port to libusb-1.0 API
[openocd.git] / src / jtag / drivers / versaloon / versaloon.c
1 /***************************************************************************
2 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <libusb.h>
27
28 #include "versaloon_include.h"
29 #include "versaloon.h"
30 #include "versaloon_internal.h"
31 #include "usbtoxxx/usbtoxxx.h"
32
33 uint8_t *versaloon_buf;
34 uint8_t *versaloon_cmd_buf;
35 uint16_t versaloon_buf_size;
36
37 struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
38 uint16_t versaloon_pending_idx;
39
40 libusb_device_handle *versaloon_usb_device_handle;
41 static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT;
42
43 RESULT versaloon_init(void);
44 RESULT versaloon_fini(void);
45 RESULT versaloon_get_target_voltage(uint16_t *voltage);
46 RESULT versaloon_set_target_voltage(uint16_t voltage);
47 RESULT versaloon_delay_ms(uint16_t ms);
48 RESULT versaloon_delay_us(uint16_t us);
49
50 struct versaloon_interface_t versaloon_interface = {
51 .init = versaloon_init,
52 .fini = versaloon_fini,
53 { /* adaptors */
54 { /* target_voltage */
55 .get = versaloon_get_target_voltage,
56 .set = versaloon_set_target_voltage,
57 },
58 { /* gpio */
59 .init = usbtogpio_init,
60 .fini = usbtogpio_fini,
61 .config = usbtogpio_config,
62 .out = usbtogpio_out,
63 .in = usbtogpio_in,
64 },
65 { /* delay */
66 .delayms = versaloon_delay_ms,
67 .delayus = versaloon_delay_us,
68 },
69 { /* swd */
70 .init = usbtoswd_init,
71 .fini = usbtoswd_fini,
72 .config = usbtoswd_config,
73 .seqout = usbtoswd_seqout,
74 .seqin = usbtoswd_seqin,
75 .transact = usbtoswd_transact,
76 },
77 { /* jtag_raw */
78 .init = usbtojtagraw_init,
79 .fini = usbtojtagraw_fini,
80 .config = usbtojtagraw_config,
81 .execute = usbtojtagraw_execute,
82 },
83 .peripheral_commit = usbtoxxx_execute_command,
84 },
85 { /* usb_setting */
86 .vid = VERSALOON_VID,
87 .pid = VERSALOON_PID,
88 .ep_out = VERSALOON_OUTP,
89 .ep_in = VERSALOON_INP,
90 .interface = VERSALOON_IFACE,
91 .serialstring = NULL,
92 .buf_size = 256,
93 }
94 };
95
96 /* programmer_cmd */
97 static uint32_t versaloon_pending_id;
98 static versaloon_callback_t versaloon_callback;
99 static void *versaloon_extra_data;
100 static struct versaloon_want_pos_t *versaloon_want_pos;
101
102 void versaloon_set_pending_id(uint32_t id)
103 {
104 versaloon_pending_id = id;
105 }
106 void versaloon_set_callback(versaloon_callback_t callback)
107 {
108 versaloon_callback = callback;
109 }
110 void versaloon_set_extra_data(void *p)
111 {
112 versaloon_extra_data = p;
113 }
114
115 void versaloon_free_want_pos(void)
116 {
117 uint16_t i;
118 struct versaloon_want_pos_t *tmp, *free_tmp;
119
120 tmp = versaloon_want_pos;
121 while (tmp != NULL) {
122 free_tmp = tmp;
123 tmp = tmp->next;
124 free(free_tmp);
125 }
126 versaloon_want_pos = NULL;
127
128 for (i = 0; i < dimof(versaloon_pending); i++) {
129 tmp = versaloon_pending[i].pos;
130 while (tmp != NULL) {
131 free_tmp = tmp;
132 tmp = tmp->next;
133 free(free_tmp);
134 }
135 versaloon_pending[i].pos = NULL;
136 }
137 }
138
139 RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff)
140 {
141 struct versaloon_want_pos_t *new_pos = NULL;
142
143 new_pos = malloc(sizeof(*new_pos));
144 if (NULL == new_pos) {
145 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
146 return ERRCODE_NOT_ENOUGH_MEMORY;
147 }
148 new_pos->offset = offset;
149 new_pos->size = size;
150 new_pos->buff = buff;
151 new_pos->next = NULL;
152
153 if (NULL == versaloon_want_pos)
154 versaloon_want_pos = new_pos;
155 else {
156 struct versaloon_want_pos_t *tmp = versaloon_want_pos;
157
158 while (tmp->next != NULL)
159 tmp = tmp->next;
160 tmp->next = new_pos;
161 }
162
163 return ERROR_OK;
164 }
165
166 RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie,
167 uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect)
168 {
169 #if PARAM_CHECK
170 if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER) {
171 LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx,
172 "versaloon pending data");
173 return ERROR_FAIL;
174 }
175 #endif
176
177 versaloon_pending[versaloon_pending_idx].type = type;
178 versaloon_pending[versaloon_pending_idx].cmd = cmd;
179 versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie;
180 versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos;
181 versaloon_pending[versaloon_pending_idx].want_data_size = want_size;
182 versaloon_pending[versaloon_pending_idx].data_buffer = buffer;
183 versaloon_pending[versaloon_pending_idx].collect = collect;
184 versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id;
185 versaloon_pending_id = 0;
186 versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data;
187 versaloon_extra_data = NULL;
188 versaloon_pending[versaloon_pending_idx].callback = versaloon_callback;
189 versaloon_callback = NULL;
190 versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos;
191 versaloon_want_pos = NULL;
192 versaloon_pending_idx++;
193
194 return ERROR_OK;
195 }
196
197 RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen)
198 {
199 int ret;
200 int transferred;
201
202 #if PARAM_CHECK
203 if (NULL == versaloon_buf) {
204 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
205 return ERRCODE_INVALID_BUFFER;
206 }
207 if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size)) {
208 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
209 return ERRCODE_INVALID_PARAMETER;
210 }
211 #endif
212
213 ret = libusb_bulk_transfer(versaloon_usb_device_handle,
214 versaloon_interface.usb_setting.ep_out,
215 versaloon_buf, out_len, &transferred, versaloon_usb_to);
216 if (0 != ret || transferred != out_len) {
217 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "send usb data");
218 return ERRCODE_FAILURE_OPERATION;
219 }
220
221 if (inlen != NULL) {
222 ret = libusb_bulk_transfer(versaloon_usb_device_handle,
223 versaloon_interface.usb_setting.ep_in,
224 versaloon_buf, versaloon_interface.usb_setting.buf_size,
225 &transferred, versaloon_usb_to);
226 if (0 == ret) {
227 *inlen = (uint16_t)transferred;
228 return ERROR_OK;
229 } else {
230 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "receive usb data");
231 return ERROR_FAIL;
232 }
233 } else
234 return ERROR_OK;
235 }
236
237 #define VERSALOON_RETRY_CNT 10
238 RESULT versaloon_init(void)
239 {
240 uint16_t ret = 0;
241 uint8_t retry;
242 uint32_t timeout_tmp;
243
244 /* malloc temporary buffer */
245 versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
246 if (NULL == versaloon_buf) {
247 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
248 return ERRCODE_NOT_ENOUGH_MEMORY;
249 }
250
251 /* connect to versaloon */
252 timeout_tmp = versaloon_usb_to;
253 /* not output error message when connectting */
254 /* 100ms delay when connect */
255 versaloon_usb_to = 100;
256 for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) {
257 versaloon_buf[0] = VERSALOON_GET_INFO;
258 if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3))
259 break;
260 }
261 versaloon_usb_to = timeout_tmp;
262 if (VERSALOON_RETRY_CNT == retry) {
263 versaloon_fini();
264 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
265 return ERRCODE_FAILURE_OPERATION;
266 }
267
268 versaloon_buf[ret] = 0;
269 versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8);
270 versaloon_interface.usb_setting.buf_size = versaloon_buf_size;
271 LOG_INFO("%s", versaloon_buf + 2);
272
273 /* free temporary buffer */
274 free(versaloon_buf);
275 versaloon_buf = NULL;
276
277 versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
278 if (NULL == versaloon_buf) {
279 versaloon_fini();
280 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
281 return ERRCODE_NOT_ENOUGH_MEMORY;
282 }
283 versaloon_cmd_buf = malloc(versaloon_interface.usb_setting.buf_size - 3);
284 if (NULL == versaloon_cmd_buf) {
285 versaloon_fini();
286 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
287 return ERRCODE_NOT_ENOUGH_MEMORY;
288 }
289 if (ERROR_OK != usbtoxxx_init()) {
290 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx");
291 return ERROR_FAIL;
292 }
293 return versaloon_get_target_voltage(&ret);
294 }
295
296 RESULT versaloon_fini(void)
297 {
298 if (versaloon_usb_device_handle != NULL) {
299 usbtoxxx_fini();
300 versaloon_free_want_pos();
301
302 versaloon_usb_device_handle = NULL;
303
304 if (versaloon_buf != NULL) {
305 free(versaloon_buf);
306 versaloon_buf = NULL;
307 }
308 if (versaloon_cmd_buf != NULL) {
309 free(versaloon_cmd_buf);
310 versaloon_cmd_buf = NULL;
311 }
312 }
313
314 return ERROR_OK;
315 }
316
317 RESULT versaloon_set_target_voltage(uint16_t voltage)
318 {
319 usbtopwr_init(0);
320 usbtopwr_config(0);
321 usbtopwr_output(0, voltage);
322 usbtopwr_fini(0);
323
324 return usbtoxxx_execute_command();
325 }
326
327 RESULT versaloon_get_target_voltage(uint16_t *voltage)
328 {
329 uint16_t inlen;
330
331 #if PARAM_CHECK
332 if (NULL == versaloon_buf) {
333 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
334 return ERRCODE_INVALID_BUFFER;
335 }
336 if (NULL == voltage) {
337 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
338 return ERRCODE_INVALID_PARAMETER;
339 }
340 #endif
341
342 versaloon_buf[0] = VERSALOON_GET_TVCC;
343
344 if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) {
345 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
346 return ERRCODE_FAILURE_OPERATION;
347 } else {
348 *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8);
349 return ERROR_OK;
350 }
351 }
352
353 RESULT versaloon_delay_ms(uint16_t ms)
354 {
355 return usbtodelay_delay(ms | 0x8000);
356 }
357
358 RESULT versaloon_delay_us(uint16_t us)
359 {
360 return usbtodelay_delay(us & 0x7FFF);
361 }

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)