i2c-tools 'raw' i2c unsupported

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I notice that the lm-sensors i2c-tools don't support 'raw' I2C device file access, instead they rely on the driver supporting the smbus interface.  I am working on an embedded system that does not have smbus, so I created a some patches for lm-sensors tools that add a 'r' access method.   The changes support i2c-get, i2c-put and i2c-dump.

These changes allow the i2c-tools to be used without smbus support in the kernel device driver for the I2C inteface.

Would the developers be interested in adding my patch to the distribution?

diff from r6127

regards,
Jason

----
Index: tools/i2cbusses.c
===================================================================
--- tools/i2cbusses.c    (revision 6127)
+++ tools/i2cbusses.c    (working copy)
@@ -415,3 +415,50 @@
 
     return 0;
 }
+
+int i2c_read_raw_again(int file, unsigned char *buffer, unsigned int count)
+{
+    unsigned char *ptr = buffer;
+    int res=0;
+
+    res = read(file, ptr, count);
+    if(res<0)fprintf(stderr, "Aborting - read data failed (%d) : %s\n",errno,strerror(errno));
+
+    return res;
+}
+
+int i2c_read_raw(int file, unsigned char *buffer, int daddress, unsigned int count)
+{
+    int res;
+    buffer[0] = (unsigned char)(daddress>>8);
+    buffer[1] = (unsigned char)daddress & 0xFF;
+
+    res = write(file, buffer, 2);
+    if (res < 0)fprintf(stderr, "Warning - write addr failed %d : %s\n",errno,strerror(errno));
+   
+    return i2c_read_raw_again(file,buffer,count);
+}
+
+int i2c_write_raw(int file, unsigned char *buffer, int daddress, unsigned int count)
+{
+    unsigned char *ptr;
+    int res;
+    unsigned int n;
+   
+    ptr = malloc(count+10);
+    if(ptr==NULL)
+    {
+        fprintf(stderr, "Memory allocation error\n");
+        return -1;
+    }
+    ptr[0] = (unsigned char)(daddress>>8);
+    ptr[1] = (unsigned char)daddress & 0xFF;
+    memcpy(ptr+2,buffer,count);
+    for(n=0;n<count+2;n++)fprintf(stderr,"%hhx ",*(ptr+n));
+    fprintf(stderr,"\n");
+    res = write(file,ptr,count+2);
+    if(res<0)fprintf(stderr, "Warning: write data failed (%d) : %s\n",errno,strerror(errno));
+   
+    free(ptr);
+    return res;
+}
Index: tools/i2cbusses.h
===================================================================
--- tools/i2cbusses.h    (revision 6127)
+++ tools/i2cbusses.h    (working copy)
@@ -38,7 +38,9 @@
 int parse_i2c_address(const char *address_arg);
 int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet);
 int set_slave_addr(int file, int address, int force);
-
+int i2c_read_raw(int file, unsigned char *buffer, int daddress, unsigned int count);
+int i2c_write_raw(int file, unsigned char *buffer, int daddress, unsigned int count);
+int i2c_read_raw_again(int file, unsigned char *buffer, unsigned int count);
 #define MISSING_FUNC_FMT    "Error: Adapter does not have %s capability\n"
 
 #endif
Index: tools/i2cdump.c
===================================================================
--- tools/i2cdump.c    (revision 6127)
+++ tools/i2cdump.c    (working copy)
@@ -33,6 +33,9 @@
 #include "util.h"
 #include "../version.h"
 
+
+#define I2C_RAW -1
+
 static void help(void)
 {
     fprintf(stderr,
@@ -46,6 +49,7 @@
         "    s (SMBus block)\n"
         "    i (I2C block)\n"
         "    c (consecutive byte)\n"
+        "    r (i2c raw device)"
         "    Append p for SMBus PEC\n");
 }
 
