| /* |
| * BRLTTY - A background process providing access to the console screen (when in |
| * text mode) for a blind person using a refreshable braille display. |
| * |
| * Copyright (C) 1995-2023 by The BRLTTY Developers. |
| * |
| * BRLTTY comes with ABSOLUTELY NO WARRANTY. |
| * |
| * This is free software, placed under the terms of the |
| * GNU Lesser General Public License, as published by the Free Software |
| * Foundation; either version 2.1 of the License, or (at your option) any |
| * later version. Please see the file LICENSE-LGPL for details. |
| * |
| * Web Page: http://brltty.app/ |
| * |
| * This software is maintained by Dave Mielke <dave@mielke.cc>. |
| */ |
| |
| #include "prologue.h" |
| |
| #include <errno.h> |
| |
| #include "log.h" |
| #include "timing.h" |
| |
| #include "serial_grub.h" |
| #include "serial_internal.h" |
| |
| #define SERIAL_NO_BYTE -1 |
| |
| #define SERIAL_BAUD_ENTRY(baud) {(baud), (baud)} |
| |
| BEGIN_SERIAL_BAUD_TABLE |
| SERIAL_BAUD_ENTRY( 110), |
| SERIAL_BAUD_ENTRY( 150), |
| SERIAL_BAUD_ENTRY( 300), |
| SERIAL_BAUD_ENTRY( 600), |
| SERIAL_BAUD_ENTRY( 1200), |
| SERIAL_BAUD_ENTRY( 2400), |
| SERIAL_BAUD_ENTRY( 4800), |
| SERIAL_BAUD_ENTRY( 9600), |
| SERIAL_BAUD_ENTRY( 19200), |
| SERIAL_BAUD_ENTRY( 38400), |
| SERIAL_BAUD_ENTRY( 57600), |
| SERIAL_BAUD_ENTRY(115200), |
| END_SERIAL_BAUD_TABLE |
| |
| void |
| serialPutInitialAttributes (SerialAttributes *attributes) { |
| } |
| |
| int |
| serialPutSpeed (SerialAttributes *attributes, SerialSpeed speed) { |
| attributes->speed = speed; |
| return 1; |
| } |
| |
| int |
| serialPutDataBits (SerialAttributes *attributes, unsigned int bits) { |
| if ((bits < 5) || (bits > 8)) return 0; |
| attributes->word_len = bits; |
| return 1; |
| } |
| |
| int |
| serialPutStopBits (SerialAttributes *attributes, SerialStopBits bits) { |
| switch (bits) { |
| case SERIAL_STOP_1: |
| attributes->stop_bits = GRUB_SERIAL_STOP_BITS_1; |
| break; |
| |
| case SERIAL_STOP_2: |
| attributes->stop_bits = GRUB_SERIAL_STOP_BITS_2; |
| break; |
| |
| default: |
| return 0; |
| } |
| |
| return 1; |
| } |
| |
| int |
| serialPutParity (SerialAttributes *attributes, SerialParity parity) { |
| switch (parity) { |
| case SERIAL_PARITY_NONE: |
| attributes->parity = GRUB_SERIAL_PARITY_NONE; |
| break; |
| |
| case SERIAL_PARITY_ODD: |
| attributes->parity = GRUB_SERIAL_PARITY_ODD; |
| break; |
| |
| case SERIAL_PARITY_EVEN: |
| attributes->parity = GRUB_SERIAL_PARITY_EVEN; |
| break; |
| |
| default: |
| return 0; |
| } |
| |
| return 1; |
| } |
| |
| SerialFlowControl |
| serialPutFlowControl (SerialAttributes *attributes, SerialFlowControl flow) { |
| return flow; |
| } |
| |
| int |
| serialPutModemState (SerialAttributes *attributes, int enabled) { |
| return 0; |
| } |
| |
| unsigned int |
| serialGetDataBits (const SerialAttributes *attributes) { |
| return attributes->word_len; |
| } |
| |
| unsigned int |
| serialGetStopBits (const SerialAttributes *attributes) { |
| switch (attributes->stop_bits) { |
| case GRUB_SERIAL_STOP_BITS_1: return 1; |
| case GRUB_SERIAL_STOP_BITS_2: return 2; |
| default: return 0; |
| } |
| } |
| |
| unsigned int |
| serialGetParityBits (const SerialAttributes *attributes) { |
| return (attributes->parity == GRUB_SERIAL_PARITY_NONE)? 0: 1; |
| } |
| |
| int |
| serialGetAttributes (SerialDevice *serial, SerialAttributes *attributes) { |
| *attributes = serial->package.port->config; |
| return 1; |
| } |
| |
| int |
| serialPutAttributes (SerialDevice *serial, const SerialAttributes *attributes) { |
| grub_err_t result = serial->package.port->driver->configure(serial->package.port, attributes); |
| if (result == GRUB_ERR_NONE) return 1; |
| return 0; |
| } |
| |
| int |
| serialCancelInput (SerialDevice *serial) { |
| return 1; |
| } |
| |
| int |
| serialCancelOutput (SerialDevice *serial) { |
| return 1; |
| } |
| |
| int |
| serialMonitorInput (SerialDevice *serial, AsyncMonitorCallback *callback, void *data) { |
| return 0; |
| } |
| |
| 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; |
| } |
| |
| int |
| serialDrainOutput (SerialDevice *serial) { |
| return 1; |
| } |
| |
| ssize_t |
| serialGetData ( |
| SerialDevice *serial, |
| void *buffer, size_t size, |
| int initialTimeout, int subsequentTimeout |
| ) { |
| unsigned char *byte = buffer; |
| const unsigned char *const first = byte; |
| const unsigned char *const end = first + size; |
| int timeout = initialTimeout; |
| |
| while (byte < end) { |
| if (!serialPollInput(serial, timeout)) break; |
| *byte++ = serial->package.byte; |
| serial->package.byte = SERIAL_NO_BYTE; |
| timeout = subsequentTimeout; |
| } |
| |
| { |
| size_t count = byte - first; |
| if (count) return count; |
| } |
| |
| errno = EAGAIN; |
| return -1; |
| } |
| |
| ssize_t |
| serialPutData ( |
| SerialDevice *serial, |
| const void *data, size_t size |
| ) { |
| const unsigned char *byte = data; |
| const unsigned char *end = byte + size; |
| |
| while (byte < end) { |
| serial->package.port->driver->put(serial->package.port, *byte++); |
| } |
| |
| return size; |
| } |
| |
| int |
| serialGetLines (SerialDevice *serial) { |
| errno = ENOSYS; |
| return 0; |
| } |
| |
| int |
| serialPutLines (SerialDevice *serial, SerialLines high, SerialLines low) { |
| errno = ENOSYS; |
| return 0; |
| } |
| |
| int |
| serialRegisterWaitLines (SerialDevice *serial, SerialLines lines) { |
| return 1; |
| } |
| |
| int |
| serialMonitorWaitLines (SerialDevice *serial) { |
| return 0; |
| } |
| |
| int |
| serialConnectDevice (SerialDevice *serial, const char *device) { |
| if ((serial->package.port = grub_serial_find(device))) { |
| serial->package.byte = SERIAL_NO_BYTE; |
| |
| if (serialPrepareDevice(serial)) { |
| logMessage(LOG_CATEGORY(SERIAL_IO), "device opened: %s", |
| device); |
| return 1; |
| } |
| } else { |
| logMessage(LOG_ERR, "cannot find serial device: %s", device); |
| errno = ENOENT; |
| } |
| |
| return 0; |
| } |
| |
| void |
| serialDisconnectDevice (SerialDevice *serial) { |
| serial->package.port = NULL; |
| } |
| |
| int |
| serialEnsureFileDescriptor (SerialDevice *serial) { |
| return 1; |
| } |
| |
| void |
| serialClearError (SerialDevice *serial) { |
| } |
| |