diff options
author | Keith Packard <keithp@keithp.com> | 2009-05-16 02:25:04 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2009-05-16 02:25:04 -0700 |
commit | 09771c644de54ae354e8f98af7ba74289b3c0fcc (patch) | |
tree | fb15f3b168a201fc4a789270dd18c391e44625d7 /aoview/aoview_dev.c | |
parent | 37250b00f6286aee4b3b28604f5d463db3079a89 (diff) |
Add preliminary aoview codesn4-flight2sn4-flight1
AoView connects with TeleDongle to present telemetry information in a
reasonable form. Right now, it just displays information to stdout, but it
does have fancy dialogs for finding the USB devices.
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'aoview/aoview_dev.c')
-rw-r--r-- | aoview/aoview_dev.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/aoview/aoview_dev.c b/aoview/aoview_dev.c new file mode 100644 index 00000000..5bb3cc9f --- /dev/null +++ b/aoview/aoview_dev.c @@ -0,0 +1,213 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "aoview.h" +#include <ctype.h> +#include <dirent.h> + +static char * +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 * +load_string(char *dir, char *file) +{ + char *full = 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 char * +basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +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; + int ntty; + char *tty; + + base = 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 = fullname(sys, endpoint_base); + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty, + alphasort); + free(endpoint_full); + if (ntty) { + tty = fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct usbdev * +usb_scan_device(char *sys) +{ + struct usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product = load_string(sys, "product"); + usbdev->serial = load_string(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = usb_tty(sys); + return usbdev; +} + +void +aoview_usbdev_free(struct usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product); + free(usbdev->serial); + 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; + return 0; + } + return 1; +} + +int +aoview_usb_scan(struct usbdev ***devs_ret) +{ + int n; + int ndev = 0; + int e; + struct dirent **ents; + char *dir; + struct usbdev **devs = NULL; + struct usbdev *dev; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + free(dir); + if (dev->idVendor == 0xfffe && dev->tty) { + if (devs) + devs = realloc(devs, ndev + 1 * sizeof (struct usbdev *)); + else + devs = malloc (sizeof (struct usbdev *)); + devs[ndev++] = dev; + } + } + free(ents); + *devs_ret = devs; + return ndev; +} |