Patrick H. E. Foubet 10 роки тому
джерело
коміт
3d29217ef3
5 змінених файлів з 890 додано та 0 видалено
  1. +30
    -0
      src/ex/testi2c.nif
  2. +374
    -0
      src/i2c.c
  3. +26
    -0
      src/i2c.h
  4. +416
    -0
      src/i2cbusses.c
  5. +44
    -0
      src/i2cbusses.h

+ 30
- 0
src/ex/testi2c.nif Переглянути файл

@@ -0,0 +1,30 @@

: test1
200 0 do
" i vaut : " "type I .
I 0x12 1 i2c_read
" et on lit : " "type . cr
1 sleep
loop
;

: test2
200 0 do
" i vaut : " "type I .
I I 0x12 1 i2c_write
" on ecrit cette valeur a cette adresse " "type
I 0x12 1 i2c_read
" et on lit : " "type . cr
1 sleep
loop
;

# fonction qui envoie une valeur a l'Arduino et qui recupere le resultat du calcul
# on suppose ici que le I2C-ID est egal a 1 car Model B
: arduino # [ val chip-address - resultat ]
dup unrot dup 1 i2c_write
1 sleep # a voir si c'est bien necessaire
-1 swap 1 i2c_read
;


+ 374
- 0
src/i2c.c Переглянути файл

@@ -0,0 +1,374 @@
/* Copyright (C) 2011-2014 Patrick H. E. Foubet - S.E.R.I.A.N.E.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*******************************************************************/
/* i2c.c */

#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif

#ifdef HAVE_LINUX_I2C_DEV_H
#include <linux/i2c-dev.h>
#ifdef I2C_FUNC_I2C
#define _WITH_I2C
#endif
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _WITH_I2C
/*
This part is a merge of Linux i2c-tools code and Nife code.
i2c-tools are user-space programs to detect, scan I2C devices,
and read and/or write an I2C register.
Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de>

Copyright (C) 2001-2003 Frodo Looijaard <frodol@dds.nl>, and
Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004-2005 Jean Delvare

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "i2cbusses.c" /* add code for I2C on Linux */

#define MODE_AUTO 0
#define MODE_QUICK 1
#define MODE_READ 2
#define MODE_FUNC 3

/*
* Print the installed i2c busses. The format is those of Linux 2.4's
* /proc/bus/i2c for historical compatibility reasons.
*/
static void print_i2c_busses(void)
{
struct i2c_adap *adapters;
int count;

adapters = gather_i2c_busses();
if (adapters == NULL) {
fprintf(stderr, "Error: Out of memory!\n");
return;
}
printf("i2c-id\tfunction \tadapter name\t\t\t\talgorithm\n");
for (count = 0; adapters[count].name; count++) {
printf("%d\t%-10s\t%-32s\t%s\n",
adapters[count].nr, adapters[count].funcs,
adapters[count].name, adapters[count].algo);
}
free_adapters(adapters);
}

static int scan_i2c_bus(int file, int mode, int first, int last)
{
int i, j;
int res;
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
for (i = 0; i < 128; i += 16) {
printf("%02x: ", i);
for(j = 0; j < 16; j++) {
fflush(stdout);

/* Skip unwanted addresses */
if (i+j < first || i+j > last) {
printf(" ");
continue;
}

/* Set slave address */
if (ioctl(file, I2C_SLAVE, i+j) < 0) {
if (errno == EBUSY) {
printf("UU ");
continue;
} else {
fprintf(stderr, "Error: Could not set "
"address to 0x%02x: %s\n", i+j,
strerror(errno));
return -1;
}
}

/* Probe this address */
switch (mode) {
case MODE_QUICK:
/* This is known to corrupt the Atmel AT24RF08
EEPROM */
res = i2c_smbus_write_quick(file,
I2C_SMBUS_WRITE);
break;
case MODE_READ:
/* This is known to lock SMBus on various
write-only chips (mainly clock chips) */
res = i2c_smbus_read_byte(file);
break;
default:
if ((i+j >= 0x30 && i+j <= 0x37)
|| (i+j >= 0x50 && i+j <= 0x5F))
res = i2c_smbus_read_byte(file);
else
res = i2c_smbus_write_quick(file,
I2C_SMBUS_WRITE);
}
if (res < 0)
printf("-- ");
else
printf("%02x ", i+j);
}
printf("\n");
}
return 0;
}

