Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e9a21ff
repair nm-cyd-c5 pinout with nm-rf-hat
RockBase-iot Jun 10, 2026
59c06bc
repair next issue, default for nm-rf-hat
RockBase-iot Jun 10, 2026
ec5971d
Merge pull request #2779 from BruceDevices/dev
pr3y Aug 11, 2026
1b28175
Merge remote-tracking branch 'BruceDevices/firmware/main' into nm-cyd-c5
RockBase-iot Aug 11, 2026
cf86db7
Fixing IR decode on env_4mb device, such as CYD-2USB, DECODE_HASH=true
RockBase-iot Aug 11, 2026
ba519c9
Merge pull request #2781 from RockBase-iot/nm-cyd-c5
pr3y Aug 11, 2026
ec3ef9a
Add files via upload
hackspb0 Aug 19, 2026
413f759
Add files via upload
hackspb0 Aug 19, 2026
c82e2ce
Add files via upload
hackspb0 Aug 19, 2026
dc6f358
Add files via upload
hackspb0 Aug 19, 2026
e1a7d58
Add files via upload
hackspb0 Aug 19, 2026
729fd18
Fix
hackspb0 Aug 19, 2026
3e5221e
Fix
hackspb0 Aug 19, 2026
e52cd6a
Fix bug
hackspb0 Aug 20, 2026
76971d7
Fix
hackspb0 Aug 20, 2026
aa2952f
Fix
hackspb0 Aug 20, 2026
e4ee5d2
Fix
hackspb0 Aug 20, 2026
968f7d6
Fix Screen
hackspb0 Aug 20, 2026
800c741
Fix Screen
hackspb0 Aug 20, 2026
af4c4bb
Fix bug
hackspb0 Aug 20, 2026
7e22ddb
Added the ability to view the host name via about
hackspb0 Aug 20, 2026
9b15eb6
Fixed bug
hackspb0 Aug 20, 2026
ec77c8f
Fixed bug hosts name
hackspb0 Aug 20, 2026
1b1df2a
Attempt to fix the bug
hackspb0 Aug 20, 2026
ba5e8f6
Fixed Bug
hackspb0 Aug 21, 2026
792d84f
Bug Fixed
hackspb0 Aug 21, 2026
03aa903
Fixed bug
hackspb0 Aug 21, 2026
8b30a15
Info AP
hackspb0 Aug 21, 2026
af5b646
.
hackspb0 Aug 21, 2026
5a7f5bc
Hostname is disabled
hackspb0 Aug 21, 2026
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Bruce is a versatile ESP32 firmware packed with offensive-security tools, built to make Red Team operations fast and portable.

