OpenCores
URL https://opencores.org/ocsvn/usb_fpga_2_14/usb_fpga_2_14/trunk

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [java/] [ztex/] [Ztex1.java] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
/*%
2
   Java host software API of ZTEX SDK
3
   Copyright (C) 2009-2017 ZTEX GmbH.
4
   http://www.ztex.de
5
 
6
   This Source Code Form is subject to the terms of the Mozilla Public
7
   License, v. 2.0. If a copy of the MPL was not distributed with this file,
8
   You can obtain one at http://mozilla.org/MPL/2.0/.
9
 
10
   Alternatively, the contents of this file may be used under the terms
11
   of the GNU General Public License Version 3, as described below:
12
 
13
   This program is free software; you can redistribute it and/or modify
14
   it under the terms of the GNU General Public License version 3 as
15
   published by the Free Software Foundation.
16
 
17
   This program is distributed in the hope that it will be useful, but
18
   WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
   General Public License for more details.
21
 
22
   You should have received a copy of the GNU General Public License
23
   along with this program; if not, see http://www.gnu.org/licenses/.
24
%*/
25
 
26
/*
27
    Functions for USB devices with ZTEX descriptor 1
28
*/
29
package ztex;
30
 
31
import java.io.*;
32
import java.util.*;
33
import java.nio.*;
34
 
35
import org.usb4java.*;
36
 
37
/**
38
  * This class implements the interface-independent part of the communication protocol for the interaction with the ZTEX firmware.<p>
39
  * All firmware implementations that provide the ZTEX descriptor 1 are supported.
40
  * A description of this descriptor can be found in {@link ZtexDevice1}.
41
  * <p>
42
  * The most important features of this class are the functions for uploading the firmware
43
  * and the renumeration management.
44
  * <p>
45
  * The interface dependent part of the communication protocol (currently only one is supported)
46
  * can be found in {@link Ztex1v1}.
47
  * @see ZtexDevice1
48
  * @see Ztex1v1
49
  */