static int check_write_funcs(int file, int size, int pec)
{
unsigned long funcs;
/* check adapter functionality */
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
fprintf(stderr, "Error: Could not get the adapter "
"functionality matrix: %s\n", strerror(errno));
return -1;
}
switch (size) {
case I2C_SMBUS_BYTE:
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
return -1;
}
break;
case I2C_SMBUS_BYTE_DATA:
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus write byte");
return -1;
}
break;
case I2C_SMBUS_WORD_DATA:
if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus write word");
return -1;
}
break;
case I2C_SMBUS_BLOCK_DATA:
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus block write");
return -1;
}
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
fprintf(stderr, MISSING_FUNC_FMT, "I2C block write");
return -1;
}
break;
}
if (pec && !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C))) {
fprintf(stderr, "Warning: Adapter does "
"not seem to support PEC\n");
}
return 0;
}

static int check_read_funcs(int file, int size, int daddress, int pec)
{
unsigned long funcs;
/* check adapter functionality */
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
fprintf(stderr, "Error: Could not get the adapter "
"functionality matrix: %s\n", strerror(errno));
return -1;
}
switch (size) {
case I2C_SMBUS_BYTE:
if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus receive byte");
return -1;
}
if (daddress >= 0
&& !(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
return -1;
}
break;
case I2C_SMBUS_BYTE_DATA:
if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus read byte");
return -1;
}
break;
case I2C_SMBUS_WORD_DATA:
if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)) {
fprintf(stderr, MISSING_FUNC_FMT, "SMBus read word");
return -1;
}
break;
}
if (pec
&& !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C))) {
fprintf(stderr, "Warning: Adapter does "
"not seem to support PEC\n");
}
return 0;
}

#endif /* for _WITH_I2C */
/* *********************************************************************/

#include "stackN.h"
#include "i2c.h"
#include "err.h"

void IF_listI2C (void)
{
#ifdef _WITH_I2C
print_i2c_busses();
#else
messErr(49);
#endif
}

void IF_showI2C (void)
{
long n;
if (!getParLong(&n)) return;

#ifdef _WITH_I2C
int i2cbus, file;
int mode=MODE_AUTO;
int first = 0x03, last = 0x77;
unsigned long funcs;
char Bus[10], filename[20];
sprintf(Bus, "%ld",n);
i2cbus = lookup_i2c_bus(Bus);
if (i2cbus < 0) messErr(50);
else {
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
if (file < 0) messErr(51);
else {
if (ioctl(file, I2C_FUNCS, &funcs) < 0) messErr(52);
else scan_i2c_bus(file, mode, first, last);
close(file);
}
}
#else
messErr(49);
#endif
}

static void i2c_read(int id, int add, int off)
{
#ifdef _WITH_I2C
int i2cbus, file, address, res;
int size = I2C_SMBUS_BYTE_DATA;
int pec = 0,force = 0;
char Buf[10], filename[20];
sprintf(Buf, "%ld",id);
i2cbus = lookup_i2c_bus(Buf);
if (i2cbus < 0) messErr(50);
else {
sprintf(Buf, "%ld",add);
address = parse_i2c_address(Buf);
if (address < 0) messErr(53);
else {
if (off == -1) size = I2C_SMBUS_BYTE;
if (off < -1 || off > 0xff) messErr(54);
else {
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
if (file < 0
|| check_read_funcs(file, size, off, pec)
|| set_slave_addr(file, address, force)) messErr(51);
else {
if (size == I2C_SMBUS_BYTE)
res = i2c_smbus_read_byte(file);
else
res = i2c_smbus_read_byte_data(file, off);
close(file);
if (res < 0) messErr(57);
else putLong((long long)res);
}
}
}
}
#else
messErr(49);
#endif
}

void IF_I2CRead (void)
{
long id, add, off;
if (!getParLong(&id)) return; /* I2C ID */
if (!getParLong(&add)) return; /* CHIP ADDRESS */
if (!getParLong(&off)) return; /* DATA ADDRESS (OFFSET) */
i2c_read(id, add, off);
}

