blob: 5b731a00825efb1172c962ca2eb36b93692e325c [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Speed translation utilities for termios.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_TERMIOS_LINUX_SPEED_UTILS_H
#define LLVM_LIBC_SRC_TERMIOS_LINUX_SPEED_UTILS_H
#include "hdr/termios_macros.h"
#include "hdr/types/speed_t.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
constexpr speed_t INVALID_SPEED = ~static_cast<speed_t>(0);
// glibc 2.42 changed the behavior of the termios Bxxx constants:
// - Before glibc 2.42, the Bxxx constants correspond to the kernel speed
// bitmasks
// directly (e.g. B50 = 1).
// - Starting from glibc 2.42, to support arbitrary baud rates numerically, the
// Bxxx constants are defined as their actual integer values (e.g. B50 = 50).
// In this case, we need to translate between the host's numerical speeds and
// the kernel's speed bitmasks.
// - If B50 == 1, then the host uses the kernel's bitmasks directly (no
// translation).
// - If B50 is not 1 (e.g. B50 == 50 in glibc >= 2.42), we apply
// translation.
#if (B50 == 1)
LIBC_INLINE constexpr speed_t encode_speed(speed_t speed) { return speed; }
LIBC_INLINE constexpr speed_t decode_speed(speed_t speed) { return speed; }
#else // Overlay mode with numerical speeds (e.g. glibc)
LIBC_INLINE constexpr speed_t encode_speed(speed_t speed) {
switch (speed) {
case 0:
return 0;
case 50:
return 0000001;
case 75:
return 0000002;
case 110:
return 0000003;
case 134:
return 0000004;
case 150:
return 0000005;
case 200:
return 0000006;
case 300:
return 0000007;
case 600:
return 0000010;
case 1200:
return 0000011;
case 1800:
return 0000012;
case 2400:
return 0000013;
case 4800:
return 0000014;
case 9600:
return 0000015;
case 19200:
return 0000016;
case 38400:
return 0000017;
case 57600:
return 0010001;
case 115200:
return 0010002;
case 230400:
return 0010003;
case 460800:
return 0010004;
case 500000:
return 0010005;
case 576000:
return 0010006;
case 921600:
return 0010007;
case 1000000:
return 0010010;
case 1152000:
return 0010011;
case 1500000:
return 0010012;
case 2000000:
return 0010013;
case 2500000:
return 0010014;
case 3000000:
return 0010015;
case 3500000:
return 0010016;
case 4000000:
return 0010017;
default:
return INVALID_SPEED;
}
}
LIBC_INLINE constexpr speed_t decode_speed(speed_t kernel_speed) {
switch (kernel_speed) {
case 0:
return 0;
case 0000001:
return 50;
case 0000002:
return 75;
case 0000003:
return 110;
case 0000004:
return 134;
case 0000005:
return 150;
case 0000006:
return 200;
case 0000007:
return 300;
case 0000010:
return 600;
case 0000011:
return 1200;
case 0000012:
return 1800;
case 0000013:
return 2400;
case 0000014:
return 4800;
case 0000015:
return 9600;
case 0000016:
return 19200;
case 0000017:
return 38400;
case 0010001:
return 57600;
case 0010002:
return 115200;
case 0010003:
return 230400;
case 0010004:
return 460800;
case 0010005:
return 500000;
case 0010006:
return 576000;
case 0010007:
return 921600;
case 0010010:
return 1000000;
case 0010011:
return 1152000;
case 0010012:
return 1500000;
case 0010013:
return 2000000;
case 0010014:
return 2500000;
case 0010015:
return 3000000;
case 0010016:
return 3500000;
case 0010017:
return 4000000;
default:
return kernel_speed;
}
}
#endif // (B50 == 1)
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_TERMIOS_LINUX_SPEED_UTILS_H