1 /*
2  * $Id$
3  *
4  * Copyright (C) 2003 ETC s.r.o.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  *
21  * Written by Marcel Telka <marcel@telka.sk>, 2003.
22  *
23  */
24 
25 #include <sysdep.h>
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include <urjtag/cable.h>
32 #include <urjtag/chain.h>
33 #include "generic.h"
34 #include "generic_usbconn.h"
35 
36 #include <urjtag/cmd.h>
37 
38 static const urj_usbconn_cable_t * const urj_tap_cable_usbconn_cables[] = {
39 #define _URJ_USB(usb) &urj_tap_cable_usbconn_##usb,
40 #include "generic_usbconn_list.h"
41     NULL
42 };
43 
44 int
urj_tap_cable_generic_usbconn_connect(urj_cable_t * cable,const urj_param_t * params[])45 urj_tap_cable_generic_usbconn_connect (urj_cable_t *cable,
46                                        const urj_param_t *params[])
47 {
48     urj_usbconn_cable_t user_specified = {
49         NULL,                   /* no name */
50         NULL,                   /* no string pattern */
51         NULL,                   /* no specific driver */
52         -1,                     /* no VID */
53         -1,                     /* no PID */
54         0,                      /* default interface */
55     };
56 
57     urj_tap_cable_generic_params_t *cable_params;
58     urj_usbconn_t *conn = NULL;
59     int i;
60 
61     if (strcasecmp (cable->driver->name, "usb") != 0)
62     {
63         user_specified.name = cable->driver->name;
64     }
65 
66     if (params != NULL)
67         /* parse arguments beyond the cable name */
68         for (i = 0; params[i] != NULL; i++)
69         {
70             switch (params[i]->key)
71             {
72             case URJ_CABLE_PARAM_KEY_PID:
73                 user_specified.pid = params[i]->value.lu;
74                 break;
75             case URJ_CABLE_PARAM_KEY_VID:
76                 user_specified.vid = params[i]->value.lu;
77                 break;
78             case URJ_CABLE_PARAM_KEY_DESC:
79                 user_specified.desc = params[i]->value.string;
80                 break;
81             case URJ_CABLE_PARAM_KEY_DRIVER:
82                 user_specified.driver = params[i]->value.string;
83                 break;
84             case URJ_CABLE_PARAM_KEY_INTERFACE:
85                 user_specified.interface = params[i]->value.lu;
86                 break;
87             case URJ_CABLE_PARAM_KEY_INDEX:
88                 user_specified.index = params[i]->value.lu;
89                 break;
90             default:
91                 // hand these to the driver connect()
92                 break;
93             }
94         }
95 
96     /* search usbconn driver list */
97     for (i = 0; urj_tap_usbconn_drivers[i] && !conn; i++)
98     {
99         if ((user_specified.driver == NULL)
100             || (strcasecmp (user_specified.driver,
101                             urj_tap_usbconn_drivers[i]->type) == 0))
102         {
103             int j;
104 
105             /* search cable list */
106             for (j = 0; urj_tap_cable_usbconn_cables[j] && !conn; j++)
107             {
108                 if ((user_specified.name == NULL)
109                     || (strcasecmp (user_specified.name,
110                                     urj_tap_cable_usbconn_cables[j]->name) == 0))
111                 {
112                     if (strcasecmp (urj_tap_cable_usbconn_cables[j]->driver,
113                                     urj_tap_usbconn_drivers[i]->type) == 0)
114                     {
115                         urj_usbconn_cable_t cable_try =
116                             *(urj_tap_cable_usbconn_cables[j]);
117 
118                         if (user_specified.vid >= 0)
119                             cable_try.vid = user_specified.vid;
120                         if (user_specified.pid >= 0)
121                             cable_try.pid = user_specified.pid;
122                         if (user_specified.desc != 0)
123                             cable_try.desc = user_specified.desc;
124                         if (user_specified.interface != 0)
125                             cable_try.interface = user_specified.interface;
126                         if (user_specified.index != 0)
127                             cable_try.index = user_specified.index;
128 
129                         conn = urj_tap_usbconn_drivers[i]->connect (&cable_try,
130                                                                     params);
131                     }
132                 }
133             }
134         }
135     }
136 
137     if (!conn)
138     {
139         // @@@@ RFHH make this into either the error from drivers->connect,
140         // or urj_error_set (NOT_FOUND)
141         urj_log (URJ_LOG_LEVEL_ERROR,
142                  _("Couldn't connect to suitable USB device.\n"));
143         return URJ_STATUS_FAIL;
144     }
145     else
146     {
147         /* If some cables have been tried before a suitable cable is found,
148            urj_error will still contain an error from the last fail trial.
149            Clear it to avoid confusing error reporting.  */
150         urj_error_reset ();
151     }
152 
153     cable_params = malloc (sizeof (urj_tap_cable_generic_params_t));
154     if (!cable_params)
155     {
156         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, _("malloc(%zd) fails"),
157                        sizeof (urj_tap_cable_generic_params_t));
158         urj_tap_usbconn_drivers[i]->free (conn);
159         return URJ_STATUS_FAIL;
160     }
161 
162     cable->link.usb = conn;
163     cable->params = cable_params;
164     cable->chain = NULL;
165 
166     return URJ_STATUS_OK;
167 }
168 
169 void
urj_tap_cable_generic_usbconn_free(urj_cable_t * cable)170 urj_tap_cable_generic_usbconn_free (urj_cable_t *cable)
171 {
172     cable->link.usb->driver->free (cable->link.usb);
173     free (cable->params);
174     free (cable);
175 }
176 
177 void
urj_tap_cable_generic_usbconn_done(urj_cable_t * cable)178 urj_tap_cable_generic_usbconn_done (urj_cable_t *cable)
179 {
180     urj_tap_usbconn_close (cable->link.usb);
181 }
182 
183 void
urj_tap_cable_generic_usbconn_help_ex(urj_log_level_t ll,const char * cablename,const char * ex_short,const char * ex_desc)184 urj_tap_cable_generic_usbconn_help_ex (urj_log_level_t ll, const char *cablename,
185                                        const char *ex_short, const char *ex_desc)
186 {
187     int i;
188     const urj_usbconn_cable_t *conn;
189 
190     for (i = 0; urj_tap_cable_usbconn_cables[i]; ++i)
191     {
192         conn = urj_tap_cable_usbconn_cables[i];
193         if (strcasecmp (conn->name, cablename) == 0)
194             break;
195     }
196     if (!urj_tap_cable_usbconn_cables[i])
197     {
198         urj_warning (_("Unable to locate cable %s"), cablename);
199         return;
200     }
201 
202     urj_log (ll,
203              _("Usage: cable %s %s %s\n"
204                "\n" "%s%s"
205                "\n"
206                "Default:   vid=0x%x pid=0x%x driver=%s\n"
207                "\n"),
208              cablename,
209              URJ_TAP_CABLE_GENERIC_USBCONN_HELP_SHORT, ex_short,
210              URJ_TAP_CABLE_GENERIC_USBCONN_HELP_DESC, ex_desc,
211              conn->vid, conn->pid, conn->driver);
212 }
213 
214 void
urj_tap_cable_generic_usbconn_help(urj_log_level_t ll,const char * cablename)215 urj_tap_cable_generic_usbconn_help (urj_log_level_t ll, const char *cablename)
216 {
217     urj_tap_cable_generic_usbconn_help_ex (ll, cablename, "", "");
218 }
219 
220 int
urj_tap_cable_usb_probe(char * params[])221 urj_tap_cable_usb_probe (char *params[])
222 {
223     int i,j;
224     urj_usbconn_t *conn;
225 
226     urj_log_level_t old_level = urj_log_state.level;
227     urj_log_state.level = URJ_LOG_LEVEL_SILENT;
228 
229     for (i = 0; urj_tap_usbconn_drivers[i]; ++i)
230     {
231         for (j = 0; urj_tap_cable_usbconn_cables[j]; ++j)
232         {
233             urj_usbconn_cable_t cable_try = *(urj_tap_cable_usbconn_cables[j]);
234             conn = urj_tap_usbconn_drivers[i]->connect (&cable_try, NULL);
235             if (conn)
236             {
237                 urj_log_state.level = old_level;
238                 params[1] = (char *)urj_tap_cable_usbconn_cables[j]->name;
239                 urj_log (URJ_LOG_LEVEL_NORMAL,
240                          _("Found USB cable: %s\n"), params[1]);
241                 return URJ_STATUS_OK;
242             }
243         }
244     }
245 
246     urj_log_state.level = old_level;
247     return URJ_STATUS_FAIL;
248 }
249