2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 #define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
30 return LIBALTOS_SUCCESS;
38 static struct altos_error last_error;
41 altos_set_last_error(int code, char *string)
43 last_error.code = code;
44 strncpy(last_error.string, string, sizeof (last_error.string) -1);
45 last_error.string[sizeof(last_error.string)-1] = '\0';
49 altos_get_last_error(struct altos_error *error)
58 /* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
60 altos_strndup (const char *s, size_t n)
62 size_t len = strlen (s);
74 #define altos_strndup strndup
85 #define USB_BUF_SIZE 64
94 unsigned char out_data[USB_BUF_SIZE];
96 unsigned char in_data[USB_BUF_SIZE];
102 altos_set_last_posix_error(void)
104 altos_set_last_error(errno, strerror(errno));
107 PUBLIC struct altos_file *
108 altos_open(struct altos_device *device)
110 struct altos_file *file = calloc (sizeof (struct altos_file), 1);
115 altos_set_last_posix_error();
119 // altos_set_last_error(12, "yeah yeah, failed again");
123 file->fd = open(device->path, O_RDWR | O_NOCTTY);
125 altos_set_last_posix_error();
132 file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
133 if (file->out_fd < 0) {
134 altos_set_last_posix_error();
140 ret = tcgetattr(file->fd, &term);
142 altos_set_last_posix_error();
151 cfsetospeed(&term, B9600);
152 cfsetispeed(&term, B9600);
155 term.c_cc[VTIME] = 0;
158 term.c_cc[VTIME] = 1;
160 ret = tcsetattr(file->fd, TCSAFLUSH, &term);
162 altos_set_last_posix_error();
174 altos_close(struct altos_file *file)
176 if (file->fd != -1) {
180 write(file->pipe[1], "\r", 1);
190 altos_free(struct altos_file *file)
197 altos_flush(struct altos_file *file)
199 if (file->out_used && 0) {
201 fwrite(file->out_data, 1, file->out_used, stdout);
204 while (file->out_used) {
210 ret = write (file->fd, file->out_data, file->out_used);
212 ret = write (file->out_fd, file->out_data, file->out_used);
215 altos_set_last_posix_error();
216 return -last_error.code;
219 memmove(file->out_data, file->out_data + ret,
220 file->out_used - ret);
221 file->out_used -= ret;
228 altos_putchar(struct altos_file *file, char c)
232 if (file->out_used == USB_BUF_SIZE) {
233 ret = altos_flush(file);
238 file->out_data[file->out_used++] = c;
240 if (file->out_used == USB_BUF_SIZE)
241 ret = altos_flush(file);
250 altos_fill(struct altos_file *file, int timeout)
259 while (file->in_read == file->in_used) {
261 return LIBALTOS_ERROR;
264 fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
265 fd[1].fd = file->pipe[0];
266 fd[1].events = POLLIN;
267 ret = poll(fd, 2, timeout);
269 altos_set_last_posix_error();
270 return LIBALTOS_ERROR;
273 return LIBALTOS_TIMEOUT;
275 if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
276 return LIBALTOS_ERROR;
277 if (fd[0].revents & POLLIN)
280 ret = read(file->fd, file->in_data, USB_BUF_SIZE);
282 altos_set_last_posix_error();
283 return LIBALTOS_ERROR;
288 if (ret == 0 && timeout > 0)
289 return LIBALTOS_TIMEOUT;
293 if (file->in_used && 0) {
295 fwrite(file->in_data, 1, file->in_used, stdout);
302 altos_getchar(struct altos_file *file, int timeout)
305 while (file->in_read == file->in_used) {
307 return LIBALTOS_ERROR;
308 ret = altos_fill(file, timeout);
312 return file->in_data[file->in_read++];
315 #endif /* POSIX_TTY */
318 * Scan for Altus Metrum devices by looking through /sys
329 #include <bluetooth/bluetooth.h>
330 #include <bluetooth/hci.h>
331 #include <bluetooth/hci_lib.h>
332 #include <bluetooth/rfcomm.h>
335 cc_fullname (char *dir, char *file)
338 int dlen = strlen (dir);
339 int flen = strlen (file);
342 if (dir[dlen-1] != '/')
344 new = malloc (dlen + slen + flen + 1);
355 cc_basename(char *file)
359 b = strrchr(file, '/');
366 load_string(char *dir, char *file)
368 char *full = cc_fullname(dir, file);
374 f = fopen(full, "r");
378 r = fgets(line, sizeof (line), f);
383 if (r[rlen-1] == '\n')
389 load_hex(char *dir, char *file)
395 line = load_string(dir, file);
398 i = strtol(line, &end, 16);
406 load_dec(char *dir, char *file)
412 line = load_string(dir, file);
415 i = strtol(line, &end, 10);
423 dir_filter_tty_colon(const struct dirent *d)
425 return strncmp(d->d_name, "tty:", 4) == 0;
429 dir_filter_tty(const struct dirent *d)
431 return strncmp(d->d_name, "tty", 3) == 0;
434 struct altos_usbdev {
439 int serial; /* AltOS always uses simple integer serial numbers */
450 struct dirent **namelist;
453 char endpoint_base[20];
459 base = cc_basename(sys);
460 num_configs = load_hex(sys, "bNumConfigurations");
461 num_interfaces = load_hex(sys, "bNumInterfaces");
462 for (config = 1; config <= num_configs; config++) {
463 for (interface = 0; interface < num_interfaces; interface++) {
464 sprintf(endpoint_base, "%s:%d.%d",
465 base, config, interface);
466 endpoint_full = cc_fullname(sys, endpoint_base);
469 /* Check for tty:ttyACMx style names
471 ntty = scandir(endpoint_full, &namelist,
472 dir_filter_tty_colon,
476 tty = cc_fullname("/dev", namelist[0]->d_name + 4);
481 /* Check for tty/ttyACMx style names
483 tty_dir = cc_fullname(endpoint_full, "tty");
484 ntty = scandir(tty_dir, &namelist,
489 tty = cc_fullname("/dev", namelist[0]->d_name);
495 /* Check for ttyACMx style names
497 ntty = scandir(endpoint_full, &namelist,
502 tty = cc_fullname("/dev", namelist[0]->d_name);
512 static struct altos_usbdev *
513 usb_scan_device(char *sys)
515 struct altos_usbdev *usbdev;
521 usbdev = calloc(1, sizeof (struct altos_usbdev));
524 usbdev->sys = strdup(sys);
525 usbdev->manufacturer = load_string(sys, "manufacturer");
526 usbdev->product_name = load_string(sys, "product");
527 usbdev->serial = load_dec(sys, "serial");
528 usbdev->idProduct = load_hex(sys, "idProduct");
529 usbdev->idVendor = load_hex(sys, "idVendor");
535 usbdev_free(struct altos_usbdev *usbdev)
538 free(usbdev->manufacturer);
539 free(usbdev->product_name);
540 /* this can get used as a return value */
546 #define USB_DEVICES "/sys/bus/usb/devices"
549 dir_filter_dev(const struct dirent *d)
551 const char *n = d->d_name;
559 if (c == '.' && n != d->d_name + 1)
567 struct altos_usbdev **dev;
573 altos_list_start(void)
576 struct dirent **ents;
578 struct altos_usbdev *dev;
579 struct altos_list *devs;
582 devs = calloc(1, sizeof (struct altos_list));
586 n = scandir (USB_DEVICES, &ents,
591 for (e = 0; e < n; e++) {
592 dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
593 dev = usb_scan_device(dir);
598 devs->dev = realloc(devs->dev,
599 (devs->ndev + 1) * sizeof (struct usbdev *));
601 devs->dev = malloc (sizeof (struct usbdev *));
602 devs->dev[devs->ndev++] = dev;
609 PUBLIC struct altos_list *
610 altos_ftdi_list_start(void)
612 return altos_list_start();
616 altos_list_next(struct altos_list *list, struct altos_device *device)
618 struct altos_usbdev *dev;
619 if (list->current >= list->ndev) {
622 dev = list->dev[list->current];
623 strcpy(device->name, dev->product_name);
624 device->vendor = dev->idVendor;
625 device->product = dev->idProduct;
626 strcpy(device->path, dev->tty);
627 device->serial = dev->serial;
633 altos_list_finish(struct altos_list *usbdevs)
639 for (i = 0; i < usbdevs->ndev; i++)
640 usbdev_free(usbdevs->dev[i]);
644 struct altos_bt_list {
652 #define INQUIRY_MAX_RSP 255
654 struct altos_bt_list *
655 altos_bt_list_start(int inquiry_time)
657 struct altos_bt_list *bt_list;
659 bt_list = calloc(1, sizeof (struct altos_bt_list));
663 bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
666 bt_list->dev_id = hci_get_route(NULL);
667 if (bt_list->dev_id < 0)
670 bt_list->sock = hci_open_dev(bt_list->dev_id);
671 if (bt_list->sock < 0)
674 bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
680 if (bt_list->num_rsp < 0)
687 close(bt_list->sock);
698 altos_bt_list_next(struct altos_bt_list *bt_list,
699 struct altos_bt_device *device)
703 if (bt_list->rsp >= bt_list->num_rsp)
706 ii = &bt_list->ii[bt_list->rsp];
707 ba2str(&ii->bdaddr, device->addr);
708 memset(&device->name, '\0', sizeof (device->name));
709 if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
710 sizeof (device->name),
711 device->name, 0) < 0) {
712 strcpy(device->name, "[unknown]");
719 altos_bt_list_finish(struct altos_bt_list *bt_list)
721 close(bt_list->sock);
727 altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
729 strncpy(device->name, name, sizeof (device->name));
730 device->name[sizeof(device->name)-1] = '\0';
731 strncpy(device->addr, addr, sizeof (device->addr));
732 device->addr[sizeof(device->addr)-1] = '\0';
736 altos_bt_open(struct altos_bt_device *device)
738 struct sockaddr_rc addr = { 0 };
740 struct altos_file *file;
742 file = calloc(1, sizeof (struct altos_file));
745 addr.rc_family = AF_BLUETOOTH;
747 str2ba(device->addr, &addr.rc_bdaddr);
749 for (i = 0; i < 5; i++) {
750 file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
752 altos_set_last_posix_error();
756 status = connect(file->fd,
757 (struct sockaddr *)&addr,
759 if (status >= 0 || errno != EBUSY)
765 altos_set_last_posix_error();
773 file->out_fd = dup(file->fd);
788 #include <IOKitLib.h>
789 #include <IOKit/usb/USBspec.h>
790 #include <sys/param.h>
792 #include <CFNumber.h>
799 io_iterator_t iterator;
804 get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
806 CFTypeRef entry_as_string;
809 entry_as_string = IORegistryEntrySearchCFProperty (object,
813 kIORegistryIterateRecursively);
814 if (entry_as_string) {
815 got_string = CFStringGetCString(entry_as_string,
817 kCFStringEncodingASCII);
819 CFRelease(entry_as_string);
827 get_number(io_object_t object, CFStringRef entry, int *result)
829 CFTypeRef entry_as_number;
832 entry_as_number = IORegistryEntrySearchCFProperty (object,
836 kIORegistryIterateRecursively);
837 if (entry_as_number) {
838 got_number = CFNumberGetValue(entry_as_number,
847 PUBLIC struct altos_list *
848 altos_list_start(void)
850 struct altos_list *list = calloc (sizeof (struct altos_list), 1);
851 CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
852 io_iterator_t tdIterator;
853 io_object_t tdObject;
857 ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
858 if (ret != kIOReturnSuccess) {
866 PUBLIC struct altos_list *
867 altos_ftdi_list_start(void)
869 struct altos_list *list = altos_list_start();
877 altos_list_next(struct altos_list *list, struct altos_device *device)
880 char serial_string[128];
883 object = IOIteratorNext(list->iterator);
887 if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
888 !get_number (object, CFSTR(kUSBProductID), &device->product))
891 if (device->vendor != 0x0403)
894 if (device->vendor != 0xfffe)
896 if (device->product < 0x000a || 0x0013 < device->product)
899 if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
900 get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
901 get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
902 device->serial = atoi(serial_string);
909 altos_list_finish(struct altos_list *list)
911 IOObjectRelease (list->iterator);
915 struct altos_bt_list {
922 #define INQUIRY_MAX_RSP 255
924 struct altos_bt_list *
925 altos_bt_list_start(int inquiry_time)
931 altos_bt_list_next(struct altos_bt_list *bt_list,
932 struct altos_bt_device *device)
938 altos_bt_list_finish(struct altos_bt_list *bt_list)
943 altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
945 strncpy(device->name, name, sizeof (device->name));
946 device->name[sizeof(device->name)-1] = '\0';
947 strncpy(device->addr, addr, sizeof (device->addr));
948 device->addr[sizeof(device->addr)-1] = '\0';
952 altos_bt_open(struct altos_bt_device *device)
964 #include <setupapi.h>
972 #define USB_BUF_SIZE 64
976 unsigned char out_data[USB_BUF_SIZE];
978 unsigned char in_data[USB_BUF_SIZE];
989 log_message(char *fmt, ...)
991 static FILE *log = NULL;
995 log = fopen("\\temp\\altos.txt", "w");
999 fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
1000 time.wYear, time.wMonth, time.wDay,
1001 time.wHour, time.wMinute, time.wSecond);
1003 vfprintf(log, fmt, a);
1010 _altos_set_last_windows_error(char *file, int line)
1012 DWORD error = GetLastError();
1013 TCHAR message[1024];
1014 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1019 sizeof (message) / sizeof (TCHAR),
1021 if (error != ERROR_SUCCESS)
1022 log_message ("%s:%d %s\n", file, line, message);
1023 altos_set_last_error(error, message);
1026 #define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__)
1028 PUBLIC struct altos_list *
1029 altos_list_start(void)
1031 struct altos_list *list = calloc(1, sizeof (struct altos_list));
1035 list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
1036 DIGCF_ALLCLASSES|DIGCF_PRESENT);
1037 if (list->dev_info == INVALID_HANDLE_VALUE) {
1038 altos_set_last_windows_error();
1047 PUBLIC struct altos_list *
1048 altos_ftdi_list_start(void)
1050 struct altos_list *list = calloc(1, sizeof (struct altos_list));
1054 list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
1055 DIGCF_ALLCLASSES|DIGCF_PRESENT);
1056 if (list->dev_info == INVALID_HANDLE_VALUE) {
1057 altos_set_last_windows_error();
1067 altos_list_next(struct altos_list *list, struct altos_device *device)
1069 SP_DEVINFO_DATA dev_info_data;
1072 char friendlyname[256];
1076 unsigned int vid, pid;
1079 DWORD friendlyname_type;
1080 DWORD friendlyname_len;
1082 dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
1083 while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
1088 dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
1089 DICS_FLAG_GLOBAL, 0, DIREG_DEV,
1091 if (dev_key == INVALID_HANDLE_VALUE) {
1092 altos_set_last_windows_error();
1101 /* Fetch symbolic name for this device and parse out
1102 * the vid/pid/serial info */
1103 symbolic_len = sizeof(symbolic);
1104 result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
1105 symbolic, &symbolic_len);
1107 altos_set_last_windows_error();
1108 RegCloseKey(dev_key);
1111 vid = pid = serial = 0;
1112 sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
1114 sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
1116 sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
1120 /* Fetch the com port name */
1121 port_len = sizeof (port);
1122 result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
1124 RegCloseKey(dev_key);
1126 altos_set_last_windows_error();
1130 /* Fetch the device description which is the device name,
1131 * with firmware that has unique USB ids */
1132 friendlyname_len = sizeof (friendlyname);
1133 if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
1137 (BYTE *)friendlyname,
1138 sizeof(friendlyname),
1141 altos_set_last_windows_error();
1144 device->vendor = vid;
1145 device->product = pid;
1146 device->serial = serial;
1147 strcpy(device->name, friendlyname);
1149 strcpy(device->path, (char *) port);
1152 result = GetLastError();
1153 if (result != ERROR_NO_MORE_ITEMS)
1154 altos_set_last_windows_error();
1159 altos_list_finish(struct altos_list *list)
1161 SetupDiDestroyDeviceInfoList(list->dev_info);
1166 altos_queue_read(struct altos_file *file)
1169 if (file->pend_read)
1170 return LIBALTOS_SUCCESS;
1172 if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
1173 if (GetLastError() != ERROR_IO_PENDING) {
1174 altos_set_last_windows_error();
1175 return LIBALTOS_ERROR;
1177 file->pend_read = TRUE;
1179 file->pend_read = FALSE;
1181 file->in_used = got;
1183 return LIBALTOS_SUCCESS;
1187 altos_wait_read(struct altos_file *file, int timeout)
1192 if (!file->pend_read)
1193 return LIBALTOS_SUCCESS;
1198 ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
1201 if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
1202 altos_set_last_windows_error();
1203 return LIBALTOS_ERROR;
1205 file->pend_read = FALSE;
1207 file->in_used = got;
1210 return LIBALTOS_TIMEOUT;
1213 altos_set_last_windows_error();
1214 return LIBALTOS_ERROR;
1216 return LIBALTOS_SUCCESS;
1220 altos_fill(struct altos_file *file, int timeout)
1224 if (file->in_read < file->in_used)
1225 return LIBALTOS_SUCCESS;
1227 file->in_read = file->in_used = 0;
1229 ret = altos_queue_read(file);
1232 ret = altos_wait_read(file, timeout);
1236 return LIBALTOS_SUCCESS;
1240 altos_flush(struct altos_file *file)
1243 unsigned char *data = file->out_data;
1244 int used = file->out_used;
1248 if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
1249 if (GetLastError() != ERROR_IO_PENDING) {
1250 altos_set_last_windows_error();
1251 return LIBALTOS_ERROR;
1253 ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
1256 if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
1257 altos_set_last_windows_error();
1258 return LIBALTOS_ERROR;
1262 altos_set_last_windows_error();
1263 return LIBALTOS_ERROR;
1270 return LIBALTOS_SUCCESS;
1274 open_serial(char *full_name)
1279 handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
1280 0, NULL, OPEN_EXISTING,
1281 FILE_FLAG_OVERLAPPED, NULL);
1283 if (handle == INVALID_HANDLE_VALUE) {
1284 altos_set_last_windows_error();
1285 return INVALID_HANDLE_VALUE;
1288 if (!GetCommState(handle, &dcb)) {
1289 altos_set_last_windows_error();
1290 CloseHandle(handle);
1291 return INVALID_HANDLE_VALUE;
1293 dcb.BaudRate = CBR_9600;
1295 dcb.fParity = FALSE;
1296 dcb.fOutxCtsFlow = FALSE;
1297 dcb.fOutxDsrFlow = FALSE;
1298 dcb.fDtrControl = DTR_CONTROL_ENABLE;
1299 dcb.fDsrSensitivity = FALSE;
1300 dcb.fTXContinueOnXoff = FALSE;
1303 dcb.fErrorChar = FALSE;
1305 dcb.fRtsControl = RTS_CONTROL_ENABLE;
1306 dcb.fAbortOnError = FALSE;
1310 dcb.Parity = NOPARITY;
1311 dcb.StopBits = ONESTOPBIT;
1319 if (!SetCommState(handle, &dcb)) {
1320 altos_set_last_windows_error();
1321 CloseHandle(handle);
1322 return INVALID_HANDLE_VALUE;
1327 PUBLIC struct altos_file *
1328 altos_open(struct altos_device *device)
1330 struct altos_file *file = calloc (1, sizeof (struct altos_file));
1332 COMMTIMEOUTS timeouts;
1338 strcpy(full_name, "\\\\.\\");
1339 strcat(full_name, device->path);
1341 file->handle = INVALID_HANDLE_VALUE;
1343 for (i = 0; i < 5; i++) {
1344 file->handle = open_serial(full_name);
1345 if (file->handle != INVALID_HANDLE_VALUE)
1347 altos_set_last_windows_error();
1351 if (file->handle == INVALID_HANDLE_VALUE) {
1356 /* The FTDI driver doesn't appear to work right unless you open it twice */
1357 if (device->vendor == 0x0403) {
1358 CloseHandle(file->handle);
1359 file->handle = open_serial(full_name);
1360 if (file->handle == INVALID_HANDLE_VALUE) {
1366 timeouts.ReadIntervalTimeout = MAXDWORD;
1367 timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
1368 timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
1369 timeouts.WriteTotalTimeoutMultiplier = 0;
1370 timeouts.WriteTotalTimeoutConstant = 0;
1371 SetCommTimeouts(file->handle, &timeouts);
1373 file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1374 file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1380 altos_close(struct altos_file *file)
1382 HANDLE handle = file->handle;
1383 if (handle != INVALID_HANDLE_VALUE) {
1384 HANDLE ov_read = file->ov_read.hEvent;
1385 HANDLE ov_write = file->ov_write.hEvent;
1386 file->handle = INVALID_HANDLE_VALUE;
1387 file->ov_read.hEvent = INVALID_HANDLE_VALUE;
1388 file->ov_write.hEvent = INVALID_HANDLE_VALUE;
1389 PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
1391 CloseHandle(handle);
1392 file->handle = INVALID_HANDLE_VALUE;
1393 CloseHandle(ov_read);
1394 CloseHandle(ov_write);
1399 altos_free(struct altos_file *file)
1406 altos_putchar(struct altos_file *file, char c)
1410 if (file->out_used == USB_BUF_SIZE) {
1411 ret = altos_flush(file);
1415 file->out_data[file->out_used++] = c;
1416 if (file->out_used == USB_BUF_SIZE)
1417 return altos_flush(file);
1418 return LIBALTOS_SUCCESS;
1422 altos_getchar(struct altos_file *file, int timeout)
1425 while (file->in_read == file->in_used) {
1426 if (file->handle == INVALID_HANDLE_VALUE) {
1427 altos_set_last_windows_error();
1428 return LIBALTOS_ERROR;
1430 ret = altos_fill(file, timeout);
1434 return file->in_data[file->in_read++];
1437 struct altos_bt_list *
1438 altos_bt_list_start(int inquiry_time)
1444 altos_bt_list_next(struct altos_bt_list *bt_list,
1445 struct altos_bt_device *device)
1451 altos_bt_list_finish(struct altos_bt_list *bt_list)
1457 altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
1459 strncpy(device->name, name, sizeof (device->name));
1460 device->name[sizeof(device->name)-1] = '\0';
1461 strncpy(device->addr, addr, sizeof (device->addr));
1462 device->addr[sizeof(device->addr)-1] = '\0';
1466 altos_bt_open(struct altos_bt_device *device)