| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * MIT License | ||
| 3 | |||
| 4 | Copyright (c) 2017 DeeplyEmbedded | ||
| 5 | |||
| 6 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 7 | of this software and associated documentation files (the "Software"), to deal | ||
| 8 | in the Software without restriction, including without limitation the rights | ||
| 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 10 | copies of the Software, and to permit persons to whom the Software is | ||
| 11 | furnished to do so, subject to the following conditions: | ||
| 12 | |||
| 13 | The above copyright notice and this permission notice shall be included in all | ||
| 14 | copies or substantial portions of the Software. | ||
| 15 | |||
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 22 | SOFTWARE. | ||
| 23 | |||
| 24 | * I2C.c | ||
| 25 | * | ||
| 26 | * Created on : September 19, 2017 | ||
| 27 | * Author : Vinay Divakar | ||
| 28 | * Description : This is an I2C Library for the BeagleBone that consists of the API's to support the standard | ||
| 29 | * I2C operations. | ||
| 30 | * Website : www.deeplyembedded.org | ||
| 31 | */ | ||
| 32 | |||
| 33 | /*Libs Includes*/ | ||
| 34 | #include <linux/i2c-dev.h> | ||
| 35 | #include <linux/i2c.h> | ||
| 36 | #include <sys/ioctl.h> | ||
| 37 | #include <fcntl.h> | ||
| 38 | #include <stdio.h> | ||
| 39 | #include <unistd.h> | ||
| 40 | |||
| 41 | /* Header Files */ | ||
| 42 | #include "I2C.h" | ||
| 43 | |||
| 44 | /* Exposed objects for i2c-x */ | ||
| 45 | I2C_DeviceT I2C_DEV_2; | ||
| 46 | |||
| 47 | /**************************************************************** | ||
| 48 | * Function Name : Open_device | ||
| 49 | * Description : Opens the I2C device to use | ||
| 50 | * Returns : 0 on success, -1 on failure | ||
| 51 | * Params @i2c_dev_path: Path to the I2C device | ||
| 52 | * @fd: Variable to store the file handler | ||
| 53 | ****************************************************************/ | ||
| 54 | 12 | int Open_device(const char* i2c_dev_path, int* fd) { | |
| 55 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if ((*fd = open(i2c_dev_path, O_RDWR)) < 0) |
| 56 | ✗ | return -1; | |
| 57 | else | ||
| 58 | 12 | return 0; | |
| 59 | } | ||
| 60 | |||
| 61 | /**************************************************************** | ||
| 62 | * Function Name : Close_device | ||
| 63 | * Description : Closes the I2C device in use | ||
| 64 | * Returns : 0 on success, -1 on failure | ||
| 65 | * Params : @fd: file descriptor | ||
| 66 | ****************************************************************/ | ||
| 67 | ✗ | int Close_device(int fd) { | |
| 68 | ✗ | if (close(fd) == -1) | |
| 69 | ✗ | return -1; | |
| 70 | else | ||
| 71 | ✗ | return 0; | |
| 72 | } | ||
| 73 | |||
| 74 | /**************************************************************** | ||
| 75 | * Function Name : Set_slave_addr | ||
| 76 | * Description : Connect to the Slave device | ||
| 77 | * Returns : 0 on success, -1 on failure | ||
| 78 | * Params @fd: File descriptor | ||
| 79 | * @slave_addr: Address of the slave device to | ||
| 80 | * talk to. | ||
| 81 | ****************************************************************/ | ||
| 82 | 12 | int Set_slave_addr(int fd, unsigned char slave_addr) { | |
| 83 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (ioctl(fd, I2C_SLAVE, slave_addr) < 0) |
| 84 | ✗ | return -1; | |
| 85 | else | ||
| 86 | 12 | return 0; | |
| 87 | } | ||
| 88 | |||
| 89 | /**************************************************************** | ||
| 90 | * Function Name : i2c_write | ||
| 91 | * Description : Write a byte on SDA | ||
| 92 | * Returns : No. of bytes written on success, -1 on failure | ||
| 93 | * Params @fd: File descriptor | ||
| 94 | * @data: data to write on SDA | ||
| 95 | ****************************************************************/ | ||
| 96 | ✗ | int i2c_write(int fd, unsigned char data) { | |
| 97 | ✗ | int ret = 0; | |
| 98 | ✗ | ret = write(fd, &data, I2C_ONE_BYTE); | |
| 99 | ✗ | if ((ret == -1) || (ret != 1)) | |
| 100 | ✗ | return -1; | |
| 101 | else | ||
| 102 | ✗ | return (ret); | |
| 103 | } | ||
| 104 | |||
| 105 | /**************************************************************** | ||
| 106 | * Function Name : i2c_read | ||
| 107 | * Description : Read a byte on SDA | ||
| 108 | * Returns : No. of bytes read on success, -1 on failure | ||
| 109 | * Params @fd: File descriptor | ||
| 110 | * @read_data: Points to the variable that stores | ||
| 111 | * the read data byte | ||
| 112 | ****************************************************************/ | ||
| 113 | ✗ | int i2c_read(int fd, unsigned char* read_data) { | |
| 114 | ✗ | int ret = 0; | |
| 115 | ✗ | ret = read(fd, &read_data, I2C_ONE_BYTE); | |
| 116 | ✗ | if (ret == -1) | |
| 117 | ✗ | perror("I2C: Failed to read |"); | |
| 118 | ✗ | if (ret == 0) | |
| 119 | ✗ | perror("I2C: End of FILE |"); | |
| 120 | ✗ | return (ret); | |
| 121 | } | ||
| 122 | |||
| 123 | /**************************************************************** | ||
| 124 | * Function Name : i2c_read_register | ||
| 125 | * Description : Read a single register of the slave device | ||
| 126 | * Returns : No. of bytes read on success, -1 on failure | ||
| 127 | * Params @fd: File descriptor | ||
| 128 | * @read_addr: Register address to be read | ||
| 129 | * @read_data: Points to the variable that stores | ||
| 130 | * the read data byte | ||
| 131 | ****************************************************************/ | ||
| 132 | ✗ | int i2c_read_register(int fd, unsigned char read_addr, unsigned char* read_data) { | |
| 133 | ✗ | int ret = 0; | |
| 134 | ✗ | if (i2c_write(fd, read_addr) == -1) { | |
| 135 | ✗ | perror("I2C: Failed to write |"); | |
| 136 | ✗ | return -1; | |
| 137 | } | ||
| 138 | ✗ | ret = read(fd, &read_data, I2C_ONE_BYTE); | |
| 139 | ✗ | if (ret == -1) | |
| 140 | ✗ | perror("I2C: Failed to read |"); | |
| 141 | ✗ | if (ret == 0) | |
| 142 | ✗ | perror("I2C: End of FILE |"); | |
| 143 | ✗ | return (ret); | |
| 144 | } | ||
| 145 | |||
| 146 | /**************************************************************** | ||
| 147 | * Function Name : i2c_read_registers | ||
| 148 | * Description : Read a multiple registers on the slave device | ||
| 149 | * from starting address | ||
| 150 | * Returns : No. of bytes read on success, -1 on failure | ||
| 151 | * Params @fd: File descriptor | ||
| 152 | * @num: Number of registers/bytes to read from. | ||
| 153 | * @starting_addr: Starting address to read from | ||
| 154 | * @buff_Ptr: Buffer to store the read bytes | ||
| 155 | ****************************************************************/ | ||
| 156 | ✗ | int i2c_read_registers(int fd, int num, unsigned char starting_addr, | |
| 157 | unsigned char* buff_Ptr) { | ||
| 158 | ✗ | int ret = 0; | |
| 159 | ✗ | if (i2c_write(fd, starting_addr) == -1) { | |
| 160 | ✗ | perror("I2C: Failed to write |"); | |
| 161 | ✗ | return -1; | |
| 162 | } | ||
| 163 | ✗ | ret = read(fd, buff_Ptr, num); | |
| 164 | ✗ | if (ret == -1) | |
| 165 | ✗ | perror("I2C: Failed to read |"); | |
| 166 | ✗ | if (ret == 0) | |
| 167 | ✗ | perror("I2C: End of FILE |"); | |
| 168 | ✗ | return (ret); | |
| 169 | } | ||
| 170 | |||
| 171 | /**************************************************************** | ||
| 172 | * Function Name : i2c_multiple_writes | ||
| 173 | * Description : Write multiple bytes on SDA | ||
| 174 | * Returns : No. of bytes written on success, -1 on failure | ||
| 175 | * Params @fd: file descriptor | ||
| 176 | * @num: No. of bytes to write | ||
| 177 | * @Ptr_buff: Pointer to the buffer containing the | ||
| 178 | * bytes to be written on the SDA | ||
| 179 | ****************************************************************/ | ||
| 180 | 664 | int i2c_multiple_writes(int fd, int num, unsigned char* Ptr_buff) { | |
| 181 | 664 | int ret = 0; | |
| 182 | 664 | ret = write(fd, Ptr_buff, num); | |
| 183 |
2/4✓ Branch 0 taken 664 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 664 times.
|
664 | if ((ret == -1) || (ret != num)) |
| 184 | ✗ | return -1; | |
| 185 | else | ||
| 186 | 664 | return (ret); | |
| 187 | } | ||
| 188 | |||
| 189 | /**************************************************************** | ||
| 190 | * Function Name : i2c_write_register | ||
| 191 | * Description : Write a control byte or byte to a register | ||
| 192 | * Returns : No. of bytes written on success, -1 on failure | ||
| 193 | * Params @fd: file descriptor | ||
| 194 | * @reg_addr_or_cntrl: Control byte or Register | ||
| 195 | * address to be written | ||
| 196 | * @val: Command or value to be written in the | ||
| 197 | * addressed register | ||
| 198 | ****************************************************************/ | ||
| 199 | 810 | int i2c_write_register(int fd, unsigned char reg_addr_or_cntrl, unsigned char val) { | |
| 200 | unsigned char buff[2]; | ||
| 201 | 810 | int ret = 0; | |
| 202 | 810 | buff[0] = reg_addr_or_cntrl; | |
| 203 | 810 | buff[1] = val; | |
| 204 | 810 | ret = write(fd, buff, I2C_TWO_BYTES); | |
| 205 |
2/4✓ Branch 0 taken 810 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 810 times.
|
810 | if ((ret == -1) || (ret != I2C_TWO_BYTES)) |
| 206 | ✗ | return -1; | |
| 207 | else | ||
| 208 | 810 | return (ret); | |
| 209 | } | ||
| 210 | |||
| 211 | /**************************************************************** | ||
| 212 | * Function Name : config_i2c_struct | ||
| 213 | * Description : Initialize the I2C device structure | ||
| 214 | * Returns : NONE | ||
| 215 | * Params @i2c_dev_path: Device path | ||
| 216 | * @slave_addr: Slave device address | ||
| 217 | * @i2c_dev: Pointer to the device structure | ||
| 218 | ****************************************************************/ | ||
| 219 | 12 | void config_i2c_struct(const char* i2c_dev_path, unsigned char slave_addr, I2C_DevicePtr i2c_dev) { | |
| 220 | 12 | i2c_dev->i2c_dev_path = i2c_dev_path; | |
| 221 | 12 | i2c_dev->fd_i2c = 0; | |
| 222 | 12 | i2c_dev->i2c_slave_addr = slave_addr; | |
| 223 | 12 | } | |
| 224 | |||
| 225 | /**************************************************************** | ||
| 226 | * Function Name : init_i2c_dev1 | ||
| 227 | * Description : Connect the i2c-2 bus to the slave device | ||
| 228 | * Returns : 0 on success, -1 on failure | ||
| 229 | * Params @slave_addr: Slave device address | ||
| 230 | ****************************************************************/ | ||
| 231 | 12 | int init_i2c_dev2(const char* i2cPath, unsigned char slave_address) { | |
| 232 | 12 | config_i2c_struct(i2cPath, slave_address, &I2C_DEV_2); | |
| 233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (Open_device(I2C_DEV_2.i2c_dev_path, &I2C_DEV_2.fd_i2c) == -1) { |
| 234 | ✗ | perror("I2C: Failed to open device |"); | |
| 235 | ✗ | return -1; | |
| 236 | } | ||
| 237 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (Set_slave_addr(I2C_DEV_2.fd_i2c, I2C_DEV_2.i2c_slave_addr) == -1) { |
| 238 | ✗ | perror("I2C: Failed to connect to slave device |"); | |
| 239 | ✗ | return -1; | |
| 240 | } | ||
| 241 | |||
| 242 | 12 | return 0; | |
| 243 | } | ||
| 244 |