| 151132e by Felipe Balbi at 2010-01-17 |
1 |
/* $(CROSS_COMPILE)gcc -Wall -O3 -g -lusb-1.0 -o cleware cleware.c */ |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
2 |
/** |
|
3 |
* cleware.c - Cleware USB-Controlled Power Switch |
|
4 |
* |
| f5acc8c by Felipe Balbi at 2010-01-13 |
5 |
* Copyright (C) 2010 Felipe Balbi <felipe.balbi@nokia.com> |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
6 |
* |
| f5acc8c by Felipe Balbi at 2010-01-13 |
7 |
* This file is part of the USB Verification Tools Project |
|
8 |
* |
|
9 |
* USB Tools is free software: you can redistribute it and/or modify |
|
10 |
* it under the terms of the GNU General Public Liicense as published by |
|
11 |
* the Free Software Foundation, either version 3 of the license, or |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
12 |
* (at your option) any later version. |
|
13 |
* |
| f5acc8c by Felipe Balbi at 2010-01-13 |
14 |
* USB Tools is distributed in the hope that it will be useful, |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
15 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| f5acc8c by Felipe Balbi at 2010-01-13 |
16 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
17 |
* GNU General Public License for more details. |
|
18 |
* |
|
19 |
* You should have received a copy of the GNU General Public License |
| f5acc8c by Felipe Balbi at 2010-01-13 |
20 |
* along with USB Tools. If not, see <http://www.gnu.org/licenses/>. |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
21 |
*/ |
|
22 |
|
|
23 |
#include <stdio.h> |
|
24 |
#include <string.h> |
|
25 |
#include <stdlib.h> |
|
26 |
#include <stdint.h> |
|
27 |
#include <unistd.h> |
|
28 |
#include <errno.h> |
| 8531a79 by Felipe Balbi at 2010-01-17 |
29 |
#include <getopt.h> |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
30 |
#include <libusb-1.0/libusb.h> |
|
31 |
|
| 1cd0433 by Felipe Balbi at 2010-01-17 |
32 |
/* |
|
33 |
* this application is known to work with the following |
|
34 |
* device: |
|
35 |
* |
|
36 |
* http://www.cleware.de/produkte/p-usbswitch-E.html |
|
37 |
*/ |
|
38 |
|
| 83cdba3 by Felipe Balbi at 2010-01-13 |
39 |
#define CLEWARE_VENDOR_ID 0x0d50 |
| 7f9aae3 by Felipe Balbi at 2010-01-17 |
40 |
#define CLEWARE_USB_SWITCH 0x0008 |
| 784055b by Felipe Balbi at 2010-06-17 |
41 |
#define CLEWARE_USB_SWITCH8 0x0030 |
|
42 |
|
|
43 |
#define CLEWARE_TYPE_SWITCH 0x00 |
|
44 |
#define CLEWARE_TYPE_CONTACT 0x03 |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
45 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
46 |
struct usb_device_id { |
|
47 |
unsigned idVendor; |
|
48 |
unsigned idProduct; |
| d260414 by Felipe Balbi at 2010-01-17 |
49 |
unsigned num_ports; |
| 784055b by Felipe Balbi at 2010-06-17 |
50 |
unsigned type; |
| 8c962cd by Felipe Balbi at 2010-01-17 |
51 |
}; |
|
52 |
|
| 784055b by Felipe Balbi at 2010-06-17 |
53 |
#define USB_DEVICE(v, p, n, t) \ |
| 8c962cd by Felipe Balbi at 2010-01-17 |
54 |
{ \ |
|
55 |
.idVendor = v, \ |
|
56 |
.idProduct = p, \ |
| 784055b by Felipe Balbi at 2010-06-17 |
57 |
.num_ports = n, \ |
|
58 |
.type = t \ |
| 8c962cd by Felipe Balbi at 2010-01-17 |
59 |
} |
|
60 |
|
|
61 |
static struct usb_device_id cleware_id[] = { |
| 784055b by Felipe Balbi at 2010-06-17 |
62 |
USB_DEVICE(CLEWARE_VENDOR_ID, CLEWARE_USB_SWITCH, 4, |
|
63 |
CLEWARE_TYPE_SWITCH), |
|
64 |
USB_DEVICE(CLEWARE_VENDOR_ID, CLEWARE_USB_SWITCH8, 8, |
|
65 |
CLEWARE_TYPE_CONTACT), |
| 8c962cd by Felipe Balbi at 2010-01-17 |
66 |
}; |
|
67 |
|
| d260414 by Felipe Balbi at 2010-01-17 |
68 |
static int num_ports; |
| 784055b by Felipe Balbi at 2010-06-17 |
69 |
static unsigned type; |
| 21fd614 by Felipe Balbi at 2010-01-13 |
70 |
static int debug; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
71 |
|
|
72 |
#define DBG(fmt, args...) \ |
|
73 |
if (debug) \ |
|
74 |
fprintf(stdout, fmt, ## args) |
|
75 |
|
|
76 |
#define TIMEOUT 1000 /* ms */ |
|
77 |
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
|
78 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
79 |
static int match_device_id(libusb_device *udev) |
|
80 |
{ |
|
81 |
struct libusb_device_descriptor desc; |
|
82 |
int match = 0; |
|
83 |
int ret; |
|
84 |
int i; |
|
85 |
|
|
86 |
ret = libusb_get_device_descriptor(udev, &desc); |
|
87 |
if (ret < 0) { |
|
88 |
DBG("%s: failed to get device descriptor\n", __func__); |
|
89 |
return ret; |
|
90 |
} |
|
91 |
|
| 8ec1c4f by Felipe Balbi at 2010-01-18 |
92 |
DBG("%s: got device desc for %04x:%04x\n", __func__, |
|
93 |
desc.idVendor, desc.idProduct); |
|
94 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
95 |
for (i = 0; i < ARRAY_SIZE(cleware_id); i++) { |
|
96 |
if ((desc.idVendor == cleware_id[i].idVendor) && |
| 9d27427 by Felipe Balbi at 2010-01-17 |
97 |
(desc.idProduct == cleware_id[i].idProduct)) { |
| 8c962cd by Felipe Balbi at 2010-01-17 |
98 |
match = 1; |
| d260414 by Felipe Balbi at 2010-01-17 |
99 |
num_ports = cleware_id[i].num_ports; |
| 784055b by Felipe Balbi at 2010-06-17 |
100 |
type = cleware_id[i].type; |
| 8ec1c4f by Felipe Balbi at 2010-01-18 |
101 |
DBG("%s: matched device %04x:%04x num_ports %d\n",__func__, |
|
102 |
desc.idVendor, desc.idProduct, num_ports); |
| 9d27427 by Felipe Balbi at 2010-01-17 |
103 |
} |
| 8c962cd by Felipe Balbi at 2010-01-17 |
104 |
} |
|
105 |
|
|
106 |
return match; |
|
107 |
} |
|
108 |
|
|
109 |
static int match_device_serial_number(libusb_device *udev, unsigned iSerial) |
|
110 |
{ |
|
111 |
struct libusb_device_descriptor desc; |
|
112 |
|
|
113 |
libusb_device_handle *tmp; |
|
114 |
|
| a1f70a2 by Felipe Balbi at 2010-01-18 |
115 |
unsigned int serialnumber; |
| 1651d0e by Felipe Balbi at 2010-01-18 |
116 |
unsigned char serial[256]; |
| 8c962cd by Felipe Balbi at 2010-01-17 |
117 |
int ret; |
|
118 |
|
| dd17376 by Felipe Balbi at 2010-01-17 |
119 |
ret = libusb_get_device_descriptor(udev, &desc); |
|
120 |
if (ret < 0) { |
|
121 |
DBG("%s: failed to get device descriptor\n", __func__); |
|
122 |
goto out0; |
|
123 |
} |
|
124 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
125 |
ret = libusb_open(udev, &tmp); |
|
126 |
if (ret < 0 || !tmp) { |
|
127 |
DBG("%s: couldn't open device\n", __func__); |
|
128 |
goto out0; |
|
129 |
} |
|
130 |
|
|
131 |
if (libusb_kernel_driver_active(tmp, 0)) { |
|
132 |
ret = libusb_detach_kernel_driver(tmp, 0); |
|
133 |
if (ret < 0) { |
|
134 |
DBG("%s: couldn't detach kernel driver\n", __func__); |
|
135 |
goto out1; |
|
136 |
} |
|
137 |
} |
|
138 |
|
| a1f70a2 by Felipe Balbi at 2010-01-18 |
139 |
ret = libusb_get_string_descriptor_ascii(tmp, desc.iSerialNumber, |
|
140 |
serial, sizeof(serial)); |
| 8c962cd by Felipe Balbi at 2010-01-17 |
141 |
|
|
142 |
if (ret < 0) { |
|
143 |
DBG("%s: failed to get string descriptor\n", __func__); |
|
144 |
goto out1; |
|
145 |
} |
|
146 |
|
| a1f70a2 by Felipe Balbi at 2010-01-18 |
147 |
ret = strtoul((const char *) &serial, NULL, 16); |
|
148 |
if (ret < 0) { |
|
149 |
DBG("%s: failed to get serial number\n", __func__); |
|
150 |
goto out2; |
|
151 |
} |
|
152 |
|
|
153 |
serialnumber = ret; |
|
154 |
|
|
155 |
if (serialnumber != iSerial) { |
| 8c962cd by Felipe Balbi at 2010-01-17 |
156 |
DBG("%s: not the serial number we want\n", __func__); |
|
157 |
goto out2; |
|
158 |
} |
|
159 |
|
|
160 |
out2: |
|
161 |
libusb_attach_kernel_driver(tmp, 0); |
|
162 |
|
|
163 |
out1: |
|
164 |
libusb_close(tmp); |
|
165 |
|
|
166 |
out0: |
|
167 |
return ret; |
|
168 |
} |
|
169 |
|
| 7c7cedc by Felipe Balbi at 2010-01-17 |
170 |
static void print_device_attributes(libusb_device *udev) |
|
171 |
{ |
|
172 |
struct libusb_device_descriptor desc; |
|
173 |
|
|
174 |
libusb_device_handle *tmp; |
|
175 |
|
|
176 |
int ret; |
|
177 |
|
|
178 |
unsigned char product[256] = { }; |
|
179 |
|
|
180 |
ret = libusb_get_device_descriptor(udev, &desc); |
|
181 |
if (ret < 0) { |
|
182 |
DBG("%s: failed to get device descriptor\n", __func__); |
|
183 |
return; |
|
184 |
} |
|
185 |
|
|
186 |
ret = libusb_open(udev, &tmp); |
|
187 |
if (ret < 0 || !tmp) { |
|
188 |
DBG("%s: couldn't open device\n", __func__); |
|
189 |
return; |
|
190 |
} |
|
191 |
|
|
192 |
if (libusb_kernel_driver_active(tmp, 0)) { |
|
193 |
ret = libusb_detach_kernel_driver(tmp, 0); |
|
194 |
if (ret < 0) { |
|
195 |
DBG("%s: couldn't detach kernel driver\n", __func__); |
|
196 |
libusb_close(tmp); |
|
197 |
return; |
|
198 |
} |
|
199 |
} |
|
200 |
|
|
201 |
if (desc.iProduct) { |
| c4f75c0 by Felipe Balbi at 2010-01-17 |
202 |
ret = libusb_get_string_descriptor_ascii(tmp, desc.iProduct, |
|
203 |
product, sizeof(product)); |
| 7c7cedc by Felipe Balbi at 2010-01-17 |
204 |
|
|
205 |
if (ret < 0) { |
|
206 |
DBG("%s: failed to get product name\n", __func__); |
| 8ec1c4f by Felipe Balbi at 2010-01-18 |
207 |
libusb_attach_kernel_driver(tmp, 0); |
| 7c7cedc by Felipe Balbi at 2010-01-17 |
208 |
libusb_close(tmp); |
|
209 |
return; |
|
210 |
} |
|
211 |
} |
|
212 |
|
|
213 |
fprintf(stdout, "%04x:%04x\t%s\n", desc.idVendor, desc.idProduct, |
|
214 |
product); |
| 8ec1c4f by Felipe Balbi at 2010-01-18 |
215 |
|
|
216 |
libusb_attach_kernel_driver(tmp, 0); |
| 7c7cedc by Felipe Balbi at 2010-01-17 |
217 |
} |
|
218 |
|
|
219 |
static void list_devices(libusb_device **list, ssize_t count) |
|
220 |
{ |
|
221 |
int i; |
|
222 |
|
|
223 |
for (i = 0; i < count; i++) { |
|
224 |
libusb_device *udev = list[i]; |
|
225 |
|
|
226 |
if (match_device_id(udev)) |
|
227 |
print_device_attributes(udev); |
|
228 |
} |
|
229 |
} |
|
230 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
231 |
static libusb_device_handle *find_and_open_device(libusb_device **list, |
|
232 |
ssize_t count, unsigned iSerial) |
|
233 |
{ |
|
234 |
libusb_device_handle *udevh = NULL; |
|
235 |
libusb_device *found = NULL; |
|
236 |
int ret; |
|
237 |
int i; |
|
238 |
|
| e42cce2 by Felipe Balbi at 2011-05-02 |
239 |
DBG("%s: iterating over %zd devices\n", __func__, count); |
| 8ec1c4f by Felipe Balbi at 2010-01-18 |
240 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
241 |
for (i = 0; i < count; i++) { |
|
242 |
libusb_device *udev = list[i]; |
|
243 |
|
|
244 |
ret = match_device_id(udev); |
| 35c7509 by Felipe Balbi at 2010-01-17 |
245 |
if (ret <= 0) { |
| 8c962cd by Felipe Balbi at 2010-01-17 |
246 |
DBG("%s: couldn't match device id\n", __func__); |
| 8ec1c4f by Felipe Balbi at 2010-01-18 |
247 |
continue; |
| 8c962cd by Felipe Balbi at 2010-01-17 |
248 |
} |
|
249 |
|
|
250 |
if (iSerial) { |
|
251 |
ret = match_device_serial_number(udev, iSerial); |
|
252 |
if (ret < 0) { |
|
253 |
DBG("%s: couldn't match serial number\n", __func__); |
|
254 |
found = NULL; |
|
255 |
break; |
|
256 |
} |
|
257 |
} |
|
258 |
|
|
259 |
found = udev; |
|
260 |
break; |
|
261 |
} |
|
262 |
|
| 1651d0e by Felipe Balbi at 2010-01-18 |
263 |
if (found) { |
|
264 |
ret = libusb_open(found, &udevh); |
|
265 |
if (ret < 0 || !found) { |
|
266 |
DBG("%s: couldn't open device\n", __func__); |
|
267 |
goto out; |
|
268 |
} |
| 8c962cd by Felipe Balbi at 2010-01-17 |
269 |
} |
|
270 |
|
| 35c7509 by Felipe Balbi at 2010-01-17 |
271 |
out: |
| 8c962cd by Felipe Balbi at 2010-01-17 |
272 |
return udevh; |
|
273 |
} |
|
274 |
|
| 83cdba3 by Felipe Balbi at 2010-01-13 |
275 |
static int find_and_claim_interface(libusb_device_handle *udevh) |
|
276 |
{ |
|
277 |
int ret; |
|
278 |
|
|
279 |
if (libusb_kernel_driver_active(udevh, 0)) { |
|
280 |
ret = libusb_detach_kernel_driver(udevh, 0); |
|
281 |
if (ret < 0) { |
|
282 |
DBG("%s: couldn't detach kernel driver\n", __func__); |
| ee17583 by Felipe Balbi at 2010-01-13 |
283 |
goto out0; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
284 |
} |
|
285 |
} |
|
286 |
|
|
287 |
ret = libusb_set_configuration(udevh, 1); |
|
288 |
if (ret < 0) { |
|
289 |
DBG("%s: couldn't set configuration 1\n", __func__); |
| ee17583 by Felipe Balbi at 2010-01-13 |
290 |
goto out0; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
291 |
} |
|
292 |
|
|
293 |
ret = libusb_claim_interface(udevh, 0); |
|
294 |
if (ret < 0) { |
|
295 |
DBG("%s: couldn't claim interface 0\n", __func__); |
| ee17583 by Felipe Balbi at 2010-01-13 |
296 |
goto out0; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
297 |
} |
|
298 |
|
|
299 |
ret = libusb_set_interface_alt_setting(udevh, 0, 0); |
|
300 |
if (ret < 0) { |
|
301 |
DBG("%s: couldn't set alternate setting 0\n", __func__); |
| ee17583 by Felipe Balbi at 2010-01-13 |
302 |
goto out1; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
303 |
} |
|
304 |
|
|
305 |
return 0; |
|
306 |
|
| ee17583 by Felipe Balbi at 2010-01-13 |
307 |
out1: |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
308 |
libusb_release_interface(udevh, 0); |
|
309 |
|
| ee17583 by Felipe Balbi at 2010-01-13 |
310 |
out0: |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
311 |
return ret; |
|
312 |
} |
|
313 |
|
|
314 |
static void release_interface(libusb_device_handle *udevh) |
|
315 |
{ |
|
316 |
libusb_release_interface(udevh, 0); |
|
317 |
} |
|
318 |
|
| 2487064 by Felipe Balbi at 2010-01-17 |
319 |
static int set_led(libusb_device_handle *udevh, unsigned led, unsigned on) |
|
320 |
{ |
|
321 |
unsigned char data[3]; |
|
322 |
|
|
323 |
data[0] = 0x00; |
|
324 |
data[1] = led; |
|
325 |
data[2] = on ? 0x00 : 0x0f; |
|
326 |
|
| 2b7fdbe by Felipe Balbi at 2010-01-17 |
327 |
return libusb_control_transfer(udevh, 0x21, 0x09, 0x200, 0x00, |
|
328 |
data, sizeof(data), TIMEOUT); |
| 2487064 by Felipe Balbi at 2010-01-17 |
329 |
} |
|
330 |
|
| e93df1d by Felipe Balbi at 2010-06-17 |
331 |
static inline int set_switch8(libusb_device_handle *udevh, unsigned port, unsigned on) |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
332 |
{ |
| 784055b by Felipe Balbi at 2010-06-17 |
333 |
unsigned char data[5]; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
334 |
|
| 784055b by Felipe Balbi at 2010-06-17 |
335 |
data[0] = type; |
| e93df1d by Felipe Balbi at 2010-06-17 |
336 |
data[1] = 0x00; |
|
337 |
data[2] = on ? (1 << port) : 0x00; |
|
338 |
data[3] = 0x00; |
|
339 |
data[4] = (1 << port); |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
340 |
|
| e93df1d by Felipe Balbi at 2010-06-17 |
341 |
return libusb_control_transfer(udevh, 0x21, 0x09, 0x200, 0x00, |
|
342 |
data, sizeof(data), TIMEOUT); |
|
343 |
} |
| 784055b by Felipe Balbi at 2010-06-17 |
344 |
|
| e93df1d by Felipe Balbi at 2010-06-17 |
345 |
static inline int set_switch4(libusb_device_handle *udevh, unsigned port, unsigned on) |
|
346 |
{ |
|
347 |
unsigned char data[3]; |
| 784055b by Felipe Balbi at 2010-06-17 |
348 |
|
| e93df1d by Felipe Balbi at 2010-06-17 |
349 |
data[0] = type; |
|
350 |
data[1] = port + 0x10; |
|
351 |
data[2] = on & 0x01; |
|
352 |
|
|
353 |
return libusb_control_transfer(udevh, 0x21, 0x09, 0x200, 0x00, |
|
354 |
data, 3, TIMEOUT); |
|
355 |
} |
| 784055b by Felipe Balbi at 2010-06-17 |
356 |
|
| e93df1d by Felipe Balbi at 2010-06-17 |
357 |
static int set_switch(libusb_device_handle *udevh, unsigned port, unsigned on) |
|
358 |
{ |
|
359 |
if (type == CLEWARE_TYPE_SWITCH) { |
|
360 |
return set_switch4(udevh, port, on); |
|
361 |
} else if (type == CLEWARE_TYPE_CONTACT) { |
|
362 |
return set_switch8(udevh, port, on); |
| 784055b by Felipe Balbi at 2010-06-17 |
363 |
} else { |
|
364 |
DBG("%s: unsupported type\n", __func__); |
|
365 |
return -EINVAL; |
|
366 |
} |
| 2487064 by Felipe Balbi at 2010-01-17 |
367 |
} |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
368 |
|
| 2487064 by Felipe Balbi at 2010-01-17 |
369 |
static int set_power(libusb_device_handle *udevh, unsigned port, unsigned on) |
|
370 |
{ |
|
371 |
int ret; |
|
372 |
|
| fe249ce by Felipe Balbi at 2010-05-12 |
373 |
if (port > num_ports) { |
| d260414 by Felipe Balbi at 2010-01-17 |
374 |
DBG("%s: this device doesn't have that many ports\n", __func__); |
|
375 |
return -EINVAL; |
|
376 |
} |
|
377 |
|
| fe249ce by Felipe Balbi at 2010-05-12 |
378 |
ret = set_switch(udevh, port - 1, on); |
| 2487064 by Felipe Balbi at 2010-01-17 |
379 |
if (ret < 0) { |
| 2b7fdbe by Felipe Balbi at 2010-01-17 |
380 |
DBG("%s: failed to toggle switch %d\n", __func__, port); |
| 298d56d by Felipe Balbi at 2010-01-17 |
381 |
return ret; |
| 2487064 by Felipe Balbi at 2010-01-17 |
382 |
} |
|
383 |
|
| fe249ce by Felipe Balbi at 2010-05-12 |
384 |
if (port == 1) { |
|
385 |
ret = set_led(udevh, port - 1, on); |
| daf88a1 by Felipe Balbi at 2010-01-17 |
386 |
if (ret < 0) { |
| ca10c13 by Felipe Balbi at 2010-01-18 |
387 |
DBG("%s: couldn't toggle led %d\n", __func__, port); |
| 298d56d by Felipe Balbi at 2010-01-17 |
388 |
return ret; |
| daf88a1 by Felipe Balbi at 2010-01-17 |
389 |
} |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
390 |
|
| fe249ce by Felipe Balbi at 2010-05-12 |
391 |
ret = set_led(udevh, port, !on); |
| daf88a1 by Felipe Balbi at 2010-01-17 |
392 |
if (ret < 0) { |
| ca10c13 by Felipe Balbi at 2010-01-18 |
393 |
DBG("%s: couldn't toggle led %d\n", __func__, port + 1); |
| 298d56d by Felipe Balbi at 2010-01-17 |
394 |
return ret; |
| daf88a1 by Felipe Balbi at 2010-01-17 |
395 |
} |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
396 |
} |
|
397 |
|
| 2487064 by Felipe Balbi at 2010-01-17 |
398 |
return 0; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
399 |
} |
|
400 |
|
| cb74fa0 by Felipe Balbi at 2010-01-17 |
401 |
static void usage(char *name) |
|
402 |
{ |
| 8531a79 by Felipe Balbi at 2010-01-17 |
403 |
fprintf(stdout, "usage: %s [-0 | -1] [-s SerialNumber] [-d] [-h]\n\ |
| e98b6e5 by Felipe Balbi at 2010-05-12 |
404 |
-0, --off Switch it off\n\ |
|
405 |
-1, --on Switch it on\n\ |
| 8531a79 by Felipe Balbi at 2010-01-17 |
406 |
-s, --serial-number Device's serial number\n\ |
| fe249ce by Felipe Balbi at 2010-05-12 |
407 |
-p, --port port number\n\ |
| 8531a79 by Felipe Balbi at 2010-01-17 |
408 |
-d, --debug Enable debugging\n\ |
|
409 |
-h, --help Print this\n", name); |
| cb74fa0 by Felipe Balbi at 2010-01-17 |
410 |
} |
|
411 |
|
| 8531a79 by Felipe Balbi at 2010-01-17 |
412 |
#define OPTION(n, h, v) \ |
|
413 |
{ \ |
|
414 |
.name = #n, \ |
|
415 |
.has_arg = h, \ |
|
416 |
.val = v, \ |
|
417 |
} |
|
418 |
|
|
419 |
static struct option cleware_opts[] = { |
|
420 |
OPTION("on", 0, '0'), |
|
421 |
OPTION("off", 0, '1'), |
|
422 |
OPTION("serial-number", 1, 's'), |
| 94132c1 by Felipe Balbi at 2010-01-17 |
423 |
OPTION("port", 1, 'p'), |
| 7c7cedc by Felipe Balbi at 2010-01-17 |
424 |
OPTION("list", 0, 'l'), |
| 8531a79 by Felipe Balbi at 2010-01-17 |
425 |
OPTION("debug", 0, 'd'), |
|
426 |
OPTION("help", 0, 'h'), |
|
427 |
{ } /* Terminating entry */ |
|
428 |
}; |
|
429 |
|
| 83cdba3 by Felipe Balbi at 2010-01-13 |
430 |
int main(int argc, char *argv[]) |
|
431 |
{ |
|
432 |
libusb_context *context; |
|
433 |
libusb_device_handle *udevh; |
| 8c962cd by Felipe Balbi at 2010-01-17 |
434 |
libusb_device **list; |
|
435 |
|
| 8c695c0 by Felipe Balbi at 2010-06-17 |
436 |
unsigned port = 1; |
| 8c962cd by Felipe Balbi at 2010-01-17 |
437 |
unsigned iSerial = 0; |
| 7c7cedc by Felipe Balbi at 2010-01-17 |
438 |
unsigned list_devs = 0; |
| 8c962cd by Felipe Balbi at 2010-01-17 |
439 |
|
|
440 |
ssize_t count; |
|
441 |
|
| 83cdba3 by Felipe Balbi at 2010-01-13 |
442 |
int ret = 0; |
| 8531a79 by Felipe Balbi at 2010-01-17 |
443 |
int on = 0; |
|
444 |
|
|
445 |
while (ARRAY_SIZE(cleware_opts)) { |
|
446 |
int optidx = 0; |
|
447 |
int opt; |
|
448 |
|
| 94132c1 by Felipe Balbi at 2010-01-17 |
449 |
opt = getopt_long(argc, argv, "l01p:s:dh", cleware_opts, &optidx); |
| 8531a79 by Felipe Balbi at 2010-01-17 |
450 |
if (opt < 0) |
|
451 |
break; |
|
452 |
|
|
453 |
switch (opt) { |
| 7c7cedc by Felipe Balbi at 2010-01-17 |
454 |
case 'l': |
|
455 |
list_devs = 1; |
|
456 |
break; |
| 8531a79 by Felipe Balbi at 2010-01-17 |
457 |
case '0': |
|
458 |
on = 0; |
|
459 |
break; |
|
460 |
case '1': |
|
461 |
on = 1; |
|
462 |
break; |
| 94132c1 by Felipe Balbi at 2010-01-17 |
463 |
case 'p': |
|
464 |
port = atoi(optarg); |
|
465 |
break; |
| 8531a79 by Felipe Balbi at 2010-01-17 |
466 |
case 's': |
| 9fb897b by Felipe Balbi at 2010-01-18 |
467 |
iSerial = strtoul(optarg, NULL, 16); |
| 8531a79 by Felipe Balbi at 2010-01-17 |
468 |
break; |
|
469 |
case 'd': |
|
470 |
debug = 1; |
|
471 |
break; |
|
472 |
case 'h': /* FALLTHROUGH */ |
|
473 |
default: |
|
474 |
usage(argv[0]); |
|
475 |
return 0; |
|
476 |
} |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
477 |
} |
|
478 |
|
|
479 |
/* initialize libusb */ |
|
480 |
libusb_init(&context); |
|
481 |
|
|
482 |
/* get rid of debug messages */ |
|
483 |
libusb_set_debug(context, 0); |
|
484 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
485 |
count = libusb_get_device_list(context, &list); |
|
486 |
if (count < 0) { |
|
487 |
DBG("%s: couldn't get device list\n", __func__); |
| 27c5b12 by Felipe Balbi at 2010-01-17 |
488 |
ret = count; |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
489 |
goto out1; |
|
490 |
} |
|
491 |
|
| 7c7cedc by Felipe Balbi at 2010-01-17 |
492 |
if (list_devs) { |
|
493 |
list_devices(list, count); |
|
494 |
goto out1; |
|
495 |
} |
|
496 |
|
| 8c962cd by Felipe Balbi at 2010-01-17 |
497 |
udevh = find_and_open_device(list, count, iSerial); |
|
498 |
if (!udevh) { |
|
499 |
DBG("%s: couldn't find a suitable device\n", __func__); |
|
500 |
goto out2; |
|
501 |
} |
|
502 |
|
| 83cdba3 by Felipe Balbi at 2010-01-13 |
503 |
ret = find_and_claim_interface(udevh); |
|
504 |
if (ret < 0) { |
| c5e2691 by Felipe Balbi at 2010-01-17 |
505 |
DBG("%s: couldn't claim interface\n", __func__); |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
506 |
goto out2; |
|
507 |
} |
|
508 |
|
| 2487064 by Felipe Balbi at 2010-01-17 |
509 |
ret = set_power(udevh, port, on); |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
510 |
if (ret < 0) { |
|
511 |
DBG("%s: couldn't switch power %s\n", __func__, |
| 90bc8b4 by Felipe Balbi at 2010-01-17 |
512 |
on ? "on" : "off"); |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
513 |
goto out3; |
|
514 |
} |
|
515 |
|
|
516 |
out3: |
|
517 |
release_interface(udevh); |
|
518 |
|
|
519 |
out2: |
|
520 |
libusb_close(udevh); |
| 8c962cd by Felipe Balbi at 2010-01-17 |
521 |
libusb_free_device_list(list, 1); |
| 83cdba3 by Felipe Balbi at 2010-01-13 |
522 |
|
|
523 |
out1: |
|
524 |
libusb_exit(context); |
|
525 |
|
|
526 |
return ret; |
|
527 |
} |
|
528 |
|