arm/189914: i2c(8)
Vadim Zaigrin
vzaigrin at yandex.ru
Sun May 18 18:10:00 UTC 2014
>Number: 189914
>Category: arm
>Synopsis: i2c(8)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-arm
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun May 18 18:10:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator: Vadim Zaigrin
>Release: 10-STABLE
>Organization:
>Environment:
FreeBSD pi 10.0-STABLE FreeBSD 10.0-STABLE #0 r262915: Sat Mar 8 19:44:28 UTC 2014 root at grind.freebsd.org:/usr/obj/arm.armv6/usr/src/sys/RPI-B arm
>Description:
Hi
i2c(8) utility does not work on Raspberry Pi.
It uses syscall ioctl I2CSTART, I2CSTOP, I2CRSTCARD, I2CWRITE and I2CREAD.
This syscalls try to call iicbus interfaces iicbus_start, iicbus_stop, iicbus_reset, iicbus_write and iicbus_read.
But there is only iicbus_transfer interface in iicbus device.
Interface iicbus_transfer is used by syscall ioctl I2CRDWR.
>How-To-Repeat:
>Fix:
I have corrected source code of the i2c(8) utility to work on Raspberry Pi.
The patch to the original source code and the updated source code are available here: https://github.com/vzaigrin/newi2c
i2c.c.patch is a patch for original source code of the i2c.c
newi2c.c is an updated source code of the i2c.c
Hope this can help
Patch attached with submission follows:
40c40,41
<
---
> #include <sys/types.h>
> #include <sys/sysctl.h>
60,61c61,62
< uint32_t addr;
< uint32_t off;
---
> uint16_t addr;
> uint16_t off;
125c126
< int *tokens, fd, error, i, index, j;
---
> int *tokens, fd, i, index, j;
126a128,132
> struct iic_msg msg[2];
> struct iic_rdwr_data rdwr;
> int mute;
> uint8_t offset, buf;
> int found = 0;
156a163,166
> /* To read from non existing device we need first to disable console messages */
> mute = 1;
> sysctlbyname("kern.consmute", NULL, NULL, &mute, sizeof(mute) );
>
177,192c187,209
< cmd.slave = i << 1;
< cmd.last = 1;
< cmd.count = 0;
< error = ioctl(fd, I2CRSTCARD, &cmd);
< if (error)
< goto out;
<
< cmd.slave = i << 1;
< cmd.last = 1;
< error = ioctl(fd, I2CSTART, &cmd);
< if (!error)
< printf("%x ", i);
< cmd.slave = i << 1;
< cmd.last = 1;
< error = ioctl(fd, I2CSTOP, &cmd);
< }
---
> offset = 0;
> msg[0].slave = i;
> msg[0].flags = !IIC_M_RD;
> msg[0].len = sizeof( offset );
> msg[0].buf = &offset;
> msg[1].slave = i;
> msg[1].flags = IIC_M_RD;
> msg[1].len = sizeof( buf );
> msg[1].buf = &buf;
> rdwr.msgs = msg;
> rdwr.nmsgs = 2;
> if ( ioctl(fd, I2CRDWR, &rdwr) >= 0 ) {
> printf("%x ", i);
> found = 1;
> }
>
> }
>
> if ( !found ) printf( "nothing found\n" );
>
> /* Now we need to enable console messages */
> mute = 0;
> sysctlbyname("kern.consmute", NULL, NULL, &mute, sizeof(mute) );
195d211
< error = ioctl(fd, I2CRSTCARD, &cmd);
201,206c217
< if (error) {
< fprintf(stderr, "Error scanning I2C controller (%s): %s\n",
< dev, strerror(errno));
< return (EX_NOINPUT);
< } else
< return (EX_OK);
---
> return (EX_OK);
212d222
< int fd, error;
214,219c224
< fd = open(dev, O_RDWR);
< if (fd == -1) {
< fprintf(stderr, "Error opening I2C controller (%s) for "
< "resetting: %s\n", dev, strerror(errno));
< return (EX_NOINPUT);
< }
---
> /* We can't reset bus, so do nothing */
221,231c226
< printf("Resetting I2C controller on %s: ", dev);
< error = ioctl(fd, I2CRSTCARD, &cmd);
< close (fd);
<
< if (error) {
< printf("error: %s\n", strerror(errno));
< return (EX_IOERR);
< } else {
< printf("OK\n");
< return (EX_OK);
< }
---
> return (EX_OK);
234c229
< static char *
---
> static uint8_t *
237c232
< char *buf;
---
> uint8_t *buf;
254c249
< i2c_write(char *dev, struct options i2c_opt, char *i2c_buf)
---
> i2c_write(char *dev, struct options i2c_opt, uint8_t *i2c_buf)
256,258c251,256
< struct iiccmd cmd;
< int ch, i, error, fd, bufsize;
< char *err_msg, *buf;
---
> int ch, i, fd, bufsize;
> char *err_msg;
> struct iic_msg msg;
> struct iic_rdwr_data rdwr;
> uint8_t *buf, *dbuf;
>
272c270
< i2c_buf[i] = ch;
---
> i2c_buf[i] = (uint8_t)ch;
284,289d281
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTART, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending start condition";
< goto err1;
< }
298,332d289
<
< cmd.count = bufsize;
< cmd.buf = buf;
< error = ioctl(fd, I2CWRITE, &cmd);
< free(buf);
< if (error == -1) {
< err_msg = "ioctl: error when write offset";
< goto err1;
< }
< }
<
< /* Mode - stop start */
< if (i2c_opt.mode == I2C_MODE_STOP_START) {
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTOP, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending stop condition";
< goto err2;
< }
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTART, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending start condition";
< goto err1;
< }
< }
< /* Mode - repeated start */
< if (i2c_opt.mode == I2C_MODE_REPEATED_START) {
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CRPTSTART, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending repeated start "
< "condition";
< goto err1;
< }
338,350c295,313
< cmd.count = i2c_opt.count;
< cmd.buf = i2c_buf;
< cmd.last = 0;
< error = ioctl(fd, I2CWRITE, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error when write";
< goto err1;
< }
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTOP, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending stop condition";
< goto err2;
---
> dbuf = malloc( (bufsize + i2c_opt.count) * sizeof(uint8_t) );
>
> for (i = 0; i < bufsize; i++) {
> dbuf[i] = buf[i];
> }
>
> for (i = 0; i < i2c_opt.count; i++ ) {
> dbuf[i+bufsize] = i2c_buf[i];
> }
>
> msg.slave = i2c_opt.addr;
> msg.flags = !IIC_M_RD;
> msg.len = (bufsize + i2c_opt.count) * sizeof( uint8_t );
> msg.buf = dbuf;
> rdwr.msgs = &msg;
> rdwr.nmsgs = 1;
> if ( ioctl(fd, I2CRDWR, &rdwr) < 0 ) {
> err_msg = "ioctl: error when write";
> goto err1;
357,364d319
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTOP, &cmd);
< if (error == -1)
< fprintf(stderr, "error sending stop condtion\n");
< err2:
< if (err_msg)
< fprintf(stderr, "%s", err_msg);
<
370c325
< i2c_read(char *dev, struct options i2c_opt, char *i2c_buf)
---
> i2c_read(char *dev, struct options i2c_opt, uint8_t *i2c_buf)
372,374c327,331
< struct iiccmd cmd;
< int i, fd, error, bufsize;
< char *err_msg, data = 0, *buf;
---
> int i, fd, bufsize;
> char *err_msg;
> struct iic_msg *msg;
> struct iic_rdwr_data rdwr;
> uint8_t *buf;
380,381d336
< bzero(&cmd, sizeof(cmd));
<
383,391d337
< cmd.slave = i2c_opt.addr;
< cmd.count = 1;
< cmd.last = 0;
< cmd.buf = &data;
< error = ioctl(fd, I2CSTART, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending start condition";
< goto err1;
< }
397a344
> }
399,407c346
< cmd.count = bufsize;
< cmd.buf = buf;
< cmd.last = 0;
< error = ioctl(fd, I2CWRITE, &cmd);
< free(buf);
< if (error == -1) {
< err_msg = "ioctl: error when write offset";
< goto err1;
< }
---
> msg = malloc( (bufsize + i2c_opt.count) * sizeof(struct iic_msg) );
409,414c348,352
< if (i2c_opt.mode == I2C_MODE_STOP_START) {
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTOP, &cmd);
< if (error == -1)
< goto err2;
< }
---
> for (i = 0; i < bufsize; i++) {
> msg[i].slave = i2c_opt.addr;
> msg[i].flags = !IIC_M_RD;
> msg[i].len = sizeof( uint8_t );
> msg[i].buf = &buf[i];
416,436d353
< cmd.slave = i2c_opt.addr;
< cmd.count = 1;
< cmd.last = 0;
< cmd.buf = &data;
< if (i2c_opt.mode == I2C_MODE_STOP_START) {
< error = ioctl(fd, I2CSTART, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending start condition";
< goto err1;
< }
< } else if (i2c_opt.mode == I2C_MODE_REPEATED_START) {
< error = ioctl(fd, I2CRPTSTART, &cmd);
< if (error == -1) {
< err_msg = "ioctl: error sending repeated start "
< "condition";
< goto err1;
< }
< }
< error = ioctl(fd, I2CSTOP, &cmd);
< if (error == -1)
< goto err2;
438,443c355,359
< for (i = 0; i < i2c_opt.count; i++) {
< error = read(fd, &i2c_buf[i], 1);
< if (error == -1) {
< err_msg = "ioctl: error while reading";
< goto err1;
< }
---
> for (i = 0; i < i2c_opt.count; i++ ) {
> msg[i+bufsize].slave = i2c_opt.addr;
> msg[i+bufsize].flags = IIC_M_RD;
> msg[i+bufsize].len = sizeof( uint8_t );
> msg[i+bufsize].buf = &i2c_buf[i];
445a362,369
> rdwr.msgs = msg;
> rdwr.nmsgs = bufsize + i2c_opt.count;
>
> if ( ioctl(fd, I2CRDWR, &rdwr) < 0 ) {
> err_msg = "ioctl: error while reading";
> goto err1;
> }
>
450,457d373
< cmd.slave = i2c_opt.addr;
< error = ioctl(fd, I2CSTOP, &cmd);
< if (error == -1)
< fprintf(stderr, "error sending stop condtion\n");
< err2:
< if (err_msg)
< fprintf(stderr, "%s", err_msg);
<
467c383
< char *dev, *skip_addr, *i2c_buf;
---
> char *dev, *skip_addr;
468a385
> uint8_t *i2c_buf;
494c411
< i2c_opt.addr = (strtoul(optarg, 0, 16) << 1);
---
> sscanf( optarg, "%hX", &i2c_opt.addr);
578c495
< i2c_opt.addr >> 1, i2c_opt.dir, i2c_opt.off,
---
> i2c_opt.addr, i2c_opt.dir, i2c_opt.off,
606,609d522
< if (i2c_opt.verbose)
< fprintf(stderr, "\nData %s (hex):\n", i2c_opt.dir == 'r' ?
< "read" : "written");
<
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-arm
mailing list