예제 #1
0
 static extern int ExternalIoCtl(int fd, uint request, ref i2c_rdwr_ioctl_data xfer);
예제 #2
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Writes/Reads a buffer in from an I2C slave device using I2C_RDWR function.
        ///
        /// </summary>
        /// <param name="devID">The I2C Device ID to write to</param>
        /// <param name="txByteBuf">The buffer with bytes to write, can be null for read only</param>
        /// <param name="txBytes">The number of bytes to write, can be 0 for read only
        /// <param name="rxByteBuf">The buffer with bytes to read, can be null for write only</param>
        /// <param name="rxBytes">The number of bytes to read, can be 0 for write only
        /// <history>
        ///    19 Dec 18  Ridler - Originally written
        /// </history>
        public void I2CTransfer(int devID, byte[] txByteBuf, int txBytes, byte[] rxByteBuf, int rxBytes)
        {
            int ioctlRetVal = -1;

            if (i2CPortFD <= 0)
            {
                throw new Exception("I2C port is not open, fd=0");
            }
            if (PortIsOpen == false)
            {
                throw new Exception("I2C port is not open");
            }
            i2c_msg[] msgs     = new i2c_msg[2];
            uint      nmsgs    = 0;
            IntPtr    txBufPtr = IntPtr.Zero;
            IntPtr    rxBufPtr = IntPtr.Zero;

            if (txByteBuf != null && txBytes != 0)
            {
                txBufPtr = Marshal.AllocHGlobal(txBytes + 1);
                // copy the data from the tx buffer to our pointer
                Marshal.Copy(txByteBuf, 0, txBufPtr, txBytes);
                msgs[nmsgs].addr  = (UInt16)devID;
                msgs[nmsgs].flags = 0;
                msgs[nmsgs].len   = (UInt16)txBytes;
                msgs[nmsgs].buf   = txBufPtr;
                nmsgs++;
            }
            if (rxByteBuf != null && rxBytes != 0)
            {
                rxBufPtr          = Marshal.AllocHGlobal(rxBytes + 1);
                msgs[nmsgs].addr  = (UInt16)devID;
                msgs[nmsgs].flags = 1;                  // I2C_M_RD;
                msgs[nmsgs].len   = (UInt16)rxBytes;
                msgs[nmsgs].buf   = rxBufPtr;
                nmsgs++;
            }
            // interpret it as an input error if nothing has to be done
            if (nmsgs == 0)
            {
                throw new Exception("I2CTransfer on I2C device " + devID.ToString() + " has nothing to write or read!");
            }
            int    msg_size  = Marshal.SizeOf(typeof(i2c_msg));             // should be 12....
            IntPtr msgbuffer = Marshal.AllocHGlobal(msg_size * 2);
            IntPtr ptr       = msgbuffer;

            for (uint ndx = 0; ndx < nmsgs; ndx++)
            {
                Marshal.StructureToPtr(msgs[ndx], ptr, false);
                ptr += msg_size;
            }
            i2c_rdwr_ioctl_data i2c_data = new i2c_rdwr_ioctl_data();

            i2c_data.msgs  = msgbuffer;
            i2c_data.nmsgs = nmsgs;
            try
            { ioctlRetVal = ExternalIoCtl(i2CPortFD, I2C_RDWR, ref i2c_data);
              if (ioctlRetVal < 0)
              {                     // it failed
                  throw new Exception("ExternalIoCtl on I2C device " + devID.ToString() + " failed. retval=" + ioctlRetVal.ToString());
              }
              // did the caller supply a receive buffer
              if (rxByteBuf != null)
              {                     // yes they did, copy the returned data in
                  Marshal.Copy(rxBufPtr, rxByteBuf, 0, rxBytes);
              }
            }
            finally
            { if (txBufPtr != IntPtr.Zero)
              {
                  Marshal.FreeHGlobal(txBufPtr);
              }
              if (rxBufPtr != IntPtr.Zero)
              {
                  Marshal.FreeHGlobal(rxBufPtr);
              }
              Marshal.FreeHGlobal(msgbuffer); }
        }