2023-12-22 13:57:52 -05:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
|
|
|
|
|
|
#include "hal/LEDs.h"
|
|
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
2024-10-11 01:06:19 -04:00
|
|
|
#include <cstring>
|
2023-12-22 13:57:52 -05:00
|
|
|
#include <fstream>
|
|
|
|
|
|
2024-10-11 01:06:19 -04:00
|
|
|
#include <fmt/format.h>
|
|
|
|
|
#include <fmt/std.h>
|
2023-12-22 13:57:52 -05:00
|
|
|
#include <wpi/fs.h>
|
|
|
|
|
|
2024-10-11 01:06:19 -04:00
|
|
|
#include "HALInternal.h"
|
2023-12-22 13:57:52 -05:00
|
|
|
#include "hal/Errors.h"
|
|
|
|
|
|
|
|
|
|
namespace hal::init {
|
|
|
|
|
|
|
|
|
|
void InitializeLEDs() {
|
|
|
|
|
int32_t status = 0;
|
|
|
|
|
HAL_SetRadioLEDState(HAL_RadioLED_kOff, &status);
|
|
|
|
|
}
|
|
|
|
|
} // namespace hal::init
|
|
|
|
|
|
|
|
|
|
static const fs::path radioLEDGreenFilePath =
|
|
|
|
|
"/sys/class/leds/nilrt:wifi:primary/brightness";
|
|
|
|
|
static const fs::path radioLEDRedFilePath =
|
|
|
|
|
"/sys/class/leds/nilrt:wifi:secondary/brightness";
|
|
|
|
|
|
|
|
|
|
static const char* onStr = "1";
|
|
|
|
|
static const char* offStr = "0";
|
|
|
|
|
|
2024-10-11 01:06:19 -04:00
|
|
|
static bool ReadStateFromFile(fs::path path, int32_t* status) {
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
fs::file_t file = fs::OpenFileForRead(path, ec, fs::OF_Text);
|
|
|
|
|
if (ec) {
|
|
|
|
|
hal::SetLastError(status, fmt::format("Could not open '{}' for read: {}",
|
|
|
|
|
path, ec.message()));
|
|
|
|
|
*status = INCOMPATIBLE_STATE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// We only need to read one byte because the file won't have leading zeros.
|
|
|
|
|
char buf[1]{};
|
|
|
|
|
ssize_t count = read(file, buf, 1);
|
|
|
|
|
// save errno, always close file.
|
|
|
|
|
int err = errno;
|
|
|
|
|
fs::CloseFile(file);
|
|
|
|
|
if (count <= 0) {
|
|
|
|
|
*status = INCOMPATIBLE_STATE;
|
|
|
|
|
if (count == 0) {
|
|
|
|
|
hal::SetLastError(status,
|
|
|
|
|
fmt::format("Read from '{}' returned no data.", path));
|
|
|
|
|
} else {
|
|
|
|
|
hal::SetLastError(status, fmt::format("Failed to read from '{}': {}",
|
|
|
|
|
path, std::strerror(err)));
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// If the brightness is not zero, the LED is on.
|
|
|
|
|
return buf[0] != '0';
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-22 13:57:52 -05:00
|
|
|
extern "C" {
|
|
|
|
|
void HAL_SetRadioLEDState(HAL_RadioLEDState state, int32_t* status) {
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
fs::file_t greenFile = fs::OpenFileForWrite(radioLEDGreenFilePath, ec,
|
|
|
|
|
fs::CD_OpenExisting, fs::OF_Text);
|
|
|
|
|
if (ec) {
|
2024-10-11 01:06:19 -04:00
|
|
|
// not opened, nothing to clean up
|
2023-12-22 13:57:52 -05:00
|
|
|
*status = INCOMPATIBLE_STATE;
|
2024-10-11 01:06:19 -04:00
|
|
|
hal::SetLastError(status, fmt::format("Could not open '{}' for write: {}",
|
|
|
|
|
greenFile, ec.message()));
|
2023-12-22 13:57:52 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
fs::file_t redFile = fs::OpenFileForWrite(radioLEDRedFilePath, ec,
|
|
|
|
|
fs::CD_OpenExisting, fs::OF_Text);
|
|
|
|
|
if (ec) {
|
2024-10-11 01:06:19 -04:00
|
|
|
// green file opened successfully, need to close it
|
|
|
|
|
fs::CloseFile(greenFile);
|
2023-12-22 13:57:52 -05:00
|
|
|
*status = INCOMPATIBLE_STATE;
|
2024-10-11 01:06:19 -04:00
|
|
|
hal::SetLastError(status, fmt::format("Could not open '{}' for write: {}",
|
|
|
|
|
greenFile, ec.message()));
|
2023-12-22 13:57:52 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
write(greenFile, state & HAL_RadioLED_kGreen ? onStr : offStr, 1);
|
|
|
|
|
write(redFile, state & HAL_RadioLED_kRed ? onStr : offStr, 1);
|
|
|
|
|
|
|
|
|
|
fs::CloseFile(greenFile);
|
|
|
|
|
fs::CloseFile(redFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HAL_RadioLEDState HAL_GetRadioLEDState(int32_t* status) {
|
|
|
|
|
bool green = ReadStateFromFile(radioLEDGreenFilePath, status);
|
|
|
|
|
bool red = ReadStateFromFile(radioLEDRedFilePath, status);
|
|
|
|
|
if (*status == 0) {
|
|
|
|
|
if (green && red) {
|
|
|
|
|
return HAL_RadioLED_kOrange;
|
|
|
|
|
} else if (green) {
|
|
|
|
|
return HAL_RadioLED_kGreen;
|
|
|
|
|
} else if (red) {
|
|
|
|
|
return HAL_RadioLED_kRed;
|
|
|
|
|
} else {
|
|
|
|
|
return HAL_RadioLED_kOff;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return HAL_RadioLED_kOff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} // extern "C"
|