diff options
Diffstat (limited to 'altosui')
-rw-r--r-- | altosui/Altos.java | 2 | ||||
-rw-r--r-- | altosui/AltosBTDevice.java | 7 | ||||
-rw-r--r-- | altosui/AltosCSVUI.java | 2 | ||||
-rw-r--r-- | altosui/AltosConfig.java | 3 | ||||
-rw-r--r-- | altosui/AltosConfigureUI.java | 33 | ||||
-rw-r--r-- | altosui/AltosDataChooser.java | 2 | ||||
-rw-r--r-- | altosui/AltosDevice.java | 1 | ||||
-rw-r--r-- | altosui/AltosDeviceDialog.java | 36 | ||||
-rw-r--r-- | altosui/AltosEepromDownload.java | 12 | ||||
-rw-r--r-- | altosui/AltosEepromManage.java | 3 | ||||
-rw-r--r-- | altosui/AltosFlashUI.java | 4 | ||||
-rw-r--r-- | altosui/AltosIgniteUI.java | 3 | ||||
-rw-r--r-- | altosui/AltosLanded.java | 4 | ||||
-rw-r--r-- | altosui/AltosLaunch.java | 201 | ||||
-rw-r--r-- | altosui/AltosLaunchUI.java | 517 | ||||
-rw-r--r-- | altosui/AltosPreferences.java | 39 | ||||
-rw-r--r-- | altosui/AltosScanUI.java | 6 | ||||
-rw-r--r-- | altosui/AltosSerial.java | 4 | ||||
-rw-r--r-- | altosui/AltosUI.java | 20 | ||||
-rw-r--r-- | altosui/AltosUSBDevice.java | 7 | ||||
-rw-r--r-- | altosui/Makefile.am | 5 | ||||
-rw-r--r-- | altosui/libaltos/libaltos.c | 175 | ||||
-rw-r--r-- | altosui/libaltos/libaltos.h | 13 |
23 files changed, 1009 insertions, 90 deletions
diff --git a/altosui/Altos.java b/altosui/Altos.java index e4f974f9..aa2fd77a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -498,5 +498,5 @@ public class Altos { public final static String bt_product_telebt = bt_product_telebt(); -// public static AltosBTKnown bt_known = new AltosBTKnown(); + public static AltosBTKnown bt_known = new AltosBTKnown(); } diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 7a876c25..55b8f8fc 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -42,6 +42,13 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { return getAddr(); } + public String getErrorString() { + altos_error error = new altos_error(); + + libaltos.altos_get_last_error(error); + return String.format("%s (%d)", error.getString(), error.getCode()); + } + public int getSerial() { String name = getName(); if (name == null) diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index e1b6002d..a212409e 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -99,7 +99,7 @@ public class AltosCSVUI writer.close(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, - file.getName(), + ee.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 122ebecc..93def70d 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -480,8 +480,7 @@ public class AltosConfig implements ActionListener { } } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index bcb9636b..980068c0 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -52,8 +52,7 @@ public class AltosConfigureUI JRadioButton serial_debug; -// BLUETOOTH -// JButton manage_bluetooth; + JButton manage_bluetooth; JButton manage_frequencies; final static String[] font_size_names = { "Small", "Medium", "Large" }; @@ -241,19 +240,18 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(serial_debug, c); -// BLUETOOTH -// manage_bluetooth = new JButton("Manage Bluetooth"); -// manage_bluetooth.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// AltosBTManage.show(owner, Altos.bt_known); -// } -// }); -// c.gridx = 0; -// c.gridy = row++; -// c.gridwidth = 2; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(manage_bluetooth, c); + manage_bluetooth = new JButton("Manage Bluetooth"); + manage_bluetooth.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosBTManage.show(owner, Altos.bt_known); + } + }); + c.gridx = 0; + c.gridy = row; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(manage_bluetooth, c); manage_frequencies = new JButton("Manage Frequencies"); manage_frequencies.addActionListener(new ActionListener() { @@ -262,9 +260,8 @@ public class AltosConfigureUI } }); manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); -// BLUETOOTH -// c.gridx = 2; - c.gridx = 1; + c.gridx = 2; + c.gridx = 2; c.gridy = row++; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 15de05c2..d81ca6d1 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -61,7 +61,7 @@ public class AltosDataChooser extends JFileChooser { } } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(frame, - filename, + fe.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java index 3357c550..1b5c1a91 100644 --- a/altosui/AltosDevice.java +++ b/altosui/AltosDevice.java @@ -26,5 +26,6 @@ public interface AltosDevice { public abstract int getSerial(); public abstract String getPath(); public abstract boolean matchProduct(int product); + public abstract String getErrorString(); public SWIGTYPE_p_altos_file open(); } diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index fa9587bc..610bb73e 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -30,8 +30,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private JList list; private JButton cancel_button; private JButton select_button; -// BLUETOOTH -// private JButton manage_bluetooth_button; + private JButton manage_bluetooth_button; private Frame frame; private int product; @@ -42,17 +41,15 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private AltosDevice[] devices() { java.util.List<AltosDevice> usb_devices = AltosUSBDevice.list(product); int num_devices = usb_devices.size(); -// BLUETOOTH -// java.util.List<AltosDevice> bt_devices = Altos.bt_known.list(product); -// num_devices += bt_devices.size(); + java.util.List<AltosDevice> bt_devices = Altos.bt_known.list(product); + num_devices += bt_devices.size(); AltosDevice[] devices = new AltosDevice[num_devices]; for (int i = 0; i < usb_devices.size(); i++) devices[i] = usb_devices.get(i); -// BLUETOOTH -// int off = usb_devices.size(); -// for (int j = 0; j < bt_devices.size(); j++) -// devices[off + j] = bt_devices.get(j); + int off = usb_devices.size(); + for (int j = 0; j < bt_devices.size(); j++) + devices[off + j] = bt_devices.get(j); return devices; } @@ -75,10 +72,9 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { cancel_button.setActionCommand("cancel"); cancel_button.addActionListener(this); -// BLUETOOTH -// manage_bluetooth_button = new JButton("Manage Bluetooth"); -// manage_bluetooth_button.setActionCommand("manage"); -// manage_bluetooth_button.addActionListener(this); + manage_bluetooth_button = new JButton("Manage Bluetooth"); + manage_bluetooth_button.setActionCommand("manage"); + manage_bluetooth_button.addActionListener(this); select_button = new JButton("Select"); select_button.setActionCommand("select"); @@ -152,8 +148,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); -// BLUETOOTH -// buttonPane.add(manage_bluetooth_button); + buttonPane.add(manage_bluetooth_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(select_button); @@ -173,12 +168,11 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { public void actionPerformed(ActionEvent e) { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); -// BLUETOOTH -// if ("manage".equals(e.getActionCommand())) { -// AltosBTManage.show(frame, Altos.bt_known); -// update_devices(); -// return; -// } + if ("manage".equals(e.getActionCommand())) { + AltosBTManage.show(frame, Altos.bt_known); + update_devices(); + return; + } setVisible(false); } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 358ad337..e7e52466 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -248,6 +248,10 @@ public class AltosEepromDownload implements Runnable { done = true; } + void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException { + + } + void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; int log_format = flights.config_data.log_format; @@ -300,10 +304,10 @@ public class AltosEepromDownload implements Runnable { extension = "eeprom"; CaptureTiny(eechunk); break; -// case Altos.AO_LOG_FORMAT_TELEMETRY: -// extension = "telem"; -// CaptureTelemetry(eechunk); -// break; + case Altos.AO_LOG_FORMAT_TELEMETRY: + extension = "telem"; + CaptureTelemetry(eechunk); + break; case Altos.AO_LOG_FORMAT_TELESCIENCE: extension = "science"; CaptureTeleScience(eechunk); diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 2e520628..083c7372 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -219,8 +219,7 @@ public class AltosEepromManage implements ActionListener { t.start(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 3874b500..3956ff20 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -200,8 +200,8 @@ public class AltosFlashUI void exception (Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(frame, - "Cannot open image", - file.toString(), + ((FileNotFoundException) e).getMessage(), + "Cannot open file", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { JOptionPane.showMessageDialog(frame, diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index c11a8614..b215c228 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -122,8 +122,7 @@ public class AltosIgniteUI void ignite_exception(Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ((FileNotFoundException) e).getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 50e6b542..4dd9a2dd 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -250,7 +250,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio FileInputStream in = new FileInputStream(file); records = new AltosTelemetryIterable(in); } else { - throw new FileNotFoundException(); + throw new FileNotFoundException(filename); } try { new AltosGraphUI(records, filename); @@ -259,7 +259,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio } } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(null, - filename, + fe.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java new file mode 100644 index 00000000..77f681b8 --- /dev/null +++ b/altosui/AltosLaunch.java @@ -0,0 +1,201 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * 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.io.*; +import java.util.concurrent.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; + +public class AltosLaunch { + AltosDevice device; + AltosSerial serial; + boolean serial_started; + int launcher_serial; + int launcher_channel; + int rssi; + + final static int Unknown = -1; + final static int Good = 0; + final static int Bad = 1; + + int armed; + int igniter; + + private void start_serial() throws InterruptedException { + serial_started = true; + } + + private void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; + if (serial == null) + return; + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref() { + value = null; + } + } + + private boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + public boolean status() throws InterruptedException, TimeoutException { + boolean ok = false; + if (serial == null) + return false; + string_ref status_name = new string_ref(); + start_serial(); + serial.printf("l %d %d\n", launcher_serial, launcher_channel); + for (;;) { + String line = serial.get_reply(20000); + if (line == null) + throw new TimeoutException(); + if (get_string(line, "Rssi: ", status_name)) { + try { + rssi = Altos.fromdec(status_name.get()); + } catch (NumberFormatException ne) { + } + break; + } else if (get_string(line, "Armed: ", status_name)) { + armed = Good; + String status = status_name.get(); + if (status.startsWith("igniter good")) + igniter = Good; + else if (status.startsWith("igniter bad")) + igniter = Bad; + else + igniter = Unknown; + ok = true; + } else if (get_string(line, "Disarmed: ", status_name)) { + armed = Bad; + if (status_name.get().startsWith("igniter good")) + igniter = Good; + else if (status_name.get().startsWith("igniter bad")) + igniter = Bad; + else + igniter = Unknown; + ok = true; + } else if (get_string(line, "Error ", status_name)) { + armed = Unknown; + igniter = Unknown; + ok = false; + break; + } + } + stop_serial(); + if (!ok) { + armed = Unknown; + igniter = Unknown; + } + return ok; + } + + public static String status_string(int status) { + switch (status) { + case Good: + return "good"; + case Bad: + return "open"; + } + return "unknown"; + } + + public void arm() { + if (serial == null) + return; + try { + start_serial(); + serial.printf("a %d %d\n", launcher_serial, launcher_channel); + serial.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void fire() { + if (serial == null) + return; + try { + start_serial(); + serial.printf("i %d %d\n", launcher_serial, launcher_channel); + serial.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void close() { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + serial.close(); + serial = null; + } + + public void set_frame(Frame frame) { + serial.set_frame(frame); + } + + public void set_remote(int in_serial, int in_channel) { + launcher_serial = in_serial; + launcher_channel = in_channel; + } + + public AltosLaunch(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + + device = in_device; + serial = new AltosSerial(device); + } +}
\ No newline at end of file diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java new file mode 100644 index 00000000..47365e03 --- /dev/null +++ b/altosui/AltosLaunchUI.java @@ -0,0 +1,517 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * 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.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +class FireButton extends JButton { + protected void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + switch (e.getID()) { + case MouseEvent.MOUSE_PRESSED: + if (actionListener != null) + actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_down")); + break; + case MouseEvent.MOUSE_RELEASED: + if (actionListener != null) + actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_up")); + break; + } + } + + public FireButton(String s) { + super(s); + } +} + +public class AltosLaunchUI + extends JDialog + implements ActionListener +{ + AltosDevice device; + JFrame owner; + JLabel label; + + int radio_channel; + JLabel radio_channel_label; + JTextField radio_channel_text; + + int launcher_serial; + JLabel launcher_serial_label; + JTextField launcher_serial_text; + + int launcher_channel; + JLabel launcher_channel_label; + JTextField launcher_channel_text; + + JLabel armed_label; + JLabel armed_status_label; + JLabel igniter; + JLabel igniter_status_label; + JToggleButton arm; + FireButton fire; + javax.swing.Timer arm_timer; + javax.swing.Timer fire_timer; + + boolean firing; + boolean armed; + int armed_status; + int igniter_status; + int rssi; + + final static int arm_timeout = 1 * 1000; + final static int fire_timeout = 250; + + int armed_count; + + LinkedBlockingQueue<String> command_queue; + + class LaunchHandler implements Runnable { + AltosLaunch launch; + JFrame owner; + + void send_exception(Exception e) { + final Exception f_e = e; + Runnable r = new Runnable() { + public void run() { + launch_exception(f_e); + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + try { + launch = new AltosLaunch(device); + } catch (Exception e) { + send_exception(e); + return; + } + launch.set_frame(owner); + launch.set_remote(launcher_serial, launcher_channel); + + for (;;) { + Runnable r; + + try { + String command = command_queue.take(); + String reply = null; + + if (command.equals("get_status")) { + launch.status(); + reply = "status"; + armed_status = launch.armed; + igniter_status = launch.igniter; + rssi = launch.rssi; + } else if (command.equals("set_remote")) { + launch.set_remote(launcher_serial, launcher_channel); + reply = "remote set"; + } else if (command.equals("arm")) { + launch.arm(); + reply = "armed"; + } else if (command.equals("fire")) { + launch.fire(); + reply = "fired"; + } else if (command.equals("quit")) { + launch.close(); + break; + } else { + throw new ParseException(String.format("invalid command %s", command), 0); + } + final String f_reply = reply; + r = new Runnable() { + public void run() { + launch_reply(f_reply); + } + }; + SwingUtilities.invokeLater(r); + } catch (Exception e) { + send_exception(e); + } + } + } + + public LaunchHandler(JFrame in_owner) { + owner = in_owner; + } + } + + void launch_exception(Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + ((FileNotFoundException) e).getMessage(), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + close(); + } + + void launch_reply(String reply) { + if (reply == null) + return; + if (reply.equals("remote set")) + poll_launch_status(); + if (reply.equals("status")) { + set_launch_status(); + } + } + + void set_arm_text() { + if (arm.isSelected()) + arm.setText(String.format("%d", armed_count)); + else + arm.setText("Arm"); + } + + void start_arm_timer() { + armed_count = 30; + set_arm_text(); + } + + void stop_arm_timer() { + armed_count = 0; + armed = false; + arm.setSelected(false); + fire.setEnabled(false); + set_arm_text(); + } + + void cancel () { + fire.setEnabled(false); + firing = false; + stop_arm_timer(); + } + + void send_command(String command) { + try { + command_queue.put(command); + } catch (Exception ex) { + launch_exception(ex); + } + } + + boolean getting_status = false; + + void set_launch_status() { + getting_status = false; + armed_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(armed_status))); + igniter_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(igniter_status))); + } + + void poll_launch_status() { + if (!getting_status && !firing && !armed) { + getting_status = true; + send_command("get_status"); + } + } + + void fired() { + firing = false; + cancel(); + } + + void close() { + send_command("quit"); + arm_timer.stop(); + setVisible(false); + dispose(); + } + + void tick_arm_timer() { + if (armed_count > 0) { + --armed_count; + if (armed_count <= 0) { + armed_count = 0; + cancel(); + } else { + if (!firing) { + send_command("arm"); + set_arm_text(); + } + } + } + poll_launch_status(); + } + + void arm() { + if (arm.isSelected()) { + fire.setEnabled(true); + start_arm_timer(); + if (!firing) + send_command("arm"); + armed = true; + } else + cancel(); + } + + void fire_more() { + if (firing) + send_command("fire"); + } + + void fire_down() { + if (arm.isEnabled() && arm.isSelected() && armed_count > 0) { + firing = true; + fire_more(); + fire_timer.restart(); + } + } + + void fire_up() { + firing = false; + fire_timer.stop(); + } + + void set_radio() { + try { + radio_channel = Integer.parseInt(radio_channel_text.getText()); + } catch (NumberFormatException ne) { + radio_channel_text.setText(String.format("%d", radio_channel)); + } + } + + void set_serial() { + try { + launcher_serial = Integer.parseInt(launcher_serial_text.getText()); + AltosPreferences.set_launcher_serial(launcher_serial); + send_command("set_remote"); + } catch (NumberFormatException ne) { + launcher_serial_text.setText(String.format("%d", launcher_serial)); + } + } + + void set_channel() { + try { + launcher_channel = Integer.parseInt(launcher_channel_text.getText()); + AltosPreferences.set_launcher_serial(launcher_channel); + send_command("set_remote"); + } catch (NumberFormatException ne) { + launcher_channel_text.setText(String.format("%d", launcher_channel)); + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + System.out.printf("cmd %s\n", cmd); + if (cmd.equals("armed") || cmd.equals("igniter")) { + stop_arm_timer(); + } + + if (cmd.equals("arm")) + arm(); + if (cmd.equals("tick_arm")) + tick_arm_timer(); + if (cmd.equals("close")) + close(); + if (cmd.equals("fire_down")) + fire_down(); + if (cmd.equals("fire_up")) + fire_up(); + if (cmd.equals("tick_fire")) + fire_more(); + if (cmd.equals("new_serial")) + set_serial(); + if (cmd.equals("new_channel")) + set_channel(); + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosLaunchUI ui; + + public ConfigListener(AltosLaunchUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + command_queue = new LinkedBlockingQueue<String>(); + + device = AltosDeviceDialog.show(owner, Altos.product_any); + if (device != null) { + LaunchHandler handler = new LaunchHandler(owner); + Thread t = new Thread(handler); + t.start(); + return true; + } + return false; + } + + public AltosLaunchUI(JFrame in_owner) { + + launcher_channel = AltosPreferences.launcher_channel(); + launcher_serial = AltosPreferences.launcher_serial(); + owner = in_owner; + armed_status = AltosLaunch.Unknown; + igniter_status = AltosLaunch.Unknown; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + arm_timer = new javax.swing.Timer(arm_timeout, this); + arm_timer.setActionCommand("tick_arm"); + arm_timer.restart(); + + fire_timer = new javax.swing.Timer(fire_timeout, this); + fire_timer.setActionCommand("tick_fire"); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + label = new JLabel ("Launch Controller"); + pane.add(label, c); + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_serial_label = new JLabel("Launcher Serial"); + pane.add(launcher_serial_label, c); + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_serial_text = new JTextField(7); + launcher_serial_text.setText(String.format("%d", launcher_serial)); + launcher_serial_text.setActionCommand("new_serial"); + launcher_serial_text.addActionListener(this); + pane.add(launcher_serial_text, c); + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_channel_label = new JLabel("Launcher Channel"); + pane.add(launcher_channel_label, c); + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_channel_text = new JTextField(7); + launcher_channel_text.setText(String.format("%d", launcher_channel)); + launcher_channel_text.setActionCommand("new_channel"); + launcher_channel_text.addActionListener(this); + pane.add(launcher_channel_text, c); + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + armed_label = new JLabel ("Armed"); + pane.add(armed_label, c); + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + armed_status_label = new JLabel(); + pane.add(armed_status_label, c); + + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + igniter = new JLabel ("Igniter"); + pane.add(igniter, c); + + c.gridx = 1; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + igniter_status_label = new JLabel(); + pane.add(igniter_status_label, c); + + c.gridx = 0; + c.gridy = 5; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + arm = new JToggleButton ("Arm"); + pane.add(arm, c); + arm.addActionListener(this); + arm.setActionCommand("arm"); + arm.setEnabled(true); + + c.gridx = 1; + c.gridy = 5; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + fire = new FireButton ("Fire"); + fire.setEnabled(false); + pane.add(fire, c); + fire.addActionListener(this); + fire.setActionCommand("fire"); + + pack(); + setLocationRelativeTo(owner); + + addWindowListener(new ConfigListener(this)); + + setVisible(true); + } +}
\ No newline at end of file diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 716559ab..48aed441 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -58,6 +58,12 @@ class AltosPreferences { /* font size preferences name */ final static String fontSizePreference = "FONT-SIZE"; + /* Launcher serial preference name */ + final static String launcherSerialPreference = "LAUNCHER-SERIAL"; + + /* Launcher channel prefernce name */ + final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -143,6 +149,9 @@ class AltosPreferences { node.put(String.format(description_format, i), frequencies[i].description); } } + static int launcher_serial; + + static int launcher_channel; public static void init() { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -176,6 +185,10 @@ class AltosPreferences { font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium); Altos.set_fonts(font_size); + launcher_serial = preferences.getInt(launcherSerialPreference, 0); + + launcher_channel = preferences.getInt(launcherChannelPreference, 0); + String firmwaredir_string = preferences.get(firmwaredirPreference, null); if (firmwaredir_string != null) firmwaredir = new File(firmwaredir_string); @@ -390,6 +403,32 @@ class AltosPreferences { return serial_debug; } + public static void set_launcher_serial(int new_launcher_serial) { + launcher_serial = new_launcher_serial; + System.out.printf("set launcher serial to %d\n", new_launcher_serial); + synchronized (preferences) { + preferences.putInt(launcherSerialPreference, launcher_serial); + flush_preferences(); + } + } + + public static int launcher_serial() { + return launcher_serial; + } + + public static void set_launcher_channel(int new_launcher_channel) { + launcher_channel = new_launcher_channel; + System.out.printf("set launcher channel to %d\n", new_launcher_channel); + synchronized (preferences) { + preferences.putInt(launcherChannelPreference, launcher_channel); + flush_preferences(); + } + } + + public static int launcher_channel() { + return launcher_channel; + } + public static Preferences bt_devices() { return preferences.node("bt_devices"); } diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index bce4b32c..df5c51d4 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -130,8 +130,7 @@ public class AltosScanUI void scan_exception(Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ((FileNotFoundException) e).getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { @@ -326,8 +325,7 @@ public class AltosScanUI return true; } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 0a531aa9..4cf306d0 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -323,8 +323,10 @@ public class AltosSerial implements Runnable { } altos = device.open(); if (altos == null) { + final String message = device.getErrorString(); close(); - throw new FileNotFoundException(device.toShortString()); + throw new FileNotFoundException(String.format("%s (%s)", + device.toShortString(), message)); } if (debug) System.out.printf("Open %s\n", device.getPath()); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 27c41838..3e5bcf43 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -52,8 +52,7 @@ public class AltosUI extends JFrame { new AltosFlightUI(voice, reader, device.getSerial()); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { @@ -210,6 +209,13 @@ public class AltosUI extends JFrame { }); b.setToolTipText("Check flight readiness of altimeter in idle mode"); + b = addButton(3, 2, "Launch Controller"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + LaunchController(); + } + }); + setTitle("AltOS"); pane.doLayout(); @@ -272,6 +278,10 @@ public class AltosUI extends JFrame { new AltosSiteMapPreload(AltosUI.this); } + void LaunchController() { + new AltosLaunchUI(AltosUI.this); + } + /* * Replay a flight from telemetry data */ @@ -345,7 +355,7 @@ public class AltosUI extends JFrame { else return new AltosTelemetryIterable(in); } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); + System.out.printf("%s\n", fe.getMessage()); return null; } } @@ -355,7 +365,7 @@ public class AltosUI extends JFrame { try { return new AltosCSV(file); } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); + System.out.printf("%s\n", fe.getMessage()); return null; } } @@ -365,7 +375,7 @@ public class AltosUI extends JFrame { try { return new AltosKML(file); } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); + System.out.printf("%s\n", fe.getMessage()); return null; } } diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index dc746a64..b11a3934 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -39,6 +39,13 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { } + public String getErrorString() { + altos_error error = new altos_error(); + + libaltos.altos_get_last_error(error); + return String.format("%s (%d)", error.getString(), error.getCode()); + } + public SWIGTYPE_p_altos_file open() { return libaltos.altos_open(this); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index ba1c830c..c4d1e611 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -68,6 +68,8 @@ altosui_JAVA = \ AltosIdleMonitorUI.java \ AltosIgnite.java \ AltosIgniteUI.java \ + AltosLaunch.java \ + AltosLaunchUI.java \ AltosInfoTable.java \ AltosKML.java \ AltosLanded.java \ @@ -116,7 +118,8 @@ altosui_JAVA = \ AltosGraphUI.java \ AltosDataChooser.java \ AltosVersion.java \ - AltosVoice.java + AltosVoice.java \ + $(altosui_BT) JFREECHART_CLASS= \ jfreechart.jar diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index d1f445bd..48e00a44 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -49,6 +49,22 @@ altos_fini(void) { } +static struct altos_error last_error; + +static void +altos_set_last_error(int code, char *string) +{ + last_error.code = code; + strncpy(last_error.string, string, sizeof (last_error.string) -1); + last_error.string[sizeof(last_error.string)-1] = '\0'; +} + +PUBLIC void +altos_get_last_error(struct altos_error *error) +{ + *error = last_error; +} + #ifdef DARWIN #undef USE_POLL @@ -96,6 +112,12 @@ struct altos_file { int in_read; }; +static void +altos_set_last_posix_error(void) +{ + altos_set_last_error(errno, strerror(errno)); +} + PUBLIC struct altos_file * altos_open(struct altos_device *device) { @@ -103,12 +125,18 @@ altos_open(struct altos_device *device) int ret; struct termios term; - if (!file) + if (!file) { + altos_set_last_posix_error(); return NULL; + } + +// altos_set_last_error(12, "yeah yeah, failed again"); +// free(file); +// return NULL; file->fd = open(device->path, O_RDWR | O_NOCTTY); if (file->fd < 0) { - perror(device->path); + altos_set_last_posix_error(); free(file); return NULL; } @@ -117,7 +145,7 @@ altos_open(struct altos_device *device) #else file->out_fd = open(device->path, O_RDWR | O_NOCTTY); if (file->out_fd < 0) { - perror(device->path); + altos_set_last_posix_error(); close(file->fd); free(file); return NULL; @@ -125,7 +153,7 @@ altos_open(struct altos_device *device) #endif ret = tcgetattr(file->fd, &term); if (ret < 0) { - perror("tcgetattr"); + altos_set_last_posix_error(); close(file->fd); #ifndef USE_POLL close(file->out_fd); @@ -143,7 +171,7 @@ altos_open(struct altos_device *device) #endif ret = tcsetattr(file->fd, TCSAFLUSH, &term); if (ret < 0) { - perror("tcsetattr"); + altos_set_last_posix_error(); close(file->fd); #ifndef USE_POLL close(file->out_fd); @@ -195,8 +223,10 @@ altos_flush(struct altos_file *file) #else ret = write (file->out_fd, file->out_data, file->out_used); #endif - if (ret < 0) + if (ret < 0) { + altos_set_last_posix_error(); return -errno; + } if (ret) { memmove(file->out_data, file->out_data + ret, file->out_used - ret); @@ -248,7 +278,7 @@ altos_fill(struct altos_file *file, int timeout) fd[1].events = POLLIN; ret = poll(fd, 2, timeout); if (ret < 0) { - perror("altos_getchar"); + altos_set_last_posix_error(); return LIBALTOS_ERROR; } if (ret == 0) @@ -261,7 +291,7 @@ altos_fill(struct altos_file *file, int timeout) { ret = read(file->fd, file->in_data, USB_BUF_SIZE); if (ret < 0) { - perror("altos_getchar"); + altos_set_last_posix_error(); return LIBALTOS_ERROR; } file->in_read = 0; @@ -598,7 +628,6 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } -#if HAS_BLUETOOTH struct altos_bt_list { inquiry_info *ii; int sock; @@ -701,8 +730,10 @@ altos_bt_open(struct altos_bt_device *device) if (!file) goto no_file; file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (file->fd < 0) + if (file->fd < 0) { + altos_set_last_posix_error(); goto no_sock; + } addr.rc_family = AF_BLUETOOTH; addr.rc_channel = 1; @@ -712,7 +743,7 @@ altos_bt_open(struct altos_bt_device *device) (struct sockaddr *)&addr, sizeof(addr)); if (status < 0) { - perror("connect"); + altos_set_last_posix_error(); goto no_link; } sleep(1); @@ -730,7 +761,6 @@ no_sock: no_file: return NULL; } -#endif /* HAS_BLUETOOTH */ #endif @@ -844,6 +874,48 @@ altos_list_finish(struct altos_list *list) free(list); } +struct altos_bt_list { + int sock; + int dev_id; + int rsp; + int num_rsp; +}; + +#define INQUIRY_MAX_RSP 255 + +struct altos_bt_list * +altos_bt_list_start(int inquiry_time) +{ + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + return 0; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ +} + +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ + strncpy(device->name, name, sizeof (device->name)); + device->name[sizeof(device->name)-1] = '\0'; + strncpy(device->addr, addr, sizeof (device->addr)); + device->addr[sizeof(device->addr)-1] = '\0'; +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ + return NULL; +} + #endif @@ -872,6 +944,21 @@ struct altos_file { OVERLAPPED ov_write; }; +static void +altos_set_last_windows_error(void) +{ + DWORD error = GetLastError(); + TCHAR message[1024]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + 0, + error, + 0, + message, + sizeof (message) / sizeof (TCHAR), + NULL); + altos_set_last_error(error, message); +} + PUBLIC struct altos_list * altos_list_start(void) { @@ -882,7 +969,7 @@ altos_list_start(void) list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES|DIGCF_PRESENT); if (list->dev_info == INVALID_HANDLE_VALUE) { - printf("SetupDiGetClassDevs failed %ld\n", GetLastError()); + altos_set_last_windows_error(); free(list); return NULL; } @@ -916,6 +1003,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (dev_key == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); printf("cannot open device registry key\n"); continue; } @@ -926,6 +1014,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, symbolic, &symbolic_len); if (result != 0) { + altos_set_last_windows_error(); printf("cannot find SymbolicName value\n"); RegCloseKey(dev_key); continue; @@ -948,6 +1037,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) port, &port_len); RegCloseKey(dev_key); if (result != 0) { + altos_set_last_windows_error(); printf("failed to get PortName\n"); continue; } @@ -963,6 +1053,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) sizeof(friendlyname), &friendlyname_len)) { + altos_set_last_windows_error(); printf("Failed to get friendlyname\n"); continue; } @@ -975,8 +1066,10 @@ altos_list_next(struct altos_list *list, struct altos_device *device) return 1; } result = GetLastError(); - if (result != ERROR_NO_MORE_ITEMS) + if (result != ERROR_NO_MORE_ITEMS) { + altos_set_last_windows_error(); printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); + } return 0; } @@ -995,8 +1088,10 @@ altos_queue_read(struct altos_file *file) return LIBALTOS_SUCCESS; if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { - if (GetLastError() != ERROR_IO_PENDING) + if (GetLastError() != ERROR_IO_PENDING) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } file->pend_read = TRUE; } else { file->pend_read = FALSE; @@ -1021,8 +1116,10 @@ altos_wait_read(struct altos_file *file, int timeout) ret = WaitForSingleObject(file->ov_read.hEvent, timeout); switch (ret) { case WAIT_OBJECT_0: - if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) + if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } file->pend_read = FALSE; file->in_read = 0; file->in_used = got; @@ -1066,15 +1163,20 @@ altos_flush(struct altos_file *file) while (used) { if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { - if (GetLastError() != ERROR_IO_PENDING) + if (GetLastError() != ERROR_IO_PENDING) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE); switch (ret) { case WAIT_OBJECT_0: - if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) + if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } break; default: + altos_set_last_windows_error(); return LIBALTOS_ERROR; } } @@ -1102,6 +1204,7 @@ altos_open(struct altos_device *device) 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (file->handle == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); free(file); return NULL; } @@ -1117,6 +1220,7 @@ altos_open(struct altos_device *device) dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(file->handle, &dcbSerialParams)) { + altos_set_last_windows_error(); CloseHandle(file->handle); free(file); return NULL; @@ -1126,6 +1230,7 @@ altos_open(struct altos_device *device) dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(file->handle, &dcbSerialParams)) { + altos_set_last_windows_error(); CloseHandle(file->handle); free(file); return NULL; @@ -1180,4 +1285,38 @@ altos_getchar(struct altos_file *file, int timeout) return file->in_data[file->in_read++]; } +struct altos_bt_list * +altos_bt_list_start(int inquiry_time) +{ + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + return 0; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ + free(bt_list); +} + +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ + strncpy(device->name, name, sizeof (device->name)); + device->name[sizeof(device->name)-1] = '\0'; + strncpy(device->addr, addr, sizeof (device->addr)); + device->addr[sizeof(device->addr)-1] = '\0'; +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ + return NULL; +} + #endif diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 363a84fd..f90fbb87 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -51,6 +51,11 @@ struct altos_bt_device { //%mutable; }; +struct altos_error { + int code; + char string[1024]; +}; + #define LIBALTOS_SUCCESS 0 #define LIBALTOS_ERROR -1 #define LIBALTOS_TIMEOUT -2 @@ -62,6 +67,9 @@ altos_init(void); PUBLIC void altos_fini(void); +PUBLIC void +altos_get_last_error(struct altos_error *error); + PUBLIC struct altos_list * altos_list_start(void); @@ -93,9 +101,6 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); -// #define HAS_BLUETOOTH 1 -#if HAS_BLUETOOTH - PUBLIC struct altos_bt_list * altos_bt_list_start(int inquiry_time); @@ -111,6 +116,4 @@ altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device); PUBLIC struct altos_file * altos_bt_open(struct altos_bt_device *device); -#endif - #endif /* _LIBALTOS_H_ */ |