14 Replies Latest reply on Oct 23, 2015 12:19 PM by PavelS

    Accessing a temperature sensor over I2C interface on Intel NUC Baytrail device with Windows 7

    prajose_john Green Belt

      Hi,

      I am using Intel's NUC Baytrail device and have connected a temperature sensor to the I2C interface.

      Platform: Intel NUC Baytrail device

      Operating System: Windows 7

      Testing interface: I2C

       

      Situations handled:

      1. Changed BIOS from UEFI to Secured mode

      2.  Step 1 helped to show the I2C device in the device manager.

      3. Writing a test application program to perform read / write operation

      4. Createfile() returns the handle of the temperature sensor device

      5. The write / read operation does not succeed.

       

      Below is the code for the same.

       

      // LocalPortTestApp.cpp : Defines the entry point for the console application.

      //

      //

       

      #include "stdafx.h"

      #include <objbase.h>

      #include <initguid.h>

      #include "I2Cpublic.h"

      #include <SetupAPI.h>

      #include <iostream>

      #include <algorithm>

      #include <combaseapi.h>

      #include <Windows.h>

      #include <RegStr.h>

      #include <WinBase.h>

      #include <tchar.h>

      #include <strsafe.h>

      #include <winioctl.h>

       

      using namespace std;

       

      /**

      * These are the generic rights used in serial com port open

      */

      #define S_GENERIC_READ           (0x80000000UL)       ///<Windows Constant

      #define S_GENERIC_WRITE          (0x40000000UL)       ///<Windows Constant

      #define S_GENERIC_EXECUTE        (0x20000000UL)       ///<Windows Constant

      #define S_GENERIC_ALL            (0x10000000U1L)      ///<Windows Constant

       

      /**

      * Constants used in serial com port open

      */

      #define S_CREATE_NEW          1UL    ///<Windows Constant

      #define S_CREATE_ALWAYS       2UL    ///<Windows Constant

      #define S_OPEN_EXISTING       3UL    ///<Windows Constant

      #define S_OPEN_ALWAYS         4UL    ///<Windows Constant

      #define S_TRUNCATE_EXISTING   5UL    ///<Windows Constant

       

      /*****************************************************************************************************

      *                               GENERAL TYPEDEF

      ****************************************************************************************************/

       

      typedef unsigned char         sUINT8;     ///<8 bit variable

      typedef signed char           sINT8;      ///<7 bit variable

      typedef unsigned char*        sUINT8P;    ///<8 bit variable pointer

      typedef const unsigned char*  sCUINT8P;   ///<8 bit constant variable pointer

      typedef short int             sINT16;     ///<15 bit variable

      typedef unsigned short        sUINT16;    ///<16 bit variable

      typedef unsigned short*       sUINT16P;   ///<16 bit variable pointer

      typedef long                  sINT32;     ///<31 bit variable

      typedef unsigned long         sUINT32;    ///<32 bit variable

      typedef unsigned long*        sUINT32P;   ///<32 bit variable pointer

      typedef const unsigned long*  sCUINT32P;  ///<32 bit variable pointer

      typedef float                 sFLOAT;     ///<float variable

      typedef double                sDOUBLE;    ///<double variable

      typedef unsigned char         sBOOL;      ///<8 bit variable

      typedef void*                 sVOIDP;     ///<memory pointer

      typedef const void*           sCVOIDP;    ///<memory pointer

       

      /**

      * ENUM for ERROR CODE which will be return value

      */

      enum returnStatus

      {

          S_SUCCESS = 0,                   ///<Task completed successfully

          S_ERROR_FAILURE = 1,             ///<Task is not completed, due to some reason

          S_ERROR_PORT_OPEN = 2,           ///<Error occurred while opening PC channel driver port

          S_ERROR_PORT_CLOSE = 3,          ///<Error occurred while closing PC channel driver port

          S_ERROR_CONFIG_PORT = 4,         ///<Error occurred while configuring PC channel driver port

          S_ERROR_READ_BUFFER = 5,         ///<Error occurred while reading data from internal port buffer

          S_ERROR_WRITE_BUFFER = 6,        ///<Error occurred while writing data to internal port buffer

          S_ERROR_ARGUMENT = 7,            ///<API argument is not valid

          S_ERROR_CHANNEL_INVALID = 8,     ///<Proper channel is not selected

          S_ERROR_TIME_OUT = 9,            ///<Waiting Time is over

          S_ERROR_SEND = 10,               ///<Error occurred while sending command to Sunset Pass Module, due to lack of acknowledgment from Sunset Pass Module or timeout.

          S_ERROR_SEQUENCE = 11,           ///<Violating task sequence I.e. configure then open etc.

          S_ERROR_PORT_ACQUIRED = 14,      ///<Error occurred while trying to acquire handle, acquired by else before and not released yet

          S_ERROR_HANDLE_MISMATCH = 15,    ///<Error occurred while port handle supplied as argument is not matching with handle acquired

          S_BOOT_MODE = 16                 ///<Microcontroller is in Boot Mode

      };

       

      #define BUF_SIZE  50

       

      int main(int argc, char* argv[])

      {

       

          returnStatus eResult = S_ERROR_PORT_OPEN;

       

          GUID *i2cGuid = const_cast<GUID *>(&I2C_LPSS_INTERFACE_GUID);

       

          HDEVINFO hDevInfo;

          SP_DEVINFO_DATA devInfoData;

       

          HANDLE i2c_Handle = HANDLE(NULL); ///<handle of i2c port to access it

          

          hDevInfo = SetupDiGetClassDevs(i2cGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);

       

          if(hDevInfo == INVALID_HANDLE_VALUE)

          {

              return S_ERROR_FAILURE;

          }

          else

          {

              std::cout << "SetupDiGetClassDevs is Successfull.\n";

          }

       

          devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

       

          SP_DEVICE_INTERFACE_DATA devInterfData = { 0 };

       

          devInterfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

       

          devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

       

          DWORD i = 0;

       

          if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, i2cGuid, i, &devInterfData))

          {

              DWORD size = 0;

       

              if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfData, NULL, 0, &size, 0))

              {          

                  if (GetLastError() == ERROR_NO_MORE_ITEMS)

                  {

                      eResult = S_SUCCESS;

                      while(1);

                      return 0;

                  }

       

                  PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, size);

       

                  pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

       

                  if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfData, pInterfaceDetailData, size, &size, &devInfoData))

                  {

                      std :: cout << "SetupDiGetDeviceInterfaceDetail is Failed.\n";

                      eResult = S_ERROR_FAILURE;

                      while(1);

                      return 0;

                  }

       

                  std :: cout << "CreatFile Calling.\n";

                  std :: cout << "PATH of I2C interface in REGEDIT : "<< pInterfaceDetailData->DevicePath<<endl;

                  std :: cout <<endl;

       

                  i2c_Handle = CreateFile(LPCWSTR(pInterfaceDetailData->DevicePath),

                                          DWORD(GENERIC_READ | GENERIC_WRITE),

                                          DWORD(FILE_SHARE_READ | FILE_SHARE_WRITE),

                                          LPSECURITY_ATTRIBUTES(NULL),

                                          DWORD(OPEN_EXISTING),

                                          DWORD(FILE_FLAG_OVERLAPPED),

                                          (HANDLE)NULL);

       

       

                  //Validation for correct open port

                  if(i2c_Handle == INVALID_HANDLE_VALUE)

                  {

                      std::cout << " Port Open Error : " << GetLastError() <<endl;

                  }

                  else

                  {

                      std :: cout << "Creatfile is successfull..... = "<< i2c_Handle << endl;

                      std::cout << endl;

                  }

              }

          }

          else

          {

              char ch;

              std::cout << "1... Press any key and then ENTER to exit\n";

              std::cin >> ch;

              return 0;

          }

       

          //HANDLE hEvent;

          DWORD varEventResult;

          //HANDLE varEventObjectHandle = 0;

        

          /*Overlapped1.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

       

          if(Overlapped1.hEvent)

          {

              std::cout <<"Create Event Successfull - 1." <<endl;

          }

          else

          {

              std::cout <<"Create event failed with error : "<< GetLastError() <<endl;

          }*/

       

          OVERLAPPED Overlapped1;

          /*Overlapped1.OffsetHigh = 0;

          Overlapped1.Offset = 0;*/

          memset(&Overlapped1, 0, sizeof(Overlapped1));

       

          BOOL status;

          I2C_SINGLE_TRANSMISSION writeTransmission;

          UCHAR writeBuf[2] = {0x90,0x00};

          UCHAR readBuf[BUF_SIZE] = {};

          UINT16 slaveAdr = 0x90;

          DWORD bytesReturned = 0;

       

          writeTransmission.Address = slaveAdr;

          writeTransmission.AddressMode = AddressMode7Bit;

          writeTransmission.BusSpeed = I2C_BUS_SPEED_400KHZ;

          writeTransmission.DataLength = sizeof(writeBuf);

          writeTransmission.pBuffer = writeBuf;

       

          status = DeviceIoControl(i2c_Handle,

                                   (DWORD)IOCTL_I2C_EXECUTE_WRITE,

                                   &writeTransmission,

                                   (DWORD)sizeof(writeTransmission),

                                   NULL,

                                   0,

                                   NULL,

                                   (LPOVERLAPPED)&Overlapped1);

       

          std::cout << "Write Transmission....."<<endl;

          std::cout << "Slave Address : "<<slaveAdr<<endl;

          std::cout << "Status : "<< status << endl << "Get-Last-Error-Code : "<< GetLastError() << endl;

          std::cout << endl;

       

          Sleep(10);

       

          //varEventResult = WaitForSingleObject(Overlapped1.hEvent, 10000);

       

          if(status || (GetLastError() == ERROR_IO_PENDING))

          {      

              status = GetOverlappedResult(i2c_Handle,

                                           (LPOVERLAPPED)&Overlapped1,

                                           &bytesReturned,

                                           TRUE);      

              if(status)

              {

                  std::cout << "Write Data : "<< writeBuf[0] << endl;

                  std::cout << endl;

              }

              else

              {

                  std::cout << "GetOverlappedResult....1 Failed - Write. "<< GetLastError() << endl;

                  std::cout << endl;

              }

       

              //ResetEvent(Overlapped1.hEvent);

              //CloseHandle(Overlapped1.hEvent);

          }

          else

          {

              std::cout << "Write Data Failed. "<< endl;

              std::cout << endl;

          }

       

          std::cout << "--------------------------------------------------------\n\n";

       

        

          OVERLAPPED Overlapped2;

          Overlapped2.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

       

          if(Overlapped2.hEvent)

          {

              std::cout <<"Create Event Successfull - 2." <<endl;

          }

          else

          {

              std::cout <<"Create event failed with error : "<< GetLastError() <<endl;

          }

        

          Overlapped2.OffsetHigh = 0;

          Overlapped2.Offset = 0;

       

          I2C_SINGLE_TRANSMISSION readTransmission;

          UINT16 slaveAdr1 = 0x91;

       

          readTransmission.Address = slaveAdr1;

          readTransmission.AddressMode = AddressMode7Bit;

          readTransmission.BusSpeed = I2C_BUS_SPEED_400KHZ;

          readTransmission.DataLength = sizeof(readBuf);

          readTransmission.pBuffer = readBuf;

       

          //memset(&Overlapped1, 0, sizeof(Overlapped1));

       

          ResetEvent(Overlapped1.hEvent);

       

          status = DeviceIoControl(i2c_Handle,

                                   (DWORD)IOCTL_I2C_EXECUTE_READ,

                                   NULL,

                                   0,

                                   &readTransmission,

                                   sizeof(readTransmission),

                                   NULL,

                                   (LPOVERLAPPED)&Overlapped2);

       

          Sleep(10);

       

          std::cout << "Read Transmission....."<<endl;

          std::cout << "Status : "<< status << endl << "Get-Last-Error-Code : "<< GetLastError() << endl;

          std::cout << endl;

       

          varEventResult = WaitForSingleObject(Overlapped2.hEvent, 10000);

        

          if(status || (GetLastError() == ERROR_IO_PENDING))

          {

              status = GetOverlappedResult(i2c_Handle,

                                           (LPOVERLAPPED)&Overlapped2,

                                           &bytesReturned,

                                           TRUE);

              if(status)

              {

                  std::cout << " data is : " << readBuf[0] << endl;

                  std::cout << endl;

              }

              else

              {

                  std::cout << "GetOverlappedResult....2 Failed - Read. "<< GetLastError() << endl;

                  std::cout << endl;

              }

       

              //ResetEvent(Overlapped2.hEvent);

              CloseHandle(Overlapped2.hEvent);

          }

          else

          {

              std::cout << "Read Data Failed. "<< endl;

          }

       

           CloseHandle(i2c_Handle);

       

           char ch;

           std::cout << "2... Press any key and then ENTER to exit.....\n";

           std::cin >> ch;

           return 0;

      }

       

       

       

      Below is the output of the above code:

      I would be grateful, If you can help me identify this issue and help resolve.

      Thanks in advance of your support.

       

      reg.

      -prajose john