1 |
2 |
ZTEX |
/*
|
2 |
|
|
* Java libusb wrapper
|
3 |
|
|
* Copyright (c) 2005-2006 Andreas Schläpfer <spandi at users.sourceforge.net>
|
4 |
|
|
*
|
5 |
|
|
* http://libusbjava.sourceforge.net
|
6 |
|
|
* This library is covered by the LGPL, read LGPL.txt for details.
|
7 |
|
|
*/
|
8 |
|
|
package ch.ntb.usb;
|
9 |
|
|
|
10 |
|
|
import java.util.Iterator;
|
11 |
|
|
import java.util.LinkedList;
|
12 |
|
|
import java.util.logging.Logger;
|
13 |
|
|
|
14 |
|
|
import ch.ntb.usb.logger.LogUtil;
|
15 |
|
|
|
16 |
|
|
/**
|
17 |
|
|
* This class manages all USB devices and defines some USB specific constants.<br>
|
18 |
|
|
*
|
19 |
|
|
*/
|
20 |
|
|
public class USB {
|
21 |
|
|
|
22 |
|
|
// Standard requests (USB spec 9.4)
|
23 |
|
|
/**
|
24 |
|
|
* This request returns status for the specified recipient (USB spec 9.4.5).
|
25 |
|
|
*
|
26 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
27 |
|
|
* boolean)
|
28 |
|
|
*/
|
29 |
|
|
public static final int REQ_GET_STATUS = 0x00;
|
30 |
|
|
/**
|
31 |
|
|
* This request is used to clear or disable a specific feature (USB spec
|
32 |
|
|
* 9.4.1).
|
33 |
|
|
*
|
34 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
35 |
|
|
* boolean)
|
36 |
|
|
*/
|
37 |
|
|
public static final int REQ_CLEAR_FEATURE = 0x01;
|
38 |
|
|
// 0x02 is reserved
|
39 |
|
|
/**
|
40 |
|
|
* This request is used to set or enable a specific feature (USB spec
|
41 |
|
|
* 9.4.9).
|
42 |
|
|
*
|
43 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
44 |
|
|
* boolean)
|
45 |
|
|
*/
|
46 |
|
|
public static final int REQ_SET_FEATURE = 0x03;
|
47 |
|
|
// 0x04 is reserved
|
48 |
|
|
/**
|
49 |
|
|
* This request sets the device address for all future device accesses (USB
|
50 |
|
|
* spec 9.4.6).
|
51 |
|
|
*
|
52 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
53 |
|
|
* boolean)
|
54 |
|
|
*/
|
55 |
|
|
public static final int REQ_SET_ADDRESS = 0x05;
|
56 |
|
|
/**
|
57 |
|
|
* This request returns the specified descriptor if the descriptor exists
|
58 |
|
|
* (USB spec 9.4.3).
|
59 |
|
|
*
|
60 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
61 |
|
|
* boolean)
|
62 |
|
|
*/
|
63 |
|
|
public static final int REQ_GET_DESCRIPTOR = 0x06;
|
64 |
|
|
/**
|
65 |
|
|
* This request is optional and may be used to update existing descriptors
|
66 |
|
|
* or new descriptors may be added (USB spec 9.4.8).
|
67 |
|
|
*
|
68 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
69 |
|
|
* boolean)
|
70 |
|
|
*/
|
71 |
|
|
public static final int REQ_SET_DESCRIPTOR = 0x07;
|
72 |
|
|
/**
|
73 |
|
|
* This request returns the current device configuration value (USB spec
|
74 |
|
|
* 9.4.2).
|
75 |
|
|
*
|
76 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
77 |
|
|
* boolean)
|
78 |
|
|
*/
|
79 |
|
|
public static final int REQ_GET_CONFIGURATION = 0x08;
|
80 |
|
|
/**
|
81 |
|
|
* This request sets the device configuration (USB spec 9.4.7).
|
82 |
|
|
*
|
83 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
84 |
|
|
* boolean)
|
85 |
|
|
*/
|
86 |
|
|
public static final int REQ_SET_CONFIGURATION = 0x09;
|
87 |
|
|
/**
|
88 |
|
|
* This request returns the selected alternate setting for the specified
|
89 |
|
|
* interface (USB spec 9.4.4).
|
90 |
|
|
*
|
91 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
92 |
|
|
* boolean)
|
93 |
|
|
*/
|
94 |
|
|
public static final int REQ_GET_INTERFACE = 0x0A;
|
95 |
|
|
/**
|
96 |
|
|
* This request allows the host to select an alternate setting for the
|
97 |
|
|
* specified interface (USB spec 9.4.10).
|
98 |
|
|
*
|
99 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
100 |
|
|
* boolean)
|
101 |
|
|
*/
|
102 |
|
|
public static final int REQ_SET_INTERFACE = 0x0B;
|
103 |
|
|
/**
|
104 |
|
|
* This request is used to set and then report an endpoint’s synchronization
|
105 |
|
|
* frame (USB spec 9.4.11).
|
106 |
|
|
*
|
107 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
108 |
|
|
* boolean)
|
109 |
|
|
*/
|
110 |
|
|
public static final int REQ_SYNCH_FRAME = 0x0C;
|
111 |
|
|
|
112 |
|
|
// data transfer direction (USB spec 9.3)
|
113 |
|
|
/**
|
114 |
|
|
* Identifies the direction of data transfer in the second phase of the
|
115 |
|
|
* control transfer.<br>
|
116 |
|
|
* The state of the Direction bit is ignored if the wLength field is zero,
|
117 |
|
|
* signifying there is no Data stage.<br>
|
118 |
|
|
* Specifies bit 7 of bmRequestType.
|
119 |
|
|
*
|
120 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
121 |
|
|
* boolean)
|
122 |
|
|
*/
|
123 |
|
|
public static final int REQ_TYPE_DIR_HOST_TO_DEVICE = (0x00 << 7),
|
124 |
|
|
REQ_TYPE_DIR_DEVICE_TO_HOST = (0x01 << 7);
|
125 |
|
|
|
126 |
|
|
// request types (USB spec 9.3)
|
127 |
|
|
/**
|
128 |
|
|
* Specifies the type of the request.<br>
|
129 |
|
|
* Specifies bits 6..5 of bmRequestType.
|
130 |
|
|
*
|
131 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
132 |
|
|
* boolean)
|
133 |
|
|
*/
|
134 |
|
|
public static final int REQ_TYPE_TYPE_STANDARD = (0x00 << 5),
|
135 |
|
|
REQ_TYPE_TYPE_CLASS = (0x01 << 5),
|
136 |
|
|
REQ_TYPE_TYPE_VENDOR = (0x02 << 5),
|
137 |
|
|
REQ_TYPE_TYPE_RESERVED = (0x03 << 5);
|
138 |
|
|
|
139 |
|
|
// request recipient (USB spec 9.3)
|
140 |
|
|
/**
|
141 |
|
|
* Specifies the intended recipient of the request.<br>
|
142 |
|
|
* Requests may be directed to the device, an interface on the device, or a
|
143 |
|
|
* specific endpoint on a device. When an interface or endpoint is
|
144 |
|
|
* specified, the wIndex field identifies the interface or endpoint.<br>
|
145 |
|
|
* Specifies bits 4..0 of bmRequestType.
|
146 |
|
|
*
|
147 |
|
|
* @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int,
|
148 |
|
|
* boolean)
|
149 |
|
|
*/
|
150 |
|
|
public static final int REQ_TYPE_RECIP_DEVICE = 0x00,
|
151 |
|
|
REQ_TYPE_RECIP_INTERFACE = 0x01, REQ_TYPE_RECIP_ENDPOINT = 0x02,
|
152 |
|
|
REQ_TYPE_RECIP_OTHER = 0x03;
|
153 |
|
|
|
154 |
|
|
/**
|
155 |
|
|
* The maximum packet size of a bulk transfer when operating in highspeed
|
156 |
|
|
* (480 MB/s) mode.
|
157 |
|
|
*/
|
158 |
|
|
public static int HIGHSPEED_MAX_BULK_PACKET_SIZE = 512;
|
159 |
|
|
|
160 |
|
|
/**
|
161 |
|
|
* The maximum packet size of a bulk transfer when operating in fullspeed
|
162 |
|
|
* (12 MB/s) mode.
|
163 |
|
|
*/
|
164 |
|
|
public static int FULLSPEED_MAX_BULK_PACKET_SIZE = 64;
|
165 |
|
|
|
166 |
|
|
private static final Logger logger = LogUtil.getLogger("ch.ntb.usb");
|
167 |
|
|
|
168 |
|
|
private static LinkedList<Device> devices = new LinkedList<Device>();
|
169 |
|
|
|
170 |
|
|
private static boolean initUSBDone = false;
|
171 |
|
|
|
172 |
|
|
/**
|
173 |
|
|
* Create a new device an register it in a device queue. If the device is
|
174 |
|
|
* already registered, a reference to it will be returned.<br>
|
175 |
|
|
*
|
176 |
|
|
* @param idVendor
|
177 |
|
|
* the vendor id of the USB device
|
178 |
|
|
* @param idProduct
|
179 |
|
|
* the product id of the USB device
|
180 |
|
|
* @param filename
|
181 |
|
|
* an optional filename which can be used to distinguish multiple
|
182 |
|
|
* devices with the same vendor and product id.
|
183 |
|
|
* @return a newly created device or an already registered device
|
184 |
|
|
*/
|
185 |
|
|
public static Device getDevice(short idVendor, short idProduct,
|
186 |
|
|
String filename) {
|
187 |
|
|
|
188 |
|
|
// check if this device is already registered
|
189 |
|
|
Device dev = getRegisteredDevice(idVendor, idProduct, filename);
|
190 |
|
|
if (dev != null) {
|
191 |
|
|
logger.info("return already registered device");
|
192 |
|
|
return dev;
|
193 |
|
|
}
|
194 |
|
|
dev = new Device(idVendor, idProduct, filename);
|
195 |
|
|
logger.info("create new device");
|
196 |
|
|
devices.add(dev);
|
197 |
|
|
return dev;
|
198 |
|
|
}
|
199 |
|
|
|
200 |
|
|
/**
|
201 |
|
|
* See {@link #getDevice(short, short, String)}. The parameter
|
202 |
|
|
* <code>filename</code> is set to null.
|
203 |
|
|
*
|
204 |
|
|
* @param idVendor
|
205 |
|
|
* @param idProduct
|
206 |
|
|
* @return a newly created device or an already registered device
|
207 |
|
|
*/
|
208 |
|
|
public static Device getDevice(short idVendor, short idProduct) {
|
209 |
|
|
return getDevice(idVendor, idProduct, null);
|
210 |
|
|
}
|
211 |
|
|
|
212 |
|
|
/**
|
213 |
|
|
* Get an already registered device or null if the device does not exist.<br>
|
214 |
|
|
*
|
215 |
|
|
* @param idVendor
|
216 |
|
|
* the vendor id of the USB device
|
217 |
|
|
* @param idProduct
|
218 |
|
|
* the product id of the USB device
|
219 |
|
|
* @param filename
|
220 |
|
|
* an optional filename which can be used to distinguish multiple
|
221 |
|
|
* devices with the same vendor and product id.
|
222 |
|
|
* @return the device or null
|
223 |
|
|
*/
|
224 |
|
|
private static Device getRegisteredDevice(short idVendor, short idProduct,
|
225 |
|
|
String filename) {
|
226 |
|
|
for (Iterator<Device> iter = devices.iterator(); iter.hasNext();) {
|
227 |
|
|
Device dev = iter.next();
|
228 |
|
|
if (filename != null && dev.getFilename() != null
|
229 |
|
|
&& filename.compareTo(dev.getFilename()) == 0
|
230 |
|
|
&& dev.getIdVendor() == idVendor
|
231 |
|
|
&& dev.getIdProduct() == idProduct) {
|
232 |
|
|
return dev;
|
233 |
|
|
} else if (dev.getIdVendor() == idVendor
|
234 |
|
|
&& dev.getIdProduct() == idProduct) {
|
235 |
|
|
return dev;
|
236 |
|
|
}
|
237 |
|
|
}
|
238 |
|
|
return null;
|
239 |
|
|
}
|
240 |
|
|
|
241 |
|
|
/**
|
242 |
|
|
* Returns the root {@link Usb_Bus} element.
|
243 |
|
|
*
|
244 |
|
|
* @return the root {@link Usb_Bus} element
|
245 |
|
|
* @throws USBException
|
246 |
|
|
*/
|
247 |
|
|
public static Usb_Bus getBus() throws USBException {
|
248 |
|
|
if (!initUSBDone) {
|
249 |
|
|
init();
|
250 |
|
|
}
|
251 |
|
|
LibusbJava.usb_find_busses();
|
252 |
|
|
LibusbJava.usb_find_devices();
|
253 |
|
|
|
254 |
|
|
Usb_Bus bus = LibusbJava.usb_get_busses();
|
255 |
|
|
if (bus == null) {
|
256 |
|
|
throw new USBException("LibusbJava.usb_get_busses(): "
|
257 |
|
|
+ LibusbJava.usb_strerror());
|
258 |
|
|
}
|
259 |
|
|
return bus;
|
260 |
|
|
}
|
261 |
|
|
|
262 |
|
|
/**
|
263 |
|
|
* Explicitly calls {@link LibusbJava#usb_init()}. Note that you don't need
|
264 |
|
|
* to call this procedure as it is called implicitly when creating a new
|
265 |
|
|
* device with {@link USB#getDevice(short, short, String)}.
|
266 |
|
|
*/
|
267 |
|
|
public static void init() {
|
268 |
|
|
LibusbJava.usb_init();
|
269 |
|
|
initUSBDone = true;
|
270 |
|
|
}
|
271 |
|
|
}
|