X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=ao-tools%2Flibaltos%2Flibaltos.c;h=65cd6c1a89bff2b2f6d3c7c0ca48388d814db0e3;hp=3e8485e450a141084a69f5432ab269ef6dcff628;hb=b7fa1ea3338f63b8edcf8aacccb5e519ca0b213f;hpb=d14c96663a1027164fa30ed89b53f5a9d3fdb82b diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 3e8485e4..65cd6c1a 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -21,6 +21,8 @@ #include #include +#define USE_POLL + PUBLIC int altos_init(void) { @@ -33,6 +35,9 @@ 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) @@ -391,24 +396,40 @@ get_string(io_object_t object, CFStringRef entry, char *result, int result_len) 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"); - UInt32 vendor = 0xfffe, product = 0x000a; - CFNumberRef vendor_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor); - CFNumberRef product_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product); io_iterator_t tdIterator; io_object_t tdObject; - - CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBVendorID), vendor_ref); - CFDictionaryAddValue(matching_dictionary, CFSTR(kUSBProductID), product_ref); + kern_return_t ret; + int i; - IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); - - CFRelease(vendor_ref); - CFRelease(product_ref); + ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); + if (ret != kIOReturnSuccess) + return NULL; return list; } @@ -423,8 +444,15 @@ altos_list_next(struct altos_list *list, struct altos_device *device) 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->product, sizeof (device->product)) && + 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; @@ -453,6 +481,11 @@ altos_list_finish(struct altos_list *list) 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]; @@ -470,29 +503,54 @@ altos_open(struct altos_device *device) if (!file) return NULL; + printf("open %s\n", device->path); file->fd = open(device->path, O_RDWR | O_NOCTTY); + printf("opened %d\n", file->fd); 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; } + printf("running %d\n", file->fd); return file; } @@ -500,8 +558,16 @@ void altos_close(struct altos_file *file) { if (file->fd != -1) { - close(file->fd); + 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 + printf("close %d\n", fd); + close(fd); } } @@ -512,22 +578,6 @@ altos_free(struct altos_file *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 0; -} - int altos_flush(struct altos_file *file) { @@ -536,7 +586,12 @@ altos_flush(struct altos_file *file) if (file->fd < 0) return -EBADF; + printf("write %d\n", file->out_used); +#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) { @@ -545,33 +600,87 @@ altos_flush(struct altos_file *file) file->out_used -= ret; } } + return 0; +} + +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 int -altos_getchar(struct altos_file *file, int timeout) +altos_fill(struct altos_file *file, int timeout) { - while (file->in_read == file->in_used) { - int ret; + int ret; +#ifdef USE_POLL + struct pollfd fd[2]; +#endif - altos_flush(file); + if (timeout == 0) + timeout = -1; + while (file->in_read == file->in_used) { if (file->fd < 0) - return -EBADF; - if (timeout) { - struct pollfd fd; - int ret; - fd.fd = file->fd; - fd.events = POLLIN; - ret = poll(&fd, 1, timeout); - if (ret == 0) + return LIBALTOS_ERROR; +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN; + 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 & POLLIN) +#endif + { + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret) + printf("read %d\n", ret); + 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 } - ret = read(file->fd, file->in_data, USB_BUF_SIZE); - if (ret < 0) + } + return 0; +} + +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; - file->in_read = 0; - file->in_used = ret; + ret = altos_fill(file, timeout); + if (ret) + return ret; } return file->in_data[file->in_read++]; } @@ -851,9 +960,6 @@ altos_getchar(struct altos_file *file, int timeout) { int ret; while (file->in_read == file->in_used) { - ret = altos_flush(file); - if (ret) - return ret; if (file->handle == INVALID_HANDLE_VALUE) return LIBALTOS_ERROR; ret = altos_fill(file, timeout);