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

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)