File: Device.java

package info (click to toggle)
libusb-java 0.8%2Bztex20090101-7
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, stretch
  • size: 416 kB
  • ctags: 810
  • sloc: java: 1,102; ansic: 605; makefile: 98; sh: 29
file content (763 lines) | stat: -rw-r--r-- 24,142 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
/* 
 * Java libusb wrapper
 * Copyright (c) 2005-2006 Andreas Schlaepfer <spandi at users.sourceforge.net>
 *
 * http://libusbjava.sourceforge.net
 * This library is covered by the LGPL, read LGPL.txt for details.
 */
package ch.ntb.usb;

import java.util.logging.Level;
import java.util.logging.Logger;

import ch.ntb.usb.logger.LogUtil;

/**
 * This class represents an USB device.<br>
 * To get an instance of an USB device use <code>USB.getDevice(...)</code>.
 * 
 */
public class Device {

	private static final Logger logger = LogUtil.getLogger("ch.ntb.usb");

	private int maxPacketSize;

	/**
	 * Mandatory identification values for the device.
	 */
	private int idVendor, idProduct;

	/**
	 * Optional identification value for the device (e.g. if there are multiple
	 * devices with the same vendor and product id).
	 */
	private String filename;

	private int dev_configuration, dev_interface, dev_altinterface;

	private long usbDevHandle;

	private boolean resetOnFirstOpen, resetDone;

	private int resetTimeout = 2000;

	private Usb_Device dev;

	protected Device(short idVendor, short idProduct) {
		resetOnFirstOpen = false;
		resetDone = false;
		maxPacketSize = -1;
		this.idVendor = idVendor;
		this.idProduct = idProduct;
		this.filename = null;
	}

	protected Device(short idVendor, short idProduct, String filename) {
		resetOnFirstOpen = false;
		resetDone = false;
		maxPacketSize = -1;
		this.idVendor = idVendor;
		this.idProduct = idProduct;
		this.filename = filename;
	}

	private void updateMaxPacketSize(Usb_Device device) throws USBException {
		maxPacketSize = -1;
		Usb_Config_Descriptor[] confDesc = device.getConfig();
		for (int i = 0; i < confDesc.length; i++) {
			Usb_Interface[] int_ = confDesc[i].getInterface();
			for (int j = 0; j < int_.length; j++) {
				Usb_Interface_Descriptor[] intDesc = int_[j].getAltsetting();
				for (int k = 0; k < intDesc.length; k++) {
					Usb_Endpoint_Descriptor[] epDesc = intDesc[k].getEndpoint();
					for (int l = 0; l < epDesc.length; l++) {
						maxPacketSize = Math.max(epDesc[l].getWMaxPacketSize(),
								maxPacketSize);
					}
				}
			}
		}
		if (maxPacketSize <= 0) {
			throw new USBException(
					"No USB endpoints found. Check the device configuration");
		}
	}

	/**
	 * Initializes the device. The parameters <code>idVendor</code> and
	 * <code>idProduct</code> are mandatory. The parameter
	 * <code>filename</code> is optional.
	 */
	private Usb_Device initDevice(int idVendorParam, int idProductParam,
			String filename) throws USBException {
		Usb_Bus bus = USB.getBus();

		Usb_Device device = null;
		// search for device
		while (bus != null) {
			device = bus.getDevices();
			while (device != null) {
				Usb_Device_Descriptor devDesc = device.getDescriptor();
				if (filename != null
						&& filename.compareTo(device.getFilename()) == 0
						&& devDesc.getIdVendor() == idVendorParam
						&& devDesc.getIdProduct() == idProductParam) {
					// idVendor, idProduct and filename
					logger.info("Device found: " + device.getFilename());
					updateMaxPacketSize(device);
					return device;
				} else if (devDesc.getIdVendor() == idVendorParam
						&& devDesc.getIdProduct() == idProductParam) {
					// only idVendor and idProduct
					logger.info("Device found: " + device.getFilename());
					updateMaxPacketSize(device);
					return device;
				}
				device = device.getNext();
			}
			bus = bus.getNext();
		}
		return null;
	}

