From c726d8f6eb861801d7543552beab6ee2c920c96f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 15:41:39 -0700 Subject: Add libaltos which talks to USB connected altos devices --- ao-tools/libaltos/Makefile | 61 ++++++ ao-tools/libaltos/cjnitest.c | 25 +++ ao-tools/libaltos/libaltos.c | 479 ++++++++++++++++++++++++++++++++++++++++++ ao-tools/libaltos/libaltos.h | 54 +++++ ao-tools/libaltos/libaltos.i0 | 5 + 5 files changed, 624 insertions(+) create mode 100644 ao-tools/libaltos/Makefile create mode 100644 ao-tools/libaltos/cjnitest.c create mode 100644 ao-tools/libaltos/libaltos.c create mode 100644 ao-tools/libaltos/libaltos.h create mode 100644 ao-tools/libaltos/libaltos.i0 diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile new file mode 100644 index 00000000..5ffbdadf --- /dev/null +++ b/ao-tools/libaltos/Makefile @@ -0,0 +1,61 @@ +.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 + +LIBEXT=dylib + +JAVAFILES=\ + $(JNI_SRCS) + +CLASSFILES = $(JAVAFILES:%.java=%.class) + +JAVAFLAGS=-Xlint:unchecked + +all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) + +.java.class: + javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java + +DARWIN_CFLAGS=\ + -I/System/Library/Frameworks/JavaVM.framework/Headers \ + -I/System/Library/Frameworks/IOKit.framework/Headers \ + -I/System/Library/Frameworks/CoreFoundation.framework/Headers +DARWIN_LIBS=\ + -framework IOKit -framework CoreFoundation + +CFLAGS = $(DARWIN_CFLAGS) -I. -O0 -g + +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 -o $@ $(OBJS) $(LIBS) + +clean: + rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest + +$(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..417c8fe5 --- /dev/null +++ b/ao-tools/libaltos/libaltos.c @@ -0,0 +1,479 @@ +/* + * 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" + +#define USE_DARWIN + +#ifdef USE_DARWIN + +#include +#include +#include +#include +#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); +} + + +#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; +}; + +void +altos_test(char *path) +{ + int n; + char buf[16]; + int fd; + struct termios term; + + fd = open(path, O_RDWR | O_NOCTTY); + if (fd < 0) { + perror(path); + return; + } + if (ioctl(fd, TIOCEXCL, (char *) 0) < 0) { + perror("TIOCEXCL"); + close (fd); + return; + } + + n = tcgetattr(fd, &term); + if (n < 0) { + perror("tcgetattr"); + close(fd); + return; + } + cfmakeraw(&term); + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; + n = tcsetattr(fd, TCSAFLUSH, &term); + if (n < 0) { + perror("tcsetattr"); + close(fd); + return; + } + write(fd, "\n?\n", 3); + for (;;) { + n = read(fd, buf, sizeof (buf)); + if (n < 0) { + perror("read"); + break; + } + if (n == 0) + break; + write(1, buf, n); + } + close(fd); +} + +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 /* USE_DARWIN */ + +#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" +%} + -- cgit v1.2.3 From 005e2d6a7bb3b0546b0c1273296875621632ec6d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 15:42:48 -0700 Subject: Switch AltosUI to libaltos for device access Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDevice.java | 35 +++++-- ao-tools/altosui/AltosDeviceDialog.java | 14 +-- ao-tools/altosui/AltosDeviceLinux.java | 172 -------------------------------- ao-tools/altosui/AltosGPS.java | 4 + ao-tools/altosui/AltosSerial.java | 72 ++++--------- ao-tools/altosui/AltosUI.java | 21 ++-- ao-tools/altosui/AltosVoice.java | 20 ++-- ao-tools/altosui/Makefile | 12 +-- 8 files changed, 78 insertions(+), 272 deletions(-) delete mode 100644 ao-tools/altosui/AltosDeviceLinux.java diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 66800c5c..8ebd3b99 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -18,13 +18,36 @@ 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; + static { + System.loadLibrary("altos"); + libaltos.altos_init(); + } + static altos_device[] 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 (;;) { + altos_device device = new altos_device(); + if (libaltos.altos_list_next(list, device) == 0) + break; + System.out.printf("Found device %s %d %s\n", + device.getProduct(), device.getSerial(), device.getPath()); + + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + altos_device[] devices = new altos_device[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..b3a0f9be 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) { + altos_device[] devices = null; + 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..073bfb78 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -26,8 +26,11 @@ 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 @@ -35,7 +38,7 @@ import altosui.AltosSerialMonitor; * threads. */ class AltosSerialReader implements Runnable { - InputStream serial_in; + SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; Thread input_thread; @@ -46,7 +49,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 +73,6 @@ class AltosSerialReader implements Runnable { } } } - } catch (IOException e) { } catch (InterruptedException e) { } } @@ -96,16 +98,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,62 +116,30 @@ 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 { + public void open(altos_device device) throws FileNotFoundException { close(); - try { - c.enableReceiveTimeout(1000); /* icky. the read method cannot be interrupted */ - } catch (UnsupportedCommOperationException ee) { - } - serial_in = c.getInputStream(); + altos = libaltos.altos_open(device); input_thread = new Thread(this); input_thread.start(); } public AltosSerialReader () { - serial_in = null; + altos = null; input_thread = null; line = ""; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); } - } 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 connect(String port_name) throws IOException, NoSuchPortException, PortInUseException { - comm_port = new RXTXPort(port_name); - open(comm_port); + public void open(altos_device device) throws FileNotFoundException { + reader.open(device); } void init() { @@ -191,13 +158,8 @@ public class AltosSerial { init(); } - public AltosSerial(File serial_name) throws FileNotFoundException { - init(); - open(serial_name); - } - - public AltosSerial(CommPort comm_port) throws IOException { + public AltosSerial(altos_device device) throws FileNotFoundException { init(); - open(comm_port); + open(device); } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 43c40799..33ed2c90 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 }; @@ -475,31 +476,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); } diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index e4ea99a2..0c34795c 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -17,14 +17,16 @@ package altosui; -import com.sun.speech.freetts.Voice; +/*import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; -import com.sun.speech.freetts.audio.JavaClipAudioPlayer; +import com.sun.speech.freetts.audio.JavaClipAudioPlayer; */ import java.util.concurrent.LinkedBlockingQueue; public class AltosVoice implements Runnable { +/* VoiceManager voice_manager; Voice voice; +*/ LinkedBlockingQueue phrases; Thread thread; @@ -34,29 +36,29 @@ public class AltosVoice implements Runnable { try { for (;;) { String s = phrases.take(); - voice.speak(s); +/* voice.speak(s); */ } } catch (InterruptedException e) { } } public void speak(String s) { try { - if (voice != null) +/* if (voice != null) */ phrases.put(s); } catch (InterruptedException e) { } } public AltosVoice () { - voice_manager = VoiceManager.getInstance(); +/* voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); - if (voice != null) { - voice.allocate(); + if (voice != null) */ { +/* voice.allocate(); */ phrases = new LinkedBlockingQueue (); thread = new Thread(this); thread.start(); speak("Rocket Flight Monitor Ready"); - } else { + } /* else { System.out.printf("Voice manager failed to open %s\n", voice_name); Voice[] voices = voice_manager.getVoices(); System.out.printf("Available voices:\n"); @@ -64,6 +66,6 @@ public class AltosVoice implements Runnable { System.out.println(" " + voices[i].getName() + " (" + voices[i].getDomain() + " domain)"); } - } + } */ } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 57c889b8..1c49ba11 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=..:../libaltos:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 CLASSFILES=\ AltosConvert.class \ AltosFile.class \ @@ -15,24 +15,18 @@ CLASSFILES=\ AltosTelemetry.class \ AltosUI.class \ AltosDevice.class \ - AltosDeviceLinux.class \ AltosDeviceDialog.class \ AltosVoice.class JAVAFLAGS=-Xlint:unchecked -all: $(CLASSFILES) altosui altosui.jar +all: $(CLASSFILES) altosui.jar .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui: Makefile - (echo '#!/bin/sh'; \ - echo exec java -cp '"$(CLASSPATH)"' altosui/AltosUI) > $@ - chmod +x $@ - altosui.jar: $(CLASSFILES) Manifest.txt - cd .. && jar cfm altosui/$@ altosui/Manifest.txt altosui/*.class + jar cfm $@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class clean: rm -f *.class -- cgit v1.2.3 From 17188f36fe18c23bc2eb877ac9a01b7693f4b863 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 17:03:47 -0700 Subject: Present list of altos devices in nice format --- ao-tools/altosui/AltosDevice.java | 18 ++++++++++-------- ao-tools/altosui/AltosDeviceDialog.java | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 8ebd3b99..0e7d01da 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -20,32 +20,34 @@ import java.lang.*; import java.util.*; import libaltosJNI.*; -public class AltosDevice { +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 altos_device[] list(String product) { + static AltosDevice[] list(String product) { SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - ArrayList device_list = new ArrayList(); + ArrayList device_list = new ArrayList(); if (list != null) { SWIGTYPE_p_altos_file file; for (;;) { - altos_device device = new altos_device(); + AltosDevice device = new AltosDevice(); if (libaltos.altos_list_next(list, device) == 0) break; - System.out.printf("Found device %s %d %s\n", - device.getProduct(), device.getSerial(), device.getPath()); - device_list.add(device); } libaltos.altos_list_finish(list); } - altos_device[] devices = new altos_device[device_list.size()]; + AltosDevice[] devices = new AltosDevice[device_list.size()]; for (int i = 0; i < device_list.size(); i++) devices[i] = device_list.get(i); return devices; diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index b3a0f9be..eb70877c 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -29,7 +29,7 @@ import altosui.AltosDevice; public class AltosDeviceDialog { static altos_device show (JFrame frame, String product) { - altos_device[] devices = null; + AltosDevice[] devices; devices = AltosDevice.list(product); if (devices != null & devices.length > 0) { Object o = JOptionPane.showInputDialog(frame, -- cgit v1.2.3 From e9153c4f2c71ed965822fcfe5112d2bc38506baf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 17:04:04 -0700 Subject: Re-enable freetts --- ao-tools/altosui/AltosVoice.java | 20 +++++++++----------- ao-tools/altosui/Makefile | 2 +- ao-tools/altosui/Manifest.txt | 1 + 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index 0c34795c..e4ea99a2 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -17,16 +17,14 @@ package altosui; -/*import com.sun.speech.freetts.Voice; +import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; -import com.sun.speech.freetts.audio.JavaClipAudioPlayer; */ +import com.sun.speech.freetts.audio.JavaClipAudioPlayer; import java.util.concurrent.LinkedBlockingQueue; public class AltosVoice implements Runnable { -/* VoiceManager voice_manager; Voice voice; -*/ LinkedBlockingQueue phrases; Thread thread; @@ -36,29 +34,29 @@ public class AltosVoice implements Runnable { try { for (;;) { String s = phrases.take(); -/* voice.speak(s); */ + voice.speak(s); } } catch (InterruptedException e) { } } public void speak(String s) { try { -/* if (voice != null) */ + if (voice != null) phrases.put(s); } catch (InterruptedException e) { } } public AltosVoice () { -/* voice_manager = VoiceManager.getInstance(); + voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); - if (voice != null) */ { -/* voice.allocate(); */ + if (voice != null) { + voice.allocate(); phrases = new LinkedBlockingQueue (); thread = new Thread(this); thread.start(); speak("Rocket Flight Monitor Ready"); - } /* else { + } else { System.out.printf("Voice manager failed to open %s\n", voice_name); Voice[] voices = voice_manager.getVoices(); System.out.printf("Available voices:\n"); @@ -66,6 +64,6 @@ public class AltosVoice implements Runnable { System.out.println(" " + voices[i].getName() + " (" + voices[i].getDomain() + " domain)"); } - } */ + } } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 1c49ba11..4068eebe 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:../libaltos:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 +CLASSPATH=..:../libaltos:/usr/share/java/*:/Users/keithp/freetts-1.2.2/lib/* CLASSFILES=\ AltosConvert.class \ AltosFile.class \ 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 -- cgit v1.2.3 From b51497597868a40df039dd3ca11b35a6258bbbb3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 18:04:10 -0700 Subject: Re-enable Linux support for altosui. This steals code from cc-usbdev for scanning the USB tree and uses the same tty code as on Darwin Signed-off-by: Keith Packard --- ao-tools/altosui/Manifest.txt | 2 +- ao-tools/libaltos/Makefile | 39 +++- ao-tools/libaltos/libaltos.c | 476 +++++++++++++++++++++++++++++++++++------- 3 files changed, 430 insertions(+), 87 deletions(-) diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 251ce2a0..7dbaafff 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: freetts.jar +Class-Path: /home/keithp/src/freetts/freetts-1.2.2/lib/freetts.jar diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 5ffbdadf..5cdc0fa7 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -1,3 +1,29 @@ +OS:=$(shell uname) + +ifeq ($(OS),Linux) + +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include -I. + +OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +LIBEXT=so + +endif + +ifeq ($(OS),Darwin) + +DARWIN_CFLAGS=\ + -I/System/Library/Frameworks/JavaVM.framework/Headers \ + -I/System/Library/Frameworks/IOKit.framework/Headers \ + -I/System/Library/Frameworks/CoreFoundation.framework/Headers +DARWIN_LIBS=\ + -framework IOKit -framework CoreFoundation + +OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY +LIBEXT=dylib + +endif + .SUFFIXES: .java .class CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" @@ -14,8 +40,6 @@ JNI_SRCS=$(JNI_FILE) \ $(JNI_DIR)/altos_device.java \ $(JNI_DIR)/libaltos.java -LIBEXT=dylib - JAVAFILES=\ $(JNI_SRCS) @@ -28,14 +52,7 @@ all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -DARWIN_CFLAGS=\ - -I/System/Library/Frameworks/JavaVM.framework/Headers \ - -I/System/Library/Frameworks/IOKit.framework/Headers \ - -I/System/Library/Frameworks/CoreFoundation.framework/Headers -DARWIN_LIBS=\ - -framework IOKit -framework CoreFoundation - -CFLAGS = $(DARWIN_CFLAGS) -I. -O0 -g +CFLAGS=$(OS_CFLAGS) -O0 -g HEADERS=libaltos.h SRCS = libaltos.c $(SWIG_WRAP) @@ -46,7 +63,7 @@ cjnitest: cjnitest.o $(OBJS) cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) libaltos.$(LIBEXT): $(OBJS) - gcc -shared -o $@ $(OBJS) $(LIBS) + gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) clean: rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 417c8fe5..7d471f38 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -16,10 +16,379 @@ */ #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; +} + +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 = 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; +} -#define USE_DARWIN +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; -#ifdef USE_DARWIN +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 @@ -30,36 +399,32 @@ #include #include #include -#include -#include -#include -#include struct altos_list { - io_iterator_t iterator; + 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); + 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; + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; } int @@ -117,10 +482,19 @@ altos_list_next(struct altos_list *list, struct altos_device *device) void altos_list_finish(struct altos_list *list) { - IOObjectRelease (list->iterator); - free(list); + IOObjectRelease (list->iterator); + free(list); } +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include #define USB_BUF_SIZE 64 @@ -133,54 +507,6 @@ struct altos_file { int in_read; }; -void -altos_test(char *path) -{ - int n; - char buf[16]; - int fd; - struct termios term; - - fd = open(path, O_RDWR | O_NOCTTY); - if (fd < 0) { - perror(path); - return; - } - if (ioctl(fd, TIOCEXCL, (char *) 0) < 0) { - perror("TIOCEXCL"); - close (fd); - return; - } - - n = tcgetattr(fd, &term); - if (n < 0) { - perror("tcgetattr"); - close(fd); - return; - } - cfmakeraw(&term); - term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; - n = tcsetattr(fd, TCSAFLUSH, &term); - if (n < 0) { - perror("tcsetattr"); - close(fd); - return; - } - write(fd, "\n?\n", 3); - for (;;) { - n = read(fd, buf, sizeof (buf)); - if (n < 0) { - perror("read"); - break; - } - if (n == 0) - break; - write(1, buf, n); - } - close(fd); -} - struct altos_file * altos_open(struct altos_device *device) { @@ -273,7 +599,7 @@ altos_getchar(struct altos_file *file, int timeout) return file->in_data[file->in_read++]; } -#endif /* USE_DARWIN */ +#endif /* POSIX_TTY */ #ifdef USE_LIBUSB #include -- cgit v1.2.3 From 0a782026f6b19e84ffd44f1ae1b466363474bd30 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 18:10:07 -0700 Subject: Darwin doesn't have strndup. This provides a private version of this GNU extension. Signed-off-by: Keith Packard --- ao-tools/libaltos/libaltos.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 7d471f38..df0d5b2e 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -40,6 +40,26 @@ match_dev(char *product, int serial, struct altos_device *device) 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) { @@ -61,7 +81,7 @@ altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) /* check for : */ colon = strchr(arg, ':'); if (colon) { - product = strndup(arg, colon - arg); + product = altos_strndup(arg, colon - arg); serial = strtol(colon + 1, &end, 0); if (*end != '\0') return 0; -- cgit v1.2.3 From fb8507975c6e081de2e909eca6faaa8f868b609e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:08:38 -0700 Subject: libaltos needs -I. on all systems Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 5cdc0fa7..7ed45b78 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -2,7 +2,7 @@ OS:=$(shell uname) ifeq ($(OS),Linux) -JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include -I. +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) @@ -52,7 +52,7 @@ all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -CFLAGS=$(OS_CFLAGS) -O0 -g +CFLAGS=$(OS_CFLAGS) -O0 -g -I. HEADERS=libaltos.h SRCS = libaltos.c $(SWIG_WRAP) -- cgit v1.2.3 From 4e3285575e0c7d029e799258587e965779990099 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:09:18 -0700 Subject: libaltos: make clean remove all built files Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 7ed45b78..7463a95c 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -66,7 +66,8 @@ libaltos.$(LIBEXT): $(OBJS) gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) clean: - rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest + rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest cjnitest.o + rm -rf swig_bindings libaltosJNI $(JNI_FILE): libaltos.i0 $(HEADERS) mkdir -p $(SWIG_DIR) -- cgit v1.2.3 From a58c44cd904e5429b807e5c23913051ed6484edc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:09:41 -0700 Subject: libaltos: build fat 10.5-compatible library Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 7463a95c..0bbd304c 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -13,13 +13,14 @@ endif ifeq ($(OS),Darwin) DARWIN_CFLAGS=\ - -I/System/Library/Frameworks/JavaVM.framework/Headers \ - -I/System/Library/Frameworks/IOKit.framework/Headers \ - -I/System/Library/Frameworks/CoreFoundation.framework/Headers + --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 +OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 LIBEXT=dylib endif @@ -63,7 +64,7 @@ cjnitest: cjnitest.o $(OBJS) cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) libaltos.$(LIBEXT): $(OBJS) - gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) + gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) clean: rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest cjnitest.o -- cgit v1.2.3 From 2c273710ea9b76ebee4101893f9fe84be8a02354 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:11:58 -0700 Subject: Add Mac OS X packaging files for altosui --- .../libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml | 1 + ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml | 1 + ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml | 1 + 3 files changed, 3 insertions(+) create mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml create mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml create mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml 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 -- cgit v1.2.3 From 3784578a40dcc61f447435cfdf22e13c409cb9c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:16:15 -0700 Subject: Add application icons for Mac OS X --- ao-tools/altosui/AltosUIIcon.icns | Bin 0 -> 129010 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ao-tools/altosui/AltosUIIcon.icns 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 -- cgit v1.2.3 From 809feb75e2155e84aebfcc431867edcfd9054670 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 01:22:56 -0700 Subject: Clean up altosui build a bit --- ao-tools/Makefile.am | 2 +- ao-tools/altosui/Makefile | 35 +++++++++++++++++++++++++++++++---- ao-tools/altosui/Manifest.txt | 2 +- ao-tools/altosui/voices.txt | 1 - 4 files changed, 33 insertions(+), 7 deletions(-) delete mode 100644 ao-tools/altosui/voices.txt 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/Makefile b/ao-tools/altosui/Makefile index 4068eebe..aa0278a8 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:../libaltos:/usr/share/java/*:/Users/keithp/freetts-1.2.2/lib/* +CLASSPATH=classes:./* CLASSFILES=\ AltosConvert.class \ AltosFile.class \ @@ -18,15 +18,42 @@ CLASSFILES=\ 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.jar +all: altosui.jar + +$(CLASSFILES): classes/altosui classes/libaltosJNI $(FREETTSJAR) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java altosui.jar: $(CLASSFILES) Manifest.txt - jar cfm $@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class + 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 + +$(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 7dbaafff..251ce2a0 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: /home/keithp/src/freetts/freetts-1.2.2/lib/freetts.jar +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 -- cgit v1.2.3 From 734cd15ccff691f851359518ce6118f29dc9f88d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 10:18:09 -0700 Subject: Remove directories as .class file dependencies; it makes them get rebuilt all the time --- ao-tools/altosui/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index aa0278a8..cd123023 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -35,12 +35,12 @@ JAVAFLAGS=-Xlint:unchecked all: altosui.jar -$(CLASSFILES): classes/altosui classes/libaltosJNI $(FREETTSJAR) +$(CLASSFILES): .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui.jar: $(CLASSFILES) Manifest.txt +altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Manifest.txt cd ./classes && jar cfm ../$@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class classes/altosui: -- cgit v1.2.3 From 8f2f38f2a9fb0c106e2c6b60cdc205292ce329ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 10:18:20 -0700 Subject: Java clean ups -- use varargs where possible, remove AltosSerialReader Add methods that format stuff using String.format for voice and serial link, remove AltosSerialReader class and just embed that in the AltosSerial class directly. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerial.java | 53 +++++++++++++-------------------------- ao-tools/altosui/AltosUI.java | 28 ++++++++------------- ao-tools/altosui/AltosVoice.java | 4 +++ 3 files changed, 32 insertions(+), 53 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 073bfb78..e84f5b63 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -37,7 +37,9 @@ import libaltosJNI.SWIGTYPE_p_altos_list; * line in a queue. Dealing with that queue is left up to other * threads. */ -class AltosSerialReader implements Runnable { + +public class AltosSerial implements Runnable { + SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; @@ -116,13 +118,27 @@ class AltosSerialReader implements Runnable { } } + public void putc(char c) { + libaltos.altos_putchar(altos, c); + } + + public void print(String data) { + for (int i = 0; i < data.length(); i++) + putc(data.charAt(i)); + } + + public void printf(String format, Object ... arguments) { + print(String.format(format, arguments)); + } + public void open(altos_device device) throws FileNotFoundException { close(); altos = libaltos.altos_open(device); input_thread = new Thread(this); input_thread.start(); } - public AltosSerialReader () { + + public AltosSerial() { altos = null; input_thread = null; line = ""; @@ -130,36 +146,3 @@ class AltosSerialReader implements Runnable { reply_queue = new LinkedBlockingQueue (); } } - -public class AltosSerial { - AltosSerialReader reader = null; - - public void close() { - reader.close(); - } - - public void open(altos_device device) throws FileNotFoundException { - reader.open(device); - } - - 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 AltosSerial() { - init(); - } - - public AltosSerial(altos_device device) throws FileNotFoundException { - init(); - open(device); - } -} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 33ed2c90..43aae295 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -221,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) { @@ -367,7 +359,7 @@ public class AltosUI extends JFrame { /* 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))); + voice.speak("%d meters", (int) (state.height + 0.5)); } /* If the rocket is coming down, check to see if it has landed; @@ -383,9 +375,9 @@ public class AltosUI extends JFrame { 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))); + voice.speak("bearing %d degrees, range %d meters", + (int) (state.from_pad.bearing + 0.5), + (int) (state.from_pad.distance + 0.5)); ++reported_landing; } } @@ -403,12 +395,12 @@ public class AltosUI extends JFrame { 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))); + voice.speak("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))); + voice.speak("max height %d meters", + (int) (state.max_height + 0.5)); break; } } 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); -- cgit v1.2.3 From 81bf2042ca39eb106b789e5a08647c3114669358 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 15:29:28 -0700 Subject: Java voice reporting cleanups. Make sure it says something at the end of a log file replay. Make sure it reports max speed after motor burn out, and max height after apogee. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 110 ++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 46 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 43aae295..3dfc8952 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -338,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("%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("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) { } @@ -393,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("max speed %d meters per second", + 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)); - break; - case AltosTelemetry.ao_flight_drogue: - voice.speak("max height %d meters", + } 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)); - break; } } old_state = state; } class DisplayThread extends Thread { + IdleThread idle_thread; + String read() throws InterruptedException { return null; } void close() { } @@ -418,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(); @@ -444,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 { @@ -500,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; @@ -537,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)); } } @@ -583,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); } } -- cgit v1.2.3