mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-26 09:36:13 +01:00
Bugfix: allocate enough bytes for digital pins. Add more sanity checks when allocating memory
This commit is contained in:
parent
818e05b425
commit
fb414a7a50
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* © 2022, Peter Cole. All rights reserved.
|
* © 2022, Peter Cole. All rights reserved.
|
||||||
|
* © 2024, Harald Barth. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of EX-CommandStation
|
* This file is part of EX-CommandStation
|
||||||
*
|
*
|
||||||
|
@ -98,34 +99,53 @@ private:
|
||||||
_numAnaloguePins = receiveBuffer[2];
|
_numAnaloguePins = receiveBuffer[2];
|
||||||
|
|
||||||
// See if we already have suitable buffers assigned
|
// See if we already have suitable buffers assigned
|
||||||
size_t digitalBytesNeeded = (_numDigitalPins + 7) / 8;
|
if (_numDigitalPins>0) {
|
||||||
if (_digitalPinBytes < digitalBytesNeeded) {
|
size_t digitalBytesNeeded = (_numDigitalPins + 7) / 8;
|
||||||
// Not enough space, free any existing buffer and allocate a new one
|
if (_digitalPinBytes < digitalBytesNeeded) {
|
||||||
if (_digitalPinBytes > 0) free(_digitalInputStates);
|
// Not enough space, free any existing buffer and allocate a new one
|
||||||
_digitalInputStates = (byte*) calloc(_digitalPinBytes, 1);
|
if (_digitalPinBytes > 0) free(_digitalInputStates);
|
||||||
_digitalPinBytes = digitalBytesNeeded;
|
if ((_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) {
|
||||||
}
|
_digitalPinBytes = digitalBytesNeeded;
|
||||||
size_t analogueBytesNeeded = _numAnaloguePins * 2;
|
} else {
|
||||||
if (_analoguePinBytes < analogueBytesNeeded) {
|
DIAG(F("EX-IOExpander I2C:%s ERROR alloc %d bytes"), _I2CAddress.toString(), digitalBytesNeeded);
|
||||||
// Free any existing buffers and allocate new ones.
|
_deviceState = DEVSTATE_FAILED;
|
||||||
if (_analoguePinBytes > 0) {
|
_digitalPinBytes = 0;
|
||||||
free(_analogueInputBuffer);
|
return;
|
||||||
free(_analogueInputStates);
|
}
|
||||||
free(_analoguePinMap);
|
|
||||||
}
|
}
|
||||||
_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
|
||||||
_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
|
||||||
_analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1);
|
|
||||||
_analoguePinBytes = analogueBytesNeeded;
|
|
||||||
}
|
}
|
||||||
} else {
|
if (_numAnaloguePins>0) {
|
||||||
DIAG(F("EX-IOExpander I2C:%s ERROR configuring device"), _I2CAddress.toString());
|
size_t analogueBytesNeeded = _numAnaloguePins * 2;
|
||||||
_deviceState = DEVSTATE_FAILED;
|
if (_analoguePinBytes < analogueBytesNeeded) {
|
||||||
return;
|
// Free any existing buffers and allocate new ones.
|
||||||
}
|
if (_analoguePinBytes > 0) {
|
||||||
|
free(_analogueInputBuffer);
|
||||||
|
free(_analogueInputStates);
|
||||||
|
free(_analoguePinMap);
|
||||||
|
}
|
||||||
|
_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
||||||
|
_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
||||||
|
_analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1);
|
||||||
|
if (_analogueInputStates != NULL &&
|
||||||
|
_analogueInputBuffer != NULL &&
|
||||||
|
_analoguePinMap != NULL) {
|
||||||
|
_analoguePinBytes = analogueBytesNeeded;
|
||||||
|
} else {
|
||||||
|
DIAG(F("EX-IOExpander I2C:%s ERROR alloc analog pin bytes"), _I2CAddress.toString());
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
_analoguePinBytes = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DIAG(F("EX-IOExpander I2C:%s ERROR configuring device"), _I2CAddress.toString());
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// We now need to retrieve the analogue pin map
|
// We now need to retrieve the analogue pin map if there are analogue pins
|
||||||
if (status == I2C_STATUS_OK) {
|
if (status == I2C_STATUS_OK && _numAnaloguePins>0) {
|
||||||
commandBuffer[0] = EXIOINITA;
|
commandBuffer[0] = EXIOINITA;
|
||||||
status = I2CManager.read(_I2CAddress, _analoguePinMap, _numAnaloguePins, commandBuffer, 1);
|
status = I2CManager.read(_I2CAddress, _analoguePinMap, _numAnaloguePins, commandBuffer, 1);
|
||||||
}
|
}
|
||||||
|
@ -239,7 +259,7 @@ private:
|
||||||
|
|
||||||
// If we're not doing anything now, check to see if a new input transfer is due.
|
// If we're not doing anything now, check to see if a new input transfer is due.
|
||||||
if (_readState == RDS_IDLE) {
|
if (_readState == RDS_IDLE) {
|
||||||
if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
|
if (_numDigitalPins>0 && currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
|
||||||
// Issue new read request for digital states. As the request is non-blocking, the buffer has to
|
// Issue new read request for digital states. As the request is non-blocking, the buffer has to
|
||||||
// be allocated from heap (object state).
|
// be allocated from heap (object state).
|
||||||
_readCommandBuffer[0] = EXIORDD;
|
_readCommandBuffer[0] = EXIORDD;
|
||||||
|
@ -247,7 +267,7 @@ private:
|
||||||
// non-blocking read
|
// non-blocking read
|
||||||
_lastDigitalRead = currentMicros;
|
_lastDigitalRead = currentMicros;
|
||||||
_readState = RDS_DIGITAL;
|
_readState = RDS_DIGITAL;
|
||||||
} else if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
|
} else if (_numAnaloguePins>0 && currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
|
||||||
// Issue new read for analogue input states
|
// Issue new read for analogue input states
|
||||||
_readCommandBuffer[0] = EXIORDAN;
|
_readCommandBuffer[0] = EXIORDAN;
|
||||||
I2CManager.read(_I2CAddress, _analogueInputBuffer,
|
I2CManager.read(_I2CAddress, _analogueInputBuffer,
|
||||||
|
@ -362,14 +382,14 @@ private:
|
||||||
uint8_t _minorVer = 0;
|
uint8_t _minorVer = 0;
|
||||||
uint8_t _patchVer = 0;
|
uint8_t _patchVer = 0;
|
||||||
|
|
||||||
uint8_t* _digitalInputStates;
|
uint8_t* _digitalInputStates = NULL;
|
||||||
uint8_t* _analogueInputStates;
|
uint8_t* _analogueInputStates = NULL;
|
||||||
uint8_t* _analogueInputBuffer; // buffer for I2C input transfers
|
uint8_t* _analogueInputBuffer = NULL; // buffer for I2C input transfers
|
||||||
uint8_t _readCommandBuffer[1];
|
uint8_t _readCommandBuffer[1];
|
||||||
|
|
||||||
uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
||||||
uint8_t _analoguePinBytes = 0; // Size of allocated memory buffers (may be longer than needed)
|
uint8_t _analoguePinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
||||||
uint8_t* _analoguePinMap;
|
uint8_t* _analoguePinMap = NULL;
|
||||||
I2CRB _i2crb;
|
I2CRB _i2crb;
|
||||||
|
|
||||||
enum {RDS_IDLE, RDS_DIGITAL, RDS_ANALOGUE}; // Read operation states
|
enum {RDS_IDLE, RDS_DIGITAL, RDS_ANALOGUE}; // Read operation states
|
||||||
|
|
Loading…
Reference in New Issue
Block a user