	/**
	 * Updates the device and descriptor information from the bus.<br>
	 * The descriptors can be read with {@link #getDeviceDescriptor()} and
	 * {@link #getConfigDescriptors()}.
	 * 
	 * @throws USBException
	 */
	public void updateDescriptors() throws USBException {
		dev = initDevice(idVendor, idProduct, filename);
	}

	/**
	 * Returns the device descriptor associated with this device.<br>
	 * The descriptor is updated by calling {@link #updateDescriptors()} or
	 * {@link #open(int, int, int)}.
	 * 
	 * @return the device descriptor associated with this device or
	 *         <code>null</code>
	 */
	public Usb_Device_Descriptor getDeviceDescriptor() {
		if (dev == null) {
			return null;
		}
		return dev.getDescriptor();
	}

	/**
	 * Returns the configuration descriptors associated with this device.<br>
	 * The descriptors are updated by calling {@link #updateDescriptors()} or
	 * {@link #open(int, int, int)}.
	 * 
	 * @return the configuration descriptors associated with this device or
	 *         <code>null</code>
	 */
	public Usb_Config_Descriptor[] getConfigDescriptors() {
		if (dev == null) {
			return null;
		}
		return dev.getConfig();
	}

	/**
	 * Opens the device and claims the specified configuration, interface and
	 * altinterface.<br>
	 * First the bus is enumerated. If the device is found its descriptors are
	 * read and the <code>maxPacketSize</code> value is updated. If no
	 * endpoints are found in the descriptors an exception is thrown.
	 * 
	 * @param configuration
	 *            the configuration, see
	 *            {@link Usb_Config_Descriptor#getBConfigurationValue()}
	 * @param interface_
	 *            the interface, see
	 *            {@link Usb_Interface_Descriptor#getBInterfaceNumber()}
	 * @param altinterface
	 *            the alternate interface, see
	 *            {@link Usb_Interface_Descriptor#getBAlternateSetting()}. If
	 *            no alternate interface must be set <i>-1</i> can be used.
	 * @throws USBException
	 */
	public void open(int configuration, int interface_, int altinterface)
			throws USBException {
		this.dev_configuration = configuration;
		this.dev_interface = interface_;
		this.dev_altinterface = altinterface;

		if (usbDevHandle != 0) {
			throw new USBException("device opened, close or reset first");
		}

		dev = initDevice(idVendor, idProduct, filename);

		if (dev != null) {
			long res = LibusbJava.usb_open(dev);
			if (res == 0) {
				throw new USBException("LibusbJava.usb_open: "
						+ LibusbJava.usb_strerror());
			}
			usbDevHandle = res;
		}

		if (dev == null || usbDevHandle == 0) {
			throw new USBException("USB device with idVendor 0x"
					+ Integer.toHexString(idVendor & 0xFFFF)
					+ " and idProduct 0x"
					+ Integer.toHexString(idProduct & 0xFFFF) + " not found");
		}
		claim_interface(usbDevHandle, configuration, interface_, altinterface);
		if (resetOnFirstOpen & !resetDone) {
			logger.info("reset on first open");
			resetDone = true;
			reset();
			try {
				Thread.sleep(resetTimeout);
			} catch (InterruptedException e) {
				//
			}
			open(configuration, interface_, altinterface);
		}
	}

