1e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang/* 2e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Author: Brendan Le Foll <brendan.le.foll@intel.com> 3e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Copyright (c) 2014 Intel Corporation. 4e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * 5e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Code is modified from the RoadNarrows-robotics i2c library (distributed under 6e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * the MIT license, license is included verbatim under src/i2c/LICENSE) 7e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * 8e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Permission is hereby granted, free of charge, to any person obtaining 9e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * a copy of this software and associated documentation files (the 10e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * "Software"), to deal in the Software without restriction, including 11e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * without limitation the rights to use, copy, modify, merge, publish, 12e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * distribute, sublicense, and/or sell copies of the Software, and to 13e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * permit persons to whom the Software is furnished to do so, subject to 14e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * the following conditions: 15e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * 16e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * The above copyright notice and this permission notice shall be 17e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * included in all copies or substantial portions of the Software. 18e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * 19e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang */ 27e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 28e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "i2c.h" 29e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "mraa_internal.h" 30e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 31e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <stdlib.h> 32e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <unistd.h> 33e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <fcntl.h> 34e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <inttypes.h> 35e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <sys/types.h> 36e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <sys/errno.h> 37e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <sys/ioctl.h> 38e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "linux/i2c-dev.h" 39e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 40e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 41e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangtypedef union i2c_smbus_data_union { 42e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang uint8_t byte; ///< data byte 43e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang unsigned short word; ///< data short word 44e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang uint8_t block[I2C_SMBUS_BLOCK_MAX + 2]; 45e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang ///< block[0] is used for length and one more for PEC 46e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} i2c_smbus_data_t; 47e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 48e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangtypedef struct i2c_smbus_ioctl_data_struct { 49e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang uint8_t read_write; ///< operation direction 50e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang uint8_t command; ///< ioctl command 51e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang int size; ///< data size 52e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t* data; ///< data 53e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} i2c_smbus_ioctl_data_t; 54e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 55e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 56e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang// static mraa_adv_func_t* func_table; 57e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 58e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangint 59e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_smbus_access(int fh, uint8_t read_write, uint8_t command, int size, i2c_smbus_data_t* data) 60e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 61e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_ioctl_data_t args; 62e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 63e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang args.read_write = read_write; 64e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang args.command = command; 65e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang args.size = size; 66e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang args.data = data; 67e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 68e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return ioctl(fh, I2C_SMBUS, &args); 69e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 70e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 71e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_i2c_context 72e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_init_internal(mraa_adv_func_t* advance_func, unsigned int bus) 73e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 74e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang mraa_result_t status = MRAA_SUCCESS; 75e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 76e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (advance_func == NULL) 77e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 78e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 796b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare mraa_i2c_context dev = (mraa_i2c_context) calloc(1, sizeof(struct _i2c)); 80e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (dev == NULL) { 81e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_CRIT, "i2c: Failed to allocate memory for context"); 82e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 83e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 84e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 85e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang dev->advance_func = advance_func; 86e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang dev->busnum = bus; 87e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 88e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_init_pre)) { 89e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang status = advance_func->i2c_init_pre(bus); 90e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (status != MRAA_SUCCESS) 91e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang goto init_internal_cleanup; 92e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 93e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 94e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_init_bus_replace)) { 95e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang status = dev->advance_func->i2c_init_bus_replace(dev); 96e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (status != MRAA_SUCCESS) 97e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang goto init_internal_cleanup; 98e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } else { 99e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang char filepath[32]; 100e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang snprintf(filepath, 32, "/dev/i2c-%u", bus); 101e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if ((dev->fh = open(filepath, O_RDWR)) < 1) { 102e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to open requested i2c port %s", filepath); 103e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang status = MRAA_ERROR_NO_RESOURCES; 104e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang goto init_internal_cleanup; 105e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 106e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 107e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (ioctl(dev->fh, I2C_FUNCS, &dev->funcs) < 0) { 108e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_CRIT, "i2c: Failed to get I2C_FUNC map from device"); 109e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang dev->funcs = 0; 110e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 111e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 112e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 113e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_init_post)) { 114e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang status = dev->advance_func->i2c_init_post(dev); 115e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (status != MRAA_SUCCESS) 116e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang goto init_internal_cleanup; 117e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 118e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 119e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 120e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhanginit_internal_cleanup: 121e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (status == MRAA_SUCCESS) { 122e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev; 1237d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban } else { 124e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (dev != NULL) 125e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang free(dev); 126e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 127e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 128e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 129e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 130e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 131e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_context 132e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_init(int bus) 133e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 134e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang mraa_board_t* board = plat; 135e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (board == NULL) { 136e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Platform Not Initialised"); 137e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 138e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 139e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 140e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_is_sub_platform_id(bus)) { 141e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_NOTICE, "i2c: Using sub platform"); 142e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang board = board->sub_platform; 143e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (board == NULL) { 144e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Sub platform Not Initialised"); 145e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 146e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 147e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang bus = mraa_get_sub_platform_index(bus); 148e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 149e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_NOTICE, "i2c: Selected bus %d", bus); 150e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 151e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (board->i2c_bus_count == 0) { 152e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "No i2c buses defined in platform"); 153e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 154e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 155e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (bus >= board->i2c_bus_count) { 156e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "Above i2c bus count"); 157e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return NULL; 158e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 159e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 160e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (board->i2c_bus[bus].bus_id == -1) { 161e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "Invalid i2c bus, moving to default i2c bus"); 162e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang bus = board->def_i2c_bus; 163e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 1646b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare if (!board->no_bus_mux) { 1656b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare int pos = board->i2c_bus[bus].sda; 1666b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare if (board->pins[pos].i2c.mux_total > 0) { 1676b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare if (mraa_setup_mux_mapped(board->pins[pos].i2c) != MRAA_SUCCESS) { 1686b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare syslog(LOG_ERR, "i2c: Failed to set-up i2c sda multiplexer"); 1696b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare return NULL; 1706b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare } 171e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 172e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 1736b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare pos = board->i2c_bus[bus].scl; 1746b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare if (board->pins[pos].i2c.mux_total > 0) { 1756b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare if (mraa_setup_mux_mapped(board->pins[pos].i2c) != MRAA_SUCCESS) { 1766b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare syslog(LOG_ERR, "i2c: Failed to set-up i2c scl multiplexer"); 1776b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare return NULL; 1786b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare } 179e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 180e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 181e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 182e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return mraa_i2c_init_internal(board->adv_func, (unsigned int) board->i2c_bus[bus].bus_id); 183e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 184e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 185e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 186e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_context 187e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_init_raw(unsigned int bus) 188e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 189e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return mraa_i2c_init_internal(plat == NULL ? NULL : plat->adv_func, bus); 190e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 191e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 192e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 193e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 194e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode) 195e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 196e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_set_frequency_replace)) { 197e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev->advance_func->i2c_set_frequency_replace(dev, mode); 198e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 199e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_ERROR_FEATURE_NOT_SUPPORTED; 200e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 201e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 202e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangint 203e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_read(mraa_i2c_context dev, uint8_t* data, int length) 204e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 205e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang int bytes_read = 0; 2067d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban if (IS_FUNC_DEFINED(dev, i2c_read_replace)) { 207e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang bytes_read = dev->advance_func->i2c_read_replace(dev, data, length); 2087d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban } 2097d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban else { 210e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang bytes_read = read(dev->fh, data, length); 2117d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban } 2127d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban if (bytes_read == length) { 2137d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban return length; 2147d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban } 2157d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban 2167d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban return 0; 217e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 218e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 219e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhanguint8_t 220e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_read_byte(mraa_i2c_context dev) 221e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 2227d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban if (IS_FUNC_DEFINED(dev, i2c_read_byte_replace)) 2237d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban return dev->advance_func->i2c_read_byte_replace(dev); 224e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t d; 225e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_READ, I2C_NOCMD, I2C_SMBUS_BYTE, &d) < 0) { 226e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to write"); 227e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return 0; 228e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 229e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return 0x0FF & d.byte; 230e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 231e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 232e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhanguint8_t 233e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_read_byte_data(mraa_i2c_context dev, uint8_t command) 234e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 235e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_read_byte_data_replace)) 236e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev->advance_func->i2c_read_byte_data_replace(dev, command); 237e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t d; 238e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_READ, command, I2C_SMBUS_BYTE_DATA, &d) < 0) { 239e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to write"); 240e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return 0; 241e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 242e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return 0x0FF & d.byte; 243e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 244e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 245e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhanguint16_t 246e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_read_word_data(mraa_i2c_context dev, uint8_t command) 247e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 2487d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban if (IS_FUNC_DEFINED(dev, i2c_read_word_data_replace)) 2497d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban return dev->advance_func->i2c_read_word_data_replace(dev, command); 250e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t d; 251e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_READ, command, I2C_SMBUS_WORD_DATA, &d) < 0) { 252e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to write"); 253e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return 0; 254e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 255e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return 0xFFFF & d.word; 256e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 257e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 258e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangint 259e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_read_bytes_data(mraa_i2c_context dev, uint8_t command, uint8_t* data, int length) 260e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 2617d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban if (IS_FUNC_DEFINED(dev, i2c_read_bytes_data_replace)) 2627d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban return dev->advance_func->i2c_read_bytes_data_replace(dev, command, data, length); 263e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang struct i2c_rdwr_ioctl_data d; 264e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang struct i2c_msg m[2]; 265e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 266e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[0].addr = dev->addr; 267e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[0].flags = 0x00; 268e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[0].len = 1; 269e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[0].buf = &command; 270e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[1].addr = dev->addr; 271e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[1].flags = I2C_M_RD; 272e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[1].len = length; 273e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang m[1].buf = data; 274e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 275e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang d.msgs = m; 276e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang d.nmsgs = 2; 277e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 278e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return ioctl(dev->fh, I2C_RDWR, &d) < 0 ? -1 : length; 279e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 280e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 281e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 282e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_write(mraa_i2c_context dev, const uint8_t* data, int length) 283e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 2847d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban if (IS_FUNC_DEFINED(dev, i2c_write_replace)) 2857d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban return dev->advance_func->i2c_write_replace(dev, data, length); 286e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t d; 287e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang int i; 288e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang uint8_t command = data[0]; 289e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 290e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang data = &data[1]; 291e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang length = length - 1; 292e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (length > I2C_SMBUS_I2C_BLOCK_MAX) { 293e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang length = I2C_SMBUS_I2C_BLOCK_MAX; 294e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 295e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 296e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang for (i = 1; i <= length; i++) { 297e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang d.block[i] = data[i - 1]; 298e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 299e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang d.block[0] = length; 300e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 301e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_WRITE, command, I2C_SMBUS_I2C_BLOCK_DATA, &d); 302e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 303e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 304e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 305e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_write_byte(mraa_i2c_context dev, const uint8_t data) 306e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 307e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_write_byte_replace)) { 308e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev->advance_func->i2c_write_byte_replace(dev, data); 309e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } else { 310e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, NULL) < 0) { 311e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to write"); 312e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_ERROR_INVALID_HANDLE; 313e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 314e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_SUCCESS; 315e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 316e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 317e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 318e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 319e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_write_byte_data(mraa_i2c_context dev, const uint8_t data, const uint8_t command) 320e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 321e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_write_byte_data_replace)) 322e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev->advance_func->i2c_write_byte_data_replace(dev, data, command); 323e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t d; 324e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang d.byte = data; 325e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_WRITE, command, I2C_SMBUS_BYTE_DATA, &d) < 0) { 326e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to write"); 327e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_ERROR_INVALID_HANDLE; 328e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 329e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_SUCCESS; 330e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 331e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 332e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 333e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_write_word_data(mraa_i2c_context dev, const uint16_t data, const uint8_t command) 334e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 335e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_write_word_data_replace)) 336e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev->advance_func->i2c_write_word_data_replace(dev, data, command); 337e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang i2c_smbus_data_t d; 338e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang d.word = data; 339e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_WRITE, command, I2C_SMBUS_WORD_DATA, &d) < 0) { 340e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to write"); 341e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_ERROR_INVALID_HANDLE; 342e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 343e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_SUCCESS; 344e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 345e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 346e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 347e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_address(mraa_i2c_context dev, uint8_t addr) 348e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 349e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (dev == NULL) { 350e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_ERROR_INVALID_HANDLE; 351e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 352e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 353e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang dev->addr = (int) addr; 354e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (IS_FUNC_DEFINED(dev, i2c_address_replace)) { 355e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return dev->advance_func->i2c_address_replace(dev, addr); 356e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } else { 357e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang if (ioctl(dev->fh, I2C_SLAVE_FORCE, addr) < 0) { 358e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang syslog(LOG_ERR, "i2c: Failed to set slave address %d", addr); 359e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_ERROR_INVALID_HANDLE; 360e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 361e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_SUCCESS; 362e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang } 363e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 364e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 365e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 366e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t 367e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_i2c_stop(mraa_i2c_context dev) 368e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{ 369e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang free(dev); 370e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang return MRAA_SUCCESS; 371e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang} 372e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang 373