static int readPacket (BrailleDisplay *brl, unsigned char *packet, int length) { size_t offset = 0; int size = -1; while (offset < length) { const unsigned char *byte = &packet[offset]; if (!serialReadChunk(serialDevice, packet, &offset, 1, 0, 1000)) { if (errno == EAGAIN) { if (!offset) return 0; logPartialPacket(packet, offset); } return -1; } if (offset == 1) { if (*byte) { logDiscardedByte(packet[0]); offset = 0; } } else { if (offset == 2) { switch (*byte) { default: size = 1; break; } size += offset; } if (offset == size) { logInputPacket(packet, offset); return offset; } } } logTruncatedPacket(packet, offset); return 0; }
static int readPacket (BrailleDisplay *brl, unsigned char *packet, int size) { int offset = 0; int length = 0; while (1) { unsigned char byte; if (!gioReadByte(brl->gioEndpoint, &byte, (offset > 0))) { if (offset > 0) logPartialPacket(packet, offset); return 0; } if (offset < size) { if (offset == 0) { switch (byte) { case BN_RSP_DISPLAY: length = 1; break; case BN_RSP_CHARACTER: case BN_RSP_SPACE: case BN_RSP_BACKSPACE: case BN_RSP_ENTER: case BN_RSP_THUMB: case BN_RSP_ROUTE: case BN_RSP_INPUT_CHAR: case BN_RSP_INPUT_VKEY: case BN_RSP_INPUT_RESET: case BN_RSP_QWERTY_KEY: case BN_RSP_QWERTY_MODS: length = 2; break; case BN_RSP_DESCRIBE: length = 3; break; default: logUnknownPacket(byte); offset = 0; length = 0; continue; } } packet[offset] = byte; } else { if (offset == size) logTruncatedPacket(packet, offset); logDiscardedByte(byte); } if (++offset == length) { if (offset > size) { offset = 0; length = 0; continue; } logInputPacket(packet, offset); return length; } } }
static size_t readPacket (BrailleDisplay *brl, void *packet, size_t size) { unsigned char *bytes = packet; size_t offset = 0; size_t length = 0; while (1) { unsigned char byte; { int started = offset > 0; if (!gioReadByte(brl->gioEndpoint, &byte, started)) { if (started) logPartialPacket(bytes, offset); return 0; } } gotByte: if (offset == 0) { switch (byte) { case 0XFC: length = 2; break; case 0XFD: length = 2; break; default: logIgnoredByte(byte); continue; } } else { int unexpected = 0; if (offset == 1) { if (bytes[0] == 0XFD) { switch (byte) { case 0X2F: length = 3; break; default: unexpected = 1; break; } } } if (unexpected) { logShortPacket(bytes, offset); offset = 0; length = 0; goto gotByte; } } if (offset < size) { bytes[offset] = byte; if (offset == (length - 1)) { logInputPacket(bytes, length); return length; } } else { if (offset == size) logTruncatedPacket(bytes, offset); logDiscardedByte(byte); } offset += 1; } }
static int readPacket (BrailleDisplay *brl, InputPacket *packet) { typedef enum { IPG_PRODUCT, IPG_KEY, IPG_DEFAULT } InputPacketGroup; InputPacketGroup group = IPG_DEFAULT; int length = 1; int offset = 0; while (1) { unsigned char byte; { int started = offset > 0; if (!readByte(&byte, started)) { if (started) logPartialPacket(packet->bytes, offset); return 0; } } gotByte: if (!offset) { switch (byte) { case IPT_KEY_NAVIGATION: case IPT_KEY_SIMULATION: case IPT_KEY_ROUTING: group = IPG_KEY; length = 4; break; default: if (byte == productPrefix[0]) { group = IPG_PRODUCT; length = sizeof(packet->product) - 1; } else { logIgnoredByte(byte); continue; } break; } } else { int unexpected = 0; switch (group) { case IPG_PRODUCT: if (offset < productPrefixLength) { if (byte != productPrefix[offset]) unexpected = 1; } else if (byte == '@') { length = offset + 1; } break; case IPG_KEY: if (offset == 1) { if (byte != packet->bytes[0]) unexpected = 1; } else if (offset == 3) { if (byte != 0X19) unexpected = 1; } break; default: break; } if (unexpected) { logShortPacket(packet->bytes, offset); group = IPG_DEFAULT; offset = 0; length = 1; goto gotByte; } } packet->bytes[offset++] = byte; if (offset == length) { if (group == IPG_PRODUCT) { packet->bytes[length] = 0; } logInputPacket(packet->bytes, offset); return length; } } }
static int readSerialPacket (BrailleDisplay *brl, unsigned char *packet, int size) { int started = 0; int escape = 0; int offset = 0; int length = 0; while (1) { unsigned char byte; if (!gioReadByte(brl->gioEndpoint, &byte, (started || escape))) { if (started) logPartialPacket(packet, offset); return 0; } if (byte == ESC) { if ((escape = !escape)) continue; } else if (escape) { escape = 0; if (offset > 0) { logShortPacket(packet, offset); offset = 0; length = 0; } else { started = 1; } } if (!started) { logIgnoredByte(byte); continue; } if (offset < size) { if (offset == 0) { switch (byte) { case 0X43: case 0X47: length = 2; break; case 0X4C: length = 3; break; case 0X46: case 0X48: length = 5; break; case 0X4B: length = 9; break; case 0X53: length = 10; break; default: logUnknownPacket(byte); started = 0; continue; } } packet[offset] = byte; } else { if (offset == size) logTruncatedPacket(packet, offset); logDiscardedByte(byte); } if (++offset == length) { if (offset > size) { offset = 0; length = 0; started = 0; continue; } logInputPacket(packet, offset); return length; } } }
static int readPacket (BrailleDisplay *brl, Packet *packet) { while (1) { int size = sizeof(PacketHeader); int hasPayload = 0; if (brl->data->inputCount >= sizeof(PacketHeader)) { if (brl->data->inputBuffer.packet.header.type & 0X80) { hasPayload = 1; size += brl->data->inputBuffer.packet.header.arg1 + 1; } } if (size <= brl->data->inputCount) { logInputPacket(brl->data->inputBuffer.bytes, size); if (hasPayload) { unsigned char checksum = 0; int index; for (index=0; index<size; index+=1) checksum -= brl->data->inputBuffer.bytes[index]; if (checksum) logMessage(LOG_WARNING, "Input packet checksum error."); } memcpy(packet, &brl->data->inputBuffer, size); memmove(&brl->data->inputBuffer.bytes[0], &brl->data->inputBuffer.bytes[size], brl->data->inputCount -= size); return size; } retry: { int count = gioReadData(brl->data->gioEndpoint, &brl->data->inputBuffer.bytes[brl->data->inputCount], size - brl->data->inputCount, 0); if (count < 1) { if (count == -1) { logSystemError("read"); } else if ((count == 0) && (brl->data->inputCount > 0)) { if (gioAwaitInput(brl->data->gioEndpoint, 1000)) goto retry; if (errno != EAGAIN) count = -1; logPartialPacket(brl->data->inputBuffer.bytes, brl->data->inputCount); brl->data->inputCount = 0; } return count; } brl->data->acknowledgementsMissing = 0; if (!brl->data->inputCount) { static const unsigned char packets[] = { PKT_ACK, PKT_NAK, PKT_KEY, PKT_EXTKEY, PKT_BUTTON, PKT_WHEEL, PKT_INFO }; int first; for (first=0; first<count; first+=1) if (memchr(packets, brl->data->inputBuffer.bytes[first], sizeof(packets))) break; if (first) { logDiscardedBytes(brl->data->inputBuffer.bytes, first); memmove(&brl->data->inputBuffer.bytes[0], &brl->data->inputBuffer.bytes[first], count-=first); } } brl->data->inputCount += count; } } }
size_t readBraillePacket ( BrailleDisplay *brl, GioEndpoint *endpoint, void *packet, size_t size, BraillePacketVerifier *verifyPacket, void *data ) { unsigned char *bytes = packet; size_t count = 0; size_t length = 1; if (!endpoint) endpoint = brl->gioEndpoint; while (1) { unsigned char byte; { int started = count > 0; if (!gioReadByte(endpoint, &byte, started)) { if (started) logPartialPacket(bytes, count); return 0; } } gotByte: if (count < size) { bytes[count++] = byte; { BraillePacketVerifierResult result = verifyPacket(brl, bytes, count, &length, data); switch (result) { case BRL_PVR_EXCLUDE: count -= 1; case BRL_PVR_INCLUDE: break; default: logMessage(LOG_WARNING, "unimplemented braille packet verifier result: %u", result); case BRL_PVR_INVALID: if (--count) { logShortPacket(bytes, count); count = 0; length = 1; goto gotByte; } logIgnoredByte(byte); continue; } } if (count == length) { logInputPacket(bytes, length); return length; } } else { if (count++ == size) logTruncatedPacket(bytes, size); logDiscardedByte(byte); } } }