From 3fbefb3eea981d34a09496cf8abf0119de2e35bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 14:57:57 -0800 Subject: Move altosui to the top level, placing libaltos inside it. Signed-off-by: Keith Packard --- altosui/libaltos/.gitignore | 12 + altosui/libaltos/Makefile-standalone | 126 +++++ altosui/libaltos/Makefile.am | 41 ++ altosui/libaltos/altos.dll | Bin 0 -> 31765 bytes altosui/libaltos/cjnitest.c | 43 ++ altosui/libaltos/libaltos.c | 1028 ++++++++++++++++++++++++++++++++++ altosui/libaltos/libaltos.dylib | Bin 0 -> 54176 bytes altosui/libaltos/libaltos.h | 102 ++++ altosui/libaltos/libaltos.i0 | 5 + 9 files changed, 1357 insertions(+) create mode 100644 altosui/libaltos/.gitignore create mode 100644 altosui/libaltos/Makefile-standalone create mode 100644 altosui/libaltos/Makefile.am create mode 100755 altosui/libaltos/altos.dll create mode 100644 altosui/libaltos/cjnitest.c create mode 100644 altosui/libaltos/libaltos.c create mode 100755 altosui/libaltos/libaltos.dylib create mode 100644 altosui/libaltos/libaltos.h create mode 100644 altosui/libaltos/libaltos.i0 (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/.gitignore b/altosui/libaltos/.gitignore new file mode 100644 index 00000000..c490e6f8 --- /dev/null +++ b/altosui/libaltos/.gitignore @@ -0,0 +1,12 @@ +*.so +*.lo +*.la +*.java +*.class +.libs/ +classlibaltos.stamp +libaltos_wrap.c +libaltosJNI +cjnitest +libaltos.swig +swig_bindings/ diff --git a/altosui/libaltos/Makefile-standalone b/altosui/libaltos/Makefile-standalone new file mode 100644 index 00000000..4e438050 --- /dev/null +++ b/altosui/libaltos/Makefile-standalone @@ -0,0 +1,126 @@ +OS:=$(shell uname) + +# +# Linux +# +ifeq ($(OS),Linux) + +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include + +OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +OS_APP_CFLAGS=$(OS_LIB_CFLAGS) + +OS_LDFLAGS= + +LIBNAME=libaltos.so +EXEEXT= +endif + +# +# Darwin (Mac OS X) +# +ifeq ($(OS),Darwin) + +OS_LIB_CFLAGS=\ + -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \ + --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 +OS_APP_CFLAGS=$(OS_LIB_CFLAGS) + +OS_LDFLAGS =\ + -framework IOKit -framework CoreFoundation + +LIBNAME=libaltos.dylib +EXEEXT= + +endif + +# +# Windows +# +ifneq (,$(findstring MINGW,$(OS))) + +CC=gcc + +OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL +OS_APP_CFLAGS = -DWINDOWS -mconsole + +OS_LDFLAGS = -lgdi32 -luser32 -lcfgmgr32 -lsetupapi -lole32 \ + -ladvapi32 -lcomctl32 -mconsole -Wl,--add-stdcall-alias + +LIBNAME=altos.dll + +EXEEXT=.exe + +endif + +.SUFFIXES: .java .class + +CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" + +SWIG_DIR=swig_bindings/java +SWIG_FILE=$(SWIG_DIR)/libaltos.swig +SWIG_WRAP=$(SWIG_DIR)/libaltos_wrap.c + +JNI_DIR=libaltosJNI +JNI_FILE=$(JNI_DIR)/libaltosJNI.java +JNI_SRCS=$(JNI_FILE) \ + $(JNI_DIR)/SWIGTYPE_p_altos_file.java \ + $(JNI_DIR)/SWIGTYPE_p_altos_list.java \ + $(JNI_DIR)/altos_device.java \ + $(JNI_DIR)/libaltos.java + +JAVAFILES=\ + $(JNI_SRCS) + +CLASSFILES = $(JAVAFILES:%.java=%.class) + +JAVAFLAGS=-Xlint:unchecked + +CJNITEST=cjnitest$(EXEEXT) + +all: $(LIBNAME) $(CJNITEST) $(CLASSFILES) + +.java.class: + javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java + +CFLAGS=$(OS_LIB_CFLAGS) -O -I. + +LDFLAGS=$(OS_LDFLAGS) + +HEADERS=libaltos.h +SRCS = libaltos.c $(SWIG_WRAP) +OBJS = $(SRCS:%.c=%.o) +LIBS = $(DARWIN_LIBS) + +$(CJNITEST): cjnitest.c $(LIBNAME) + $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS) + +$(LIBNAME): $(OBJS) + $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) + +clean: + rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o + rm -rf swig_bindings libaltosJNI + +distclean: clean + +$(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) + +ifeq ($(OS),Linux) +install: $(LIBNAME) + install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) + +endif + +.NOTPARALLEL: diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am new file mode 100644 index 00000000..388d2104 --- /dev/null +++ b/altosui/libaltos/Makefile.am @@ -0,0 +1,41 @@ +JAVAC=javac +AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) +AM_JAVACFLAGS=-encoding UTF-8 + +altoslibdir=$(libdir)/altos + +altoslib_LTLIBRARIES=libaltos.la + +libaltos_la_LDFLAGS = -version-info 1:0:1 + +libaltos_la_SOURCES=\ + libaltos.c \ + libaltos_wrap.c + +noinst_PROGRAMS=cjnitest + +cjnitest_LDADD=libaltos.la + +LIBS= + +HFILES=libaltos.h + +SWIG_FILE=libaltos.swig + +CLASSDIR=libaltosJNI + +$(SWIG_FILE): libaltos.i0 $(HFILES) + sed 's;//%;%;' libaltos.i0 $(HFILES) > $(SWIG_FILE) + +all-local: classlibaltos.stamp + +libaltos_wrap.c: classlibaltos.stamp + +classlibaltos.stamp: $(SWIG_FILE) + swig -java -package libaltosJNI $(SWIG_FILE) + mkdir -p libaltosJNI + $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \ + touch classlibaltos.stamp + +clean-local: + -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll new file mode 100755 index 00000000..28e9b4ad Binary files /dev/null and b/altosui/libaltos/altos.dll differ diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c new file mode 100644 index 00000000..c6d6e069 --- /dev/null +++ b/altosui/libaltos/cjnitest.c @@ -0,0 +1,43 @@ +#include +#include "libaltos.h" + +static void +altos_puts(struct altos_file *file, char *string) +{ + char c; + + while ((c = *string++)) + altos_putchar(file, c); +} + +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; + + printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product, + device.name, device.serial, device.path); + + file = altos_open(&device); + if (!file) { + printf("altos_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); + altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar (c); + } + if (c != LIBALTOS_TIMEOUT) + printf ("getchar returns %d\n", c); + altos_close(file); + } + altos_list_finish(list); + altos_fini(); +} diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c new file mode 100644 index 00000000..465f0ac8 --- /dev/null +++ b/altosui/libaltos/libaltos.c @@ -0,0 +1,1028 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "libaltos.h" +#include +#include +#include + +#define USE_POLL + +PUBLIC int +altos_init(void) +{ + return LIBALTOS_SUCCESS; +} + +PUBLIC void +altos_fini(void) +{ +} + +#ifdef DARWIN + +#undef USE_POLL + +/* 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 + +/* + * Scan for Altus Metrum devices by looking through /sys + */ + +#ifdef LINUX + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +static char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} + +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product_name; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; + +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct altos_usbdev * +usb_scan_device(char *sys) +{ + struct altos_usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct altos_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product_name = 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_name); + /* 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; +}; + +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 (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { + 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->name, dev->product_name); + device->vendor = dev->idVendor; + device->product = dev->idProduct; + strcpy(device->path, dev->tty); + device->serial = dev->serial; + list->current++; + return 1; +} + +void +altos_list_finish(struct altos_list *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} + +#endif + +#ifdef DARWIN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct altos_list { + io_iterator_t iterator; +}; + +static int +get_string(io_object_t object, CFStringRef entry, char *result, int result_len) +{ + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); + + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; +} + +static int +get_number(io_object_t object, CFStringRef entry, int *result) +{ + CFTypeRef entry_as_number; + Boolean got_number; + + entry_as_number = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_number) { + got_number = CFNumberGetValue(entry_as_number, + kCFNumberIntType, + result); + if (got_number) + return 1; + } + return 0; +} + +struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc (sizeof (struct altos_list), 1); + CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); + io_iterator_t tdIterator; + io_object_t tdObject; + kern_return_t ret; + int i; + + ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); + if (ret != kIOReturnSuccess) + return NULL; + 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_number (object, CFSTR(kUSBVendorID), &device->vendor) || + !get_number (object, CFSTR(kUSBProductID), &device->product)) + continue; + if (device->vendor != 0xfffe) + continue; + if (device->product < 0x000a || 0x0013 < device->product) + continue; + if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) && + get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) && + get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { + device->serial = atoi(serial_string); + return 1; + } + } +} + +void +altos_list_finish(struct altos_list *list) +{ + IOObjectRelease (list->iterator); + free(list); +} + +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; +#ifdef USE_POLL + int pipe[2]; +#else + int out_fd; +#endif + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +PUBLIC 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; + } +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->out_fd < 0) { + perror(device->path); + close(file->fd); + free(file); + return NULL; + } +#endif + ret = tcgetattr(file->fd, &term); + if (ret < 0) { + perror("tcgetattr"); + close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif + free(file); + return NULL; + } + cfmakeraw(&term); +#ifdef USE_POLL + term.c_cc[VMIN] = 1; + term.c_cc[VTIME] = 0; +#else + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; +#endif + ret = tcsetattr(file->fd, TCSAFLUSH, &term); + if (ret < 0) { + perror("tcsetattr"); + close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif + free(file); + return NULL; + } + return file; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->fd != -1) { + int fd = file->fd; + file->fd = -1; +#ifdef USE_POLL + write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + close(fd); + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + free(file); +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + if (file->out_used && 0) { + printf ("flush \""); + fwrite(file->out_data, 1, file->out_used, stdout); + printf ("\"\n"); + } + while (file->out_used) { + int ret; + + if (file->fd < 0) + return -EBADF; +#ifdef USE_POLL + ret = write (file->fd, file->out_data, file->out_used); +#else + ret = write (file->out_fd, file->out_data, file->out_used); +#endif + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } + return 0; +} + +PUBLIC 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; + ret = 0; + if (file->out_used == USB_BUF_SIZE) + ret = altos_flush(file); + return 0; +} + +#ifdef USE_POLL +#include +#endif + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; +#ifdef USE_POLL + struct pollfd fd[2]; +#endif + + if (timeout == 0) + timeout = -1; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; + ret = poll(fd, 2, timeout); + if (ret < 0) { + perror("altos_getchar"); + return LIBALTOS_ERROR; + } + if (ret == 0) + return LIBALTOS_TIMEOUT; + + if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL)) + return LIBALTOS_ERROR; + if (fd[0].revents & POLLIN) +#endif + { + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret < 0) { + perror("altos_getchar"); + return LIBALTOS_ERROR; + } + file->in_read = 0; + file->in_used = ret; +#ifndef USE_POLL + if (ret == 0 && timeout > 0) + return LIBALTOS_TIMEOUT; +#endif + } + } + if (file->in_used && 0) { + printf ("fill \""); + fwrite(file->in_data, 1, file->in_used, stdout); + printf ("\"\n"); + } + return 0; +} + +PUBLIC int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* POSIX_TTY */ + +#ifdef WINDOWS + +#include +#include +#include + +struct altos_list { + HDEVINFO dev_info; + int index; +}; + +#define USB_BUF_SIZE 64 + +struct altos_file { + HANDLE handle; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; + OVERLAPPED ov_read; + BOOL pend_read; + OVERLAPPED ov_write; +}; + +PUBLIC struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc(1, sizeof (struct altos_list)); + + if (!list) + return NULL; + list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, + DIGCF_ALLCLASSES|DIGCF_PRESENT); + if (list->dev_info == INVALID_HANDLE_VALUE) { + printf("SetupDiGetClassDevs failed %d\n", GetLastError()); + free(list); + return NULL; + } + list->index = 0; + return list; +} + +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + SP_DEVINFO_DATA dev_info_data; + char port[128]; + DWORD port_len; + char friendlyname[256]; + char symbolic[256]; + DWORD symbolic_len; + HKEY dev_key; + int vid, pid; + int serial; + HRESULT result; + DWORD friendlyname_type; + DWORD friendlyname_len; + + dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); + while(SetupDiEnumDeviceInfo(list->dev_info, list->index, + &dev_info_data)) + { + list->index++; + + dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data, + DICS_FLAG_GLOBAL, 0, DIREG_DEV, + KEY_READ); + if (dev_key == INVALID_HANDLE_VALUE) { + printf("cannot open device registry key\n"); + continue; + } + + /* Fetch symbolic name for this device and parse out + * the vid/pid/serial info */ + symbolic_len = sizeof(symbolic); + result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, + symbolic, &symbolic_len); + if (result != 0) { + printf("cannot find SymbolicName value\n"); + RegCloseKey(dev_key); + continue; + } + vid = pid = serial = 0; + sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1, + "%04X", &vid); + sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + "%04X", &pid); + sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + "%d", &serial); + if (!USB_IS_ALTUSMETRUM(vid, pid)) { + RegCloseKey(dev_key); + continue; + } + + /* Fetch the com port name */ + port_len = sizeof (port); + result = RegQueryValueEx(dev_key, "PortName", NULL, NULL, + port, &port_len); + RegCloseKey(dev_key); + if (result != 0) { + printf("failed to get PortName\n"); + continue; + } + + /* Fetch the device description which is the device name, + * with firmware that has unique USB ids */ + friendlyname_len = sizeof (friendlyname); + if(!SetupDiGetDeviceRegistryProperty(list->dev_info, + &dev_info_data, + SPDRP_FRIENDLYNAME, + &friendlyname_type, + (BYTE *)friendlyname, + sizeof(friendlyname), + &friendlyname_len)) + { + printf("Failed to get friendlyname\n"); + continue; + } + device->vendor = vid; + device->product = pid; + device->serial = serial; + strcpy(device->name, friendlyname); + + strcpy(device->path, port); + return 1; + } + result = GetLastError(); + if (result != ERROR_NO_MORE_ITEMS) + printf ("SetupDiEnumDeviceInfo failed error %d\n", result); + return 0; +} + +PUBLIC void +altos_list_finish(struct altos_list *list) +{ + SetupDiDestroyDeviceInfoList(list->dev_info); + free(list); +} + +static int +altos_queue_read(struct altos_file *file) +{ + DWORD got; + if (file->pend_read) + return LIBALTOS_SUCCESS; + + if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { + if (GetLastError() != ERROR_IO_PENDING) + return LIBALTOS_ERROR; + file->pend_read = TRUE; + } else { + file->pend_read = FALSE; + file->in_read = 0; + file->in_used = got; + } + return LIBALTOS_SUCCESS; +} + +static int +altos_wait_read(struct altos_file *file, int timeout) +{ + DWORD ret; + DWORD got; + + if (!file->pend_read) + return LIBALTOS_SUCCESS; + + if (!timeout) + timeout = INFINITE; + + ret = WaitForSingleObject(file->ov_read.hEvent, timeout); + switch (ret) { + case WAIT_OBJECT_0: + if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) + return LIBALTOS_ERROR; + file->pend_read = FALSE; + file->in_read = 0; + file->in_used = got; + break; + case WAIT_TIMEOUT: + return LIBALTOS_TIMEOUT; + break; + default: + return LIBALTOS_ERROR; + } + return LIBALTOS_SUCCESS; +} + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; + + if (file->in_read < file->in_used) + return LIBALTOS_SUCCESS; + + file->in_read = file->in_used = 0; + + ret = altos_queue_read(file); + if (ret) + return ret; + ret = altos_wait_read(file, timeout); + if (ret) + return ret; + + return LIBALTOS_SUCCESS; +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + DWORD put; + char *data = file->out_data; + char used = file->out_used; + DWORD ret; + + while (used) { + if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { + if (GetLastError() != ERROR_IO_PENDING) + 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)) + return LIBALTOS_ERROR; + break; + default: + return LIBALTOS_ERROR; + } + } + data += put; + used -= put; + } + file->out_used = 0; + return LIBALTOS_SUCCESS; +} + +PUBLIC struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (1, sizeof (struct altos_file)); + char full_name[64]; + DCB dcbSerialParams = {0}; + COMMTIMEOUTS timeouts; + + if (!file) + return NULL; + + strcpy(full_name, "\\\\.\\"); + strcat(full_name, device->path); + file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + if (file->handle == INVALID_HANDLE_VALUE) { + free(file); + return NULL; + } + file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */ + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + SetCommTimeouts(file->handle, &timeouts); + + dcbSerialParams.DCBlength = sizeof(dcbSerialParams); + if (!GetCommState(file->handle, &dcbSerialParams)) { + CloseHandle(file->handle); + free(file); + return NULL; + } + dcbSerialParams.BaudRate = CBR_9600; + dcbSerialParams.ByteSize = 8; + dcbSerialParams.StopBits = ONESTOPBIT; + dcbSerialParams.Parity = NOPARITY; + if (!SetCommState(file->handle, &dcbSerialParams)) { + CloseHandle(file->handle); + free(file); + return NULL; + } + + return file; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->handle != INVALID_HANDLE_VALUE) { + CloseHandle(file->handle); + file->handle = INVALID_HANDLE_VALUE; + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + 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 LIBALTOS_SUCCESS; +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->handle == INVALID_HANDLE_VALUE) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif diff --git a/altosui/libaltos/libaltos.dylib b/altosui/libaltos/libaltos.dylib new file mode 100755 index 00000000..89aa12e7 Binary files /dev/null and b/altosui/libaltos/libaltos.dylib differ diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h new file mode 100644 index 00000000..6e94899e --- /dev/null +++ b/altosui/libaltos/libaltos.h @@ -0,0 +1,102 @@ +/* + * 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_ + +#include + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef BUILD_STATIC +# ifdef BUILD_DLL +# define PUBLIC __declspec(dllexport) +# else +# define PUBLIC __declspec(dllimport) +# endif +# endif /* BUILD_STATIC */ +#endif + +#ifndef PUBLIC +# define PUBLIC +#endif + +#define USB_VENDOR_FSF 0xfffe +#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF +#define USB_PRODUCT_ALTUSMETRUM 0x000a +#define USB_PRODUCT_TELEMETRUM 0x000b +#define USB_PRODUCT_TELEDONGLE 0x000c +#define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 + +#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ + (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ + (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) + +struct altos_device { + //%immutable; + int vendor; + int product; + int serial; + char name[256]; + char path[256]; + //%mutable; +}; + +#define LIBALTOS_SUCCESS 0 +#define LIBALTOS_ERROR -1 +#define LIBALTOS_TIMEOUT -2 + +/* Returns 0 for success, < 0 on error */ +PUBLIC int +altos_init(void); + +PUBLIC void +altos_fini(void); + +PUBLIC struct altos_list * +altos_list_start(void); + +/* Returns 1 for success, zero on end of list */ +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device); + +PUBLIC void +altos_list_finish(struct altos_list *list); + +PUBLIC struct altos_file * +altos_open(struct altos_device *device); + +PUBLIC void +altos_close(struct altos_file *file); + +PUBLIC void +altos_free(struct altos_file *file); + +/* Returns < 0 for error */ +PUBLIC int +altos_putchar(struct altos_file *file, char c); + +/* Returns < 0 for error */ +PUBLIC int +altos_flush(struct altos_file *file); + +/* Returns < 0 for error or timeout. timeout of 0 == wait forever */ +PUBLIC int +altos_getchar(struct altos_file *file, int timeout); + +#endif /* _LIBALTOS_H_ */ diff --git a/altosui/libaltos/libaltos.i0 b/altosui/libaltos/libaltos.i0 new file mode 100644 index 00000000..d06468f5 --- /dev/null +++ b/altosui/libaltos/libaltos.i0 @@ -0,0 +1,5 @@ +%module libaltos +%{ +#include "libaltos.h" +%} + -- cgit v1.2.3 From bf1c7df5301a1727e871a8447f835fe75bdce3fc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 8 Apr 2011 10:12:50 -0700 Subject: altosui: Add TeleBT USB device support TeleBT can work just like a TeleDongle over USB. Signed-off-by: Keith Packard --- altosui/AltosDevice.java | 14 +++++++++++--- altosui/libaltos/libaltos.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java index f0fda57b..b7aa38f6 100644 --- a/altosui/AltosDevice.java +++ b/altosui/AltosDevice.java @@ -81,15 +81,21 @@ public class AltosDevice extends altos_device { return 0x000d; } + static int usb_product_telebt() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEBT; + return 0x000e; + } + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); public final static int product_altusmetrum = usb_product_altusmetrum(); public final static int product_telemetrum = usb_product_telemetrum(); public final static int product_teledongle = usb_product_teledongle(); public final static int product_teleterra = usb_product_teleterra(); + public final static int product_telebt = usb_product_telebt(); public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); - public final static int product_any = 0x10000; public final static int product_basestation = 0x10000 + 1; @@ -98,7 +104,7 @@ public class AltosDevice extends altos_device { if (name == null) name = "Altus Metrum"; return String.format("%-20.20s %4d %s", - getName(), getSerial(), getPath()); + name, getSerial(), getPath()); } public String toShortString() { @@ -129,7 +135,9 @@ public class AltosDevice extends altos_device { return true; if (want_product == product_basestation) - return matchProduct(product_teledongle) || matchProduct(product_teleterra); + return matchProduct(product_teledongle) || + matchProduct(product_teleterra) || + matchProduct(product_telebt); int have_product = getProduct(); diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 6e94899e..0e5691cb 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -40,6 +40,7 @@ #define USB_PRODUCT_TELEMETRUM 0x000b #define USB_PRODUCT_TELEDONGLE 0x000c #define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_TELEBT 0x000e #define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a #define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 -- cgit v1.2.3 From 8dd455204cf8712fa8c142b0c0517cec1bf5fd0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 8 Apr 2011 10:13:55 -0700 Subject: altosui: Add low-level Bluetooth APIs Adds the JNI functions to query and connect to arbitrary bluetooth devices. Adds Java wrappers to construct a list of proximate bluetooth devices. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 142 ++++++++++ altosui/AltosEepromDownload.java | 1 + altosui/Makefile.am | 1 + altosui/libaltos/Makefile.am | 2 +- altosui/libaltos/cjnitest.c | 26 ++ altosui/libaltos/libaltos.c | 574 ++++++++++++++++++++++++--------------- altosui/libaltos/libaltos.h | 21 ++ 7 files changed, 543 insertions(+), 224 deletions(-) create mode 100644 altosui/AltosBTDevice.java (limited to 'altosui/libaltos') diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java new file mode 100644 index 00000000..8eb18bb9 --- /dev/null +++ b/altosui/AltosBTDevice.java @@ -0,0 +1,142 @@ +/* + * Copyright © 2011 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.util.*; +import libaltosJNI.*; + +public class AltosBTDevice extends altos_bt_device { + + static public boolean initialized = false; + static public boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + loaded_library = false; + } + initialized = true; + } + return loaded_library; + } + + static String bt_product_telebt() { + if (load_library()) + return libaltosConstants.BLUETOOTH_PRODUCT_TELEBT; + return "TeleBT"; + } + + public final static String bt_product_telebt = bt_product_telebt(); + public final static String bt_product_any = "Any"; + public final static String bt_product_basestation = "Basestation"; + + public String getProduct() { + String name = getName(); + if (name == null) + return "Altus Metrum"; + int dash = name.lastIndexOf("-"); + if (dash < 0) + return name; + return name.substring(0,dash); + } + + public int getSerial() { + String name = getName(); + if (name == null) + return 0; + int dash = name.lastIndexOf("-"); + if (dash < 0 || dash >= name.length()) + return 0; + String sn = name.substring(dash + 1, name.length()); + try { + return Integer.parseInt(sn); + } catch (NumberFormatException ne) { + return 0; + } + } + + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%-20.20s %4d %s", + getProduct(), getSerial(), getAddr()); + } + + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + getProduct(), getSerial(), getAddr()); + + } + + public boolean isAltusMetrum() { + if (getName().startsWith(bt_product_telebt)) + return true; + return false; + } + + public boolean matchProduct(String want_product) { + + if (!isAltusMetrum()) + return false; + + if (want_product.equals(bt_product_any)) + return true; + + if (want_product.equals(bt_product_basestation)) + return matchProduct(bt_product_telebt); + + if (want_product.equals(getProduct())) + return true; + + return false; + } + + static AltosBTDevice[] list(String product) { + if (!load_library()) + return null; + + SWIGTYPE_p_altos_bt_list list = libaltos.altos_bt_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + SWIGTYPE_p_altos_file file; + + for (;;) { + AltosBTDevice device = new AltosBTDevice(); + if (libaltos.altos_bt_list_next(list, device) == 0) + break; + if (device.matchProduct(product)) + device_list.add(device); + } + libaltos.altos_bt_list_finish(list); + } + + AltosBTDevice[] devices = new AltosBTDevice[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/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index fad16460..5c704968 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -158,6 +158,7 @@ public class AltosEepromDownload implements Runnable { r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0); if (s == Altos.ao_flight_landed) done = true; + state = s; any_valid = true; } else { if (v != 0xffff) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 01fe50c8..5b11d1b0 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -26,6 +26,7 @@ altosui_JAVA = \ AltosDescent.java \ AltosDeviceDialog.java \ AltosDevice.java \ + AltosBTDevice.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am index 388d2104..3f5f3ee2 100644 --- a/altosui/libaltos/Makefile.am +++ b/altosui/libaltos/Makefile.am @@ -16,7 +16,7 @@ noinst_PROGRAMS=cjnitest cjnitest_LDADD=libaltos.la -LIBS= +LIBS=-lbluetooth HFILES=libaltos.h diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c index c6d6e069..79561643 100644 --- a/altosui/libaltos/cjnitest.c +++ b/altosui/libaltos/cjnitest.c @@ -14,6 +14,8 @@ main () { struct altos_device device; struct altos_list *list; + struct altos_bt_device bt_device; + struct altos_bt_list *bt_list; altos_init(); list = altos_list_start(); @@ -39,5 +41,29 @@ main () altos_close(file); } altos_list_finish(list); + bt_list = altos_bt_list_start(); + while (altos_bt_list_next(bt_list, &bt_device)) { + printf ("%s %s\n", bt_device.name, bt_device.addr); + if (strncmp(bt_device.name, "TeleBT", 6) == 0) { + struct altos_file *file; + + int c; + file = altos_bt_open(&bt_device); + if (!file) { + printf("altos_bt_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); + altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar(c); + } + if (c != LIBALTOS_TIMEOUT) + printf("getchar returns %d\n", c); + altos_close(file); + } + } + altos_bt_list_finish(bt_list); altos_fini(); + return 0; } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 465f0ac8..13635a0d 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -56,6 +56,230 @@ altos_strndup (const char *s, size_t n) #define altos_strndup strndup #endif +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; +#ifdef USE_POLL + int pipe[2]; +#else + int out_fd; +#endif + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +PUBLIC 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; + } +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->out_fd < 0) { + perror(device->path); + close(file->fd); + free(file); + return NULL; + } +#endif + ret = tcgetattr(file->fd, &term); + if (ret < 0) { + perror("tcgetattr"); + close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif + free(file); + return NULL; + } + cfmakeraw(&term); +#ifdef USE_POLL + term.c_cc[VMIN] = 1; + term.c_cc[VTIME] = 0; +#else + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; +#endif + ret = tcsetattr(file->fd, TCSAFLUSH, &term); + if (ret < 0) { + perror("tcsetattr"); + close(file->fd); +#ifndef USE_POLL + close(file->out_fd); +#endif + free(file); + return NULL; + } + return file; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->fd != -1) { + int fd = file->fd; + file->fd = -1; +#ifdef USE_POLL + write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + close(fd); + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + free(file); +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + if (file->out_used && 0) { + printf ("flush \""); + fwrite(file->out_data, 1, file->out_used, stdout); + printf ("\"\n"); + } + while (file->out_used) { + int ret; + + if (file->fd < 0) + return -EBADF; +#ifdef USE_POLL + ret = write (file->fd, file->out_data, file->out_used); +#else + ret = write (file->out_fd, file->out_data, file->out_used); +#endif + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } + return 0; +} + +PUBLIC 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; + ret = 0; + if (file->out_used == USB_BUF_SIZE) + ret = altos_flush(file); + return 0; +} + +#ifdef USE_POLL +#include +#endif + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; +#ifdef USE_POLL + struct pollfd fd[2]; +#endif + + if (timeout == 0) + timeout = -1; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; + ret = poll(fd, 2, timeout); + if (ret < 0) { + perror("altos_getchar"); + return LIBALTOS_ERROR; + } + if (ret == 0) + return LIBALTOS_TIMEOUT; + + if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL)) + return LIBALTOS_ERROR; + if (fd[0].revents & POLLIN) +#endif + { + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret < 0) { + perror("altos_getchar"); + return LIBALTOS_ERROR; + } + file->in_read = 0; + file->in_used = ret; +#ifndef USE_POLL + if (ret == 0 && timeout > 0) + return LIBALTOS_TIMEOUT; +#endif + } + } + if (file->in_used && 0) { + printf ("fill \""); + fwrite(file->in_data, 1, file->in_used, stdout); + printf ("\"\n"); + } + return 0; +} + +PUBLIC int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* POSIX_TTY */ + /* * Scan for Altus Metrum devices by looking through /sys */ @@ -68,6 +292,10 @@ altos_strndup (const char *s, size_t n) #include #include #include +#include +#include +#include +#include static char * cc_fullname (char *dir, char *file) @@ -354,6 +582,129 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } +struct altos_bt_list { + inquiry_info *ii; + int sock; + int dev_id; + int rsp; + int num_rsp; +}; + +#define INQUIRY_MAX_RSP 255 +#define INQUIRY_LEN 8 + +struct altos_bt_list * +altos_bt_list_start(void) +{ + struct altos_bt_list *bt_list; + + bt_list = calloc(1, sizeof (struct altos_bt_list)); + if (!bt_list) + goto no_bt_list; + + bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info)); + if (!bt_list->ii) + goto no_ii; + bt_list->dev_id = hci_get_route(NULL); + if (bt_list->dev_id < 0) + goto no_dev_id; + + bt_list->sock = hci_open_dev(bt_list->dev_id); + if (bt_list->sock < 0) + goto no_sock; + + bt_list->num_rsp = hci_inquiry(bt_list->dev_id, + INQUIRY_LEN, + INQUIRY_MAX_RSP, + NULL, + &bt_list->ii, + IREQ_CACHE_FLUSH); + if (bt_list->num_rsp < 0) + goto no_rsp; + + bt_list->rsp = 0; + return bt_list; + +no_rsp: + close(bt_list->sock); +no_sock: +no_dev_id: + free(bt_list->ii); +no_ii: + free(bt_list); +no_bt_list: + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + inquiry_info *ii; + + if (bt_list->rsp >= bt_list->num_rsp) + return 0; + + ii = &bt_list->ii[bt_list->rsp]; + ba2str(&ii->bdaddr, device->addr); + memset(&device->name, '\0', sizeof (device->name)); + if (hci_read_remote_name(bt_list->sock, &ii->bdaddr, + sizeof (device->name), + device->name, 0) < 0) { + strcpy(device->name, "[unknown]"); + } + bt_list->rsp++; + return 1; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ + close(bt_list->sock); + free(bt_list->ii); + free(bt_list); +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ + struct sockaddr_rc addr = { 0 }; + int s, status; + struct altos_file *file; + + file = calloc(1, sizeof (struct altos_file)); + if (!file) + goto no_file; + file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (file->fd < 0) + goto no_sock; + + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = 1; + str2ba(device->addr, &addr.rc_bdaddr); + + status = connect(file->fd, + (struct sockaddr *)&addr, + sizeof(addr)); + if (status < 0) { + perror("connect"); + goto no_link; + } + +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = dup(file->fd); +#endif + return file; +no_link: + close(s); +no_sock: + free(file); +no_file: + return NULL; +} + #endif #ifdef DARWIN @@ -468,229 +819,6 @@ altos_list_finish(struct altos_list *list) #endif -#ifdef POSIX_TTY - -#include -#include -#include -#include -#include - -#define USB_BUF_SIZE 64 - -struct altos_file { - int fd; -#ifdef USE_POLL - int pipe[2]; -#else - int out_fd; -#endif - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - int in_read; -}; - -PUBLIC 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; - } -#ifdef USE_POLL - pipe(file->pipe); -#else - file->out_fd = open(device->path, O_RDWR | O_NOCTTY); - if (file->out_fd < 0) { - perror(device->path); - close(file->fd); - free(file); - return NULL; - } -#endif - ret = tcgetattr(file->fd, &term); - if (ret < 0) { - perror("tcgetattr"); - close(file->fd); -#ifndef USE_POLL - close(file->out_fd); -#endif - free(file); - return NULL; - } - cfmakeraw(&term); -#ifdef USE_POLL - term.c_cc[VMIN] = 1; - term.c_cc[VTIME] = 0; -#else - term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; -#endif - ret = tcsetattr(file->fd, TCSAFLUSH, &term); - if (ret < 0) { - perror("tcsetattr"); - close(file->fd); -#ifndef USE_POLL - close(file->out_fd); -#endif - free(file); - return NULL; - } - return file; -} - -PUBLIC void -altos_close(struct altos_file *file) -{ - if (file->fd != -1) { - int fd = file->fd; - file->fd = -1; -#ifdef USE_POLL - write(file->pipe[1], "\r", 1); -#else - close(file->out_fd); - file->out_fd = -1; -#endif - close(fd); - } -} - -PUBLIC void -altos_free(struct altos_file *file) -{ - altos_close(file); - free(file); -} - -PUBLIC int -altos_flush(struct altos_file *file) -{ - if (file->out_used && 0) { - printf ("flush \""); - fwrite(file->out_data, 1, file->out_used, stdout); - printf ("\"\n"); - } - while (file->out_used) { - int ret; - - if (file->fd < 0) - return -EBADF; -#ifdef USE_POLL - ret = write (file->fd, file->out_data, file->out_used); -#else - ret = write (file->out_fd, file->out_data, file->out_used); -#endif - if (ret < 0) - return -errno; - if (ret) { - memmove(file->out_data, file->out_data + ret, - file->out_used - ret); - file->out_used -= ret; - } - } - return 0; -} - -PUBLIC 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; - ret = 0; - if (file->out_used == USB_BUF_SIZE) - ret = altos_flush(file); - return 0; -} - -#ifdef USE_POLL -#include -#endif - -static int -altos_fill(struct altos_file *file, int timeout) -{ - int ret; -#ifdef USE_POLL - struct pollfd fd[2]; -#endif - - if (timeout == 0) - timeout = -1; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; -#ifdef USE_POLL - fd[0].fd = file->fd; - fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; - fd[1].fd = file->pipe[0]; - fd[1].events = POLLIN; - ret = poll(fd, 2, timeout); - if (ret < 0) { - perror("altos_getchar"); - return LIBALTOS_ERROR; - } - if (ret == 0) - return LIBALTOS_TIMEOUT; - - if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL)) - return LIBALTOS_ERROR; - if (fd[0].revents & POLLIN) -#endif - { - ret = read(file->fd, file->in_data, USB_BUF_SIZE); - if (ret < 0) { - perror("altos_getchar"); - return LIBALTOS_ERROR; - } - file->in_read = 0; - file->in_used = ret; -#ifndef USE_POLL - if (ret == 0 && timeout > 0) - return LIBALTOS_TIMEOUT; -#endif - } - } - if (file->in_used && 0) { - printf ("fill \""); - fwrite(file->in_data, 1, file->in_used, stdout); - printf ("\"\n"); - } - return 0; -} - -PUBLIC int -altos_getchar(struct altos_file *file, int timeout) -{ - int ret; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; - ret = altos_fill(file, timeout); - if (ret) - return ret; - } - return file->in_data[file->in_read++]; -} - -#endif /* POSIX_TTY */ #ifdef WINDOWS diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 0e5691cb..9c3f9655 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -58,6 +58,15 @@ struct altos_device { //%mutable; }; +#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" + +struct altos_bt_device { + //%immutable; + char name[256]; + char addr[20]; + //%mutable; +}; + #define LIBALTOS_SUCCESS 0 #define LIBALTOS_ERROR -1 #define LIBALTOS_TIMEOUT -2 @@ -100,4 +109,16 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); +PUBLIC struct altos_bt_list * +altos_bt_list_start(void); + +PUBLIC int +altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); + +PUBLIC void +altos_bt_list_finish(struct altos_bt_list *list); + +PUBLIC struct altos_file * +altos_bt_open(struct altos_bt_device *device); + #endif /* _LIBALTOS_H_ */ -- cgit v1.2.3 From 17f38e045fcd8ca0224095c0b2b7b098df77a8d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 08:43:40 -0700 Subject: altosui: Use persistent list of bluetooth devices for device dialogs Store a list of known bluetooth devices as preferences. Always include those in device dialogs with an option to go browse for more devices in both the device dialog and the Configure AltosUI dialog. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 + altosui/AltosBTDevice.java | 24 ++- altosui/AltosBTDeviceIterator.java | 7 +- altosui/AltosBTKnown.java | 97 +++++++++++++ altosui/AltosBTManage.java | 291 ++++++++++++++++++++++++++++--------- altosui/AltosConfigureUI.java | 2 +- altosui/AltosDeviceDialog.java | 53 ++++--- altosui/AltosFlightUI.java | 2 +- altosui/AltosPreferences.java | 25 +++- altosui/AltosSiteMap.java | 2 - altosui/AltosUI.java | 8 +- altosui/AltosUSBDevice.java | 9 +- altosui/Makefile.am | 1 + altosui/libaltos/cjnitest.c | 2 +- altosui/libaltos/libaltos.c | 16 +- altosui/libaltos/libaltos.h | 5 +- 16 files changed, 423 insertions(+), 123 deletions(-) create mode 100644 altosui/AltosBTKnown.java (limited to 'altosui/libaltos') diff --git a/altosui/Altos.java b/altosui/Altos.java index d221077e..a087f73a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -309,4 +309,6 @@ public class Altos { } public final static String bt_product_telebt = bt_product_telebt(); + + public static AltosBTKnown bt_known = new AltosBTKnown(); } diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index ff2be49a..c2721b26 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -86,8 +86,9 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { public boolean matchProduct(int want_product) { - if (!isAltusMetrum()) - return false; + System.out.printf("matchProduct %s %d\n", toString(), want_product); +// if (!isAltusMetrum()) +// return false; if (want_product == Altos.product_any) return true; @@ -100,4 +101,23 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { return false; } + + public boolean equals(Object o) { + if (!(o instanceof AltosBTDevice)) + return false; + AltosBTDevice other = (AltosBTDevice) o; + System.out.printf("AltosBTDevice equals %s == %s\n", toString(), other.toString()); + return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); + } + + public int hashCode() { + return getName().hashCode() ^ getAddr().hashCode(); + } + + public AltosBTDevice(String name, String addr) { + libaltos.altos_bt_fill_in(name, addr,this); + } + + public AltosBTDevice() { + } } \ No newline at end of file diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java index 63ce3674..7c360705 100644 --- a/altosui/AltosBTDeviceIterator.java +++ b/altosui/AltosBTDeviceIterator.java @@ -21,7 +21,6 @@ import java.util.*; import libaltosJNI.*; public class AltosBTDeviceIterator implements Iterator { - int product; AltosBTDevice current; boolean done; SWIGTYPE_p_altos_bt_list list; @@ -58,11 +57,9 @@ public class AltosBTDeviceIterator implements Iterator { throw new UnsupportedOperationException(); } - public AltosBTDeviceIterator(int in_product) { - product = in_product; + public AltosBTDeviceIterator(int inquiry_time) { done = false; current = null; - list = libaltos.altos_bt_list_start(); - System.out.printf("Iteration of BT list started\n"); + list = libaltos.altos_bt_list_start(inquiry_time); } } diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java new file mode 100644 index 00000000..95830637 --- /dev/null +++ b/altosui/AltosBTKnown.java @@ -0,0 +1,97 @@ +/* + * Copyright © 2011 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.util.*; +import libaltosJNI.*; +import java.util.prefs.*; + +public class AltosBTKnown implements Iterable { + LinkedList devices = new LinkedList(); + Preferences bt_pref = AltosPreferences.bt_devices(); + + private String get_address(String name) { + return bt_pref.get(name, ""); + } + + private void set_address(String name, String addr) { + bt_pref.put(name, addr); + System.out.printf("saving known %s %s\n", name, addr); + } + + private void remove(String name) { + bt_pref.remove(name); + } + + private void load() { + try { + String[] names = bt_pref.keys(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + String addr = get_address(name); + System.out.printf("Known device %s %s\n", name, addr); + devices.add(new AltosBTDevice(name, addr)); + } + } catch (BackingStoreException be) { + } catch (IllegalStateException ie) { + } + } + + public Iterator iterator() { + return devices.iterator(); + } + + private void flush() { + AltosPreferences.flush_preferences(); + } + + public void set(Iterable new_devices) { + for (AltosBTDevice old : devices) { + boolean found = false; + for (AltosBTDevice new_device : new_devices) { + if (new_device.equals(old)) { + found = true; + break; + } + } + if (!found) + remove(old.getName()); + } + devices = new LinkedList(); + for (AltosBTDevice new_device : new_devices) { + devices.add(new_device); + set_address(new_device.getName(), new_device.getAddr()); + } + flush(); + } + + public List list(int product) { + LinkedList list = new LinkedList(); + for (AltosBTDevice device : devices) { + if (device.matchProduct(product)) + list.add(device); + } + return list; + } + + public AltosBTKnown() { + devices = new LinkedList(); + bt_pref = AltosPreferences.bt_devices(); + load(); + } +} \ No newline at end of file diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 66e1210e..98a8b757 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -22,6 +22,8 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; +import javax.swing.event.*; +import javax.swing.plaf.basic.*; import java.io.*; import java.util.*; import java.text.*; @@ -30,17 +32,32 @@ import java.util.concurrent.*; import libaltosJNI.*; -public class AltosBTManage extends JDialog implements ActionListener { +public class AltosBTManage extends JDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; Frame frame; + LinkedList listeners; + AltosBTKnown bt_known; class DeviceList extends JList implements Iterable { LinkedList devices; DefaultListModel list_model; public void add (AltosBTDevice device) { - devices.add(device); - list_model.addElement(device); + if (!devices.contains(device)) { + devices.add(device); + list_model.addElement(device); + } + } + + public void remove (AltosBTDevice device) { + if (devices.contains(device)) { + devices.remove(device); + list_model.removeElement(device); + } + } + + public boolean contains(AltosBTDevice device) { + return devices.contains(device); } //Subclass JList to workaround bug 4832765, which can cause the @@ -75,6 +92,14 @@ public class AltosBTManage extends JDialog implements ActionListener { return devices.iterator(); } + public java.util.List selected_list() { + java.util.LinkedList l = new java.util.LinkedList(); + Object[] a = getSelectedValues(); + for (int i = 0; i < a.length; i++) + l.add((AltosBTDevice)a[i]); + return l; + } + public DeviceList() { devices = new LinkedList(); list_model = new DefaultListModel(); @@ -87,111 +112,233 @@ public class AltosBTManage extends JDialog implements ActionListener { DeviceList visible_devices; - DeviceList selected_devices; + DeviceList known_devices; + Thread bt_thread; + + public Iterator iterator() { + return known_devices.iterator(); + } + + public void commit() { + bt_known.set(this); + } + + public void add_known() { + for (AltosBTDevice device : visible_devices.selected_list()) { + System.out.printf("Add known %s\n", device.toString()); + known_devices.add(device); + visible_devices.remove(device); + } + } + + public void remove_known() { + for (AltosBTDevice device : known_devices.selected_list()) { + System.out.printf("Remove known %s\n", device.toString()); + known_devices.remove(device); + visible_devices.add(device); + } + } + + public void addActionListener(ActionListener l) { + listeners.add(l); + } + + private void forwardAction(ActionEvent e) { + for (ActionListener l : listeners) + l.actionPerformed(e); + } public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + System.out.printf("manage command %s\n", command); + if ("ok".equals(command)) { + bt_thread.interrupt(); + commit(); + setVisible(false); + forwardAction(e); + } else if ("cancel".equals(command)) { + bt_thread.interrupt(); + setVisible(false); + forwardAction(e); + } else if ("select".equals(command)) { + add_known(); + } else if ("deselect".equals(command)) { + remove_known(); + } } public void got_visible_device() { while (!found_devices.isEmpty()) { AltosBTDevice device = found_devices.remove(); - visible_devices.add(device); + if (!known_devices.contains(device)) + visible_devices.add(device); } } class BTGetVisibleDevices implements Runnable { public void run () { - - try { - AltosBTDeviceIterator i = new AltosBTDeviceIterator(Altos.product_any); - AltosBTDevice device; - - while ((device = i.next()) != null) { - Runnable r; - - found_devices.add(device); - r = new Runnable() { - public void run() { - got_visible_device(); - } - }; - SwingUtilities.invokeLater(r); + for (;;) + for (int time = 1; time <= 8; time <<= 1) { + AltosBTDeviceIterator i = new AltosBTDeviceIterator(time); + AltosBTDevice device; + + if (Thread.interrupted()) + return; + try { + while ((device = i.next()) != null) { + Runnable r; + + if (Thread.interrupted()) + return; + found_devices.add(device); + r = new Runnable() { + public void run() { + got_visible_device(); + } + }; + SwingUtilities.invokeLater(r); + } + } catch (Exception e) { + System.out.printf("uh-oh, exception %s\n", e.toString()); + } } - } catch (Exception e) { - System.out.printf("uh-oh, exception %s\n", e.toString()); - } } } - public static void show(Component frameComp) { + public static void show(Component frameComp, AltosBTKnown known) { Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosBTManage dialog; - dialog = new AltosBTManage(frame); + dialog = new AltosBTManage(frame, known); dialog.setVisible(true); } - public AltosBTManage(Frame in_frame) { + public AltosBTManage(Frame in_frame, AltosBTKnown in_known) { super(in_frame, "Manage Bluetooth Devices", true); frame = in_frame; - + bt_known = in_known; BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices(); + bt_thread = new Thread(get_visible_devices); + bt_thread.start(); - Thread t = new Thread(get_visible_devices); - t.start(); + listeners = new LinkedList(); found_devices = new LinkedBlockingQueue(); - JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(this); - - final JButton selectButton = new JButton("Select"); - selectButton.setActionCommand("select"); - selectButton.addActionListener(this); - getRootPane().setDefaultButton(selectButton); - - selected_devices = new DeviceList(); - JScrollPane selected_list_scroller = new JScrollPane(selected_devices); - selected_list_scroller.setPreferredSize(new Dimension(400, 80)); - selected_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(4,4,4,4); + + /* + * Known devices label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + pane.add(new JLabel("Known Devices"), c); + + known_devices = new DeviceList(); + for (AltosBTDevice device : bt_known) + known_devices.add(device); + + JScrollPane known_list_scroller = new JScrollPane(known_devices); + known_list_scroller.setPreferredSize(new Dimension(400, 80)); + known_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 2; + pane.add(known_list_scroller, c); + + /* + * Visible devices label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 2; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + pane.add(new JLabel("Visible Devices"), c); visible_devices = new DeviceList(); JScrollPane visible_list_scroller = new JScrollPane(visible_devices); visible_list_scroller.setPreferredSize(new Dimension(400, 80)); visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 2; + c.gridy = 1; + c.gridheight = 2; + c.gridwidth = 1; + pane.add(visible_list_scroller, c); + + /* + * Arrows between the two lists + */ + BasicArrowButton select_arrow = new BasicArrowButton(SwingConstants.WEST); + select_arrow.setActionCommand("select"); + select_arrow.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.SOUTH; + c.gridx = 1; + c.gridy = 1; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(select_arrow, c); + + BasicArrowButton deselect_arrow = new BasicArrowButton(SwingConstants.EAST); + deselect_arrow.setActionCommand("deselect"); + deselect_arrow.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTH; + c.gridx = 1; + c.gridy = 2; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(deselect_arrow, c); + + JButton cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 3; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(cancel_button, c); + + JButton ok_button = new JButton("OK"); + ok_button.setActionCommand("ok"); + ok_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 2; + c.gridy = 3; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(ok_button, c); + + getRootPane().setDefaultButton(ok_button); - //Create a container so that we can add a title around - //the scroll pane. Can't add a title directly to the - //scroll pane because its background would be white. - //Lay out the label and scroll pane from top to bottom. - JPanel listPane = new JPanel(); - listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); - - JLabel label = new JLabel("Select Device"); - label.setLabelFor(selected_devices); - listPane.add(label); - listPane.add(Box.createRigidArea(new Dimension(0,5))); - listPane.add(selected_list_scroller); - listPane.add(visible_list_scroller); - listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - - //Lay out the buttons from left to right. - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); - buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); - buttonPane.add(Box.createHorizontalGlue()); - buttonPane.add(cancelButton); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(selectButton); - - //Put everything together, using the content pane's BorderLayout. - Container contentPane = getContentPane(); - contentPane.add(listPane, BorderLayout.CENTER); - contentPane.add(buttonPane, BorderLayout.PAGE_END); - - //Initialize values. -// list.setSelectedValue(initial, true); pack(); + setLocationRelativeTo(frame); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + bt_thread.interrupt(); + setVisible(false); + } + }); } } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index a2755a06..0f5e4a3b 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -204,7 +204,7 @@ public class AltosConfigureUI manage_bluetooth = new JButton("Manage Bluetooth"); manage_bluetooth.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - new AltosBTManage(AltosBTDevice.bt_product_any, owner); + AltosBTManage.show(owner, Altos.bt_known); } }); c.gridx = 1; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index fa20f867..e17504e2 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -26,37 +26,46 @@ import libaltosJNI.*; public class AltosDeviceDialog extends JDialog implements ActionListener { - public static AltosDevice show (Component frameComp, int product) { - - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosDevice[] devices; - devices = AltosUSBDevice.list(product); - AltosDeviceDialog dialog; - - dialog = new AltosDeviceDialog(frame, frameComp, - devices); - dialog.setVisible(true); - return dialog.getValue(); - } - private AltosDevice value; private JList list; private JButton cancel_button; private JButton select_button; private JButton manage_bluetooth_button; private Frame frame; + private int product; private AltosDevice getValue() { return value; } - private AltosDeviceDialog (Frame in_frame, Component location, - AltosDevice[] devices) { + private AltosDevice[] devices() { + java.util.List usb_devices = AltosUSBDevice.list(product); + java.util.List bt_devices = Altos.bt_known.list(product); + AltosDevice[] devices = new AltosDevice[usb_devices.size() + bt_devices.size()]; + + for (int i = 0; i < usb_devices.size(); i++) + devices[i] = usb_devices.get(i); + int off = usb_devices.size(); + for (int j = 0; j < bt_devices.size(); j++) + devices[off + j] = bt_devices.get(j); + return devices; + } + + private void update_devices() { + AltosDevice[] devices = devices(); + list.setListData(devices); + select_button.setEnabled(devices.length > 0); + } + + private AltosDeviceDialog (Frame in_frame, Component location, int in_product) { super(in_frame, "Device Selection", true); + product = in_product; frame = in_frame; value = null; + AltosDevice[] devices = devices(); + cancel_button = new JButton("Cancel"); cancel_button.setActionCommand("cancel"); cancel_button.addActionListener(this); @@ -147,7 +156,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { contentPane.add(buttonPane, BorderLayout.PAGE_END); //Initialize values. - if (devices != null && devices.length > 0) + if (devices != null && devices.length != 0) list.setSelectedValue(devices[0], true); pack(); setLocationRelativeTo(location); @@ -158,10 +167,20 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame); + AltosBTManage.show(frame, Altos.bt_known); + update_devices(); return; } setVisible(false); } + public static AltosDevice show (Component frameComp, int product) { + + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosDeviceDialog dialog; + + dialog = new AltosDeviceDialog(frame, frameComp, product); + dialog.setVisible(true); + return dialog.getValue(); + } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 66dcdad5..eb6c6d9d 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -122,7 +122,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { JComboBox telemetries; public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { - AltosPreferences.init(this); + AltosPreferences.set_component(this); voice = in_voice; reader = in_reader; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 5f827655..b1192be1 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -79,11 +79,9 @@ class AltosPreferences { /* Serial debug */ static boolean serial_debug; - public static void init(Component ui) { + public static void init() { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); - component = ui; - /* Initialize logdir from preferences */ String logdir_string = preferences.get(logdirPreference, null); if (logdir_string != null) @@ -116,14 +114,23 @@ class AltosPreferences { AltosSerial.set_debug(serial_debug); } + static { init(); } + + static void set_component(Component in_component) { + component = in_component; + } + static void flush_preferences() { try { preferences.flush(); } catch (BackingStoreException ee) { - JOptionPane.showMessageDialog(component, - preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); + if (component != null) + JOptionPane.showMessageDialog(component, + preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + else + System.err.printf("Cannot save preferences\n"); } } @@ -262,4 +269,8 @@ class AltosPreferences { public static boolean serial_debug() { return serial_debug; } + + public static Preferences bt_devices() { + return preferences.node("bt_devices"); + } } diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index f4b6b7e0..7575c10e 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -164,8 +164,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } public static void prefetchMaps(double lat, double lng, int w, int h) { - AltosPreferences.init(null); - AltosSiteMap asm = new AltosSiteMap(true); asm.centre = asm.getBaseLocation(lat, lng); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 4b808c41..7955c1c2 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -99,7 +99,7 @@ public class AltosUI extends JFrame { if (imgURL != null) setIconImage(new ImageIcon(imgURL).getImage()); - AltosPreferences.init(this); + AltosPreferences.set_component(this); pane = getContentPane(); gridbag = new GridBagLayout(); @@ -397,9 +397,9 @@ public class AltosUI extends JFrame { AltosUI altosui = new AltosUI(); altosui.setVisible(true); - AltosDevice[] devices = AltosUSBDevice.list(Altos.product_basestation); - for (int i = 0; i < devices.length; i++) - altosui.telemetry_window(devices[i]); + java.util.List devices = AltosUSBDevice.list(Altos.product_basestation); + for (AltosDevice device : devices) + altosui.telemetry_window(device); } } } diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index deed0056..dc746a64 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -77,13 +77,13 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return false; } - static AltosUSBDevice[] list(int product) { + static java.util.List list(int product) { if (!Altos.load_library()) return null; SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - ArrayList device_list = new ArrayList(); + ArrayList device_list = new ArrayList(); if (list != null) { for (;;) { AltosUSBDevice device = new AltosUSBDevice(); @@ -95,9 +95,6 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { libaltos.altos_list_finish(list); } - AltosUSBDevice[] devices = new AltosUSBDevice[device_list.size()]; - for (int i = 0; i < device_list.size(); i++) - devices[i] = device_list.get(i); - return devices; + return device_list; } } \ No newline at end of file diff --git a/altosui/Makefile.am b/altosui/Makefile.am index f2de4a3a..f4d84ad2 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -30,6 +30,7 @@ altosui_JAVA = \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ + AltosBTKnown.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c index 79561643..88e40d73 100644 --- a/altosui/libaltos/cjnitest.c +++ b/altosui/libaltos/cjnitest.c @@ -41,7 +41,7 @@ main () altos_close(file); } altos_list_finish(list); - bt_list = altos_bt_list_start(); + bt_list = altos_bt_list_start(8); while (altos_bt_list_next(bt_list, &bt_device)) { printf ("%s %s\n", bt_device.name, bt_device.addr); if (strncmp(bt_device.name, "TeleBT", 6) == 0) { diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 13635a0d..2c47f3e5 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -591,10 +591,9 @@ struct altos_bt_list { }; #define INQUIRY_MAX_RSP 255 -#define INQUIRY_LEN 8 struct altos_bt_list * -altos_bt_list_start(void) +altos_bt_list_start(int inquiry_time) { struct altos_bt_list *bt_list; @@ -614,7 +613,7 @@ altos_bt_list_start(void) goto no_sock; bt_list->num_rsp = hci_inquiry(bt_list->dev_id, - INQUIRY_LEN, + inquiry_time, INQUIRY_MAX_RSP, NULL, &bt_list->ii, @@ -665,6 +664,15 @@ 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) { @@ -768,7 +776,7 @@ get_number(io_object_t object, CFStringRef entry, int *result) } struct altos_list * -altos_list_start(void) +altos_list_start(int time) { struct altos_list *list = calloc (sizeof (struct altos_list), 1); CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 9c3f9655..f710919c 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -110,7 +110,7 @@ PUBLIC int altos_getchar(struct altos_file *file, int timeout); PUBLIC struct altos_bt_list * -altos_bt_list_start(void); +altos_bt_list_start(int inquiry_time); PUBLIC int altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); @@ -118,6 +118,9 @@ altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); PUBLIC void altos_bt_list_finish(struct altos_bt_list *list); +PUBLIC void +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); -- cgit v1.2.3 From 6b5957d5f6f8181da7be98c9bce49a0ec0b4a713 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 10:41:28 -0700 Subject: altosui: Wait two seconds after bluetooth connect XXX "something" isn't quite ready to communicate right after the device is connected, so we stick a delay in. There should be a better fix. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 1 + 1 file changed, 1 insertion(+) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 2c47f3e5..c5bcf900 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -698,6 +698,7 @@ altos_bt_open(struct altos_bt_device *device) perror("connect"); goto no_link; } + sleep(2); #ifdef USE_POLL pipe(file->pipe); -- cgit v1.2.3 From d41edb3384b6336f3482e61b0c9f9400a8b4f519 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 15:29:39 -0700 Subject: altosui: Make flight data download work through TeleBT This required flushing input before reading data blocks and adjusting some delays. Signed-off-by: Keith Packard --- altosui/AltosEepromChunk.java | 1 + altosui/AltosEepromList.java | 2 +- altosui/AltosEepromLog.java | 7 ++++--- altosui/libaltos/libaltos.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java index 8eec407d..1e42077f 100644 --- a/altosui/AltosEepromChunk.java +++ b/altosui/AltosEepromChunk.java @@ -59,6 +59,7 @@ public class AltosEepromChunk { data = new int[chunk_size]; address = block * chunk_size; + serial_line.flush_input(); serial_line.printf("e %x\n", block); for (offset = 0; offset < chunk_size; offset += per_line) { diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index 575c0bc2..185fec91 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -114,7 +114,7 @@ public class AltosEepromList extends ArrayList { */ for (AltosEepromFlight flight : flights) { add(new AltosEepromLog(serial_line, config_data.serial, - flight.start, flight.end)); + flight.flight, flight.start, flight.end)); } } finally { if (remote) diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index f7fb39e1..0cf420d9 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -47,7 +47,8 @@ public class AltosEepromLog { boolean delete; public AltosEepromLog(AltosSerial serial_line, int in_serial, - int in_start_block, int in_end_block) + int in_flight, int in_start_block, + int in_end_block) throws InterruptedException, TimeoutException { int block; @@ -73,8 +74,8 @@ public class AltosEepromLog { AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); if (block == in_start_block) { - if (eechunk.data(0) != Altos.AO_LOG_FLIGHT) { - flight = eechunk.data16(0); + if (eechunk.data16(0) == in_flight) { + flight = in_flight; has_flight = true; break; } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index c5bcf900..5e507cdf 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -698,7 +698,7 @@ altos_bt_open(struct altos_bt_device *device) perror("connect"); goto no_link; } - sleep(2); + sleep(1); #ifdef USE_POLL pipe(file->pipe); -- cgit v1.2.3 From a315b200cd0da1a964f5395cd59660be1b49672b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 12:31:48 -0700 Subject: altosui: Pull out BlueTooth support This leaves the code in place, but commented out so that it isn't used until we've got a bluetooth device ready for use. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- altosui/AltosConfigureUI.java | 32 ++++++++++++++++++-------------- altosui/AltosDeviceDialog.java | 38 +++++++++++++++++++++++--------------- altosui/Makefile.am | 10 ++++++---- altosui/libaltos/cjnitest.c | 2 ++ altosui/libaltos/libaltos.c | 2 ++ altosui/libaltos/libaltos.h | 6 ++++++ 7 files changed, 58 insertions(+), 34 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/Altos.java b/altosui/Altos.java index 1acce949..b257ad7b 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -408,5 +408,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/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index a8a70ffd..abb54c74 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -49,7 +49,8 @@ public class AltosConfigureUI JRadioButton serial_debug; - JButton manage_bluetooth; +// BLUETOOTH +// JButton manage_bluetooth; JButton manage_frequencies; /* DocumentListener interface methods */ @@ -202,18 +203,19 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(serial_debug, 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 = 6; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(manage_bluetooth, 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 = 6; +// 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() { @@ -221,7 +223,9 @@ public class AltosConfigureUI AltosConfigFreqUI.show(owner); } }); - c.gridx = 2; +// BLUETOOTH +// c.gridx = 2; + c.gridx = 1; c.gridy = 6; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index e17504e2..fa9587bc 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -30,7 +30,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private JList list; private JButton cancel_button; private JButton select_button; - private JButton manage_bluetooth_button; +// BLUETOOTH +// private JButton manage_bluetooth_button; private Frame frame; private int product; @@ -40,14 +41,18 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private AltosDevice[] devices() { java.util.List usb_devices = AltosUSBDevice.list(product); - java.util.List bt_devices = Altos.bt_known.list(product); - AltosDevice[] devices = new AltosDevice[usb_devices.size() + bt_devices.size()]; + int num_devices = usb_devices.size(); +// BLUETOOTH +// java.util.List 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); - int off = usb_devices.size(); - for (int j = 0; j < bt_devices.size(); j++) - devices[off + j] = bt_devices.get(j); +// BLUETOOTH +// int off = usb_devices.size(); +// for (int j = 0; j < bt_devices.size(); j++) +// devices[off + j] = bt_devices.get(j); return devices; } @@ -70,9 +75,10 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { cancel_button.setActionCommand("cancel"); cancel_button.addActionListener(this); - manage_bluetooth_button = new JButton("Manage Bluetooth"); - manage_bluetooth_button.setActionCommand("manage"); - manage_bluetooth_button.addActionListener(this); +// BLUETOOTH +// 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"); @@ -146,7 +152,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(manage_bluetooth_button); +// BLUETOOTH +// buttonPane.add(manage_bluetooth_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(select_button); @@ -166,11 +173,12 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { public void actionPerformed(ActionEvent e) { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); - if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame, Altos.bt_known); - update_devices(); - return; - } +// BLUETOOTH +// if ("manage".equals(e.getActionCommand())) { +// AltosBTManage.show(frame, Altos.bt_known); +// update_devices(); +// return; +// } setVisible(false); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 4bac6df1..713a02f4 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -10,6 +10,12 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:libaltos:$(FREETTS)/*:/ bin_SCRIPTS=altosui +altosui_BT = \ + AltosBTDevice.java \ + AltosBTDeviceIterator.java \ + AltosBTManage.java \ + AltosBTKnown.java + altosui_JAVA = \ GrabNDrag.java \ AltosAscent.java \ @@ -28,10 +34,6 @@ altosui_JAVA = \ AltosDeviceDialog.java \ AltosDevice.java \ AltosUSBDevice.java \ - AltosBTDevice.java \ - AltosBTDeviceIterator.java \ - AltosBTManage.java \ - AltosBTKnown.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c index 88e40d73..f0fe78f7 100644 --- a/altosui/libaltos/cjnitest.c +++ b/altosui/libaltos/cjnitest.c @@ -41,6 +41,7 @@ main () altos_close(file); } altos_list_finish(list); +#if HAS_BLUETOOTH bt_list = altos_bt_list_start(8); while (altos_bt_list_next(bt_list, &bt_device)) { printf ("%s %s\n", bt_device.name, bt_device.addr); @@ -64,6 +65,7 @@ main () } } altos_bt_list_finish(bt_list); +#endif altos_fini(); return 0; } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 5e507cdf..b00a7704 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -582,6 +582,7 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } +#if HAS_BLUETOOTH struct altos_bt_list { inquiry_info *ii; int sock; @@ -713,6 +714,7 @@ no_sock: no_file: return NULL; } +#endif /* HAS_BLUETOOTH */ #endif diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index f710919c..dd091e51 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -34,6 +34,8 @@ # define PUBLIC #endif +#define HAS_BLUETOOTH 0 + #define USB_VENDOR_FSF 0xfffe #define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF #define USB_PRODUCT_ALTUSMETRUM 0x000a @@ -109,6 +111,8 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); +#if HAS_BLUETOOTH + PUBLIC struct altos_bt_list * altos_bt_list_start(int inquiry_time); @@ -124,4 +128,6 @@ 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_ */ -- cgit v1.2.3 From 12bfa6cc42e3689f09abae2bd2584cbacf2aa2e0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Aug 2011 18:26:07 -0700 Subject: altosui: Don't export product defs from libaltos As we add new products, that would change the ABI generated for java, invaliding old library versions sitting around for windows and mac. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 16 ++++++++++++++++ altosui/libaltos/libaltos.h | 19 +------------------ 2 files changed, 17 insertions(+), 18 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index b00a7704..00a75de9 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -20,6 +20,22 @@ #include #include +#define USB_VENDOR_FSF 0xfffe +#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF +#define USB_PRODUCT_ALTUSMETRUM 0x000a +#define USB_PRODUCT_TELEMETRUM 0x000b +#define USB_PRODUCT_TELEDONGLE 0x000c +#define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_TELEBT 0x000e +#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 + +#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ + (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ + (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) + +#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" + #define USE_POLL PUBLIC int diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index dd091e51..363a84fd 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -34,22 +34,6 @@ # define PUBLIC #endif -#define HAS_BLUETOOTH 0 - -#define USB_VENDOR_FSF 0xfffe -#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF -#define USB_PRODUCT_ALTUSMETRUM 0x000a -#define USB_PRODUCT_TELEMETRUM 0x000b -#define USB_PRODUCT_TELEDONGLE 0x000c -#define USB_PRODUCT_TELETERRA 0x000d -#define USB_PRODUCT_TELEBT 0x000e -#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 - -#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ - (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ - (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) - struct altos_device { //%immutable; int vendor; @@ -60,8 +44,6 @@ struct altos_device { //%mutable; }; -#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" - struct altos_bt_device { //%immutable; char name[256]; @@ -111,6 +93,7 @@ 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 * -- cgit v1.2.3 From 313d740b5284b24f1cc7a1ba5779136b55d49ebe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:33:07 -0700 Subject: libaltos: Mis-allocated device list in libaltos Would overrun mis-allocated array, causing chaos. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 00a75de9..f2c8bd8d 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -559,7 +559,7 @@ altos_list_start(void) if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { if (devs->dev) devs->dev = realloc(devs->dev, - devs->ndev + 1 * sizeof (struct usbdev *)); + (devs->ndev + 1) * sizeof (struct usbdev *)); else devs->dev = malloc (sizeof (struct usbdev *)); devs->dev[devs->ndev++] = dev; -- cgit v1.2.3 From d5bd40847b17c32405dfba864a2a5a3b19aa7e85 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Aug 2011 22:12:53 -0700 Subject: altosui/windows: Fix a bunch of windows compiler warnings. Some of these may have actually been serious -- a write length was getting stored in a signed char... Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index f2c8bd8d..21e94ca0 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -882,7 +882,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 %d\n", GetLastError()); + printf("SetupDiGetClassDevs failed %ld\n", GetLastError()); free(list); return NULL; } @@ -894,13 +894,13 @@ PUBLIC int altos_list_next(struct altos_list *list, struct altos_device *device) { SP_DEVINFO_DATA dev_info_data; - char port[128]; + BYTE port[128]; DWORD port_len; char friendlyname[256]; - char symbolic[256]; + BYTE symbolic[256]; DWORD symbolic_len; HKEY dev_key; - int vid, pid; + unsigned int vid, pid; int serial; HRESULT result; DWORD friendlyname_type; @@ -931,11 +931,11 @@ altos_list_next(struct altos_list *list, struct altos_device *device) continue; } vid = pid = serial = 0; - sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1, + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, "%04X", &vid); - sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, "%04X", &pid); - sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, "%d", &serial); if (!USB_IS_ALTUSMETRUM(vid, pid)) { RegCloseKey(dev_key); @@ -971,12 +971,12 @@ altos_list_next(struct altos_list *list, struct altos_device *device) device->serial = serial; strcpy(device->name, friendlyname); - strcpy(device->path, port); + strcpy(device->path, (char *) port); return 1; } result = GetLastError(); if (result != ERROR_NO_MORE_ITEMS) - printf ("SetupDiEnumDeviceInfo failed error %d\n", result); + printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); return 0; } @@ -1059,10 +1059,10 @@ altos_fill(struct altos_file *file, int timeout) PUBLIC int altos_flush(struct altos_file *file) { - DWORD put; - char *data = file->out_data; - char used = file->out_used; - DWORD ret; + DWORD put; + unsigned char *data = file->out_data; + int used = file->out_used; + DWORD ret; while (used) { if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { @@ -1150,7 +1150,7 @@ altos_free(struct altos_file *file) free(file); } -int +PUBLIC int altos_putchar(struct altos_file *file, char c) { int ret; @@ -1166,7 +1166,7 @@ altos_putchar(struct altos_file *file, char c) return LIBALTOS_SUCCESS; } -int +PUBLIC int altos_getchar(struct altos_file *file, int timeout) { int ret; -- cgit v1.2.3 From 393d231b9689cd1c358600ee76e0e808f89670c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Aug 2011 22:52:45 -0700 Subject: altosui: Attempt to make both 32- and 64-bit windows DLLs We'll see if they work... Signed-off-by: Keith Packard --- altosui/Altos.java | 8 +++++++- altosui/Makefile.am | 18 ++++++++++++++++-- altosui/libaltos/Makefile.am | 15 ++++++++++++++- altosui/libaltos/altos.dll | Bin 31765 -> 91605 bytes 4 files changed, 37 insertions(+), 4 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/Altos.java b/altosui/Altos.java index d3f8fa67..ddf1005a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -366,7 +366,13 @@ public class Altos { libaltos.altos_init(); loaded_library = true; } catch (UnsatisfiedLinkError e) { - loaded_library = false; + try { + System.loadLibrary("altos64"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e2) { + loaded_library = false; + } } initialized = true; } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index e4986ba5..f626d3fa 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -191,7 +191,7 @@ LINUX_EXTRA=altosui-fat MACOSX_FILES=$(FAT_FILES) libaltos.dylib MACOSX_EXTRA=$(FIRMWARE) -WINDOWS_FILES=$(FAT_FILES) altos.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) +WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb @@ -282,10 +282,24 @@ libaltos.dylib: -rm -f "$@" $(LN_S) libaltos/"$@" . -altos.dll: +altos.dll: libaltos/altos.dll -rm -f "$@" $(LN_S) libaltos/"$@" . +altos64.dll: libaltos/altos64.dll + -rm -f "$@" + $(LN_S) libaltos/"$@" . + +libaltos/altos.dll: build-altos-dll + +libaltos/altos64.dll: build-altos64-dll + +build-altos-dll: + +cd libaltos && make altos.dll + +build-altos64-dll: + +cd libaltos && make altos64.dll + $(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am index 3f5f3ee2..b5ab1ddb 100644 --- a/altosui/libaltos/Makefile.am +++ b/altosui/libaltos/Makefile.am @@ -37,5 +37,18 @@ classlibaltos.stamp: $(SWIG_FILE) $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \ touch classlibaltos.stamp +MINGCC32=i686-w64-mingw32-gcc +MINGCC64=x86_64-w64-mingw32-gcc +MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE) +MINGLIBS=-lsetupapi + +fat: altos.dll altos64.dll + +altos.dll: $(libaltos_la_SOURCES) + $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) + +altos64.dll: $(libaltos_la_SOURCES) + $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) + clean-local: - -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c + -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll index 28e9b4ad..a96d3129 100755 Binary files a/altosui/libaltos/altos.dll and b/altosui/libaltos/altos.dll differ -- cgit v1.2.3 From afe6aba9cb91e93234ffee2a22eee40f848ddedd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 18:25:34 -0700 Subject: altosui: Add --summary option to dump flight stats to stdout useful for quickly capturing sense of a flight. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 80 ++++++++++++++++++++++++++++++++++++--------- altosui/libaltos/altos.dll | Bin 91605 -> 0 bytes 2 files changed, 64 insertions(+), 16 deletions(-) delete mode 100755 altosui/libaltos/altos.dll (limited to 'altosui/libaltos') diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 0317f569..13cda637 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -369,6 +369,7 @@ public class AltosUI extends JFrame { static final int process_kml = 2; static final int process_graph = 3; static final int process_replay = 4; + static final int process_summary = 5; static void process_csv(String input) { AltosRecordIterable iterable = open_logfile(input); @@ -406,13 +407,13 @@ public class AltosUI extends JFrame { } } - static void process_replay(String filename) { + static AltosRecordIterable record_iterable_file(String filename) { FileInputStream in; try { in = new FileInputStream(filename); } catch (Exception e) { System.out.printf("Failed to open file '%s'\n", filename); - return; + return null; } AltosRecordIterable recs; AltosReplayReader reader; @@ -421,32 +422,74 @@ public class AltosUI extends JFrame { } else { recs = new AltosTelemetryIterable(in); } - reader = new AltosReplayReader(recs.iterator(), new File(filename)); + return recs; + } + + static AltosReplayReader replay_file(String filename) { + AltosRecordIterable recs = record_iterable_file(filename); + if (recs == null) + return null; + return new AltosReplayReader(recs.iterator(), new File(filename)); + } + + static void process_replay(String filename) { + AltosReplayReader reader = replay_file(filename); AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); flight_ui.set_exit_on_close(); } static void process_graph(String filename) { - FileInputStream in; - try { - in = new FileInputStream(filename); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", filename); + AltosRecordIterable recs = record_iterable_file(filename); + if (recs == null) return; - } - AltosRecordIterable recs; - if (filename.endsWith("eeprom")) { - recs = new AltosEepromIterable(in); - } else { - recs = new AltosTelemetryIterable(in); - } try { - new AltosGraphUI(recs); + new AltosGraphUI(recs, filename); } catch (InterruptedException ie) { } catch (IOException ie) { } } + static void process_summary(String filename) { + AltosReplayReader reader = replay_file(filename); + try { + AltosFlightStats stats = new AltosFlightStats(reader); + if (stats.serial > 0) + System.out.printf("Serial: %5d\n", stats.serial); + if (stats.flight > 0) + System.out.printf("Flight: %5d\n", stats.flight); + if (stats.year > 0) + System.out.printf("Date: %04d-%02d-%02d\n", + stats.year, stats.month, stats.day); + if (stats.hour > 0) + System.out.printf("Time: %02d:%02d:%02d UTC\n", + stats.hour, stats.minute, stats.second); + System.out.printf("Max height: %6.0f m %6.0f ft\n", + stats.max_height, + AltosConvert.meters_to_feet(stats.max_height)); + System.out.printf("Max speed: %6.0f m/s %6.0f ft/s %6.4f Mach\n", + stats.max_speed, + AltosConvert.meters_to_feet(stats.max_speed), + AltosConvert.meters_to_mach(stats.max_speed)); + if (stats.max_acceleration != AltosRecord.MISSING) { + System.out.printf("Max accel: %6.0f m/s² %6.0f ft/s² %6.2f g\n", + stats.max_acceleration, + AltosConvert.meters_to_feet(stats.max_acceleration), + AltosConvert.meters_to_g(stats.max_acceleration)); + } + System.out.printf("Drogue rate: %6.0f m/s %6.0f ft/s\n", + stats.state_baro_speed[Altos.ao_flight_drogue], + AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_drogue])); + System.out.printf("Main rate: %6.0f m/s %6.0f ft/s\n", + stats.state_baro_speed[Altos.ao_flight_main], + AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_main])); + System.out.printf("Flight time: %6.0f s\n", + stats.state_end[Altos.ao_flight_main] - + stats.state_start[Altos.ao_flight_boost]); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + } + public static void help(int code) { System.out.printf("Usage: altosui [OPTION]... [FILE]...\n"); System.out.printf(" Options:\n"); @@ -489,6 +532,8 @@ public class AltosUI extends JFrame { process = process_csv; else if (args[i].equals("--graph")) process = process_graph; + else if (args[i].equals("--summary")) + process = process_summary; else if (args[i].startsWith("--")) help(1); else { @@ -506,6 +551,9 @@ public class AltosUI extends JFrame { case process_csv: process_csv(args[i]); break; + case process_summary: + process_summary(args[i]); + break; } } } diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll deleted file mode 100755 index a96d3129..00000000 Binary files a/altosui/libaltos/altos.dll and /dev/null differ -- cgit v1.2.3 From fa6df3fa21e8f09e70371e6c6cc7827a533b4fe6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:35:28 -0700 Subject: altosui: Update mac os X library This has been tested on 32-bit OS X and it works; dunno about 64-bit. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.dylib | Bin 54176 -> 41648 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.dylib b/altosui/libaltos/libaltos.dylib index 89aa12e7..1038817d 100755 Binary files a/altosui/libaltos/libaltos.dylib and b/altosui/libaltos/libaltos.dylib differ -- cgit v1.2.3 From 754b9591574c12ddd6e4ab590c6a5f3806b80213 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Aug 2011 13:29:23 -0700 Subject: libaltos: fix Mac OS X function signatures altos_list_start was declared to take a (int time) parameter for some reason. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 21e94ca0..d1f445bd 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -794,8 +794,8 @@ get_number(io_object_t object, CFStringRef entry, int *result) return 0; } -struct altos_list * -altos_list_start(int time) +PUBLIC struct altos_list * +altos_list_start(void) { struct altos_list *list = calloc (sizeof (struct altos_list), 1); CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); @@ -810,7 +810,7 @@ altos_list_start(int time) return list; } -int +PUBLIC int altos_list_next(struct altos_list *list, struct altos_device *device) { io_object_t object; @@ -837,7 +837,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) } } -void +PUBLIC void altos_list_finish(struct altos_list *list) { IOObjectRelease (list->iterator); -- cgit v1.2.3 From cf72c2f5a69a736c28a9b63e124d510ef41a9f5d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:50:01 -0700 Subject: altosui: Add bluetooth bits back in Stub out functions on mac/windows for now. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- altosui/AltosConfigureUI.java | 33 ++++++++---------- altosui/AltosDeviceDialog.java | 36 ++++++++----------- altosui/Makefile.am | 3 +- altosui/libaltos/libaltos.c | 78 ++++++++++++++++++++++++++++++++++++++++-- altosui/libaltos/libaltos.h | 5 --- 6 files changed, 109 insertions(+), 48 deletions(-) (limited to 'altosui/libaltos') 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/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/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 usb_devices = AltosUSBDevice.list(product); int num_devices = usb_devices.size(); -// BLUETOOTH -// java.util.List bt_devices = Altos.bt_known.list(product); -// num_devices += bt_devices.size(); + java.util.List 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/Makefile.am b/altosui/Makefile.am index e2e42d84..c4d1e611 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -118,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..a3796ee3 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -598,7 +598,6 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } -#if HAS_BLUETOOTH struct altos_bt_list { inquiry_info *ii; int sock; @@ -730,7 +729,6 @@ no_sock: no_file: return NULL; } -#endif /* HAS_BLUETOOTH */ #endif @@ -844,6 +842,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 @@ -1180,4 +1220,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..a05bed4c 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -93,9 +93,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 +108,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_ */ -- cgit v1.2.3 From 31e3255b6cbfaf95c0e97e2d1ec8de72f845994c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:50:30 -0700 Subject: altosui: Report error message back from libaltos This includes changing all of the error dialogs to show the error message rather than just the file name. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 7 +++ altosui/AltosCSVUI.java | 2 +- altosui/AltosConfig.java | 3 +- altosui/AltosDataChooser.java | 2 +- altosui/AltosDevice.java | 1 + altosui/AltosEepromDownload.java | 12 +++-- altosui/AltosEepromManage.java | 3 +- altosui/AltosFlashUI.java | 4 +- altosui/AltosIgniteUI.java | 3 +- altosui/AltosLanded.java | 4 +- altosui/AltosLaunchUI.java | 3 +- altosui/AltosScanUI.java | 6 +-- altosui/AltosSerial.java | 4 +- altosui/AltosUI.java | 9 ++-- altosui/AltosUSBDevice.java | 7 +++ altosui/libaltos/libaltos.c | 97 +++++++++++++++++++++++++++++++++------- altosui/libaltos/libaltos.h | 8 ++++ 17 files changed, 131 insertions(+), 44 deletions(-) (limited to 'altosui/libaltos') 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/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/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/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 4e630afb..47365e03 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -164,8 +164,7 @@ public class AltosLaunchUI void launch_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/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 60adfc7c..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) { @@ -356,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; } } @@ -366,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; } } @@ -376,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/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index a3796ee3..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; @@ -700,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; @@ -711,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); @@ -912,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) { @@ -922,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; } @@ -956,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; } @@ -966,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; @@ -988,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; } @@ -1003,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; } @@ -1015,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; } @@ -1035,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; @@ -1061,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; @@ -1106,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; } } @@ -1142,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; } @@ -1157,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; @@ -1166,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; diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index a05bed4c..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); -- cgit v1.2.3 From f11f05c5d634de2a80c34d0d3dc93925980f52e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 22:20:50 -0700 Subject: altosui: Make libaltos recognise new USB ids libaltos has a small range of 'AltusMetrum' products to avoid opening other devices. We've got more IDs, so open up the range. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'altosui/libaltos') diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 48e00a44..1cc27cbe 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -23,12 +23,8 @@ #define USB_VENDOR_FSF 0xfffe #define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF #define USB_PRODUCT_ALTUSMETRUM 0x000a -#define USB_PRODUCT_TELEMETRUM 0x000b -#define USB_PRODUCT_TELEDONGLE 0x000c -#define USB_PRODUCT_TELETERRA 0x000d -#define USB_PRODUCT_TELEBT 0x000e #define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x00ff #define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ -- cgit v1.2.3 From 0bf21399d3d47d58410df4c6ce89fc20fcd42c89 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:34:00 -0700 Subject: altosui: Handle Monitor Idle errors better Deal with missing data by checking for MISSING in more places. Handle serial communication failures during send by reporting back from libaltos. Signed-off-by: Keith Packard --- altoslib/AltosIdleMonitor.java | 67 +++++++++++++++++------------------------- altoslib/AltosLink.java | 20 +++++++++++-- altoslib/AltosRecord.java | 2 +- altoslib/AltosRecordTM.java | 16 +++++----- altoslib/AltosState.java | 2 ++ altosui/AltosSerial.java | 14 +++++++-- altosui/libaltos/libaltos.c | 4 +-- 7 files changed, 70 insertions(+), 55 deletions(-) (limited to 'altosui/libaltos') diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index 57c4da71..27ea3a2b 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -23,16 +23,10 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; -class AltosSensorTM { - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; +class AltosSensorTM extends AltosRecordTM { - public AltosSensorTM(AltosLink link) throws InterruptedException, TimeoutException { + public AltosSensorTM(AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { + super(); link.printf("a\n"); for (;;) { String line = link.get_reply_no_dialog(5000); @@ -82,6 +76,10 @@ class AltosSensorTM { } break; } + ground_accel = config_data.accel_cal_plus; + ground_pres = pres; + accel_plus_g = config_data.accel_cal_plus; + accel_minus_g = config_data.accel_cal_minus; } } @@ -253,7 +251,7 @@ class AltosGPSQuery extends AltosGPS { if (line.startsWith("Date:")) { if (bits.length < 2) continue; - String[] d = bits[1].split(":"); + String[] d = bits[1].split("/"); if (d.length < 3) continue; year = Integer.parseInt(d[0]) + 2000; @@ -264,7 +262,7 @@ class AltosGPSQuery extends AltosGPS { if (line.startsWith("Time:")) { if (bits.length < 2) continue; - String[] d = bits[1].split("/"); + String[] d = bits[1].split(":"); if (d.length < 3) continue; hour = Integer.parseInt(d[0]); @@ -339,8 +337,7 @@ public class AltosIdleMonitor extends Thread { } void update_state() throws InterruptedException, TimeoutException { - AltosRecord record; - int rssi; + AltosRecord record = null; try { if (remote) { @@ -350,20 +347,7 @@ public class AltosIdleMonitor extends Thread { link.flush_input(); config_data = new AltosConfigData(link); if (config_data.product.startsWith("TeleMetrum")) { - AltosRecordTM record_tm = new AltosRecordTM(); - AltosSensorTM sensor = new AltosSensorTM(link); - record_tm.accel = sensor.accel; - record_tm.pres = sensor.pres; - record_tm.batt = sensor.batt; - record_tm.temp = sensor.temp; - record_tm.drogue = sensor.drogue; - record_tm.main = sensor.main; - record_tm.ground_accel = record_tm.accel; - record_tm.ground_pres = record_tm.pres; - record_tm.accel_plus_g = config_data.accel_cal_plus; - record_tm.accel_minus_g = config_data.accel_cal_minus; - record_tm.tick = sensor.tick; - record = record_tm; + record = new AltosSensorTM(link, config_data); } else if (config_data.product.startsWith("MegaMetrum")) { AltosRecordMM record_mm = new AltosRecordMM(); AltosSensorMM sensor = new AltosSensorMM(link); @@ -390,24 +374,27 @@ public class AltosIdleMonitor extends Thread { record = new AltosRecord(); gps = new AltosGPSQuery(link, config_data); + + record.version = 0; + record.callsign = config_data.callsign; + record.serial = config_data.serial; + record.flight = config_data.log_available() > 0 ? 255 : 0; + record.status = 0; + record.state = AltosLib.ao_flight_idle; + record.gps = gps; + record.new_gps = true; + state = new AltosState (record, state); } finally { if (remote) { link.stop_remote(); - rssi = AltosRSSI(); - } else - rssi = 0; + if (record != null) + record.rssi = AltosRSSI(); + } else { + if (record != null) + record.rssi = 0; + } } - record.version = 0; - record.callsign = config_data.callsign; - record.serial = config_data.serial; - record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = rssi; - record.status = 0; - record.state = AltosLib.ao_flight_idle; - - record.gps = gps; - state = new AltosState (record, state); } public void set_frequency(double in_frequency) { diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index d59e73ba..fd5db7e9 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -101,15 +101,23 @@ public abstract class AltosLink { try { for (;;) { c = getchar(); - if (Thread.interrupted()) + if (Thread.interrupted()) { + if (debug) + System.out.printf("INTERRUPTED\n"); break; + } if (c == ERROR) { + if (debug) + System.out.printf("ERROR\n"); add_telem (new AltosLine()); add_reply (new AltosLine()); break; } - if (c == TIMEOUT) + if (c == TIMEOUT) { + if (debug) + System.out.printf("TIMEOUT\n"); continue; + } if (c == '\r') continue; synchronized(this) { @@ -180,6 +188,14 @@ public abstract class AltosLink { reply_queue.put (line); } + public void abort_reply() { + try { + add_telem (new AltosLine()); + add_reply (new AltosLine()); + } catch (InterruptedException e) { + } + } + public void add_string(String line) throws InterruptedException { if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { add_telem(new AltosLine(line)); diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index e468f84b..8722bc05 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -127,7 +127,7 @@ public class AltosRecord implements Comparable , Cloneable { double p = filtered_pressure(); if (p == MISSING) - return MISSING; + return raw_altitude(); return AltosConvert.pressure_to_altitude(p); } diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java index afb70790..37accef6 100644 --- a/altoslib/AltosRecordTM.java +++ b/altoslib/AltosRecordTM.java @@ -177,14 +177,14 @@ public class AltosRecordTM extends AltosRecord { drogue = MISSING; main = MISSING; - flight_accel = 0; - flight_vel = 0; - flight_pres = 0; - - ground_accel = 0; - ground_pres = 0; - accel_plus_g = 0; - accel_minus_g = 0; + flight_accel = MISSING; + flight_vel = MISSING; + flight_pres = MISSING; + + ground_accel = MISSING; + ground_pres = MISSING; + accel_plus_g = MISSING; + accel_minus_g = MISSING; } public AltosRecordTM(AltosRecord old) { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index e20ec9a7..3b37a3d4 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -38,6 +38,7 @@ public class AltosState { public boolean boost; /* under power */ public double ground_altitude; + public double altitude; public double height; public double speed; public double acceleration; @@ -82,6 +83,7 @@ public class AltosState { data = cur; ground_altitude = data.ground_altitude(); + altitude = data.raw_altitude(); height = data.filtered_height(); report_time = System.currentTimeMillis(); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index c4e9c697..8b692fa9 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -54,13 +54,19 @@ public class AltosSerial extends AltosLink implements Runnable { Frame frame; public int getchar() { + if (altos == null) + return ERROR; return libaltos.altos_getchar(altos, 0); } public void flush_output() { super.flush_output(); if (altos != null) { - libaltos.altos_flush(altos); + if (libaltos.altos_flush(altos) != 0) { + libaltos.altos_close(altos); + altos = null; + abort_reply(); + } } } @@ -155,7 +161,11 @@ public class AltosSerial extends AltosLink implements Runnable { private void putc(char c) { if (altos != null) - libaltos.altos_putchar(altos, c); + if (libaltos.altos_putchar(altos, c) != 0) { + libaltos.altos_close(altos); + altos = null; + abort_reply(); + } } public void print(String data) { diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 1cc27cbe..515432f9 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -221,7 +221,7 @@ altos_flush(struct altos_file *file) #endif if (ret < 0) { altos_set_last_posix_error(); - return -errno; + return -last_error.code; } if (ret) { memmove(file->out_data, file->out_data + ret, @@ -247,7 +247,7 @@ altos_putchar(struct altos_file *file, char c) ret = 0; if (file->out_used == USB_BUF_SIZE) ret = altos_flush(file); - return 0; + return ret; } #ifdef USE_POLL -- cgit v1.2.3