14 #include <sys/ioctl.h>
16 #include <IOKit/serial/ioss.h>
25 "title" :
"VuoSerialIO",
28 "VuoList_VuoSerialDevice"
38 typedef struct _VuoSerial_internal
41 dispatch_queue_t queue;
43 dispatch_source_t source;
55 static void __attribute__((constructor)) VuoSerialIO_init()
68 ssize_t bytesRead = 0;
70 int bytesAvailable = dispatch_source_get_data(si->source);
71 if (bytesAvailable == 0)
74 fd = dispatch_source_get_handle(si->source);
76 data.
data = (
char *)malloc(bytesAvailable);
78 bytesRead = read(fd, data.
data, bytesAvailable);
86 data.
size = bytesRead;
90 char *hex = (
char *)malloc(data.
size * 4 + 2);
91 bzero(hex, data.
size * 4 + 2);
92 for(
int i = 0; i < data.
size; ++i)
94 hex[i] = isprint(data.
data[i]) ? data.
data[i] :
'_';
95 sprintf(hex + data.
size + 1 + i*3,
"%02x ", (
unsigned char)data.
data[i]);
97 hex[data.
size] =
'\t';
103 si->triggerSet.fire(data);
112 dispatch_source_cancel(si->source);
113 dispatch_release(si->source);
127 si->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, si->fileHandle, 0, si->queue);
128 dispatch_source_set_event_handler(si->source, ^{
129 VuoSerial_processPacket(si);
131 dispatch_source_set_cancel_handler(si->source, ^{
132 close(si->fileHandle);
134 dispatch_resume(si->source);
142 return open(devicePath,
160 (*i)->fileHandle = VuoSerial_openDevice((*i)->devicePath);
161 if ((*i)->fileHandle < 0)
189 si->queue = dispatch_queue_create(
"org.vuo.serial", NULL);
194 if (si->fileHandle >= 0)
198 VUserLog(
"Warning: Serial device '%s' isn't currently available (%s). I'll keep trying.", si->devicePath, strerror(errno));
216 dispatch_sync(si->queue, ^{
217 dispatch_source_cancel(si->source);
218 dispatch_release(si->source);
222 dispatch_release(si->queue);
224 VuoSerial_internalPool->removeSharedInstance(si->devicePath);
241 return (
VuoSerial)VuoSerial_internalPool->getSharedInstance(devicePath);
257 si->triggerSet.addTrigger(receivedData);
273 si->triggerSet.removeTrigger(receivedData);
281 if (!device || !data.
size || !data.
data)
285 dispatch_async(si->queue, ^{
286 ssize_t ret = write(si->fileHandle, data.data, data.size);
288 VUserLog(
"Error: %s", strerror(errno));
289 else if (ret != data.size)
290 VUserLog(
"Warning: Could only write %ld bytes (of %lld bytes total).", ret, data.size);
307 if (ioctl(si->fileHandle, IOSSIOSPEED, &baudRate) == -1)
308 VUserLog(
"Couldn't set %s to baud rate %lld: %s", si->devicePath, baudRate, strerror(errno));
312 struct termios options;
313 if (tcgetattr(si->fileHandle, &options) == -1)
315 VUserLog(
"Couldn't get TTY attributes for %s: %s", si->devicePath, strerror(errno));
321 options.c_cflag &= ~CSIZE;
323 options.c_cflag |= CS5;
324 else if (dataBits == 6)
325 options.c_cflag |= CS6;
326 else if (dataBits == 7)
327 options.c_cflag |= CS7;
328 else if (dataBits == 8)
329 options.c_cflag |= CS8;
331 VUserLog(
"Couldn't set %s dataBits to %lld.", si->devicePath, dataBits);
335 if (parity == VuoParity_None)
336 options.c_cflag &= ~PARENB;
337 else if (parity == VuoParity_Even)
339 options.c_cflag |= PARENB;
340 options.c_cflag &= ~PARODD;
342 else if (parity == VuoParity_Odd)
343 options.c_cflag |= PARENB | PARODD;
345 VUserLog(
"Couldn't set %s parity to %d.", si->devicePath, parity);
350 options.c_cflag &= ~CSTOPB;
351 else if (stopBits == 2)
352 options.c_cflag |= CSTOPB;
354 VUserLog(
"Couldn't set %s stopBits to %lld.", si->devicePath, stopBits);
358 if (tcsetattr(si->fileHandle, TCSANOW, &options) == -1)
359 VUserLog(
"Couldn't configure %s: %s", si->devicePath, strerror(errno));