int I2C::transfer(i2c_msg_s *msgv, unsigned msgs) { int ret; unsigned retry_count = 0; /* force the device address and Frequency into the message vector */ for (unsigned i = 0; i < msgs; i++) { msgv[i].frequency = _bus_clocks[_bus - 1]; msgv[i].addr = _address; } do { ret = I2C_TRANSFER(_dev, msgv, msgs); /* success */ if (ret == OK) { break; } /* if we have already retried once, or we are going to give up, then reset the bus */ if ((retry_count >= 1) || (retry_count >= _retries)) { I2C_RESET(_dev); } } while (retry_count++ < _retries); return ret; }
int I2C::transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len) { struct i2c_msg_s msgv[2]; unsigned msgs; int ret; unsigned retry_count = 0; do { // DEVICE_DEBUG("transfer out %p/%u in %p/%u", send, send_len, recv, recv_len); msgs = 0; if (send_len > 0) { msgv[msgs].frequency = _bus_clocks[_bus - 1]; msgv[msgs].addr = _address; msgv[msgs].flags = 0; msgv[msgs].buffer = const_cast<uint8_t *>(send); msgv[msgs].length = send_len; msgs++; } if (recv_len > 0) { msgv[msgs].frequency = _bus_clocks[_bus - 1];; msgv[msgs].addr = _address; msgv[msgs].flags = I2C_M_READ; msgv[msgs].buffer = recv; msgv[msgs].length = recv_len; msgs++; } if (msgs == 0) { return -EINVAL; } ret = I2C_TRANSFER(_dev, &msgv[0], msgs); /* success */ if (ret == OK) { break; } /* if we have already retried once, or we are going to give up, then reset the bus */ if ((retry_count >= 1) || (retry_count >= _retries)) { I2C_RESET(_dev); } } while (retry_count++ < _retries); return ret; }
static int i2cdrvr_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { FAR struct inode *inode = filep->f_inode; FAR struct i2c_driver_s *priv; FAR struct i2c_transfer_s *transfer; int ret; i2cvdbg("cmd=%d arg=%lu\n", cmd, arg); /* Get our private data structure */ DEBUGASSERT(filep != NULL && filep->f_inode != NULL); inode = filep->f_inode; priv = (FAR struct i2c_driver_s *)inode->i_private; DEBUGASSERT(priv); /* Get exclusive access to the I2C driver state structure */ ret = sem_wait(&priv->exclsem); if (ret < 0) { int errcode = errno; DEBUGASSERT(errcode < 0); return -errcode; } /* Process the IOCTL command */ switch (cmd) { /* Command: I2CIOC_TRANSFER * Description: Perform an I2C transfer * Argument: A reference to an instance of struct i2c_transfer_s. * Dependencies: CONFIG_I2C_DRIVER */ case I2CIOC_TRANSFER: { /* Get the reference to the i2c_transfer_s structure */ transfer = (FAR struct i2c_transfer_s *)((uintptr_t)arg); DEBUGASSERT(transfer != NULL); /* Perform the transfer */ ret = I2C_TRANSFER(priv->i2c, transfer->msgv, transfer->msgc); } break; #ifdef CONFIG_I2C_RESET /* Command: I2CIOC_RESET * Description: Perform an I2C bus reset in an attempt to break loose * stuck I2C devices. * Argument: None * Dependencies: CONFIG_I2C_DRIVER && CONFIG_I2C_RESET */ case I2CIOC_RESET: { ret = I2C_RESET(priv->i2c); } break; #endif default: ret = -ENOTTY; break; } sem_post(&priv->exclsem); return ret; }