It also supports [M5Stack](https://shop.m5stack.com), [LILYGO](https://lilygo.cc) and [Elecrow](https://www.elecrow.com) products, and works great with the Cardputer, Sticks, M5Cores, T-Decks and T-Embeds.
It also supports [M5Stack](https://shop.m5stack.com), [LILYGO](https://lilygo.cc) , [RockBase IoT](https://www.rockbaseiot.com) and [Elecrow](https://www.elecrow.com) products, and works great with the Cardputer, Sticks, M5Cores, T-Decks and T-Embeds.

## :zap: Get Our Official DevKit!

Expand Down Expand Up @@ -245,6 +245,7 @@ Also, [read our FAQ](https://wiki.bruce.computer/faq/)
| [Bruce RF Reaper](https://www.elecrow.com/bruce-pcb-rf-reaper.html) | :ok: | :ok: | :x: | :ok: but w/ ST25R3916 | :x: | :ok: | :ok: | :x: | :ok: | :x: |
| [Elecrow 24B](https://www.elecrow.com/2-4inch-esp32-miner-lcd-display-2pcs-cryptocurrency-solo-miner-with-1000kh-s-hashrate.html) | :ok: | :ok: | :ok: | :ok: | :x: | :ok:¹ | :x: | :x: | :x: | :x:² |
| [Elecrow 3.5"](https://www.elecrow.com/esp-terminal-with-esp32-3-5-inch-parallel-480x320-tft-capacitive-touch-display-rgb-by-chip-ili9488.html) | :ok: | :ok: | :ok: | :ok: | :x: | :ok:¹ | :x: | :x: | :x: | :x:² |
| [NM-CYD-C5 + RF HAT](https://https://rockbase.shop/products/nm-cyd-c5-colorful) | :ok: | :ok: | :x: | :ok: | :x: | :ok: | :ok: | :x: | :ok: | :x: |
² CYD have a LITE_VERSION version for Launcher Compatibility
¹ Core, CYD and StickCs Bad-USB: [here](https://wiki.bruce.computer/features/others/#badusb)

Expand All @@ -258,6 +259,7 @@ Bruce stems from a keen observation within the community focused on devices like
![Bruce on M5Core](./media/pictures/core.png)
![Bruce on Stick](./media/pictures/stick.png)
![Bruce on CYD](./media/pictures/cyd.png)
![Bruce on CYD with NM-RF-HAT](./media/pictures/bruce-cyd.png)

Other media can be [found here](./media/).

Expand Down
12 changes: 6 additions & 6 deletions boards/CYD-2432S028/CYD-2432S028.ini
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ build_flags =
-DBAD_RX=GROVE_SCL

; SERIAL (GPS) dedicated pins
-DSERIAL_TX=1
-DSERIAL_RX=3
-DSERIAL_TX=3
-DSERIAL_RX=1
-DGPS_SERIAL_TX=SERIAL_TX
-DGPS_SERIAL_RX=SERIAL_RX

Expand All @@ -75,14 +75,14 @@ build_flags =

;Infrared Led default pin and state
-DIR_TX_PINS='{{"Pin 22", 22}, {"Pin 27", 27}}'
-DIR_RX_PINS='{{"Pin 22", 22}, {"Pin 27", 27}, {"Pin 35", 35}}'
-DIR_RX_PINS='{{"Pin 27", 27}, {"Pin 22", 22}, {"Pin 35", 35}}'
-DTXLED=22 ;NEED TO SET SOMETHING HERE, at least -1
-DLED_ON=HIGH
-DLED_OFF=LOW

;Radio Frequency (one pin modules) pin setting
-DRF_TX_PINS='{{"Pin 22", 22}, {"Pin 27", 27}}'
-DRF_RX_PINS='{{"Pin 22", 22}, {"Pin 27", 27}, {"Pin 35", 35}}'
-DRF_RX_PINS='{{"Pin 27", 27}, {"Pin 22", 22}, {"Pin 35", 35}}'

;CC1101 SPI connection pins
; best connection pins for higher speed https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/spi_master.html#gpio-matrix-and-io-mux
Expand Down Expand Up @@ -116,7 +116,7 @@ build_flags =

;Screen Setup
-DHAS_SCREEN=1
-DROTATION=1
-DROTATION=3
-DBACKLIGHT=21
-DMINBRIGHT=160

Expand Down Expand Up @@ -339,7 +339,7 @@ build_flags =
extends=env:CYD-2432S028
build_flags =
${env:CYD-2432S028.build_flags}
-DTFT_INVERSION_ON
;-DTFT_INVERSION_ON
-DDEVICE_NAME='"CYD-2USB"'

[env:LAUNCHER_CYD-2USB]
Expand Down
34 changes: 34 additions & 0 deletions boards/CYD-2432S028/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,40 @@ void _post_setup_gpio() {
pinMode(TFT_BL, OUTPUT);
ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits);
ledcWrite(TFT_BL, 255);

// Force sync color inversion to prevent bruceConf.json from overriding
// the value set in _setup_gpio(). For CYD variants with TFT_INVERSION_ON,
// the init() sequence sends INVON; we send INVOFF here to ensure normal colors.
#ifdef TFT_INVERSION_ON
bruceConfig.colorInverted = 0;
tft.invertDisplay(0);
#else
bruceConfig.colorInverted = 1;
tft.invertDisplay(1);
#endif

bruceConfigPins.gps_bus.rx = (gpio_num_t)GPS_SERIAL_RX;
bruceConfigPins.gps_bus.tx = (gpio_num_t)GPS_SERIAL_TX;
bruceConfigPins.gpsBaudrate = 9600;

bool pinsChanged = false;
if (bruceConfigPins.rfTx != 22) {
bruceConfigPins.rfTx = 22;
pinsChanged = true;
}
if (bruceConfigPins.rfRx != 27) {
bruceConfigPins.rfRx = 27;
pinsChanged = true;
}
if (bruceConfigPins.irTx != 22) {
bruceConfigPins.irTx = 22;
pinsChanged = true;
}
if (bruceConfigPins.irRx != 27) {
bruceConfigPins.irRx = 27;
pinsChanged = true;
}
if (pinsChanged) bruceConfigPins.saveFile();
}

/*********************************************************************
Expand Down
8 changes: 8 additions & 0 deletions boards/CYD-2432S028/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ static const uint8_t T9 = 32;
static const uint8_t DAC1 = 25;
static const uint8_t DAC2 = 26;

// I2C
#define GROVE_SDA 27
#define GROVE_SCL 22

// InfraRed
#define RXLED 27
#define TXLED 22

// Deepsleep
#define DEEPSLEEP_WAKEUP_PIN 36 // Touch interrupt
#define DEEPSLEEP_PIN_ACT LOW
Expand Down
24 changes: 18 additions & 6 deletions boards/nm-cyd-c5/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ void _setup_gpio() {
digitalWrite(SDCARD_CS, HIGH);
digitalWrite(W5500_SS_PIN, HIGH);
digitalWrite(TFT_CS, HIGH);
#ifdef ST7789_DRIVER
bruceConfig.colorInverted = 0;
#endif
#ifdef ILI9341_DRIVER
bruceConfig.colorInverted = 0;
#endif
}
/***************************************************************************************
** Function name: _post_setup_gpio()
Expand All @@ -60,6 +54,24 @@ void _post_setup_gpio() {
bruceConfigPins.gpsBaudrate = 9600;
bruceConfigPins.rfTx = 8;
bruceConfigPins.rfRx = 9;

// Force disable color inversion for ST7789/ILI9341 on nm-cyd-c5.
// Must be done here because begin_storage() loads bruceConf.json which may
// override the value set in _setup_gpio().
#ifdef ST7789_DRIVER
bruceConfig.colorInverted = 0;
tft.invertDisplay(0);
#endif
#ifdef ILI9341_DRIVER
bruceConfig.colorInverted = 0;
tft.invertDisplay(0);
#endif

// Force set I2C bus pins for nm-cyd-c5.
// brucePins.conf may have stale/wrong i2c_bus values, so override them
// to ensure PN532 and other I2C devices use the correct GPIO9(SDA)/GPIO8(SCL).
bruceConfigPins.i2c_bus.sda = (gpio_num_t)GROVE_SDA;
bruceConfigPins.i2c_bus.scl = (gpio_num_t)GROVE_SCL;
}

/***************************************************************************************
Expand Down
4 changes: 2 additions & 2 deletions boards/nm-cyd-c5/nm-cyd-c5.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ build_flags =
-DGPS_SERIAL_RX=4
; grove pins
; defaults from https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h
-DGROVE_SDA=8 ; default RF TX pin
-DGROVE_SCL=9 ; default IR/RF RX pin
-DGROVE_SDA=9 ; default IR/RF RX pin
-DGROVE_SCL=8 ; default IR/RF TX pin
;-DALLOW_ALL_GPIO_FOR_IR_RF=1 ; Set this option to make use of all GPIOs, from 1 to 44 to be chosen, except TFT and SD pins

; ir led pin
Expand Down
6 changes: 4 additions & 2 deletions boards/nm-cyd-c5/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ static const uint8_t LP_TX = 11;
// UART
#define SERIAL_TX 11
#define SERIAL_RX 12

// I2C
#define GROVE_SDA 8
#define GROVE_SCL 9
#define GROVE_SDA 9
#define GROVE_SCL 8

// SPI
#define SPI_SCK_PIN 6
#define SPI_MOSI_PIN 7
Expand Down
Binary file added media/pictures/bruce-cyd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ build_flags =
-DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1
# Restrict IR protocols to save Flash on 4mb devices
-D_IR_ENABLE_DEFAULT_=false
-DDECODE_HASH=true
-DDECODE_NEC=true
-DSEND_NEC=true
-DDECODE_SAMSUNG=true
Expand Down
14 changes: 14 additions & 0 deletions src/core/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ JsonDocument BruceConfig::toJson() const {
JsonObject _wifiAp = setting["wifiAp"].to<JsonObject>();
_wifiAp["ssid"] = wifiAp.ssid;
_wifiAp["pwd"] = wifiAp.pwd;
setting["wifiHostname"] = wifiHostname;
setting["wifiHostnameEnabled"] = wifiHostnameEnabled;
setting["wifiMAC"] = wifiMAC; //@IncursioHack
setting["TerminalLog"] = TerminalLog;

Expand Down Expand Up @@ -285,6 +287,13 @@ void BruceConfig::fromFile(bool checkFS) {
log_e("Fail");
}

if (!setting["wifiHostname"].isNull()) {
wifiHostname = setting["wifiHostname"].as<String>();
}
if (!setting["wifiHostnameEnabled"].isNull()) {
wifiHostnameEnabled = setting["wifiHostnameEnabled"].as<bool>();
}

//@IncursioHack
if (!setting["wifiMAC"].isNull()) {
wifiMAC = setting["wifiMAC"].as<String>();
Expand Down Expand Up @@ -650,6 +659,11 @@ void BruceConfig::setWifiApCreds(const String &ssid, const String &pwd) {
saveFile();
}

void BruceConfig::setWifiHostname(const String &hostname) {
wifiHostname = hostname;
saveFile();
}

void BruceConfig::setTerminalLog(bool value) {
TerminalLog = value;
saveFile();
Expand Down
3 changes: 3 additions & 0 deletions src/core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class BruceConfig : public BruceTheme {
Credential webUI = {"admin", "bruce"};
std::vector<String> webUISessions = {}; // FIFO queue of session tokens
WiFiCredential wifiAp = {"BruceNet", "brucenet"};
String wifiHostname = "Bruce Firmware";
bool wifiHostnameEnabled = true;
std::map<String, String> wifi = {};
std::set<String> evilWifiNames = {};
String wifiMAC = ""; //@IncursioHack
Expand Down Expand Up @@ -159,6 +161,7 @@ class BruceConfig : public BruceTheme {
// Wifi
void setWebUICreds(const String &usr, const String &pwd);
void setWifiApCreds(const String &ssid, const String &pwd);
void setWifiHostname(const String &hostname);
void setTerminalLog(bool value);
void addWifiCredential(const String &ssid, const String &pwd);
void addQrCodeEntry(const String &menuName, const String &content);
Expand Down
5 changes: 5 additions & 0 deletions src/core/menu_items/ConfigMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ void ConfigMenu::advancedMenu() {
if (name.length() > 0 && name != "\x1B") bruceConfigPins.setBleName(name);
} },
{"Network Creds", [this]() { setNetworkCredsMenu(); }},
{String("Hostname: ") + (bruceConfig.wifiHostnameEnabled ? "ON" : "OFF"),
[this]() {
bruceConfig.wifiHostnameEnabled = !bruceConfig.wifiHostnameEnabled;
bruceConfig.saveFile();
} },
{"Factory Reset",
[]() {
// Confirmation dialog for destructive action
Expand Down
1 change: 1 addition & 0 deletions src/core/menu_items/WifiMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ void WifiMenu::configMenu() {
std::vector<Option> wifiOptions;

wifiOptions.push_back({"Change MAC", wifiMACMenu});
wifiOptions.push_back({"Device hosts name", setWifiHostnameMenu});
wifiOptions.push_back({"Add Evil Wifi", addEvilWifiMenu});
wifiOptions.push_back({"Remove Evil Wifi", removeEvilWifiMenu});
wifiOptions.push_back({bruceConfig.TerminalLog ? "SSH/Telnet Log OFF" : "SSH/Telnet Log ON", [this]() {
Expand Down
6 changes: 6 additions & 0 deletions src/core/mykeyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,11 @@ String generalKeyboard(

tft.fillScreen(bruceConfig.bgColor); // reset the screen

#if defined(HAS_3_BUTTONS)
uint8_t longNextPress = 0;
uint8_t longPrevPress = 0;
unsigned long LongPressTmp = millis();
#endif

// main loop
while (1) {
Expand Down Expand Up @@ -799,15 +801,19 @@ String generalKeyboard(
/* Next-Prev Btns to move in X axis (right-left) */
else if (check(NextPress)) {
NextPress = false;
#if defined(HAS_3_BUTTONS)
longNextPress = false;
#endif
x++;
if ((y < 0 && x >= buttons_number) || x >= KeyboardWidth) x = 0;
redraw = true;
}
/* Down-Up Btns to move in Y axis */
else if (check(PrevPress)) {
PrevPress = false;
#if defined(HAS_3_BUTTONS)
longPrevPress = false;
#endif
x--;
if (y < 0 && x >= buttons_number) x = buttons_number - 1;
else if (x < 0) x = KeyboardWidth - 1;
Expand Down
14 changes: 14 additions & 0 deletions src/core/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "settingsColor.h"
#include "utils.h"
#include <ELECHOUSE_CC1101_SRC_DRV.h>
#include <cctype>
#include <globals.h>

int currentScreenBrightness = -1;
Expand Down Expand Up @@ -1351,6 +1352,19 @@ void setNetworkCredsMenu() {
loopOptions(options);
}

void setWifiHostnameMenu() {
String hostname = keyboard(bruceConfig.wifiHostname, 32, "Device hostname:");
if (hostname == "\x1B") return;
if (hostname.isEmpty()) {
displayError("Name cannot be empty", true);
return;
}

bruceConfig.setWifiHostname(hostname);
if (WiFi.getMode() != WIFI_MODE_NULL) wifiDisconnect();
displayInfo("Device name: " + hostname, true);
}

/*********************************************************************
** Function: setBadUSBBLEMenu
** Main Menu for setting Bad USB/BLE options
Expand Down
6 changes: 4 additions & 2 deletions src/core/settings.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef __SETTINGS_H__
#define __SETTINGS_H__
#ifndef BRUCE_CORE_SETTINGS_H
#define BRUCE_CORE_SETTINGS_H

#include "config.h"
#include "configPins.h"
Expand Down Expand Up @@ -92,6 +92,8 @@ void setGpsBaudrateMenu();

void setNetworkCredsMenu();

void setWifiHostnameMenu();

void setBadUSBBLEMenu();
void setBadUSBBLEKeyboardLayoutMenu();
void setBadUSBBLEKeyDelayMenu();
Expand Down
1 change: 1 addition & 0 deletions src/core/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ void showDeviceInfo() {
area.addLine("");
area.addLine("[NETWORK]");
area.addLine("MAC addr: " + String(WiFi.macAddress()));
area.addLine("Hostname: " + (bruceConfig.wifiHostnameEnabled ? bruceConfig.wifiHostname : "Disabled"));
String localIP = WiFi.localIP().toString();
String softAPIP = WiFi.softAPIP().toString();
String ipStatus = (WiFi.isConnected()) ? (localIP != "0.0.0.0" ? localIP
Expand Down
Loading