static int brl_construct (BrailleDisplay *brl, char **parameters, const char *device) { if (!isSerialDevice(&device)) { unsupportedDevice(device); return 0; } if ((serialDevice = serialOpenDevice(device))) { if (serialRestartDevice(serialDevice, serialBaud)) { static const unsigned char request[] = {BNO_DESCRIBE}; charactersPerSecond = serialBaud / 10; if (writePacket(brl, request, sizeof(request)) != -1) { while (serialAwaitInput(serialDevice, 100)) { ResponsePacket response; int size = getPacket(&response); if (size) { if (response.data.code == BNI_DESCRIBE) { statusCells = response.data.values.description.statusCells; brl->textColumns = response.data.values.description.textCells; brl->textRows = 1; brl->keyBindings = "keys"; if ((statusCells == 5) && (brl->textColumns == 30)) { statusCells -= 2; brl->textColumns += 2; } dataCells = brl->textColumns * brl->textRows; cellCount = statusCells + dataCells; makeOutputTable(dotsTable_ISO11548_1); makeInputTable(); if ((cellBuffer = malloc(cellCount))) { memset(cellBuffer, 0, cellCount); statusArea = cellBuffer; dataArea = statusArea + statusCells; refreshCells(brl); persistentKeyboardMode = KBM_NAVIGATE; temporaryKeyboardMode = persistentKeyboardMode; persistentRoutingOperation = BRL_BLK_ROUTE; temporaryRoutingOperation = persistentRoutingOperation; return 1; } else { logSystemError("cell buffer allocation"); } } else { logUnexpectedPacket(response.bytes, size); } } } } } serialCloseDevice(serialDevice); serialDevice = NULL; } return 0; }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { ResponsePacket packet; int size; while ((size = getPacket(&packet))) { switch (packet.data.code) { case BN_RSP_ROUTE: enqueueKey(BN_SET_RoutingKeys, packet.data.values.routingKey); break; case BN_RSP_DISPLAY: doVisualDisplay(); break; default: { unsigned char set = BN_SET_NavigationKeys; unsigned char keys = packet.data.values.dotKeys & 0X3F; unsigned char base = BN_KEY_Dot1; unsigned char modifier = 0; switch (packet.data.code) { case BN_RSP_CHARACTER: if (keys) break; case BN_RSP_SPACE: modifier = BN_KEY_Space; break; case BN_RSP_BACKSPACE: modifier = BN_KEY_Backspace; break; case BN_RSP_ENTER: modifier = BN_KEY_Enter; break; case BN_RSP_THUMB: keys = packet.data.values.thumbKeys & 0X0F; base = BN_KEY_Previous; break; default: logUnexpectedPacket(packet.bytes, size); continue; } if (modifier) enqueueKeyEvent(set, modifier, 1); enqueueKeys(keys, set, base); if (modifier) enqueueKeyEvent(set, modifier, 0); break; } } } return (errno == EAGAIN)? EOF: BRL_CMD_RESTARTBRL; }
int probeBrailleDisplay ( BrailleDisplay *brl, unsigned int retryLimit, GioEndpoint *endpoint, int inputTimeout, BrailleRequestWriter *writeRequest, BraillePacketReader *readPacket, void *responsePacket, size_t responseSize, BrailleResponseHandler *handleResponse ) { unsigned int retryCount = 0; if (!endpoint) endpoint = brl->gioEndpoint; while (writeRequest(brl)) { drainBrailleOutput(brl, 0); while (gioAwaitInput(endpoint, inputTimeout)) { size_t size = readPacket(brl, responsePacket, responseSize); if (!size) break; { BrailleResponseResult result = handleResponse(brl, responsePacket, size); switch (result) { case BRL_RSP_DONE: return 1; case BRL_RSP_UNEXPECTED: logUnexpectedPacket(responsePacket, size); case BRL_RSP_CONTINUE: break; default: logMessage(LOG_WARNING, "unimplemented braille response result: %u", result); case BRL_RSP_FAIL: return 0; } } } if (errno != EAGAIN) #ifdef ETIMEDOUT if (errno != ETIMEDOUT) #endif /* ETIMEDOUT */ break; if (retryCount == retryLimit) break; retryCount += 1; } return 0; }
static int nextSerialPacket (BrailleDisplay *brl, unsigned char code, unsigned char *buffer, int size, int wait) { int length; if (wait) if (!awaitBrailleInput(brl, SERIAL_WAIT_TIMEOUT)) return 0; while ((length = readSerialPacket(brl, buffer, size))) { if (buffer[0] == code) return length; logUnexpectedPacket(buffer, length); } return 0; }
static int nextSerialPacket (unsigned char code, unsigned char *buffer, int size, int wait) { int length; if (wait) if (!gioAwaitInput(gioEndpoint, SERIAL_WAIT_TIMEOUT)) return 0; while ((length = readSerialPacket(buffer, size))) { if (buffer[0] == code) return length; logUnexpectedPacket(buffer, length); } return 0; }
/* for BRL_ROUTING, the code is the ofset to route, starting from 0 */ static int brl_readKey(BrailleDisplay *brl) { unsigned char ch, packet[MAXPACKETSIZE]; static int routing = 0; ssize_t packetSize; packetSize = brl_readPacket(brl,packet,sizeof(packet)); if (packetSize==0) return EOF; if ((packet[0]!=0x3c) && (packet[0]!=0x3d) && (packet[0]!=0x23)) { logUnexpectedPacket(packet, packetSize); return EOF; } ch = packet[1]; if (routing) { routing=0; if (ch>=0xc0) return (packet[1]-0xc0) | BRL_VSMSK_ROUTING; return EOF; } if ((ch>=0xc0) && (ch<=0xdf)) return (ch-0xc0) | BRL_VSMSK_FUNCTIONKEY; if (ch==0x91) { routing = 1; return BRL_CMD_NOOP; } if ((ch>=0x20) && (ch<=0x9e)) { switch (ch) { case 0x80: ch = 0xc7; break; case 0x81: ch = 0xfc; break; case 0x82: ch = 0xe9; break; case 0x83: ch = 0xe2; break; case 0x84: ch = 0xe4; break; case 0x85: ch = 0xe0; break; case 0x87: ch = 0xe7; break; case 0x88: ch = 0xea; break; case 0x89: ch = 0xeb; break; case 0x8a: ch = 0xe8; break; case 0x8b: ch = 0xef; break; case 0x8c: ch = 0xee; break; case 0x8f: ch = 0xc0; break; case 0x93: ch = 0xf4; break; case 0x94: ch = 0xf6; break; case 0x96: ch = 0xfb; break; case 0x97: ch = 0xf9; break; case 0x9e: ch = 0x60; break; } return ch | BRL_VSMSK_CHAR; } return ch | BRL_VSMSK_OTHER; }
static int startDisplayMode (BrailleDisplay *brl) { static const unsigned char data[] = {MM_BLINK_NO, 0}; if (writePacket(brl, MM_CMD_StartDisplayMode, 0, data, sizeof(data))) { if (gioAwaitInput(brl->gioEndpoint, START_INPUT_TIMEOUT)) { MM_CommandPacket response; size_t size = readPacket(brl, &response); if (size) { if (response.fields.header.id1 == MM_HEADER_ACK) return 1; logUnexpectedPacket(response.bytes, size); } } } return 0; }
static int identifyDisplay (BrailleDisplay *brl) { static const unsigned char identify[] = {'I', CR}; if (writeBytes(brl, identify, sizeof(identify))) { if (serialAwaitInput(serialDevice, 1000)) { unsigned char identity[0X100]; size_t length; if (readBytes(identity, sizeof(identity), &length)) { static const unsigned char prefix[] = {'b', 'r', 'a', 'u', 'd', 'i', ' '}; if ((length >= sizeof(prefix)) && (memcmp(identity, prefix, sizeof(prefix)) == 0)) { const unsigned char *bytes = memchr(identity, ',', length); if (bytes) { int count = length - (bytes - identity); int cells; ++bytes, --count; skipCharacter(' ', &bytes, &count); if (interpretNumber(&cells, &bytes, &count)) { if (!count) { logMessage(LOG_INFO, "Detected: %.*s", (int)length, identity); brl->textColumns = cells; brl->textRows = 1; return 1; } } } } logUnexpectedPacket(identity, length); } } } return 0; }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { unsigned char packet[MAXIMUM_RESPONSE_SIZE]; size_t size; while ((size = readPacket(brl, packet, sizeof(packet)))) { switch (packet[0]) { case 0XFD: switch (packet[1]) { case 0X2F: continue; default: break; } break; case 0XFC: { unsigned int key = packet[1]; if ((key >= NP_KEY_ROUTING_MIN) && (key <= NP_KEY_ROUTING_MAX)) { enqueueKey(brl, NP_GRP_RoutingKeys, (key - NP_KEY_ROUTING_MIN)); continue; } else { int press = !!(key & NP_KEY_NAVIGATION_PRESS); if (press) key &= ~NP_KEY_NAVIGATION_PRESS; enqueueKeyEvent(brl, NP_GRP_NavigationKeys, key, press); continue; } break; } } logUnexpectedPacket(packet, size); } return (errno == EAGAIN)? EOF: BRL_CMD_RESTARTBRL; }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { InputPacket packet; int length; if (context == KTB_CTX_WAITING) return BRL_CMD_NOOP; if (writeFunction) return EOF; while (*initialCommand != EOF) enqueueCommand(*initialCommand++); while ((length = readPacket(brl, &packet))) { if ((packet.data.type >= IPT_MINIMUM_LINE) && (packet.data.type <= IPT_MAXIMUM_LINE)) { enqueueCommand(BRL_CMD_BLK(GOTOLINE) | BRL_FLG_MOTION_TOLEFT | (packet.data.type - IPT_MINIMUM_LINE)); writeFunction = writeLine; return EOF; } switch (packet.data.type) { case IPT_SEARCH_ATTRIBUTE: case IPT_CURRENT_LINE: enqueueCommand(BRL_CMD_HOME); enqueueCommand(BRL_CMD_LNBEG); writeFunction = writeLine; return EOF; case IPT_CURRENT_LOCATION: writeFunction = writeLocation; return EOF; default: logUnexpectedPacket(&packet, length); break; } } return (errno == EAGAIN)? EOF: BRL_CMD_RESTARTBRL; }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { while (1) { unsigned char packet[3]; int size = readPacket(brl, packet, sizeof(packet)); if (size == 0) break; if (size < 0) return BRL_CMD_RESTARTBRL; switch (packet[1]) { default: break; case 1: return BRL_BLK_PASSDOTS | translateInputCell(packet[2]); case 2: { unsigned char column = packet[2]; if (column && (column <= brl->textColumns)) return BRL_BLK_ROUTE + (column - 1); break; } case 3: switch (packet[2]) { default: break; // left rear: two columns, one row case 0X02: // ESC return BRL_CMD_LEARN; case 0X01: // M return BRL_CMD_PREFMENU; // left middle: cross case 0X06: // up return BRL_CMD_LNUP; case 0X03: // left return BRL_CMD_FWINLT; case 0X05: // right return BRL_CMD_FWINRT; case 0X04: // down return BRL_CMD_LNDN; // left front: two columns, three rows case 0X09: // ins return BRL_CMD_RETURN; case 0X0A: // E return BRL_CMD_TOP; case 0X0B: // supp return BRL_CMD_CSRTRK; case 0X0C: // L return BRL_CMD_BOT; case 0X07: // extra 1 (40s only) return BRL_CMD_CHRLT; case 0X08: // extra 2 (40s only) return BRL_CMD_CHRRT; case 0x0E: // left thumb return BRL_BLK_PASSKEY + BRL_KEY_BACKSPACE; case 0x0F: // right thumb return BRL_BLK_PASSDOTS; case 0x3F: // both thumbs return BRL_BLK_PASSKEY + BRL_KEY_ENTER; case 0X29: // key under dot 7 return BRL_BLK_PASSKEY + BRL_KEY_ESCAPE; case 0X2A: // key under dot 8 return BRL_BLK_PASSKEY + BRL_KEY_TAB; // right rear: one column, one row case 0X19: // extra 3 (40s only) return BRL_CMD_INFO; // right middle: one column, two rows case 0X1B: // extra 4 (40s only) return BRL_CMD_PRDIFLN; case 0X1A: // extra 5 (40s only) return BRL_CMD_NXDIFLN; // right front: one column, four rows case 0X2B: // slash (40s only) return BRL_CMD_FREEZE; case 0X2C: // asterisk (40s only) return BRL_CMD_DISPMD; case 0X2D: // minus (40s only) return BRL_CMD_ATTRVIS; case 0X2E: // plus (40s only) return BRL_CMD_CSRVIS; // first (top) row of numeric pad case 0X37: // seven (40s only) return BRL_BLK_PASSKEY + BRL_KEY_HOME; case 0X38: // eight (40s only) return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_UP; case 0X39: // nine (40s only) return BRL_BLK_PASSKEY + BRL_KEY_PAGE_UP; // second row of numeric pad case 0X34: // four (40s only) return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_LEFT; case 0X35: // five (40s only) return BRL_CMD_CSRJMP_VERT; case 0X36: // six (40s only) return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_RIGHT; // third row of numeric pad case 0X31: // one (40s only) return BRL_BLK_PASSKEY + BRL_KEY_END; case 0X32: // two (40s only) return BRL_BLK_PASSKEY + BRL_KEY_CURSOR_DOWN; case 0X33: // three (40s only) return BRL_BLK_PASSKEY + BRL_KEY_PAGE_DOWN; // fourth (bottom) row of numeric pad case 0X28: // verr num (40s only) return BRL_CMD_SIXDOTS; case 0X30: // zero (40s only) return BRL_BLK_PASSKEY + BRL_KEY_INSERT; case 0X2F: // supp (40s only) return BRL_BLK_PASSKEY + BRL_KEY_DELETE; } break; /* When data is written to the display it acknowledges with: * 0X00 0X04 0Xxx * where xx is the number of bytes written. */ case 4: continue; } logUnexpectedPacket(packet, size); } return EOF; }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { ResponsePacket packet; int size; while ((size = getPacket(&packet))) { int (*handler)(BrailleDisplay *, unsigned char, KeyTableCommandContext); unsigned char data; switch (packet.data.code) { case BNI_CHARACTER: handler = interpretCharacter; data = packet.data.values.dotKeys; break; case BNI_SPACE: handler = interpretSpaceChord; data = packet.data.values.dotKeys; break; case BNI_BACKSPACE: handler = interpretBackspaceChord; data = packet.data.values.dotKeys; break; case BNI_ENTER: handler = interpretEnterChord; data = packet.data.values.dotKeys; break; case BNI_THUMB: handler = interpretThumbKeys; data = packet.data.values.thumbKeys; break; case BNI_ROUTE: handler = interpretRoutingKey; data = packet.data.values.routingKey; break; case BNI_DISPLAY: handler = visualDisplay; data = 0; break; default: logUnexpectedPacket(packet.bytes, size); continue; } currentKeyboardMode = temporaryKeyboardMode; temporaryKeyboardMode = persistentKeyboardMode; currentRoutingOperation = temporaryRoutingOperation; temporaryRoutingOperation = persistentRoutingOperation; return handler(brl, data, context); } return (errno == EAGAIN)? EOF: BRL_CMD_RESTARTBRL; }
static int brl_readCommand (BrailleDisplay *brl, KeyTableCommandContext context) { unsigned char buffer[0X100]; size_t length; while (readBytes(buffer, sizeof(buffer), &length)) { const unsigned char *bytes = buffer; int count = length; if (count > 0) { unsigned char category = *bytes++; --count; switch (category) { case 'F': { int keys; writeAcknowledgement(brl); if (interpretNumber(&keys, &bytes, &count)) { if (!count) { switch (keys) { case 1: return BRL_CMD_TOP_LEFT; case 2: return BRL_CMD_FWINLT; case 3: return BRL_CMD_LNDN; case 4: return BRL_CMD_LNUP; case 5: return BRL_CMD_FWINRT; case 6: return BRL_CMD_BOT_LEFT; case 23: return BRL_CMD_LNBEG; case 56: return BRL_CMD_LNEND; case 14: return BRL_CMD_CSRVIS; case 25: return BRL_CMD_DISPMD; case 26: return BRL_CMD_INFO; case 36: return BRL_CMD_HOME; } } } break; } case 'K': { int key; writeAcknowledgement(brl); if (interpretNumber(&key, &bytes, &count)) { if (!count) { if ((key > 0) && (key <= brl->textColumns)) return BRL_BLK_ROUTE + (key - 1); } } break; } } } logUnexpectedPacket(buffer, length); } if (errno == EAGAIN) return EOF; return BRL_CMD_RESTARTBRL; }