Developing an Application, which communicates with COM for Windows on Linux (MinGW-64)

Globment.de - Blog

Developing an Application, which communicates with COM for Windows on Linux (MinGW-64)
MinGW-64 is an OpenSource project and contains cross-compilers for Linux to build Applications for Windows. This post will show how to implement an Application communicating with a specific COM-Port on Windows. The Application will be able to read data from an connected device to display them in Windows CMD. For Debian based Linux system you can download compiler and linker with following command :


      apt-get install x86_64-w64-mingw32-gcc

      
After the package has installed on you system you can use a simple coding editor to implement the Application. First you will need to include following headers.
      

      #include <windows.h>
      #include <stdio.h>
      #include <stdbool.h>

      
      
To be able to read from COM-Port it is necessary to select the correct COM-ID. The following function selects the last added COM-Port and returns the ID of it.


      int SelectComPort() 
      {
          char lpTargetPath[5000]; 
          int portsList[256];
          int count = 0;

          for (int i = 0; i < 255; i++) 
          {
              DWORD res = QueryDosDevice(str, lpTargetPath, 5000);

              if (res != 0) 
              {
                  portsList[count] = i;
                  count++;
              }
          }
          return portsList[count - 1];
      }

    
The main function opens the selected COM-Port and starts reading from it in a while loop. Specific attributes like baud rate and timeout are set to the COM-State.

      int main()
      {
        HANDLE port;
        char fileName[256];

        sprintf(fileName, "\\\\.\\COM%d", SelectComPort());
        fileName[strlen(fileName)] = '\0';
          port = CreateFileA(fileName,  
              GENERIC_READ | GENERIC_WRITE, 
              0,                           
              NULL,                        
              OPEN_EXISTING,
              0,            
              NULL);        

        if (port == INVALID_HANDLE_VALUE)
          printf("Error in opening serial port\n");
        else
          printf("opening serial port successful\n");

        COMMTIMEOUTS timeouts = {0};
        timeouts.ReadIntervalTimeout = 0;
        timeouts.ReadTotalTimeoutConstant = 200;
        timeouts.ReadTotalTimeoutMultiplier = 0;
        timeouts.WriteTotalTimeoutConstant = 100;
        timeouts.WriteTotalTimeoutMultiplier = 0;

        bool success = SetCommTimeouts(port, &timeouts);
        if (!success)
        {
          printf("Failed to set serial timeouts\n");
          CloseHandle(port);
          return -1;
        }


        DCB state = {0};
        state.DCBlength = sizeof(DCB);
        state.BaudRate = 9600; 
        state.ByteSize = 8;
        state.Parity = NOPARITY;
        state.StopBits = ONESTOPBIT;
        success = SetCommState(port, &state);
        
        if (!success)
        {
          printf("Failed to set serial settings\n");
          CloseHandle(port);
          return -1;
        }
        

        DWORD received;
        char buffer;
        
        int size;
        size = sizeof(buffer);
        
        while(buffer != '-1') { //change for your break condition
          success = ReadFile(port, &buffer, size, &received, NULL);
          if(success) {
            printf("Read from serial port %c\n", buffer);
          } else {
            printf("[Read from serial port failed");
          }
        }


        
        CloseHandle(port);

        return 0;
      }
    
To get an executable file for Windows you need to compile and link it with MinGW-64 cross-compiler.

      x86_64-w64-mingw32-gcc -Wall -c "%f" -I path-to-your-mingw-include-dir 
      x86_64-w64-mingw32-gcc -Wall -o "%e" "%f"     
    
If everything went without errors the compiler will generate an exe file in your working directory.
Useful links:
MSDN Win32 API

Tags: #Win32 #minGW-64 #Cross-compiler #Win-API