1 /*
2 * $Id$
3 *
4 * Copyright (C) 2003 ETC s.r.o.
5 * Copyright (C) 2005 Hein Roehrig,
6 * Copyright (C) 2008 Kolja Waschk
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA.
22 *
23 * Written by Marcel Telka <marcel@telka.sk>, 2003;
24 * Busy loop waiting (*freq* functions) Hein Roehrig, 2005;
25 * JTAG activity queuing and API (*defer* functions) K. Waschk, 2008
26 *
27 */
28
29 #include <sysdep.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <stdint.h>
36 #include <string.h>
37
38 #include <urjtag/log.h>
39 #include <urjtag/error.h>
40 #include <urjtag/bus.h>
41 #include <urjtag/bus_driver.h>
42 #include <urjtag/chain.h>
43 #include <urjtag/tap.h>
44 #include <urjtag/cable.h>
45
46 #include "cable.h"
47
48 const urj_cable_driver_t * const urj_tap_cable_drivers[] = {
49 #define _URJ_CABLE(cable) &urj_tap_cable_##cable##_driver,
50 #include "cable_list.h"
51 NULL /* last must be NULL */
52 };
53
54 const urj_cable_driver_t *
urj_tap_cable_find(const char * cname)55 urj_tap_cable_find (const char *cname)
56 {
57 size_t i;
58
59 for (i = 0; urj_tap_cable_drivers[i]; ++i)
60 if (strcasecmp (cname, urj_tap_cable_drivers[i]->name) == 0)
61 break;
62
63 return urj_tap_cable_drivers[i];
64 }
65
66 void
urj_tap_cable_free(urj_cable_t * cable)67 urj_tap_cable_free (urj_cable_t *cable)
68 {
69 cable->driver->cable_free (cable);
70 }
71
72 int
urj_tap_cable_init(urj_cable_t * cable)73 urj_tap_cable_init (urj_cable_t *cable)
74 {
75 cable->delay = 0;
76 cable->frequency = 0;
77
78 cable->todo.max_items = 128;
79 cable->todo.num_items = 0;
80 cable->todo.next_item = 0;
81 cable->todo.next_free = 0;
82 cable->todo.data =
83 malloc (cable->todo.max_items * sizeof (urj_cable_queue_t));
84
85 cable->done.max_items = 128;
86 cable->done.num_items = 0;
87 cable->done.next_item = 0;
88 cable->done.next_free = 0;
89 cable->done.data =
90 malloc (cable->done.max_items * sizeof (urj_cable_queue_t));
91
92 if (cable->todo.data == NULL || cable->done.data == NULL)
93 {
94 urj_error_set (URJ_ERROR_OUT_OF_MEMORY,
95 _("malloc(%zd)/malloc(%zd) fails"),
96 cable->todo.max_items * sizeof (urj_cable_queue_t),
97 cable->done.max_items * sizeof (urj_cable_queue_t));
98 if (cable->todo.data != NULL)
99 free (cable->todo.data);
100 if (cable->done.data != NULL)
101 free (cable->done.data);
102 return URJ_STATUS_FAIL;
103 }
104
105 return cable->driver->init (cable);
106 }
107
108 void
urj_tap_cable_flush(urj_cable_t * cable,urj_cable_flush_amount_t how_much)109 urj_tap_cable_flush (urj_cable_t *cable, urj_cable_flush_amount_t how_much)
110 {
111 cable->driver->flush (cable, how_much);
112 }
113
114 void
urj_tap_cable_done(urj_cable_t * cable)115 urj_tap_cable_done (urj_cable_t *cable)
116 {
117 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
118 if (cable->todo.data != NULL)
119 {
120 free (cable->todo.data);
121 free (cable->done.data);
122 }
123 cable->driver->done (cable);
124 }
125
126 int
urj_tap_cable_add_queue_item(urj_cable_t * cable,urj_cable_queue_info_t * q)127 urj_tap_cable_add_queue_item (urj_cable_t *cable, urj_cable_queue_info_t *q)
128 {
129 int i, j;
130 if (q->num_items >= q->max_items) /* queue full? */
131 {
132 int new_max_items;
133 urj_cable_queue_t *resized;
134
135 urj_log (URJ_LOG_LEVEL_DETAIL,
136 "Queue %p needs resizing; n(%d) >= max(%d); free=%d, next=%d\n",
137 q, q->num_items, q->max_items, q->next_free, q->next_item);
138
139 new_max_items = q->max_items + 128;
140 resized = realloc (q->data, new_max_items * sizeof (urj_cable_queue_t));
141 if (resized == NULL)
142 {
143 urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "realloc(%s,%zd) fails",
144 "q->data",
145 new_max_items * sizeof (urj_cable_queue_t));
146 return -1; /* report failure */
147 }
148 urj_log (URJ_LOG_LEVEL_DETAIL,
149 _("(Resized JTAG activity queue to hold max %d items)\n"),
150 new_max_items);
151 q->data = resized;
152
153 /* The queue was full. Except for the special case when next_item is 0,
154 * resizing just introduced a gap between old and new max, which has to
155 * be filled; either by moving data from next_item .. max_items, or
156 * from 0 .. next_free (whatever is smaller). */
157
158 #define CHOOSE_SMALLEST_AREA_TO_MOVE 1
159
160 if (q->next_item != 0)
161 {
162 int added_space = new_max_items - q->max_items;
163 int num_to_move = q->max_items - q->next_item;
164
165 #ifdef CHOOSE_SMALLEST_AREA_TO_MOVE
166 if (num_to_move <= q->next_free)
167 #endif /* def CHOOSE_SMALLEST_AREA_TO_MOVE */
168 {
169 /* Move queue items at end of old array
170 * towards end of new array: 345612__ -> 3456__12 */
171
172 int dest = new_max_items - num_to_move;
173 urj_log (URJ_LOG_LEVEL_DETAIL,
174 "Resize: Move %d items towards end of queue memory (%d > %d)\n",
175 num_to_move, q->next_item, dest);
176 memmove (&q->data[dest], &q->data[q->next_item],
177 num_to_move * sizeof (urj_cable_queue_t));
178
179 q->next_item = dest;
180 }
181 #ifdef CHOOSE_SMALLEST_AREA_TO_MOVE
182 else
183 {
184 if (q->next_free <= added_space)
185 {
186 /* Relocate queue items at beginning of old array
187 * to end of new array: 561234__ -> __123456 */
188
189 urj_log (URJ_LOG_LEVEL_DETAIL,
190 "Resize: Move %d items from start to end\n",
191 q->next_free);
192 memcpy (&q->data[q->max_items], &q->data[0],
193 q->next_free * sizeof (urj_cable_queue_t));
194
195 }
196 else
197 {
198 /* Same as above, but for the case if new space
199 * isn't large enough to hold all relocated items */
200
201 /* Step 1: 456123__ -> __612345 */
202
203 urj_log (URJ_LOG_LEVEL_DETAIL,
204 "Resize.A: Move %d items from start to end\n",
205 added_space);
206
207 memcpy (&q->data[q->max_items], &q->data[0],
208 added_space * sizeof (urj_cable_queue_t));
209
210 /* Step 2: __612345 -> 6__12345 */
211
212 urj_log (URJ_LOG_LEVEL_DETAIL,
213 "Resize.B: Move %d items towards start (offset %d)\n",
214 (q->next_free - added_space), added_space);
215
216 memmove (&q->data[0], &q->data[added_space],
217 (q->next_free -
218 added_space) * sizeof (urj_cable_queue_t));
219 }
220 }
221 #endif /* def CHOOSE_SMALLEST_AREA_TO_MOVE */
222 }
223 q->max_items = new_max_items;
224 q->next_free = q->next_item + q->num_items;
225 if (q->next_free >= new_max_items)
226 q->next_free -= new_max_items;
227
228 urj_log (URJ_LOG_LEVEL_DETAIL,
229 "Queue %p after resizing; n(%d) >= max(%d); free=%d, next=%d\n",
230 q, q->num_items, q->max_items, q->next_free, q->next_item);
231 }
232
233 i = q->next_free;
234 j = i + 1;
235 if (j >= q->max_items)
236 j = 0;
237 q->next_free = j;
238 q->num_items++;
239
240 // urj_log (URJ_LOG_LEVEL_DEBUG, "add_queue_item to %p: %d\n", q, i);
241 return i;
242 }
243
244 int
urj_tap_cable_get_queue_item(urj_cable_t * cable,urj_cable_queue_info_t * q)245 urj_tap_cable_get_queue_item (urj_cable_t *cable, urj_cable_queue_info_t *q)
246 {
247 if (q->num_items > 0)
248 {
249 int i = q->next_item;
250 int j = i + 1;
251 if (j >= q->max_items)
252 j = 0;
253 q->next_item = j;
254 q->num_items--;
255 // urj_log (URJ_LOG_LEVEL_DEBUG, "get_queue_item from %p: %d\n", q, i);
256 return i;
257 }
258
259 urj_error_set (URJ_ERROR_NOTFOUND, "queue is empty");
260 // urj_log (URJ_LOG_LEVEL_DEBUG, "get_queue_item from %p: %d\n", q, -1);
261 return -1;
262 }
263
264 void
urj_tap_cable_purge_queue(urj_cable_queue_info_t * q,int io)265 urj_tap_cable_purge_queue (urj_cable_queue_info_t *q, int io)
266 {
267 while (q->num_items > 0)
268 {
269 int i = q->next_item;
270 if (q->data[i].action == URJ_TAP_CABLE_TRANSFER)
271 {
272 if (io == 0) /* todo queue */
273 {
274 if (q->data[i].arg.transfer.in != NULL)
275 free (q->data[i].arg.transfer.in);
276 if (q->data[i].arg.transfer.out != NULL)
277 free (q->data[i].arg.transfer.out);
278 }
279 else /* done queue */
280 {
281 if (q->data[i].arg.xferred.out != NULL)
282 free (q->data[i].arg.xferred.out);
283 }
284 }
285
286 i++;
287 if (i >= q->max_items)
288 i = 0;
289 q->num_items--;
290 }
291
292 q->num_items = 0;
293 q->next_item = 0;
294 q->next_free = 0;
295 }
296
297 void
urj_tap_cable_clock(urj_cable_t * cable,int tms,int tdi,int n)298 urj_tap_cable_clock (urj_cable_t *cable, int tms, int tdi, int n)
299 {
300 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
301 cable->driver->clock (cable, tms, tdi, n);
302 }
303
304 int
urj_tap_cable_defer_clock(urj_cable_t * cable,int tms,int tdi,int n)305 urj_tap_cable_defer_clock (urj_cable_t *cable, int tms, int tdi, int n)
306 {
307 int i = urj_tap_cable_add_queue_item (cable, &cable->todo);
308 if (i < 0)
309 return URJ_STATUS_FAIL; /* report failure */
310 cable->todo.data[i].action = URJ_TAP_CABLE_CLOCK;
311 cable->todo.data[i].arg.clock.tms = tms;
312 cable->todo.data[i].arg.clock.tdi = tdi;
313 cable->todo.data[i].arg.clock.n = n;
314 urj_tap_cable_flush (cable, URJ_TAP_CABLE_OPTIONALLY);
315 return URJ_STATUS_OK; /* success */
316 }
317
318 int
urj_tap_cable_get_tdo(urj_cable_t * cable)319 urj_tap_cable_get_tdo (urj_cable_t *cable)
320 {
321 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
322 return cable->driver->get_tdo (cable);
323 }
324
325 int
urj_tap_cable_get_tdo_late(urj_cable_t * cable)326 urj_tap_cable_get_tdo_late (urj_cable_t *cable)
327 {
328 int i;
329 urj_tap_cable_flush (cable, URJ_TAP_CABLE_TO_OUTPUT);
330 i = urj_tap_cable_get_queue_item (cable, &cable->done);
331 if (i >= 0)
332 {
333 if (cable->done.data[i].action != URJ_TAP_CABLE_GET_TDO)
334 {
335 urj_warning (
336 _("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"),
337 cable->done.data[i].action, &cable->done, i);
338 urj_tap_cable_purge_queue (&cable->done, 1);
339 }
340 else
341 {
342 return cable->done.data[i].arg.value.val;
343 }
344 }
345 return cable->driver->get_tdo (cable);
346 }
347
348 int
urj_tap_cable_defer_get_tdo(urj_cable_t * cable)349 urj_tap_cable_defer_get_tdo (urj_cable_t *cable)
350 {
351 int i = urj_tap_cable_add_queue_item (cable, &cable->todo);
352 if (i < 0)
353 return URJ_STATUS_FAIL; /* report failure */
354 cable->todo.data[i].action = URJ_TAP_CABLE_GET_TDO;
355 urj_tap_cable_flush (cable, URJ_TAP_CABLE_OPTIONALLY);
356 return URJ_STATUS_OK; /* success */
357 }
358
359 int
urj_tap_cable_set_signal(urj_cable_t * cable,int mask,int val)360 urj_tap_cable_set_signal (urj_cable_t *cable, int mask, int val)
361 {
362 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
363 return cable->driver->set_signal (cable, mask, val);
364 }
365
366 int
urj_tap_cable_defer_set_signal(urj_cable_t * cable,int mask,int val)367 urj_tap_cable_defer_set_signal (urj_cable_t *cable, int mask, int val)
368 {
369 int i = urj_tap_cable_add_queue_item (cable, &cable->todo);
370 if (i < 0)
371 return URJ_STATUS_FAIL; /* report failure */
372 cable->todo.data[i].action = URJ_TAP_CABLE_SET_SIGNAL;
373 cable->todo.data[i].arg.value.mask = mask;
374 cable->todo.data[i].arg.value.val = val;
375 urj_tap_cable_flush (cable, URJ_TAP_CABLE_OPTIONALLY);
376 return URJ_STATUS_OK; /* success */
377 }
378
379 int
urj_tap_cable_get_signal(urj_cable_t * cable,urj_pod_sigsel_t sig)380 urj_tap_cable_get_signal (urj_cable_t *cable, urj_pod_sigsel_t sig)
381 {
382 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
383 return cable->driver->get_signal (cable, sig);
384 }
385
386 int
urj_tap_cable_get_signal_late(urj_cable_t * cable,urj_pod_sigsel_t sig)387 urj_tap_cable_get_signal_late (urj_cable_t *cable, urj_pod_sigsel_t sig)
388 {
389 int i;
390 urj_tap_cable_flush (cable, URJ_TAP_CABLE_TO_OUTPUT);
391 i = urj_tap_cable_get_queue_item (cable, &cable->done);
392 if (i >= 0)
393 {
394 if (cable->done.data[i].action != URJ_TAP_CABLE_GET_SIGNAL)
395 {
396 urj_warning (
397 _("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"),
398 cable->done.data[i].action, &cable->done, i);
399 urj_tap_cable_purge_queue (&cable->done, 1);
400 }
401 else if (cable->done.data[i].arg.value.sig != sig)
402 {
403 urj_warning (
404 _("Internal error: Got wrong signal's value from queue (%d? %p.%d)\n"),
405 cable->done.data[i].action, &cable->done, i);
406 urj_tap_cable_purge_queue (&cable->done, 1);
407 }
408 else
409 {
410 return cable->done.data[i].arg.value.val;
411 }
412 }
413 return cable->driver->get_signal (cable, sig);
414 }
415
416 int
urj_tap_cable_defer_get_signal(urj_cable_t * cable,urj_pod_sigsel_t sig)417 urj_tap_cable_defer_get_signal (urj_cable_t *cable, urj_pod_sigsel_t sig)
418 {
419 int i = urj_tap_cable_add_queue_item (cable, &cable->todo);
420 if (i < 0)
421 return URJ_STATUS_FAIL; /* report failure */
422 cable->todo.data[i].action = URJ_TAP_CABLE_GET_SIGNAL;
423 cable->todo.data[i].arg.value.sig = sig;
424 urj_tap_cable_flush (cable, URJ_TAP_CABLE_OPTIONALLY);
425 return URJ_STATUS_OK; /* success */
426 }
427
428 int
urj_tap_cable_transfer(urj_cable_t * cable,int len,char * in,char * out)429 urj_tap_cable_transfer (urj_cable_t *cable, int len, char *in, char *out)
430 {
431 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
432 return cable->driver->transfer (cable, len, in, out);
433 }
434
435 int
urj_tap_cable_transfer_late(urj_cable_t * cable,char * out)436 urj_tap_cable_transfer_late (urj_cable_t *cable, char *out)
437 {
438 int i;
439 urj_tap_cable_flush (cable, URJ_TAP_CABLE_TO_OUTPUT);
440 i = urj_tap_cable_get_queue_item (cable, &cable->done);
441
442 if (i >= 0 && cable->done.data[i].action == URJ_TAP_CABLE_TRANSFER)
443 {
444 #if 0
445 urj_log (URJ_LOG_LEVEL_DEBUG, "Got queue item (%p.%d) len=%d out=%p\n",
446 &cable->done, i,
447 cable->done.data[i].arg.xferred.len,
448 cable->done.data[i].arg.xferred.out);
449 #endif
450 if (out)
451 memcpy (out,
452 cable->done.data[i].arg.xferred.out,
453 cable->done.data[i].arg.xferred.len);
454 free (cable->done.data[i].arg.xferred.out);
455 return cable->done.data[i].arg.xferred.res;
456 }
457
458 if (cable->done.data[i].action != URJ_TAP_CABLE_TRANSFER)
459 {
460 urj_warning (
461 _("Internal error: Got wrong type of result from queue (#%d %p.%d)\n"),
462 cable->done.data[i].action, &cable->done, i);
463 urj_tap_cable_purge_queue (&cable->done, 1);
464 }
465 else
466 {
467 urj_warning (
468 _("Internal error: Wanted transfer result but none was queued\n"));
469 }
470 return 0;
471 }
472
473 int
urj_tap_cable_defer_transfer(urj_cable_t * cable,int len,char * in,char * out)474 urj_tap_cable_defer_transfer (urj_cable_t *cable, int len, char *in,
475 char *out)
476 {
477 char *ibuf, *obuf = NULL;
478 int i;
479
480 ibuf = malloc (len);
481 if (ibuf == NULL)
482 {
483 urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails",
484 (size_t) len);
485 return URJ_STATUS_FAIL;
486 }
487
488 if (out)
489 {
490 obuf = malloc (len);
491 if (obuf == NULL)
492 {
493 free (ibuf);
494 urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails",
495 (size_t) len);
496 return URJ_STATUS_FAIL;
497 }
498 }
499
500 i = urj_tap_cable_add_queue_item (cable, &cable->todo);
501 if (i < 0)
502 {
503 free (ibuf);
504 if (obuf)
505 free (obuf);
506 return URJ_STATUS_FAIL; /* report failure */
507 }
508
509 cable->todo.data[i].action = URJ_TAP_CABLE_TRANSFER;
510 cable->todo.data[i].arg.transfer.len = len;
511 if (in)
512 memcpy (ibuf, in, len);
513 cable->todo.data[i].arg.transfer.in = ibuf;
514 cable->todo.data[i].arg.transfer.out = obuf;
515 urj_tap_cable_flush (cable, URJ_TAP_CABLE_OPTIONALLY);
516 return URJ_STATUS_OK; /* success */
517 }
518
519 void
urj_tap_cable_set_frequency(urj_cable_t * cable,uint32_t new_frequency)520 urj_tap_cable_set_frequency (urj_cable_t *cable, uint32_t new_frequency)
521 {
522 urj_tap_cable_flush (cable, URJ_TAP_CABLE_COMPLETELY);
523 cable->driver->set_frequency (cable, new_frequency);
524 }
525
526 uint32_t
urj_tap_cable_get_frequency(urj_cable_t * cable)527 urj_tap_cable_get_frequency (urj_cable_t *cable)
528 {
529 return cable->frequency;
530 }
531
532 void
urj_tap_cable_wait(urj_cable_t * cable)533 urj_tap_cable_wait (urj_cable_t *cable)
534 {
535 int i;
536 volatile int j;
537
538 j = 0;
539 for (i = 0; i < cable->delay; ++i)
540 j = i;
541
542 /* Avoid gcc set-but-unused warnings */
543 cable->delay = j + 1;
544 }
545
546 static urj_cable_t *
urj_tap_cable_create(urj_chain_t * chain,const urj_cable_driver_t * driver)547 urj_tap_cable_create (urj_chain_t *chain, const urj_cable_driver_t *driver)
548 {
549 urj_cable_t *cable;
550
551 if (urj_bus)
552 urj_bus_buses_delete (urj_bus);
553
554 urj_tap_chain_disconnect (chain);
555
556 cable = calloc (1, sizeof (urj_cable_t));
557 if (!cable)
558 {
559 urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "calloc(%zd,%zd) fails",
560 (size_t) 1, sizeof (urj_cable_t));
561 return NULL;
562 }
563
564 cable->driver = driver;
565
566 return cable;
567 }
568
569 static int
urj_tap_cable_start(urj_chain_t * chain,urj_cable_t * cable)570 urj_tap_cable_start (urj_chain_t *chain, urj_cable_t *cable)
571 {
572 chain->cable = cable;
573
574 if (urj_tap_cable_init (chain->cable) != URJ_STATUS_OK)
575 {
576 urj_tap_chain_disconnect (chain);
577 return URJ_STATUS_FAIL;
578 }
579
580 urj_tap_trst_reset (chain);
581
582 return URJ_STATUS_OK;
583 }
584
585 urj_cable_t *
urj_tap_cable_parport_connect(urj_chain_t * chain,const urj_cable_driver_t * driver,urj_cable_parport_devtype_t devtype,const char * devname,const urj_param_t * params[])586 urj_tap_cable_parport_connect (urj_chain_t *chain, const urj_cable_driver_t *driver,
587 urj_cable_parport_devtype_t devtype,
588 const char *devname, const urj_param_t *params[])
589 {
590 urj_cable_t *cable;
591
592 if (driver->device_type != URJ_CABLE_DEVICE_PARPORT)
593 {
594 urj_error_set (URJ_ERROR_INVALID,
595 "parport cable needs parport_connect");
596 return NULL;
597 }
598
599 cable = urj_tap_cable_create (chain, driver);
600 if (cable == NULL)
601 return NULL;
602
603 if (cable->driver->connect.parport (cable, devtype, devname,
604 params) != URJ_STATUS_OK)
605 {
606 free (cable);
607 return NULL;
608 }
609
610 if (urj_tap_cable_start (chain, cable) != URJ_STATUS_OK)
611 return NULL;
612
613 return cable;
614 }
615
616 urj_cable_t *
urj_tap_cable_usb_connect(urj_chain_t * chain,const urj_cable_driver_t * driver,const urj_param_t * params[])617 urj_tap_cable_usb_connect (urj_chain_t *chain, const urj_cable_driver_t *driver,
618 const urj_param_t *params[])
619 {
620 urj_cable_t *cable;
621
622 if (driver->device_type != URJ_CABLE_DEVICE_USB)
623 {
624 urj_error_set (URJ_ERROR_INVALID, "USB cable needs usb_connect");
625 return NULL;
626 }
627
628 cable = urj_tap_cable_create (chain, driver);
629 if (cable == NULL)
630 return NULL;
631
632 if (cable->driver->connect.usb (cable, params) != URJ_STATUS_OK)
633 {
634 free (cable);
635 return NULL;
636 }
637
638 if (urj_tap_cable_start (chain, cable) != URJ_STATUS_OK)
639 return NULL;
640
641 return cable;
642 }
643
644 urj_cable_t *
urj_tap_cable_other_connect(urj_chain_t * chain,const urj_cable_driver_t * driver,const urj_param_t * params[])645 urj_tap_cable_other_connect (urj_chain_t *chain, const urj_cable_driver_t *driver,
646 const urj_param_t *params[])
647 {
648 urj_cable_t *cable;
649
650 if (driver->device_type != URJ_CABLE_DEVICE_OTHER)
651 {
652 urj_error_set (URJ_ERROR_INVALID, "'other' cable needs other_connect");
653 return NULL;
654 }
655
656 cable = urj_tap_cable_create (chain, driver);
657 if (cable == NULL)
658 return NULL;
659
660 if (cable->driver->connect.other (cable, params) != URJ_STATUS_OK)
661 {
662 free (cable);
663 return NULL;
664 }
665
666 if (urj_tap_cable_start (chain, cable) != URJ_STATUS_OK)
667 return NULL;
668
669 return cable;
670 }
671
672 static const urj_param_descr_t cable_param[] =
673 {
674 { URJ_CABLE_PARAM_KEY_PID, URJ_PARAM_TYPE_LU, "pid", },
675 { URJ_CABLE_PARAM_KEY_VID, URJ_PARAM_TYPE_LU, "vid", },
676 { URJ_CABLE_PARAM_KEY_DESC, URJ_PARAM_TYPE_STRING, "desc", },
677 { URJ_CABLE_PARAM_KEY_DRIVER, URJ_PARAM_TYPE_STRING, "driver", },
678 { URJ_CABLE_PARAM_KEY_BITMAP, URJ_PARAM_TYPE_STRING, "bitmap", },
679 { URJ_CABLE_PARAM_KEY_TDI, URJ_PARAM_TYPE_LU, "tdi", },
680 { URJ_CABLE_PARAM_KEY_TDO, URJ_PARAM_TYPE_LU, "tdo", },
681 { URJ_CABLE_PARAM_KEY_TMS, URJ_PARAM_TYPE_LU, "tms", },
682 { URJ_CABLE_PARAM_KEY_TCK, URJ_PARAM_TYPE_LU, "tck", },
683 { URJ_CABLE_PARAM_KEY_INTERFACE, URJ_PARAM_TYPE_LU, "interface", },
684 { URJ_CABLE_PARAM_KEY_FIRMWARE, URJ_PARAM_TYPE_STRING, "firmware", },
685 { URJ_CABLE_PARAM_KEY_INDEX, URJ_PARAM_TYPE_LU, "index", },
686 { URJ_CABLE_PARAM_KEY_TRST, URJ_PARAM_TYPE_LU, "trst", },
687 { URJ_CABLE_PARAM_KEY_RESET, URJ_PARAM_TYPE_LU, "reset", },
688 };
689
690 const urj_param_list_t urj_cable_param_list =
691 {
692 .list = cable_param,
693 .n = ARRAY_SIZE (cable_param),
694 };
695