mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-01 02:09:57 +00:00
Trunk n stuff (#5833)
Some checks failed
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32-s3 (push) Blocked by required conditions
CI / build-esp32-c3 (push) Blocked by required conditions
CI / build-esp32-c6 (push) Blocked by required conditions
CI / build-nrf52 (push) Blocked by required conditions
CI / build-rpi2040 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / package-raspbian (push) Waiting to run
CI / package-raspbian-armv7l (push) Waiting to run
CI / package-native (push) Waiting to run
CI / build-debian-src (push) Waiting to run
CI / test-native (push) Waiting to run
CI / build-docker (push) Waiting to run
CI / after-checks (push) Blocked by required conditions
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
Flawfinder Scan / Flawfinder (push) Waiting to run
Nightly Debian Packaging / package-ppa (jammy) (push) Has been cancelled
Nightly Debian Packaging / package-ppa (noble) (push) Has been cancelled
Nightly Debian Packaging / package-ppa (oracular) (push) Has been cancelled
Nightly Debian Packaging / package-ppa (plucky) (push) Has been cancelled
Nightly Debian Packaging / package-obs (push) Has been cancelled
Some checks failed
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32-s3 (push) Blocked by required conditions
CI / build-esp32-c3 (push) Blocked by required conditions
CI / build-esp32-c6 (push) Blocked by required conditions
CI / build-nrf52 (push) Blocked by required conditions
CI / build-rpi2040 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / package-raspbian (push) Waiting to run
CI / package-raspbian-armv7l (push) Waiting to run
CI / package-native (push) Waiting to run
CI / build-debian-src (push) Waiting to run
CI / test-native (push) Waiting to run
CI / build-docker (push) Waiting to run
CI / after-checks (push) Blocked by required conditions
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
Flawfinder Scan / Flawfinder (push) Waiting to run
Nightly Debian Packaging / package-ppa (jammy) (push) Has been cancelled
Nightly Debian Packaging / package-ppa (noble) (push) Has been cancelled
Nightly Debian Packaging / package-ppa (oracular) (push) Has been cancelled
Nightly Debian Packaging / package-ppa (plucky) (push) Has been cancelled
Nightly Debian Packaging / package-obs (push) Has been cancelled
* Trunk * Allow new gpio syntax with defaults * Exit on pin init failure
This commit is contained in:
parent
70296b47bc
commit
6b1c01ce02
67
src/main.cpp
67
src/main.cpp
@ -826,43 +826,37 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
const struct { configNames cfgName;
|
const struct {
|
||||||
std::string strName;
|
configNames cfgName;
|
||||||
} loraModules[] = {
|
std::string strName;
|
||||||
{ use_rf95, "RF95" },
|
} loraModules[] = {{use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"}, {use_sx1280, "sx1280"},
|
||||||
{ use_sx1262, "sx1262" },
|
{use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
||||||
{ use_sx1268, "sx1268" },
|
|
||||||
{ use_sx1280, "sx1280" },
|
|
||||||
{ use_lr1110, "lr1110" },
|
|
||||||
{ use_lr1120, "lr1120" },
|
|
||||||
{ use_lr1121, "lr1121" },
|
|
||||||
{ use_llcc68, "LLCC68" }
|
|
||||||
};
|
|
||||||
// as one can't use a function pointer to the class constructor:
|
// as one can't use a function pointer to the class constructor:
|
||||||
auto loraModuleInterface = [](configNames cfgName, LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) {
|
auto loraModuleInterface = [](configNames cfgName, LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
|
||||||
switch (cfgName) {
|
RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) {
|
||||||
case use_rf95:
|
switch (cfgName) {
|
||||||
return (RadioInterface*)new RF95Interface(hal, cs, irq, rst, busy);
|
case use_rf95:
|
||||||
case use_sx1262:
|
return (RadioInterface *)new RF95Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new SX1262Interface(hal, cs, irq, rst, busy);
|
case use_sx1262:
|
||||||
case use_sx1268:
|
return (RadioInterface *)new SX1262Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new SX1268Interface(hal, cs, irq, rst, busy);
|
case use_sx1268:
|
||||||
case use_sx1280:
|
return (RadioInterface *)new SX1268Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new SX1280Interface(hal, cs, irq, rst, busy);
|
case use_sx1280:
|
||||||
case use_lr1110:
|
return (RadioInterface *)new SX1280Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new LR1110Interface(hal, cs, irq, rst, busy);
|
case use_lr1110:
|
||||||
case use_lr1120:
|
return (RadioInterface *)new LR1110Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new LR1120Interface(hal, cs, irq, rst, busy);
|
case use_lr1120:
|
||||||
case use_lr1121:
|
return (RadioInterface *)new LR1120Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new LR1121Interface(hal, cs, irq, rst, busy);
|
case use_lr1121:
|
||||||
case use_llcc68:
|
return (RadioInterface *)new LR1121Interface(hal, cs, irq, rst, busy);
|
||||||
return (RadioInterface*)new LLCC68Interface(hal, cs, irq, rst, busy);
|
case use_llcc68:
|
||||||
default:
|
return (RadioInterface *)new LLCC68Interface(hal, cs, irq, rst, busy);
|
||||||
assert(0); // shouldn't happen
|
default:
|
||||||
return (RadioInterface*)nullptr;
|
assert(0); // shouldn't happen
|
||||||
}
|
return (RadioInterface *)nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
for (auto& loraModule : loraModules) {
|
for (auto &loraModule : loraModules) {
|
||||||
if (settingsMap[loraModule.cfgName] && !rIf) {
|
if (settingsMap[loraModule.cfgName] && !rIf) {
|
||||||
LOG_DEBUG("Activate %s radio on SPI port %s", loraModule.strName.c_str(), settingsStrings[spidev].c_str());
|
LOG_DEBUG("Activate %s radio on SPI port %s", loraModule.strName.c_str(), settingsStrings[spidev].c_str());
|
||||||
if (settingsStrings[spidev] == "ch341") {
|
if (settingsStrings[spidev] == "ch341") {
|
||||||
@ -870,7 +864,8 @@ void setup()
|
|||||||
} else {
|
} else {
|
||||||
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||||
}
|
}
|
||||||
rIf = loraModuleInterface(loraModule.cfgName, (LockingArduinoHal *)RadioLibHAL, settingsMap[cs_pin], settingsMap[irq_pin], settingsMap[reset_pin], settingsMap[busy_pin]);
|
rIf = loraModuleInterface(loraModule.cfgName, (LockingArduinoHal *)RadioLibHAL, settingsMap[cs_pin],
|
||||||
|
settingsMap[irq_pin], settingsMap[reset_pin], settingsMap[busy_pin]);
|
||||||
if (!rIf->init()) {
|
if (!rIf->init()) {
|
||||||
LOG_WARN("No %s radio", loraModule.strName.c_str());
|
LOG_WARN("No %s radio", loraModule.strName.c_str());
|
||||||
delete rIf;
|
delete rIf;
|
||||||
|
@ -121,7 +121,8 @@ template <typename T> bool SX126xInterface<T>::init()
|
|||||||
// no effect
|
// no effect
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
if (res == RADIOLIB_ERR_NONE) {
|
if (res == RADIOLIB_ERR_NONE) {
|
||||||
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen_pin], settingsMap[txen_pin]);
|
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen_pin],
|
||||||
|
settingsMap[txen_pin]);
|
||||||
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]);
|
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -134,21 +134,10 @@ void portduinoSetup()
|
|||||||
{
|
{
|
||||||
printf("Set up Meshtastic on Portduino...\n");
|
printf("Set up Meshtastic on Portduino...\n");
|
||||||
int max_GPIO = 0;
|
int max_GPIO = 0;
|
||||||
const configNames GPIO_lines[] = {cs_pin,
|
const configNames GPIO_lines[] = {
|
||||||
irq_pin,
|
cs_pin, irq_pin, busy_pin, reset_pin, sx126x_ant_sw_pin, txen_pin,
|
||||||
busy_pin,
|
rxen_pin, displayDC, displayCS, displayBacklight, displayBacklightPWMChannel, displayReset,
|
||||||
reset_pin,
|
touchscreenCS, touchscreenIRQ, user};
|
||||||
sx126x_ant_sw_pin,
|
|
||||||
txen_pin,
|
|
||||||
rxen_pin,
|
|
||||||
displayDC,
|
|
||||||
displayCS,
|
|
||||||
displayBacklight,
|
|
||||||
displayBacklightPWMChannel,
|
|
||||||
displayReset,
|
|
||||||
touchscreenCS,
|
|
||||||
touchscreenIRQ,
|
|
||||||
user};
|
|
||||||
|
|
||||||
std::string gpioChipName = "gpiochip";
|
std::string gpioChipName = "gpiochip";
|
||||||
settingsStrings[i2cdev] = "";
|
settingsStrings[i2cdev] = "";
|
||||||
@ -257,7 +246,6 @@ void portduinoSetup()
|
|||||||
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
|
||||||
|
|
||||||
// Need to bind all the configured GPIO pins so they're not simulated
|
// Need to bind all the configured GPIO pins so they're not simulated
|
||||||
// TODO: Can we do this in the for loop above?
|
|
||||||
// TODO: If one of these fails, we should log and terminate
|
// TODO: If one of these fails, we should log and terminate
|
||||||
if (settingsMap.count(user) > 0 && settingsMap[user] != RADIOLIB_NC) {
|
if (settingsMap.count(user) > 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||||
if (initGPIOPin(settingsMap[user], defaultGpioChipName, settingsMap[user]) != ERRNO_OK) {
|
if (initGPIOPin(settingsMap[user], defaultGpioChipName, settingsMap[user]) != ERRNO_OK) {
|
||||||
@ -283,22 +271,25 @@ void portduinoSetup()
|
|||||||
|
|
||||||
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
||||||
if (settingsStrings[spidev] != "" && settingsStrings[spidev] != "ch341") {
|
if (settingsStrings[spidev] != "" && settingsStrings[spidev] != "ch341") {
|
||||||
const struct { configNames pin; configNames gpiochip; configNames line; } pinMappings[] = {
|
const struct {
|
||||||
{ cs_pin, cs_gpiochip, cs_line },
|
configNames pin;
|
||||||
{ irq_pin, irq_gpiochip, irq_line },
|
configNames gpiochip;
|
||||||
{ busy_pin, busy_gpiochip, busy_line },
|
configNames line;
|
||||||
{ reset_pin, reset_gpiochip, reset_line },
|
} pinMappings[] = {{cs_pin, cs_gpiochip, cs_line},
|
||||||
{ rxen_pin, rxen_gpiochip, rxen_line },
|
{irq_pin, irq_gpiochip, irq_line},
|
||||||
{ txen_pin, txen_gpiochip, txen_line },
|
{busy_pin, busy_gpiochip, busy_line},
|
||||||
{ sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line }
|
{reset_pin, reset_gpiochip, reset_line},
|
||||||
};
|
{rxen_pin, rxen_gpiochip, rxen_line},
|
||||||
for (auto& pinMap : pinMappings) {
|
{txen_pin, txen_gpiochip, txen_line},
|
||||||
|
{sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line}};
|
||||||
|
for (auto &pinMap : pinMappings) {
|
||||||
auto setMapIter = settingsMap.find(pinMap.pin);
|
auto setMapIter = settingsMap.find(pinMap.pin);
|
||||||
if (setMapIter != settingsMap.end() && setMapIter->second != RADIOLIB_NC) {
|
if (setMapIter != settingsMap.end() && setMapIter->second != RADIOLIB_NC) {
|
||||||
if (initGPIOPin(setMapIter->second, gpioChipName + std::to_string(settingsMap[pinMap.gpiochip]), settingsMap[pinMap.line] ) != ERRNO_OK) {
|
if (initGPIOPin(setMapIter->second, gpioChipName + std::to_string(settingsMap[pinMap.gpiochip]),
|
||||||
settingsMap[pinMap.pin] = RADIOLIB_NC;
|
settingsMap[pinMap.line]) != ERRNO_OK) {
|
||||||
settingsMap[pinMap.gpiochip] = RADIOLIB_NC;
|
printf("Error setting pin number %d. It may not exist, or may already be in use.\n",
|
||||||
settingsMap[pinMap.line] = RADIOLIB_NC;
|
settingsMap[pinMap.line]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,21 +351,16 @@ bool loadConfig(const char *configPath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["Lora"]) {
|
if (yamlConfig["Lora"]) {
|
||||||
const struct { configNames cfgName; std::string strName; } loraModules[] = {
|
const struct {
|
||||||
{ use_rf95, "RF95" },
|
configNames cfgName;
|
||||||
{ use_sx1262, "sx1262" },
|
std::string strName;
|
||||||
{ use_sx1268, "sx1268" },
|
} loraModules[] = {{use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"}, {use_sx1280, "sx1280"},
|
||||||
{ use_sx1280, "sx1280" },
|
{use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
|
||||||
{ use_lr1110, "lr1110" },
|
for (auto &loraModule : loraModules) {
|
||||||
{ use_lr1120, "lr1120" },
|
|
||||||
{ use_lr1121, "lr1121" },
|
|
||||||
{ use_llcc68, "LLCC68" }
|
|
||||||
};
|
|
||||||
for (auto& loraModule : loraModules) {
|
|
||||||
settingsMap[loraModule.cfgName] = false;
|
settingsMap[loraModule.cfgName] = false;
|
||||||
}
|
}
|
||||||
if (yamlConfig["Lora"]["Module"]) {
|
if (yamlConfig["Lora"]["Module"]) {
|
||||||
for (auto& loraModule : loraModules) {
|
for (auto &loraModule : loraModules) {
|
||||||
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.strName) {
|
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.strName) {
|
||||||
settingsMap[loraModule.cfgName] = true;
|
settingsMap[loraModule.cfgName] = true;
|
||||||
break;
|
break;
|
||||||
@ -391,28 +377,26 @@ bool loadConfig(const char *configPath)
|
|||||||
// backwards API compatibility and to globally set gpiochip once
|
// backwards API compatibility and to globally set gpiochip once
|
||||||
int defaultGpioChip = settingsMap[default_gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
int defaultGpioChip = settingsMap[default_gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
|
||||||
|
|
||||||
const struct { configNames pin;
|
const struct {
|
||||||
configNames gpiochip;
|
configNames pin;
|
||||||
configNames line;
|
configNames gpiochip;
|
||||||
std::string strName; } pinMappings[] = {
|
configNames line;
|
||||||
{ cs_pin, cs_gpiochip, cs_line, "CS" },
|
std::string strName;
|
||||||
{ irq_pin, irq_gpiochip, irq_line, "IRQ" },
|
} pinMappings[] = {
|
||||||
{ busy_pin, busy_gpiochip, busy_line, "Busy" },
|
{cs_pin, cs_gpiochip, cs_line, "CS"},
|
||||||
{ reset_pin, reset_gpiochip, reset_line, "Reset" },
|
{irq_pin, irq_gpiochip, irq_line, "IRQ"},
|
||||||
{ txen_pin, txen_gpiochip, txen_line, "TXen" },
|
{busy_pin, busy_gpiochip, busy_line, "Busy"},
|
||||||
{ rxen_pin, rxen_gpiochip, rxen_line, "RXen" },
|
{reset_pin, reset_gpiochip, reset_line, "Reset"},
|
||||||
{ sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line, "SX126X_ANT_SW" },
|
{txen_pin, txen_gpiochip, txen_line, "TXen"},
|
||||||
|
{rxen_pin, rxen_gpiochip, rxen_line, "RXen"},
|
||||||
|
{sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line, "SX126X_ANT_SW"},
|
||||||
};
|
};
|
||||||
for (auto& pinMap : pinMappings) {
|
for (auto &pinMap : pinMappings) {
|
||||||
if (yamlConfig["Lora"][pinMap.strName].IsMap()
|
if (yamlConfig["Lora"][pinMap.strName].IsMap()) {
|
||||||
&& (yamlConfig["Lora"][pinMap.strName]["pin"]
|
|
||||||
|| yamlConfig["Lora"][pinMap.strName]["line"]
|
|
||||||
|| yamlConfig["Lora"][pinMap.strName]["gpiochip"])) {
|
|
||||||
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName]["pin"].as<int>(RADIOLIB_NC);
|
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName]["pin"].as<int>(RADIOLIB_NC);
|
||||||
settingsMap[pinMap.line] = yamlConfig["Lora"][pinMap.strName]["line"].as<int>(settingsMap[pinMap.pin]);
|
settingsMap[pinMap.line] = yamlConfig["Lora"][pinMap.strName]["line"].as<int>(settingsMap[pinMap.pin]);
|
||||||
settingsMap[pinMap.gpiochip] = yamlConfig["Lora"][pinMap.strName]["gpiochip"].as<int>(defaultGpioChip);
|
settingsMap[pinMap.gpiochip] = yamlConfig["Lora"][pinMap.strName]["gpiochip"].as<int>(defaultGpioChip);
|
||||||
}
|
} else { // backwards API compatibility
|
||||||
else { // backwards API compatibility
|
|
||||||
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName].as<int>(RADIOLIB_NC);
|
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName].as<int>(RADIOLIB_NC);
|
||||||
settingsMap[pinMap.line] = settingsMap[pinMap.pin];
|
settingsMap[pinMap.line] = settingsMap[pinMap.pin];
|
||||||
settingsMap[pinMap.gpiochip] = defaultGpioChip;
|
settingsMap[pinMap.gpiochip] = defaultGpioChip;
|
||||||
@ -584,4 +568,4 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac)
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user