#include <stdlib.h>
#include <string.h>
+#define USE_POLL
+
PUBLIC int
altos_init(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)
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;
}
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;
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];
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;
}
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);
}
}
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)
{
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) {
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 <poll.h>
+#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++];
}
{
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);