craspberry-pipopenavrdude

Read output of avrdude in C program using popen()


I need to use the same program to program multiple different microcontrollers with avrdude. To do this I need to identify the device signature of the connected microcontroller to use the correct avrdude command. The only way I've found to do this in-software is to call avrdude with an incorrect microcontroller, and read the result where it gives the device signature. I am trying to use popen() to read the output of avrdude, but I'm not getting anything at all. Here's the code I am using to test popen():

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char ch, avrBuffer[100];
    FILE *avr;

    avr = popen("sudo avrdude -n -q -p x192d3 -c avrisp2", "r");

    if(avr == NULL) {
        printf("Unable to open avrdude");
        return(0);
    }

    fgets(avrBuffer, 100, avr);
    printf("Buffer: %s \n", avrBuffer);

    pclose(avr);
    return EXIT_SUCCESS; 
}

Running this gives me this result:

avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x000000 (retrying)
avrdude: Device signature = 0x1e9749 (probably x192d3)

avrdude done.  Thank you.

Buffer:  

As you can see, the buffer isn't getting anything added to it. However, when I switch to a different command:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char ch, avrBuffer[100];
    FILE *avr;

    avr = popen("uname", "r");

    if(avr == NULL) {
        printf("Unable to open avrdude");
        return(0);
    }

    fgets(avrBuffer, 100, avr);
    printf("Buffer: %s \n", avrBuffer);

    pclose(avr);
    return EXIT_SUCCESS;
}

I get this result, which is what I was expecting:

Buffer: Linux

Am I using popen() wrong, or is there a different way I should be doing this? If it matters, I am running the program on a Raspberry Pi.


Solution

  • Based on the wording of the documentation for the -l logfile option, these messages probably classify as "diagnostics output" and are therefore written to stderr, not stdout which is captured by popen.

    One way to solve this would be to redirect avrdude's stderr to its stdout. E.g. you could append 2>&1 to the end of the first argument to popen:

    avr = popen("sudo avrdude -n -q -p x192d3 -c avrisp2 2>&1", "r");