static size_t readPacket (BrailleDisplay *brl, InputPacket *packet) { const size_t length = 10; size_t offset = 0; while (1) { unsigned char byte; { int started = offset > 0; if (!gioReadByte(brl->gioEndpoint, &byte, started)) { if (started) logPartialPacket(packet->bytes, offset); return 0; } } if (!offset) { if (byte != 0XFA) { logIgnoredByte(byte); continue; } } packet->bytes[offset++] = byte; if (offset == length) { if (byte == 0XFB) { { int checksum = -packet->data.checksum; { size_t i; for (i=0; i<offset; i+=1) checksum += packet->bytes[i]; } if ((checksum & 0XFF) != packet->data.checksum) { logInputProblem("Incorrect Input Checksum", packet->bytes, offset); } } logInputPacket(packet->bytes, offset); return length; } { const unsigned char *start = memchr(packet->bytes+1, packet->bytes[0], offset-1); const unsigned char *end = packet->bytes + offset; if (!start) start = end; logDiscardedBytes(packet->bytes, start-packet->bytes); memmove(packet->bytes, start, (offset = end - start)); } } } }
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; } } }