QProcess does not operate on /sys/class/gpioxx



  • I have written a QProcess to access gpio ports on a Riot running Debain. If I send the command from the console (terminal) it works as advertised, for example
    "echo in > /sys/class/gpio/gpio112/direction "
    This is true for export, in out & direction, but if I send the same with QProcess it does not return an error, but nothing happens.

    /** ---------------------------------------------------------------------------
     * @brief riot_gpio::system_command
     * This method send a command line and list of arguments to the linux command
     * line and read the system response to the 'cmd' send
     * @note if more than one system reply this will concatenate the reponce
     * and send a single string as answer that must be parsed by the user
     * @param cmd
     * @param arguments
     * @param sys_return
     * @return
     */
    uint32_t riot_gpio::system_command (QString     & cmd,
                                        QStringList & arguments,
                                        QString     & sys_return)
    {
        QProcess process;
    
        // qProcess 'forward' all stderr messages to the stdout
        process.setProcessChannelMode(QProcess::MergedChannels);
    
        // exec the system commands, check if we need arguments
        if (arguments.count() > 0)
            // yip we do have arguments
            process.start (cmd, arguments);
        else
            // no no arguments
            process.start (cmd);
    
        // wait for the system process to finish the system cmd
        if (!process.waitForStarted(10) )
        {
            gprintf (FLRed"\nCould not start command %s "FGray, cmd.toLatin1().data() );
            return  false;
        }
        if (!process.waitForFinished(50))
        {
            // send a error message to the console
            gprintf (FLRed"\nNo finito for %s "FGray, cmd.toLatin1().data() );
            return  false;
        }
        // read the system outout and passed this to the caller answer string
        QByteArray result = process.readAll();
        sys_return.clear();
        sys_return.append(result);
        return true;
    }
    

    I tried to send normal command like ls, etc, it works, but not when you try to access the ports.
    I also tried to run it as root, the same story
    I initialise the GPIOs with the following

    /** ---------------------------------------------------------------------------
     * @brief riot_gpio::init_gpio_pin
     * This method used the ENUM port to lookup the pin number to set the port pin
     * as either input or output
     * @param port          ENUM port pin;
     * @param input_output
     */
    void riot_gpio::init_gpio_pin(uint32_t enum_port,  bool input_nOutput)
    {
        QString     command, answer;
        int32_t     pin_number;
    
        // lookup the port pin
        pin_number = lookup_pin_number (enum_port);
    
        if (verbose)
            gprintf(FLCyan,"\n Set GPIO [%s] %03d %s "FGray,
                    display_pin_number_name(enum_port),
                    pin_number,
                    display_direction(input_nOutput)
                    );
    
        // set the system variable in Linux
        command.sprintf("echo %d > /sys/class/gpio/export",  pin_number);
        if (!system_command(command, answer))
        {
            gprintf (FLRed"\ncmd[%s]\n  Error: init_gpio_pin Export %s to %s %s"FGray,
                     command.toLatin1().data(),
                     display_pin_number_name(enum_port),
                     display_direction(input_nOutput),
                     answer.toLatin1().data());
        }
        // set the system variable direction
        command.sprintf ("echo %s > /sys/class/gpio/gpio%d/direction \n",
                         (input_nOutput==true?"in":"out"),
                         pin_number);
        if (!system_command(command, answer))
        {
            gprintf (FLRed"\ncmd[%s]\n   Error: init_gpio_pin SetDir %s to %s %s"FGray,
                     command.toLatin1().data(),
                     display_pin_number_name(enum_port),
                     display_direction(input_nOutput),
                     answer.toLatin1().data());
        }
    }
    

    To access ports i have

    /** ---------------------------------------------------------------------------
     * @brief riot_gpio::set_gpio_pin
     * @param pin_no
     * @param state
     */
    void riot_gpio::set_gpio_pin(uint32_t pin_no, BOOL state)
    {
        QString command, answer;
    
        command.sprintf ("echo %d > /sys/class/gpio/gpio%d/value ",
                         state,
                         pin_no);
        if (!system_command(command, answer))
        {
            gprintf (FLRed"\ncmd[%s]=> Error set pin %d to %d %s"FGray,
                     command.toLatin1().data(),
                     pin_no, state, answer.toLatin1().data());
        }
    }
    /** ---------------------------------------------------------------------------
     * @brief riot_gpio::get_gpio_pin
     * @param pin_no
     * @return
     */
    UINT_32 riot_gpio::get_gpio_pin(uint32_t pin_no)
    {
        UINT_32  li = 0;
        QString  command, answer;
    
        command.sprintf ("cat /sys/class/gpio/gpio%d/value",  pin_no);
    
        if (!system_command(command, answer))
        {
            gprintf (FLRed"\ncmd[%s]=> Error read pin%d status %s"FGray,
                     command.toLatin1().data(),
                     pin_no,
                     answer.toLatin1().data());
        }
        li = answer.toInt();
        if (verbose)
            gprintf ("\n>> Read gpio_pin::pin%d = '%d' ",
                     pin_no, li);
        return li;
    }
    

    I read that you cannot use scripts with QProcess, is this then also true with the echo?

    Thanks


  • Moderators

    Hi! QProcess can call a program with arguments. This: echo in > /sys/class/gpio/gpio112/direction is not a program with arguments but a shell command. echo is a program and here in is passed as argument. So you could run this with QProcess but not the rest because the rest needs to be interpreted by a shell. There is also no reason use "echo blah > .." and another process here. /sys/class/blah is a file. You can just write to that file using QFile, etc.



  • Thanks, I changed it and could access the file as output, but seem to have a problem reading the output state, and inputs, can you direct me to a site with an example, please.


  • Moderators

    You can see here how to use streams to read from files: http://doc.qt.io/qt-5/qfile.html#details.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.