From: Keith Packard Date: Tue, 27 Jul 2010 01:04:10 +0000 (-0700) Subject: Re-enable Linux support for altosui. X-Git-Tag: debian/0.6+268+gd0fd53b~7^2~7 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=b51497597868a40df039dd3ca11b35a6258bbbb3;hp=e9153c4f2c71ed965822fcfe5112d2bc38506baf Re-enable Linux support for altosui. This steals code from cc-usbdev for scanning the USB tree and uses the same tty code as on Darwin Signed-off-by: Keith Packard --- diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 251ce2a0..7dbaafff 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: freetts.jar +Class-Path: /home/keithp/src/freetts/freetts-1.2.2/lib/freetts.jar diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 5ffbdadf..5cdc0fa7 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -1,3 +1,29 @@ +OS:=$(shell uname) + +ifeq ($(OS),Linux) + +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include -I. + +OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +LIBEXT=so + +endif + +ifeq ($(OS),Darwin) + +DARWIN_CFLAGS=\ + -I/System/Library/Frameworks/JavaVM.framework/Headers \ + -I/System/Library/Frameworks/IOKit.framework/Headers \ + -I/System/Library/Frameworks/CoreFoundation.framework/Headers +DARWIN_LIBS=\ + -framework IOKit -framework CoreFoundation + +OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY +LIBEXT=dylib + +endif + .SUFFIXES: .java .class CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" @@ -14,8 +40,6 @@ JNI_SRCS=$(JNI_FILE) \ $(JNI_DIR)/altos_device.java \ $(JNI_DIR)/libaltos.java -LIBEXT=dylib - JAVAFILES=\ $(JNI_SRCS) @@ -28,14 +52,7 @@ all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -DARWIN_CFLAGS=\ - -I/System/Library/Frameworks/JavaVM.framework/Headers \ - -I/System/Library/Frameworks/IOKit.framework/Headers \ - -I/System/Library/Frameworks/CoreFoundation.framework/Headers -DARWIN_LIBS=\ - -framework IOKit -framework CoreFoundation - -CFLAGS = $(DARWIN_CFLAGS) -I. -O0 -g +CFLAGS=$(OS_CFLAGS) -O0 -g HEADERS=libaltos.h SRCS = libaltos.c $(SWIG_WRAP) @@ -46,7 +63,7 @@ cjnitest: cjnitest.o $(OBJS) cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) libaltos.$(LIBEXT): $(OBJS) - gcc -shared -o $@ $(OBJS) $(LIBS) + gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) clean: rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 417c8fe5..7d471f38 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -16,10 +16,379 @@ */ #include "libaltos.h" +#include +#include +#include + +static int +match_dev(char *product, int serial, struct altos_device *device) +{ + struct altos_list *list; + int i; + + list = altos_list_start(); + if (!list) + return 0; + while ((i = altos_list_next(list, device)) != 0) { + if (product && strncmp (product, device->product, strlen(product)) != 0) + continue; + if (serial && serial != device->serial) + continue; + break; + } + altos_list_finish(list); + return i; +} + +int +altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) +{ + char *product; + int serial; + char *end; + char *colon; + int ret; + + if (arg) + { + /* check for */ + serial = strtol(arg, &end, 0); + if (end != arg) { + if (*end != '\0') + return 0; + product = NULL; + } else { + /* check for : */ + colon = strchr(arg, ':'); + if (colon) { + product = strndup(arg, colon - arg); + serial = strtol(colon + 1, &end, 0); + if (*end != '\0') + return 0; + } else { + product = arg; + serial = 0; + } + } + } else { + product = NULL; + serial = 0; + } + if (!product && default_product) + ret = match_dev(default_product, serial, device); + if (!ret) + ret = match_dev(product, serial, device); + if (product && product != arg) + free(product); + return ret; +} + +#ifdef LINUX + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +static char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} -#define USE_DARWIN +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; -#ifdef USE_DARWIN +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct altos_usbdev * +usb_scan_device(char *sys) +{ + struct altos_usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct altos_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product = load_string(sys, "product"); + usbdev->serial = load_dec(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = usb_tty(sys); + return usbdev; +} + +static void +usbdev_free(struct altos_usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product); + /* this can get used as a return value */ + if (usbdev->tty) + free(usbdev->tty); + free(usbdev); +} + +#define USB_DEVICES "/sys/bus/usb/devices" + +static int +dir_filter_dev(const struct dirent *d) +{ + const char *n = d->d_name; + char c; + + while ((c = *n++)) { + if (isdigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && n != d->d_name + 1) + continue; + return 0; + } + return 1; +} + +struct altos_list { + struct altos_usbdev **dev; + int current; + int ndev; +}; + +int +altos_init(void) +{ + return 1; +} + +void +altos_fini(void) +{ +} + +struct altos_list * +altos_list_start(void) +{ + int e; + struct dirent **ents; + char *dir; + struct altos_usbdev *dev; + struct altos_list *devs; + int n; + + devs = calloc(1, sizeof (struct altos_list)); + if (!devs) + return NULL; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = cc_fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + free(dir); + if (dev->idVendor == 0xfffe && dev->tty) { + if (devs->dev) + devs->dev = realloc(devs->dev, + devs->ndev + 1 * sizeof (struct usbdev *)); + else + devs->dev = malloc (sizeof (struct usbdev *)); + devs->dev[devs->ndev++] = dev; + } + } + free(ents); + devs->current = 0; + return devs; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + struct altos_usbdev *dev; + if (list->current >= list->ndev) + return 0; + dev = list->dev[list->current]; + strcpy(device->product, dev->product); + strcpy(device->path, dev->tty); + device->serial = dev->serial; + list->current++; + return 1; +} + +void +altos_list_finish(struct altos_list *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} + +#endif + +#ifdef DARWIN #include #include @@ -30,36 +399,32 @@ #include #include #include -#include -#include -#include -#include struct altos_list { - io_iterator_t iterator; + io_iterator_t iterator; }; static int get_string(io_object_t object, CFStringRef entry, char *result, int result_len) { - CFTypeRef entry_as_string; - Boolean got_string; - - entry_as_string = IORegistryEntrySearchCFProperty (object, - kIOServicePlane, - entry, - kCFAllocatorDefault, - kIORegistryIterateRecursively); - if (entry_as_string) { - got_string = CFStringGetCString(entry_as_string, - result, result_len, - kCFStringEncodingASCII); + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); - CFRelease(entry_as_string); - if (got_string) - return 1; - } - return 0; + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; } int @@ -117,10 +482,19 @@ altos_list_next(struct altos_list *list, struct altos_device *device) void altos_list_finish(struct altos_list *list) { - IOObjectRelease (list->iterator); - free(list); + IOObjectRelease (list->iterator); + free(list); } +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include #define USB_BUF_SIZE 64 @@ -133,54 +507,6 @@ struct altos_file { int in_read; }; -void -altos_test(char *path) -{ - int n; - char buf[16]; - int fd; - struct termios term; - - fd = open(path, O_RDWR | O_NOCTTY); - if (fd < 0) { - perror(path); - return; - } - if (ioctl(fd, TIOCEXCL, (char *) 0) < 0) { - perror("TIOCEXCL"); - close (fd); - return; - } - - n = tcgetattr(fd, &term); - if (n < 0) { - perror("tcgetattr"); - close(fd); - return; - } - cfmakeraw(&term); - term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; - n = tcsetattr(fd, TCSAFLUSH, &term); - if (n < 0) { - perror("tcsetattr"); - close(fd); - return; - } - write(fd, "\n?\n", 3); - for (;;) { - n = read(fd, buf, sizeof (buf)); - if (n < 0) { - perror("read"); - break; - } - if (n == 0) - break; - write(1, buf, n); - } - close(fd); -} - struct altos_file * altos_open(struct altos_device *device) { @@ -273,7 +599,7 @@ altos_getchar(struct altos_file *file, int timeout) return file->in_data[file->in_read++]; } -#endif /* USE_DARWIN */ +#endif /* POSIX_TTY */ #ifdef USE_LIBUSB #include