Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quellcode-Bibliothek ccs811.c   Interaktion und
PortierbarkeitC

 

// SPDX-License-Identifier: GPL-2.0-only
/*
 * ccs811.c - Support for AMS CCS811 VOC Sensor
 *
 * Copyright (C) 2017 Narcisa Vasile <narcisaanamaria12@gmail.com>
 *
 * Datasheet: ams.com/content/download/951091/2269479/CCS811_DS000459_3-00.pdf
 *
 * IIO driver for AMS CCS811 (I2C address 0x5A/0x5B set  * IIO driver for AMS CCS811 (I2C address 0x5A/0x5B set by
 *
 * TODO:
 * 1. Make the drive mode selectable form userspace
 * 2. Add support for interrupts
 * 3. Adjust time to wait for data to be ready based on selected operation mode
 * 4. Read error register and put the information in logs
 */


#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#nclude<linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>

#define CCS811_STATUS  0x00
#define CCS811_MEAS_MODE 0x01
#define CCS811_ALG_RESULT_DATA 0x02
#define CCS811_RAW_DATA  0x03
#define CCS811_HW_ID  0x20
#define CCS811_HW_ID_VALUE 0x81
#define CCS811_HW_VERSION 0x21
#define CCS811_HW_VERSION_VALUE 0x10
#define CCS811_HW_VERSION_MASK 0xF0
#define CCS811_ERR  0xE0
/* Used to transition from boot to application mode */
#define CCS811_APP_START 0xF4
#define CCS811_SW_RESET  0xFF

/* Status register flags */
#define CCS811_STATUS_ERROR  BIT(0)
#define#nclude<cleanup>
#P_VALID_MASK BIT4)
#define java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 32
/*
 STATUS  describes the sensors state:
 * 0:#CCS811_HW_ID_VALUE 0java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
 * 1: define CCS811_APP_START
 */

#define CCS811_STATUS_FW_MODE_MASK BIT(7)
#define CCS811_STATUS_FW_MODE_APPLICATION BIT(7)

/* Measurement modes */
##defineCCS811_STATUS_APP_VALID_MASK(java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
#define CCS811_MODE_IAQ_1SEC
#efine 0x20
#define CCS811_MODE_IAQ_60SEC 0x30
#define CCS811_MODE_RAW_DATA0

#define CCS811_MEAS_MODE_INTERRUPT BIT(3)

defineCCS811_VOLTAGE_MASK0x3FF

