+ // TODO: Regex instead?
+ if( strcmp(tmp, "ok") == 0 ) {
+ // We think dispense worked
+ // - The machine returns 'ok' if an empty slot is dispensed, even if
+ // it doesn't actually try to dispense (no sound)
+ ret = 0;
+ }
+ else {
+ printf("Coke_DoDispense: Machine returned unknown value '%s'\n", tmp);
+ ret = -1;
+ }
+
+ #if TRACE_COKE
+ printf("Coke_DoDispense: Updating slot status\n");
+ #endif
+ // Update status
+ Writef("s%i\r\n", Item);
+ len = ReadLine(sizeof tmp, tmp);
+ if(len == -1) gaCoke_CachedStatus[Item] = -1;
+ Coke_int_GetSlotStatus(tmp, Item);
+
+ // Release and return
+ pthread_mutex_unlock(&gCoke_Mutex);
+
+ return ret;
+}
+
+char ReadChar()
+{
+ fd_set readfs;
+ char ch = 0;
+ int ret;
+ struct timeval timeout;
+
+ timeout.tv_sec = READ_TIMEOUT;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&readfs);
+ FD_SET(giCoke_SerialFD, &readfs);
+
+ ret = select(giCoke_SerialFD+1, &readfs, NULL, NULL, &timeout);
+ if( ret == 0 ) return 0; // Timeout
+ if( ret != 1 ) {
+ printf("readchar return %i\n", ret);
+ return 0;
+ }
+
+ ret = read(giCoke_SerialFD, &ch, 1);
+ if( ret != 1 ) {
+ printf("ret = %i\n", ret);
+ return 0;
+ }
+
+ return ch;
+}
+
+int Writef(const char *Format, ...)
+{
+ va_list args;
+ int len;
+
+ va_start(args, Format);
+ len = vsnprintf(NULL, 0, Format, args);
+ va_end(args);
+
+ {
+ char buf[len+1];
+ va_start(args, Format);
+ vsnprintf(buf, len+1, Format, args);
+ va_end(args);
+
+ #if DEBUG
+ printf("Writef: %s", buf);
+ #endif
+
+ return write(giCoke_SerialFD, buf, len);
+ }
+
+}
+
+int WaitForColon()
+{
+ fd_set readfs;
+ char ch = 0;
+
+ FD_SET(giCoke_SerialFD, &readfs);
+
+ while( (ch = ReadChar()) != ':' && ch != 0);
+
+ if( ch == 0 ) return -1; // Timeout
+