From 553f137eb1153012d4aa672228a9e4b5204f0af2 Mon Sep 17 00:00:00 2001 From: Jean-Marc Eurin Date: Thu, 30 Mar 2017 13:45:35 -0700 Subject: [PATCH 1/2] Add a new smbus_writeread command to perform a write followed by a read in one transaction. Signed-off-by: --- linux-i2c-dev.h | 2 -- smbus_rw.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/linux-i2c-dev.h b/linux-i2c-dev.h index da1fd31..835784f 100644 --- a/linux-i2c-dev.h +++ b/linux-i2c-dev.h @@ -47,8 +47,6 @@ struct i2c_msg { #define I2C_M_NO_RD_ACK 0x0800 short len; /* msg length */ char *buf; /* pointer to msg data */ - int err; - short done; }; /* To determine what functionality is present */ diff --git a/smbus_rw.c b/smbus_rw.c index 61c62a5..6c8ff43 100644 --- a/smbus_rw.c +++ b/smbus_rw.c @@ -56,6 +56,7 @@ struct smbus_op_params { uint8_t reg; uint8_t i2c_bus; uint8_t address; + uint8_t read_count; int len; SMBUS_DTYPE data; }; @@ -547,6 +548,74 @@ smbus_block_process_call_op(struct smbus_op_params *params, return 0; } +static int +smbus_writeread(int argc, const char *argv[], const struct cmd_info *info) +{ + int ret; + struct smbus_op_params params; + memset(¶ms, 0, sizeof(params)); + const struct smbus_op *op = (const struct smbus_op *)info->privdata; + + if (smbus_prologue(argv, ¶ms, op) < 0) { + return -1; + } + + if(parse_uint8(argv[3], ¶ms.read_count) < 0) { + fprintf(stderr, "invalid read count %s.\n", argv[4]); + return -1; + } + if (params.read_count > I2C_SMBUS_BLOCK_MAX) { + fprintf(stderr, "read count %s > %d.\n", + argv[3], I2C_SMBUS_BLOCK_MAX); + return -1; + } + if (parse_io_width(argv[4], ¶ms, op) < 0) { + fprintf(stderr, "%s: %s: invalid value to write\n", + argv[0], argv[4]); + close(params.fd); + return -1; + } + + ret = op->perform_op(¶ms, op); + + close(params.fd); + + return ret; +} + +static int +smbus_writeread_op(struct smbus_op_params *params, const struct smbus_op *op) +{ + struct i2c_msg msg[2]; + struct i2c_rdwr_ioctl_data data; + + /* First transfer: write the params bytes */ + msg[0].addr = params->address; + msg[0].flags = 0; + msg[0].len = params->len; + msg[0].buf = (char*) params->data.array; + + /* Second transfer: read `read_count` bytes */ + msg[1].addr = params->address; + msg[1].flags = I2C_M_RD; + msg[1].len = params->read_count; + msg[1].buf = (char*) params->data.array; + + /* Run the transfers */ + data.msgs = msg; + data.nmsgs = 2; + int rv = ioctl(params->fd, I2C_RDWR, &data); + + /* Error check */ + if (rv < 0) { + fprintf(stderr, "I2C_RDWR failed: %s\n", strerror(errno)); + return -1; + } + + print_read_data(SMBUS_SIZE_BLOCK, params->read_count, ¶ms->data); + return 0; +} + MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_read_params, 4, "
", 0); MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_write_params, 5, @@ -557,6 +626,8 @@ MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_send_byte_params, 4, "
", 0); MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_quick_params, 4, "
<0|1>", 0); +MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_writeread_params, 5, + "
", 0); #define MAKE_SMBUS_OP(name_, size_, fn_) \ static const struct smbus_op name_ = { \ @@ -577,6 +648,7 @@ MAKE_SMBUS_OP(smbus_op_quick, SMBUS_QUICK, smbus_write_op); MAKE_SMBUS_OP(smbus_op_proc_call, SMBUS_PROC_CALL, smbus_process_call_op); MAKE_SMBUS_OP(smbus_op_block_proc_call, SMBUS_BLOCK_PROC_CALL, smbus_block_process_call_op); +MAKE_SMBUS_OP(smbus_op_writeread, SMBUS_SIZE_BLOCK, smbus_writeread_op); #define MAKE_SMBUS_RW_CMDS(size_) \ MAKE_CMD_WITH_PARAMS(smbus_read ##size_, smbus_read, \ @@ -600,6 +672,8 @@ static const struct cmd_info smbus_cmds[] = { &smbus_op_proc_call, &smbus_write_params), MAKE_CMD_WITH_PARAMS(smbus_block_process_call, smbus_process_call, &smbus_op_block_proc_call, &smbus_write_params), + MAKE_CMD_WITH_PARAMS(smbus_writeread, smbus_writeread, + &smbus_op_writeread, &smbus_writeread_params), }; MAKE_CMD_GROUP(SMBus, "commands to access the system management bus", From aedc75982035895e6ee51ee04193f7a8c3666d8d Mon Sep 17 00:00:00 2001 From: Jean-Marc Eurin Date: Thu, 6 Apr 2017 12:33:58 -0700 Subject: [PATCH 2/2] Changing the order of the arguments to be . Signed-off-by: JeanMarc.Eurin@gmail.com --- smbus_rw.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/smbus_rw.c b/smbus_rw.c index 6c8ff43..a1fb375 100644 --- a/smbus_rw.c +++ b/smbus_rw.c @@ -44,6 +44,7 @@ enum SMBUS_SIZE SMBUS_QUICK, SMBUS_PROC_CALL, SMBUS_BLOCK_PROC_CALL, + SMBUS_WRITE_READ, }; typedef union { @@ -188,6 +189,7 @@ parse_io_width(const char *arg, struct smbus_op_params *params, break; case SMBUS_SIZE_BLOCK: case SMBUS_BLOCK_PROC_CALL: + case SMBUS_WRITE_READ: { int len; const char *src = arg; @@ -282,7 +284,9 @@ smbus_prologue(const char *argv[], struct smbus_op_params *params, /* Only obtain the register if size designates that it is not a byte * or quick operation. */ - if (op->size != SMBUS_SIZE_BYTE && op->size != SMBUS_QUICK) { + if (op->size != SMBUS_SIZE_BYTE && + op->size != SMBUS_QUICK && + op->size != SMBUS_WRITE_READ) { if (parse_uint8(argv[3], ¶ms->reg)) { fprintf(stderr, "invalid register value\n"); return -1; @@ -560,7 +564,13 @@ smbus_writeread(int argc, const char *argv[], const struct cmd_info *info) return -1; } - if(parse_uint8(argv[3], ¶ms.read_count) < 0) { + if (parse_io_width(argv[3], ¶ms, op) < 0) { + fprintf(stderr, "%s: %s: invalid value to write\n", + argv[0], argv[3]); + close(params.fd); + return -1; + } + if(parse_uint8(argv[4], ¶ms.read_count) < 0) { fprintf(stderr, "invalid read count %s.\n", argv[4]); return -1; } @@ -569,13 +579,6 @@ smbus_writeread(int argc, const char *argv[], const struct cmd_info *info) argv[3], I2C_SMBUS_BLOCK_MAX); return -1; } - if (parse_io_width(argv[4], ¶ms, op) < 0) { - fprintf(stderr, "%s: %s: invalid value to write\n", - argv[0], argv[4]); - close(params.fd); - return -1; - } - ret = op->perform_op(¶ms, op); close(params.fd); @@ -627,7 +630,7 @@ MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_send_byte_params, 4, MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_quick_params, 4, "
<0|1>", 0); MAKE_PREREQ_PARAMS_FIXED_ARGS(smbus_writeread_params, 5, - "
", 0); + "
", 0); #define MAKE_SMBUS_OP(name_, size_, fn_) \ static const struct smbus_op name_ = { \ @@ -648,7 +651,7 @@ MAKE_SMBUS_OP(smbus_op_quick, SMBUS_QUICK, smbus_write_op); MAKE_SMBUS_OP(smbus_op_proc_call, SMBUS_PROC_CALL, smbus_process_call_op); MAKE_SMBUS_OP(smbus_op_block_proc_call, SMBUS_BLOCK_PROC_CALL, smbus_block_process_call_op); -MAKE_SMBUS_OP(smbus_op_writeread, SMBUS_SIZE_BLOCK, smbus_writeread_op); +MAKE_SMBUS_OP(smbus_op_writeread, SMBUS_WRITE_READ, smbus_writeread_op); #define MAKE_SMBUS_RW_CMDS(size_) \ MAKE_CMD_WITH_PARAMS(smbus_read ##size_, smbus_read, \