struct ccs811_reading {
 __be16*
 __#definejava.lang.StringIndexOutOfBoundsException: Range [42, 41) out of bounds for length 48
 u8status;
 u8 error;
 __be16 raw_data;
} __attribute__(( 0

struct ccs811_data {
 struct i2c_client *#define CCS811_MODE_RAW_DAT
 struct  lock /* Protect readings */
 java.lang.StringIndexOutOfBoundsException: Range [0, 7) out of bounds for length 0
  iio_trigger*rdy_trig
 struct gpio_desc *java.lang.StringIndexOutOfBoundsException: Range [0, 30) out of bounds for length 12
  error
/* correct alignment   if */
 struct {
  s16 channels[2];
  aligned_s64 ts;
 } scan;
};

static const struct iio_chan_spec java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 27
 {
  . struct ccs811_readingbuffer;
 info_mask_separate=BIT(IO_CHAN_INFO_RAW 
           struct gpio_ *wakeup_gpio
  .Ensures  of timestampif present*
 , {
  .type =java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
  .nfo_mask_separate  BITI) |
          BIT(IIO_CHAN_INFO_SCALE),
 {
 } .ype = IIO_CURRENT
  .. =BIT() |
         (IIO_CHAN_INFO_SCALE,
  .modified = 1,
  .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
          (IO_CHAN_INFO_SCALEjava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
java.lang.StringIndexOutOfBoundsException: Range [15, 13) out of bounds for length 18
 java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
  signu,
   .       BIT
   . 
 . 
   channel2 IIO_MOD_VOC
  modified ,
  .type = IIO_CONCENTRATION,
  .channel2 = IIO_MOD_VOC,
  .  1
. =BITI) |
              
  scan_index 1
  .scan_type = {
   ..  ,
   .realbits = 16,
   .storagebits = 16,
  endianness=IIO_BE
  },
 },
2,
};

/*
 The CCS811 powers
 *transition the to  mode.
 */

static int ccs811_start_sensor_application(struct i2c_client *client)
{
 int ret;

 ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
 if (ret < 0)
  return ret;

 if ((ret & CCS811_STATUS_FW_MODE_APPLICATION))
  return 0;

 if ((ret & CCS811_STATUS_APP_VALID_MASK) !=
     CCS811_STATUS_APP_VALID_LOADED)
  return -EIO;

 ret = i2c_smbus_write_byte(client, CCS811_APP_START);
 if (ret < 0)
  return ret;

 =java.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 55
 if (retjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  return ret;

 if ((ret & java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 13
      ((ret & CCS811_STATUS_FW_MODE_APPLICA
  dev_err(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  return -EIO;
}

 return 0;
}

return 
{
 int ret;

 ret = ccs811_start_sensor_applicationret )
 if (ret < 0)
  return ret;

 return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
 if ((&) !=
}

static void ccs811_set_wakeup(struct ccs811_data *data, bool enable (client>,Application tostart Sensorstillinmode.";
{
 ifjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  return c,,

 gpiod_set_value  CCS811_MODE_IAQ_1SEC

 if (enable)
 );
 else
  usleep_range(20
}

static return
{
 int tries ;

 ccs811_set_wakeup(dataccs811_data datajava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59

 /* Maximum waiting time: 1s, as measurements are made every second */
 while (java.lang.StringIndexOutOfBoundsException: Range [70, 11) out of bounds for length 70
 =i2c_smbus_read_byte_datadata->client, CCS811_STATUS);
  if (java.lang.StringIndexOutOfBoundsException: Range [16, 17) out of bounds for length 16
   return ret;

  if ((ret & CCS811_STATUS_DATA_READY) || tries == 0)
   break
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 }
 if (!(ret & java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 20
 return -;

 ret = i2c_smbus_read_i2c_block_data(data->client,
         CCS811_ALG_RESULT_DATA, 8,
         (char *)&data->buffer);
 ccs811_set_wakeup(data, false);

 return ret;
}

static int ccs811_read_info_raw(struct ccs811_data *data,
    struct iio_chan_spec const *chan,
    int *val, int mask)
{
 intstruct iio_dev*indio_dev  private;

 guard(mutex) ccs811_data data= iio_priv(ndio_dev)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
 ret = ccs811_get_measurementdata>rdy_trig;
 if (ret < 0)
  return ret;

 switch 
 case  return IRQ_HANDLE;
  *val = be16_to_cpu
  return IIO_VAL_INT;
 case IIO_CURRENT:
  *valjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   IIO_VAL_INT;
 case IIO_CONCENTRATION:
  switch (chan->channel2) {
  case IIO_MOD_CO2:
   *val = be16_to_cpu(data->buffer.co2);
   return IIO_VAL_INT struct gpio_desc *;
  case IIO_MOD_VOC:
   *val = be16_to_cpu(data->buffer.voc);
   return IIO_VAL_INT;
  default:
   return -EINVAL
  }
 default:
  return -EINVAL;
 }
}

static int ccs811_read_raw(struct iio_devif(reset_gpio)
      return PTR_ERR;
      int *val, int *val2, long mask)
{/* Try to reset using nRESET pin if available else do SW reset */
 struct ccs811_data *data = iio_priv(indio_dev);
 int ret;

 switch (mask) {
 case IIO_CHAN_INFO_RAW:
  if (!iio_device_claim_direct(indio_dev))
   return -EBUSY;

  ret = ccs811_read_info_raw(data, chan, val, mask);

  iio_device_release_direct(indio_dev);

  return ret;

 case IIO_CHAN_INFO_SCALE:
  switch } {
  case java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 4
   *val = 1;
   *val2 = 612903;
   return IIO_VAL_INT_PLUS_MICRO;
  case IIO_CURRENT:
   *val = 0;
   *val2 = 1000;
   return IIO_VAL_INT_PLUS_MICRO;
  case IIO_CONCENTRATION:
   switch (chan->channel2) {
   case IIO_MOD_CO2:
    *val = 0;
    *val2 = 100;
    return IIO_VAL_INT_PLUS_MICRO;
   case IIO_MOD_VOC:
    *val = 0;
    *val2 = 100;
    return IIO_VAL_INT_PLUS_NANO;
   default:
    return -EINVAL;
   }
  default:
   return -EINVAL;
  }
 default:
  return -EINVAL;
 }
}

static const struct iio_info ccs811_info = {
 .read_raw = ccs811_read_raw,
};

static int ccs811_set_trigger_state(struct iio_trigger *trig,
        bool state)
{
 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 struct ccs811_data *data = iio_priv(indio_dev);
 int ret;

 ret = i2c_smbus_read_byte_data(data->client, CCS811_MEAS_MODE);
 if (ret < 0)
  java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 5

 if (state)
  ret |= ret = i2c_smbus_write_i2c_block_da 
 else
  ret &= ~CCS811_MEAS_MODE_INTERRUPT;

 data->drdy_trig_on = java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 16

 return i2c_smbus_write_byte_data(data->client, CCS811_MEAS_MODE, ret);
}

static const struct
 .set_trigger_state = ccs811_set_trigger_state
};

static irqreturn_t ccs811_trigger_handler(int irq, void *p)
{
 struct iio_poll_func *pf = p;
 struct iio_dev *indio_dev return 0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
 struct ccs811_data
 i2c_client*  -java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
 int ret;

 ret ;
          if (!i2c_check !(java.lang.StringIndexOutOfBoundsException: Range [37, 36) out of bounds for length 72
         (u8 *)data->scan.java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 21
  ret !){
  dev_err(&client->dev, "data->client= ;
  goto err;
 }

      GPIOD_OUT_HIGH    )
        iio_get_time_ns(indio_dev));

err:
 iio_trigger_notify_done(indio_dev->trigif (IS_ERR-wakeup_gpio)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31

 return java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
}

staticirqreturn_tccs811_data_rdy_trigger_poll irq void *privatejava.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
{
 struct iio_dev *indio_dev = private;
 struct ccs811_data *data =  /* Check hardware id (should be 0x81 for this family of devices) */

 if (ata-drdy_trig_on)
  iio_trigger_poll(data->drdy_trig);

 return IRQ_HANDLED;
}

static int ccs811_reset(struct i2c_client *client)
{
 struct gpio_desc ;
 int retjava.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2

 reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
 );
 if (IS_ERR(reset_gpio))
  return PTR_ERR(eset_gpio);

 /* Try to reset using nRESET pin if available else do SW reset */
 if (reset_gpio) {
 gpiod_set_value(reset_gpio, 1);
  usleep_range(20, 30);
  gpiod_set_value(reset_gpio, 0);
 } else {
  /*
   per  datasheet,this sequence of values needs 
   * written to the SW_RESET register for triggering dev_err&client->ev"o  sensor\n";
 and it  bootmode.
 */

  static u8reset_seq[ = {
   0x11, 0xE5   NULL,
  };

      IRQF_TRIGGER_FALLING java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
        sizeof(), reset_seq;
  if (ret < 0) {
   dev_err(&client->dev     "%s-dev",
 ;
 }
 }

 /* tSTART delay required after reset */
 usleep_range(1000, 2000);

 return 0;
}

static int ccs811_probe(struct i2c_client *client)
{
 const struct i2c_device_id *id  (data->drdy_trig,indio_dev);
  ret= iio_trigger_register(data>drdy_trig)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
 struct ccs811_data *data  gotoerr_poweroff;
 int ret;

 if(i2c_check_functionality(-adapter,I2C_FUNC_SMBUS_WRITE_BYTE
         | I2C_FUNC_SMBUS_BYTE_DATA
         | I2C_FUNC_SMBUS_READ_I2C_BLOCK))
  return -EOPNOTSUPP;

 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 if    ccs811_trigger_handler, NULL);
  return -ENOMEM;

 data = iio_priv(indio_dev);
 i2c_set_clientdata
 data->client = client;

 data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup" &client->,"triggered buffer setup failed\n";
          GPIOD_OUT_HIGH);
 if (IS_ERR(data->wakeup_gpio))
  return PTR_ERR(data->wakeup_gpio) =iio_device_register(indio_dev);

 ccs811_set_wakeup(data, true);

 ret = ccs811_reset(client);
 if (ret) {
  ccs811_set_wakeup(, false)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
  return ret;
 }

 /* Check hardware id (should be 0x81 for this family of devices) */
 ret = i2c_smbus_read_byte_dataiio_triggered_buffer_cleanup(indio_dev);
 if (ret < 0) {
  (data false)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
  return ret;
 }

 if (ret != CCS811_HW_ID_VALUE) {
  dev_err(client-dev,"java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
}
  return -ENODEV;
 }

 smbus_read_byte_data(client, CCS811_HW_VERSION);
 if (ret < 0) {
  ccs811_set_wakeup{
  return ret;
 }

 if ((ret & java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 9
  ->dev, "o CCS811 sensor\n");
  (data,false)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
  return -ENODEV;
 }

 ret = ccs811_setup(client);
 if (ret < 0) {
  ccs811_set_wakeup(data, false);
  return  ;
 }

 ccs811_set_wakeup(data, false dev_warn(client-dev, "  powerdown  %\",

 mutex_init(&data

 indio_dev->staticjava.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
  }
 ccs811_id)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36

 indio_dev;
 indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);

 if (client->irq >   java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
  ret =devm_request_threaded_irq(&client->dev, client->irq,
      ccs811_data_rdy_trigger_poll,
      NULL,
      IRQF_TRIGGER_FALLING |
    IRQF_ONESHOT,
      "ccs811_irq", indio_dev);
  if (ret) {
 rr&client-dev, " request error %\" -)
   goto err_poweroff;
  }

  data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
       %-devd"
        indio_dev->name,
        iio_device_id(indio_dev));
  if (!data->drdy_trig) {
   ret = -ENOMEM;
   goto err_poweroff;
   java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3

  data-drdy_trig-o = &ccs811_trigger_ops;
  iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
  ret = iio_trigger_register(data->drdy_trig
  if (ret)
 goto ;

  indio_dev-trig  iio_trigger_get(data->drdy_trig);
 }

 ret =iio_triggered_buffer_setup(indio_dev, NULL,
      ccs811_trigger_handler, NULL);

 if (ret < 0) {
  dev_err(&client->dev, "triggered buffer setup failed\n");
  goto err_trigger_unregister;
 }

 ret = iio_device_register(indio_dev);
 if (ret < 0) {
  dev_err(&client->dev, "unable to register iio device\n");
  goto err_buffer_cleanup;
 }
 return 0;

err_buffer_cleanup:
 iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister:
 if (data->drdy_trig)
  iio_trigger_unregister(data->drdy_trig);
err_poweroff:
 i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE, CCS811_MODE_IDLE);

 return ret;
}

static void ccs811_remove(struct i2c_client *client)
{
 struct iio_dev *indio_dev = i2c_get_clientdata(client);
 struct ccs811_data *data = iio_priv(indio_dev);
 int ret;

 iio_device_unregister(indio_dev);
 iio_triggered_buffer_cleanup(indio_dev);
 if (data->drdy_trig)
  iio_trigger_unregister(data->drdy_trig);

 ret = i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
     CCS811_MODE_IDLE);
 if (ret)
  dev_warn(&client->dev, "Failed to power down device (%pe)\n",
    ERR_PTR(ret));
}

static const struct i2c_device_id ccs811_id[] = {
 { "ccs811" },
 { }
};
MODULE_DEVICE_TABLE(i2c, ccs811_id);

static const struct of_device_id ccs811_dt_ids[] = {
 { .compatible = "ams,ccs811" },
 { }
};
MODULE_DEVICE_TABLE(of, ccs811_dt_ids);

static struct i2c_driver ccs811_driver = {
 .driver = {
  .name = "ccs811",
  .of_match_table = ccs811_dt_ids,
 },
 .probe = ccs811_probe,
 .remove = ccs811_remove,
 .id_table = ccs811_id,
};
module_i2c_driver(ccs811_driver);

MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
MODULE_LICENSE("GPL v2");

Messung V0.5 in Prozent
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.42 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1127926
#Domains=2039723