@@ -61,6 +65,14 @@
     }
 
     switch(size) {
+    case I2C_RAW:
+        //If raw i2c is specified, use that instead of SMBus
+        if (!(funcs & I2C_FUNC_I2C)){
+            fprintf(stderr, MISSING_FUNC_FMT, "Raw I2C");
+            return -1;
+        }
+        break;
+   
     case I2C_SMBUS_BYTE:
         if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
             fprintf(stderr, MISSING_FUNC_FMT, "SMBus receive byte");
@@ -184,8 +196,10 @@
     } else if (!strncmp(argv[flags+3], "c", 1)) {
         size = I2C_SMBUS_BYTE;
         pec = argv[flags+3][1] == 'p';
-    } else if (!strcmp(argv[flags+3], "i"))
+    } else if (!strcmp(argv[flags+3], "i")) {
         size = I2C_SMBUS_I2C_BLOCK_DATA;
+    } else if (!strcmp(argv[flags+3], "r"))
+        size = I2C_RAW;
     else {
         fprintf(stderr, "Error: Invalid mode!\n");
         help();
@@ -248,6 +262,7 @@
 
         /* Check mode constraints */
         switch (size) {
+        case I2C_RAW:
         case I2C_SMBUS_BYTE:
         case I2C_SMBUS_BYTE_DATA:
             break;
@@ -285,6 +300,7 @@
             size == I2C_SMBUS_BLOCK_DATA ? "smbus block" :
             size == I2C_SMBUS_I2C_BLOCK_DATA ? "i2c block" :
             size == I2C_SMBUS_BYTE ? "byte consecutive read" :
+            size == I2C_RAW ? "raw I2C consecutive read" :
             size == I2C_SMBUS_BYTE_DATA ? "byte" : "word");
         if (pec)
             fprintf(stderr, "PEC checking enabled.\n");
@@ -292,7 +308,9 @@
             fprintf(stderr, "Only probing even register "
                 "addresses.\n");
         if (bank) {
-            if (size == I2C_SMBUS_BLOCK_DATA)
+            if (size == I2C_RAW)
+                fprintf(stderr, "With bank offset 0x%04x\n",(bank*256));
+            else if (size == I2C_SMBUS_BLOCK_DATA)
                 fprintf(stderr, "Using command 0x%02x.\n",
                     bank);
             else
@@ -314,7 +332,7 @@
     }
 
     /* See Winbond w83781d data sheet for bank details */
-    if (bank && size != I2C_SMBUS_BLOCK_DATA) {
+    if (bank && size != I2C_SMBUS_BLOCK_DATA && size != I2C_RAW) {
         res = i2c_smbus_read_byte_data(file, bankreg);
         if (res >= 0) {
             old_bank = res;
@@ -331,7 +349,7 @@
     if (size != I2C_SMBUS_WORD_DATA || even) {
         /* do the block transaction */
         if (size == I2C_SMBUS_BLOCK_DATA
-         || size == I2C_SMBUS_I2C_BLOCK_DATA) {
+         || size == I2C_SMBUS_I2C_BLOCK_DATA || size == I2C_RAW) {
             unsigned char cblock[288];
 
             if (size == I2C_SMBUS_BLOCK_DATA) {
@@ -340,6 +358,9 @@
                 /* Remember returned block length for a nicer
                    display later */
                 s_length = res;
+            } else if(size == I2C_RAW) {
+                res = i2c_read_raw(file, cblock, (bank*256), 256);
+                s_length = res;
             } else {
                 for (res = 0; res < 256; res += i) {
                     i = i2c_smbus_read_i2c_block_data(file,
@@ -359,7 +380,7 @@
                 res = 256;
             for (i = 0; i < res; i++)
                 block[i] = cblock[i];
-            if (size != I2C_SMBUS_BLOCK_DATA)
+            if (size != I2C_SMBUS_BLOCK_DATA && size != I2C_RAW)
                 for (i = res; i < 256; i++)
                     block[i] = -1;
         }
@@ -372,12 +393,14 @@
                 exit(1);
             }
         }
-
+       
         printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f"
                "    0123456789abcdef\n");
         for (i = 0; i < 256; i+=16) {
             if (size == I2C_SMBUS_BLOCK_DATA && i >= s_length)
                 break;
+            if (size == I2C_RAW && i >= s_length)
+                break;
             if (i/16 < first/16)
                 continue;
             if (i/16 > last/16)
@@ -400,8 +423,7 @@
                     block[i+j] = res =
                       i2c_smbus_read_byte_data(file, i+j);
                 } else if (size == I2C_SMBUS_WORD_DATA) {
-                    res = i2c_smbus_read_word_data(file,
-                                       i+j);
+                    res = i2c_smbus_read_word_data(file, i+j);
                     if (res < 0) {
                         block[i+j] = res;
                         block[i+j+1] = res;
@@ -415,7 +437,7 @@
                 } else
                     res = block[i+j];
 
-                if (size == I2C_SMBUS_BLOCK_DATA
+                if ((size == I2C_SMBUS_BLOCK_DATA || size == I2C_RAW)
                  && i+j >= s_length) {
                     printf("   ");
                 } else if (res < 0) {
@@ -433,7 +455,7 @@
             printf("   ");
 
             for (j = 0; j < 16; j++) {
-                if (size == I2C_SMBUS_BLOCK_DATA
+                if ((size == I2C_SMBUS_BLOCK_DATA || size == I2C_RAW)
                  && i+j >= s_length)
                     break;
                 /* Skip unwanted registers */
@@ -483,7 +505,7 @@
             printf("\n");
         }
     }
-    if (bank && size != I2C_SMBUS_BLOCK_DATA) {
+    if (bank && size != I2C_SMBUS_BLOCK_DATA && size != I2C_RAW) {
         i2c_smbus_write_byte_data(file, bankreg, old_bank);
     }
     exit(0);
Index: tools/i2cget.c
===================================================================
--- tools/i2cget.c    (revision 6127)
+++ tools/i2cget.c    (working copy)
@@ -38,6 +38,8 @@
 
 static void help(void) __attribute__ ((noreturn));
 
+#define I2C_RAW -1
+
 static void help(void)
 {
     fprintf(stderr,
@@ -45,6 +47,7 @@
         "  I2CBUS is an integer or an I2C bus name\n"
         "  ADDRESS is an integer (0x03 - 0x77)\n"
         "  MODE is one of:\n"
+        "    r (read byte using raw i2c device)\n"
         "    b (read byte data, default)\n"
         "    w (read word data)\n"
         "    c (write byte/read byte)\n"
@@ -52,6 +55,7 @@
     exit(1);
 }
 
+
 static int check_funcs(int file, int size, int daddress, int pec)
 {
     unsigned long funcs;
@@ -62,8 +66,15 @@
             "functionality matrix: %s\n", strerror(errno));
         return -1;
     }
-
+   
     switch (size) {
+    case I2C_RAW:
+        //If raw i2c is specified, use that instead of SMBus
+        if (!(funcs & I2C_FUNC_I2C)){
+            fprintf(stderr, MISSING_FUNC_FMT, "Raw I2C");
+            return -1;
+        }
+        break;
     case I2C_SMBUS_BYTE:
         if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
             fprintf(stderr, MISSING_FUNC_FMT, "SMBus receive byte");
@@ -135,8 +146,8 @@
     fprintf(stderr, ", using %s.\n",
         size == I2C_SMBUS_BYTE ? (daddress < 0 ?
         "read byte" : "write byte/read byte") :
-        size == I2C_SMBUS_BYTE_DATA ? "read byte data" :
-        "read word data");
+        (size == I2C_SMBUS_BYTE_DATA || size == I2C_RAW) ?
+        "read byte data" : "read word data");
     if (pec)
         fprintf(stderr, "PEC checking enabled.\n");
 
@@ -159,6 +170,7 @@
     int pec = 0;
     int flags = 0;
     int force = 0, yes = 0, version = 0;
+    unsigned char buffer[10];
 
     /* handle (optional) flags first */
     while (1+flags < argc && argv[1+flags][0] == '-') {
@@ -208,6 +220,7 @@
         case 'b': size = I2C_SMBUS_BYTE_DATA; break;
         case 'w': size = I2C_SMBUS_WORD_DATA; break;
         case 'c': size = I2C_SMBUS_BYTE; break;
+        case 'r': size = I2C_RAW; break;
         default:
             fprintf(stderr, "Error: Invalid mode!\n");
             help();
@@ -232,11 +245,14 @@
     }
 
     switch (size) {
+    case I2C_RAW:
+        res = i2c_read_raw(file,buffer,daddress,1);
+        break;
     case I2C_SMBUS_BYTE:
         if (daddress >= 0) {
             res = i2c_smbus_write_byte(file, daddress);
             if (res < 0)
-                fprintf(stderr, "Warning - write failed\n");
+                fprintf(stderr, "Warning - write addr failed\n");
         }
         res = i2c_smbus_read_byte(file);
         break;
@@ -253,7 +269,13 @@
         exit(2);
     }
 
-    printf("0x%0*x\n", size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
-
+    switch(size){
+    case I2C_RAW:
+        printf("0x%04x = %02hhx\n", daddress, buffer[0]);
+        break;
+    default:
+        printf("0x%0*x\n", size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
+    }
+   
     exit(0);
 }
Index: tools/i2cset.c
===================================================================
--- tools/i2cset.c    (revision 6127)
+++ tools/i2cset.c    (working copy)
@@ -35,6 +35,8 @@
 
 static void help(void) __attribute__ ((noreturn));
 
+#define I2C_RAW -1
+
 static void help(void)
 {
     fprintf(stderr,
@@ -42,6 +44,7 @@
         "  I2CBUS is an integer or an I2C bus name\n"
         "  ADDRESS is an integer (0x03 - 0x77)\n"
         "  MODE is one of:\n"
+        "    r (write byte using raw i2c device)\n"
         "    c (byte, no value)\n"
         "    b (byte data, default)\n"
         "    w (word data)\n"
@@ -63,6 +66,13 @@
     }
 
     switch (size) {
+    case I2C_RAW:
+        //If raw i2c is specified, use that instead of SMBus
+        if (!(funcs & I2C_FUNC_I2C)){
+            fprintf(stderr, MISSING_FUNC_FMT, "Raw I2C");
+            return -1;
+        }
+        break;
     case I2C_SMBUS_BYTE:
         if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
             fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
@@ -140,7 +150,7 @@
     } else
         fprintf(stderr, "data 0x%02x%s, mode %s.\n", value,
             vmask ? " (masked)" : "",
-            size == I2C_SMBUS_BYTE_DATA ? "byte" : "word");
+            (size == I2C_SMBUS_BYTE_DATA || size == I2C_RAW) ? "byte" : "word");
     if (pec)
         fprintf(stderr, "PEC checking enabled.\n");
 
@@ -235,6 +245,7 @@
         case 'w': size = I2C_SMBUS_WORD_DATA; break;
         case 's': size = I2C_SMBUS_BLOCK_DATA; break;
         case 'i': size = I2C_SMBUS_I2C_BLOCK_DATA; break;
+        case 'r': size = I2C_RAW; break;
         default:
             fprintf(stderr, "Error: Invalid mode '%s'!\n", argv[argc-1]);
             help();
@@ -263,6 +274,7 @@
 
     /* read values from command line */
     switch (size) {
+    case I2C_RAW:
     case I2C_SMBUS_BYTE_DATA:
     case I2C_SMBUS_WORD_DATA:
         value = strtol(argv[flags+4], &end, 0);
@@ -303,7 +315,7 @@
             fprintf(stderr, "Error: Data value mask invalid!\n");
             help();
         }
-        if (((size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA)
+        if (((size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA || size == I2C_RAW)
              && vmask > 0xff) || vmask > 0xffff) {
             fprintf(stderr, "Error: Data value mask out of range!\n");
             help();
@@ -320,10 +332,15 @@
                  value, vmask, block, len, pec))
         exit(0);
 
+    //Get the old value
     if (vmask) {
         int oldvalue;
 
         switch (size) {
+        case I2C_RAW:
+            res = i2c_read_raw(file,block,daddress,1);
+            oldvalue = (unsigned int)block[0];
+        break;
         case I2C_SMBUS_BYTE:
             oldvalue = i2c_smbus_read_byte(file);
             break;
@@ -366,7 +383,12 @@
         exit(1);
     }
 
+    //Do the write
     switch (size) {
+    case I2C_RAW:
+        block[0] = value;
+        res = i2c_write_raw(file,block,daddress,1);
+        break;
     case I2C_SMBUS_BYTE:
         res = i2c_smbus_write_byte(file, daddress);
         break;
@@ -403,7 +425,11 @@
         exit(0);
     }
 
+    //Verify the write
     switch (size) {
+    case I2C_RAW:
+        i2c_read_raw(file,block,daddress,1);
+        res = (unsigned int)block[0];
     case I2C_SMBUS_BYTE:
         res = i2c_smbus_read_byte(file);
         value = daddress;
 
_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux