@@ -110,6 +110,15 @@ static void deregister_device(i2c_dev_t *dev)
110110esp_err_t i2cdev_init (void )
111111{
112112 ESP_LOGV (TAG , "Initializing I2C subsystem..." );
113+
114+ // Guard against re-initialization to prevent resource leaks
115+ static bool initialized = false;
116+ if (initialized )
117+ {
118+ ESP_LOGW (TAG , "I2C subsystem already initialized, skipping re-initialization" );
119+ return ESP_OK ;
120+ }
121+
113122 memset (active_devices , 0 , sizeof (active_devices ));
114123 for (int i = 0 ; i < I2C_NUM_MAX ; i ++ )
115124 {
@@ -129,6 +138,8 @@ esp_err_t i2cdev_init(void)
129138 i2c_ports [i ].sda_pin_current = -1 ;
130139 i2c_ports [i ].scl_pin_current = -1 ;
131140 }
141+
142+ initialized = true; // Mark as initialized
132143 ESP_LOGV (TAG , "I2C subsystem initialized." );
133144 return ESP_OK ;
134145}
@@ -218,9 +229,16 @@ esp_err_t i2c_dev_delete_mutex(i2c_dev_t *dev)
218229 // Update port reference count if port is valid
219230 if (dev -> port < I2C_NUM_MAX )
220231 {
221- if (xSemaphoreTake (i2c_ports [dev -> port ].lock , pdMS_TO_TICKS (CONFIG_I2CDEV_TIMEOUT )) == pdTRUE )
232+ // Check if port mutex is initialized
233+ if (!i2c_ports [dev -> port ].lock )
234+ {
235+ ESP_LOGW (TAG , "[0x%02x at %d] Port mutex not initialized, skipping ref_count update" , dev -> addr , dev -> port );
236+ // Continue with cleanup - just skip the mutex-protected section
237+ }
238+ else if (xSemaphoreTake (i2c_ports [dev -> port ].lock , pdMS_TO_TICKS (CONFIG_I2CDEV_TIMEOUT )) == pdTRUE )
222239 {
223- if (i2c_ports [dev -> port ].installed && i2c_ports [dev -> port ].ref_count > 0 )
240+ // Only decrement ref_count if THIS device was actually added to the bus
241+ if (i2c_ports [dev -> port ].installed && i2c_ports [dev -> port ].ref_count > 0 && dev -> dev_handle != NULL )
224242 {
225243 i2c_ports [dev -> port ].ref_count -- ;
226244 ESP_LOGV (TAG , "[Port %d] Decremented ref_count to %" PRIu32 , dev -> port , i2c_ports [dev -> port ].ref_count );
@@ -245,6 +263,10 @@ esp_err_t i2c_dev_delete_mutex(i2c_dev_t *dev)
245263 i2c_ports [dev -> port ].scl_pin_current = -1 ;
246264 }
247265 }
266+ else if (dev -> dev_handle == NULL )
267+ {
268+ ESP_LOGV (TAG , "[0x%02x at %d] Device was never added to bus, skipping ref_count decrement" , dev -> addr , dev -> port );
269+ }
248270 xSemaphoreGive (i2c_ports [dev -> port ].lock );
249271 }
250272 else
@@ -336,6 +358,13 @@ static esp_err_t i2c_setup_port(i2c_dev_t *dev) // dev is non-const to update de
336358 esp_err_t res = ESP_OK ;
337359 i2c_port_state_t * port_state = & i2c_ports [dev -> port ];
338360
361+ // Check if i2cdev subsystem is initialized
362+ if (!port_state -> lock )
363+ {
364+ ESP_LOGE (TAG , "[Port %d] I2C subsystem not initialized - call i2cdev_init() first" , dev -> port );
365+ return ESP_ERR_INVALID_STATE ;
366+ }
367+
339368 ESP_LOGV (TAG , "[Port %d] Setup request for device 0x%02x" , dev -> port , dev -> addr );
340369 if (xSemaphoreTake (port_state -> lock , pdMS_TO_TICKS (CONFIG_I2CDEV_TIMEOUT )) != pdTRUE )
341370 {
@@ -498,6 +527,14 @@ static esp_err_t i2c_setup_device(i2c_dev_t *dev) // dev is non-const - modifies
498527 if (dev -> dev_handle == NULL )
499528 {
500529 i2c_port_state_t * port_state = & i2c_ports [dev -> port ];
530+
531+ // Check if i2cdev subsystem is initialized
532+ if (!port_state -> lock )
533+ {
534+ ESP_LOGE (TAG , "[0x%02x at %d] I2C subsystem not initialized - call i2cdev_init() first" , dev -> addr , dev -> port );
535+ return ESP_ERR_INVALID_STATE ;
536+ }
537+
501538 if (xSemaphoreTake (port_state -> lock , pdMS_TO_TICKS (CONFIG_I2CDEV_TIMEOUT )) != pdTRUE )
502539 {
503540 ESP_LOGE (TAG , "[0x%02x at %d] Could not take port mutex for device add" , dev -> addr , dev -> port );
@@ -750,12 +787,18 @@ esp_err_t i2c_dev_write(const i2c_dev_t *dev, const void *out_reg, size_t out_re
750787
751788esp_err_t i2c_dev_read_reg (const i2c_dev_t * dev , uint8_t reg , void * data , size_t size )
752789{
790+ if (!dev )
791+ return ESP_ERR_INVALID_ARG ;
792+
753793 ESP_LOGV (TAG , "[0x%02x at %d] i2c_dev_read_reg called (reg: 0x%02x, size: %u)" , dev -> addr , dev -> port , reg , size );
754794 return i2c_dev_read (dev , & reg , 1 , data , size );
755795}
756796
757797esp_err_t i2c_dev_write_reg (const i2c_dev_t * dev , uint8_t reg , const void * data , size_t size )
758798{
799+ if (!dev )
800+ return ESP_ERR_INVALID_ARG ;
801+
759802 ESP_LOGV (TAG , "[0x%02x at %d] i2c_dev_write_reg called (reg: 0x%02x, size: %u)" , dev -> addr , dev -> port , reg , size );
760803 return i2c_dev_write (dev , & reg , 1 , data , size );
761804}
@@ -824,6 +867,9 @@ esp_err_t i2c_dev_check_present(const i2c_dev_t *dev_const)
824867// The new driver implementation uses i2c_master_probe which doesn't need operation_type
825868esp_err_t i2c_dev_probe (const i2c_dev_t * dev , i2c_dev_type_t operation_type )
826869{
870+ if (!dev )
871+ return ESP_ERR_INVALID_ARG ;
872+
827873 ESP_LOGV (TAG , "[0x%02x at %d] Legacy probe called (operation_type %d), redirecting to new implementation" , dev -> addr , dev -> port , operation_type );
828874
829875 return i2c_dev_check_present (dev );
@@ -895,3 +941,46 @@ esp_err_t i2cdev_done(void)
895941 ESP_LOGV (TAG , "I2C subsystem cleanup finished with result: %d" , result );
896942 return result ;
897943}
944+
945+ esp_err_t i2cdev_get_shared_handle (i2c_port_t port , void * * bus_handle )
946+ {
947+ if (port >= I2C_NUM_MAX || bus_handle == NULL )
948+ {
949+ ESP_LOGE (TAG , "Invalid arguments: port=%d, bus_handle=%p" , port , bus_handle );
950+ return ESP_ERR_INVALID_ARG ;
951+ }
952+
953+ i2c_port_state_t * port_state = & i2c_ports [port ];
954+
955+ // Check if i2cdev subsystem is initialized
956+ if (port_state -> lock == NULL )
957+ {
958+ ESP_LOGE (TAG , "[Port %d] I2C subsystem not initialized - call i2cdev_init() first" , port );
959+ return ESP_ERR_INVALID_STATE ;
960+ }
961+
962+ // Take port mutex for thread-safe access
963+ if (xSemaphoreTake (port_state -> lock , pdMS_TO_TICKS (CONFIG_I2CDEV_TIMEOUT )) != pdTRUE )
964+ {
965+ ESP_LOGE (TAG , "[Port %d] Could not take port mutex for get_shared_handle" , port );
966+ return ESP_ERR_TIMEOUT ;
967+ }
968+
969+ // Check if bus is initialized
970+ if (!port_state -> installed || port_state -> bus_handle == NULL )
971+ {
972+ xSemaphoreGive (port_state -> lock );
973+ ESP_LOGE (TAG , "[Port %d] Bus not initialized - create an i2c_dev_t device first to initialize the bus" , port );
974+ return ESP_ERR_INVALID_STATE ;
975+ }
976+
977+ // Return the bus handle
978+ * bus_handle = (void * )port_state -> bus_handle ;
979+
980+ ESP_LOGI (TAG , "[Port %d] Shared bus handle retrieved: %p (SDA=%d, SCL=%d, ref_count=%" PRIu32 ")" ,
981+ port , port_state -> bus_handle , port_state -> sda_pin_current ,
982+ port_state -> scl_pin_current , port_state -> ref_count );
983+
984+ xSemaphoreGive (port_state -> lock );
985+ return ESP_OK ;
986+ }
0 commit comments