search for Ftdi shared library in build/ first
[slipway.git] / src / com / ftdi / usb / FtdiUart.java
1 package com.ftdi.usb;
2 import java.io.*;
3
4 /**
5  *  A Java wrapper around libftdi.
6  *
7  *  Note: blocking reads are currently implemented by busy-waiting.
8  *  This is really ugly.  Check the linux kernel source to see how to
9  *  get libftdi to do it properly.
10  */
11 public class FtdiUart {
12
13     static {
14         try {
15             File f = new File("build/"+System.mapLibraryName("FtdiUartNative"));
16             if (f.exists()) System.load(f.getAbsolutePath());
17             else System.loadLibrary("FtdiUartNative");
18         } catch (Exception e) {
19             throw new RuntimeException();
20         }
21     }
22
23     private SWIGTYPE_p_ftdi_context context = FtdiUartNative.new_ftdi_context();
24
25     public FtdiUart(int vendorId, int productId, int baud) throws IOException {
26         FtdiUartNative.ftdi_init(context);
27         FtdiUartNative.ftdi_usb_open(context, vendorId, productId);
28         FtdiUartNative.ftdi_usb_reset(context);
29         FtdiUartNative.ftdi_set_baudrate(context, baud);
30         FtdiUartNative.ftdi_set_line_property(context, 8, 0, 0);
31         FtdiUartNative.ftdi_setflowctrl(context, (1<<8));
32         purge();
33     }
34
35     /** the output stream to the uart or dbus pins (depending on mode) */
36     public OutputStream getOutputStream() { return out; }
37
38     /** the input stream from the uart or dbus pins (depending on mode) */
39     public InputStream  getInputStream() { return in; }
40
41     /**
42      *  Switch to uart mode, with read/write access to four CBUS lines.
43      *  This function is used to write to the CBUS lines (re-invoke it to change their state).
44      *  I think readPins() is used to read from them, but I'm not sure.
45      *
46      *  @param cbus_mask a four-bit mask; set bit=1 to write to a CBUS line, bit=0 to read from it
47      *  @param cbus_bits a four-bit mask; the bits to assert on the write-enabled CBUS lines
48      */
49     public synchronized void uart_and_cbus_mode(int cbus_mask, int cbus_bits) throws IOException {
50         FtdiUartNative.ftdi_set_bitmode(context, (short)((cbus_mask << 4) | cbus_bits), (short)0x20);
51         FtdiUartNative.ftdi_setflowctrl(context, (1<<8));
52     }
53
54     /**
55      *  Switch to dbus mode; CBUS lines will be released (ie they will float).
56      *  Use getInputStream()/getOutputStream() to read/write the eight DBUS lines.
57      * 
58      *  @param dbus_mask an eight-bit mask; set bit=1 to write to a DBUS line, bit=0 to read from it
59      */
60     public synchronized void dbus_mode(int dbus_mask) throws IOException {
61         FtdiUartNative.ftdi_set_bitmode(context, (short)dbus_mask, (short)0x01);
62     }
63
64     public synchronized void setBitRate(int bitRate) throws IOException {
65         FtdiUartNative.ftdi_set_baudrate(context, bitRate);
66     }
67
68     /** returns the instantaneous value present on the DBUS pins */
69     public synchronized int readPins() throws IOException {
70         getOutputStream().flush();
71         byte[] b = new byte[1];
72         FtdiUartNative.ftdi_read_pins(context, b);
73         return b[0];
74     }
75
76     /** purge the on-chip buffers */
77     public synchronized void purge() throws IOException {
78         FtdiUartNative.ftdi_usb_purge_buffers(context);
79     }
80
81     private final InputStream in = new InputStream() {
82             public int available() throws IOException {
83                 // FIXME
84                 return 0;
85             }
86             public int read() throws IOException {
87                 byte[] b = new byte[1];
88                 int result = 0;
89                 while(result==0) result = read(b, 0, 1);
90                 return b[0] & 0xff;
91             }
92             public int read(byte[] b, int off, int len) throws IOException {
93                 // FIXME: blocking reads?
94                 int result = 0;
95                 while(true) {
96                     if (len==0) return 0;
97                     byte[] b0 = new byte[len];
98                     synchronized(FtdiUart.this) {
99                         result = FtdiUartNative.ftdi_read_data(context, b0, len);
100                     }
101                     if (result>0) {
102                         System.arraycopy(b0, 0, b, off, result);
103                         return result;
104                     }
105                     try { Thread.sleep(50); } catch (Exception e) { e.printStackTrace(); } 
106                 }
107             }
108         };
109
110     private final OutputStream out = new BufferedOutputStream(new OutputStream() {
111             public void write(int b) throws IOException {
112                 byte[] d = new byte[1];
113                 d[0] = (byte)b;
114                 write(d, 0, 1);
115             }
116             public void write(byte[] b, int off, int len) throws IOException {
117                 byte[] b2 = new byte[64];
118                 while(len > 0) {
119                     System.arraycopy(b, off, b2, 0, Math.min(b2.length, len));
120                     int result;
121                     synchronized(FtdiUart.this) {
122                         result = FtdiUartNative.ftdi_write_data(context, b2, Math.min(b2.length, len));
123                     }
124                     off += result;
125                     len -= result;
126                 }
127             }
128         });
129 }