static void i2c_write(int id, int add, int off, int val)
{
#ifdef _WITH_I2C
int i2cbus, file, address, res;
int size = I2C_SMBUS_BYTE_DATA;
int pec = 0,force = 0;
char Buf[10], filename[20];
sprintf(Buf, "%ld",id);
i2cbus = lookup_i2c_bus(Buf);
if (i2cbus < 0) messErr(50);
else {
sprintf(Buf, "%ld",add);
address = parse_i2c_address(Buf);
if (address < 0) messErr(53);
else {
if (off < 0 || off > 0xff) messErr(54);
else {
if (val > 0xff) messErr(55);
else {
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
if (file < 0
|| check_write_funcs(file, size, pec)
|| set_slave_addr(file, address, force)) messErr(51);
else {
res = i2c_smbus_write_byte_data(file, off, val);
close(file);
if (res < 0) messErr(56);
}
}
}
}
}
#else
messErr(49);
#endif
}

void IF_I2CWrite (void)
{
long id, add, off, val;
if (!getParLong(&id)) return; /* I2C ID */
if (!getParLong(&add)) return; /* CHIP ADDRESS */
if (!getParLong(&off)) return; /* DATA ADDRESS (OFFSET) */
if (!getParLong(&val)) return; /* DATA BYTE */
i2c_write(id, add, off, val);
return;
}



+ 26
- 0
src/i2c.h Переглянути файл

@@ -0,0 +1,26 @@
/* Copyright (C) 2011-2014 Patrick H. E. Foubet - S.E.R.I.A.N.E.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*******************************************************************/
/* i2c.h */

#ifndef __NIFE_I2C_H__
#define __NIFE_I2C_H__

extern void IF_listI2C (void);
extern void IF_showI2C (void);
extern void IF_I2CRead (void);
extern void IF_I2CWrite (void);

#endif

+ 416
- 0
src/i2cbusses.c Переглянути файл

@@ -0,0 +1,416 @@
/*
i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
Part of user-space programs to access for I2C
devices.
Copyright (c) 1999-2003 Frodo Looijaard <frodol@dds.nl> and
Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2008-2012 Jean Delvare <jdelvare@suse.de>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA.
*/

/* For strdup and snprintf */
#define _BSD_SOURCE 1

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h> /* for NAME_MAX */
#include <sys/ioctl.h>
#include <string.h>
#include <strings.h> /* for strcasecmp() */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include "i2cbusses.h"
#include <linux/i2c-dev.h>

enum adt { adt_dummy, adt_isa, adt_i2c, adt_smbus, adt_unknown };

struct adap_type {
const char *funcs;
const char* algo;
};

static struct adap_type adap_types[5] = {
{ .funcs = "dummy",
.algo = "Dummy bus", },
{ .funcs = "isa",
.algo = "ISA bus", },
{ .funcs = "i2c",
.algo = "I2C adapter", },
{ .funcs = "smbus",
.algo = "SMBus adapter", },
{ .funcs = "unknown",
.algo = "N/A", },
};

