From: Keith Packard Date: Wed, 28 Jul 2010 18:20:22 +0000 (-0700) Subject: Merge branch 'macos' X-Git-Tag: debian/0.6+268+gd0fd53b~12 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=172a2817dde6718724f2b5fad5a7761801446fa0;hp=f2a006fd98045066bdf429cc142d033e9feb0a8f Merge branch 'macos' --- diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 2850e909..54dc777a 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view +SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view libaltos altosui diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 66800c5c..0e7d01da 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -18,13 +18,38 @@ package altosui; import java.lang.*; import java.util.*; +import libaltosJNI.*; -public class AltosDevice { - String tty; /* suitable to be passed to AltosSerial.connect */ - String manufacturer; - String product; - int serial; - int idProduct; - int idVendor; +public class AltosDevice extends altos_device { + public String toString() { + return String.format("%-20.20s %4d %s", + getProduct(), getSerial(), getPath()); + } + + static { + System.loadLibrary("altos"); + libaltos.altos_init(); + } + static AltosDevice[] list(String product) { + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + SWIGTYPE_p_altos_file file; + + for (;;) { + AltosDevice device = new AltosDevice(); + if (libaltos.altos_list_next(list, device) == 0) + break; + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + AltosDevice[] devices = new AltosDevice[device_list.size()]; + for (int i = 0; i < device_list.size(); i++) + devices[i] = device_list.get(i); + return devices; + } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index cb1eef8b..eb70877c 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -20,15 +20,17 @@ package altosui; import java.lang.*; import java.util.*; import javax.swing.*; +import libaltosJNI.libaltos; +import libaltosJNI.altos_device; +import libaltosJNI.SWIGTYPE_p_altos_file; +import libaltosJNI.SWIGTYPE_p_altos_list; import altosui.AltosDevice; -import altosui.AltosDeviceLinux; public class AltosDeviceDialog { - static AltosDevice show (JFrame frame, String product) { - AltosDevice[] devices = null; - if (System.getProperty("os.name").startsWith("Linux")) - devices = AltosDeviceLinux.list(product); + static altos_device show (JFrame frame, String product) { + AltosDevice[] devices; + devices = AltosDevice.list(product); if (devices != null & devices.length > 0) { Object o = JOptionPane.showInputDialog(frame, "Select a device", @@ -37,7 +39,7 @@ public class AltosDeviceDialog { null, devices, devices[0]); - return (AltosDevice) o; + return (altos_device) o; } else { return null; } diff --git a/ao-tools/altosui/AltosDeviceLinux.java b/ao-tools/altosui/AltosDeviceLinux.java deleted file mode 100644 index ffc70aff..00000000 --- a/ao-tools/altosui/AltosDeviceLinux.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package altosui; -import java.lang.*; -import java.io.*; -import java.util.*; -import altosui.AltosDevice; - -public class AltosDeviceLinux extends AltosDevice { - - String load_string(File file) { - try { - FileInputStream in = new FileInputStream(file); - String result = ""; - int c; - try { - while ((c = in.read()) != -1) { - if (c == '\n') - break; - result = result + (char) c; - } - return result; - } catch (IOException ee) { - return ""; - } - } catch (FileNotFoundException ee) { - return ""; - } - } - String load_string(File dir, String name) { - return load_string(new File(dir, name)); - } - - int load_hex(File file) { - try { - return Integer.parseInt(load_string(file).trim(), 16); - } catch (NumberFormatException ee) { - return -1; - } - } - - int load_hex(File dir, String name) { - return load_hex(new File(dir, name)); - } - - int load_dec(File file) { - try { - return Integer.parseInt(load_string(file).trim()); - } catch (NumberFormatException ee) { - return -1; - } - } - - int load_dec(File dir, String name) { - return load_dec(new File(dir, name)); - } - - String usb_tty(File sys_dir) { - String base = sys_dir.getName(); - int num_configs = load_hex(sys_dir, "bNumConfigurations"); - int num_inters = load_hex(sys_dir, "bNumInterfaces"); - for (int config = 1; config <= num_configs; config++) { - for (int inter = 0; inter < num_inters; inter++) { - String endpoint_base = String.format("%s:%d.%d", - base, config, inter); - File endpoint_full = new File(sys_dir, endpoint_base); - - File[] namelist; - - /* Check for tty:ttyACMx style names */ - class tty_colon_filter implements FilenameFilter { - public boolean accept(File dir, String name) { - return name.startsWith("tty:"); - } - } - namelist = endpoint_full.listFiles(new tty_colon_filter()); - if (namelist != null && namelist.length > 0) - return new File ("/dev", namelist[0].getName().substring(4)).getPath(); - - /* Check for tty/ttyACMx style names */ - class tty_filter implements FilenameFilter { - public boolean accept(File dir, String name) { - return name.startsWith("tty"); - } - } - File tty_dir = new File(endpoint_full, "tty"); - namelist = tty_dir.listFiles(new tty_filter()); - if (namelist != null && namelist.length > 0) - return new File ("/dev", namelist[0].getName()).getPath(); - } - } - return null; - } - - public AltosDeviceLinux (File sys) { - sys = sys; - manufacturer = load_string(sys, "manufacturer"); - product = load_string(sys, "product"); - serial = load_dec(sys, "serial"); - idProduct = load_hex(sys, "idProduct"); - idVendor = load_hex(sys, "idVendor"); - tty = usb_tty(sys); - } - - public String toString() { - return String.format("%-20s %6d %-15s", product, serial, tty == null ? "" : tty); - } - static public AltosDeviceLinux[] list() { - LinkedList devices = new LinkedList(); - - class dev_filter implements FilenameFilter{ - public boolean accept(File dir, String name) { - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (Character.isDigit(c)) - continue; - if (c == '-') - continue; - if (c == '.' && i != 1) - continue; - return false; - } - return true; - } - } - - File usb_devices = new File("/sys/bus/usb/devices"); - File[] devs = usb_devices.listFiles(new dev_filter()); - if (devs != null) { - for (int e = 0; e < devs.length; e++) { - AltosDeviceLinux dev = new AltosDeviceLinux(devs[e]); - if (dev.idVendor == 0xfffe && dev.tty != null) { - devices.add(dev); - } - } - } - AltosDeviceLinux[] foo = new AltosDeviceLinux[devices.size()]; - for (int e = 0; e < devices.size(); e++) - foo[e] = devices.get(e); - return foo; - } - - static public AltosDeviceLinux[] list(String model) { - AltosDeviceLinux[] devices = list(); - if (model != null) { - LinkedList subset = new LinkedList(); - for (int i = 0; i < devices.length; i++) { - if (devices[i].product.startsWith(model)) - subset.add(devices[i]); - } - devices = new AltosDeviceLinux[subset.size()]; - for (int e = 0; e < subset.size(); e++) - devices[e] = subset.get(e); - } - return devices; - } -} diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index c3b368e2..f8eb5f48 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -90,6 +90,9 @@ public class AltosGPS { gps_connected = true; gps_time = new AltosGPSTime(); i++; + } else if ((words[i]).equals("not-connected")) { + gps_time = new AltosGPSTime(); + i++; } else if (words.length >= 40) { gps_locked = true; gps_connected = true; @@ -106,6 +109,7 @@ public class AltosGPS { v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)")); } else { gps_time = new AltosGPSTime(); + i++; } AltosParse.word(words[i++], "SAT"); int tracking_channels = 0; diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 03ab28c5..e84f5b63 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -26,16 +26,21 @@ import java.io.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.LinkedList; import java.util.Iterator; -import gnu.io.*; import altosui.AltosSerialMonitor; +import libaltosJNI.libaltos; +import libaltosJNI.altos_device; +import libaltosJNI.SWIGTYPE_p_altos_file; +import libaltosJNI.SWIGTYPE_p_altos_list; /* * This class reads from the serial port and places each received * line in a queue. Dealing with that queue is left up to other * threads. */ -class AltosSerialReader implements Runnable { - InputStream serial_in; + +public class AltosSerial implements Runnable { + + SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; Thread input_thread; @@ -46,7 +51,7 @@ class AltosSerialReader implements Runnable { try { for (;;) { - c = serial_in.read(); + c = libaltos.altos_getchar(altos, 0); if (Thread.interrupted()) break; if (c == -1) @@ -70,7 +75,6 @@ class AltosSerialReader implements Runnable { } } } - } catch (IOException e) { } catch (InterruptedException e) { } } @@ -96,16 +100,13 @@ class AltosSerialReader implements Runnable { } public boolean opened() { - return serial_in != null; + return altos != null; } public void close() { - if (serial_in != null) { - try { - serial_in.close(); - } catch (IOException e) { - } - serial_in = null; + if (altos != null) { + libaltos.altos_close(altos); + altos = null; } if (input_thread != null) { try { @@ -117,87 +118,31 @@ class AltosSerialReader implements Runnable { } } - public void open(File name) throws FileNotFoundException { - close(); - serial_in = new FileInputStream(name); - input_thread = new Thread(this); - input_thread.start(); - } - public void open(CommPort c) throws IOException { - close(); - try { - c.enableReceiveTimeout(1000); /* icky. the read method cannot be interrupted */ - } catch (UnsupportedCommOperationException ee) { - } - serial_in = c.getInputStream(); - input_thread = new Thread(this); - input_thread.start(); - } - public AltosSerialReader () { - serial_in = null; - input_thread = null; - line = ""; - monitors = new LinkedList> (); - reply_queue = new LinkedBlockingQueue (); + public void putc(char c) { + libaltos.altos_putchar(altos, c); } -} - -public class AltosSerial { - OutputStream serial_out = null; - AltosSerialReader reader = null; - - CommPort comm_port = null; - - public void close() { - try { - serial_out.close(); - } catch (IOException ee) { - } - reader.close(); - if (comm_port != null) { - comm_port.close(); - } - } - - public void open(File serial_name) throws FileNotFoundException { - reader.open(serial_name); - serial_out = new FileOutputStream(serial_name); - } - - public void open(CommPort c) throws IOException { - reader.open(c); - serial_out = c.getOutputStream(); + public void print(String data) { + for (int i = 0; i < data.length(); i++) + putc(data.charAt(i)); } - public void connect(String port_name) throws IOException, NoSuchPortException, PortInUseException { - comm_port = new RXTXPort(port_name); - open(comm_port); + public void printf(String format, Object ... arguments) { + print(String.format(format, arguments)); } - void init() { - reader = new AltosSerialReader(); - } - - public void add_monitor(LinkedBlockingQueue q) { - reader.add_monitor(q); - } - - public void remove_monitor(LinkedBlockingQueue q) { - reader.remove_monitor(q); + public void open(altos_device device) throws FileNotFoundException { + close(); + altos = libaltos.altos_open(device); + input_thread = new Thread(this); + input_thread.start(); } public AltosSerial() { - init(); - } - - public AltosSerial(File serial_name) throws FileNotFoundException { - init(); - open(serial_name); - } - - public AltosSerial(CommPort comm_port) throws IOException { - init(); - open(comm_port); + altos = null; + input_thread = null; + line = ""; + monitors = new LinkedList> (); + reply_queue = new LinkedBlockingQueue (); } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 43c40799..3dfc8952 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -27,7 +27,6 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import gnu.io.*; import altosui.AltosSerial; import altosui.AltosSerialMonitor; @@ -38,6 +37,8 @@ import altosui.AltosPreferences; import altosui.AltosLog; import altosui.AltosVoice; +import libaltosJNI.*; + class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; private Object[] data = { 0, "idle", 0, 0 }; @@ -220,16 +221,8 @@ public class AltosUI extends JFrame { flightInfoModel[col].addRow(name, value); } - public void info_add_row(int col, String name, String format, Object value) { - flightInfoModel[col].addRow(name, String.format(format, value)); - } - - public void info_add_row(int col, String name, String format, Object v1, Object v2) { - flightInfoModel[col].addRow(name, String.format(format, v1, v2)); - } - - public void info_add_row(int col, String name, String format, Object v1, Object v2, Object v3) { - flightInfoModel[col].addRow(name, String.format(format, v1, v2, v3)); + public void info_add_row(int col, String name, String format, Object... parameters) { + flightInfoModel[col].addRow(name, String.format(format, parameters)); } public void info_add_deg(int col, String name, double v, int pos, int neg) { @@ -345,48 +338,57 @@ public class AltosUI extends JFrame { class IdleThread extends Thread { private AltosState state; + int reported_landing; + + public void report(boolean last) { + if (state == null) + return; + + /* reset the landing count once we hear about a new flight */ + if (state.state < AltosTelemetry.ao_flight_drogue) + reported_landing = 0; + + /* Shut up once the rocket is on the ground */ + if (reported_landing > 2) { + return; + } + + /* If the rocket isn't on the pad, then report height */ + if (state.state > AltosTelemetry.ao_flight_pad) { + voice.speak("%d meters", (int) (state.height + 0.5)); + } else { + reported_landing = 0; + } + + /* If the rocket is coming down, check to see if it has landed; + * either we've got a landed report or we haven't heard from it in + * a long time + */ + if (!state.ascent && + (last || + System.currentTimeMillis() - state.report_time >= 15000 || + state.state == AltosTelemetry.ao_flight_landed)) + { + if (Math.abs(state.baro_speed) < 20 && state.height < 100) + voice.speak("rocket landed safely"); + else + voice.speak("rocket may have crashed"); + if (state.gps != null) + voice.speak("bearing %d degrees, range %d meters", + (int) (state.from_pad.bearing + 0.5), + (int) (state.from_pad.distance + 0.5)); + ++reported_landing; + } + } public void run () { - int reported_landing = 0; + reported_landing = 0; state = null; try { for (;;) { Thread.sleep(10000); - if (state == null) - continue; - - /* reset the landing count once we hear about a new flight */ - if (state.state < AltosTelemetry.ao_flight_drogue) - reported_landing = 0; - - /* Shut up once the rocket is on the ground */ - if (reported_landing > 2) - continue; - - /* If the rocket isn't on the pad, then report height */ - if (state.state > AltosTelemetry.ao_flight_pad) { - voice.speak(String.format("%d meters", (int) (state.height + 0.5))); - } - - /* If the rocket is coming down, check to see if it has landed; - * either we've got a landed report or we haven't heard from it in - * a long time - */ - if (!state.ascent && - (System.currentTimeMillis() - state.report_time > 10000 || - state.state == AltosTelemetry.ao_flight_landed)) - { - if (Math.abs(state.baro_speed) < 20 && state.height < 100) - voice.speak("rocket landed safely"); - else - voice.speak("rocket may have crashed"); - if (state.gps != null) - voice.speak(String.format("bearing %d degrees, range %d meters", - (int) (state.from_pad.bearing + 0.5), - (int) (state.from_pad.distance + 0.5))); - ++reported_landing; - } + report(false); } } catch (InterruptedException ie) { } @@ -400,21 +402,22 @@ public class AltosUI extends JFrame { private void tell(AltosState state, AltosState old_state) { if (old_state == null || old_state.state != state.state) { voice.speak(state.data.state); - switch (state.state) { - case AltosTelemetry.ao_flight_fast: - voice.speak(String.format("max speed %d meters per second", - (int) (state.max_speed + 0.5))); - break; - case AltosTelemetry.ao_flight_drogue: - voice.speak(String.format("max height %d meters", - (int) (state.max_height + 0.5))); - break; + if ((old_state == null || old_state.state <= AltosTelemetry.ao_flight_boost) && + state.state > AltosTelemetry.ao_flight_boost) { + voice.speak("max speed: %d meters per second.", + (int) (state.max_speed + 0.5)); + } else if ((old_state == null || old_state.state < AltosTelemetry.ao_flight_drogue) && + state.state >= AltosTelemetry.ao_flight_drogue) { + voice.speak("max height: %d meters.", + (int) (state.max_height + 0.5)); } } old_state = state; } class DisplayThread extends Thread { + IdleThread idle_thread; + String read() throws InterruptedException { return null; } void close() { } @@ -425,7 +428,8 @@ public class AltosUI extends JFrame { String line; AltosState state = null; AltosState old_state = null; - IdleThread idle_thread = new IdleThread(); + + idle_thread = new IdleThread(); info_reset(); info_finish(); @@ -451,6 +455,11 @@ public class AltosUI extends JFrame { idle_thread.interrupt(); } } + + public void report() { + if (idle_thread != null) + idle_thread.report(true); + } } class DeviceThread extends DisplayThread { @@ -475,31 +484,21 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { - AltosDevice device = AltosDeviceDialog.show(AltosUI.this, "TeleDongle"); + altos_device device = AltosDeviceDialog.show(AltosUI.this, "TeleDongle"); if (device != null) { try { - serial_line.connect(device.tty); + serial_line.open(device); DeviceThread thread = new DeviceThread(serial_line); run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.tty, + device.getPath(), "Cannot open serial port", JOptionPane.ERROR_MESSAGE); - } catch (NoSuchPortException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - device.tty, - "No such serial port", - JOptionPane.ERROR_MESSAGE); - } catch (PortInUseException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - device.tty, - "Port in use", - JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.tty, + device.getPath(), "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); } @@ -517,8 +516,9 @@ public class AltosUI extends JFrame { while ((c = s.read()) != -1) { if (c == '\r') continue; - if (c == '\n') + if (c == '\n') { return line; + } line = line + (char) c; } return null; @@ -554,12 +554,13 @@ public class AltosUI extends JFrame { replay.close(); } catch (IOException ee) { } + report(); } void update(AltosState state) throws InterruptedException { /* Make it run in realtime after the rocket leaves the pad */ if (state.state > AltosTelemetry.ao_flight_pad) - Thread.sleep((int) (state.time_change * 1000)); + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); } } @@ -600,7 +601,7 @@ public class AltosUI extends JFrame { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, filename, - "Cannot open serial port", + "Cannot open telemetry file", JOptionPane.ERROR_MESSAGE); } } diff --git a/ao-tools/altosui/AltosUIIcon.icns b/ao-tools/altosui/AltosUIIcon.icns new file mode 100644 index 00000000..fe49f362 Binary files /dev/null and b/ao-tools/altosui/AltosUIIcon.icns differ diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index e4ea99a2..c39bfb9b 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -47,6 +47,10 @@ public class AltosVoice implements Runnable { } } + public void speak(String format, Object... parameters) { + speak(String.format(format, parameters)); + } + public AltosVoice () { voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 57c889b8..cd123023 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 +CLASSPATH=classes:./* CLASSFILES=\ AltosConvert.class \ AltosFile.class \ @@ -15,24 +15,45 @@ CLASSFILES=\ AltosTelemetry.class \ AltosUI.class \ AltosDevice.class \ - AltosDeviceLinux.class \ AltosDeviceDialog.class \ AltosVoice.class +FREETTSSRC=/home/keithp/src/freetts/freetts-1.2.2 +FREETTSLIB=$(FREETTSSRC)/lib +FREETTSJAR= \ + cmudict04.jar \ + cmulex.jar \ + cmu_time_awb.jar \ + cmutimelex.jar \ + cmu_us_kal.jar \ + en_us.jar \ + freetts.jar \ + freetts-jsapi10.jar \ + jsapi.jar + JAVAFLAGS=-Xlint:unchecked -all: $(CLASSFILES) altosui altosui.jar +all: altosui.jar + +$(CLASSFILES): .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui: Makefile - (echo '#!/bin/sh'; \ - echo exec java -cp '"$(CLASSPATH)"' altosui/AltosUI) > $@ - chmod +x $@ +altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Manifest.txt + cd ./classes && jar cfm ../$@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class + +classes/altosui: + mkdir -p classes + ln -s .. classes/altosui + +classes/libaltosJNI: + mkdir -p classes + ln -s ../../libaltos/libaltosJNI classes/libaltosJNI -altosui.jar: $(CLASSFILES) Manifest.txt - cd .. && jar cfm altosui/$@ altosui/Manifest.txt altosui/*.class +$(FREETTSJAR): + ln -s $(FREETTSLIB)/$@ . clean: - rm -f *.class + rm -f *.class $(FREETTSJAR) altosui.jar + rm -rf classes diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 0305fcfb..251ce2a0 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1 +1,2 @@ Main-Class: altosui.AltosUI +Class-Path: freetts.jar diff --git a/ao-tools/altosui/voices.txt b/ao-tools/altosui/voices.txt deleted file mode 100644 index e8825fc3..00000000 --- a/ao-tools/altosui/voices.txt +++ /dev/null @@ -1 +0,0 @@ -com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml new file mode 100644 index 00000000..e19a1e4c --- /dev/null +++ b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml new file mode 100644 index 00000000..5d84e5f0 --- /dev/null +++ b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml @@ -0,0 +1 @@ +org.altusmetrum.altosUi.AltosUI.pkg1.0/Users/keithp/AltosUI.app/Applications/AltosUI.appinstallTo.pathparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml new file mode 100644 index 00000000..1277db62 --- /dev/null +++ b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml @@ -0,0 +1 @@ +AltOS UI/Users/keithp/Documents/AltosUI.pkgorg.altusmetrum01altosui.xmlproperties.title \ No newline at end of file diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile new file mode 100644 index 00000000..0bbd304c --- /dev/null +++ b/ao-tools/libaltos/Makefile @@ -0,0 +1,80 @@ +OS:=$(shell uname) + +ifeq ($(OS),Linux) + +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include + +OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +LIBEXT=so + +endif + +ifeq ($(OS),Darwin) + +DARWIN_CFLAGS=\ + --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \ + -iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \ + -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \ + -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers +DARWIN_LIBS=\ + -framework IOKit -framework CoreFoundation + +OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 +LIBEXT=dylib + +endif + +.SUFFIXES: .java .class + +CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" + +SWIG_DIR=swig_bindings/java +SWIG_FILE=$(SWIG_DIR)/libaltos.swig +SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c + +JNI_DIR=libaltosJNI +JNI_FILE=$(JNI_DIR)/libaltosJNI.java +JNI_SRCS=$(JNI_FILE) \ + $(JNI_DIR)/SWIGTYPE_p_altos_file.java \ + $(JNI_DIR)/SWIGTYPE_p_altos_list.java \ + $(JNI_DIR)/altos_device.java \ + $(JNI_DIR)/libaltos.java + +JAVAFILES=\ + $(JNI_SRCS) + +CLASSFILES = $(JAVAFILES:%.java=%.class) + +JAVAFLAGS=-Xlint:unchecked + +all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) + +.java.class: + javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java + +CFLAGS=$(OS_CFLAGS) -O0 -g -I. + +HEADERS=libaltos.h +SRCS = libaltos.c $(SWIG_WRAP) +OBJS = $(SRCS:%.c=%.o) +LIBS = $(DARWIN_LIBS) + +cjnitest: cjnitest.o $(OBJS) + cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) + +libaltos.$(LIBEXT): $(OBJS) + gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) + +clean: + rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest cjnitest.o + rm -rf swig_bindings libaltosJNI + +$(JNI_FILE): libaltos.i0 $(HEADERS) + mkdir -p $(SWIG_DIR) + mkdir -p libaltosJNI + sed 's;//%;%;' libaltos.i0 $(HEADERS) > $(SWIG_FILE) + swig -java -package libaltosJNI $(SWIG_FILE) + cp swig_bindings/java/*.java libaltosJNI + +$(SWIG_WRAP): $(JNI_FILE) diff --git a/ao-tools/libaltos/cjnitest.c b/ao-tools/libaltos/cjnitest.c new file mode 100644 index 00000000..cd3898ed --- /dev/null +++ b/ao-tools/libaltos/cjnitest.c @@ -0,0 +1,25 @@ +#include +#include "libaltos.h" + +main () +{ + struct altos_device device; + struct altos_list *list; + + altos_init(); + list = altos_list_start(); + while (altos_list_next(list, &device)) { + struct altos_file *file; + int c; + + file = altos_open(&device); + altos_putchar(file, '?'); altos_putchar(file, '\n'); altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar (c); + } + printf ("getchar returns %d\n", c); + altos_close(file); + } + altos_list_finish(list); + altos_fini(); +} diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c new file mode 100644 index 00000000..df0d5b2e --- /dev/null +++ b/ao-tools/libaltos/libaltos.c @@ -0,0 +1,825 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "libaltos.h" +#include +#include +#include + +static int +match_dev(char *product, int serial, struct altos_device *device) +{ + struct altos_list *list; + int i; + + list = altos_list_start(); + if (!list) + return 0; + while ((i = altos_list_next(list, device)) != 0) { + if (product && strncmp (product, device->product, strlen(product)) != 0) + continue; + if (serial && serial != device->serial) + continue; + break; + } + altos_list_finish(list); + return i; +} + +#ifdef DARWIN +/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */ +static char * +altos_strndup (const char *s, size_t n) +{ + size_t len = strlen (s); + char *ret; + + if (len <= n) + return strdup (s); + ret = malloc(n + 1); + strncpy(ret, s, n); + ret[n] = '\0'; + return ret; +} + +#else +#define altos_strndup strndup +#endif + +int +altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) +{ + char *product; + int serial; + char *end; + char *colon; + int ret; + + if (arg) + { + /* check for */ + serial = strtol(arg, &end, 0); + if (end != arg) { + if (*end != '\0') + return 0; + product = NULL; + } else { + /* check for : */ + colon = strchr(arg, ':'); + if (colon) { + product = altos_strndup(arg, colon - arg); + serial = strtol(colon + 1, &end, 0); + if (*end != '\0') + return 0; + } else { + product = arg; + serial = 0; + } + } + } else { + product = NULL; + serial = 0; + } + if (!product && default_product) + ret = match_dev(default_product, serial, device); + if (!ret) + ret = match_dev(product, serial, device); + if (product && product != arg) + free(product); + return ret; +} + +#ifdef LINUX + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +static char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} + +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; + +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct altos_usbdev * +usb_scan_device(char *sys) +{ + struct altos_usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct altos_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product = load_string(sys, "product"); + usbdev->serial = load_dec(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = usb_tty(sys); + return usbdev; +} + +static void +usbdev_free(struct altos_usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product); + /* this can get used as a return value */ + if (usbdev->tty) + free(usbdev->tty); + free(usbdev); +} + +#define USB_DEVICES "/sys/bus/usb/devices" + +static int +dir_filter_dev(const struct dirent *d) +{ + const char *n = d->d_name; + char c; + + while ((c = *n++)) { + if (isdigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && n != d->d_name + 1) + continue; + return 0; + } + return 1; +} + +struct altos_list { + struct altos_usbdev **dev; + int current; + int ndev; +}; + +int +altos_init(void) +{ + return 1; +} + +void +altos_fini(void) +{ +} + +struct altos_list * +altos_list_start(void) +{ + int e; + struct dirent **ents; + char *dir; + struct altos_usbdev *dev; + struct altos_list *devs; + int n; + + devs = calloc(1, sizeof (struct altos_list)); + if (!devs) + return NULL; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = cc_fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + free(dir); + if (dev->idVendor == 0xfffe && dev->tty) { + if (devs->dev) + devs->dev = realloc(devs->dev, + devs->ndev + 1 * sizeof (struct usbdev *)); + else + devs->dev = malloc (sizeof (struct usbdev *)); + devs->dev[devs->ndev++] = dev; + } + } + free(ents); + devs->current = 0; + return devs; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + struct altos_usbdev *dev; + if (list->current >= list->ndev) + return 0; + dev = list->dev[list->current]; + strcpy(device->product, dev->product); + strcpy(device->path, dev->tty); + device->serial = dev->serial; + list->current++; + return 1; +} + +void +altos_list_finish(struct altos_list *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} + +#endif + +#ifdef DARWIN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct altos_list { + io_iterator_t iterator; +}; + +static int +get_string(io_object_t object, CFStringRef entry, char *result, int result_len) +{ + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); + + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; +} + +int +altos_init(void) +{ + return 1; +} + +void +altos_fini(void) +{ +} + +struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc (sizeof (struct altos_list), 1); + CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); + UInt32 vendor = 0xfffe, product = 0x000a; + CFNumberRef vendor_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor); + CFNumberRef product_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product); + io_iterator_t tdIterator; + io_object_t tdObject; + + CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBVendorID), vendor_ref); + CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBProductID), product_ref); + + IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); + + CFRelease(vendor_ref); + CFRelease(product_ref); + return list; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + io_object_t object; + char serial_string[128]; + + for (;;) { + object = IOIteratorNext(list->iterator); + if (!object) + return 0; + + if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) && + get_string (object, CFSTR("USB Product Name"), device->product, sizeof (device->product)) && + get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { + device->serial = atoi(serial_string); + return 1; + } + } +} + +void +altos_list_finish(struct altos_list *list) +{ + IOObjectRelease (list->iterator); + free(list); +} + +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (sizeof (struct altos_file), 1); + int ret; + struct termios term; + + if (!file) + return NULL; + + file->fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->fd < 0) { + perror(device->path); + free(file); + return NULL; + } + ret = tcgetattr(file->fd, &term); + if (ret < 0) { + perror("tcgetattr"); + close(file->fd); + free(file); + return NULL; + } + cfmakeraw(&term); + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; + ret = tcsetattr(file->fd, TCSAFLUSH, &term); + if (ret < 0) { + perror("tcsetattr"); + close(file->fd); + free(file); + return NULL; + } + return file; +} + +void +altos_close(struct altos_file *file) +{ + close(file->fd); + free(file); +} + +int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == USB_BUF_SIZE) { + ret = altos_flush(file); + if (ret) + return ret; + } + file->out_data[file->out_used++] = c; + if (file->out_used == USB_BUF_SIZE) + return altos_flush(file); + return 0; +} + +int +altos_flush(struct altos_file *file) +{ + while (file->out_used) { + int ret; + + ret = write (file->fd, file->out_data, file->out_used); + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + while (file->in_read == file->in_used) { + int ret; + + altos_flush(file); + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret < 0) + return -errno; + file->in_read = 0; + file->in_used = ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* POSIX_TTY */ + +#ifdef USE_LIBUSB +#include +#include +#include +#include + +libusb_context *usb_context; + +int altos_init(void) +{ + int ret; + ret = libusb_init(&usb_context); + if (ret) + return ret; + libusb_set_debug(usb_context, 3); + return 0; +} + +void altos_fini(void) +{ + libusb_exit(usb_context); + usb_context = NULL; +} + +static libusb_device **list; +static ssize_t num, current; + +int altos_list_start(void) +{ + if (list) + altos_list_finish(); + current = 0; + num = libusb_get_device_list(usb_context, &list); + if (num == 0) { + current = num = 0; + list = NULL; + return 0; + } + return 1; +} + +int altos_list_next(struct altos_device *device) +{ + while (current < num) { + struct libusb_device_descriptor descriptor; + libusb_device *usb_device = list[current++]; + + if (libusb_get_device_descriptor(usb_device, &descriptor) == 0) { + if (descriptor.idVendor == 0xfffe) + { + libusb_device_handle *handle; + if (libusb_open(usb_device, &handle) == 0) { + char serial_number[256]; + libusb_get_string_descriptor_ascii(handle, descriptor.iProduct, + device->product, + sizeof(device->product)); + libusb_get_string_descriptor_ascii(handle, descriptor.iSerialNumber, + serial_number, + sizeof (serial_number)); + libusb_close(handle); + device->serial = atoi(serial_number); + device->device = usb_device; + return 1; + } + } + } + } + return 0; +} + +void altos_list_finish(void) +{ + if (list) { + libusb_free_device_list(list, 1); + list = NULL; + } +} + +#define USB_BUF_SIZE 64 + +struct altos_file { + struct libusb_device *device; + struct libusb_device_handle *handle; + int out_ep; + int out_size; + int in_ep; + int in_size; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file; + struct libusb_device_handle *handle; + if (libusb_open(device->device, &handle) == 0) { + int ret; + + ret = libusb_claim_interface(handle, 1); +#if 0 + if (ret) { + libusb_close(handle); + return NULL; + } +#endif + ret = libusb_detach_kernel_driver(handle, 1); +#if 0 + if (ret) { + libusb_close(handle); + return NULL; + } +#endif + + file = calloc(sizeof (struct altos_file), 1); + file->device = libusb_ref_device(device->device); + file->handle = handle; + /* XXX should get these from the endpoint descriptors */ + file->out_ep = 4 | LIBUSB_ENDPOINT_OUT; + file->out_size = 64; + file->in_ep = 5 | LIBUSB_ENDPOINT_IN; + file->in_size = 64; + + return file; + } + return NULL; +} + +void +altos_close(struct altos_file *file) +{ + libusb_close(file->handle); + libusb_unref_device(file->device); + file->handle = NULL; + free(file); +} + +int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == file->out_size) { + ret = altos_flush(file); + if (ret) + return ret; + } + file->out_data[file->out_used++] = c; + if (file->out_used == file->out_size) + return altos_flush(file); + return 0; +} + +int +altos_flush(struct altos_file *file) +{ + while (file->out_used) { + int transferred; + int ret; + + ret = libusb_bulk_transfer(file->handle, + file->out_ep, + file->out_data, + file->out_used, + &transferred, + 0); + if (ret) + return ret; + if (transferred) { + memmove(file->out_data, file->out_data + transferred, + file->out_used - transferred); + file->out_used -= transferred; + } + } +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + while (file->in_read == file->in_used) { + int ret; + int transferred; + + altos_flush(file); + ret = libusb_bulk_transfer(file->handle, + file->in_ep, + file->in_data, + file->in_size, + &transferred, + (unsigned int) timeout); + if (ret) + return ret; + file->in_read = 0; + file->in_used = transferred; + } + return file->in_data[file->in_read++]; +} + +#endif /* USE_LIBUSB */ diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h new file mode 100644 index 00000000..782f244e --- /dev/null +++ b/ao-tools/libaltos/libaltos.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _LIBALTOS_H_ +#define _LIBALTOS_H_ + +struct altos_device { + //%immutable; + char product[256]; + int serial; + char path[256]; + //%mutable; +}; + +int altos_init(void); + +void altos_fini(void); + +struct altos_list * +altos_list_start(void); + +int altos_list_next(struct altos_list *list, struct altos_device *device); + +void altos_list_finish(struct altos_list *list); + +struct altos_file * +altos_open(struct altos_device *device); + +void altos_close(struct altos_file *file); + +int +altos_putchar(struct altos_file *file, char c); + +int +altos_flush(struct altos_file *file); + +int +altos_getchar(struct altos_file *file, int timeout); + +#endif /* _LIBALTOS_H_ */ diff --git a/ao-tools/libaltos/libaltos.i0 b/ao-tools/libaltos/libaltos.i0 new file mode 100644 index 00000000..d06468f5 --- /dev/null +++ b/ao-tools/libaltos/libaltos.i0 @@ -0,0 +1,5 @@ +%module libaltos +%{ +#include "libaltos.h" +%} +