50
public class Ztex1 {
51
    private DeviceHandle handle = null;
52
    private ZtexDevice1 dev = null;
53
    private Vector<String> oldDevices = new Vector<String>();
54
    private String oldDev = null;
55
    private boolean[] interfaceClaimed = new boolean[256];
56
    private boolean configurationSet = false;
57
/** * The timeout for  control messages in ms. */
58
    public int controlMsgTimeout = 2000;        // in ms
59
    private long lastVendorCommandT = 0;
60
 
61
 
62
// ******* Ztex1 ***************************************************************
63
/**
64
  * Constructs an instance from a given device.
65
  * @param pDev The given device.
66
  * @throws UsbException if an communication error occurred.
67
  */
68
    public Ztex1 ( ZtexDevice1 pDev ) throws UsbException {
69
        dev = pDev;
70
        init();
71
        dev.ref();
72
    }
73
 
74
// ******* init ****************************************************************
75
/**
76
  * Initializates the class.
77
  * @throws UsbException if an communication error occurred.
78
  */
79
    protected synchronized void init () throws UsbException {
80
        for (int i=0; i<256; i++)
81
            interfaceClaimed[i] = false;
82
 
83
        handle = new DeviceHandle();
84
        int result = LibUsb.open(dev.dev(), handle);
85
        if (result != LibUsb.SUCCESS) throw new UsbException(dev.dev(), "Unable to open USB device", result);
86
 
87
    }
88
 
89
// ******* dispose *************************************************************
90
/**
91
  * This should be called if the class is not used anymore.
92
  * It closes the USB connection and releases all resources
93
  */
94
    public synchronized void dispose () {
95
        if ( handle != null ) {
96
            for (int i=0; i<256; i++)
97
                if ( interfaceClaimed[i] )
98
                    LibUsb.releaseInterface(handle, i);
99
 
100
            LibUsb.close(handle);
101
            handle = null;
102
        }
103
        if ( dev != null ) {
104
            dev.unref();
105
            dev = null;
106
        }
107
    }
108
 
109
// ******* finalize ************************************************************
110
/**
111
  * Releases all resources.
112
  */
113
    protected void finalize() throws Throwable {
114
        dispose();
115
    }
116
 
117
// ******* handle **************************************************************
118
/** Returns the USB file handle.
119
  * @return the USB file handle.
120
  */
121
    public synchronized final DeviceHandle handle()
122
    {
123
        return handle;
124
    }
125
 
126
// ******* dev *****************************************************************
127
/**
128
  * Returns the corresponding {@link ZtexDevice1}.
129
  * @return the corresponding {@link ZtexDevice1}.
130
  */
131
    public synchronized final ZtexDevice1 dev()
132
    {
133
        return dev;
134
    }
135
 
136
// ******* valid ***************************************************************
137
/**
138
  * Returns true if ZTEX descriptor 1 is available.
139
  * @return true if ZTEX descriptor 1 is available.
140
  */
141
    public synchronized boolean valid ( ) {
142
        return dev.valid();
143
    }
144
 
145
// ******* checkValid **********************************************************
146
/**
147
  * Checks whether ZTEX descriptor 1 is available.
148
  * @throws InvalidFirmwareException if ZTEX descriptor 1 is not available.
149
  */
150
    public synchronized void checkValid () throws InvalidFirmwareException {
151
        if ( ! dev.valid() )
152
            throw new InvalidFirmwareException(this, "Can't read ZTEX descriptor 1");
153
    }
154
 
155
// ******* vendorCommand *******************************************************
156
/**
157
  * Sends a vendor command to Endpoint 0 of the EZ-USB device.
158
  * The command may be send multiple times until the {@link #controlMsgTimeout} is reached.
159
  * @param cmd The command number (0..255).
160
  * @param func The name of the command. This string is used for the generation of error messages.
161
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
162
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
163
  * @param buf The payload data buffer. The full buffer is sent, i.e. transfer size is equal to buffer capacity.
164
  * @return the number of bytes sent.
165
  * @throws UsbException if a communication error occurs.
166
  */
167
    public synchronized int vendorCommand (int cmd, String func, int value, int index, ByteBuffer buf) throws UsbException {
168
        long t0 = new Date().getTime()-100;
169
        int trynum = 0;
170
        int i = -1;
171
        if ( controlMsgTimeout < 400 ) controlMsgTimeout = 400;
172
        while ( i<=0 && new Date().getTime()-t0<controlMsgTimeout ) {            // repeat the message until the timeout has reached
173
            i = LibUsb.controlTransfer(handle, (byte)0x40, (byte)(cmd & 255), (short)(value & 0xffff), (short)(index & 0xffff), buf, controlMsgTimeout>>2);
174
            lastVendorCommandT = new Date().getTime();
175
            if ( i < 0 ) {
176
                System.err.println("Warning (try " + (trynum+1) + "): " + LibUsb.strError(i) );
177
                try {
178
                    Thread.sleep( 1 << trynum );
179
                }
180
                    catch ( InterruptedException e ) {
181
                }
182
                trynum++;
183
            }
184
        }
185
        if ( i < 0 ) throw new UsbException( dev.dev(), (func != null ? func + ": " : "" ) + LibUsb.strError(i));
186
        return i;
187
    }
188
 
189
/**
190
  * Sends a vendor command to Endpoint 0 of the EZ-USB device.
191
  * The command may be send multiple times until the {@link #controlMsgTimeout} is reached.
192
  * @param cmd The command number (0..255).
193
  * @param func The name of the command. This string is used for the generation of error messages.
194
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
195
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
196
  * @param length The size of the payload data (0..65535), i.e. bytes 6 and 7 of the setup data.
197
  * @param buf The payload data buffer.
198
  * @return the number of bytes sent.
199
  * @throws UsbException if a communication error occurs.
200
  */
201
    public synchronized int vendorCommand (int cmd, String func, int value, int index, byte[] buf, int length) throws UsbException {
202
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(length);
203
        buffer.put(buf,0,length);
204
        return vendorCommand(cmd, func, value, index, buffer);
205
    }
206
 
207
/**
208
  * Sends a vendor command with no payload data to Endpoint 0 of the EZ-USB device.
209
  * The command may be send multiple times until the {@link #controlMsgTimeout} is reached.
210
  * @param cmd The command number (0..255).
211
  * @param func The name of the command. This string is used for the generation of error messages.
212
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
213
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
214
  * @return the number of bytes sent.
215
  * @throws UsbException if a communication error occurs.
216
  */
217
    public int vendorCommand (int cmd, String func, int value, int index) throws UsbException {
218
        return vendorCommand (cmd, func, value, index, ByteBuffer.allocateDirect(0));
219
    }
220
 
221
/**
222
  * Sends a vendor command with no payload data and no setup data to Endpoint 0 of the EZ-USB device.
223
  * The command may be send multiple times until the {@link #controlMsgTimeout} is reached.
224
  * @param cmd The command number (0..255).
225
  * @param func The name of the command. This string is used for the generation of error messages.
226
  * @return the number of bytes sent.
227
  * @throws UsbException if a communication error occurs.
228
  */
229
    public int vendorCommand (int cmd, String func) throws UsbException {
230
        byte[] buf = { 0 };
231
        return vendorCommand (cmd, func, 0, 0, ByteBuffer.allocateDirect(0));
232
    }
233
 
234
// ******* vendorRequest *******************************************************
235
/**
236
  * Sends a vendor request to Endpoint 0 of the EZ-USB device.
237
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
238
  * @param cmd The request number (0..255).
239
  * @param func The name of the request. This string is used for the generation of error messages.
240
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
241
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
242
  * @param buf The payload data buffer. Buffer capacity determines the length of the transfer.
243
  * @return the number of bytes received.
244
  * @throws UsbException if a communication error occurs.
245
  */
246
    public synchronized int vendorRequest (int cmd, String func, int value, int index, ByteBuffer buf) throws UsbException {
247
        long t0 = new Date().getTime()-100;
248
        int trynum = 0;
249
        int i = -1;
250
        if ( controlMsgTimeout < 400 ) controlMsgTimeout = 400;
251
        while ( i<=0 && new Date().getTime()-t0<controlMsgTimeout ) {            // we repeat the message until the timeout has reached
252
            //  Wait at least 1ms after the last command has been send
253
            long ms = new Date().getTime() - lastVendorCommandT;
254
            if ( ms < 2 ) {
255
                try {
256
                    Thread.sleep(1);
257
                }
258
                    catch ( InterruptedException e ) {
259
                }
260
            }
261
 
262
            i = LibUsb.controlTransfer(handle, (byte)(0xc0 & 255), (byte)(cmd & 255), (short)(value & 0xffff), (short)(index & 0xffff), buf, controlMsgTimeout>>2);
263
            if ( i < 0 ) {
264
                System.err.println("Warning (try " + (trynum+1) + "): " + LibUsb.strError(i) );
265
                try {
266
                    Thread.sleep( 1 << trynum );
267
                }
268
                    catch ( InterruptedException e ) {
269
                }
270
                trynum++;
271
            }
272
        }
273
        if ( i < 0 )
274
            throw new UsbException( dev.dev(), (func != null ? func + ": " : "" ) + LibUsb.strError(i));
275
        return i;
276
    }
277
 
278
/**
279
  * Sends a vendor request to Endpoint 0 of the EZ-USB device.
280
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
281
  * @param cmd The request number (0..255).
282
  * @param func The name of the request. This string is used for the generation of error messages.
283
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
284
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
285
  * @param maxlen The size of the requested payload data (0..65535), i.e. bytes 6 and 7 of the setup data.
286
  * @param buf The payload data buffer.
287
  * @return the number of bytes received.
288
  * @throws UsbException if a communication error occurs.
289
  */
290
    public synchronized int vendorRequest (int cmd, String func, int value, int index, byte[] buf, int maxlen) throws UsbException {
291
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(maxlen);
292
        int i = vendorRequest(cmd, func, value, index, buffer);
293
        try {
294
            buffer.get(buf,0,maxlen);
295
        }
296
        catch ( Exception e ) {
297
            // errors can be ignored
298
        }
299
        return i;
300
 
301
    }
302
 
303
/**
304
  * Sends a vendor request to Endpoint 0 of the EZ-USB device.
305
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
306
  * @param cmd The request number (0..255).
307
  * @param func The name of the request. This string is used for the generation of error messages.
308
  * @param buf The payload data buffer.
309
  * @return the number of bytes sent.
310
  * @throws UsbException if a communication error occurs.
311
  */
312
    public int vendorRequest (int cmd, String func, ByteBuffer buf) throws UsbException {
313
        return vendorRequest (cmd, func, 0, 0, buf);
314
    }
315
 
316
/**
317
  * Sends a vendor request to Endpoint 0 of the EZ-USB device.
318
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
319
  * @param cmd The request number (0..255).
320
  * @param func The name of the request. This string is used for the generation of error messages.
321
  * @param maxlen The size of the requested payload data (0..65535), i.e. bytes 6 and 7 of the setup data.
322
  * @param buf The payload data buffer.
323
  * @return the number of bytes sent.
324
  * @throws UsbException if a communication error occurs.
325
  */
326
    public int vendorRequest (int cmd, String func, byte[] buf, int maxlen) throws UsbException {
327
        return vendorRequest (cmd, func, 0, 0, buf, maxlen);
328
    }
329
 
330
// ******* vendorCommand2 ******************************************************
331
/**
332
  * Sends a vendor command to Endpoint 0 of the EZ-USB device and throws an {@link UsbException} if not all of the payload has been sent.
333
  * The command may be send multiple times until the {@link #controlMsgTimeout} is reached.
334
  * @param cmd The command number (0..255).
335
  * @param func The name of the command. This string is used for the generation of error messages.
336
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
337
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
338
  * @param buf The payload data buffer. The full buffer is sent, i.e. transfer size is equal to buffer capacity.
339
  * @throws UsbException if a communication error occurs or if not all of the payload has been sent.
340
  */
341
    public synchronized void vendorCommand2 (int cmd, String func, int value, int index, ByteBuffer buf) throws UsbException {
342
        int length = buf.capacity();
343
        int i = vendorCommand (cmd, func, value, index, buf);
344
        if ( i != length )
345
            throw new UsbException( dev.dev(), (func != null ? func + ": " : "" ) + "Send " + i + " byte of data instead of " + length + " bytes");
346
    }
347
 
348
/**
349
  * Sends a vendor command to Endpoint 0 of the EZ-USB device and throws an {@link UsbException} if not all of the payload has been sent.
350
  * The command may be send multiple times until the {@link #controlMsgTimeout} is reached.
351
  * @param cmd The command number (0..255).
352
  * @param func The name of the command. This string is used for the generation of error messages.
353
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
354
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
355
  * @param length The size of the payload data (0..65535), i.e. bytes 6 and 7 of the setup data.
356
  * @param buf The payload data buffer.
357
  * @throws UsbException if a communication error occurs or if not all of the payload has been sent.
358
  */
359
    public synchronized void vendorCommand2 (int cmd, String func, int value, int index, byte[] buf, int length) throws UsbException {
360
        int i = vendorCommand (cmd, func, value, index, buf, length);
361
        if ( i != length )
362
            throw new UsbException( dev.dev(), (func != null ? func + ": " : "" ) + "Send " + i + " byte of data instead of " + length + " bytes");
363
    }
364
 
365
// ******* vendorRequest2 ******************************************************
366
/**
367
  * Sends a vendor request to Endpoint 0 of the EZ-USB device and throws an {@link UsbException} if not all of the payload has been received.
368
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
369
  * @param cmd The request number (0..255).
370
  * @param func The name of the request. This string is used for the generation of error messages.
371
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
372
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
373
  * @param buf The payload data buffer. Buffer capacity determines the length of the transfer.
374
  * @throws UsbException if a communication error occurs or not all of the payload has been received.
375
  */
376
    public void vendorRequest2 (int cmd, String func, int value, int index, ByteBuffer buf) throws UsbException {
377
        int maxlen = buf.capacity();
378
        int i = vendorRequest(cmd, func, value, index, buf);
379
        if ( i != maxlen )
380
            throw new UsbException( dev.dev(), (func != null ? func + ": " : "" ) + "Received " + i + " byte of data, expected "+maxlen+" bytes");
381
    }
382
 
383
/**
384
  * Sends a vendor request to Endpoint 0 of the EZ-USB device and throws an {@link UsbException} if not all of the payload has been received.
385
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
386
  * @param cmd The request number (0..255).
387
  * @param func The name of the request. This string is used for the generation of error messages.
388
  * @param buf The payload data buffer.
389
  * @throws UsbException if a communication error occurs or not all of the payload has been received.
390
  */
391
    public void vendorRequest2 (int cmd, String func, ByteBuffer buf) throws UsbException {
392
        vendorRequest2(cmd, func, 0, 0, buf);
393
    }
394
 
395
/**
396
  * Sends a vendor request to Endpoint 0 of the EZ-USB device and throws an {@link UsbException} if not all of the payload has been received.
397
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
398
  * @param cmd The request number (0..255).
399
  * @param func The name of the request. This string is used for the generation of error messages.
400
  * @param value The value (0..65535), i.e bytes 2 and 3 of the setup data.
401
  * @param index The index (0..65535), i.e. bytes 4 and 5 of the setup data.
402
  * @param maxlen The size of the requested payload data (0..65535), i.e. bytes 6 and 7 of the setup data.
403
  * @param buf The payload data buffer.
404
  * @throws UsbException if a communication error occurs or not all of the payload has been received.
405
  */
406
    public void vendorRequest2 (int cmd, String func, int value, int index, byte[] buf, int maxlen) throws UsbException {
407
        int i = vendorRequest(cmd, func, value, index, buf, maxlen);
408
        if ( i != maxlen )
409
            throw new UsbException( dev.dev(), (func != null ? func + ": " : "" ) + "Received " + i + " byte of data, expected "+maxlen+" bytes");
410
    }
411
 
412
/**
413
  * Sends a vendor request to Endpoint 0 of the EZ-USB device and throws an {@link UsbException} if not all of the payload has been received.
414
  * The request may be send multiple times until the {@link #controlMsgTimeout} is reached.
415
  * @param cmd The request number (0..255).
416
  * @param func The name of the request. This string is used for the generation of error messages.
417
  * @param maxlen The size of the requested payload data (0..65535), i.e. bytes 6 and 7 of the setup data.
418
  * @param buf The payload data buffer.
419
  * @throws UsbException if a communication error occurs or not all of the payload has been received.
420
  */
421
    public void vendorRequest2 (int cmd, String func, byte[] buf, int maxlen) throws UsbException {
422
        vendorRequest2(cmd, func, 0, 0, buf, maxlen);
423
    }
424
 
425
// ******* bulkWrite ***********************************************************
426
/**
427
  * Wrapper method for ibUsb.bulkTransfer(DeviceHandle,byte,ByteBuffer,IntBuffer,long).
428
  * @param ep The endpoint number.
429
  * @param buffer The payload data buffer. The whole buffer is transferred, i.e. transfer legth is equal to buffer capacity
430
  * @param timeout The timeout in ms
431
  * @return The error code (<0) if an error occurred, otherwise the amount of transferred date
432
  */
433
    public int bulkWrite(int ep, ByteBuffer buffer, long timeout)
434
    {
435
        IntBuffer transferred = BufferUtils.allocateIntBuffer();
436
        int result = LibUsb.bulkTransfer(handle, (byte)(ep & 127), buffer, transferred, timeout);
437
        return result < 0 ? result : transferred.get();
438
    }
439
 
440
/**
441
  * Wrapper method for LibUsb.bulkTransfer(DeviceHandle,byte,ByteBuffer,IntBuffer,long).
442
  * @param ep The endpoint number.
443
  * @param buf The payload data buffer.
444
  * @param length The size of the payload data
445
  * @param timeout The timeout in ms
446
  * @return The error code (<0) if an error occurred, otherwise the amount of transferred date
447
  */
448
    public int bulkWrite(int ep, byte[] buf, int length, long timeout)
449
    {
450
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(length);
451
        buffer.put(buf,0,length);
452
        IntBuffer transferred = BufferUtils.allocateIntBuffer();
453
        int result = LibUsb.bulkTransfer(handle, (byte)(ep & 127), buffer, transferred, timeout);
454
        return result < 0 ? result : transferred.get();
455
    }
456
 
457
// ******* bulkRead ************************************************************
458
/**
459
  * Wrapper method for LibUsb.bulkTransfer(DeviceHandle,byte,ByteBuffer,IntBuffer,long).
460
  * @param ep The endpoint number.
461
  * @param buffer The payload data buffer. The transfer length is determined by buffer capacity.
462
  * @param timeout The timeout in ms
463
  * @return The error code (<0) if an error occurred, otherwise the amount of transferred date
464
  */
465
    public int bulkRead(int ep, ByteBuffer buffer, long timeout)
466
    {
467
        IntBuffer transferred = BufferUtils.allocateIntBuffer();
468
        int result = LibUsb.bulkTransfer(handle, (byte)(128 | (ep & 127)), buffer, transferred, timeout);
469
        return result < 0 ? result : transferred.get();
470
    }
471
 
472
/**
473
  * Wrapper method for LibUsb.bulkTransfer(DeviceHandle,byte,ByteBuffer,IntBuffer,long).
474
  * @param ep The endpoint number.
475
  * @param buf The payload data buffer.
476
  * @param maxlen The size of the transfer.
477
  * @param timeout The timeout in ms
478
  * @return The error code (<0) if an error occurred, otherwise the amount of transferred date
479
  */
480
    public int bulkRead(int ep, byte[] buf, int maxlen, long timeout)
481
    {
482
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(maxlen);
483
        IntBuffer transferred = BufferUtils.allocateIntBuffer();
484
        int result = LibUsb.bulkTransfer(handle, (byte)(128 | (ep & 127)), buffer, transferred, timeout);
485
        try {
486
            buffer.get(buf,0,maxlen);
487
        }
488
        catch ( Exception e ) {
489
            // errors can be ignored
490
        }
491
        return result < 0 ? result : transferred.get();
492
    }
493
 
494
// ******* allocateByteBuffer **************************************************
495
/**
496
  * Utility function that creates a ByteBuffer from byte array.
497
  * @param buf The byte array.
498
  * @return A ByteBuffer.
499
  */
500
    public static ByteBuffer allocateByteBuffer(byte[] buf)
501
    {
502
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(buf.length);
503
        return buffer.put(buf,0,buf.length);
504
    }
505
 
506
/**
507
  * Utility function that creates a ByteBuffer from byte array.
508
  * @param buf The byte array.
509
  * @param offs The offset of the first data in the byte array.
510
  * @param length Length of the The byte array.
511
  * @return A ByteBuffer.
512
  */
513
    public static ByteBuffer allocateByteBuffer(byte[] buf, int offs, int length)
514
    {
515
        ByteBuffer buffer = BufferUtils.allocateByteBuffer(length);
516
        return buffer.put(buf,offs,length);
517
    }
518
 
519
// ******* setConfiguration ****************************************************
520
/**
521
  * Sets the configuration.
522
  * @param config The configuration number (usually 1)
523
  * @throws UsbException if an error occurs while attempting to set the configuration.
524
  */
525
    public synchronized void setConfiguration ( int config) throws UsbException{
526
        int result = LibUsb.setConfiguration(handle(), config);
527
        if ( result < 0 )
528
            throw new UsbException(dev.dev(), "Setting configuration to " + config + " failed: ", result);
529
        configurationSet = true;
530
    }
531
 
532
 
533
// ******* trySetConfiguration ****************************************************
534
/**
535
  * Tries to set the configuration.
536
  * If an error occurs while attempting to set the configuration, a warning message is printed to stderr.
537
  * @param config The configuration number (usually 1)
538
  */
539
    public synchronized void trySetConfiguration ( int config) {
540
        int result = LibUsb.setConfiguration(handle(), config);
541
        if ( result < 0 )
542
            System.err.println("Setting configuration to " + config + " failed: " + LibUsb.strError(result));
543
        configurationSet = true;
544
    }
545
 
546
 
547
// ******* getInterfaceClaimed *************************************************
548
/**
549
  * Returns true if interface is claimed.
550
  * @return true if interface is claimed
551
  * @param iface The interface number
552
  */
553
    public synchronized boolean getInterfaceClaimed ( int iface ) {
554
        return iface>=0 && iface<256 && interfaceClaimed[iface];
555
    }
556
 
557
 
558
// ******* claimInterface ******************************************************
559
/**
560
  * Claims an interface.
561
  * @param iface The interface number (usually 0)
562
  * @throws UsbException if an error occurs while attempting to claim the interface.
563
  */
564
    public synchronized void claimInterface ( int iface) throws UsbException{
565
        if ( ! configurationSet )
566
            trySetConfiguration(1);
567
        if ( iface<0 || iface>=256 || (!interfaceClaimed[iface]) ) {
568
            int result = LibUsb.claimInterface(handle(), iface);
569
            if ( result < 0 ) throw new UsbException(dev.dev(), "Claiming interface " + iface + " failed: ", result);
570
        }
571
        if ( iface>=0 && iface < 256 )
572
            interfaceClaimed[iface]=true;
573
    }
574
 
575
 
576
// ******* releaseInterface ****************************************************
577
/**
578
  * Releases an interface.
579
  * @param iface The interface number (usually 0)
580
  */
581
    public synchronized void releaseInterface ( int iface ) {
582
        if ( iface<0 || iface>=256 || interfaceClaimed[iface] )
583
            LibUsb.releaseInterface(handle(), iface);
584
        if ( iface>=0 && iface < 256 )
585
            interfaceClaimed[iface]=false;
586
    }
587
 
588
 
589
// ******* findOldDevices ******************************************************
590
    private synchronized void findOldDevices() throws DeviceLostException, UsbException {
591
        oldDev = dev.name();
592
        oldDevices.clear();
593
//      System.out.println("oldDev="+oldDev);
594
 
595
        ZtexContext context = new ZtexContext();
596
        DeviceList dl = new DeviceList();
597
        int result = LibUsb.getDeviceList(context.context(), dl);
598
        if (result < 0) {
599
            context.unref();
600
            throw new UsbException( "findOldDevices: Unable to get device list: ", result);
601
        }
602
 
603
        try {
604
            for (Device dev: dl) {
605
                oldDevices.add(ZtexDevice1.name(dev));
606
//              System.out.println("add " + ZtexDevice1.name(dev) );
607
            }
608
        }
609
        finally {
610
            LibUsb.freeDeviceList(dl, true);
611
            context.unref();
612
        }
613
    }
614
 
615
// ******* initNewDevice *******************************************************
616
    private synchronized void initNewDevice (String errBase, boolean scanUnconfigured ) throws DeviceLostException, UsbException, InvalidFirmwareException {
617
 
618
        // close current connection
619
        dispose();
620
 
621
        // scan the bus for up to 60 s for a new device. Boot sequence may take a while.
622
        for ( int i=0; i<300 && dev==null; i++ ) {
623
            Device newDev = null;
624
 
625
            // wait 0.2s
626
            try {
627
                Thread.sleep( 200 );
628
            }
629
                catch ( InterruptedException e ) {
630
            }
631
            // accept old address after 5s
632
            if ( i == 25 ) oldDevices.remove(oldDev);
633
 
634
            // scan bus for new devices
635
            ZtexContext context = new ZtexContext();
636
            DeviceList dl = new DeviceList();
637
            int result = LibUsb.getDeviceList(context.context(), dl);
638
            if ( result < 0 ) {
639
                context.unref();
640
                throw new UsbException( "findNewDevice: Unable to get device list: ", result);
641
            }
642
            try {
643
                for (Device udev: dl) {
644
                    String s = ZtexDevice1.name(udev);
645
//                  System.out.println(s + ": " + oldDevices.indexOf(s));
646
                    if ( oldDevices.indexOf(s)<0 ) {
647
                        if ( newDev != null ) throw new DeviceLostException( errBase + "More than 1 new devices found: `" + ZtexDevice1.name(newDev) + "', `" + ZtexDevice1.name(udev) + "'");
648
                        newDev = udev;
649
                    }
650
                }
651
 
652
                // init new device
653
                if ( newDev != null ) {
654
                    // create ZtexDevice1
655
                    DeviceDescriptor dd = new DeviceDescriptor();
656
                    result = LibUsb.getDeviceDescriptor(newDev, dd);
657
                    if (result != LibUsb.SUCCESS) throw new UsbException(newDev, "Unable to read device descriptor", result);
658
                    int vid = dd.idVendor() & 65535;
659
                    int pid = dd.idProduct() & 65535;
660
                    try {
661
                        dev = new ZtexDevice1(context, newDev, dd.idVendor() & 65535, dd.idProduct() & 65535, scanUnconfigured );
662
                    }
663
                    catch ( DeviceNotSupportedException e ) {
664
                        throw new InvalidFirmwareException( e.getLocalizedMessage() );
665
                    }
666
                    init();
667
                }
668
            }
669
            finally {
670
                LibUsb.freeDeviceList(dl, true);
671
                context.unref();
672
            }
673
        }
674
 
675
        if ( dev == null ) throw new DeviceLostException( errBase + ": No new device found" );
676
    }
677
 
678
// ******* uploadFirmware ******************************************************
679
/**
680
  * Uploads the firmware to the EZ-USB and manages the renumeration process.
681
  * <p>
682
  * Before the firmware is uploaded the device is set into a reset state.
683
  * After the upload the firmware is booted and the renumeration starts.
684
  * During this process the device disappears from the bus and a new one
685
  * occurs which will be assigned to this class automatically (instead of the disappeared one).
686
  * @param imgFile The firmware image.
687
  * @param force The compatibility check is skipped if true.
688
  * @throws IncompatibleFirmwareException if the given firmware is not compatible to the installed one, see {@link ZtexDevice1#compatible(int,int,int,int)} (Upload can be enforced using the <tt>force</tt> parameter)
689
  * @throws FirmwareUploadException If an error occurred while attempting to upload the firmware.
690
  * @throws UsbException if a communication error occurs.
691
  * @throws InvalidFirmwareException if ZTEX descriptor 1 is not available.
692
  * @throws DeviceLostException if a device went lost after renumeration.
693
  * @return the upload time in ms.
694
  */
695
//  returns upload time in ms
696
    public long uploadFirmware ( ZtexImgFile1 imgFile, boolean force ) throws IncompatibleFirmwareException, FirmwareUploadException, UsbException, InvalidFirmwareException, DeviceLostException {
697
// load the firmware file
698
//      imgFile.dataInfo(System.out);
699
//      System.out.println(imgFile);
700
 
701
// check for compatibility
702
        if ( ! force && dev.valid() ) {
703
            if ( imgFile.interfaceVersion() != dev.interfaceVersion() )
704
                throw new IncompatibleFirmwareException("Wrong interface version: Expected 1, got " + imgFile.interfaceVersion() );
705
 
706
            if ( ! dev.compatible ( imgFile.productId(0), imgFile.productId(1), imgFile.productId(2), imgFile.productId(3) ) )
707
                throw new IncompatibleFirmwareException("Incompatible productId's: Current firmware: " + ZtexDevice1.byteArrayString(dev.productId())
708
                    + "  firmware file: " + ZtexDevice1.byteArrayString(imgFile.productId()) );
709
        }
710
 
711
// prepare FX3 for booting from USB
712
        if ( dev.valid() && dev.fx3() ) {
713
            findOldDevices();
714
            resetFX3(false);
715
            initNewDevice("Device lost after reset", true);
716
        }
717
 
718
// scan the bus for comparison
719
        findOldDevices();
720
 
721
// upload the firmware
722
        long time = EzUsb.uploadFirmware( handle, imgFile );
723
 
724
// find and init new device
725
        initNewDevice("Device lost after uploading Firmware", false);
726
 
727
        return time;
728
    }
729
 
730
/**
731
  * Uploads the firmware to the EZ-USB and manages the renumeration process.
732
  * <p>
733
  * Before the firmware is uploaded the device is set into a reset state.
734
  * After the upload the firmware is booted and the renumeration starts.
735
  * During this process the device disappears from the bus and a new one
736
  * occurs which will be assigned to this class automatically (instead of the disappeared one).
737
  * @param imgFileName The file name of the firmware image in ihx or img format. The file can be a regular file or a system resource (e.g. a file from the current jar archive).
738
  * @param force The compatibility check is skipped if true.
739
  * @throws IncompatibleFirmwareException if the given firmware is not compatible to the installed one, see {@link ZtexDevice1#compatible(int,int,int,int)} (Upload can be enforced using the <tt>force</tt> parameter)
740
  * @throws FirmwareUploadException If an error occurred while attempting to upload the firmware.
741
  * @throws UsbException if a communication error occurs.
742
  * @throws InvalidFirmwareException if ZTEX descriptor 1 is not available.
743
  * @throws DeviceLostException if a device went lost after renumeration.
744
  * @return the upload time in ms.
745
  */
746
//  returns upload time in ms
747
    public long uploadFirmware ( String imgFileName, boolean force ) throws IncompatibleFirmwareException, FirmwareUploadException, UsbException, InvalidFirmwareException, DeviceLostException {
748
// load the firmware file
749
        ZtexImgFile1 imgFile;
750
        try {
751
            imgFile = new ZtexImgFile1( imgFileName );
752
        }
753
        catch ( IOException e ) {
754
            throw new FirmwareUploadException( e.getLocalizedMessage() );
755
        }
756
        catch ( ImgFileDamagedException e ) {
757
            throw new FirmwareUploadException( e.getLocalizedMessage() );
758
        }
759
        return uploadFirmware( imgFile, force );
760
    }
761
 
762
/**
763
  * Uploads the firmware to the EZ-USB and manages the renumeration process.
764
  * <p>
765
  * Before the firmware is uploaded the device is set into a reset state.
766
  * After the upload the firmware is booted and the renumeration starts.
767
  * During this process the device disappears from the bus and a new one
768
  * occurs which will be assigned to this class automatically (instead of the disappeared one).
769
  * @param imgIn Input stream from which the img file is read.
770
  * @param name Name of the input.
771
  * @param force The compatibility check is skipped if true.
772
  * @throws IncompatibleFirmwareException if the given firmware is not compatible to the installed one, see {@link ZtexDevice1#compatible(int,int,int,int)} (Upload can be enforced using the <tt>force</tt> parameter)
773
  * @throws FirmwareUploadException If an error occurred while attempting to upload the firmware.
774
  * @throws UsbException if a communication error occurs.
775
  * @throws InvalidFirmwareException if ZTEX descriptor 1 is not available.
776
  * @throws DeviceLostException if a device went lost after renumeration.
777
  * @return the upload time in ms.
778
  */
779
//  returns upload time in ms
780
    public long uploadFirmware ( InputStream imgIn, String name, boolean force ) throws IncompatibleFirmwareException, FirmwareUploadException, UsbException, InvalidFirmwareException, DeviceLostException {
781
// load the firmware file
782
        ZtexImgFile1 imgFile;
783
        try {
784
            imgFile = new ZtexImgFile1( imgIn, name );
785
        }
786
        catch ( IOException e ) {
787
            throw new FirmwareUploadException( e.getLocalizedMessage() );
788
        }
789
        catch ( ImgFileDamagedException e ) {
790
            throw new FirmwareUploadException( e.getLocalizedMessage() );
791
        }
792
        return uploadFirmware( imgFile, force );
793
    }
794
 
795
 
796
// ******* resetFX3 ************************************************************
797
/**
798
  * Resets a FX3 device with ztex firmware using vendor command 0xA1.
799
  * If parameter boot is false new firmware has to be uploaded via USB.
800
  * @param boot True in order to enable booting firmware from Flash.
801
  * <p>
802
  * @throws UsbException if a communication error occurs.
803
  * @throws InvalidFirmwareException if device its not an FX3 device with ZTEX firmware.
804
  */
805
// boot
806
    private void resetFX3 ( boolean boot ) throws UsbException, InvalidFirmwareException {
807
        if ( !dev.valid() || !dev.fx3() ) throw new InvalidFirmwareException("Reset using vendor command 0xA1 is not supported by the device");
808
        LibUsb.controlTransfer(handle, (byte)0x40, (byte)(0xA1 & 255), /*value*/ (short)(boot ? 1 : 0), /*index*/ (short)0, ByteBuffer.allocateDirect(0), 100);
809
    }
810
 
811
// ******* resetEzUsb **********************************************************
812
/**
813
  * Resets the EZ-USB and manages the renumeration process.
814
  * <p>
815
  * After the reset the renumeration starts.
816
  * During this process the device disappears from the bus and a new one
817
  * occurs which will be assigned to this class automatically (instead of the disappeared one).
818
  * @throws FirmwareUploadException If an error occurred while attempting to reset the EZ-USB
819
  * @throws UsbException if a communication error occurs.
820
  * @throws InvalidFirmwareException if ZTEX descriptor 1 is not available.
821
  * @throws DeviceLostException if a device went lost after renumeration.
822
  */
823
    public void resetEzUsb () throws FirmwareUploadException, UsbException, InvalidFirmwareException, DeviceLostException {
824
        if ( !dev.valid() && dev.fx3() ) {
825
            System.err.println("Warning: Attempting to reset a FX3 device in factory state");
826
            return;
827
        }
828
 
829
// scan the bus for comparison
830
        findOldDevices();
831
 
832
        if ( dev.fx3() ) {
833
            resetFX3(true);
834
        }
835
        else {
836
// reset the EZ-USB
837
            EzUsb.resetFx2(handle,true);
838
            try {
839
                EzUsb.resetFx2(handle,false);           // error (may caused by re-numeration) can be ignored
840
            }
841
            catch ( FirmwareUploadException e ) {
842
            }
843
        }
844
 
845
// find and init new device
846
        initNewDevice( "Device lost after resetting the EZ-USB", true );
847
    }
848
 
849
// ******* resetDevice *********************************************************
850
/**
851
  * Performs a configuration or bus reset. This method is used to synchronize data toggles at start-up of the host software.
852
  * @param force True enforces a bus reset. By default a configuration reset is tried first and if it fails, a bus reset is performed.
853
  * @throws UsbException if a communication error occurs.
854
  */
855
    public void resetDevice (boolean force) throws FirmwareUploadException, UsbException, InvalidFirmwareException, DeviceLostException {
856
        int result;
857
        if ( ! force ) {
858
            result = LibUsb.setConfiguration(handle(), -1);
859
            if ( result < 0 ) {
860
                System.err.println("Warning: Resetting configuration failed: " + LibUsb.strError(result)+ " trying bus reset");
861
                force = true;
862
            }
863
        }
864
        if ( force ) {
865
            result = LibUsb.resetDevice(handle());
866
            if (result != LibUsb.SUCCESS) throw new UsbException(dev.dev(), "Bus reset failed", result);
867
        }
868
 
869
    }
870
 
871
// ******* toString ************************************************************
872
/**
873
  * Returns a lot of useful information about the corresponding device.
874
  * @return a lot of useful information about the corresponding device.
875
  */
876
    public String toString () {
877
        return dev.toString();
878
    }
879
 
880
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.