4

I wrote the following program to communicate with with an Arduino UNO. This test program let the user send one byte at a time from PC to the Arduino board. If the broad received byte sequence 65,71,67,68 UNO broad will blink the built-in LED and write the same sequence 65,71,67,68 to the serial buffer. Otherwise the broad does nothing.The Arduino sketch I wrote works as intended(I checked it using the serial monitor).

But the C++ program doesn't always receive the full byte sequence.
Received sequence can be (65,71,67,68) or (65,71,67) or (65,71) or 65 or 0 in different iterations. some insight would be greatly appreciated.

#include "libusb.h"
#include <iostream>`
#include <stdio.h>`
#include <string.h>`
#include <unistd.h>`

libusb_device_handle *dev_handle;
libusb_context *ctx = NULL;

static int ENDPOINT_IN  = 0x83;
static int ENDPOINT_OUT = 0x04;

static const int    USB_TIMEOUT = 2000;     

int CLOSE_DEVICE();
int OPEN_DEVICE();

int main(){

if(OPEN_DEVICE()!=0){
    printf("Device Open Failed!\n");
    libusb_close(dev_handle); 
    libusb_exit(ctx); 
    return -1;
}


int rc=-1;
    
unsigned char encoding[] = { 0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08 }; //9600 1N8

    rc = libusb_control_transfer(dev_handle,0x21, 0x20, 0, 0, encoding,7, 0);
    if (rc < 0) {
        
            printf("ERROR IN CONTROL TRANSFER!\n");
    }

unsigned char cUsbBuf[64]={0,0,0,0};
unsigned char iUsbBuf[64]={0,0,0,0};
int   nBytes=0;
int status =-1;
unsigned int character=0;

        
    while(1){

        printf("send byte:");
        scanf("%u",&character); 

        if(character==255){
            break;
        }else{
            cUsbBuf[0] = static_cast<unsigned char>(character);
        }

        status = libusb_bulk_transfer(dev_handle, (ENDPOINT_OUT|LIBUSB_ENDPOINT_OUT),cUsbBuf,1,&nBytes, USB_TIMEOUT);
        if(status<0){
            printf("TRANSFER ERROR:%s\n",libusb_error_name(status));
        }

        printf(")ut Bytes:%d\n",nBytes);
        usleep(2000000);
        
        status = libusb_bulk_transfer(dev_handle,(ENDPOINT_IN|LIBUSB_ENDPOINT_IN),iUsbBuf,4,&nBytes, USB_TIMEOUT);
    
        if(status<0){
            printf("TRANSFER ERROR:%s\n",libusb_error_name(status));
        }
        printf("in Bytes:%d\n",nBytes);
    
        for(int i=0;i<4;++i){
            printf("%d ", iUsbBuf[i]);
            iUsbBuf[i]=0;
        }
        printf("\n\n\n");
        nBytes=0;

                    
    }
    


CLOSE_DEVICE();

return 0;

}

int CLOSE_DEVICE(){

if(libusb_release_interface(dev_handle, 0)!=0){ //release the claimed interface 0
    printf("Error releasing interface 0 !\n",1);
        return -1;
    }


if(libusb_release_interface(dev_handle, 1)!=0){ //release the claimed interface 1
    printf("Error releasing interface 1 !\n",1);
        return -1;
    }

libusb_close(dev_handle); 

libusb_exit(ctx); 

return 0;

}

int OPEN_DEVICE(){

libusb_device **devs;
ssize_t cnt; 

if(libusb_init(&ctx)<0){
    printf("ERROR INIT!");
    return -1;
} 
    
cnt=libusb_get_device_list(ctx, &devs);
    
dev_handle = libusb_open_device_with_vid_pid(ctx,0x2341,0x0043); //ARIDUNO UNO VENDER and DEVICE ID 0x2341:0x0043

if(dev_handle == NULL){
    printf("ERROR OPENING!");
        return -1;
}
    else{
        printf("UNO OPENED!\n");
}

libusb_free_device_list(devs, 1);
libusb_reset_device(dev_handle);

if(libusb_set_configuration(dev_handle,1)<0){
    printf("SET CONFIG ERROR!\n");
}   

for(int k=0;k<2;++k){

    if(libusb_kernel_driver_active(dev_handle, k) == 1) { 

            printf("KERNEL DRIVER ACTIVE:INTERFACE %d\n",k);
        if(libusb_detach_kernel_driver(dev_handle, k) != 0){ 
            printf("ERROR KERNEL DETACH:INTERFACE %d\n",k);
                return -1;
        }
        }
            
    if(libusb_claim_interface(dev_handle, k)<0){
        printf("ERROR CLAM INTERFACE %d!\n",k);
        return -1;
    }

    printf("INTERFACE %d CLAMED!\n",k);

}

return 0;

}

