Primeira contribuição ao Linux

By Filipe Tressmann

Como parte da disciplina MAC0470, tive a oportunidade de enviar um patch para o kernel do Linux.

O patch foi uma contribuição ao driver ti-ads124s08. Esse driver, anteriormente, não fazia uso da função iio_device_claim_direct, responsável por garantir que diferentes modos de leitura não entrem em conflito entre si.

Para realizar essa modificação, precisei me aprofundar no funcionamento do subsistema IIO (Industrial I/O) do kernel, compreendendo tanto o propósito da função quanto a forma como ela interage com o restante do código. Também estudei como drivers são integrados ao sistema operacional, o que me deu uma visão mais ampla da arquitetura do Linux.

Além de adicionar a chamada à função mencionada, aproveitei para refatorar uma parte do código que estava duplicada. O trecho a seguir aparecia tanto na função read_raw quanto no trigger handler:

ret = ads124s_write_reg(indio_dev, ADS124S08_INPUT_MUX, chan->channel);
if (ret) {
    dev_err(&priv->spi->dev, "Set ADC CH failed\n");
    goto out;
}

ret = ads124s_write_cmd(indio_dev, ADS124S08_START_CONV);
if (ret) {
    dev_err(&priv->spi->dev, "Start conversions failed\n");
    goto out;
}

ret = ads124s_read(indio_dev);
if (ret < 0) {
    dev_err(&priv->spi->dev, "Read ADC failed\n");
    goto out;
}

*val = ret;

ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV);
if (ret) {
    dev_err(&priv->spi->dev, "Stop conversions failed\n");
    goto out;
}

Essa lógica foi extraída para uma função auxiliar, tornando o código mais limpo e reutilizável:

static int  ads124s_read_channel(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) {
       int ret = ads124s_write_reg(indio_dev, ADS124S08_INPUT_MUX, chan);
       if (ret) {
               dev_err(&priv->spi->dev, "Set ADC CH failed\n");
               return ret;
       }
       
       ret = ads124s_write_cmd(indio_dev, ADS124S08_START_CONV);
       if (ret) {
               dev_err(&priv->spi->dev, "Start ADC conversions failed\n");
               return ret;
       }

       ret = ads124s_read(indio_dev);
       if (ret < 0) {
               dev_err(&priv->spi->dev, "Read ADC failed\n");
               return ret;
       }

       *val = ret;

       ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV);
       if (ret) {
               dev_err(&priv->spi->dev, "Stop conversions failed\n");
               return ret;
       }

       return IIO_VAL_INT;
}