From 137ed6702935b6c43d027dcd49fa52dc101f8e6e Mon Sep 17 00:00:00 2001
From: Laurent Meunier <laurent.meunier@st.com>
Date: Fri, 10 Aug 2018 10:15:47 +0200
Subject: [PATCH] Handle I2C scan with specific call to HAL_I2C_IsDeviceReady

When size is 0, the objective is to check if device is there and ready.
A typical use case is to scan through all addresses to check for
available slaves.

So we're checking the various error cases to report to application.
---
 cores/arduino/stm32/twi.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/cores/arduino/stm32/twi.c b/cores/arduino/stm32/twi.c
index ccd633fb40..c715f46808 100644
--- a/cores/arduino/stm32/twi.c
+++ b/cores/arduino/stm32/twi.c
@@ -355,6 +355,11 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
   uint32_t tickstart = HAL_GetTick();
   uint32_t delta = 0;
 
+  /* When size is 0, this is usually an I2C scan / ping to check if device is there and ready */
+  if (size == 0) {
+    return i2c_IsDeviceReady(obj, dev_address, 1);
+  }
+
   do{
     if(HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size) == HAL_OK){
       ret = I2C_OK;
@@ -447,8 +452,19 @@ i2c_status_e i2c_IsDeviceReady(i2c_t *obj, uint8_t devAddr, uint32_t trials)
 {
   i2c_status_e ret = HAL_OK;
 
-  if(HAL_I2C_IsDeviceReady( &(obj->handle), devAddr, trials, I2C_TIMEOUT_TICK) != HAL_OK) {
-    ret = I2C_BUSY;
+  switch (HAL_I2C_IsDeviceReady( &(obj->handle), devAddr, trials, I2C_TIMEOUT_TICK)) {
+    case HAL_OK:
+      ret = HAL_OK;
+      break;
+    case HAL_TIMEOUT:
+      ret = I2C_TIMEOUT;
+      break;
+    case HAL_BUSY:
+      ret = I2C_BUSY;
+      break;
+    default:
+      ret = I2C_TIMEOUT;
+      break;
   }
 
   return ret;