Skip to content

Commit

Permalink
build i2c_ext app
Browse files Browse the repository at this point in the history
  • Loading branch information
ligenxxxx committed Aug 29, 2023
1 parent 6dd95d3 commit 27af753
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ if(NOT EMULATOR_BUILD)
softwinner
)

#i2c_ext application
file(GLOB SRC_FILES_I2C_EXT "src/i2c_ext/*.c" "src/i2c_ext/*.h")
add_executable(i2c_ext
${SRC_FILES_I2C_EXT}
)

# rtspLive application
file(GLOB SRC_FILES_RTSPLIVE "src/rtspLive/*.cpp" "src/rtspLive/*.hh")
file(GLOB SRC_FILES_RTSPLIVE_STREAM "src/rtspLive/stream/*.c" "src/rtspLive/stream/*.h")
Expand Down
261 changes: 261 additions & 0 deletions src/i2c_ext/i2c_ext.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
#include "i2c_ext.h"

#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/ioctl.h>

#define IIC_PORTS 4
static char *IIC_DEVS[IIC_PORTS] = {
"/dev/i2c-0",
"/dev/i2c-1",
"/dev/i2c-2",
"/dev/i2c-3",
};

int i2c_fd;
bool i2c_report_once = false;
i2c_ext_mode_t mode;
arg_t arg;

void i2c_ext_init(uint8_t port) {
i2c_fd = open(IIC_DEVS[port], O_RDONLY);

if (port < 0 || port >= IIC_PORTS) {
printf("Port %d contains an invalid range [0=N/A,1=Right,2=Main,3=Left]", port);
return;
} else if (i2c_fd < 0) {
if (!i2c_report_once) {
i2c_report_once = true;
printf("Device %d:%s is not available [0=N/A,1=Right,2=Main,3=Left]", port, IIC_DEVS[port]);
}
return;
}
}

static int i2c_write_ext(i2c_ext_mode_t mode, uint8_t slave_address, uint32_t reg_address, uint32_t reg_val) {
struct i2c_rdwr_ioctl_data work_queue;
struct i2c_msg msgs;
uint8_t obuf[8];
const uint8_t alen = (mode >> 2) + 1;
const uint8_t dlen = (mode & 3) + 1;
const uint8_t len = alen + dlen;
int i;
int ret;

work_queue.nmsgs = 1;
work_queue.msgs = &msgs;
msgs.buf = obuf;

(work_queue.msgs[0]).len = len;
(work_queue.msgs[0]).flags = I2C_SMBUS_WRITE;

(work_queue.msgs[0]).addr = slave_address;

for (i = 0; i < alen; i++) {
(work_queue.msgs[0]).buf[i] = (reg_address >> (i << 3)) & 0xff;
}

for (i = 0; i < dlen; i++) {
(work_queue.msgs[0]).buf[i + alen] = (reg_val >> (i << 3)) & 0xff;
}

ret = ioctl(i2c_fd, I2C_RDWR, (unsigned long)&work_queue);
if (ret < 0) {
printf("iic_write[%x.%x]<-%x failed.", slave_address, reg_address, reg_val);
ret = 0;
}
return ret;
}

static void i2c_read_ext(i2c_ext_mode_t mode, uint32_t slave_address, uint32_t reg_address) {
struct i2c_rdwr_ioctl_data work_queue;
struct i2c_msg msgs[2];
const uint8_t alen = (mode >> 2) + 1;
const uint8_t dlen = (mode & 3) + 1;
const uint8_t len = alen + dlen;
int i, j;
int ret;
uint8_t reg_data[4];

reg_data[0] = (uint8_t)(reg_address & 0xff);
reg_data[1] = (uint8_t)((reg_address >> 8) & 0xff);
reg_data[2] = (uint8_t)((reg_address >> 16) & 0xff);
reg_data[3] = (uint8_t)((reg_address >> 24) & 0xff);

work_queue.nmsgs = 2;
work_queue.msgs = msgs;

(work_queue.msgs[0]).len = alen;
(work_queue.msgs[0]).flags = I2C_SMBUS_WRITE;
(work_queue.msgs[0]).addr = (uint8_t)slave_address;
(work_queue.msgs[0]).buf = reg_data;

(work_queue.msgs[1]).len = dlen;
(work_queue.msgs[1]).flags = I2C_SMBUS_READ;
(work_queue.msgs[1]).addr = (uint8_t)slave_address;
(work_queue.msgs[1]).buf = reg_data;
ret = ioctl(i2c_fd, I2C_RDWR, (unsigned long)&work_queue);

if (ret < 0) {
printf("\r\ni2c_read[%x.%x] failed.", slave_address, reg_address);
} else {
printf("\r\n0x%08x: 0x", reg_address);
for (i = 0; i < dlen; i++) {
printf("%02x", reg_data[i]);
}
}
}

