PXX2 refactoring + Popups refactoring
This commit is contained in:
@@ -37,7 +37,7 @@ void onModelCustomScriptMenu(const char *result)
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a lua file in the list
|
||||
copySelection(sd.file, result, sizeof(sd.file));
|
||||
memset(sd.inputs, 0, sizeof(sd.inputs));
|
||||
|
||||
@@ -73,7 +73,7 @@ void onTelemetryScriptFileSelectionMenu(const char *result)
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file in the list
|
||||
memcpy(g_model.frsky.screens[screenIndex].script.file, result, sizeof(g_model.frsky.screens[screenIndex].script.file));
|
||||
storageDirty(EE_MODEL);
|
||||
|
||||
@@ -56,7 +56,7 @@ void onModelSelectMenu(const char * result)
|
||||
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
|
||||
}
|
||||
#if defined(SDCARD)
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file on SD to restore
|
||||
storageCheck(true);
|
||||
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
|
||||
|
||||
@@ -276,7 +276,7 @@ enum MenuModelSetupItems {
|
||||
|
||||
void onPXX2BindMenu(const char * result)
|
||||
{
|
||||
if (result) {
|
||||
if (result != STR_EXIT) {
|
||||
reusableBuffer.moduleSetup.pxx2.bindSelectedReceiverIndex = (result - reusableBuffer.moduleSetup.pxx2.bindCandidateReceiversNames[0]) / sizeof(reusableBuffer.moduleSetup.pxx2.bindCandidateReceiversNames[0]);
|
||||
reusableBuffer.moduleSetup.pxx2.bindStep = BIND_RX_NAME_SELECTED;
|
||||
}
|
||||
|
||||
@@ -57,12 +57,12 @@ void onCustomFunctionsFileSelectionMenu(const char * result)
|
||||
strcpy(directory, SOUNDS_PATH);
|
||||
strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
}
|
||||
if (!sdListFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), NULL)) {
|
||||
if (!sdListFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), nullptr)) {
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
POPUP_MENU_UNSET_BSS_FLAG();
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file in the list
|
||||
memcpy(cfn->play.name, result, sizeof(cfn->play.name));
|
||||
storageDirty(eeFlags);
|
||||
@@ -96,7 +96,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result)
|
||||
CFN_PARAM(cfn) = 0;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
onSourceLongEnterPress(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ void onModelCustomScriptMenu(const char *result)
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a lua file in the list
|
||||
copySelection(sd.file, result, sizeof(sd.file));
|
||||
memset(sd.inputs, 0, sizeof(sd.inputs));
|
||||
|
||||
@@ -72,7 +72,7 @@ void onTelemetryScriptFileSelectionMenu(const char *result)
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file in the list
|
||||
memcpy(g_model.frsky.screens[screenIndex].script.file, result, sizeof(g_model.frsky.screens[screenIndex].script.file));
|
||||
storageDirty(EE_MODEL);
|
||||
|
||||
@@ -55,7 +55,7 @@ void onModelSelectMenu(const char * result)
|
||||
POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr);
|
||||
SET_WARNING_INFO(nametmp, sizeof(g_model.header.name), 0);
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file on SD to restore
|
||||
storageCheck(true);
|
||||
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
|
||||
|
||||
@@ -148,7 +148,7 @@ void onModelSetupBitmapMenu(const char * result)
|
||||
POPUP_WARNING(STR_NO_BITMAPS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a bmp file in the list
|
||||
copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap));
|
||||
memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap));
|
||||
|
||||
@@ -56,7 +56,7 @@ void onCustomFunctionsFileSelectionMenu(const char * result)
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file in the list
|
||||
memcpy(cfn->play.name, result, sizeof(cfn->play.name));
|
||||
storageDirty(eeFlags);
|
||||
@@ -129,7 +129,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result)
|
||||
CFN_PARAM(cfn) = 0;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
onSourceLongEnterPress(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ void onModelCustomScriptMenu(const char *result)
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a lua file in the list
|
||||
copySelection(sd.file, result, sizeof(sd.file));
|
||||
memset(sd.inputs, 0, sizeof(sd.inputs));
|
||||
|
||||
@@ -151,7 +151,7 @@ void onModelSetupBitmapMenu(const char * result)
|
||||
POPUP_WARNING(STR_NO_BITMAPS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a bmp file in the list
|
||||
copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap));
|
||||
storageDirty(EE_MODEL);
|
||||
|
||||
@@ -56,7 +56,7 @@ void onCustomFunctionsFileSelectionMenu(const char * result)
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
// The user choosed a file in the list
|
||||
memcpy(cf->play.name, result, sizeof(cf->play.name));
|
||||
storageDirty(eeFlags);
|
||||
@@ -128,7 +128,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result)
|
||||
CFN_PARAM(cfn) = 0;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
onSourceLongEnterPress(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ void onZoneOptionFileSelectionMenu(const char * result)
|
||||
POPUP_WARNING(STR_NO_BITMAPS_ON_SD);
|
||||
}
|
||||
}
|
||||
else if (result) {
|
||||
else if (result != STR_EXIT) {
|
||||
fileSelectionDone = true;
|
||||
memcpy(fileSelection, result, sizeof(fileSelection));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ void showMessageBox(const char * title)
|
||||
|
||||
const char * runPopupMenu(event_t event)
|
||||
{
|
||||
const char * result = NULL;
|
||||
const char * result = nullptr;
|
||||
|
||||
uint8_t display_count = min<uint8_t>(popupMenuItemsCount, MENU_MAX_DISPLAY_LINES);
|
||||
uint8_t y = LCD_H / 2 - (popupMenuTitle ? 0 : 3) - (display_count * FH / 2);
|
||||
@@ -149,7 +149,11 @@ const char * runPopupMenu(event_t event)
|
||||
#endif
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
result = popupMenuItems[s_menu_item + (popupMenuOffsetType == MENU_OFFSET_INTERNAL ? popupMenuOffset : 0)];
|
||||
// no break
|
||||
popupMenuItemsCount = 0;
|
||||
s_menu_item = 0;
|
||||
popupMenuOffset = 0;
|
||||
popupMenuTitle = nullptr;
|
||||
break;
|
||||
|
||||
#if defined(CASE_EVT_ROTARY_LONG)
|
||||
CASE_EVT_ROTARY_LONG
|
||||
@@ -158,6 +162,7 @@ const char * runPopupMenu(event_t event)
|
||||
#endif
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
result = STR_EXIT;
|
||||
popupMenuItemsCount = 0;
|
||||
s_menu_item = 0;
|
||||
popupMenuOffset = 0;
|
||||
|
||||
+1
-11
@@ -400,8 +400,6 @@ void handleGui(event_t event) {
|
||||
}
|
||||
}
|
||||
|
||||
bool inPopupMenu = false;
|
||||
|
||||
void guiMain(event_t evt)
|
||||
{
|
||||
#if defined(LUA)
|
||||
@@ -446,22 +444,14 @@ void guiMain(event_t evt)
|
||||
else if (popupMenuItemsCount > 0) {
|
||||
// popup menu is active display it on top of normal menus
|
||||
handleGui(0); // suppress events, they are handled by the popup
|
||||
if (!inPopupMenu) {
|
||||
TRACE("Popup Menu started");
|
||||
inPopupMenu = true;
|
||||
}
|
||||
const char * result = runPopupMenu(evt);
|
||||
if (popupMenuItemsCount == 0) {
|
||||
if (result) {
|
||||
TRACE("popupMenuHandler(%s)", result);
|
||||
popupMenuHandler(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// normal menus
|
||||
if (inPopupMenu) {
|
||||
TRACE("Popup Menu ended");
|
||||
inPopupMenu = false;
|
||||
}
|
||||
handleGui(evt);
|
||||
}
|
||||
|
||||
|
||||
+54
-42
@@ -36,53 +36,69 @@ uint8_t Pxx2Pulses::addFlag0(uint8_t module)
|
||||
return flag0;
|
||||
}
|
||||
|
||||
void Pxx2Pulses::addFlag1(uint8_t module)
|
||||
void Pxx2Pulses::addFlag1()
|
||||
{
|
||||
uint8_t flag1 = 0;
|
||||
Pxx2Transport::addByte(flag1);
|
||||
}
|
||||
|
||||
void Pxx2Pulses::addChannels(uint8_t module, uint8_t sendFailsafe, uint8_t firstChannel)
|
||||
void Pxx2Pulses::addPulsesValues(uint16_t low, uint16_t high)
|
||||
{
|
||||
Pxx2Transport::addByte(low); // Low byte of channel
|
||||
Pxx2Transport::addByte(((low >> 8) & 0x0F) | (high << 4)); // 4 bits each from 2 channels
|
||||
Pxx2Transport::addByte(high >> 4); // High byte of channel
|
||||
}
|
||||
|
||||
void Pxx2Pulses::addChannels(uint8_t module)
|
||||
{
|
||||
uint16_t pulseValue = 0;
|
||||
uint16_t pulseValueLow = 0;
|
||||
|
||||
for (int8_t i=0; i<8; i++) {
|
||||
uint8_t channel = firstChannel + i;
|
||||
if (sendFailsafe) {
|
||||
if (g_model.moduleData[module].failsafeMode == FAILSAFE_HOLD) {
|
||||
uint8_t channel = g_model.moduleData[module].channelsStart;
|
||||
uint8_t count = sentModuleChannels(module);
|
||||
|
||||
for (int8_t i = 0; i < count; i++, channel++) {
|
||||
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
|
||||
pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
|
||||
if (i & 1)
|
||||
addPulsesValues(pulseValueLow, pulseValue);
|
||||
else
|
||||
pulseValueLow = pulseValue;
|
||||
}
|
||||
}
|
||||
|
||||
void Pxx2Pulses::addFailsafe(uint8_t module)
|
||||
{
|
||||
uint16_t pulseValue = 0;
|
||||
uint16_t pulseValueLow = 0;
|
||||
|
||||
uint8_t channel = g_model.moduleData[module].channelsStart;
|
||||
uint8_t count = sentModuleChannels(module);
|
||||
|
||||
for (int8_t i = 0; i < count; i++, channel++) {
|
||||
if (g_model.moduleData[module].failsafeMode == FAILSAFE_HOLD) {
|
||||
pulseValue = 2047;
|
||||
}
|
||||
else if (g_model.moduleData[module].failsafeMode == FAILSAFE_NOPULSES) {
|
||||
pulseValue = 0;
|
||||
}
|
||||
else {
|
||||
int16_t failsafeValue = g_model.failsafeChannels[channel];
|
||||
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
|
||||
pulseValue = 2047;
|
||||
}
|
||||
else if (g_model.moduleData[module].failsafeMode == FAILSAFE_NOPULSES) {
|
||||
else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
|
||||
pulseValue = 0;
|
||||
}
|
||||
else {
|
||||
int16_t failsafeValue = g_model.failsafeChannels[channel];
|
||||
if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
|
||||
pulseValue = 2047;
|
||||
}
|
||||
else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
|
||||
pulseValue = 0;
|
||||
}
|
||||
else {
|
||||
failsafeValue += 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
|
||||
pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
|
||||
}
|
||||
failsafeValue += 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
|
||||
pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
|
||||
pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
|
||||
}
|
||||
|
||||
if (i & 1) {
|
||||
Pxx2Transport::addByte(pulseValueLow); // Low byte of channel
|
||||
Pxx2Transport::addByte(((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels
|
||||
Pxx2Transport::addByte(pulseValue >> 4); // High byte of channel
|
||||
}
|
||||
else {
|
||||
if (i & 1)
|
||||
addPulsesValues(pulseValueLow, pulseValue);
|
||||
else
|
||||
pulseValueLow = pulseValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,21 +106,17 @@ void Pxx2Pulses::setupChannelsFrame(uint8_t module)
|
||||
{
|
||||
addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_CHANNELS);
|
||||
|
||||
// FLAG0
|
||||
// Flag0
|
||||
uint8_t flag0 = addFlag0(module);
|
||||
|
||||
// FLAG1
|
||||
addFlag1(module);
|
||||
// Flag1
|
||||
addFlag1();
|
||||
|
||||
// Channels
|
||||
uint8_t channelsCount = sentModuleChannels(module);
|
||||
addChannels(module, flag0 & PXX2_CHANNELS_FLAG0_FAILSAFE, g_model.moduleData[module].channelsStart);
|
||||
if (channelsCount > 8) {
|
||||
addChannels(module, flag0 & PXX2_CHANNELS_FLAG0_FAILSAFE, g_model.moduleData[module].channelsStart + 8);
|
||||
if (channelsCount > 16) {
|
||||
addChannels(module, flag0 & PXX2_CHANNELS_FLAG0_FAILSAFE, g_model.moduleData[module].channelsStart + 16);
|
||||
}
|
||||
}
|
||||
// Failsafe / Channels
|
||||
if (flag0 & PXX2_CHANNELS_FLAG0_FAILSAFE)
|
||||
addFailsafe(module);
|
||||
else
|
||||
addChannels(module);
|
||||
}
|
||||
|
||||
void Pxx2Pulses::setupTelemetryFrame(uint8_t module)
|
||||
|
||||
@@ -158,9 +158,13 @@ class Pxx2Pulses: public PxxPulses<Pxx2Transport> {
|
||||
|
||||
uint8_t addFlag0(uint8_t module);
|
||||
|
||||
void addFlag1(uint8_t module);
|
||||
void addFlag1();
|
||||
|
||||
void addChannels(uint8_t module, uint8_t sendFailsafe, uint8_t firstChannel);
|
||||
void addPulsesValues(uint16_t low, uint16_t high);
|
||||
|
||||
void addChannels(uint8_t module);
|
||||
|
||||
void addFailsafe(uint8_t module);
|
||||
|
||||
void addCrc()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
|
||||
void i2c2Init()
|
||||
{
|
||||
I2C_DeInit(I2CX);
|
||||
|
||||
I2C_InitTypeDef I2C_InitStructure;
|
||||
I2C_InitStructure.I2C_ClockSpeed = I2CX_SPEED;
|
||||
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
|
||||
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
|
||||
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
|
||||
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
|
||||
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||||
I2C_Init(I2CX, &I2C_InitStructure);
|
||||
I2C_Cmd(I2CX, ENABLE);
|
||||
|
||||
GPIO_PinAFConfig(I2CX_SCL_GPIO, I2CX_SCL_GPIO_PinSource, I2CX_GPIO_AF);
|
||||
GPIO_PinAFConfig(I2CX_SDA_GPIO, I2CX_SDA_GPIO_PinSource, I2CX_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = I2CX_SCL_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(I2CX_SCL_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = I2CX_SDA_GPIO_PIN;
|
||||
GPIO_Init(I2CX_SDA_GPIO, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
#define I2C_TIMEOUT_MAX 1000
|
||||
bool I2C_WaitEvent(uint32_t event)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT_MAX;
|
||||
while (!I2C_CheckEvent(I2CX, event)) {
|
||||
if ((timeout--) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2C2_WaitEventCleared(uint32_t event)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT_MAX;
|
||||
while (I2C_CheckEvent(I2CX, event)) {
|
||||
if ((timeout--) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void setVolume(uint8_t volume)
|
||||
{
|
||||
if (!I2C2_WaitEventCleared(I2C_FLAG_BUSY))
|
||||
return;
|
||||
|
||||
I2C_GenerateSTART(I2CX, ENABLE);
|
||||
if (!I2C2_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
|
||||
return;
|
||||
|
||||
I2C_Send7bitAddress(I2C, I2C_ADDRESS_VOLUME, I2C_Direction_Transmitter);
|
||||
if (!I2C2_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
return;
|
||||
|
||||
I2C_SendData(I2CX, 0);
|
||||
if (!I2C2_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
|
||||
return;
|
||||
I2C_SendData(I2CX, volume);
|
||||
if (!I2C2_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
return;
|
||||
|
||||
I2C_GenerateSTOP(I2CX, ENABLE);
|
||||
}
|
||||
|
||||
int32_t getVolume()
|
||||
{
|
||||
return -1; // TODO
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user