	/**
	 * Release the claimed interface and close the opened device.<br>
	 * 
	 * @throws USBException
	 */
	public void close() throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		release_interface(usbDevHandle, dev_interface);
		if (LibusbJava.usb_close(usbDevHandle) < 0) {
			usbDevHandle = 0;
			throw new USBException("LibusbJava.usb_close: "
					+ LibusbJava.usb_strerror());
		}
		usbDevHandle = 0;
		maxPacketSize = -1;
		logger.info("device closed");
	}

	/**
	 * Sends an USB reset to the device. The device handle will no longer be
	 * valid. To use the device again, {@link #open(int, int, int)} must be
	 * called.
	 * 
	 * @throws USBException
	 */
	public void reset() throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		release_interface(usbDevHandle, dev_interface);
		if (LibusbJava.usb_reset(usbDevHandle) < 0) {
			usbDevHandle = 0;
			throw new USBException("LibusbJava.usb_reset: "
					+ LibusbJava.usb_strerror());
		}
		usbDevHandle = 0;
		logger.info("device reset");
	}

	/**
	 * Write data to the device using a bulk transfer.<br>
	 * 
	 * @param out_ep_address
	 *            endpoint address to write to
	 * @param data
	 *            data to write to this endpoint
	 * @param size
	 *            size of the data
	 * @param timeout
	 *            amount of time in ms the device will try to send the data
	 *            until a timeout exception is thrown
	 * @param reopenOnTimeout
	 *            if set to true, the device will try to open the connection and
	 *            send the data again before a timeout exception is thrown
	 * @return the actual number of bytes written
	 * @throws USBException
	 */
	public int writeBulk(int out_ep_address, byte[] data, int size,
			int timeout, boolean reopenOnTimeout) throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		if (data == null) {
			throw new USBException("data must not be null");
		}
		if (size <= 0 || size > data.length) {
			throw new ArrayIndexOutOfBoundsException("invalid size: " + size);
		}
		int lenWritten = LibusbJava.usb_bulk_write(usbDevHandle,
				out_ep_address, data, size, timeout);
		if (lenWritten < 0) {
			if (lenWritten == LibusbJava.ERROR_TIMEDOUT) {
				// try to reopen the device and send the data again
				if (reopenOnTimeout) {
					logger.info("try to reopen");
					reset();
					open(dev_configuration, dev_interface, dev_altinterface);
					return writeBulk(out_ep_address, data, size, timeout, false);
				}
				throw new USBTimeoutException("LibusbJava.usb_bulk_write: "
						+ LibusbJava.usb_strerror());
			}
			throw new USBException("LibusbJava.usb_bulk_write: "
					+ LibusbJava.usb_strerror());
		}

		logger.info("length written: " + lenWritten);
		if (logger.isLoggable(Level.FINEST)) {
			StringBuffer sb = new StringBuffer("bulkwrite, ep 0x"
					+ Integer.toHexString(out_ep_address) + ": " + lenWritten
					+ " Bytes sent: ");
			for (int i = 0; i < lenWritten; i++) {
				sb.append("0x" + String.format("%1$02X", data[i]) + " ");
			}
			logger.info(sb.toString());
		}
		return lenWritten;
	}

	/**
	 * Read data from the device using a bulk transfer.<br>
	 * 
	 * @param in_ep_address
	 *            endpoint address to read from
	 * @param data
	 *            data buffer for the data to be read
	 * @param size
	 *            the maximum requested data size
	 * @param timeout
	 *            amount of time in ms the device will try to receive data until
	 *            a timeout exception is thrown
	 * @param reopenOnTimeout
	 *            if set to true, the device will try to open the connection and
	 *            receive the data again before a timeout exception is thrown
	 * @return the actual number of bytes read
	 * @throws USBException
	 */
	public int readBulk(int in_ep_address, byte[] data, int size, int timeout,
			boolean reopenOnTimeout) throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		if (data == null) {
			throw new USBException("data must not be null");
		}
		if (size <= 0 || size > data.length) {
			throw new ArrayIndexOutOfBoundsException("invalid size: " + size);
		}
		int lenRead = LibusbJava.usb_bulk_read(usbDevHandle, in_ep_address,
				data, size, timeout);
		if (lenRead < 0) {
			if (lenRead == LibusbJava.ERROR_TIMEDOUT) {
				// try to reopen the device and send the data again
				if (reopenOnTimeout) {
					logger.info("try to reopen");
					reset();
					open(dev_configuration, dev_interface, dev_altinterface);
					return readBulk(in_ep_address, data, size, timeout, false);
				}
				throw new USBTimeoutException("LibusbJava.usb_bulk_read: "
						+ LibusbJava.usb_strerror());
			}
			throw new USBException("LibusbJava.usb_bulk_read: "
					+ LibusbJava.usb_strerror());
		}

		logger.info("length read: " + lenRead);
		if (logger.isLoggable(Level.FINEST)) {
			StringBuffer sb = new StringBuffer("bulkread, ep 0x"
					+ Integer.toHexString(in_ep_address) + ": " + lenRead
					+ " Bytes received: ");
			for (int i = 0; i < lenRead; i++) {
				sb.append("0x" + String.format("%1$02X", data[i]) + " ");
			}
			logger.info(sb.toString());
		}
		return lenRead;
	}

	/**
	 * Write data to the device using a interrupt transfer.<br>
	 * 
	 * @param out_ep_address
	 *            endpoint address to write to
	 * @param data
	 *            data to write to this endpoint
	 * @param size
	 *            size of the data
	 * @param timeout
	 *            amount of time in ms the device will try to send the data
	 *            until a timeout exception is thrown
	 * @param reopenOnTimeout
	 *            if set to true, the device will try to open the connection and
	 *            send the data again before a timeout exception is thrown
	 * @return the actual number of bytes written
	 * @throws USBException
	 */
	public int writeInterrupt(int out_ep_address, byte[] data, int size,
			int timeout, boolean reopenOnTimeout) throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		if (data == null) {
			throw new USBException("data must not be null");
		}
		if (size <= 0 || size > data.length) {
			throw new ArrayIndexOutOfBoundsException("invalid size: " + size);
		}
		int lenWritten = LibusbJava.usb_interrupt_write(usbDevHandle,
				out_ep_address, data, size, timeout);
		if (lenWritten < 0) {
			if (lenWritten == LibusbJava.ERROR_TIMEDOUT) {
				// try to reopen the device and send the data again
				if (reopenOnTimeout) {
					logger.info("try to reopen");
					reset();
					open(dev_configuration, dev_interface, dev_altinterface);
					return writeInterrupt(out_ep_address, data, size, timeout,
							false);
				}
				throw new USBTimeoutException(
						"LibusbJava.usb_interrupt_write: "
								+ LibusbJava.usb_strerror());
			}
			throw new USBException("LibusbJava.usb_interrupt_write: "
					+ LibusbJava.usb_strerror());
		}

		logger.info("length written: " + lenWritten);
		if (logger.isLoggable(Level.FINEST)) {
			StringBuffer sb = new StringBuffer("interruptwrite, ep 0x"
					+ Integer.toHexString(out_ep_address) + ": " + lenWritten
					+ " Bytes sent: ");
			for (int i = 0; i < lenWritten; i++) {
				sb.append("0x" + String.format("%1$02X", data[i]) + " ");
			}
			logger.info(sb.toString());
		}
		return lenWritten;
	}

	/**
	 * Read data from the device using a interrupt transfer.<br>
	 * 
	 * @param in_ep_address
	 *            endpoint address to read from
	 * @param data
	 *            data buffer for the data to be read
	 * @param size
	 *            the maximum requested data size
	 * @param timeout
	 *            amount of time in ms the device will try to receive data until
	 *            a timeout exception is thrown
	 * @param reopenOnTimeout
	 *            if set to true, the device will try to open the connection and
	 *            receive the data again before a timeout exception is thrown
	 * @return the actual number of bytes read
	 * @throws USBException
	 */
	public int readInterrupt(int in_ep_address, byte[] data, int size,
			int timeout, boolean reopenOnTimeout) throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		if (data == null) {
			throw new USBException("data must not be null");
		}
		if (size <= 0 || size > data.length) {
			throw new ArrayIndexOutOfBoundsException("invalid size: " + size);
		}
		int lenRead = LibusbJava.usb_interrupt_read(usbDevHandle,
				in_ep_address, data, size, timeout);
		if (lenRead < 0) {
			if (lenRead == LibusbJava.ERROR_TIMEDOUT) {
				// try to reopen the device and send the data again
				if (reopenOnTimeout) {
					logger.info("try to reopen");
					reset();
					open(dev_configuration, dev_interface, dev_altinterface);
					return readInterrupt(in_ep_address, data, size, timeout,
							false);
				}
				throw new USBTimeoutException("LibusbJava.usb_interrupt_read: "
						+ LibusbJava.usb_strerror());
			}
			throw new USBException("LibusbJava.usb_interrupt_read: "
					+ LibusbJava.usb_strerror());
		}

		logger.info("length read: " + lenRead);
		if (logger.isLoggable(Level.FINEST)) {
			StringBuffer sb = new StringBuffer("interrupt, ep 0x"
					+ Integer.toHexString(in_ep_address) + ": " + lenRead
					+ " Bytes received: ");
			for (int i = 0; i < lenRead; i++) {
				sb.append("0x" + String.format("%1$02X", data[i]) + " ");
			}
			logger.info(sb.toString());
		}
		return lenRead;
	}

	/**
	 * Performs a control request to the default control pipe on a device.<br>
	 * The parameters mirror the types of the same name in the USB
	 * specification.
	 * 
	 * @param requestType
	 *            USB device request type (USB specification 9.3,
	 *            bmRequestType). Use constants from {@link ch.ntb.usb.USB}
	 *            (REQ_TYPE_xxx).
	 * @param request
	 *            specific request (USB specification 9.4, bRequest). Use
	 *            constants from {@link ch.ntb.usb.USB} (REQ_xxx).
	 * @param value
	 *            field that varies according to request (USB specification 9.4,
	 *            wValue)
	 * @param index
	 *            field that varies according to request (USB specification 9.4,
	 *            wIndex)
	 * @param data
	 *            the send/receive buffer
	 * @param size
	 *            the buffer size. 0 is a valid value, but there must still be a
	 *            dummy data buffer provided.
	 * @param timeout
	 *            amount of time in ms the device will try to send/receive data
	 *            until a timeout exception is thrown
	 * @param reopenOnTimeout
	 *            if set to true, the device will try to open the connection and
	 *            send/receive the data again before a timeout exception is
	 *            thrown
	 * @return the number of bytes written/read
	 * @throws USBException
	 */
	public int controlMsg(int requestType, int request, int value, int index,
			byte[] data, int size, int timeout, boolean reopenOnTimeout)
			throws USBException {
		if (usbDevHandle == 0) {
			throw new USBException("invalid device handle");
		}
		if (data == null) {
			throw new USBException("data must not be null");
		}
		if (size < 0 || size > data.length) {
			throw new ArrayIndexOutOfBoundsException("invalid size: " + size);
		}
		int len = LibusbJava.usb_control_msg(usbDevHandle, requestType,
				request, value, index, data, size, timeout);
		if (len < 0) {
			if (len == LibusbJava.ERROR_TIMEDOUT) {
				// try to reopen the device and send the data again
				if (reopenOnTimeout) {
					logger.info("try to reopen");
					reset();
					open(dev_configuration, dev_interface, dev_altinterface);
					return controlMsg(requestType, request, value, index, data,
							size, timeout, false);
				}
				throw new USBTimeoutException("LibusbJava.controlMsg: "
						+ LibusbJava.usb_strerror());
			}
			throw new USBException("LibusbJava.controlMsg: "
					+ LibusbJava.usb_strerror());
		}

		logger.info("length read/written: " + len);
		if (logger.isLoggable(Level.FINEST)) {
			StringBuffer sb = new StringBuffer("controlMsg: " + len
					+ " Bytes received(written: ");
			for (int i = 0; i < len; i++) {
				sb.append("0x" + String.format("%1$02X", data[i]) + " ");
			}
			logger.info(sb.toString());
		}
		return len;
	}

	/**
	 * Claim an interface to send and receive USB data.<br>
	 * 
	 * @param usb_dev_handle
	 *            the handle of the device <b>(MUST BE VALID)</b>
	 * @param configuration
	 *            the configuration to use
	 * @param interface_
	 *            the interface to claim
	 * @param altinterface
	 *            the alternate interface to use. If no alternate interface must
	 *            be set <i>-1</i> can be used.
	 * @throws USBException
	 *             throws an USBException if the action fails
	 */
	private void claim_interface(long usb_dev_handle, int configuration,
			int interface_, int altinterface) throws USBException {
		if (LibusbJava.usb_set_configuration(usb_dev_handle, configuration) < 0) {
			usbDevHandle = 0;
			throw new USBException("LibusbJava.usb_set_configuration: "
					+ LibusbJava.usb_strerror());
		}
		if (LibusbJava.usb_claim_interface(usb_dev_handle, interface_) < 0) {
			usbDevHandle = 0;
			throw new USBException("LibusbJava.usb_claim_interface: "
					+ LibusbJava.usb_strerror());
		}
		if (altinterface >= 0) {
			if (LibusbJava.usb_set_altinterface(usb_dev_handle, altinterface) < 0) {
				try {
					release_interface(usb_dev_handle, interface_);
				} catch (USBException e) {
					// ignore
				}
				usbDevHandle = 0;
				throw new USBException("LibusbJava.usb_set_altinterface: "
						+ LibusbJava.usb_strerror());
			}
		}
		logger.info("interface claimed");
	}

	/**
	 * Release a previously claimed interface.<br>
	 * 
	 * @param dev_handle
	 *            the handle of the device <b>(MUST BE VALID)</b>
	 * @param interface_
	 *            the interface to claim
	 * @throws USBException
	 *             throws an USBException if the action fails
	 */
	private void release_interface(long dev_handle, int interface_)
			throws USBException {
		if (LibusbJava.usb_release_interface(dev_handle, interface_) < 0) {
			usbDevHandle = 0;
			throw new USBException("LibusbJava.usb_release_interface: "
					+ LibusbJava.usb_strerror());
		}
		logger.info("interface released");
	}

	/**
	 * Returns the product ID of the device.<br>
	 * 
	 * @return the product ID of the device.
	 */
	public int getIdProduct() {
		return idProduct;
	}

	/**
	 * Returns the vendor ID of the device.<br>
	 * 
	 * @return the vendor ID of the device.
	 */
	public int getIdVendor() {
		return idVendor;
	}

	/**
	 * Returns the alternative interface.<br>
	 * This value is only valid after opening the device.
	 * 
	 * @return the alternative interface. This value is only valid after opening
	 *         the device.
	 */
	public int getAltinterface() {
		return dev_altinterface;
	}

	/**
	 * Returns the current configuration used.<br>
	 * This value is only valid after opening the device.
	 * 
	 * @return the current configuration used. This value is only valid after
	 *         opening the device.
	 */
	public int getConfiguration() {
		return dev_configuration;
	}

	/**
	 * Returns the current interface.<br>
	 * This value is only valid after opening the device.
	 * 
	 * @return the current interface. This value is only valid after opening the
	 *         device.
	 */
	public int getInterface() {
		return dev_interface;
	}

	/**
	 * Returns the maximum packet size in bytes which is allowed to be
	 * transmitted at once.<br>
	 * The value is determined by reading the endpoint descriptor(s) when
	 * opening the device. It is invalid before the device is opened! Note that
	 * if some endpoints use different packet sizes the maximum packet size is
	 * return. This value may be used to determine if a device is opened in
	 * fullspeed or highspeed mode.
	 * 
	 * @return the maximum packet size
	 */
	public int getMaxPacketSize() {
		return maxPacketSize;
	}

	/**
	 * Check if the device is open.<br>
	 * This checks only for a valid device handle. It doesn't check if the
	 * device is still attached or working.
	 * 
	 * @return true if the device is open
	 */
	public boolean isOpen() {
		return usbDevHandle != 0;
	}

	/**
	 * If enabled, the device is reset when first opened. <br>
	 * This will only happen once. When the application is started, the device
	 * state is unknown. If the device is not reset, read or write may result in
	 * a {@link USBTimeoutException}.<br>
	 * <br>
	 * This feature is disabled by default.
	 * 
	 * @param enable
	 *            true if the device should be reset when first opened
	 * @param timeout
	 *            the timeout between the reset and the reopening
	 */
	public void setResetOnFirstOpen(boolean enable, int timeout) {
		resetOnFirstOpen = enable;
		resetTimeout = timeout;
	}

	/**
	 * Returns the optional filename which is set when there are multiple
	 * devices with the same vendor and product id. See
	 * {@link USB#getDevice(short, short, String)}. Use
	 * {@link Usb_Device#getFilename()} to read the filename of a device.
	 * 
	 * @return the filename if set or null
	 */
	protected String getFilename() {
		return filename;
	}

	/**
	 * Returns the Usb_Device instance associated with this device. This value
	 * is only valid after opening the device.
	 * 
	 * @return the Usb_Device instance associated with this device.
	 */
	public Usb_Device getDevice() {
		return dev;
	}
}