void display_usage(void) {
printf("\r\nusage:\r\n");
printf("\r\n i2c_ext -p[port] -m[mode] -w/r [device address] [reg address] [reg value]");
printf("\r\n -p: i2c bus port");
printf("\r\n 0: None ");
printf("\r\n 1: Right ");
printf("\r\n 2: Main ");
printf("\r\n 3: Left ");
printf("\r\n -m: mode");
printf("\r\n 0: A8D8 ");
printf("\r\n 1: A8D16 ");
printf("\r\n 2: A8D24 ");
printf("\r\n 3: A8D32 ");
printf("\r\n 4: A16D8 ");
printf("\r\n 5: A16D16");
printf("\r\n 6: A16D24");
printf("\r\n 7: A16D32");
printf("\r\n -w/r: write or read");
printf("\r\n -w: write");
printf("\r\n -r: read");
printf("\r\n [slave address(7 bits)]");
printf("\r\n eg 64: means 0x64");
printf("\r\n [reg address(hex)]");
printf("\r\n eg ff: means ff");
printf("\r\n [reg value(hex)]");
printf("\r\n reg_value for write");
printf("\r\n length for read");
printf("\r\n eg 6: 0x06");
printf("\r\n");
}

void arg_error(char cmd) {
printf("\r\n-%c:error", cmd);
}

int is_hex_string(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
} else {
return -1;
}
}

uint8_t parse_arg(int argc, char *argv[]) {
uint8_t ret = 0;
uint8_t i, j, k;
char cur_op[256] = {0};

if (argc <= 1) {
printf("No parameter detected");
display_usage();
ret = 1;
} else {
arg.data[0] = 0;
arg.data[1] = 0;
arg.data[2] = 0;
// parse
k = 0;
for (i = 1; i < argc; i++) {
memset(cur_op, 0, sizeof(cur_op));
memcpy(cur_op, argv[i], sizeof(cur_op));

if (cur_op[0] == '-') {
switch (cur_op[1]) {
case 'p':
case 'P':
arg.port = cur_op[2] - '0';
break;
case 'm':
case 'M':
arg.mode = cur_op[2] - '0';
break;

case 'w':
case 'W':
arg.is_write = 1;
break;

case 'r':
case 'R':
arg.is_write = 0;
break;

default:
break;
}
} else {
// parse data
j = 0;
while (1) {
if (cur_op[j] == 0) {
// string end
break;
} else {
if (is_hex_string(cur_op[j]) < 0) {
break;
} else {
arg.data[k] = arg.data[k] << 4;
arg.data[k] += is_hex_string(cur_op[j]);
}
j++;
}
}
k++;
k &= 3;
}
}

// parse result
printf("\r\nmode: %d", arg.mode);
printf("\r\nis_write: %d", arg.is_write);
printf("\r\nslave address:0x%02x", arg.data[0]);
printf("\r\nreg_addr: 0x%08x", arg.data[1]);
if (arg.is_write)
printf("\r\nreg_data: 0x%08x", arg.data[2]);
else {
printf("\r\nlen: 0x%08x", arg.data[2]);
}
printf("\r\n");
}

return ret;
}

int main(int argc, char *argv[]) {
if (parse_arg(argc, argv))
return 0;

i2c_ext_init(arg.port);
if (arg.is_write) {
i2c_write_ext(arg.mode, arg.data[0], arg.data[1], arg.data[2]);
i2c_read_ext(arg.mode, arg.data[0], arg.data[1]);
printf("\r\n");
} else {

if (arg.data[2] == 0) {
arg.data[2] = 1;
}

for (int i = 0; i < arg.data[2]; i++) {
i2c_read_ext(arg.mode, arg.data[0], (arg.data[1] + i));
}
printf("\r\n");
}
}
21 changes: 21 additions & 0 deletions src/i2c_ext/i2c_ext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include "stdbool.h"
#include <stdint.h>

typedef enum {
A8D8 = 0,
A8D16 = 1,
A8D24 = 2,
A8D32 = 3,
A16D8 = 4,
A16D16 = 5,
A16D24 = 6,
A16D32 = 7,
} i2c_ext_mode_t;

typedef struct {
uint8_t port;
i2c_ext_mode_t mode;
bool is_write;
uint32_t data[3];
} arg_t;

0 comments on commit 27af753

Please sign in to comment.