static enum adt i2c_get_funcs(int i2cbus)
{
unsigned long funcs;
int file;
char filename[20];
enum adt ret;

file = open_i2c_dev(i2cbus, filename, sizeof(filename), 1);
if (file < 0)
return adt_unknown;

if (ioctl(file, I2C_FUNCS, &funcs) < 0)
ret = adt_unknown;
else if (funcs & I2C_FUNC_I2C)
ret = adt_i2c;
else if (funcs & (I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
ret = adt_smbus;
else
ret = adt_dummy;

close(file);
return ret;
}

/* Remove trailing spaces from a string
Return the new string length including the trailing NUL */
static int rtrim(char *s)
{
int i;

for (i = strlen(s) - 1; i >= 0 && (s[i] == ' ' || s[i] == '\n'); i--)
s[i] = '\0';
return i + 2;
}

void free_adapters(struct i2c_adap *adapters)
{
int i;

for (i = 0; adapters[i].name; i++)
free(adapters[i].name);
free(adapters);
}

/* We allocate space for the adapters in bunches. The last item is a
terminator, so here we start with room for 7 adapters, which should
be enough in most cases. If not, we allocate more later as needed. */
#define BUNCH 8

/* n must match the size of adapters at calling time */
static struct i2c_adap *more_adapters(struct i2c_adap *adapters, int n)
{
struct i2c_adap *new_adapters;

new_adapters = realloc(adapters, (n + BUNCH) * sizeof(struct i2c_adap));
if (!new_adapters) {
free_adapters(adapters);
return NULL;
}
memset(new_adapters + n, 0, BUNCH * sizeof(struct i2c_adap));

return new_adapters;
}

struct i2c_adap *gather_i2c_busses(void)
{
char s[120];
struct dirent *de, *dde;
DIR *dir, *ddir;
FILE *f;
char fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX];
int foundsysfs = 0;
int count=0;
struct i2c_adap *adapters;

adapters = calloc(BUNCH, sizeof(struct i2c_adap));
if (!adapters)
return NULL;

/* look in /proc/bus/i2c */
if ((f = fopen("/proc/bus/i2c", "r"))) {
while (fgets(s, 120, f)) {
char *algo, *name, *type, *all;
int len_algo, len_name, len_type;
int i2cbus;

algo = strrchr(s, '\t');
*(algo++) = '\0';
len_algo = rtrim(algo);

name = strrchr(s, '\t');
*(name++) = '\0';
len_name = rtrim(name);

type = strrchr(s, '\t');
*(type++) = '\0';
len_type = rtrim(type);

sscanf(s, "i2c-%d", &i2cbus);

if ((count + 1) % BUNCH == 0) {
/* We need more space */
adapters = more_adapters(adapters, count + 1);
if (!adapters)
return NULL;
}

all = malloc(len_name + len_type + len_algo);
if (all == NULL) {
free_adapters(adapters);
return NULL;
}
adapters[count].nr = i2cbus;
adapters[count].name = strcpy(all, name);
adapters[count].funcs = strcpy(all + len_name, type);
adapters[count].algo = strcpy(all + len_name + len_type,
algo);
count++;
}
fclose(f);
goto done;
}

/* look in sysfs */
/* First figure out where sysfs was mounted */
if ((f = fopen("/proc/mounts", "r")) == NULL) {
goto done;
}
while (fgets(n, NAME_MAX, f)) {
sscanf(n, "%*[^ ] %[^ ] %[^ ] %*s\n", sysfs, fstype);
if (strcasecmp(fstype, "sysfs") == 0) {
foundsysfs++;
break;
}
}
fclose(f);
if (! foundsysfs) {
goto done;
}

/* Bus numbers in i2c-adapter don't necessarily match those in
i2c-dev and what we really care about are the i2c-dev numbers.
Unfortunately the names are harder to get in i2c-dev */
strcat(sysfs, "/class/i2c-dev");
if(!(dir = opendir(sysfs)))
goto done;
/* go through the busses */
while ((de = readdir(dir)) != NULL) {
if (!strcmp(de->d_name, "."))
continue;
if (!strcmp(de->d_name, ".."))
continue;

/* this should work for kernels 2.6.5 or higher and */
/* is preferred because is unambiguous */
sprintf(n, "%s/%s/name", sysfs, de->d_name);
f = fopen(n, "r");
/* this seems to work for ISA */
if(f == NULL) {
sprintf(n, "%s/%s/device/name", sysfs, de->d_name);
f = fopen(n, "r");
}
/* non-ISA is much harder */
/* and this won't find the correct bus name if a driver
has more than one bus */
if(f == NULL) {
sprintf(n, "%s/%s/device", sysfs, de->d_name);
if(!(ddir = opendir(n)))
continue;
while ((dde = readdir(ddir)) != NULL) {
if (!strcmp(dde->d_name, "."))
continue;
if (!strcmp(dde->d_name, ".."))
continue;
if ((!strncmp(dde->d_name, "i2c-", 4))) {
sprintf(n, "%s/%s/device/%s/name",
sysfs, de->d_name, dde->d_name);
if((f = fopen(n, "r")))
goto found;
}
}
}

found:
if (f != NULL) {
int i2cbus;
enum adt type;
char *px;

px = fgets(s, 120, f);
fclose(f);
if (!px) {
fprintf(stderr, "%s: read error\n", n);
continue;
}
if ((px = strchr(s, '\n')) != NULL)
*px = 0;
if (!sscanf(de->d_name, "i2c-%d", &i2cbus))
continue;
if (!strncmp(s, "ISA ", 4)) {
type = adt_isa;
} else {
/* Attempt to probe for adapter capabilities */
type = i2c_get_funcs(i2cbus);
}

if ((count + 1) % BUNCH == 0) {
/* We need more space */
adapters = more_adapters(adapters, count + 1);
if (!adapters)
return NULL;
}

adapters[count].nr = i2cbus;
adapters[count].name = strdup(s);
if (adapters[count].name == NULL) {
free_adapters(adapters);
return NULL;
}
adapters[count].funcs = adap_types[type].funcs;
adapters[count].algo = adap_types[type].algo;
count++;
}
}
closedir(dir);

done:
return adapters;
}

static int lookup_i2c_bus_by_name(const char *bus_name)
{
struct i2c_adap *adapters;
int i, i2cbus = -1;

adapters = gather_i2c_busses();
if (adapters == NULL) {
fprintf(stderr, "Error: Out of memory!\n");
return -3;
}

/* Walk the list of i2c busses, looking for the one with the
right name */
for (i = 0; adapters[i].name; i++) {
if (strcmp(adapters[i].name, bus_name) == 0) {
if (i2cbus >= 0) {
fprintf(stderr,
"Error: I2C bus name is not unique!\n");
i2cbus = -4;
goto done;
}
i2cbus = adapters[i].nr;
}
}

if (i2cbus == -1)
fprintf(stderr, "Error: I2C bus name doesn't match any "
"bus present!\n");

done:
free_adapters(adapters);
return i2cbus;
}

/*
* Parse an I2CBUS command line argument and return the corresponding
* bus number, or a negative value if the bus is invalid.
*/
int lookup_i2c_bus(const char *i2cbus_arg)
{
unsigned long i2cbus;
char *end;

i2cbus = strtoul(i2cbus_arg, &end, 0);
if (*end || !*i2cbus_arg) {
/* Not a number, maybe a name? */
return lookup_i2c_bus_by_name(i2cbus_arg);
}
if (i2cbus > 0xFFFFF) {
fprintf(stderr, "Error: I2C bus out of range!\n");
return -2;
}

return i2cbus;
}

/*
* Parse a CHIP-ADDRESS command line argument and return the corresponding
* chip address, or a negative value if the address is invalid.
*/
int parse_i2c_address(const char *address_arg)
{
long address;
char *end;

address = strtol(address_arg, &end, 0);
if (*end || !*address_arg) {
fprintf(stderr, "Error: Chip address is not a number!\n");
return -1;
}
if (address < 0x03 || address > 0x77) {
fprintf(stderr, "Error: Chip address out of range "
"(0x03-0x77)!\n");
return -2;
}

return address;
}

int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
{
int file;

snprintf(filename, size, "/dev/i2c/%d", i2cbus);
filename[size - 1] = '\0';
file = open(filename, O_RDWR);

if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {
sprintf(filename, "/dev/i2c-%d", i2cbus);
file = open(filename, O_RDWR);
}

if (file < 0 && !quiet) {
if (errno == ENOENT) {
fprintf(stderr, "Error: Could not open file "
"`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
i2cbus, i2cbus, strerror(ENOENT));
} else {
fprintf(stderr, "Error: Could not open file "
"`%s': %s\n", filename, strerror(errno));
if (errno == EACCES)
fprintf(stderr, "Run as root?\n");
}
}

return file;
}

int set_slave_addr(int file, int address, int force)
{
/* With force, let the user read from/write to the registers
even when a driver is also running */
if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) {
fprintf(stderr,
"Error: Could not set address to 0x%02x: %s\n",
address, strerror(errno));
return -errno;
}

return 0;
}

+ 44
- 0
src/i2cbusses.h Переглянути файл

@@ -0,0 +1,44 @@
/*
i2cbusses.h - Part of the i2c-tools package

Copyright (C) 2004-2010 Jean Delvare <jdelvare@suse.de>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA.
*/

#ifndef _I2CBUSSES_H
#define _I2CBUSSES_H

#include <unistd.h>

struct i2c_adap {
int nr;
char *name;
const char *funcs;
const char *algo;
};

struct i2c_adap *gather_i2c_busses(void);
void free_adapters(struct i2c_adap *adapters);

int lookup_i2c_bus(const char *i2cbus_arg);
int parse_i2c_address(const char *address_arg);
int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet);
int set_slave_addr(int file, int address, int force);

#define MISSING_FUNC_FMT "Error: Adapter does not have %s capability\n"

#endif

Завантаження…
Відмінити
Зберегти