Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 162489
b: refs/heads/master
c: c57f1ba
h: refs/heads/master
i:
  162487: f2ff262
v: v3
  • Loading branch information
Jonathan Cameron authored and Greg Kroah-Hartman committed Sep 15, 2009
1 parent 20b79f1 commit 272c42a
Show file tree
Hide file tree
Showing 8 changed files with 601 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 930bae8667c100d727360c0fa0df0378af9097ea
refs/heads/master: c57f1ba7326100fd90c35259a588a8484bf569b4
49 changes: 49 additions & 0 deletions trunk/drivers/staging/iio/Documentation/device.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
IIO Device drivers

This is not intended to provide a comprehensive guide to writing an
IIO device driver. For further information see the drivers within the
subsystem.

The crucial structure for device drivers in iio is iio_dev.

First allocate one using:

struct iio_dev *indio_dev = iio_allocate_device();

The fill in the following.

indio_dev->dev.parent
the struct device associated with the underlying hardware.

indio_dev->num_interrupt_lines
number of event triggering hardware lines the device has.

indio_dev->event_attrs
attributes used to enable / disable hardware events - note the
attributes are embedded in iio_event_attr structures with an
associated iio_event_handler which may or may note be shared.
If num_interrupt_lines = 0, then no need to fill this in.

indio_dev->attrs
general attributes such as polled access to device channels.

indio_dev->dev_data
private device specific data.

indio_dev->driver_module
typically set to THIS_MODULE. Used to specify ownership of some
iio created resources.

indio_dev->modes
whether direct access and / or ring buffer access is supported.

Once these are set up, a call to iio_device_register(indio_dev),
will register the device with the iio core.

Worth noting here is that, if a ring buffer is to be used, it can be
allocated prior to registering the device with the iio-core, but must
be registered afterwards (otherwise the whole parentage of devices
gets confused)

On remove iio_device_unregister(indio_dev) will remove the device from
the core, and iio_free_device will clean up.
159 changes: 159 additions & 0 deletions trunk/drivers/staging/iio/Documentation/iio_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/* IIO - useful set of util functionality
*
* Copyright (c) 2008 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/

#define IIO_EVENT_CODE_RING_50_FULL 200
#define IIO_EVENT_CODE_RING_75_FULL 201
#define IIO_EVENT_CODE_RING_100_FULL 202

struct iio_event_data {
int id;
__s64 timestamp;
};


inline char *find_ring_subelement(const char *directory, const char *subelement)
{
DIR *dp;
const struct dirent *ent;
int pos;
char temp[100];
char *returnstring;
dp = opendir(directory);
if (dp == NULL) {
printf("could not directory: %s\n", directory);
return NULL;
}
while (ent = readdir(dp), ent != NULL) {
if (strcmp(ent->d_name, ".") != 0 &&
strcmp(ent->d_name, "..") != 0) {
if (strncmp(ent->d_name, subelement, strlen(subelement)) == 0) {
int length = sprintf(temp, "%s%s%s", directory, ent->d_name, "/");
returnstring = malloc(length+1);
strncpy(returnstring, temp, length+1);
return returnstring;

}
}
}
return 0;
}


char *find_type_by_name(const char *name, const char *type)
{
const char *iio_dir = "/sys/class/iio/";
const struct dirent *ent;
int cnt, pos, pos2;

FILE *nameFile;
DIR *dp;
char thisname[100];
char temp[100];

char *returnstring = NULL;
struct stat Stat;
pos = sprintf(temp, "%s", iio_dir);
dp = opendir(iio_dir);
if (dp == NULL) {
printf("No industrialio devices available");
return NULL;
}
while (ent = readdir(dp), ent != NULL) {
cnt++;
/*reject . and .. */
if (strcmp(ent->d_name, ".") != 0 &&
strcmp(ent->d_name, "..") != 0) {
/*make sure it isn't a trigger!*/
if (strncmp(ent->d_name, type, strlen(type)) == 0) {
/* build full path to new file */
pos2 = pos + sprintf(temp + pos, "%s/", ent->d_name);
sprintf(temp + pos2, "name");
printf("search location %s\n", temp);
nameFile = fopen(temp, "r");
if (!nameFile) {
sprintf(temp + pos2, "modalias", ent->d_name);
nameFile = fopen(temp, "r");
if (!nameFile) {
printf("Failed to find a name for device\n");
return NULL;
}
}
fscanf(nameFile, "%s", thisname);
if (strcmp(name, thisname) == 0) {
returnstring = malloc(strlen(temp) + 1);
sprintf(temp + pos2, "");
strcpy(returnstring, temp);
return returnstring;
}
fclose(nameFile);

}
}
}
}

int write_sysfs_int(char *filename, char *basedir, int val)
{
int ret;
FILE *sysfsfp;
char temp[100];
sprintf(temp, "%s%s", basedir, filename);
sysfsfp = fopen(temp, "w");
if (sysfsfp == NULL)
return -1;
fprintf(sysfsfp, "%d", val);
fclose(sysfsfp);
return 0;
}

/**
* write_sysfs_string_and_verify() - string write, readback and verify
* @filename: name of file to write to
* @basedir: the sysfs directory in which the file is to be found
* @val: the string to write
**/
int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
{
int ret;
FILE *sysfsfp;
char temp[100];
sprintf(temp, "%s%s", basedir, filename);
sysfsfp = fopen(temp, "w");
if (sysfsfp == NULL)
return -1;
fprintf(sysfsfp, "%s", val);
fclose(sysfsfp);

sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL)
return -1;
fscanf(sysfsfp, "%s", temp);
if (strcmp(temp, val) != 0) {
printf("Possible failure in string write %s to %s%s \n",
val,
basedir,
filename);
return -1;
}
return 0;
}

