Re: read /dev/iio:device0 return -1 (Invalid argument)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 13 December 2015 14:42:08 GMT+00:00, Julio Cruz <jcsistemas2001@xxxxxxxxx> wrote:
>Hi Jonathan,
>
>Below the content of all the files under scan_elements to check if
>something is odd (using iio_info). I cannot distribute all the source
>code, but I will re-make and share as below.
>
>Thanks again for any suggestion.
Sorry, not spotted anything. I think you are going to need to chase the error through
 the core elements.  There may well be a bug hiding there somewhere!

J
>
>---------------------
>Library version: 0.6 (git tag: 9d8aa76)
>IIO context created with local backend.
>Backend version: 0.6 (git tag: 9d8aa76)
>Backend description string: Linux Board Custom
>3.10.53-1.1.0_ga-boardcustom #94 SMP PREEMPT Sun Dec 13 16:17:57 CST
>2015 armv7l
>IIO context has 2 devices:
>        trigger0: customdevice-dev0
>                0 channels found:
>        iio:device0: customdevice
>                9 channels found:
>                        voltage0: 0 (input)
>                        3 channel-specific attributes found:
>                                attr 0: en value: 1
>                                attr 1: index value: 0
>                                attr 2: type value: be:u24/32>>0
>                        voltage1: 1 (input)
>                        3 channel-specific attributes found:
>                                attr 0: en value: 1
>                                attr 1: type value: be:u24/32>>0
>                                attr 2: index value: 1
>                        voltage2: 2 (input)
>                        3 channel-specific attributes found:
>                                attr 0: en value: 1
>                                attr 1: type value: be:u24/32>>0
>                                attr 2: index value: 2
>                        voltage3: 3 (input)
>                        3 channel-specific attributes found:
>                                attr 0: type value: be:u24/32>>0
>                                attr 1: index value: 3
>                                attr 2: en value: 1
>                        voltage4: 4 (input)
>                        3 channel-specific attributes found:
>                                attr 0: en value: 1
>                                attr 1: type value: be:u24/32>>0
>                                attr 2: index value: 4
>                        voltage5: 5 (input)
>                        3 channel-specific attributes found:
>                                attr 0: en value: 1
>                                attr 1: index value: 5
>                                attr 2: type value: be:u24/32>>0
>                        voltage6: 6 (input)
>                        3 channel-specific attributes found:
>                                attr 0: index value: 6
>                                attr 1: type value: be:u24/32>>0
>                                attr 2: en value: 1
>                        voltage7: 7 (input)
>                        3 channel-specific attributes found:
>                                attr 0: index value: 7
>                                attr 1: type value: be:u24/32>>0
>                                attr 2: en value: 1
>                        voltage8: 8 (input)
>                        3 channel-specific attributes found:
>                                attr 0: index value: 8
>                                attr 1: type value: be:u24/32>>0
>                                attr 2: en value: 1
>                1 device-specific attributes found:
>                                attr 0: config1 value: 133
>                Current trigger: trigger0(customde
>---------------------
>
>--------------------
>struct customdevice_state {
>       struct spi_device       *spi;
>
>       bool sampling;
>       bool irq_enabled;
>
>       uint8_t               *samples_data;
>
>       struct iio_trigger *trig;
>
>       struct mutex lock;
>
>
>       /*
>        * DMA (thus cache coherency maintenance) requires the
>        * transfer buffers to live in their own cache lines.
>        */
>  uint8_t rx_buf[customdevice_SPI_MAX_FRAMESIZE] ____cacheline_aligned;
>  uint8_t tx_buf[customdevice_SPI_MAX_FRAMESIZE] ____cacheline_aligned;
>};
>
>static int customdevice_send_command(struct iio_dev *indio_dev,
>unsigned char command)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>       int ret;
>
>       if (iio_buffer_enabled(indio_dev))
>              return -EBUSY;
>
>       mutex_lock(&st->lock);
>       st->tx_buf[0] = command;
>       ret = spi_write(st->spi, &st->tx_buf, 1);
>       mutex_unlock(&st->lock);
>
>       return ret;
>};
>
>static int customdevice_read_register(struct iio_dev *indio_dev,
>unsigned char address,
>       unsigned char *value)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>       struct spi_transfer xfer;
>       struct spi_message msg;
>       int ret;
>
>       if (iio_buffer_enabled(indio_dev))
>              return -EBUSY;
>
>       memset(&xfer, 0, sizeof(xfer));
>       xfer.tx_buf = &st->tx_buf;
>       xfer.rx_buf = &st->rx_buf;
>       xfer.len = 3;
>       xfer.delay_usecs = 2;
>       xfer.cs_change = 0;
>       xfer.bits_per_word = 8;
>
>       spi_message_init(&msg);
>       spi_message_add_tail(&xfer, &msg);
>
>       mutex_lock(&st->lock);
>       st->tx_buf[0] = customdevice_CMD_RREG | address;
>       st->tx_buf[1] = 0;
>       st->tx_buf[2] = 0;
>       ret = spi_sync(st->spi, &msg);
>       if (ret)
>              goto out;
>       *value = st->rx_buf[2];
>out:
>       mutex_unlock(&st->lock);
>
>       return ret;
>};
>
>static int customdevice_write_register(struct iio_dev *indio_dev,
>unsigned char address,
>       unsigned char value)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>       struct spi_transfer xfer;
>       struct spi_message msg;
>       int ret;
>
>       if (iio_buffer_enabled(indio_dev))
>              return -EBUSY;
>
>       memset(&xfer, 0, sizeof(xfer));
>       xfer.tx_buf = &st->tx_buf;
>       xfer.rx_buf = &st->rx_buf;
>       xfer.len = 3;
>       xfer.delay_usecs = 2;
>       xfer.cs_change = 0;
>       xfer.bits_per_word = 8;
>
>       spi_message_init(&msg);
>       spi_message_add_tail(&xfer, &msg);
>
>       mutex_lock(&st->lock);
>       st->tx_buf[0] = customdevice_CMD_WREG | address;
>       st->tx_buf[1] = 0;
>       st->tx_buf[2] = value;
>       ret = spi_sync(st->spi, &msg);
>       if (ret)
>              goto out;
>out:
>       mutex_unlock(&st->lock);
>
>       return ret;
>};
>
>struct gpio customdevice_gpio_reset = { .label = "reset-gpio", .flags
>= GPIOF_OUT_INIT_HIGH };
>struct gpio customdevice_gpio_acquire = { .label = "acquire-gpio",
>.flags =GPIOF_OUT_INIT_LOW };
>
>static void customdevice_reset_by_gpio(void)
>{
>       gpio_set_value_cansleep(customdevice_gpio_reset.gpio, 0);
>       udelay(5);
>       gpio_set_value_cansleep(customdevice_gpio_reset.gpio, 1);
>       udelay(20);
>       printk(KERN_ALERT "DEBUG: Passed %s %d GPIO setting
>%s\n",__FUNCTION__,__LINE__, customdevice_gpio_reset.label);
>}
>
>static void customdevice_acquire_by_gpio(bool enable)
>{
>       gpio_set_value_cansleep(customdevice_gpio_acquire.gpio, enable);
>       printk(KERN_ALERT "DEBUG: Passed %s %d GPIO setting
>%s\n",__FUNCTION__,__LINE__, customdevice_gpio_acquire.label);
>}
>
>static int customdevice_init_io_from_dt(struct device *dev, struct gpio
>*pgpio)
>{
>       struct device_node *np = dev->of_node;
>
>       int ret;
>
>       pgpio->gpio = of_get_named_gpio(np, pgpio->label, 0);
>
>       if (!gpio_is_valid(pgpio->gpio)) {
>              return -EINVAL;
>       } else {
>              ret = devm_gpio_request_one(dev, pgpio->gpio,
>pgpio->flags, pgpio->label);
>              if (ret < 0) {
>                     return ret;
>              }
>       }
>
>       return 0;
>};
>
>static int customdevice_init_gpio_pins(struct iio_dev *indio_dev)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>       struct device *dev = &st->spi->dev;
>       int ret;
>
>     ret = customdevice_init_io_from_dt(dev, &customdevice_gpio_reset);
>       printk(KERN_ALERT "DEBUG: Passed %s %d init GPIO RESET return
>%d \n",__FUNCTION__,__LINE__, ret);
>
>   ret = customdevice_init_io_from_dt(dev, &customdevice_gpio_acquire);
>       printk(KERN_ALERT "DEBUG: Passed %s %d init GPIO START return
>%d \n",__FUNCTION__,__LINE__, ret);
>       if (ret < 0)
>              goto out;
>
>       gpio_set_value_cansleep(customdevice_gpio_acquire.gpio, 0);
>       printk(KERN_ALERT "DEBUG: Passed %s %d GPIO setting
>%s\n",__FUNCTION__,__LINE__, customdevice_gpio_acquire.label);
>       gpio_set_value_cansleep(customdevice_gpio_reset.gpio, 1);
>       printk(KERN_ALERT "DEBUG: Passed %s %d GPIO setting
>%s\n",__FUNCTION__,__LINE__, customdevice_gpio_reset.label);
>
>       return 0;
>
>out:
>       return ret;
>};
>#ifdef CONFIG_DEBUG_FS
>static void customdevice_debugfs_init(struct iio_dev *indio_dev)
>{
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>}
>
>static int customdevice_debugfs_reg_access(struct iio_dev *indio_dev,
>                              unsigned reg, unsigned writeval,
>                              unsigned *readval)
>{
>       unsigned char readdata;
>       int ret;
>
>       if (readval == NULL) {
>              printk(KERN_ALERT "DEBUG: Passed %s %d WRITE reg = %x
>val = %x\n",__FUNCTION__,__LINE__, (unsigned char)reg, (unsigned
>char)writeval);
>              return customdevice_write_register(indio_dev, (unsigned
>char)reg, (unsigned char)writeval);
>       }
>
>       ret = customdevice_read_register(indio_dev, (unsigned char)reg,
>&readdata);
>       if (ret)
>              return ret;
>       *readval = (unsigned)readdata;
>       printk(KERN_ALERT "DEBUG: Passed %s %d READ reg = %x val =
>%x\n",__FUNCTION__,__LINE__, (unsigned char)reg, (unsigned
>char)writeval);
>       return 0;
>}
>
>#else
>
>static inline void customdevice_debugfs_init(struct iio_dev *indio_dev)
>{};
>#define customdevice_debugfs_reg_access NULL
>
>#endif
>
>static int customdevice_startup(struct iio_dev *indio_dev, unsigned
>long mask)
>{
>       unsigned char reg;
>       int ret;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>
>       // enable conversions
>       customdevice_acquire_by_gpio(true);
>
>       return 0;
>}
>
>static int customdevice_shutdown(struct iio_dev *indio_dev)
>{
>       int ret;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>
>       // stop conversions
>       customdevice_acquire_by_gpio(false);
>
>       return 0;
>}
>
>static int customdevice_preenable(struct iio_dev *indio_dev)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>       int ret;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       ret = iio_sw_buffer_preenable(indio_dev);
>       if (ret)
>              return ret;
>
>   ret = customdevice_startup(indio_dev, *indio_dev->active_scan_mask);
>       if (ret)
>              return ret;
>
>       st->sampling = true;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       return ret;
>}
>
>static int customdevice_postenable(struct iio_dev *indio_dev)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       iio_triggered_buffer_postenable(indio_dev);
>
>       if (st->spi->irq) {
>              st->irq_enabled = true;
>              enable_irq(st->spi->irq);
>       }
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       return 0;
>}
>
>static int customdevice_postdisable(struct iio_dev *indio_dev)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       st->sampling = false;
>
>       return customdevice_shutdown(indio_dev);
>}
>
>static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops
>= {
>       .preenable = &customdevice_preenable,
>       .postenable = &customdevice_postenable,
>       .predisable = &iio_triggered_buffer_predisable,
>       .postdisable = &customdevice_postdisable,
>};
>
>unsigned long int test = 0;
>static irqreturn_t customdevice_trigger_handler(int irq, void *p)
>{
>       struct iio_poll_func *pf = p;
>       struct iio_dev *indio_dev = pf->indio_dev;
>       struct customdevice_state *st = iio_priv(indio_dev);
>       struct spi_transfer xfer;
>       struct spi_message msg;
>       int ret;
>
>       memset(&xfer, 0, sizeof(xfer));
>       xfer.tx_buf = &st->tx_buf;
>       xfer.rx_buf = &st->rx_buf;
>xfer.len = indio_dev->num_channels*3; /*assuming all channels enabled*/
>       xfer.delay_usecs = 2;
>       xfer.cs_change = 0;
>       xfer.bits_per_word = 8;
>
>       spi_message_init(&msg);
>       spi_message_add_tail(&xfer, &msg);
>       ret = spi_sync(st->spi, &msg);
>       if (ret)
>              goto err;
>
>       /* Unpacking data */
>
>       test++;
>       st->samples_data[0] = (unsigned char)(test & 0xFF);
>       st->samples_data[1] = (unsigned char)(test >> 8 & 0xFF);
>       st->samples_data[2] = (unsigned char)(test >> 16 & 0xFF);
>       st->samples_data[3] = (unsigned char)(test >> 24 & 0xFF);
>
>       iio_push_to_buffers(indio_dev, st->samples_data);
>
>err:
>       iio_trigger_notify_done(indio_dev->trig);
>       enable_irq(st->spi->irq);
>
>       return IRQ_HANDLED;
>}
>
>static int customdevice_update_scan_mode(struct iio_dev *indio_dev,
>       const unsigned long *scan_mask)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>
>       /* We have to make sure to output all zeros on the SDO line */
>       memset(st->tx_buf, 0x00, customdevice_SPI_MAX_FRAMESIZE);
>
>       st->samples_data = krealloc(st->samples_data,
>indio_dev->scan_bytes, GFP_KERNEL);
>       if (!st->samples_data)
>              return -ENOMEM;
>
>       return 0;
>}
>
>// data leads channels
>enum customdevice_channel_leads {
>       CUSTOMDEVICE_1,
>       CUSTOMDEVICE_2,
>       CUSTOMDEVICE_3,
>       CUSTOMDEVICE_4,
>       CUSTOMDEVICE_5,
>       CUSTOMDEVICE_6,
>       CUSTOMDEVICE_7,
>       CUSTOMDEVICE_8,
>       CUSTOMDEVICE_9,
>};
>
>#define customdevice_ADC_CHAN(_chan1, _scan_index, _extend_name) {     
> \
>       .type = IIO_VOLTAGE,                            \
>       .indexed = 1,                                   \
>       .differential = 1,                            \
>       .channel = (_chan1),                            \
>       .scan_index = (_scan_index),                     \
>       .scan_type = {                                   \
>              .sign = 'u',                            \
>              .realbits = 24,                            \
>              .storagebits = 32,                     \
>              .shift = 0,                            \
>              .endianness = IIO_BE,                     \
>       },                                          \
>       .extend_name = (_extend_name),                     \
>}
>
>static const struct iio_chan_spec customdevice_channels[] = {
>       customdevice_ADC_CHAN(CUSTOMDEVICE_1, 0, "1"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_2, 1, "2"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_3, 2, "3"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_4, 3, "4"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_5, 4, "5"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_6, 5, "6"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_7, 6, "7"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_8, 7, "8"),
>       customdevice_ADC_CHAN(CUSTOMDEVICE_9, 8, "9"),
>};
>
>static const struct iio_trigger_ops customdevice_trigger_ops = {
>       .owner = THIS_MODULE,
>};
>
>static irqreturn_t customdevice_trigger_irq(int irq, void *data)
>{
>       struct customdevice_state *st = data;
>       struct iio_trigger *trig = st->trig;
>
>       if (!st->sampling) {
>              disable_irq_nosync(irq);
>              st->irq_enabled = false;
>              return IRQ_HANDLED;
>       }
>
>       iio_trigger_poll(trig, iio_get_time_ns());
>       disable_irq_nosync(irq);
>
>       return IRQ_HANDLED;
>}
>
>static struct iio_trigger *customdevice_allocate_trigger(struct
>iio_dev *indio_dev,
>       int irq)
>{
>       struct customdevice_state *st = iio_priv(indio_dev);
>       struct iio_trigger *trig;
>       int ret;
>
>  trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
>       if (!trig)
>              return NULL;
>
>       trig->dev.parent = indio_dev->dev.parent;
>       trig->ops = &customdevice_trigger_ops;
>
>     ret = request_irq(irq, customdevice_trigger_irq, IRQF_TRIGGER_LOW,
>                     trig->name, st);
>       if (ret)
>              return NULL;
>
>       indio_dev->trig = trig;
>       iio_trigger_get(indio_dev->trig);
>
>       ret = iio_trigger_register(trig);
>       if (ret) {
>              free_irq(irq, trig);
>              return NULL;
>       }
>
>       return trig;
>}
>
>
>
>static const struct iio_info customdevice_info = {
>       .update_scan_mode = customdevice_update_scan_mode,
>       .debugfs_reg_access = customdevice_debugfs_reg_access,
>       .driver_module = THIS_MODULE,
>};
>
>static int customdevice_inital_setup(struct iio_dev *indio_dev,
>       struct customdevice_platform_data *pdata)
>{
>       int ret;
>       unsigned char id;
>
>       ret = customdevice_init_gpio_pins(indio_dev);
>       if (ret)
>              return ret;
>
>       // reset device
>       customdevice_reset_by_gpio();
>       customdevice_acquire_by_gpio(false);
>
>       return ret;
>}
>
>static int customdevice_probe(struct spi_device *spi)
>{
>     struct customdevice_platform_data *pdata = spi->dev.platform_data;
>       struct iio_dev *indio_dev;
>       struct customdevice_state *st;
>       int ret;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>
>       indio_dev = iio_device_alloc(sizeof(*st));
>       if (indio_dev == NULL)
>              return -ENOMEM;
>
>       st = iio_priv(indio_dev);
>
>       mutex_init(&st->lock);
>       spi_set_drvdata(spi, indio_dev);
>       st->spi = spi;
>
>       indio_dev->dev.parent = &spi->dev;
>       indio_dev->name = spi_get_device_id(spi)->name;
>       indio_dev->modes = INDIO_DIRECT_MODE;
>       indio_dev->info = &customdevice_info;
>       indio_dev->channels = customdevice_channels;
>       indio_dev->num_channels = ARRAY_SIZE(customdevice_channels);
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       ret = customdevice_inital_setup(indio_dev, pdata);
>       if (ret)
>              goto error_free;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>  ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
>       &customdevice_trigger_handler, &iio_triggered_buffer_setup_ops);
>       if (ret)
>              goto error_free;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       st->irq_enabled = true;
>       if (spi->irq)
>         st->trig = customdevice_allocate_trigger(indio_dev, spi->irq);
>
>       ret = iio_device_register(indio_dev);
>       if (ret)
>              goto error_buffer_cleanup;
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       customdevice_debugfs_init(indio_dev);
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       return 0;
>
>error_buffer_cleanup:
>       iio_triggered_buffer_cleanup(indio_dev);
>error_free:
>       iio_device_free(indio_dev);
>
>     printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__);
>       return ret;
>}
>
>static int customdevice_remove(struct spi_device *spi)
>{
>       struct iio_dev *indio_dev = spi_get_drvdata(spi);
>       struct customdevice_state *st = iio_priv(indio_dev);
>
>       iio_device_unregister(indio_dev);
>       iio_triggered_buffer_cleanup(indio_dev);
>       kfree(st->samples_data);
>       mutex_destroy(&st->lock);
>       iio_device_free(indio_dev);
>
>       return 0;
>}
>
>static const struct of_device_id customdevice_dt_ids[] = {
>       { .compatible = "customdevice" },
>       { }
>};
>MODULE_DEVICE_TABLE(of, customdevice_dt_ids);
>
>static const struct spi_device_id customdevice_ids[] = {
>       {"customdevice", 0},
>       { }
>};
>MODULE_DEVICE_TABLE(spi, customdevice_ids);
>
>static struct spi_driver customdevice_driver = {
>       .driver = {
>              .name       = "customdevice",
>              .owner       = THIS_MODULE,
>              .of_match_table = of_match_ptr(customdevice_dt_ids),
>       },
>       .probe              = customdevice_probe,
>       .remove              = customdevice_remove,
>       .id_table       = customdevice_ids,
>};
>module_spi_driver(customdevice_driver);
>--------------------
>
>On Sun, Dec 13, 2015 at 8:14 PM, Jonathan Cameron
><jic23@xxxxxxxxxxxxxxxxxxxxx> wrote:
>>
>>
>> On 13 December 2015 10:44:29 GMT+00:00, Julio Cruz
><jcsistemas2001@xxxxxxxxx> wrote:
>>>Hi Jonathan,
>>>
>>>Right now, the app is able to read the data from /dev/iio:device0
>with
>>>success (not data loss). Currently, the app read 1 sample (with 9
>>>channels of 4 bytes each one) every time (using "read" function).
>>>
>>>I still have some doubts about my implementation, because, sometimes
>>>there is data lost.
>>>
>>>For example, when the app try to read more than 1 sample (for
>example,
>>>2 samples: 72 bytes, using "read"), the results are strange. For
>>>instance, when the app is using libiio, the function
>iio_buffer_refill
>>>return -1 and is not able to receive data.
>> That is definitely odd.
>> Perhaps you could post the content of all the files under
>scan_elements so we can
>>  check nothing odd has happened with the channel definitions.
>>
>>
>>  In this case, the buffer
>>>(at iio_device_create_buffer) need to be setup with 1 sample to work.
>>>
>>>Below some assumptions/questions:
>>>
>>>- The buffer/length define the kfifo length (in samples, not in
>>>bytes)?
>> Number and of scans where a scan is one sample from all enabled
>channels.
>>
>>> In this case, the buffer must be multiple of 36 bytes right?
>> The one you are reading into should be.
>>>- At user space, the application can read 36 bytes or more (i.e. 72,
>>>...) (/dev/iio:device0) (but not less)? According with the buffer
>>>length.
>> Yes.
>>
>> So I have no idea what is going on. Can only suggest you add printks
>to find out
>>  what exactly is causing that error return
>>
>> Any chance you could post the driver?
>>>
>>>Thanks
>>>
>>>
>>>On Sat, Dec 12, 2015 at 8:41 PM, Julio Cruz
><jcsistemas2001@xxxxxxxxx>
>>>wrote:
>>>> OK, I understood! Thanks
>>>>
>>>> I will use 32 bits for storage in all the channels
>>>>
>>>> On Sat, Dec 12, 2015 at 8:35 PM, Jonathan Cameron
>>>> <jic23@xxxxxxxxxxxxxxxxxxxxx> wrote:
>>>>> On 12/12/15 12:24, Julio Cruz wrote:
>>>>>> HI Jonathan,
>>>>> Hi Julio
>>>>>
>>>>> I've kept the list cc'd as this sort of conversation acts as
>>>>> 'free' documentation solving other people's problems in future.
>>>>>
>>>>>>
>>>>>> Thanks for your quick reply.
>>>>>>
>>>>>> When you mention the alignment, I remember some things that I did
>>>>>> about it, as below.
>>>>>>
>>>>>> When I started testing the _trigger_handler, I found that the
>>>driver
>>>>>> calculate indio_dev->scan_bytes. This value is not clear to me
>>>>>> because, for example, 1 channel is 3 bytes,
>>>>> It shouldn't be. Padding is to the nearest power of 2 bytes so
>>>should
>>>>> be 4.  The non power of two realbits may have resulted in an
>>>unexpected
>>>>> path in which case we should add a sanity check to catch this.
>>>>>> and for 2 channels is 8
>>>>>> bytes (1 byte padding). The channel spec are realbits = 24 and
>>>>>> storagebits = 24.
>>>>> Storage bits should be a power of 2.  So in this case 32 bytes.
>>>>> Might seem wasteful but processors handle aligned data a lot
>>>>> more easily so to keep rates up it is usually better to burn a
>small
>>>>> amount of memory and keep everything aligned.
>>>>>
>>>>>  At that point, I fixed the frame buffer size to 27
>>>>>> (used at iio_push_to_buffers) assuming that the same buffer could
>>>be
>>>>>> read at user space.
>>>>>>
>>>>>> Please, may I know if this approach is correct?
>>>>> Sorry nope, the buffer structure assumes power of 2 alignment
>>>everywhere.
>>>>>>
>>>>>> The SPI device send 9 channels, 3 bytes each one (for a total of
>27
>>>>>> bytes) and each channels is 24 bits width.
>>>>> Unfortunately you'll have to do unpacking of this before pushing
>to
>>>the buffer.
>>>>> It'll have to happen somewhere anyway (as userspace code would
>need
>>>to unpack
>>>>> it otherwise).
>>>>>
>>>>> It's actually relatively unusual to find a device that does this
>>>sort of
>>>>> packing.  We have talked in the past about allowing this sort of
>>>packing and
>>>>> modifying the buffer infrastructure to accept it, but I'm
>>>unconvinced that
>>>>> it is worth the added complexity + cost in userspace complexity.
>>>>>
>>>>> Jonathan
>>>>>>
>>>>>> Thanks
>>>>>>
>>>>>> Julio
>>>>>>
>>>>>>
>>>>>> On Sat, Dec 12, 2015 at 7:51 PM, Jonathan Cameron
>>><jic23@xxxxxxxxxx> wrote:
>>>>>>> On 12/12/15 08:36, Julio Cruz wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I get an error trying to read /dev/iio:device0 in a custom
>>>application
>>>>>>>> (C/C++), however in a terminal the command "cat
>/dev/iio_device0"
>>>>>>>> return data.
>>>>>>>>
>>>>>>>> Below the procedure:
>>>>>>>>
>>>>>>>> - enable channels
>>>>>>>> - setup trigger
>>>>>>>> - setup buffer lenght
>>>>>>>> - enable buffer (the SPI interrupt is setup properly and all
>the
>>>>>>>> trigger handler are done)
>>>>>>>> - read /dev/iio_device0
>>>>>>>>
>>>>>>>> It's a SPI device acquiring 27 bytes @ 1KHz.
>>>>>>> Reading this again after point 4 below this makes me ask the
>>>question
>>>>>>> what are you pushing into the buffer? 27 bytes seems unlikely
>>>given
>>>>>>> the alignment requirements.
>>>>>>>
>>>>>>>>
>>>>>>>> Results:
>>>>>>>>
>>>>>>>> 1. Custom application (based on generic_buffer.c): function
>>>'read'
>>>>>>>> return -1 and strerror(errno) return "Invalid argument"
>>>>>>>> 2. iio_readdev (libiio): show the message "Unable to refill
>>>buffer:
>>>>>>>> Input/output error"
>>>>>>>> 3. In terminal, the command "cat /dev/iio_device0" show values
>>>(no
>>>>>>>> readable) while the buffer is enable.
>>>>>>>>
>>>>>>>> Any suggestion?
>>>>>>>>
>>>>>>>> Thanks for your help!
>>>>>>> Sounds like you are ultimately getting that error from a call to
>>>>>>>  iio_buffer_read_first_n_outer
>>>>>>> so what can return -EINVAL (which is -1)?
>>>>>>>
>>>>>>> 1) Buffer not being allocated (seems unlikely - that's really
>just
>>>to
>>>>>>> pick up on bugs in side the driver)
>>>>>>> 2) read_first_n from the buffer not supplied - again not likely.
>>>>>>> 3) wait_event_interruptible returns it - unlikely.
>>>>>>> 4) read_first_n which comes from the buffer implementation is
>>>returning -EINVAL
>>>>>>> This last one seems most likely.
>>>>>>>
>>>>>>> So I am guessing you are using the kfifo buffer (most common
>>>option).
>>>>>>> Reasons this can return -EINVAL are
>>>>>>> 1) kfifo not initialized (unlikely)
>>>>>>> 2) Read length is less than the buffer element size (which is
>the
>>>full scan storage
>>>>>>> size)
>>>>>>> 3) an error from kfifo_to_user (unlikely)
>>>>>>>
>>>>>>> So I'm guessing you are reading too small an amount of data.
>>>(tricky to chase
>>>>>>> down without adding further printk's etc to the relevant bits of
>>>kernel code)
>>>>>>> If I've 'guessed' right, interesting question is how this came
>>>about.
>>>>>>> How many bytes is it trying to read?
>>>>>>>
>>>>>>> Note that IIO has strict alignment requirements - any element
>must
>>>be aligned
>>>>>>> to it's own size and this will in some case add lots of padding.
>>>The full buffer
>>>>>>> element will be a multiple of the largest element in the scan. 
>If
>>>you have a timestamp
>>>>>>> for example at 64bits the whole buffer element will be a
>multiple
>>>of 8bytes.
>>>>>>>
>>>>>>> Jonathan
>>>>>>>> --
>>>>>>>> To unsubscribe from this list: send the line "unsubscribe
>>>linux-iio" in
>>>>>>>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>>>>>>>> More majordomo info at
>>>http://vger.kernel.org/majordomo-info.html
>>>>>>>>
>>>>>>>
>>>>>
>>
>> --
>> Sent from my Android device with K-9 Mail. Please excuse my brevity.

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux