├── .gitignore ├── .idea ├── .gitignore ├── vcs.xml ├── modules.xml ├── misc.xml ├── libraries │ └── lib.xml ├── $PRODUCT_WORKSPACE_FILE$ ├── artifacts │ └── RglComm_jar.xml └── uiDesigner.xml ├── src ├── META-INF │ └── MANIFEST.MF ├── ImageViewer.java ├── RglScan.java ├── WaveViewer.java ├── USBIO.java └── RglComm.java ├── images ├── zadig-2.4.png ├── DG4162 Capture.png ├── DS1102E Capture.png ├── DS4024 Capture.png └── RglComm Screenshot.png ├── lib ├── usb4java-1.3.0.jar ├── commons-lang3-3.8.1.jar ├── libusb4java-1.3.0-linux-arm.jar ├── libusb4java-1.3.0-linux-x86.jar ├── libusb4java-1.3.0-win32-x86.jar ├── libusb4java-1.3.0-linux-x86-64.jar ├── libusb4java-1.3.0-win32-x86-64.jar ├── libusb4java-1.3.0-darwin-x86-64.jar └── libusb4java-1.3.0-linux-aarch64.jar ├── out └── artifacts │ └── RglComm_jar │ └── RglComm.jar ├── RglComm.iml ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: RglComm 3 | 4 | -------------------------------------------------------------------------------- /images/zadig-2.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/images/zadig-2.4.png -------------------------------------------------------------------------------- /lib/usb4java-1.3.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/usb4java-1.3.0.jar -------------------------------------------------------------------------------- /images/DG4162 Capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/images/DG4162 Capture.png -------------------------------------------------------------------------------- /images/DS1102E Capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/images/DS1102E Capture.png -------------------------------------------------------------------------------- /images/DS4024 Capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/images/DS4024 Capture.png -------------------------------------------------------------------------------- /lib/commons-lang3-3.8.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/commons-lang3-3.8.1.jar -------------------------------------------------------------------------------- /images/RglComm Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/images/RglComm Screenshot.png -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-linux-arm.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-linux-arm.jar -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-linux-x86.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-linux-x86.jar -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-win32-x86.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-win32-x86.jar -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-linux-x86-64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-linux-x86-64.jar -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-win32-x86-64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-win32-x86-64.jar -------------------------------------------------------------------------------- /out/artifacts/RglComm_jar/RglComm.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/out/artifacts/RglComm_jar/RglComm.jar -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-darwin-x86-64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-darwin-x86-64.jar -------------------------------------------------------------------------------- /lib/libusb4java-1.3.0-linux-aarch64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wholder/RglComm/HEAD/lib/libusb4java-1.3.0-linux-aarch64.jar -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/libraries/lib.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /RglComm.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Wayne Holder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.idea/$PRODUCT_WORKSPACE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | 1.8 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /.idea/artifacts/RglComm_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/RglComm_jar 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/ImageViewer.java: -------------------------------------------------------------------------------- 1 | import javax.imageio.ImageIO; 2 | import javax.swing.*; 3 | import javax.swing.filechooser.FileNameExtensionFilter; 4 | import java.awt.*; 5 | import java.awt.image.BufferedImage; 6 | import java.io.ByteArrayInputStream; 7 | import java.io.File; 8 | import java.util.prefs.Preferences; 9 | 10 | class ImageViewer extends JFrame { 11 | static class Surface extends JPanel { 12 | BufferedImage img; 13 | 14 | Surface(byte[] data) throws Exception { 15 | ByteArrayInputStream bis = new ByteArrayInputStream(data); 16 | img = ImageIO.read(bis); 17 | setPreferredSize(new Dimension(img.getWidth(null), img.getHeight(null))); 18 | } 19 | 20 | @Override 21 | public void paintComponent(Graphics g) { 22 | Graphics2D g2d = (Graphics2D) g; 23 | g2d.drawImage(img, 0, 0, null); 24 | } 25 | } 26 | 27 | ImageViewer (Preferences prefs, byte[] data) throws Exception { 28 | setTitle("ImageViewer"); 29 | Surface surface = new Surface(data); 30 | add(surface); 31 | JMenuBar menuBar = new JMenuBar(); 32 | setJMenuBar(menuBar); 33 | JMenu menu = new JMenu("File"); 34 | menuBar.add(menu); 35 | JMenuItem save = new JMenuItem("Save as PNG"); 36 | menu.add(save); 37 | save.addActionListener(ev -> { 38 | JFileChooser chooser = new JFileChooser(); 39 | String fileDir = prefs.get("file.dir", null); 40 | if (fileDir != null) { 41 | chooser.setCurrentDirectory(new File(fileDir)); 42 | } 43 | chooser.setDialogType(JFileChooser.SAVE_DIALOG); 44 | chooser.setSelectedFile(new File("screen.png")); 45 | chooser.setFileFilter(new FileNameExtensionFilter("png file","png")); 46 | if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { 47 | File file = chooser.getSelectedFile(); 48 | prefs.put("file.dir", chooser.getCurrentDirectory().toString()); 49 | try { 50 | ImageIO.write(surface.img, "png", file); 51 | } catch (Exception ex) { 52 | ex.printStackTrace(); 53 | } 54 | } 55 | }); 56 | pack(); 57 | setLocationRelativeTo(null); 58 | setVisible(true); 59 | } 60 | } -------------------------------------------------------------------------------- /src/RglScan.java: -------------------------------------------------------------------------------- 1 | import org.usb4java.*; 2 | 3 | class RglScan { 4 | static String doScan () { 5 | StringBuilder buf = new StringBuilder(); 6 | Context context = new Context(); 7 | int result = LibUsb.init(context); 8 | if (result < 0) { 9 | throw new LibUsbException("Unable to initialize libusb", result); 10 | } 11 | DeviceList list = new DeviceList(); 12 | result = LibUsb.getDeviceList(context, list); 13 | if (result < 0) { 14 | throw new LibUsbException("Unable to get device list", result); 15 | } 16 | try { 17 | boolean deviceFound = false; 18 | for (Device device : list) { 19 | DeviceDescriptor desc = new DeviceDescriptor(); 20 | result = LibUsb.getDeviceDescriptor(device, desc); 21 | if (result < 0) { 22 | throw new LibUsbException("Unable to read device descriptor", result); 23 | } 24 | String usbClass = DescriptorUtils.getUSBClassName(desc.bDeviceClass()); 25 | short vend = desc.idVendor(); 26 | short prod = desc.idProduct(); 27 | if (!"hub".equalsIgnoreCase(usbClass) && vend == (short) 0x1AB1) { 28 | deviceFound = true; 29 | buf.append(String.format("\nVendor Id: 0x%04X\nProduct Id: 0x%04X%n", vend, prod)); 30 | DeviceHandle handle = new DeviceHandle(); 31 | if (LibUsb.open(device, handle) >= 0) { 32 | buf.append("Manufacturer: "); 33 | buf.append(LibUsb.getStringDescriptor(handle, desc.iManufacturer())); 34 | buf.append("\nProduct: "); 35 | buf.append(LibUsb.getStringDescriptor(handle, desc.iProduct())); 36 | buf.append("\nSerialNumber: "); 37 | buf.append(LibUsb.getStringDescriptor(handle, desc.iSerialNumber())); 38 | buf.append("\n"); 39 | LibUsb.close(handle); 40 | } 41 | } 42 | } 43 | if (!deviceFound) { 44 | buf.append("No Rigol devices detected\n"); 45 | } 46 | } catch (Exception ex) { 47 | buf.append(ex.getMessage()); 48 | } finally { 49 | LibUsb.freeDeviceList(list, true); 50 | } 51 | LibUsb.exit(context); 52 | return buf.toString(); 53 | } 54 | 55 | public static void main (String[] args) { 56 | System.out.println(doScan()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/WaveViewer.java: -------------------------------------------------------------------------------- 1 | import javax.imageio.ImageIO; 2 | import javax.swing.*; 3 | import javax.swing.filechooser.FileNameExtensionFilter; 4 | import java.awt.*; 5 | import java.awt.geom.Line2D; 6 | import java.awt.geom.Path2D; 7 | import java.awt.image.BufferedImage; 8 | import java.io.File; 9 | import java.util.prefs.Preferences; 10 | 11 | class WaveViewer extends JFrame { 12 | static class Surface extends JPanel { 13 | private BufferedImage img; 14 | 15 | Surface(byte[] data) { 16 | img = new BufferedImage(600, 512, BufferedImage.TYPE_INT_ARGB); 17 | Dimension size = new Dimension(img.getWidth(null), img.getHeight(null)); 18 | setPreferredSize(size); 19 | Graphics2D g2 = img.createGraphics(); 20 | g2.setColor(Color.WHITE); 21 | g2.fillRect(0, 0, size.width, size.height); 22 | RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 23 | hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 24 | g2.setRenderingHints(hints); 25 | g2.setStroke(new BasicStroke((1.0f))); 26 | g2.setPaint(Color.lightGray); 27 | g2.draw(new Line2D.Double(0, 256, 599, 255)); 28 | for (int ii = 0; ii < 256; ii += 64) { 29 | g2.draw(new Line2D.Double(0, 256 + ii, 599, 256 + ii)); 30 | g2.draw(new Line2D.Double(0, 256 - ii, 599, 256 - ii)); 31 | } 32 | g2.setPaint(Color.darkGray); 33 | for (int ii = 60; ii < 600; ii += 60) { 34 | g2.draw(new Line2D.Double(ii, 256 - 5, ii, 256 + 5)); 35 | } 36 | g2.setStroke(new BasicStroke((1.0f))); 37 | g2.setPaint(Color.BLACK); 38 | Path2D.Double path = new Path2D.Double(); 39 | path.moveTo(0, ((int) data[0] & 0xFF) * 2); 40 | for (int ii = 1; ii < data.length; ii++) { 41 | path.lineTo(ii, ((int) data[ii] & 0xFF) * 2); 42 | } 43 | g2.draw(path); 44 | } 45 | 46 | @Override 47 | public void paintComponent(Graphics g) { 48 | Graphics2D g2d = (Graphics2D) g; 49 | g2d.drawImage(img, 0, 0, null); 50 | } 51 | } 52 | 53 | WaveViewer (Preferences prefs, byte[] data) throws Exception { 54 | setTitle("WaveViewer"); 55 | Surface surface = new Surface(data); 56 | add(surface); 57 | JMenuBar menuBar = new JMenuBar(); 58 | setJMenuBar(menuBar); 59 | JMenu menu = new JMenu("File"); 60 | menuBar.add(menu); 61 | JMenuItem save = new JMenuItem("Save as PNG"); 62 | menu.add(save); 63 | save.addActionListener(ev -> { 64 | JFileChooser chooser = new JFileChooser(); 65 | String fileDir = prefs.get("file.dir", null); 66 | if (fileDir != null) { 67 | chooser.setCurrentDirectory(new File(fileDir)); 68 | } 69 | chooser.setDialogType(JFileChooser.SAVE_DIALOG); 70 | chooser.setSelectedFile(new File("screen.png")); 71 | chooser.setFileFilter(new FileNameExtensionFilter("png file","png")); 72 | if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { 73 | File file = chooser.getSelectedFile(); 74 | prefs.put("file.dir", chooser.getCurrentDirectory().toString()); 75 | try { 76 | ImageIO.write(surface.img, "png", file); 77 | } catch (Exception ex) { 78 | ex.printStackTrace(); 79 | } 80 | } 81 | }); 82 | pack(); 83 | setLocationRelativeTo(null); 84 | setVisible(true); 85 | } 86 | } -------------------------------------------------------------------------------- /src/USBIO.java: -------------------------------------------------------------------------------- 1 | import org.usb4java.*; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.nio.ByteOrder; 5 | import java.nio.IntBuffer; 6 | 7 | import static org.usb4java.LibUsb.*; 8 | 9 | /** 10 | * Implements a bulk transfer I/O driver that uses usb4java to communicate with a USB Device 11 | * using the Usb4Java Library. 12 | * 13 | * See: http://usb4java.org, and http://usb4java.org/apidocs/index.html for more info 14 | * 15 | * http://libusb.sourceforge.net/api-1.0/ 16 | */ 17 | 18 | class USBIO { 19 | private static final int TIMEOUT = 500; 20 | private DeviceHandle handle; 21 | private Context context; 22 | private byte iFace, outEnd, inEnd; 23 | short maxPkt; 24 | private boolean handleOpen, contextOpen, interfaceOpen; 25 | 26 | USBIO (short vendorId, short productId) { 27 | context = new Context(); 28 | int result = LibUsb.init(context); 29 | contextOpen = true; 30 | if (result < 0) { 31 | throw new LibUsbException("Unable to initialize libusb", result); 32 | } 33 | DeviceList list = new DeviceList(); 34 | if ((result = LibUsb.getDeviceList(context, list)) < 0) { 35 | throw new LibUsbException("Unable to get device list", result); 36 | } 37 | for (Device device : list) { 38 | DeviceDescriptor desc = new DeviceDescriptor(); 39 | LibUsb.getDeviceDescriptor(device, desc); 40 | String usbClass = DescriptorUtils.getUSBClassName(desc.bDeviceClass()); 41 | short vend = desc.idVendor(); 42 | short prod = desc.idProduct(); 43 | if (!"hub".equalsIgnoreCase(usbClass) && vend == vendorId) { 44 | if (prod == productId) { 45 | handle = new DeviceHandle(); 46 | byte numConfigs = desc.bNumConfigurations(); 47 | for (byte ii = 0; ii < numConfigs; ii++) { 48 | ConfigDescriptor cDesc = new ConfigDescriptor(); 49 | if (LibUsb.getConfigDescriptor(device, ii, cDesc) >= 0) { 50 | Interface[] ifaces = cDesc.iface(); 51 | for (Interface iface : ifaces) { 52 | InterfaceDescriptor[] iDescs = iface.altsetting(); 53 | for (InterfaceDescriptor iDesc : iDescs) { 54 | this.iFace = iDesc.bInterfaceNumber(); 55 | byte numEndpoints = iDesc.bNumEndpoints(); 56 | if (numEndpoints > 0) { 57 | EndpointDescriptor[] eDescs = iDesc.endpoint(); 58 | for (EndpointDescriptor eDesc : eDescs) { 59 | byte endAdd = eDesc.bEndpointAddress(); 60 | byte eAttr = eDesc.bmAttributes(); 61 | if ((eAttr & 0x03) == 2) { 62 | if ((endAdd & 0x80) != 0) { 63 | this.inEnd = endAdd; 64 | } else { 65 | maxPkt = eDesc.wMaxPacketSize(); 66 | this.outEnd = endAdd; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | if ((result = LibUsb.open(device, handle)) >= 0) { 76 | handleOpen = true; 77 | if ((result = LibUsb.claimInterface(handle, iFace)) == LibUsb.SUCCESS) { 78 | interfaceOpen = true; 79 | return; 80 | } else { 81 | if (LibUsb.detachKernelDriver(handle, iFace) == LibUsb.SUCCESS) { 82 | if ((result = LibUsb.claimInterface(handle, iFace)) == LibUsb.SUCCESS) { 83 | interfaceOpen = true; 84 | return; 85 | } 86 | throw new LibUsbException("Unable to claim interface", result); 87 | } 88 | } 89 | LibUsb.close(handle); 90 | handleOpen = false; 91 | } 92 | } 93 | } 94 | } 95 | LibUsb.exit(context); 96 | throw new LibUsbException("Unable to open selected device", result < 0 ? result : ERROR_NOT_FOUND); 97 | } 98 | 99 | void resetDevice () { 100 | if (handle != null) { 101 | LibUsb.resetDevice(handle); 102 | } 103 | } 104 | 105 | void send (byte[] data) { 106 | ByteBuffer outBuf = BufferUtils.allocateByteBuffer(data.length); 107 | outBuf.put(data); 108 | IntBuffer outNum = IntBuffer.allocate(1); 109 | int error; 110 | if ((error = LibUsb.bulkTransfer(handle, outEnd, outBuf, outNum, TIMEOUT)) < 0) { 111 | throw new LibUsbException("Unable to send data", error); 112 | } 113 | } 114 | 115 | byte[] receive () { 116 | ByteBuffer inBuf = ByteBuffer.allocateDirect(maxPkt * 2).order(ByteOrder.LITTLE_ENDIAN); 117 | IntBuffer inNum = IntBuffer.allocate(1); // Used to get bytes read count 118 | int error; 119 | int retry = 3; 120 | do { 121 | if ((error = LibUsb.bulkTransfer(handle, inEnd, inBuf, inNum, TIMEOUT)) >= 0) { 122 | if (inBuf.hasArray()) { 123 | return inBuf.array(); 124 | } else { 125 | int cnt = inNum.get(0); 126 | int cap = inBuf.capacity(); 127 | byte[] data = new byte[cnt]; 128 | for (int ii = 0; ii < cnt && ii < cap; ii++) { 129 | data[ii] = inBuf.get(); 130 | } 131 | inBuf.clear(); 132 | return data; 133 | } 134 | } 135 | } while (error == -7 && --retry > 0); 136 | throw new LibUsbException("Unable to receive data", error); 137 | } 138 | 139 | void close () { 140 | try { 141 | if (interfaceOpen && handleOpen) { 142 | int error = LibUsb.releaseInterface(handle, iFace); 143 | if (error != LibUsb.SUCCESS) { 144 | throw new LibUsbException("Unable to release interface", error); 145 | } 146 | } 147 | } finally { 148 | if (handleOpen) { 149 | LibUsb.close(handle); 150 | handleOpen = false; 151 | } 152 | if (contextOpen) { 153 | LibUsb.exit(context); 154 | contextOpen = false; 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RglComm 2 | 3 |

4 | 5 | **RglComm** is a GUI-based program written in the Java Language that I created to experiment with communicating with and controlling Rigol™ devices using IEEE 488 Commands [USBTMC-USB488](http://sdpha2.ucsd.edu/Lab_Equip_Manuals/usbtmc_usb488_subclass_1_00.pdf) sent over the instrument's USB interface. My eventual goal is to use this code as the basis for a program that can run simple scripts to make various measurements and perform calculations (sort of a poor man's LabVIEW™), so stay tuned if you're interested. However, I'm publishing it here so that others can learn the basic techniques needed to use usb4java to communicate these kinds of devices. My implementation of the USBTMC-USB488 protocol is just enough to enable RglComm to send commands and receive responses and does not implement all the details of the full specification. 6 | 7 | To use RglComm, first select the device to communicate with using the selector, then type the command into the text field and press the Enter key, or press the "**`RUN`**" button. Note; some devices, such as the Rigol DG4162 Function/Arbitrary Waveform Generator make need to be set to "PC" mode in the I/O menu before they will respond to commands: 8 | 9 | #### Precautions 10 | - Be careful when using commends that switch measuring modes, such as issuing a **`:MEASure:CURRent:DC?`** command when the instrument is connected to a voltage source, as this can damage the instrument. 11 | - Using the **`MEASure`** command switch from one mode to another can sometimes result in a read timeout, as it takes time for the DM3058 to internally make the mode change. So, it's better to first use a **`FUNCtion`** command t0 select the measurement mode before issuing a **`MEASure`** command. 12 | - Try to connect all instruments directly to the host computer, as adding intermediate USB hubs can interfere with communication and cause timeout errors. 13 | - Make sure the device's USB I/O Mode is set to '**`PC`**' and not to '**`Printer`**' as it's not possible to communicate with the device when set to Printer Mode. 14 | 15 | #### Commands common to most instruments include: 16 | 17 | - **`*IDN?`** - Queries the equipment ID and returns a String of text info 18 | - **`*CLS`** - Clear Status Register 19 | - **`*RST`** - Resets the instrument to factory defined condition 20 | - **`*WAI`** - Waits until all pending commands are completed, before executing any other commands 21 | 22 | #### Commands for the Rigol DM3058 Digital Multimeter include: 23 | 24 | - **`:FUNCtion:VOLTage:DC`** - Sets DM3058 to measure DC Voltage 25 | - **`:MEASure:VOLTage:DC?`** - Measure DC Voltage 26 | - **`:FUNCtion:VOLTage:AC`** - Sets DM3058 to measure AC Voltage 27 | - **`:MEASure:VOLTage:AC?`** - Measure AC Voltage 28 | - **`:FUNCtion:CURRent:DC`** - Sets DM3058 to measure DC Current 29 | - **`:MEASure:CURRent:DC?`** - Measure DC Current 30 | - **`:FUNCtion:CURRent:AC`** - Sets DM3058 to measure AC Current 31 | - **`:MEASure:CURRent:AC?`** - Measure AC Current 32 | - **`:FUNCtion:RESistance`** - Sets DM3058 to measure Resistance 33 | - **`:MEASure:RESistance?`** - Measure Resistance 34 | 35 | Note: the portions of the commands shown in lower case letters are optional and can be omitted. So, for example, sending the command **`:FUNC:VOLT:DC`** is the same as sending the command **`:FUNCtion:VOLTage:DC`**. Also, multiple commands can be entered as one line by separating each command with a '**_;_**' character. 36 | 37 | #### Commands for a Rigol DS4024 Digital Oscilloscope include: 38 | 39 | - **`:CHANnel1:COUPling?`** - Query coupling mode of Channel 1 (AC,DC,GND) 40 | - **`:CHANnel1:COUPling AC`** - Set coupling mode of Channel to AC 41 | - **`:CHANnel1:DISPlay?`** - Query display state of Channel 1 (1 = On, 0 = Off) 42 | - **`:CHANnel1:DISPlay 1`** - Enable display of Channel 1 43 | - **`:CHANnel1:OFFSet?`** - Query vertical position of Channel 1 44 | - **`:CHANnel1:OFFSet -0.3`** - Set vertical position of Channel 1 to -300mV 45 | - **`:CHANnel1:SCALe?`** - Query vertical scale of Channel 1 46 | - **`:CHANnel1:SCALe 0.5`** - Set vertical scale of Channel 1 to 500mV 47 | - **`:TIMebase:SCALe?`** - Query Timebase Scale 48 | - **`:TIMebase:SCALe 0.00001`** - Set Timebase Scale to 10uS 49 | - **`:DISPlay:DATA?`** - Download and display Screen image from DS4024 (see below) 50 | 51 |

52 | 53 | #### Commands for a Rigol DS1102E Digital Oscilloscope include: 54 | 55 | - **`:WAV:POIN:NOR;:WAVeform:DATA? CH1`** - Select normal mode then display waveform from DS1102E Ch 1 (see below) 56 | - **`:WAV:POIN:NOR;:WAVeform:DATA? CH2`** - Select normal mode then display waveform from DS1102E Ch 2 57 | 58 |

59 | 60 | #### Commands for a Rigol DG4162 Function/Arbitrary Waveform Generator include: 61 | 62 | - **`:SOURce1:FREQuency:FIXed 888888`** - Set Channel 1 Frequency to 888.888 kHz 63 | - **`:OUTPut1:STATe ON`** - Channel 1 Output On 64 | - **`:OUTPut1:STATe OFF`** - Channel 1 Output Off 65 | - **`:SOURce1:VOLTage?`** - Read Channel 1 Amplitude in Volts (pp) 66 | - **`:SOURce1:VOLTage 2.25`** - Channel 1 Amplitude to 2.25 Volts 67 | - **`:SOURce1:FUNCtion:SHAPe?`** - Read Selected Waveform Shape of Channel 1 68 | - **`:SOURce1:FUNCtion:SHAPe SQUare`** - Set Channel 1 Output to Square Wave 69 | - **`:SOURce1:FUNCtion:SHAPe SINusoid`** - Set Channel 1 Output to Sinusoid 70 | - **`:SOURce1:FUNCtion:SHAPe RAMP`** - Set Channel 1 Output to Ramp (Triangle) 71 | - **`:HCOPy:SDUMp:DATA?`** - Download and display Screen image from DG4162 (see below) 72 | 73 |

74 | 75 | #### Supported Devices 76 | 77 | Note: while I designed and tested RglComm with devices made by Rigol Technologies, it might also work with other devices that support IEEE 488 Commands sent over the devices's USB interface. However, at the moment, I have only done basic testing with the following Rigol devices: 78 | 79 | - [**DM3058** Digital Multimeter](https://www.rigolna.com/products/digital-multimeters/dm3000/) - Vendor Id: **`1ab1`**, Product Id: **`09c4`** 80 | - [**DP832** Programmable DC Power Supply](https://www.rigolna.com/products/dc-power-loads/dp800/) - Vendor Id: **`1ab1`**, Product Id: **`0e11`** 81 | - [**DS4024** Digital Oscilloscope](https://www.rigolna.com/products/digital-oscilloscopes/4000/) - Vendor Id: **`1ab1`**, Product Id: **`04b1`** 82 | - [**DS1102E** Digital Oscilloscope](https://www.rigolna.com/products/digital-oscilloscopes/1000/) - Vendor Id: **`1ab1`**, Product Id: **`0588`** 83 | - [**DSA815** Spectrum Analyzer](https://www.rigolna.com/products/spectrum-analyzers/dsa800/) - Vendor Id: **`1ab1`**, Product Id: **`0960`** 84 | - [**DG4162** Function/Arbitrary Waveform Generator](https://www.rigolna.com/products/waveform-generators/dg4000/) - Vendor Id: **`1ab1`**, Product Id: **`0641`** 85 | 86 | If you wish to use other devices, you will need to add them to the "devices" Map in RglComm.java. The utility program RglScan.java (included in .jar file) can be used to scan for Rigol devices that are powered on and connected to the computer. You can type "**`scan`**" into the command text field and then press either the Enter key, or the "**`RUN`**" button. Or, you can run it from the command line like this: 87 | 88 | **`java -cp RglComm.jar RglScan`** 89 | 90 | ### **Requirements** 91 | A [Java JDK or JVM](https://www.java.com/en/) or [OpenJDK](http://openjdk.java.net) version 8, or later must be installed in order to run the code. There is also a [**Runnable JAR file**](https://github.com/wholder/RglComm/blob/master/out/artifacts/RglComm_jar) included in the checked in code that you can download and run without having to compile the cource code. 92 | 93 | #### macOS 94 | On a Mac, just double click the **`RglComm.jar`** file and it should start. However, you'll need to right click on the .jar file and select "Open" the first time you run RglComm due to new Mac OS X security checks. 95 | 96 | #### Windows 97 | Follow [these instructions](https://windowsreport.com/jar-file-windows/) to run the JAR file on Windows. However, you will first need to install device drivers for the Rigol devices you are using. The instructions on this page provides more details, but you can use the automated driver installer [Zadig](https://zadig.akeo.ie) to install a generic driver for each Rigol device using its Vendor and Product Ids, like this: 98 | 99 |

100 | 101 | #### Linux 102 | Follow [these instructions](https://itsfoss.com/run-jar-file-ubuntu-linux/) to run the JAR file on a Linux system. However, you will first need to setup the USB permissions for each device using a [udev-based USB permission rule](http://ask.xmodulo.com/change-usb-device-permission-linux.html). For example, to set USB permissions for the DM3058 Digital Multimeter, create a file named something like "**`50-myusb.rules`**" in the "**`/lib/udev/rules.d/`**" directory that includes the following text: 103 | 104 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="09c4", GROUP="users", MODE="0666" 105 | 106 | This rule identifies the device by using its USB Vendor Id (**`1ab1`**) and Product Id (**`09c4`**). Alternately, you can grant permissions for all Rigol devices by only specifying the Vendor Id (**`1ab1`**) in the file, such as: 107 | 108 | SUBSYSTEMS=="usb", ATTRS{idVendor}=="1ab1", GROUP="users", MODE="0666" 109 | 110 | Then, save the file and restart Linux, or type this command to reload the udev rules: 111 | 112 | sudo udevadm control --reload-rules 113 | 114 | ## Credits 115 | RglComm uses the following Java code to perform some of its functions, or build this project: 116 | - [Usb4Java](http://usb4java.org) is used to perform low-level USB I/O using the USBTMC protocol 117 | - [IntelliJ IDEA from JetBrains](https://www.jetbrains.com/idea/) (my favorite development environment for Java coding. Thanks JetBrains!) 118 | -------------------------------------------------------------------------------- /src/RglComm.java: -------------------------------------------------------------------------------- 1 | import javax.swing.*; 2 | import java.awt.*; 3 | import java.awt.event.*; 4 | import java.io.ByteArrayOutputStream; 5 | import java.text.DecimalFormat; 6 | import java.util.*; 7 | import java.util.List; 8 | import java.util.prefs.Preferences; 9 | 10 | /* 11 | * Test Program to communicate with and control Rigol devices using IEEE 488 Commands 12 | * 13 | * Author: Wayne Holder, 2019 14 | * License: MIT (https://opensource.org/licenses/MIT) 15 | */ 16 | 17 | public class RglComm extends JFrame { 18 | private transient Preferences prefs = Preferences.userRoot().node(this.getClass().getName()); 19 | private transient boolean running; 20 | private static List devices = new LinkedList<>(); 21 | private JTextArea text = new JTextArea(); 22 | private JTextField command; 23 | private JComboBox select; 24 | private USBIO usb; 25 | private byte bTag; 26 | 27 | static class Rigol { 28 | String name; 29 | short vend, prod; 30 | 31 | Rigol (String name, int vend, int prod) { 32 | this.name = name; 33 | this.vend = (short) vend; 34 | this.prod = (short) prod; 35 | } 36 | 37 | public String toString () { 38 | return name; 39 | } 40 | } 41 | 42 | static { 43 | // Selector Description VendId ProdId 44 | devices.add(new Rigol("DM3058 Digital Multimeter", 0x1AB1, 0x09C4)); 45 | devices.add(new Rigol("DP832 Prog DC Power Supply", 0x1AB1, 0x0E11)); 46 | devices.add(new Rigol("DS4024 Digital Oscilloscope", 0x1AB1, 0x04B1)); 47 | devices.add(new Rigol("DS1102E Digital Oscilloscope", 0x1AB1, 0x0588)); 48 | devices.add(new Rigol("DSA815 Spectrum Analyzer", 0x1AB1, 0x0960)); 49 | devices.add(new Rigol("DG4162 Func/Wave Generator", 0x1AB1, 0x0641)); // Shows as PID 0x0588 in "Printer" mode 50 | devices.add(new Rigol("DS1054Z Digital Oscilloscope", 0x1AB1, 0x04CE)); // Not verified 51 | } 52 | 53 | class PopMenuTextField extends JTextField { 54 | private Map shortcuts = new LinkedHashMap<>(); 55 | { 56 | shortcuts.put("Identify", "*IDN?"); 57 | shortcuts.put("Clear Error", "*CLS"); 58 | shortcuts.put("DS1102E/Wave Capture Ch1", ":WAV:POIN:MODE NOR;:WAVeform:DATA? CH1"); 59 | shortcuts.put("DS1102E/Wave Capture Ch2", ":WAV:POIN:MODE NOR;:WAVeform:DATA? CH2"); 60 | shortcuts.put("DS4024/Screen Capture", ":DISP:DATA?"); 61 | shortcuts.put("DG4162/Screen Capture", ":HCOP:SDUM:DATA?"); 62 | shortcuts.put("DM3058/Measure DC Voltage", ":FUNC:VOLT:DC;DLY1;:MEAS:VOLT:DC?"); 63 | shortcuts.put("DM3058/Measure AC Voltage", ":FUNC:VOLT:AC;DLY1;:MEAS:VOLT:AC?"); 64 | shortcuts.put("DM3058/Measure Resistance", ":FUNC:RES;DLY1;:MEAS:RES?"); 65 | } 66 | 67 | PopMenuTextField (JComboBox select) { 68 | setToolTipText("Right click for shortcut commands"); 69 | addMouseListener(new MouseAdapter() { 70 | public void mouseReleased (MouseEvent ev1) { 71 | processMouse(ev1); 72 | } 73 | public void mousePressed (MouseEvent ev1) { 74 | processMouse(ev1); 75 | } 76 | void processMouse (MouseEvent ev1) { 77 | if (ev1.isPopupTrigger()) { 78 | Rigol item = (Rigol) select.getSelectedItem(); 79 | JPopupMenu menu = new JPopupMenu(); 80 | boolean addSep = true; 81 | for (String key : shortcuts.keySet()) { 82 | String[] parts = key.split("/"); 83 | JMenuItem menuItem = null; 84 | if (parts.length == 1) { 85 | // Add common commands 86 | menuItem = new JMenuItem(key); 87 | } else if (parts.length == 2 && item != null) { 88 | if (addSep) { 89 | menu.addSeparator(); 90 | addSep = false; 91 | } 92 | // Add device-specific commands 93 | String[] tmp = item.name.split(" "); 94 | if (tmp.length >= 2 && tmp[0].equals(parts[0])) { 95 | menuItem = new JMenuItem(parts[1]); 96 | } 97 | } 98 | if (menuItem != null) { 99 | menu.add(menuItem); 100 | menuItem.addActionListener(ev2 -> { 101 | setText(shortcuts.get(key)); 102 | runCommand(); 103 | }); 104 | } 105 | } 106 | menu.show(ev1.getComponent(), ev1.getX(), ev1.getY()); 107 | } 108 | } 109 | }); 110 | } 111 | } 112 | 113 | public static void main (String[] args) { 114 | new RglComm(); 115 | } 116 | 117 | private void doCommand () { 118 | String cmd = command.getText(); 119 | if ("scan".equalsIgnoreCase(cmd)) { 120 | appendLine(RglScan.doScan()); 121 | } else { 122 | running = true; 123 | try { 124 | Rigol sel = (Rigol) select.getSelectedItem(); 125 | if (sel == null) { 126 | return; 127 | } 128 | usb = new USBIO(sel.vend, sel.prod); 129 | command.setText(""); 130 | String[] parts = cmd.split(";"); 131 | for (int ii = 0; ii < parts.length; ii++) { 132 | boolean doPrint = ii == parts.length - 1; 133 | cmd = parts[ii]; 134 | if (cmd.length() >= 3 && cmd.startsWith("DLY")) { 135 | int seconds = cmd.length() > 3 ? Integer.parseInt(cmd.substring(3)) : 1; 136 | try { 137 | Thread.sleep(seconds * 1000); 138 | } catch (InterruptedException ex) { 139 | ex.printStackTrace(); 140 | } 141 | continue; 142 | } 143 | if (doPrint) { 144 | appendLine("Snd: " + cmd); 145 | } 146 | byte[] rsp = sendCmd(cmd + '\n'); 147 | if (rsp != null) { 148 | int pLen = prefixLength(rsp); 149 | if (pLen > 0) { 150 | String prefix = new String(Arrays.copyOf(rsp, pLen)); 151 | byte[] body = Arrays.copyOfRange(rsp, pLen, rsp.length); 152 | if (body[0] == 'B' && body[1] == 'M') { 153 | // :DISPlay:DATA? 154 | appendLine("Rsp: BMP image received: " + prefix); 155 | new ImageViewer(prefs, body); 156 | } else if (body[0] == (byte) 0xFF && body[1] == (byte) 0xD8) { 157 | // :HCOPy:SDUMp:DATA? 158 | appendLine("Rsp: JPG image received: " + prefix); 159 | new ImageViewer(prefs, body); 160 | } else { 161 | if (body.length == 600) { 162 | appendLine("Rsp: Waveform received: " + prefix); 163 | new WaveViewer(prefs, body); 164 | } else { 165 | appendLine("Rsp: Waveform received: " + prefix + " but too large to display"); 166 | } 167 | } 168 | } else { 169 | if (doPrint) { 170 | if (rsp.length > 0) { 171 | String value = new String(rsp).trim(); 172 | try { 173 | double dVal = Double.parseDouble(value); 174 | DecimalFormat fmt = new DecimalFormat("#.#########"); 175 | value += " (" + fmt.format(dVal) + ")"; 176 | } catch (NumberFormatException ex) { 177 | // Ignore 178 | } 179 | appendLine("Rsp: " + value); 180 | } 181 | } 182 | } 183 | } 184 | } 185 | } catch (Exception ex) { 186 | appendLine("Err: " + ex.toString()); 187 | ex.printStackTrace(); 188 | usb.resetDevice(); 189 | } finally { 190 | if (usb != null) { 191 | usb.close(); 192 | } 193 | running = false; 194 | } 195 | } 196 | } 197 | 198 | private int prefixLength (byte[] data) { 199 | if (data.length >= 2 && data[0] == '#' && data[1] >= '0' && data[1] <= '9') { 200 | int len = (char) data[1] - '0'; 201 | if (data.length >= len + 2) { 202 | for (int ii = 2; ii < len; ii++) { 203 | if (data[ii] < '0' || data[ii] > '9') { 204 | return 0; 205 | } 206 | } 207 | return len + 2; 208 | } 209 | } 210 | return 0; 211 | } 212 | 213 | private RglComm () { 214 | super("RglComm"); 215 | select = new JComboBox<>(devices.toArray(new Rigol[0])); 216 | text.setFont(getCodeFont(12)); 217 | text.setColumns(40); 218 | text.setRows(20); 219 | text.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 220 | text.setEditable(false); 221 | JScrollPane scroll = new JScrollPane(text, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 222 | add(scroll, BorderLayout.CENTER); 223 | JPanel controls = new JPanel(new FlowLayout()); 224 | command = new PopMenuTextField(select); 225 | command.setText("*IDN?"); 226 | command.setColumns(30); 227 | controls.add(command); 228 | try { 229 | select.setSelectedIndex(prefs.getInt("select", 0)); 230 | } catch (Exception ex) { 231 | // Ignore 232 | } 233 | select.addActionListener(ev -> prefs.putInt("select", select.getSelectedIndex())); 234 | controls.add(select); 235 | JButton run = new JButton("RUN"); 236 | run.addActionListener(e -> runCommand()); 237 | command.addKeyListener(new KeyAdapter() { 238 | @Override 239 | public void keyPressed(KeyEvent ev) { 240 | if(ev.getKeyCode() == KeyEvent.VK_ENTER) { 241 | runCommand(); 242 | } 243 | } 244 | }); 245 | controls.add(run); 246 | add(controls, BorderLayout.SOUTH); 247 | setLocationRelativeTo(null); 248 | setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 249 | pack(); 250 | setLocation(prefs.getInt("window.x", 10), prefs.getInt("window.y", 10)); 251 | // Track window resize/move events and save in prefs 252 | addComponentListener(new ComponentAdapter() { 253 | public void componentMoved (ComponentEvent ev) { 254 | Rectangle bounds = ev.getComponent().getBounds(); 255 | prefs.putInt("window.x", bounds.x); 256 | prefs.putInt("window.y", bounds.y); 257 | } 258 | }); 259 | setVisible(true); 260 | } 261 | 262 | private void runCommand () { 263 | if (!running){ 264 | Thread worker = new Thread(this::doCommand); 265 | worker.start(); 266 | } 267 | } 268 | 269 | private static Font getCodeFont (int points) { 270 | String os = System.getProperty("os.name").toLowerCase(); 271 | if (os.contains("win")) { 272 | return new Font("Consolas", Font.PLAIN, points); 273 | } else if (os.contains("mac")) { 274 | return new Font("Menlo", Font.PLAIN, points); 275 | } else if (os.contains("linux")) { 276 | return new Font("Courier", Font.PLAIN, points); 277 | } else { 278 | return new Font("Courier", Font.PLAIN, points); 279 | } 280 | } 281 | 282 | private byte[] sendCmd (String cmd) { 283 | //System.out.print("Block Size: " + usb.maxPkt); 284 | // Note: making blockSize larger than 128 breaks communication with some devices 285 | int blockSize = Math.min(usb.maxPkt, 512); 286 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); 287 | for (int idx = 0; idx < cmd.length(); idx += blockSize) { 288 | buf.reset(); 289 | int pktSize = Math.min(blockSize, cmd.length() - idx); 290 | byte term = (byte) (idx + blockSize >= cmd.length() ? 0x01 : 0x00); 291 | bTag++; 292 | buf.write(1); // 0: MsgID 293 | buf.write(bTag); // 1: bTag 294 | buf.write(bTag ^ 0xFF); // 2: bTagInverse 295 | buf.write(0x00); // 3: Reserved 296 | buf.write(pktSize & 0xFF); // 4: TransferSize 297 | buf.write(pktSize >> 8); // 5: TransferSize 298 | buf.write(0x00); // 6: TransferSize 299 | buf.write(0x00); // 7: TransferSize 300 | buf.write(term); // 8: bmTransfer Attributes (EOM is set on last packet) 301 | buf.write(0x00); // 9: Reserved(0x00) 302 | buf.write(0x00); // 10: Reserved(0x00) 303 | buf.write(0x00); // 11: Reserved(0x00) 304 | for (int ii = 0; ii < pktSize; ii++) { 305 | buf.write(cmd.charAt(idx + ii)); 306 | } 307 | while ((buf.size() & 0x03) != 0) { 308 | buf.write(0x00); // Pad to multiple of 4 309 | } 310 | if (buf.size() > blockSize) { 311 | throw new IllegalStateException("buf.size(): " + buf.size() + " > " + "blockSize" + blockSize); 312 | } 313 | usb.send(buf.toByteArray()); 314 | } 315 | if (cmd.contains("?")) { 316 | bTag++; 317 | ByteArrayOutputStream rec = new ByteArrayOutputStream(); 318 | buf.reset(); 319 | buf.write(2); // 0: MsgID 320 | buf.write(bTag); // 1: bTag 321 | buf.write(bTag ^ 0xFF); // 2: bTagInverse 322 | buf.write(0x00); // 3: Reserved 323 | buf.write(blockSize & 0xFF); // 4: TransferSize 324 | buf.write(blockSize >> 8); // 5: TransferSize 325 | buf.write(0x00); // 6: TransferSize 326 | buf.write(0x00); // 7: TransferSize 327 | buf.write(0x00); // 8: bmTransfer Attributes 328 | buf.write(0x00); // 9: Reserved(0x00) 329 | buf.write(0x00); // 10: Reserved(0x00) 330 | buf.write(0x00); // 11: Reserved(0x00) 331 | byte[] data; 332 | do { 333 | if (buf.size() > blockSize) { 334 | throw new IllegalStateException("buf.size(): " + buf.size() + " > " + "blockSize" + blockSize); 335 | } 336 | usb.send(buf.toByteArray()); 337 | // delay(50); 338 | data = usb.receive(); 339 | //int size = ((int) data[4] & 0xFF) + (((int) data[5] & 0xFF) << 8); 340 | for (int ii = 12; ii < data.length; ii++) { 341 | rec.write(data[ii]); 342 | } 343 | } while (data[8] == 0); 344 | return rec.toByteArray(); 345 | } 346 | return null; 347 | } 348 | 349 | private void appendLine (String line) { 350 | text.append(line + "\n"); 351 | text.setCaretPosition(text.getDocument().getLength()); 352 | } 353 | } 354 | --------------------------------------------------------------------------------