int read_sysfs_posint(char *filename, char *basedir)
{
int ret;
FILE *sysfsfp;
char temp[100];
sprintf(temp, "%s%s", basedir, filename);
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL)
return -1;
fscanf(sysfsfp, "%d\n", &ret);
fclose(sysfsfp);
return ret;
}
171 changes: 171 additions & 0 deletions trunk/drivers/staging/iio/Documentation/lis3l02dqbuffersimple.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* Industrialio test ring buffer with a lis3l02dq acceleromter
*
* Copyright (c) 2008 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Assumes suitable udev rules are used to create the dev nodes as named here.
*/

#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>

#include <linux/types.h>
#include <dirent.h>
#include "iio_util.h"

static const char *ring_access = "/dev/iio/lis3l02dq_ring_access";
static const char *ring_event = "/dev/iio/lis3l02dq_ring_event";
static const char *device_name = "lis3l02dq";
static const char *trigger_name = "lis3l02dq-dev0";
static int NumVals = 3;
static int scan_ts = 1;
static int RingLength = 128;

/*
* Could get this from ring bps, but only after starting the ring
* which is a bit late for it to be useful
*/
int size_from_scanmode(int numVals, int timestamp)
{
if (numVals && timestamp)
return 16;
else if (timestamp)
return 8;
else
return numVals*2;
}

int main(int argc, char **argv)
{
int i, j, k, toread;
FILE *fp_ev;
int fp;
char *data;
size_t read_size;
struct iio_event_data dat;

char *BaseDirectoryName,
*TriggerDirectoryName,
*RingBufferDirectoryName;

BaseDirectoryName = find_type_by_name(device_name, "device");
if (BaseDirectoryName == NULL) {
printf("Failed to find the %s \n", device_name);
return -1;
}
TriggerDirectoryName = find_type_by_name(trigger_name, "trigger");
if (TriggerDirectoryName == NULL) {
printf("Failed to find the %s\n", trigger_name);
return -1;
}
RingBufferDirectoryName = find_ring_subelement(BaseDirectoryName,
"ring_buffer");
if (RingBufferDirectoryName == NULL) {
printf("Failed to find ring buffer\n");
return -1;
}

if (write_sysfs_string_and_verify("trigger/current_trigger",
BaseDirectoryName,
(char *)trigger_name) < 0) {
printf("Failed to write current_trigger file \n");
return -1;
}

/* Setup ring buffer parameters */
if (write_sysfs_int("length", RingBufferDirectoryName,
RingLength) < 0) {
printf("Failed to open the ring buffer length file \n");
return -1;
}

/* Enable the ring buffer */
if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 1) < 0) {
printf("Failed to open the ring buffer control file \n");
return -1;
};

data = malloc(size_from_scanmode(NumVals, scan_ts)*RingLength);
if (!data) {
printf("Could not allocate space for usespace data store\n");
return -1;
}

/* Attempt to open non blocking the access dev */
fp = open(ring_access, O_RDONLY | O_NONBLOCK);
if (fp == -1) { /*If it isn't there make the node */
printf("Failed to open %s\n", ring_access);
return -1;
}
/* Attempt to open the event access dev (blocking this time) */
fp_ev = fopen(ring_event, "rb");
if (fp_ev == NULL) {
printf("Failed to open %s\n", ring_event);
return -1;
}

/* Wait for events 10 times */
for (j = 0; j < 10; j++) {
read_size = fread(&dat, 1, sizeof(struct iio_event_data),
fp_ev);
switch (dat.id) {
case IIO_EVENT_CODE_RING_100_FULL:
toread = RingLength;
break;
case IIO_EVENT_CODE_RING_75_FULL:
toread = RingLength*3/4;
break;
case IIO_EVENT_CODE_RING_50_FULL:
toread = RingLength/2;
break;
default:
printf("Unexpecteded event code\n");
continue;
}
read_size = read(fp,
data,
toread*size_from_scanmode(NumVals, scan_ts));
if (read_size == -EAGAIN) {
printf("nothing available \n");
continue;
}

for (i = 0;
i < read_size/size_from_scanmode(NumVals, scan_ts);
i++) {
for (k = 0; k < NumVals; k++) {
__s16 val = *(__s16 *)(&data[i*size_from_scanmode(NumVals, scan_ts)
+ (k)*2]);
printf("%05d ", val);
}
printf(" %lld\n",
*(__s64 *)(&data[(i+1)*size_from_scanmode(NumVals, scan_ts)
- sizeof(__s64)]));
}
}

/* Stop the ring buffer */
if (write_sysfs_int("ring_enable", RingBufferDirectoryName, 0) < 0) {
printf("Failed to open the ring buffer control file \n");
return -1;
};

/* Disconnect from the trigger - writing something that doesn't exist.*/
write_sysfs_string_and_verify("trigger/current_trigger",
BaseDirectoryName, "NULL");
free(BaseDirectoryName);
free(TriggerDirectoryName);
free(RingBufferDirectoryName);
free(data);

return 0;
}
Loading

0 comments on commit 272c42a

Please sign in to comment.