Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ struct Option {
void *hoverPointer;
bool hovered; // return to the remote (webui or app) if it is hovered on the loopoptions

// Optional trailing icons drawn by loopOptions (opt-in; both default to
// "off" so existing menus are unchanged):
// iconRssi != 0 -> four-bar signal meter for that dBm value
// iconLock: 0 none, 1 locked/secured, 2 open
int iconRssi = 0;
uint8_t iconLock = 0;

Option(
const char *lbl, const std::function<void()> &op, bool sel = false,
bool (*hov)(void *hoverPointer, bool shouldRender) = nullptr, void *ptr = nullptr, bool hvrd = false,
Expand Down
53 changes: 51 additions & 2 deletions src/core/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,18 @@ Opt_Coord drawOptions(
else tft.setTextColor(fgcolor, bgcolor);
if (!options[i].enabled) tft.setTextColor(TFT_DARKGREY, bgcolor);

// Reserve room on the right for any opt-in trailing icons
int iconReserve = 0;
if (options[i].iconRssi != 0) iconReserve += 14;
if (options[i].iconLock != 0) iconReserve += 11;
int maxChars = (tftWidth * 0.8 - 10 - iconReserve) / (LW * FM) - 1;

String text = "";
if (i == index) {
text += ">";
coord.x = tftWidth * 0.10 + 5 + FM * LW;
coord.y = tft.getCursorY() + 4;
coord.size = (tftWidth * 0.8 - 10) / (LW * FM) - 1;
coord.size = maxChars;
coord.fgcolor = fgcolor;
coord.bgcolor = bgcolor;
} else text += " ";
Expand All @@ -839,11 +845,27 @@ Opt_Coord drawOptions(

// Draw text with appropriate colors for selection
if (i == index) { tft.setTextColor(bgcolor, bruceConfig.priColor); }
tft.println(text.substring(0, (tftWidth * 0.8 - 10) / (LW * FM) - 1));
tft.println(text.substring(0, maxChars));

// Reset text color for next item
tft.setTextColor(fgcolor, bgcolor);

// Optional trailing icons (signal strength / lock), right-aligned
if (options[i].iconRssi != 0 || options[i].iconLock != 0) {
uint16_t iconCol = (i == index) ? bgcolor : fgcolor;
int iconY = cursorY + 4 + (FM * LH - 8) / 2;
int ix = tftWidth * 0.10 + tftWidth * 0.8 - 6;
if (options[i].iconRssi != 0) {
ix -= 11;
drawSignalBars(ix, iconY, options[i].iconRssi, iconCol);
ix -= 3;
}
if (options[i].iconLock != 0) {
ix -= 9;
drawLockIcon(ix, iconY, options[i].iconLock == 1, iconCol);
}
}

cont++;
}
if (cont > MAX_MENU_SIZE) break;
Expand Down Expand Up @@ -1737,6 +1759,33 @@ uint16_t getColorVariation(uint16_t color, int delta, int direction) {
return compl_color;
}

void drawSignalBars(int x, int y, int rssi, uint16_t color) {
int bars = 0;
if (rssi > -55) bars = 4;
else if (rssi > -68) bars = 3;
else if (rssi > -80) bars = 2;
else if (rssi > -92) bars = 1;
for (int i = 0; i < 4; i++) {
int h = 2 + i * 2;
if (i < bars) tft.fillRect(x + i * 3, y + 8 - h, 2, h, color);
else tft.drawFastHLine(x + i * 3, y + 7, 2, color);
}
}

void drawLockIcon(int x, int y, bool locked, uint16_t color) {
// Solid body (drawn in `color` so it reads on any row background)
tft.fillRect(x, y + 4, 9, 6, color);
if (locked) {
// Closed shackle centered over the body
tft.drawRoundRect(x + 2, y, 5, 6, 2, color);
} else {
// Open shackle: an unlatched hook to the right
tft.drawFastHLine(x + 3, y, 4, color);
tft.drawFastVLine(x + 6, y, 5, color);
tft.drawPixel(x + 2, y + 1, color);
}
}

// Draw BITMAP files
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
Expand Down
10 changes: 10 additions & 0 deletions src/core/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ uint16_t getComplementaryColor(uint16_t color);
uint16_t getComplementaryColor2(uint16_t color);
uint16_t getColorVariation(uint16_t color, int delta = 10, int direction = 0);

// Small four-bar signal-strength meter icon (RSSI, in dBm). Draws in an
// ~11x8 px box with its top-left at (x, y); stronger signal fills more bars.
// Shared by the WiFi/BLE scan lists so signal reads at a glance per entry.
void drawSignalBars(int x, int y, int rssi, uint16_t color);

// Small padlock icon (~9x10 px, top-left at x,y). `locked` draws a closed
// shackle, otherwise an open one — flags secured vs open networks. Drawn in
// `color`, so it stays visible on any row background.
void drawLockIcon(int x, int y, bool locked, uint16_t color);

void resetTftDisplay(
int x = 0, int y = 0, uint16_t fc = bruceConfig.priColor, int size = FM,
uint16_t bg = bruceConfig.bgColor, uint16_t screen = bruceConfig.bgColor
Expand Down
16 changes: 8 additions & 8 deletions src/core/wifi/wifi_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@ bool wifiConnectMenu(wifi_mode_t mode) {
int encryptionType = WiFi.encryptionType(i);
int32_t rssi = WiFi.RSSI(i);
int32_t ch = WiFi.channel(i);
// Check if the network is secured
String encryptionPrefix = (encryptionType == WIFI_AUTH_OPEN) ? "" : "#";
String encryptionTypeStr;
switch (encryptionType) {
case WIFI_AUTH_OPEN: encryptionTypeStr = "Open"; break;
Expand All @@ -233,13 +231,15 @@ bool wifiConnectMenu(wifi_mode_t mode) {
default: encryptionTypeStr = "Unknown"; break;
}

String optionText = encryptionPrefix + ssid + "(" + String(rssi) + "|" +
encryptionTypeStr + "|ch." + String(ch) + ")";
String optionText = ssid + " (" + encryptionTypeStr + "|ch." + String(ch) + ")";

options.push_back({optionText.c_str(), [&selSsid, &selEnc, ssid, encryptionType]() {
selSsid = ssid;
selEnc = encryptionType;
}});
Option opt(optionText.c_str(), [&selSsid, &selEnc, ssid, encryptionType]() {
selSsid = ssid;
selEnc = encryptionType;
});
opt.iconRssi = rssi;
opt.iconLock = (encryptionType == WIFI_AUTH_OPEN) ? 2 : 1;
options.push_back(opt);
}
}
WiFi.scanDelete();
Expand Down
10 changes: 3 additions & 7 deletions src/modules/NRF24/nrf_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ HardwareSerial NRFSerial = HardwareSerial(2); // Uses UART2 for External NRF's
SPIClass *NRFSPI;

void nrf_info() {
tft.fillScreen(bruceConfig.bgColor);
tft.setTextSize(FM);
tft.setTextColor(TFT_RED, bruceConfig.bgColor);
tft.drawCentreString("_Disclaimer_", tftWidth / 2, 10, 1);
tft.setTextColor(TFT_WHITE, bruceConfig.bgColor);
drawMainBorderWithTitle("NRF24 INFO");
printSubtitle("Disclaimer");
tft.setTextSize(FP);
tft.setCursor(15, 33);
padprintln("");
padprintln("These functions were made to be used in a controlled environment for STUDY only.");
padprintln("");
padprintln("DO NOT use these functions to harm people or companies, you can go to jail!");
tft.setTextColor(bruceConfig.priColor, bruceConfig.bgColor);
padprintln("");
padprintln(
"This device is VERY sensible to noise, so long wires or passing near VCC line can make "
Expand Down
23 changes: 10 additions & 13 deletions src/modules/badusb_ble/ducky_typer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ void key_input(FS fs, const String &bad_script, HIDInterface *_hid) {
);
if (!bruceConfig.badUSBBLEShowOutput) {
tft.setTextSize(FP);
tft.setTextColor(TFT_RED);
tft.setTextColor(getColorVariation(bruceConfig.priColor, 8, -1));
tft.setCursor(BORDER_OFFSET_FROM_SCREEN_EDGE * 2, tftHeight / 2);
tft.print("Script output disabled");
}
Expand Down Expand Up @@ -954,10 +954,10 @@ void key_input(FS fs, const String &bad_script, HIDInterface *_hid) {
} else if (PriCmd->type != DuckyCommandType_Comment) {
printTFTBadUSBBLE(Command, bruceConfig.priColor);
if (Argument.length() > 0) {
printTFTBadUSBBLE(" " + Argument, (ArgCmd == nullptr ? TFT_WHITE : TFT_WHITE), true);
} else printTFTBadUSBBLE("", TFT_WHITE, true);
printTFTBadUSBBLE(" " + Argument, bruceConfig.priColor, true);
} else printTFTBadUSBBLE("", bruceConfig.priColor, true);
} else if (PriCmd->type == DuckyCommandType_Comment) {
printTFTBadUSBBLE(Argument, TFT_DARKGREEN, true);
printTFTBadUSBBLE(Argument, getColorVariation(bruceConfig.priColor, 8, 1), true);
}
}

Expand Down Expand Up @@ -1410,13 +1410,7 @@ void PresenterMode(HIDInterface *&hid, bool ble) {
bool timerStarted = false;

auto drawStaticUI = [&]() {
tft.fillScreen(bruceConfig.bgColor);

tft.setTextSize(FM);
tft.setTextColor(bruceConfig.priColor, bruceConfig.bgColor);
tft.drawCentreString("PRESENTER", tftWidth / 2, 10, 1);

tft.drawFastHLine(10, 35, tftWidth - 20, bruceConfig.priColor);
drawMainBorderWithTitle("PRESENTER");

tft.setTextSize(FM);
tft.setTextColor(bruceConfig.priColor, bruceConfig.bgColor);
Expand All @@ -1431,7 +1425,7 @@ void PresenterMode(HIDInterface *&hid, bool ble) {
tft.fillRect(0, tftHeight / 2 - 35, tftWidth, 40, bruceConfig.bgColor);

tft.setTextSize(4);
tft.setTextColor(TFT_WHITE, bruceConfig.bgColor);
tft.setTextColor(bruceConfig.priColor, bruceConfig.bgColor);
String slideStr = "Slide " + String(currentSlide);
tft.drawCentreString(slideStr, tftWidth / 2, tftHeight / 2 - 30, 1);
lastDisplayedSlide = currentSlide;
Expand All @@ -1454,7 +1448,10 @@ void PresenterMode(HIDInterface *&hid, bool ble) {

tft.fillRect(0, tftHeight / 2 + 30, tftWidth, 30, bruceConfig.bgColor);
tft.setTextSize(3);
tft.setTextColor(timerStarted ? TFT_GREEN : TFT_DARKGREY, bruceConfig.bgColor);
tft.setTextColor(
timerStarted ? bruceConfig.priColor : getColorVariation(bruceConfig.priColor, 8, -1),
bruceConfig.bgColor
);
tft.drawCentreString(timeBuffer, tftWidth / 2, tftHeight / 2 + 35, 1);

lastDisplayedSeconds = elapsed;
Expand Down
4 changes: 3 additions & 1 deletion src/modules/ble/ble_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,9 @@ void ble_scan() {
if (bt_title.isEmpty()) bt_title = bt_address;

if (options.size() < MAX_DISPLAY_DEVICES) {
options.emplace_back(bt_title.c_str(), [=]() { ble_info(bt_name, bt_address, bt_signal); });
Option opt(bt_title.c_str(), [=]() { ble_info(bt_name, bt_address, bt_signal); });
opt.iconRssi = advertisedDevice->getRSSI();
options.push_back(opt);
processedCount++;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/modules/ble/ble_ninebot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ void BLENinebot::loop() {
loopOptions(deviceSelection);
}}
);
deviceSelection.back().iconRssi = adv->getRSSI();
}

bool returnToMenu = false;
Expand Down
3 changes: 1 addition & 2 deletions src/modules/ethernet/HostInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ void HostInfo::setup(const Host &host) {
};
const int portCount = sizeof(portNumbers) / sizeof(portNumbers[0]);

// Initialize display
drawMainBorder();
// Initialize display — ScrollableTextArea draws its own titled frame.
tft.setTextSize(FP);

ScrollableTextArea area = ScrollableTextArea("HOST INFO");
Expand Down
Loading