From f6c34a23039510505b55b93a501dbd06203ece62 Mon Sep 17 00:00:00 2001
From: Martin Kojtal <0xc0170@gmail.com>
Date: Tue, 5 Sep 2017 12:41:18 +0100
Subject: [PATCH] SerialBase and CAN: fix Callbacks comparision

As Callback currently does not have fully functional comparision (see #5017),
we workaround by doing null check.
---
 drivers/CAN.cpp        | 16 ++++++++--------
 drivers/SerialBase.cpp | 28 +++++++++++++---------------
 2 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/drivers/CAN.cpp b/drivers/CAN.cpp
index 226a546e94..e49b7adfcb 100644
--- a/drivers/CAN.cpp
+++ b/drivers/CAN.cpp
@@ -22,13 +22,11 @@
 
 namespace mbed {
 
-static void donothing() {}
-
 CAN::CAN(PinName rd, PinName td) : _can(), _irq() {
     // No lock needed in constructor
 
     for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
-        _irq[i] = callback(donothing);
+        _irq[i] = NULL;
     }
 
     can_init(&_can, rd, td);
@@ -39,7 +37,7 @@ CAN::CAN(PinName rd, PinName td, int hz) : _can(), _irq() {
     // No lock needed in constructor
 
     for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
-        _irq[i] = callback(donothing);
+        _irq[i] = NULL;
     }
 
     can_init_freq(&_can, rd, td, hz);
@@ -117,17 +115,17 @@ void CAN::attach(Callback<void()> func, IrqType type) {
     lock();
     if (func) {
         // lock deep sleep only the first time
-        if (_irq[(CanIrqType)type] == callback(donothing)) {
+        if (!_irq[(CanIrqType)type]) {
             sleep_manager_lock_deep_sleep();
         }
         _irq[(CanIrqType)type] = func;
         can_irq_set(&_can, (CanIrqType)type, 1);
     } else {
         // unlock deep sleep only the first time
-        if (_irq[(CanIrqType)type] != callback(donothing)) {
+        if (_irq[(CanIrqType)type]) {
             sleep_manager_unlock_deep_sleep();
         }
-        _irq[(CanIrqType)type] = callback(donothing);
+        _irq[(CanIrqType)type] = NULL;
         can_irq_set(&_can, (CanIrqType)type, 0);
     }
     unlock();
@@ -135,7 +133,9 @@ void CAN::attach(Callback<void()> func, IrqType type) {
 
 void CAN::_irq_handler(uint32_t id, CanIrqType type) {
     CAN *handler = (CAN*)id;
-    handler->_irq[type].call();
+    if (handler->_irq[type]) {
+        handler->_irq[type].call();
+    }
 }
 
 void CAN::lock() {
diff --git a/drivers/SerialBase.cpp b/drivers/SerialBase.cpp
index c171d1487b..e07a44149d 100644
--- a/drivers/SerialBase.cpp
+++ b/drivers/SerialBase.cpp
@@ -22,21 +22,17 @@
 
 namespace mbed {
 
-static void donothing() {};
-static void donothing2(int arg) {};
-
-
 SerialBase::SerialBase(PinName tx, PinName rx, int baud) :
 #if DEVICE_SERIAL_ASYNCH
                                                  _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
-                                                 _rx_usage(DMA_USAGE_NEVER), _tx_callback(donothing2),
-                                                 _rx_callback(donothing2),
+                                                 _rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL),
+                                                 _rx_callback(NULL),
 #endif
                                                 _serial(), _baud(baud) {
     // No lock needed in the constructor
 
     for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
-        _irq[i] = donothing;
+        _irq[i] = NULL;
     }
 
     serial_init(&_serial, tx, rx);
@@ -78,17 +74,17 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
     core_util_critical_section_enter();
     if (func) {
         // lock deep sleep only the first time
-        if (_irq[type] == donothing) {
+        if (!_irq[type]) {
             sleep_manager_lock_deep_sleep();
         } 
         _irq[type] = func;
         serial_irq_set(&_serial, (SerialIrq)type, 1);
     } else {
         // unlock deep sleep only the first time
-        if (_irq[type] != donothing) {
+        if (_irq[type]) {
             sleep_manager_unlock_deep_sleep();
         } 
-        _irq[type] = donothing;
+        _irq[type] = NULL;
         serial_irq_set(&_serial, (SerialIrq)type, 0);
     }
     core_util_critical_section_exit();
@@ -97,7 +93,9 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
 
 void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) {
     SerialBase *handler = (SerialBase*)id;
-    handler->_irq[irq_type]();
+    if (handler->_irq[irq_type]) {
+        handler->_irq[irq_type]();
+    }
 }
 
 int SerialBase::_base_getc() {
@@ -192,20 +190,20 @@ void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_wi
 void SerialBase::abort_write(void)
 {
     // rx might still be active
-    if (_rx_callback == &donothing2) {
+    if (_rx_callback) {
         sleep_manager_unlock_deep_sleep();
     }
-    _tx_callback = donothing2;
+    _tx_callback = NULL;
     serial_tx_abort_asynch(&_serial);
 }
 
 void SerialBase::abort_read(void)
 {
     // tx might still be active
-    if (_tx_callback == &donothing2) {
+    if (_tx_callback) {
         sleep_manager_unlock_deep_sleep();
     }
-    _rx_callback = donothing2;
+    _rx_callback = NULL;
     serial_rx_abort_asynch(&_serial);
 }