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