int flushMidiDevice (MidiDevice *midi) { int ok = 1; if (midi->count > 0) { MMRESULT error; MIDIHDR header; header.lpData = midi->buffer; header.dwBufferLength = midi->count; header.dwFlags = 0; if ((error = midiOutPrepareHeader(midi->handle, &header, sizeof(header))) == MMSYSERR_NOERROR) { if ((error = midiOutLongMsg(midi->handle, &header, sizeof(header))) == MMSYSERR_NOERROR) { midi->count = 0; } else { logMidiOutError(error, LOG_ERR, "midiOutLongMsg"); ok = 0; } while ((error = midiOutUnprepareHeader(midi->handle, &header, sizeof(header))) == MIDIERR_STILLPLAYING) { approximateDelay(1); } if (error != MMSYSERR_NOERROR) { logMidiOutError(error, LOG_ERR, "midiOutUnprepareHeader"); } } else { logMidiOutError(error, LOG_ERR, "midiOutPrepareHeader"); ok = 0; } } return ok; }
static void awaitAction (long int timeout) { AsyncWaitData *wd = getWaitData(); if (wd) { const CallbackExecuterEntry *cbx = callbackExecuterTable; CallbackExecuterParameters parameters = { .tsd = wd->tsd, .timeout = timeout }; wd->waitDepth += 1; logMessage(LOG_CATEGORY(ASYNC_EVENTS), "begin: level %u: timeout %ld", wd->waitDepth, timeout); while (cbx->execute) { if (cbx->execute(¶meters)) break; cbx += 1; } logMessage(LOG_CATEGORY(ASYNC_EVENTS), "end: level %u: %s", wd->waitDepth, cbx->action); wd->waitDepth -= 1; } else { logMessage(LOG_CATEGORY(ASYNC_EVENTS), "waiting: %ld", timeout); approximateDelay(timeout); } }
int writePcmData (PcmDevice *pcm, const unsigned char *buffer, int count) { int frameSize = getPcmFrameSize(pcm); int framesLeft = count / frameSize; while (framesLeft > 0) { int result; if ((result = pcmAlsa_pcm_writei(pcm->handle, buffer, framesLeft)) > 0) { framesLeft -= result; buffer += result * frameSize; } else { switch (result) { case -EPIPE: if ((result = pcmAlsa_pcm_prepare(pcm->handle)) < 0) { logPcmError(LOG_WARNING, "underrun recovery - prepare", result); return 0; } continue; case -ESTRPIPE: while ((result = pcmAlsa_pcm_resume(pcm->handle)) == -EAGAIN) approximateDelay(1); if (result < 0) { if ((result = pcmAlsa_pcm_prepare(pcm->handle)) < 0) { logPcmError(LOG_WARNING, "resume - prepare", result); return 0; } } continue; } } } return 1; }
int getUinputDevice (void) { static int uinputDevice = -1; #ifdef HAVE_LINUX_UINPUT_H if (uinputDevice == -1) { const char *name; { static int status = 0; int wait = !status; if (!installKernelModule("uinput", &status)) wait = 0; if (wait) approximateDelay(500); } { static const char *const names[] = {"uinput", "input/uinput", NULL}; name = resolveDeviceName(names, "uinput"); } if (name) { int device = openCharacterDevice(name, O_WRONLY, 10, 223); if (device != -1) { struct uinput_user_dev description; logMessage(LOG_DEBUG, "uinput opened: %s fd=%d", name, device); memset(&description, 0, sizeof(description)); strcpy(description.name, "brltty"); if (write(device, &description, sizeof(description)) != -1) { if (enableUinputKeyEvents(device)) { if (enableUinputAutorepeat(device)) { if (ioctl(device, UI_DEV_CREATE) != -1) { uinputDevice = device; } else { logSystemError("ioctl[UI_DEV_CREATE]"); } } } } else { logSystemError("write(struct uinput_user_dev)"); } if (device != uinputDevice) { close(device); logMessage(LOG_DEBUG, "uinput closed"); } } else { logMessage(LOG_DEBUG, "cannot open uinput"); } } } #endif /* HAVE_LINUX_UINPUT_H */ return uinputDevice; }
static int awaitMonitors (const MonitorGroup *monitors, int timeout) { if (monitors->count) { DWORD result = WaitForMultipleObjects(monitors->count, monitors->array, FALSE, timeout); if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + monitors->count))) return 1; if (result == WAIT_FAILED) { logWindowsSystemError("WaitForMultipleObjects"); } } else { approximateDelay(timeout); } return 0; }
static int modifyFileLock (int file, int mode) { int ok = 0; off_t offset; if ((offset = lseek(file, 0, SEEK_CUR)) != -1) { if (lseek(file, 0, SEEK_SET) != -1) { int wait; if (mode == _LK_LOCK) { mode = _LK_NBLCK; wait = 1; } else if (mode == _LK_RLCK) { mode = _LK_NBRLCK; wait = 1; } else { wait = 0; } while (1) { if (_locking(file, mode, LONG_MAX) != -1) { ok = 1; break; } if (errno != EACCES) { logSystemError("_locking"); break; } if (!wait) break; approximateDelay(1000); } if (lseek(file, offset, SEEK_SET) == -1) { logSystemError("lseek"); ok = 0; } } else { logSystemError("lseek"); } } else { logSystemError("lseek"); } return ok; }
int serialPollInput (SerialDevice *serial, int timeout) { if (serial->package.byte == SERIAL_NO_BYTE) { TimePeriod period; startTimePeriod(&period, timeout); while ((serial->package.byte = serial->package.port->driver->fetch(serial->package.port)) == SERIAL_NO_BYTE) { if (afterTimePeriod(&period, NULL)) { errno = EAGAIN; return 0; } approximateDelay(1); } } return 1; }
BluetoothConnection * bthOpenConnection (const char *address, uint8_t channel, int force) { BluetoothConnection *connection; if ((connection = malloc(sizeof(*connection)))) { memset(connection, 0, sizeof(*connection)); connection->channel = channel; if (bthParseAddress(&connection->address, address)) { int alreadyTried = 0; if (force) { bthForgetConnectError(connection->address); } else { int value; if (bthRecallConnectError(connection->address, &value)) { errno = value; alreadyTried = 1; } } if (!alreadyTried) { TimePeriod period; startTimePeriod(&period, 2000); while (1) { if ((connection->extension = bthConnect(connection->address, connection->channel, 15000))) return connection; if (afterTimePeriod(&period, NULL)) break; if (errno != EBUSY) break; approximateDelay(100); } bthRememberConnectError(connection->address, errno); } } free(connection); } else { logMallocError(); } return NULL; }
static int readKey (void) { unsigned char key; unsigned char arg; if (serialReadData(serialDevice, &key, 1, 0, 0) != 1) return EOF; switch (key) { default: arg = 0; break; case KEY_FUNCTION: case KEY_FUNCTION2: case KEY_UPDATE: while (serialReadData(serialDevice, &arg, 1, 0, 0) != 1) approximateDelay(1); break; } { int result = COMPOUND_KEY(key, arg); logMessage(LOG_DEBUG, "Key read: %4.4X", result); return result; } }
static struct usbdevfs_urb * usbInterruptTransfer ( UsbEndpoint *endpoint, void *buffer, int length, int timeout ) { UsbDevice *device = endpoint->device; struct usbdevfs_urb *urb = usbSubmitRequest(device, endpoint->descriptor->bEndpointAddress, buffer, length, NULL); if (urb) { UsbEndpointExtension *eptx = endpoint->extension; int interval = endpoint->descriptor->bInterval + 1; TimePeriod period; if (timeout) startTimePeriod(&period, timeout); do { if (usbReapUrb(device, 0) && deleteItem(eptx->completedRequests, urb)) { if (!urb->status) return urb; if ((errno = urb->status) < 0) errno = -errno; free(urb); break; } if (!timeout || afterTimePeriod(&period, NULL)) { usbCancelRequest(device, urb); errno = ETIMEDOUT; break; } approximateDelay(interval); } while (1); } return NULL; }
void usleep (int usec) { if (usec > 0) { approximateDelay((usec + (USECS_PER_MSEC - 1)) / USECS_PER_MSEC); } }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { int key = readKey(); if (context != currentContext) { logMessage(LOG_DEBUG, "Context switch: %d -> %d", currentContext, context); switch (currentContext = context) { case KTB_CTX_DEFAULT: deviceStatus = DEV_ONLINE; break; default: break; } } if (key != EOF) { switch (key) { case KEY_FUNCTION_ENTER: return BRL_BLK_PASSKEY + BRL_KEY_ENTER; case KEY_FUNCTION_TAB: return BRL_BLK_PASSKEY + BRL_KEY_TAB; case KEY_FUNCTION_CURSOR_UP: return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_UP; case KEY_FUNCTION_CURSOR_DOWN: return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_DOWN; case KEY_FUNCTION_CURSOR_LEFT: return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_LEFT; case KEY_FUNCTION_CURSOR_RIGHT: return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_RIGHT; case KEY_FUNCTION_CURSOR_UP_JUMP: return BRL_BLK_PASSKEY + BRL_KEY_HOME; case KEY_FUNCTION_CURSOR_DOWN_JUMP: return BRL_BLK_PASSKEY + BRL_KEY_END; case KEY_FUNCTION_CURSOR_LEFT_JUMP: return BRL_BLK_PASSKEY + BRL_KEY_PAGE_UP; case KEY_FUNCTION_CURSOR_RIGHT_JUMP: return BRL_BLK_PASSKEY + BRL_KEY_PAGE_DOWN; case KEY_FUNCTION_F1: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 0; case KEY_FUNCTION_F2: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 1; case KEY_FUNCTION_F3: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 2; case KEY_FUNCTION_F4: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 3; case KEY_FUNCTION_F5: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 4; case KEY_FUNCTION_F6: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 5; case KEY_FUNCTION_F7: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 6; case KEY_FUNCTION_F9: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 8; case KEY_FUNCTION_F10: return BRL_BLK_PASSKEY + BRL_KEY_FUNCTION + 9; case KEY_COMMAND: { int command; while ((command = readKey()) == EOF) approximateDelay(1); logMessage(LOG_DEBUG, "Received command: (0x%2.2X) 0x%4.4X", KEY_COMMAND, command); switch (command) { case KEY_COMMAND: /* pressing the escape command twice will pass it through */ return BRL_BLK_PASSDOTS + translateInputCell(KEY_COMMAND); case KEY_COMMAND_SWITCHVT_PREV: return BRL_CMD_SWITCHVT_PREV; case KEY_COMMAND_SWITCHVT_NEXT: return BRL_CMD_SWITCHVT_NEXT; case KEY_COMMAND_SWITCHVT_1: return BRL_BLK_SWITCHVT + 0; case KEY_COMMAND_SWITCHVT_2: return BRL_BLK_SWITCHVT + 1; case KEY_COMMAND_SWITCHVT_3: return BRL_BLK_SWITCHVT + 2; case KEY_COMMAND_SWITCHVT_4: return BRL_BLK_SWITCHVT + 3; case KEY_COMMAND_SWITCHVT_5: return BRL_BLK_SWITCHVT + 4; case KEY_COMMAND_SWITCHVT_6: return BRL_BLK_SWITCHVT + 5; case KEY_COMMAND_SWITCHVT_7: return BRL_BLK_SWITCHVT + 6; case KEY_COMMAND_SWITCHVT_8: return BRL_BLK_SWITCHVT + 7; case KEY_COMMAND_SWITCHVT_9: return BRL_BLK_SWITCHVT + 8; case KEY_COMMAND_SWITCHVT_10: return BRL_BLK_SWITCHVT + 9; case KEY_COMMAND_PAGE_UP: return BRL_BLK_PASSKEY + BRL_KEY_PAGE_UP; case KEY_COMMAND_PAGE_DOWN: return BRL_BLK_PASSKEY + BRL_KEY_PAGE_DOWN; case KEY_COMMAND_PREFMENU: currentLine = 0; cursorRow = 0; cursorColumn = 31; sendCursorRow(); return BRL_CMD_PREFMENU; case KEY_COMMAND_PREFSAVE: return BRL_CMD_PREFSAVE; case KEY_COMMAND_PREFLOAD: return BRL_CMD_PREFLOAD; case KEY_COMMAND_FREEZE_ON: return BRL_CMD_FREEZE | BRL_FLG_TOGGLE_ON; case KEY_COMMAND_FREEZE_OFF: return BRL_CMD_FREEZE | BRL_FLG_TOGGLE_OFF; case KEY_COMMAND_RESTARTBRL: return BRL_CMD_RESTARTBRL; case KEY_COMMAND_DOWNLOAD: downloadFile(); break; default: logMessage(LOG_WARNING, "Unknown command: (0X%2.2X) 0X%4.4X", KEY_COMMAND, command); break; } break; } default: switch (key & KEY_MASK) { case KEY_UPDATE: handleUpdate(key >> KEY_SHIFT); break; case KEY_FUNCTION: logMessage(LOG_WARNING, "Unknown function: (0X%2.2X) 0X%4.4X", KEY_COMMAND, key>>KEY_SHIFT); break; default: { unsigned char dots = translateInputCell(key); logMessage(LOG_DEBUG, "Received character: 0X%2.2X dec=%d dots=%2.2X", key, key, dots); return BRL_BLK_PASSDOTS + dots; } } break; } } return EOF; }
static int awaitCursorMotion (RoutingData *routing, int direction) { int oldx = (routing->oldx = routing->curx); int oldy = (routing->oldy = routing->cury); long timeout = routing->timeSum / routing->timeCount; int moved = 0; TimeValue start; getCurrentTime(&start); while (1) { long time; approximateDelay(ROUTING_INTERVAL); time = millisecondsSince(&start) + 1; { int row = routing->cury + routing->verticalDelta; int bestRow = row; int bestLength = 0; do { ScreenCharacter buffer[routing->screenColumns]; if (!readScreenRow(routing, buffer, row)) break; { int before = routing->curx; int after = before; while (buffer[before].text == routing->rowBuffer[before].text) if (--before < 0) break; while (buffer[after].text == routing->rowBuffer[after].text) if (++after >= routing->screenColumns) break; { int length = after - before - 1; if (length > bestLength) { bestRow = row; if ((bestLength = length) == routing->screenColumns) break; } } } row -= direction; } while ((row >= 0) && (row < routing->screenRows)); routing->verticalDelta = bestRow - routing->cury; } oldy = routing->cury; oldx = routing->curx; if (!getCurrentPosition(routing)) return 0; if ((routing->cury != oldy) || (routing->curx != oldx)) { logRouting("moved: [%d,%d] -> [%d,%d]", oldx, oldy, routing->curx, routing->cury); if (!moved) { moved = 1; timeout = time * 2; routing->timeSum += time * 8; routing->timeCount += 1; } } else if (time > timeout) { if (!moved) { logRouting("timed out"); } break; } } return 1; }
GioEndpoint * gioConnectResource ( const char *identifier, const GioDescriptor *descriptor ) { GioEndpoint *endpoint; if ((endpoint = malloc(sizeof(*endpoint)))) { endpoint->bytesPerSecond = 0; endpoint->input.error = 0; endpoint->input.from = 0; endpoint->input.to = 0; endpoint->hidReportItems.address = NULL; endpoint->hidReportItems.size = 0; if (descriptor->serial.parameters) { if (isSerialDevice(&identifier)) { if ((endpoint->handle.serial.device = serialOpenDevice(identifier))) { if (serialSetParameters(endpoint->handle.serial.device, descriptor->serial.parameters)) { endpoint->methods = &serialMethods; endpoint->options = descriptor->serial.options; setBytesPerSecond(endpoint, descriptor->serial.parameters); goto connectSucceeded; } serialCloseDevice(endpoint->handle.serial.device); } goto connectFailed; } } if (descriptor->usb.channelDefinitions) { if (isUsbDevice(&identifier)) { if ((endpoint->handle.usb.channel = usbFindChannel(descriptor->usb.channelDefinitions, identifier))) { endpoint->methods = &usbMethods; endpoint->options = descriptor->usb.options; if (!endpoint->options.applicationData) { endpoint->options.applicationData = endpoint->handle.usb.channel->definition.data; } { UsbChannel *channel = endpoint->handle.usb.channel; const SerialParameters *parameters = channel->definition.serial; if (parameters) setBytesPerSecond(endpoint, parameters); } goto connectSucceeded; } goto connectFailed; } } if (descriptor->bluetooth.channelNumber) { if (isBluetoothDevice(&identifier)) { if ((endpoint->handle.bluetooth.connection = bthOpenConnection(identifier, descriptor->bluetooth.channelNumber, 0))) { endpoint->methods = &bluetoothMethods; endpoint->options = descriptor->bluetooth.options; goto connectSucceeded; } goto connectFailed; } } errno = ENOSYS; logMessage(LOG_WARNING, "unsupported input/output resource identifier: %s", identifier); connectFailed: free(endpoint); } else { logMallocError(); } return NULL; connectSucceeded: { int delay = endpoint->options.readyDelay; if (delay) approximateDelay(delay); } if (!gioDiscardInput(endpoint)) { int originalErrno = errno; gioDisconnectResource(endpoint); errno = originalErrno; return NULL; } return endpoint; }
static int awaitCursorMotion (RoutingData *routing, int direction, const CursorAxisEntry *axis) { int moved = 0; long int timeout = routing->timeSum / routing->timeCount; TimeValue start; int trgy = routing->cury; int trgx = routing->curx; routing->oldy = routing->cury; routing->oldx = routing->curx; axis->adjustCoordinate(&trgy, &trgx, direction); getMonotonicTime(&start); while (1) { long int time; TimeValue now; int oldy; int oldx; approximateDelay(ROUTING_INTERVAL); getMonotonicTime(&now); time = millisecondsBetween(&start, &now) + 1; { int row = routing->cury + routing->verticalDelta; int bestRow = row; int bestLength = 0; do { ScreenCharacter buffer[routing->screenColumns]; if (!readScreenRow(routing, buffer, row)) break; { int before = routing->curx; int after = before; while (buffer[before].text == routing->rowBuffer[before].text) if (--before < 0) break; while (buffer[after].text == routing->rowBuffer[after].text) if (++after >= routing->screenColumns) break; { int length = after - before - 1; if (length > bestLength) { bestRow = row; if ((bestLength = length) == routing->screenColumns) break; } } } row -= direction; } while ((row >= 0) && (row < routing->screenRows)); routing->verticalDelta = bestRow - routing->cury; } oldy = routing->cury; oldx = routing->curx; if (!getCurrentPosition(routing)) return 0; if ((routing->cury != oldy) || (routing->curx != oldx)) { logRouting("moved: [%d,%d] -> [%d,%d] (%dms)", oldx, oldy, routing->curx, routing->cury, time); if (!moved) { moved = 1; timeout = (time * 2) + 1; routing->timeSum += time * 8; routing->timeCount += 1; } if ((routing->cury == trgy) && (routing->curx == trgx)) break; if (ROUTING_INTERVAL) { start = now; } else { approximateDelay(1); getMonotonicTime(&start); } } else if (time > timeout) { if (!moved) logRouting("timed out: %ldms", timeout); break; } } return 1; }
int insertMidiWait (MidiDevice *midi, int duration) { approximateDelay(duration); return 1; }
void usleep (int usec) { if (usec > 0) { approximateDelay((usec+999)/1000); } }
static int brl_construct (BrailleDisplay *brl, char **parameters, const char *device) { short n, success; /* loop counters, flags, etc. */ unsigned char *init_seq = (unsigned char *)"\002\0330"; /* string to send to Braille to initialise: [ESC][0] */ unsigned char *init_ack = (unsigned char *)"\002\033V"; /* string to expect as acknowledgement: [ESC][V]... */ unsigned char c; TimePeriod period; if (!isSerialDevice(&device)) { unsupportedDevice(device); return 0; } brlcols = -1; /* length of braille display (auto-detected) */ prevdata = rawdata = NULL; /* clear pointers */ /* No need to load translation tables, as these are now * defined in tables.h */ /* Now open the Braille display device for random access */ if (!(MB_serialDevice = serialOpenDevice(device))) goto failure; if (!serialRestartDevice(MB_serialDevice, BAUDRATE)) goto failure; if (!serialSetFlowControl(MB_serialDevice, SERIAL_FLOW_HARDWARE)) goto failure; /* MultiBraille initialisation procedure: * [ESC][V][Braillelength][Software Version][CR] * I guess, they mean firmware version with software version :*} * firmware version == [Software Version] / 10.0 */ success = 0; if (init_seq[0]) if (serialWriteData (MB_serialDevice, init_seq + 1, init_seq[0]) != init_seq[0]) goto failure; startTimePeriod (&period, ACK_TIMEOUT); /* initialise timeout testing */ n = 0; do { approximateDelay (20); if (serialReadData (MB_serialDevice, &c, 1, 0, 0) == 0) continue; if (n < init_ack[0] && c != init_ack[1 + n]) continue; if (n == init_ack[0]) { brlcols = c, success = 1; /* reading version-info */ /* firmware version == [Software Version] / 10.0 */ serialReadData (MB_serialDevice, &c, 1, 0, 0); logMessage (LOG_INFO, "MultiBraille: Version: %2.1f", c/10.0); /* read trailing [CR] */ serialReadData (MB_serialDevice, &c, 1, 0, 0); } n++; } while (!afterTimePeriod (&period, NULL) && n <= init_ack[0]); if (success && (brlcols != 25)) { if ((prevdata = malloc(brl->textColumns * brl->textRows))) { if ((rawdata = malloc(20 + (brl->textColumns * brl->textRows * 2)))) { brl->textColumns = brlcols; brl->textRows = BRLROWS; brl->statusColumns = 5; brl->statusRows = 1; { static const DotsTable dots = { 0X01, 0X02, 0X04, 0X80, 0X40, 0X20, 0X08, 0X10 }; makeOutputTable(dots); } return 1; } else { logMallocError(); } free(prevdata); } else { logMallocError(); } } failure: if (MB_serialDevice) { serialCloseDevice(MB_serialDevice); MB_serialDevice = NULL; } return 0; }
static void spk_flush (void) { approximateDelay(spk_written * 1000 / CB_charactersPerSecond); spk_written = 0; }
int asyncExecuteIoCallback (AsyncIoData *iod, long int timeout) { if (iod) { Queue *functions = iod->functionQueue; unsigned int functionCount = functions? getQueueSize(functions): 0; prepareMonitors(); if (functionCount) { MonitorEntry monitorArray[functionCount]; MonitorGroup monitors = { .array = monitorArray, .count = 0 }; int executed = 0; Element *functionElement = processQueue(functions, addFunctionMonitor, &monitors); if (!functionElement) { if (!monitors.count) { approximateDelay(timeout); } else if (awaitMonitors(&monitors, timeout)) { functionElement = processQueue(functions, testFunctionMonitor, NULL); } } if (functionElement) { FunctionEntry *function = getElementItem(functionElement); Element *operationElement = getActiveOperationElement(function); OperationEntry *operation = getElementItem(operationElement); if (!operation->finished) finishOperation(operation); operation->active = 1; if (!function->methods->invokeCallback(operation)) operation->cancel = 1; operation->active = 0; executed = 1; if (operation->cancel) { deleteElement(operationElement); } else { operation->error = 0; } if ((operationElement = getActiveOperationElement(function))) { operation = getElementItem(operationElement); if (!operation->finished) startOperation(operation); requeueElement(functionElement); } else { deleteElement(functionElement); } } return executed; } } approximateDelay(timeout); return 0; } static void deallocateOperationEntry (void *item, void *data) { OperationEntry *operation = item; if (operation->extension) free(operation->extension); free(operation); }