altosui: Report error message back from libaltos
[fw/altos] / altosui / libaltos / libaltos.c
index 465f0ac89475c03d61b1b89067a7b4b05ef67e4a..48e00a4415d4bd034f33bd45710035a561d69fe9 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#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
@@ -33,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
@@ -56,6 +88,244 @@ altos_strndup (const char *s, size_t n)
 #define altos_strndup strndup
 #endif
 
+#ifdef POSIX_TTY
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+
+#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;
+};
+
+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)
+{
+       struct altos_file       *file = calloc (sizeof (struct altos_file), 1);
+       int                     ret;
+       struct termios          term;
+
+       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) {
+               altos_set_last_posix_error();
+               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) {
+               altos_set_last_posix_error();
+               close(file->fd);
+               free(file);
+               return NULL;
+       }
+#endif
+       ret = tcgetattr(file->fd, &term);
+       if (ret < 0) {
+               altos_set_last_posix_error();
+               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) {
+               altos_set_last_posix_error();
+               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) {
+                       altos_set_last_posix_error();
+                       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 <poll.h>
+#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) {
+                       altos_set_last_posix_error();
+                       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) {
+                               altos_set_last_posix_error();
+                               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 +338,10 @@ altos_strndup (const char *s, size_t n)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
 
 static char *
 cc_fullname (char *dir, char *file)
@@ -315,7 +589,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;
@@ -354,6 +628,140 @@ 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
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+       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_time,
+                                      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);
+}
+
+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)
+{
+       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) {
+               altos_set_last_posix_error();
+               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) {
+               altos_set_last_posix_error();
+               goto no_link;
+       }
+       sleep(1);
+
+#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
@@ -416,7 +824,7 @@ get_number(io_object_t object, CFStringRef entry, int *result)
        return 0;
 }
 
-struct altos_list *
+PUBLIC struct altos_list *
 altos_list_start(void)
 {
        struct altos_list *list = calloc (sizeof (struct altos_list), 1);
@@ -432,7 +840,7 @@ altos_list_start(void)
        return list;
 }
 
-int
+PUBLIC int
 altos_list_next(struct altos_list *list, struct altos_device *device)
 {
        io_object_t object;
@@ -459,238 +867,57 @@ altos_list_next(struct altos_list *list, struct altos_device *device)
        }
 }
 
-void
+PUBLIC void
 altos_list_finish(struct altos_list *list)
 {
        IOObjectRelease (list->iterator);
        free(list);
 }
 
-#endif
-
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#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;
+struct altos_bt_list {
+       int             sock;
+       int             dev_id;
+       int             rsp;
+       int             num_rsp;
 };
 
-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);
-       }
-}
+#define INQUIRY_MAX_RSP        255
 
-PUBLIC void
-altos_free(struct altos_file *file)
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
 {
-       altos_close(file);
-       free(file);
+       return NULL;
 }
 
-PUBLIC int
-altos_flush(struct altos_file *file)
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+                  struct altos_bt_device *device)
 {
-       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)
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
 {
-       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 <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
 {
-       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;
+       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';
 }
 
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
 {
-       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++];
+       return NULL;
 }
 
-#endif /* POSIX_TTY */
+#endif
+
 
 #ifdef WINDOWS
 
@@ -717,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)
 {
@@ -727,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 %d\n", GetLastError());
+               altos_set_last_windows_error();
                free(list);
                return NULL;
        }
@@ -739,13 +981,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;
@@ -761,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;
                }
@@ -771,16 +1014,17 @@ 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;
                }
                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);
@@ -793,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;
                }
@@ -808,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;
                }
@@ -816,12 +1062,14 @@ 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);
+       if (result != ERROR_NO_MORE_ITEMS) {
+               altos_set_last_windows_error();
+               printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result);
+       }
        return 0;
 }
 
@@ -840,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;
@@ -866,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;
@@ -904,22 +1156,27 @@ 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)) {
-                       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;
                        }
                }
@@ -947,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;
        }
@@ -962,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;
@@ -971,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;
@@ -995,7 +1255,7 @@ altos_free(struct altos_file *file)
        free(file);
 }
 
-int
+PUBLIC int
 altos_putchar(struct altos_file *file, char c)
 {
        int     ret;
@@ -1011,7 +1271,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;
@@ -1025,4 +1285,38 @@ altos_getchar(struct altos_file *file, int timeout)
        return file->in_data[file->in_read++];
 }
 
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+       return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+                  struct altos_bt_device *device)
+{
+       return 0;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+       free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+       strncpy(device->name, name, sizeof (device->name));
+       device->name[sizeof(device->name)-1] = '\0';
+       strncpy(device->addr, addr, sizeof (device->addr));
+       device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+       return NULL;
+}
+
 #endif