Skip to content

Commit b14172f

Browse files
committed
Use locks to prevent race conditions in HCICordioTransport
1 parent 9263b3a commit b14172f

File tree

4 files changed

+41
-8
lines changed

4 files changed

+41
-8
lines changed

src/utility/HCI.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,24 @@ void HCIClass::poll(unsigned long timeout)
136136
HCITransport.wait(timeout);
137137
}
138138

139+
HCITransport.lockForRead();
139140
while (HCITransport.available()) {
140141
byte b = HCITransport.read();
141142

142143
if (_recvIndex >= (int)sizeof(_recvBuffer)) {
143144
_recvIndex = 0;
144145
if (_debug) {
146+
HCITransport.unlockForRead();
145147
_debug->println("_recvBuffer overflow");
148+
HCITransport.lockForRead();
146149
}
147150
}
148151

149152
_recvBuffer[_recvIndex++] = b;
150153

151154
if (_recvBuffer[0] == HCI_ACLDATA_PKT) {
152155
if (_recvIndex > 5 && _recvIndex >= (5 + (_recvBuffer[3] + (_recvBuffer[4] << 8)))) {
156+
HCITransport.unlockForRead();
153157
if (_debug) {
154158
dumpPkt("HCI ACLDATA RX <- ", _recvIndex, _recvBuffer);
155159
}
@@ -164,9 +168,11 @@ void HCIClass::poll(unsigned long timeout)
164168
#ifdef ARDUINO_AVR_UNO_WIFI_REV2
165169
digitalWrite(NINA_RTS, LOW);
166170
#endif
171+
HCITransport.lockForRead();
167172
}
168173
} else if (_recvBuffer[0] == HCI_EVENT_PKT) {
169174
if (_recvIndex > 3 && _recvIndex >= (3 + _recvBuffer[2])) {
175+
HCITransport.unlockForRead();
170176
if (_debug) {
171177
dumpPkt("HCI EVENT RX <- ", _recvIndex, _recvBuffer);
172178
}
@@ -182,19 +188,23 @@ void HCIClass::poll(unsigned long timeout)
182188
#ifdef ARDUINO_AVR_UNO_WIFI_REV2
183189
digitalWrite(NINA_RTS, LOW);
184190
#endif
191+
HCITransport.lockForRead();
185192
}
186193
} else {
187194
_recvIndex = 0;
188195

189196
if (_debug) {
197+
HCITransport.unlockForRead();
190198
_debug->println(b, HEX);
199+
HCITransport.lockForRead();
191200
}
192201
}
193202
}
194203

195204
#ifdef ARDUINO_AVR_UNO_WIFI_REV2
196205
digitalWrite(NINA_RTS, HIGH);
197206
#endif
207+
HCITransport.unlockForRead();
198208
}
199209

200210
int HCIClass::reset()

src/utility/HCICordioTransport.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,11 @@ void HCICordioTransportClass::end()
254254

255255
void HCICordioTransportClass::wait(unsigned long timeout)
256256
{
257-
if (available()) {
258-
return;
257+
{
258+
mbed::CriticalSectionLock critical_section;
259+
if (available()) {
260+
return;
261+
}
259262
}
260263

261264
// wait for handleRxData to signal
@@ -277,6 +280,14 @@ int HCICordioTransportClass::read()
277280
return _rxBuf.read_char();
278281
}
279282

283+
void HCICordioTransportClass::lockForRead() {
284+
mbed::CriticalSectionLock::enable();
285+
}
286+
287+
void HCICordioTransportClass::unlockForRead() {
288+
mbed::CriticalSectionLock::disable();
289+
}
290+
280291
size_t HCICordioTransportClass::write(const uint8_t* data, size_t length)
281292
{
282293
if (!_begun) {
@@ -299,13 +310,16 @@ size_t HCICordioTransportClass::write(const uint8_t* data, size_t length)
299310

300311
void HCICordioTransportClass::handleRxData(uint8_t* data, uint8_t len)
301312
{
302-
if (_rxBuf.availableForStore() < len) {
303-
// drop!
304-
return;
305-
}
313+
{
314+
mbed::CriticalSectionLock critical_section;
315+
if (_rxBuf.availableForStore() < len) {
316+
// drop!
317+
return;
318+
}
306319

307-
for (int i = 0; i < len; i++) {
308-
_rxBuf.store_char(data[i]);
320+
for (int i = 0; i < len; i++) {
321+
_rxBuf.store_char(data[i]);
322+
}
309323
}
310324

311325
bleEventFlags.set(0x01);

src/utility/HCICordioTransport.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class HCICordioTransportClass : public HCITransportInterface {
4040
virtual int peek();
4141
virtual int read();
4242

43+
virtual void lockForRead() override;
44+
virtual void unlockForRead() override;
45+
4346
virtual size_t write(const uint8_t* data, size_t length);
4447

4548
private:

src/utility/HCITransport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ class HCITransportInterface {
3333
virtual int peek() = 0;
3434
virtual int read() = 0;
3535

36+
// Some transports require a lock to use available/peek/read
37+
// These methods allow to keep the lock while reading an unknown number of bytes
38+
// These methods might disable interrupts. Only keep the lock as long as necessary.
39+
virtual void lockForRead() {}
40+
virtual void unlockForRead() {}
41+
3642
virtual size_t write(const uint8_t* data, size_t length) = 0;
3743
};
3844

0 commit comments

Comments
 (0)