The Arduino sketch is also attached here.

unsigned char buff[] = {0, 0, 0, 0};

    void setup() {
        Serial.begin(9600);
        while (!Serial){
           ;
        }
        Serial.setTimeout(5000);
        pinMode(LED_BUILTIN, OUTPUT);
    }
    
void loop() {}

void serialEvent() {

  if (Serial.available() >= 4) {

      Serial.readBytes(buff, 4);

      if ((buff[0] == 65) && (buff[1] == 71) && (buff[2] == 67) && (buff[3] == 68)) {
      
      Serial.write(buff,4);
      Serial.flush();
      digitalWrite(LED_BUILTIN, HIGH);
      buff[0]=buff[1]=buff[2]=buff[3]=0x0;
      delay(500);

      }
    
    digitalWrite(LED_BUILTIN, LOW);

  }
}

The Compiler output is attached here

g++ -Wall -fPIC -Wextra -Werror -pedantic -pedantic-errors -O3 -I. -o UNOTEST UNOTest_2.cpp -L/home/mkovash/sis3153/libUSB1Driver/libusb-1.0.23/exports/lib -Bstatic -lusb-1.0
In file included from UNOTest_2.cpp:1:0:
libusb.h:741:46: error: ISO C++ forbids zero-size array ‘dev_capability_data’ [-Wpedantic]
  uint8_t dev_capability_data[ZERO_SIZED_ARRAY];
                                              ^
libusb.h:766:78: error: ISO C++ forbids zero-size array ‘dev_capability’ [-Wpedantic]
  struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY];
                                                                              ^
libusb.h:1259:70: error: ISO C++ forbids zero-size array ‘iso_packet_desc’ [-Wpedantic]
  struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY];
                                                                      ^
UNOTest_2.cpp: In function ‘int main()’:
UNOTest_2.cpp:48:9: error: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Werror=unused-result]
    scanf("%u",&character);
    ~~~~~^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
  • 1
    https://stackoverflow.com/editing-help – Yunnosch Jun 30 '20 at 13:28
  • Giving that info down here in the comments did not work? Try [edit] your question to provide all info directly there. – Yunnosch Jun 30 '20 at 13:30
  • the uno resets on new usb connection – Juraj Jun 30 '20 at 13:36
  • @danulagodagama Do you get any warnings when compiling? Include those in the question in that case. – Ted Lyngmo Jun 30 '20 at 14:02
  • @TedLyngmo I attached the compiler output. – danula godagama Jun 30 '20 at 14:12
  • @danulagodagama Good, but fix the undefined behavior I mentioned in my answer. Both in your own code and in your question. Otherwise it doesn't matter how many things we fix. If the program has undefined behavior _anything_ can happen. – Ted Lyngmo Jun 30 '20 at 14:13
  • `printf("Error releasing interface 0 !\n",1);` also has undefined behavior. You add an `int` (`1`) on the stack but you haven't told `printf` to read it. – Ted Lyngmo Jun 30 '20 at 14:14
  • Can you add compiler options? `-Wall` is good. Add these: `-Wextra -Werror -pedantic -pedantic-errors` – Ted Lyngmo Jun 30 '20 at 14:16
  • 1
    @TedLyngmo Will Do! – danula godagama Jun 30 '20 at 14:18
  • @TedLyngmo updated the compiler output – danula godagama Jun 30 '20 at 14:24
  • 1
    It seems `libusb.h` isn't well prepared to be used in a C++ program. `uint8_t dev_capability_data[0];` is not a valid C++ array :-/ Even C forbids it. Not a very good lib I'd say. – Ted Lyngmo Jun 30 '20 at 14:26
  • I checked the libusb log and on Wed Jul 5 13:09:29 2017 they made a patch to make the code valid C (by using a flexible array instead of a zero-size array). This does however not make it valid C++. – Ted Lyngmo Jun 30 '20 at 14:36
  • @TedLyngmo May be I should write my program in C instead – danula godagama Jun 30 '20 at 14:40
  • @danulagodagama It's certainly an option, but you still need a newer version of libusb if you are going to be able to keep the extra support those compiler flags I mentioned will give. You couldn't compile it as a C program either with your current version of libusb with those flags unfortunately. – Ted Lyngmo Jun 30 '20 at 14:42
  • @Juraj USB connection occurs at the beginning of the program. It doesn't get reset with in the while loop. – danula godagama Jun 30 '20 at 15:04
  • Can I ask where did you get the encoding part? `unsigned char encoding[] = { 0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08 }; //9600 1N8` – Vahagn Sep 21 '21 at 12:10
  • I am not sure, but the wiki page https://en.wikipedia.org/wiki/8-N-1 says that the encoding you set is related to the asynchronous mode. The problem might be there. – Vahagn Sep 21 '21 at 12:14

0 Answers0