2014-04-22 15:51:28 +01:00
|
|
|
/*
|
|
|
|
|
* Author: Brendan Le Foll <brendan.le.foll@intel.com>
|
2014-05-01 16:55:23 +01:00
|
|
|
* Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
|
2016-01-20 15:58:06 +00:00
|
|
|
* Copyright (c) 2014-2016 Intel Corporation.
|
2014-04-22 15:51:28 +01:00
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
|
* a copy of this software and associated documentation files (the
|
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
|
* the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be
|
|
|
|
|
* included in all copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
|
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
|
|
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
|
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
2015-07-10 17:52:50 +01:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
|
|
|
|
|
#define _XOPEN_SOURCE 600 /* Get nftw() and S_IFSOCK declarations */
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-04-29 15:01:24 +01:00
|
|
|
#include <stddef.h>
|
2014-05-19 09:50:58 +01:00
|
|
|
#include <stdlib.h>
|
2014-06-04 14:39:41 +01:00
|
|
|
#include <sched.h>
|
|
|
|
|
#include <string.h>
|
2014-12-15 22:40:57 +01:00
|
|
|
#include <pwd.h>
|
2015-02-15 12:47:11 +01:00
|
|
|
#include <glob.h>
|
2015-07-10 17:52:50 +01:00
|
|
|
#include <ftw.h>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <stdio.h>
|
2016-03-15 17:32:18 -04:00
|
|
|
#include <stdbool.h>
|
2016-05-23 13:55:57 +01:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <limits.h>
|
2016-03-15 17:32:18 -04:00
|
|
|
|
2016-03-16 18:58:56 +00:00
|
|
|
#if defined(IMRAA)
|
2016-03-15 17:32:18 -04:00
|
|
|
#include <json-c/json.h>
|
2016-03-23 11:31:51 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/mman.h>
|
2016-03-15 17:32:18 -04:00
|
|
|
#endif
|
2014-04-29 15:01:24 +01:00
|
|
|
|
2014-06-24 17:24:54 +01:00
|
|
|
#include "mraa_internal.h"
|
2016-03-07 14:49:42 +00:00
|
|
|
#include "firmata/firmata_mraa.h"
|
2014-04-29 15:01:24 +01:00
|
|
|
#include "gpio.h"
|
2014-04-28 00:29:14 +01:00
|
|
|
#include "version.h"
|
2016-05-23 13:55:57 +01:00
|
|
|
#include "i2c.h"
|
|
|
|
|
#include "pwm.h"
|
|
|
|
|
#include "aio.h"
|
|
|
|
|
#include "spi.h"
|
|
|
|
|
#include "uart.h"
|
|
|
|
|
|
2014-04-08 18:43:26 +01:00
|
|
|
|
2015-10-06 23:14:08 +02:00
|
|
|
#define IIO_DEVICE_WILDCARD "iio:device*"
|
2014-07-14 16:56:12 +01:00
|
|
|
mraa_board_t* plat = NULL;
|
2015-10-06 11:51:56 +01:00
|
|
|
mraa_iio_info_t* plat_iio = NULL;
|
2016-02-26 13:50:07 -08:00
|
|
|
mraa_lang_func_t* lang_func = NULL;
|
2015-08-20 12:08:57 -07:00
|
|
|
|
2016-01-20 16:01:52 +00:00
|
|
|
static char* platform_name = NULL;
|
|
|
|
|
static char* platform_long_name = NULL;
|
2014-04-29 15:01:24 +01:00
|
|
|
|
2015-09-28 16:26:53 +01:00
|
|
|
static int num_i2c_devices = 0;
|
|
|
|
|
static int num_iio_devices = 0;
|
|
|
|
|
|
2015-03-23 14:39:12 +00:00
|
|
|
const char*
|
2014-06-24 17:24:54 +01:00
|
|
|
mraa_get_version()
|
2014-04-08 18:43:26 +01:00
|
|
|
{
|
2014-04-28 00:29:14 +01:00
|
|
|
return gVERSION;
|
2014-04-08 18:43:26 +01:00
|
|
|
}
|
2014-04-29 15:01:24 +01:00
|
|
|
|
2014-09-25 14:31:04 +01:00
|
|
|
mraa_result_t
|
|
|
|
|
mraa_set_log_level(int level)
|
|
|
|
|
{
|
|
|
|
|
if (level <= 7 && level >= 0) {
|
|
|
|
|
setlogmask(LOG_UPTO(level));
|
2015-08-14 11:15:57 +01:00
|
|
|
syslog(LOG_DEBUG, "Loglevel %d is set", level);
|
2014-09-25 14:31:04 +01:00
|
|
|
return MRAA_SUCCESS;
|
|
|
|
|
}
|
2015-08-14 11:15:57 +01:00
|
|
|
syslog(LOG_NOTICE, "Invalid loglevel %d requested", level);
|
2014-09-25 14:31:04 +01:00
|
|
|
return MRAA_ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 17:32:18 -04:00
|
|
|
/**
|
|
|
|
|
* Whilst the actual mraa init function is now called imraa_init, it's only
|
|
|
|
|
* callable externally if IMRAA is enabled
|
|
|
|
|
*/
|
2015-03-01 10:22:13 +00:00
|
|
|
mraa_result_t
|
2016-03-15 17:32:18 -04:00
|
|
|
imraa_init()
|
2014-04-29 15:01:24 +01:00
|
|
|
{
|
2014-12-09 18:31:20 +00:00
|
|
|
if (plat != NULL) {
|
2016-04-15 14:01:23 +01:00
|
|
|
return MRAA_SUCCESS;
|
2014-12-09 18:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
2014-12-15 22:40:57 +01:00
|
|
|
uid_t proc_euid = geteuid();
|
2015-03-23 14:39:12 +00:00
|
|
|
struct passwd* proc_user = getpwuid(proc_euid);
|
2014-12-15 22:40:57 +01:00
|
|
|
|
2014-09-25 14:31:04 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
setlogmask(LOG_UPTO(LOG_DEBUG));
|
|
|
|
|
#else
|
|
|
|
|
setlogmask(LOG_UPTO(LOG_NOTICE));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
openlog("libmraa", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
|
2015-03-23 14:39:12 +00:00
|
|
|
syslog(LOG_NOTICE, "libmraa version %s initialised by user '%s' with EUID %d",
|
|
|
|
|
mraa_get_version(), (proc_user != NULL) ? proc_user->pw_name : "<unknown>", proc_euid);
|
2014-12-15 22:40:57 +01:00
|
|
|
|
2015-07-01 10:24:39 -07:00
|
|
|
mraa_platform_t platform_type;
|
2015-06-26 09:59:40 +01:00
|
|
|
#if defined(X86PLAT)
|
2014-11-21 00:01:08 +00:00
|
|
|
// Use runtime x86 platform detection
|
|
|
|
|
platform_type = mraa_x86_platform();
|
2015-06-26 09:59:40 +01:00
|
|
|
#elif defined(ARMPLAT)
|
|
|
|
|
// Use runtime ARM platform detection
|
|
|
|
|
platform_type = mraa_arm_platform();
|
|
|
|
|
#else
|
|
|
|
|
#error mraa_ARCH NOTHING
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-01-20 16:01:52 +00:00
|
|
|
if (plat != NULL) {
|
2015-07-01 10:24:39 -07:00
|
|
|
plat->platform_type = platform_type;
|
2016-01-20 16:01:52 +00:00
|
|
|
} else {
|
|
|
|
|
platform_name = NULL;
|
|
|
|
|
}
|
2015-07-01 10:24:39 -07:00
|
|
|
|
2016-03-01 11:15:43 -08:00
|
|
|
// Create null base platform if one doesn't already exist
|
2015-05-27 15:36:46 -07:00
|
|
|
if (plat == NULL) {
|
|
|
|
|
plat = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
|
|
|
|
|
if (plat != NULL) {
|
2015-08-20 12:08:57 -07:00
|
|
|
plat->platform_type = MRAA_NULL_PLATFORM;
|
2015-10-06 11:51:56 +01:00
|
|
|
plat->platform_name = "Unknown platform";
|
2015-07-01 10:24:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-01 11:15:43 -08:00
|
|
|
|
|
|
|
|
#if defined(USBPLAT)
|
2016-02-11 10:16:58 +00:00
|
|
|
// Now detect sub platform, note this is not an else since we could be in
|
|
|
|
|
// an error case and fall through to MRAA_ERROR_PLATFORM_NOT_INITIALISED
|
2015-07-01 10:24:39 -07:00
|
|
|
if (plat != NULL) {
|
|
|
|
|
mraa_platform_t usb_platform_type = mraa_usb_platform_extender(plat);
|
2016-02-11 10:16:58 +00:00
|
|
|
// if we have no known platform just replace usb platform with platform
|
2015-08-11 11:54:11 +01:00
|
|
|
if (plat->platform_type == MRAA_UNKNOWN_PLATFORM && usb_platform_type != MRAA_UNKNOWN_PLATFORM) {
|
2015-07-01 10:24:39 -07:00
|
|
|
plat->platform_type = usb_platform_type;
|
2015-05-27 15:36:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
2014-11-21 00:01:08 +00:00
|
|
|
if (plat == NULL) {
|
|
|
|
|
printf("mraa: FATAL error, failed to initialise platform\n");
|
|
|
|
|
return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
|
2014-06-16 18:45:59 +01:00
|
|
|
}
|
2015-06-26 09:59:40 +01:00
|
|
|
#endif
|
2014-12-15 22:40:57 +01:00
|
|
|
|
2016-03-15 17:32:18 -04:00
|
|
|
#if defined(IMRAA)
|
|
|
|
|
const char* subplatform_lockfile = "/tmp/imraa.lock";
|
2016-03-23 11:31:51 +00:00
|
|
|
mraa_add_from_lockfile(subplatform_lockfile);
|
2016-03-07 14:49:42 +00:00
|
|
|
#endif
|
|
|
|
|
|
2015-12-03 15:24:10 -08:00
|
|
|
// Look for IIO devices
|
|
|
|
|
mraa_iio_detect();
|
2015-12-03 12:30:59 -08:00
|
|
|
|
2016-01-20 16:01:52 +00:00
|
|
|
if (plat != NULL) {
|
|
|
|
|
int length = strlen(plat->platform_name) + 1;
|
|
|
|
|
if (mraa_has_sub_platform()) {
|
2016-02-12 11:27:02 +00:00
|
|
|
// Account for ' + ' chars
|
|
|
|
|
length += strlen(plat->sub_platform->platform_name) + 3;
|
2016-01-20 16:01:52 +00:00
|
|
|
}
|
|
|
|
|
platform_name = calloc(length, sizeof(char));
|
|
|
|
|
if (mraa_has_sub_platform()) {
|
|
|
|
|
snprintf(platform_name, length, "%s + %s", plat->platform_name, plat->sub_platform->platform_name);
|
|
|
|
|
} else {
|
|
|
|
|
strncpy(platform_name, plat->platform_name, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 13:50:07 -08:00
|
|
|
lang_func = (mraa_lang_func_t*) calloc(1, sizeof(mraa_lang_func_t));
|
2016-03-01 15:50:55 +00:00
|
|
|
if (lang_func == NULL) {
|
|
|
|
|
return MRAA_ERROR_NO_RESOURCES;
|
|
|
|
|
}
|
2016-02-26 13:50:07 -08:00
|
|
|
|
2015-07-30 12:15:03 -07:00
|
|
|
syslog(LOG_NOTICE, "libmraa initialised for platform '%s' of type %d", mraa_get_platform_name(), mraa_get_platform_type());
|
2014-06-24 17:24:54 +01:00
|
|
|
return MRAA_SUCCESS;
|
2014-04-29 15:01:24 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-15 17:32:18 -04:00
|
|
|
#if (defined SWIGPYTHON) || (defined SWIG)
|
|
|
|
|
mraa_result_t
|
|
|
|
|
#else
|
|
|
|
|
mraa_result_t __attribute__((constructor))
|
|
|
|
|
#endif
|
|
|
|
|
mraa_init()
|
|
|
|
|
{
|
|
|
|
|
if (plat != NULL) {
|
2016-04-15 14:01:23 +01:00
|
|
|
return MRAA_SUCCESS;
|
2016-03-15 17:32:18 -04:00
|
|
|
} else {
|
|
|
|
|
return imraa_init();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-01 16:38:41 +01:00
|
|
|
void
|
|
|
|
|
mraa_deinit()
|
|
|
|
|
{
|
2014-12-16 22:12:18 +01:00
|
|
|
if (plat != NULL) {
|
|
|
|
|
if (plat->pins != NULL) {
|
|
|
|
|
free(plat->pins);
|
|
|
|
|
}
|
2015-07-27 09:32:39 -07:00
|
|
|
mraa_board_t* sub_plat = plat->sub_platform;
|
2015-09-03 15:28:36 +01:00
|
|
|
if (sub_plat != NULL) {
|
2015-07-27 09:32:39 -07:00
|
|
|
if (sub_plat->pins != NULL) {
|
|
|
|
|
free(sub_plat->pins);
|
|
|
|
|
}
|
2015-09-03 15:28:36 +01:00
|
|
|
free(sub_plat);
|
2015-07-27 09:32:39 -07:00
|
|
|
}
|
2014-12-16 22:12:18 +01:00
|
|
|
free(plat);
|
2015-09-03 15:28:36 +01:00
|
|
|
|
2014-12-16 22:12:18 +01:00
|
|
|
}
|
2015-10-06 11:51:56 +01:00
|
|
|
if (plat_iio != NULL) {
|
|
|
|
|
free(plat_iio);
|
|
|
|
|
}
|
2014-09-25 14:31:04 +01:00
|
|
|
closelog();
|
2014-07-01 16:38:41 +01:00
|
|
|
}
|
|
|
|
|
|
2014-06-04 14:39:41 +01:00
|
|
|
int
|
2016-05-19 11:49:25 +01:00
|
|
|
mraa_set_priority(const int priority)
|
2014-06-04 14:39:41 +01:00
|
|
|
{
|
|
|
|
|
struct sched_param sched_s;
|
|
|
|
|
|
|
|
|
|
memset(&sched_s, 0, sizeof(struct sched_param));
|
|
|
|
|
if (priority > sched_get_priority_max(SCHED_RR)) {
|
|
|
|
|
sched_s.sched_priority = sched_get_priority_max(SCHED_RR);
|
2015-03-23 14:39:12 +00:00
|
|
|
} else {
|
2014-06-04 14:39:41 +01:00
|
|
|
sched_s.sched_priority = priority;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sched_setscheduler(0, SCHED_RR, &sched_s);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-03 12:30:59 -08:00
|
|
|
static int
|
|
|
|
|
mraa_count_iio_devices(const char* path, const struct stat* sb, int flag, struct FTW* ftwb)
|
|
|
|
|
{
|
|
|
|
|
// we are only interested in files with specific names
|
|
|
|
|
if (fnmatch(IIO_DEVICE_WILDCARD, basename(path), 0) == 0) {
|
|
|
|
|
num_iio_devices++;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2015-12-02 14:39:17 -08:00
|
|
|
|
|
|
|
|
mraa_result_t
|
|
|
|
|
mraa_iio_detect()
|
|
|
|
|
{
|
|
|
|
|
plat_iio = (mraa_iio_info_t*) calloc(1, sizeof(mraa_iio_info_t));
|
2015-12-21 15:27:15 +00:00
|
|
|
plat_iio->iio_device_count = num_iio_devices;
|
2015-12-02 14:39:17 -08:00
|
|
|
// Now detect IIO devices, linux only
|
|
|
|
|
// find how many iio devices we have if we haven't already
|
|
|
|
|
if (num_iio_devices == 0) {
|
|
|
|
|
if (nftw("/sys/bus/iio/devices", &mraa_count_iio_devices, 20, FTW_PHYS) == -1) {
|
|
|
|
|
return MRAA_ERROR_UNSPECIFIED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
char name[64], filepath[64];
|
|
|
|
|
int fd, len, i;
|
|
|
|
|
plat_iio->iio_device_count = num_iio_devices;
|
|
|
|
|
plat_iio->iio_devices = calloc(num_iio_devices, sizeof(struct _iio));
|
|
|
|
|
struct _iio* device;
|
|
|
|
|
for (i=0; i < num_iio_devices; i++) {
|
|
|
|
|
device = &plat_iio->iio_devices[i];
|
|
|
|
|
device->num = i;
|
|
|
|
|
snprintf(filepath, 64, "/sys/bus/iio/devices/iio:device%d/name", i);
|
|
|
|
|
fd = open(filepath, O_RDONLY);
|
2015-12-21 15:15:15 +00:00
|
|
|
if (fd != -1) {
|
2015-12-02 14:39:17 -08:00
|
|
|
len = read(fd, &name, 64);
|
|
|
|
|
if (len > 1) {
|
|
|
|
|
// remove any trailing CR/LF symbols
|
|
|
|
|
name[strcspn(name, "\r\n")] = '\0';
|
|
|
|
|
len = strlen(name);
|
|
|
|
|
// use strndup
|
|
|
|
|
device->name = malloc((sizeof(char) * len) + sizeof(char));
|
|
|
|
|
strncpy(device->name, name, len+1);
|
|
|
|
|
}
|
|
|
|
|
close(fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return MRAA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-30 18:09:27 +00:00
|
|
|
mraa_result_t
|
2014-06-24 17:24:54 +01:00
|
|
|
mraa_setup_mux_mapped(mraa_pin_t meta)
|
2014-04-30 11:13:36 +01:00
|
|
|
{
|
2016-05-19 11:49:25 +01:00
|
|
|
unsigned int mi;
|
2016-03-12 23:46:17 +03:00
|
|
|
mraa_result_t ret;
|
|
|
|
|
mraa_gpio_context mux_i = NULL;
|
2016-06-29 10:02:46 +01:00
|
|
|
// avoids the unsigned comparison and we should never have a pin that is UINT_MAX!
|
|
|
|
|
unsigned int last_pin = UINT_MAX;
|
2014-12-10 15:29:08 +00:00
|
|
|
|
2014-05-02 11:52:40 +01:00
|
|
|
for (mi = 0; mi < meta.mux_total; mi++) {
|
2014-12-15 11:47:21 +00:00
|
|
|
|
2016-03-12 23:46:17 +03:00
|
|
|
switch(meta.mux[mi].pincmd) {
|
|
|
|
|
case PINCMD_UNDEFINED: // used for backward compatibility
|
|
|
|
|
if(meta.mux[mi].pin != last_pin) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
|
|
|
|
|
if (mux_i == NULL) return MRAA_ERROR_INVALID_HANDLE;
|
|
|
|
|
last_pin = meta.mux[mi].pin;
|
|
|
|
|
}
|
|
|
|
|
// this function will sometimes fail, however this is not critical as
|
|
|
|
|
// long as the write succeeds - Test case galileo gen2 pin2
|
|
|
|
|
mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
|
|
|
|
|
ret = mraa_gpio_write(mux_i, meta.mux[mi].value);
|
|
|
|
|
if(ret != MRAA_SUCCESS) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PINCMD_SET_VALUE:
|
|
|
|
|
if(meta.mux[mi].pin != last_pin) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
|
|
|
|
|
if (mux_i == NULL) return MRAA_ERROR_INVALID_HANDLE;
|
|
|
|
|
last_pin = meta.mux[mi].pin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = mraa_gpio_write(mux_i, meta.mux[mi].value);
|
|
|
|
|
|
|
|
|
|
if(ret != MRAA_SUCCESS) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PINCMD_SET_DIRECTION:
|
|
|
|
|
if(meta.mux[mi].pin != last_pin) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
|
|
|
|
|
if (mux_i == NULL) return MRAA_ERROR_INVALID_HANDLE;
|
|
|
|
|
last_pin = meta.mux[mi].pin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = mraa_gpio_dir(mux_i, meta.mux[mi].value);
|
|
|
|
|
|
|
|
|
|
if(ret != MRAA_SUCCESS) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PINCMD_SET_IN_VALUE:
|
|
|
|
|
if(meta.mux[mi].pin != last_pin) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
|
|
|
|
|
if (mux_i == NULL) return MRAA_ERROR_INVALID_HANDLE;
|
|
|
|
|
last_pin = meta.mux[mi].pin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = mraa_gpio_dir(mux_i, MRAA_GPIO_IN);
|
|
|
|
|
|
|
|
|
|
if(ret == MRAA_SUCCESS)
|
|
|
|
|
ret = mraa_gpio_write(mux_i, meta.mux[mi].value);
|
|
|
|
|
|
|
|
|
|
if(ret != MRAA_SUCCESS) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PINCMD_SET_OUT_VALUE:
|
|
|
|
|
if(meta.mux[mi].pin != last_pin) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
|
|
|
|
|
if (mux_i == NULL) return MRAA_ERROR_INVALID_HANDLE;
|
|
|
|
|
last_pin = meta.mux[mi].pin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
|
|
|
|
|
|
|
|
|
|
if(ret == MRAA_SUCCESS)
|
|
|
|
|
ret = mraa_gpio_write(mux_i, meta.mux[mi].value);
|
|
|
|
|
|
|
|
|
|
if(ret != MRAA_SUCCESS) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PINCMD_SET_MODE:
|
|
|
|
|
if(meta.mux[mi].pin != last_pin) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
|
|
|
|
|
if (mux_i == NULL) return MRAA_ERROR_INVALID_HANDLE;
|
|
|
|
|
last_pin = meta.mux[mi].pin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = mraa_gpio_mode(mux_i, meta.mux[mi].value);
|
|
|
|
|
|
|
|
|
|
if(ret != MRAA_SUCCESS) {
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
|
|
|
|
mraa_gpio_close(mux_i);
|
|
|
|
|
}
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PINCMD_SKIP:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
syslog(LOG_NOTICE, "mraa_setup_mux_mapped: wrong command %d on pin %d with value %d", meta.mux[mi].pincmd, meta.mux[mi].pin, meta.mux[mi].value);
|
|
|
|
|
break;
|
2014-12-10 15:29:08 +00:00
|
|
|
}
|
2016-03-12 23:46:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mux_i != NULL) {
|
|
|
|
|
mraa_gpio_owner(mux_i, 0);
|
2014-12-10 15:29:08 +00:00
|
|
|
mraa_gpio_close(mux_i);
|
2014-04-30 11:13:36 +01:00
|
|
|
}
|
2014-12-10 15:29:08 +00:00
|
|
|
|
2014-06-24 17:24:54 +01:00
|
|
|
return MRAA_SUCCESS;
|
2014-04-30 11:13:36 +01:00
|
|
|
}
|
|
|
|
|
|
2014-05-06 15:29:42 +01:00
|
|
|
void
|
2014-06-24 17:24:54 +01:00
|
|
|
mraa_result_print(mraa_result_t result)
|
2014-05-06 15:29:42 +01:00
|
|
|
{
|
|
|
|
|
switch (result) {
|
2014-09-25 14:31:04 +01:00
|
|
|
case MRAA_SUCCESS:
|
|
|
|
|
fprintf(stdout, "MRAA: SUCCESS\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_FEATURE_NOT_IMPLEMENTED:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Feature not implemented.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_FEATURE_NOT_SUPPORTED:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Feature not supported by Hardware.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_INVALID_VERBOSITY_LEVEL:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Invalid verbosity level.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_INVALID_PARAMETER:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Invalid parameter.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_INVALID_HANDLE:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Invalid Handle.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_NO_RESOURCES:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: No resources.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_INVALID_RESOURCE:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Invalid resource.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_INVALID_QUEUE_TYPE:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Invalid Queue Type.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_NO_DATA_AVAILABLE:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: No Data available.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_INVALID_PLATFORM:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Platform not recognised.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_PLATFORM_NOT_INITIALISED:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Platform not initialised.\n");
|
|
|
|
|
break;
|
uart_ow: Initial support for Dallas 1-wire over UART support for MRAA
This commit introduces support for Dallas Semiconductor (DS) 1-wire
compliant device support using an available UART device.
The principle of operation is described in the following Application
note by Maxim Electronics:
https://www.maximintegrated.com/en/app-notes/index.mvp/id/214
with help (1-wire search) from:
https://www.maximintegrated.com/en/app-notes/index.mvp/id/187
It has been tested on Galileo 2 and Edison, with 2 DS 1-wire devices,
the DS18B20 and DS2413 connected to the bus. A UPM driver for the
DS2413 is already complete and a PR will be submitted after this one.
It is important that you use a UART with CMOS/TTL level voltages
(3.3v/5v) RX and TX lines. DO NOT use standard RS232 level voltages
or you are going to have a bad day.
In order for this to work, a simple interface circuit, using a single
diode must be constructed:
(forgive my "Asciihematic" :)
-|
U|
A| TX---|<--+
R| |
T| RX-------o--------o 1-wire data bus
-|
The diode on TX is a 1N4148 (cheap and common), with the cathode
connected to TX, and the anode connected to RX and the 1-wire data
line.
The 1-wire data line requires a pull-up resistor, as the DS 1-wire
spec requires. 4.7-5K is typical for DS 1-wire buses.
NOTE: DHT-type (temp/humidity sensor) 1-wire devices ARE NOT DS 1-wire
compliant, and will not work with this code/circuit unfortunately.
Also note, this will use up one of your UARTs, which cannot be used
for any other purpose (ie: to access true UART-type serial devices).
You can however, connect as many DS 1-wire devices as feasible to this
UART, as it will function as a DS 1-wire bus master.
Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
2015-12-15 17:11:14 -07:00
|
|
|
case MRAA_ERROR_UART_OW_SHORTED:
|
|
|
|
|
fprintf(stdout, "MRAA: UART OW: Bus short detected.\n");
|
|
|
|
|
break;
|
|
|
|
|
case MRAA_ERROR_UART_OW_NO_DEVICES:
|
|
|
|
|
fprintf(stdout, "MRAA: UART OW: No devices detected on bus.\n");
|
|
|
|
|
break;
|
|
|
|
|
case MRAA_ERROR_UART_OW_DATA_ERROR:
|
|
|
|
|
fprintf(stdout, "MRAA: UART OW: Data or Bus error detected.\n");
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_ERROR_UNSPECIFIED:
|
2014-09-25 14:31:04 +01:00
|
|
|
fprintf(stdout, "MRAA: Unspecified Error.\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf(stdout, "MRAA: Unrecognised error.\n");
|
|
|
|
|
break;
|
2014-05-06 15:29:42 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-05-07 15:54:59 +01:00
|
|
|
|
2015-07-27 09:32:39 -07:00
|
|
|
|
2015-09-03 15:28:36 +01:00
|
|
|
mraa_boolean_t
|
2015-07-28 16:35:18 -07:00
|
|
|
mraa_has_sub_platform()
|
|
|
|
|
{
|
|
|
|
|
return (plat != NULL) && (plat->sub_platform != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-27 09:32:39 -07:00
|
|
|
mraa_boolean_t
|
2015-08-20 12:08:57 -07:00
|
|
|
mraa_pin_mode_test(int pin, mraa_pinmodes_t mode)
|
2015-07-27 09:32:39 -07:00
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat == NULL)
|
2015-07-27 09:32:39 -07:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
mraa_board_t* current_plat = plat;
|
|
|
|
|
if (mraa_is_sub_platform_id(pin)) {
|
2015-07-27 09:32:39 -07:00
|
|
|
current_plat = plat->sub_platform;
|
2015-08-20 12:08:57 -07:00
|
|
|
if (current_plat == NULL) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_pin_mode_test: Sub platform Not Initialised");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
pin = mraa_get_sub_platform_index(pin);
|
|
|
|
|
}
|
2015-07-27 09:32:39 -07:00
|
|
|
|
2016-03-11 11:35:31 +00:00
|
|
|
if (current_plat == NULL || current_plat->platform_type == MRAA_UNKNOWN_PLATFORM || current_plat->platform_type == MRAA_NULL_PLATFORM) {
|
2015-04-04 18:27:44 +01:00
|
|
|
return 0;
|
2014-05-07 16:07:58 +01:00
|
|
|
}
|
2015-07-27 09:32:39 -07:00
|
|
|
if (pin > (current_plat->phy_pin_count - 1) || pin < 0)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2015-03-23 14:39:12 +00:00
|
|
|
switch (mode) {
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_VALID:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.valid == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_GPIO:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.gpio == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_PWM:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.pwm == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_FAST_GPIO:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.fast_gpio == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_SPI:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.spi == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_I2C:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.i2c == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-06-24 17:24:54 +01:00
|
|
|
case MRAA_PIN_AIO:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.aio == 1)
|
2014-05-07 15:54:59 +01:00
|
|
|
return 1;
|
|
|
|
|
break;
|
2014-12-18 14:11:25 +00:00
|
|
|
case MRAA_PIN_UART:
|
2015-07-27 09:32:39 -07:00
|
|
|
if (current_plat->pins[pin].capabilites.uart == 1)
|
2014-12-18 14:11:25 +00:00
|
|
|
return 1;
|
2015-01-05 23:04:50 +00:00
|
|
|
break;
|
2014-12-18 14:13:04 +00:00
|
|
|
default:
|
|
|
|
|
syslog(LOG_NOTICE, "requested pinmode invalid");
|
|
|
|
|
break;
|
2014-05-07 15:54:59 +01:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2014-05-29 16:30:07 +01:00
|
|
|
|
2015-03-23 14:39:12 +00:00
|
|
|
mraa_platform_t
|
|
|
|
|
mraa_get_platform_type()
|
2014-06-20 18:00:19 +01:00
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat == NULL)
|
2015-07-01 10:24:39 -07:00
|
|
|
return MRAA_UNKNOWN_PLATFORM;
|
2015-08-20 12:08:57 -07:00
|
|
|
return plat->platform_type;
|
2014-06-20 18:00:19 +01:00
|
|
|
}
|
2014-06-25 17:32:41 +01:00
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
int
|
|
|
|
|
mraa_get_platform_combined_type()
|
|
|
|
|
{
|
|
|
|
|
int type = mraa_get_platform_type();
|
|
|
|
|
int sub_type = mraa_has_sub_platform() ? plat->sub_platform->platform_type : MRAA_UNKNOWN_PLATFORM;
|
|
|
|
|
return type | (sub_type << 8);
|
|
|
|
|
}
|
2015-07-23 14:56:03 -07:00
|
|
|
|
2014-06-25 17:32:41 +01:00
|
|
|
unsigned int
|
|
|
|
|
mraa_adc_raw_bits()
|
|
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat == NULL)
|
2014-06-25 17:32:41 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat->aio_count == 0)
|
2014-06-25 17:32:41 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
return plat->adc_raw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
|
mraa_get_platform_adc_raw_bits(uint8_t platform_offset)
|
|
|
|
|
{
|
|
|
|
|
if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET)
|
|
|
|
|
return mraa_adc_raw_bits();
|
|
|
|
|
else {
|
|
|
|
|
if (!mraa_has_sub_platform())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (plat->sub_platform->aio_count == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return plat->sub_platform->adc_raw;
|
|
|
|
|
}
|
2014-06-25 17:32:41 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
|
2014-06-25 17:32:41 +01:00
|
|
|
unsigned int
|
|
|
|
|
mraa_adc_supported_bits()
|
|
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat == NULL)
|
2014-06-25 17:32:41 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat->aio_count == 0)
|
2014-06-25 17:32:41 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
return plat->adc_supported;
|
2014-06-25 17:32:41 +01:00
|
|
|
}
|
2014-07-10 00:55:50 +01:00
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
unsigned int
|
|
|
|
|
mraa_get_platform_adc_supported_bits(int platform_offset)
|
|
|
|
|
{
|
|
|
|
|
if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET)
|
|
|
|
|
return mraa_adc_supported_bits();
|
|
|
|
|
else {
|
|
|
|
|
if (!mraa_has_sub_platform())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (plat->sub_platform->aio_count == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return plat->sub_platform->adc_supported;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-20 15:58:28 +00:00
|
|
|
const char*
|
2014-11-26 15:15:55 +00:00
|
|
|
mraa_get_platform_name()
|
|
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
return platform_name;
|
2014-11-26 15:15:55 +00:00
|
|
|
}
|
2015-01-21 15:11:03 +00:00
|
|
|
|
2016-01-20 15:58:06 +00:00
|
|
|
const char*
|
|
|
|
|
mraa_get_platform_version(int platform_offset)
|
|
|
|
|
{
|
|
|
|
|
if (plat == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET) {
|
|
|
|
|
return plat->platform_version;
|
|
|
|
|
} else {
|
|
|
|
|
return plat->sub_platform->platform_version;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-25 15:04:38 +08:00
|
|
|
int
|
|
|
|
|
mraa_get_i2c_bus_count()
|
|
|
|
|
{
|
|
|
|
|
if (plat == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return plat->i2c_bus_count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2016-05-19 11:49:25 +01:00
|
|
|
mraa_get_i2c_bus_id(int i2c_bus)
|
2015-08-25 15:04:38 +08:00
|
|
|
{
|
|
|
|
|
if (plat == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i2c_bus >= plat->i2c_bus_count) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return plat->i2c_bus[i2c_bus].bus_id;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 15:11:03 +00:00
|
|
|
unsigned int
|
|
|
|
|
mraa_get_pin_count()
|
|
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat == NULL) {
|
2015-01-21 15:11:03 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-08-20 12:08:57 -07:00
|
|
|
return plat->phy_pin_count;
|
2015-01-21 15:11:03 +00:00
|
|
|
}
|
2015-02-15 12:47:11 +01:00
|
|
|
|
2015-08-20 12:08:57 -07:00
|
|
|
unsigned int
|
|
|
|
|
mraa_get_platform_pin_count(uint8_t platform_offset)
|
|
|
|
|
{
|
|
|
|
|
if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET)
|
|
|
|
|
return mraa_get_pin_count();
|
|
|
|
|
else {
|
|
|
|
|
if (mraa_has_sub_platform())
|
|
|
|
|
return plat->sub_platform->phy_pin_count;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-04 18:52:35 +01:00
|
|
|
char*
|
|
|
|
|
mraa_get_pin_name(int pin)
|
|
|
|
|
{
|
2015-08-20 12:08:57 -07:00
|
|
|
if (plat == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
mraa_board_t* current_plat = plat;
|
|
|
|
|
if (mraa_is_sub_platform_id(pin)) {
|
|
|
|
|
current_plat = plat->sub_platform;
|
|
|
|
|
if (current_plat == NULL) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_get_pin_name: Sub platform Not Initialised");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
pin = mraa_get_sub_platform_index(pin);
|
2015-04-04 18:52:35 +01:00
|
|
|
}
|
2015-08-20 12:08:57 -07:00
|
|
|
|
2015-07-27 09:32:39 -07:00
|
|
|
if (pin > (current_plat->phy_pin_count - 1) || pin < 0)
|
2015-04-04 18:52:35 +01:00
|
|
|
return NULL;
|
2015-07-27 09:32:39 -07:00
|
|
|
return (char*) current_plat->pins[pin].name;
|
2015-04-04 18:52:35 +01:00
|
|
|
}
|
|
|
|
|
|
2015-05-27 15:36:46 -07:00
|
|
|
int
|
2015-08-20 12:08:57 -07:00
|
|
|
mraa_get_default_i2c_bus(uint8_t platform_offset)
|
2015-05-27 15:36:46 -07:00
|
|
|
{
|
2015-09-03 15:28:36 +01:00
|
|
|
if (plat == NULL)
|
2015-05-27 15:36:46 -07:00
|
|
|
return -1;
|
2015-08-20 12:08:57 -07:00
|
|
|
if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET) {
|
|
|
|
|
return plat->def_i2c_bus;
|
|
|
|
|
} else {
|
|
|
|
|
if (mraa_has_sub_platform())
|
|
|
|
|
return plat->sub_platform->def_i2c_bus;
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2015-05-27 15:36:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-02-15 12:47:11 +01:00
|
|
|
mraa_boolean_t
|
2015-04-04 18:41:13 +01:00
|
|
|
mraa_file_exist(const char* filename)
|
2015-03-23 14:39:12 +00:00
|
|
|
{
|
2015-02-15 12:47:11 +01:00
|
|
|
glob_t results;
|
|
|
|
|
results.gl_pathc = 0;
|
|
|
|
|
glob(filename, 0, NULL, &results);
|
|
|
|
|
int file_found = results.gl_pathc == 1;
|
|
|
|
|
globfree(&results);
|
|
|
|
|
return file_found;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-04 18:52:35 +01:00
|
|
|
mraa_boolean_t
|
|
|
|
|
mraa_file_contains(const char* filename, const char* content)
|
2015-03-18 20:48:14 +01:00
|
|
|
{
|
2015-04-04 18:52:35 +01:00
|
|
|
mraa_boolean_t found = 0;
|
|
|
|
|
if ((filename == NULL) || (content == NULL)) {
|
|
|
|
|
return 0;
|
2015-03-18 20:48:14 +01:00
|
|
|
}
|
2015-04-04 18:52:35 +01:00
|
|
|
|
|
|
|
|
char* file = mraa_file_unglob(filename);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
size_t len = 1024;
|
mraa: Prefer calloc over malloc
Switch to using calloc on all calls to malloc where the memory isn't
initialized. For things like the mraa_board_t, not allocating all to zero
causes issues such as with the sub_platform member, where if that's not zero
mraa_get_platform_type will try to dereference a random memory location for the
sub_platform->platform_name, which can result in segmentation faults and other
issues.
Note that in some places where immediately after the malloc call is a copy
operation, there is no need for calloc, as all the memory gets overwritten
anyways, but in cases where there may or may not be memory written to (such as
in mraa_file_contains, with reading from a file), even though in most cases the
memory is overwritten, it could be the case that the read operation does
nothing, but the memory still has non-zero values, by virtue of the fact it
wasn't overwritten.
Signed-off-by: Ian Johnson <ijohnson@wolfram.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
2016-01-17 09:39:45 -06:00
|
|
|
char* line = calloc(len, sizeof(char));
|
2015-08-14 15:36:50 +01:00
|
|
|
if (line == NULL) {
|
2015-08-20 19:09:42 +01:00
|
|
|
free(file);
|
2015-08-14 15:36:50 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-04-04 18:52:35 +01:00
|
|
|
FILE* fh = fopen(file, "r");
|
2015-08-13 15:25:59 +01:00
|
|
|
if (fh == NULL) {
|
2015-08-20 19:09:42 +01:00
|
|
|
free(file);
|
2015-08-14 15:36:50 +01:00
|
|
|
free(line);
|
2015-08-13 15:25:59 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-04-04 18:52:35 +01:00
|
|
|
while ((getline(&line, &len, fh) != -1) && (found == 0)) {
|
|
|
|
|
if (strstr(line, content)) {
|
|
|
|
|
found = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose(fh);
|
|
|
|
|
free(file);
|
|
|
|
|
free(line);
|
|
|
|
|
}
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mraa_boolean_t
|
|
|
|
|
mraa_file_contains_both(const char* filename, const char* content, const char* content2)
|
|
|
|
|
{
|
|
|
|
|
mraa_boolean_t found = 0;
|
|
|
|
|
if ((filename == NULL) || (content == NULL)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* file = mraa_file_unglob(filename);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
size_t len = 1024;
|
mraa: Prefer calloc over malloc
Switch to using calloc on all calls to malloc where the memory isn't
initialized. For things like the mraa_board_t, not allocating all to zero
causes issues such as with the sub_platform member, where if that's not zero
mraa_get_platform_type will try to dereference a random memory location for the
sub_platform->platform_name, which can result in segmentation faults and other
issues.
Note that in some places where immediately after the malloc call is a copy
operation, there is no need for calloc, as all the memory gets overwritten
anyways, but in cases where there may or may not be memory written to (such as
in mraa_file_contains, with reading from a file), even though in most cases the
memory is overwritten, it could be the case that the read operation does
nothing, but the memory still has non-zero values, by virtue of the fact it
wasn't overwritten.
Signed-off-by: Ian Johnson <ijohnson@wolfram.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
2016-01-17 09:39:45 -06:00
|
|
|
char* line = calloc(len, sizeof(char));
|
2015-08-14 15:36:50 +01:00
|
|
|
if (line == NULL) {
|
2015-08-20 19:09:42 +01:00
|
|
|
free(file);
|
2015-08-14 15:36:50 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-04-04 18:52:35 +01:00
|
|
|
FILE* fh = fopen(file, "r");
|
2015-08-13 15:25:59 +01:00
|
|
|
if (fh == NULL) {
|
2015-08-20 19:09:42 +01:00
|
|
|
free(file);
|
2015-08-14 15:36:50 +01:00
|
|
|
free(line);
|
2015-08-13 15:25:59 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
2015-04-04 18:52:35 +01:00
|
|
|
while ((getline(&line, &len, fh) != -1) && (found == 0)) {
|
|
|
|
|
if (strstr(line, content) && strstr(line, content2)) {
|
|
|
|
|
found = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose(fh);
|
|
|
|
|
free(file);
|
|
|
|
|
free(line);
|
|
|
|
|
}
|
|
|
|
|
return found;
|
2015-03-18 20:48:14 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-15 12:47:11 +01:00
|
|
|
char*
|
2015-04-04 18:41:13 +01:00
|
|
|
mraa_file_unglob(const char* filename)
|
2015-03-23 14:39:12 +00:00
|
|
|
{
|
2015-02-15 12:47:11 +01:00
|
|
|
glob_t results;
|
2015-03-23 14:39:12 +00:00
|
|
|
char* res = NULL;
|
2015-02-15 12:47:11 +01:00
|
|
|
results.gl_pathc = 0;
|
|
|
|
|
glob(filename, 0, NULL, &results);
|
|
|
|
|
if (results.gl_pathc == 1)
|
|
|
|
|
res = strdup(results.gl_pathv[0]);
|
|
|
|
|
globfree(&results);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mraa_boolean_t
|
2015-04-04 18:41:13 +01:00
|
|
|
mraa_link_targets(const char* filename, const char* targetname)
|
2015-03-23 14:39:12 +00:00
|
|
|
{
|
2015-02-15 12:47:11 +01:00
|
|
|
int size = 100;
|
|
|
|
|
int nchars = 0;
|
2015-03-23 14:39:12 +00:00
|
|
|
char* buffer = NULL;
|
|
|
|
|
while (nchars == 0) {
|
|
|
|
|
buffer = (char*) realloc(buffer, size);
|
2015-02-15 12:47:11 +01:00
|
|
|
if (buffer == NULL)
|
|
|
|
|
return 0;
|
2015-03-23 14:39:12 +00:00
|
|
|
nchars = readlink(filename, buffer, size);
|
|
|
|
|
if (nchars < 0) {
|
2015-02-15 12:47:11 +01:00
|
|
|
free(buffer);
|
|
|
|
|
return 0;
|
2015-07-01 10:52:31 +01:00
|
|
|
} else {
|
|
|
|
|
buffer[nchars] = '\0';
|
2015-02-15 12:47:11 +01:00
|
|
|
}
|
|
|
|
|
if (nchars >= size) {
|
2015-03-23 14:39:12 +00:00
|
|
|
size *= 2;
|
|
|
|
|
nchars = 0;
|
2015-02-15 12:47:11 +01:00
|
|
|
}
|
|
|
|
|
}
|
2015-03-23 14:39:12 +00:00
|
|
|
if (strstr(buffer, targetname)) {
|
2015-02-15 12:47:11 +01:00
|
|
|
free(buffer);
|
|
|
|
|
return 1;
|
2015-03-23 14:39:12 +00:00
|
|
|
} else {
|
2015-02-15 12:47:11 +01:00
|
|
|
free(buffer);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-10 17:52:50 +01:00
|
|
|
|
|
|
|
|
static int
|
2015-09-28 16:26:53 +01:00
|
|
|
mraa_count_i2c_files(const char* path, const struct stat* sb, int flag, struct FTW* ftwb)
|
2015-07-10 17:52:50 +01:00
|
|
|
{
|
|
|
|
|
switch (sb->st_mode & S_IFMT) {
|
|
|
|
|
case S_IFLNK:
|
|
|
|
|
num_i2c_devices++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mraa_find_i2c_bus(const char* devname, int startfrom)
|
|
|
|
|
{
|
2015-07-15 13:50:28 +01:00
|
|
|
char path[64];
|
2015-07-10 17:52:50 +01:00
|
|
|
int fd;
|
|
|
|
|
int i = startfrom;
|
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
|
|
// because feeding mraa_find_i2c_bus result back into the function is
|
|
|
|
|
// useful treat -1 as 0
|
|
|
|
|
if (startfrom < 0) {
|
|
|
|
|
startfrom = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find how many i2c buses we have if we haven't already
|
|
|
|
|
if (num_i2c_devices == 0) {
|
2015-09-28 16:26:53 +01:00
|
|
|
if (nftw("/sys/class/i2c-dev/", &mraa_count_i2c_files, 20, FTW_PHYS) == -1) {
|
2015-07-10 17:52:50 +01:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// i2c devices are numbered numerically so 0 must exist otherwise there is
|
|
|
|
|
// no i2c-dev loaded
|
|
|
|
|
if (mraa_file_exist("/sys/class/i2c-dev/i2c-0")) {
|
|
|
|
|
for (i; i < num_i2c_devices; i++) {
|
|
|
|
|
off_t size, err;
|
|
|
|
|
snprintf(path, 64, "/sys/class/i2c-dev/i2c-%u/name", i);
|
|
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
|
if (fd < 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
size = lseek(fd, 0, SEEK_END);
|
|
|
|
|
if (size < 0) {
|
|
|
|
|
syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
|
|
|
|
|
close(fd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
err = lseek(fd, 0, SEEK_SET);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
|
|
|
|
|
close(fd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-07-15 13:50:28 +01:00
|
|
|
char* value = malloc(size);
|
|
|
|
|
if (value == NULL) {
|
|
|
|
|
syslog(LOG_ERR, "mraa: failed to allocate memory for i2c file");
|
|
|
|
|
close(fd);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-07-10 17:52:50 +01:00
|
|
|
ssize_t r = read(fd, value, size);
|
|
|
|
|
if (r > 0) {
|
|
|
|
|
if (strcasestr(value, devname) != NULL) {
|
2015-07-15 13:50:28 +01:00
|
|
|
free(value);
|
2015-07-10 17:52:50 +01:00
|
|
|
close(fd);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
syslog(LOG_ERR, "mraa: sysfs i2cdev failed");
|
|
|
|
|
}
|
2015-07-15 13:50:28 +01:00
|
|
|
free(value);
|
2015-07-10 17:52:50 +01:00
|
|
|
close(fd);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
syslog(LOG_WARNING, "mraa: no i2c-dev detected, load i2c-dev");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2015-06-26 14:22:09 -07:00
|
|
|
|
|
|
|
|
mraa_boolean_t
|
2015-08-10 17:16:00 -07:00
|
|
|
mraa_is_sub_platform_id(int pin_or_bus)
|
2015-06-26 14:22:09 -07:00
|
|
|
{
|
2015-07-01 10:24:39 -07:00
|
|
|
return (pin_or_bus & MRAA_SUB_PLATFORM_MASK) != 0;
|
2015-06-26 14:22:09 -07:00
|
|
|
}
|
|
|
|
|
|
2015-09-03 15:28:36 +01:00
|
|
|
int
|
2015-08-10 17:16:00 -07:00
|
|
|
mraa_get_sub_platform_id(int pin_or_bus)
|
2015-06-26 14:22:09 -07:00
|
|
|
{
|
|
|
|
|
return pin_or_bus | MRAA_SUB_PLATFORM_MASK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-03 15:28:36 +01:00
|
|
|
int
|
2015-06-26 14:22:09 -07:00
|
|
|
mraa_get_sub_platform_index(int pin_or_bus)
|
|
|
|
|
{
|
|
|
|
|
return pin_or_bus & (~MRAA_SUB_PLATFORM_MASK);
|
|
|
|
|
}
|
2015-09-28 16:26:53 +01:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mraa_get_iio_device_count()
|
|
|
|
|
{
|
2015-10-06 11:51:56 +01:00
|
|
|
return plat_iio->iio_device_count;
|
2015-09-28 16:26:53 +01:00
|
|
|
}
|
2016-03-07 14:49:42 +00:00
|
|
|
|
|
|
|
|
mraa_result_t
|
|
|
|
|
mraa_add_subplatform(mraa_platform_t subplatformtype, const char* uart_dev)
|
|
|
|
|
{
|
2016-03-15 17:32:18 -04:00
|
|
|
#if defined(FIRMATA)
|
2016-03-07 14:49:42 +00:00
|
|
|
if (subplatformtype == MRAA_GENERIC_FIRMATA) {
|
2016-04-22 09:38:30 +01:00
|
|
|
if (plat->sub_platform != NULL) {
|
|
|
|
|
return MRAA_ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
2016-03-07 14:49:42 +00:00
|
|
|
if (mraa_firmata_platform(plat, uart_dev) == MRAA_GENERIC_FIRMATA) {
|
|
|
|
|
syslog(LOG_NOTICE, "mraa: Added firmata subplatform");
|
|
|
|
|
return MRAA_SUCCESS;
|
|
|
|
|
}
|
2016-03-15 17:32:18 -04:00
|
|
|
syslog(LOG_NOTICE, "mraa: Failed to add firmata subplatform");
|
2016-03-07 14:49:42 +00:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return MRAA_ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
2016-03-15 17:32:18 -04:00
|
|
|
|
2016-04-22 09:38:30 +01:00
|
|
|
mraa_result_t
|
|
|
|
|
mraa_remove_subplatform(mraa_platform_t subplatformtype)
|
|
|
|
|
{
|
|
|
|
|
#if defined(FIRMATA)
|
|
|
|
|
if (subplatformtype == MRAA_GENERIC_FIRMATA) {
|
|
|
|
|
if (plat == NULL || plat->sub_platform == NULL) {
|
|
|
|
|
return MRAA_ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
free(plat->sub_platform->adv_func);
|
|
|
|
|
free(plat->sub_platform->pins);
|
|
|
|
|
free(plat->sub_platform);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return MRAA_ERROR_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-15 17:32:18 -04:00
|
|
|
#if defined(IMRAA)
|
2016-03-23 11:31:51 +00:00
|
|
|
mraa_result_t
|
|
|
|
|
mraa_add_from_lockfile(const char* imraa_lock_file)
|
|
|
|
|
{
|
|
|
|
|
mraa_result_t ret = MRAA_SUCCESS;
|
2016-03-18 16:35:26 -04:00
|
|
|
mraa_platform_t type = plat->platform_type;
|
2016-03-15 17:32:18 -04:00
|
|
|
char* buffer = NULL;
|
2016-03-23 11:31:51 +00:00
|
|
|
off_t file_size;
|
|
|
|
|
struct stat st;
|
2016-03-15 17:32:18 -04:00
|
|
|
int i = 0;
|
|
|
|
|
uint32_t subplat_num = 0;
|
2016-03-23 11:31:51 +00:00
|
|
|
int flock = open(imraa_lock_file, O_RDONLY);
|
|
|
|
|
if (flock == -1) {
|
|
|
|
|
syslog(LOG_ERR, "imraa: Failed to open lock file");
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
2016-03-15 17:32:18 -04:00
|
|
|
}
|
2016-03-23 11:31:51 +00:00
|
|
|
if (fstat(flock, &st) != 0 || (!S_ISREG(st.st_mode))) {
|
|
|
|
|
close(flock);
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
|
|
|
|
}
|
|
|
|
|
buffer = mmap(0, st.st_size, PROT_READ, MAP_SHARED, flock, 0);
|
|
|
|
|
close(flock);
|
|
|
|
|
if (buffer == MAP_FAILED) {
|
|
|
|
|
syslog(LOG_ERR, "imraa: lockfile read error");
|
|
|
|
|
return MRAA_ERROR_INVALID_RESOURCE;
|
2016-03-15 17:32:18 -04:00
|
|
|
}
|
|
|
|
|
json_object* jobj_lock = json_tokener_parse(buffer);
|
|
|
|
|
|
|
|
|
|
struct json_object* ioarray;
|
|
|
|
|
if (json_object_object_get_ex(jobj_lock, "Platform", &ioarray) == true &&
|
|
|
|
|
json_object_is_type(ioarray, json_type_array)) {
|
|
|
|
|
subplat_num = json_object_array_length(ioarray);
|
|
|
|
|
int id = -1;
|
|
|
|
|
const char* uartdev = NULL;
|
|
|
|
|
for (i = 0; i < subplat_num; i++) {
|
|
|
|
|
struct json_object *ioobj = json_object_array_get_idx(ioarray, i);
|
|
|
|
|
json_object_object_foreach(ioobj, key, val) {
|
|
|
|
|
if (strcmp(key, "id") == 0) {
|
|
|
|
|
id = atoi(json_object_get_string(val));
|
|
|
|
|
} else if (strcmp(key, "uart") == 0) {
|
|
|
|
|
uartdev = json_object_get_string(val);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-18 16:35:26 -04:00
|
|
|
if (id != -1 && id != MRAA_NULL_PLATFORM && id != MRAA_UNKNOWN_PLATFORM && uartdev != NULL) {
|
2016-03-15 17:32:18 -04:00
|
|
|
if (mraa_add_subplatform(id, uartdev) == MRAA_SUCCESS) {
|
|
|
|
|
syslog(LOG_NOTICE, "imraa: automatically added subplatform %d, %s", id, uartdev);
|
|
|
|
|
} else {
|
|
|
|
|
syslog(LOG_ERR, "imraa: Failed to add subplatform (%d on %s) from lockfile", id, uartdev);
|
|
|
|
|
}
|
|
|
|
|
id = -1;
|
|
|
|
|
uartdev = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2016-03-23 11:31:51 +00:00
|
|
|
ret = MRAA_ERROR_INVALID_RESOURCE;
|
2016-03-15 17:32:18 -04:00
|
|
|
}
|
2016-03-15 23:37:40 -04:00
|
|
|
json_object_put(jobj_lock);
|
2016-03-23 11:31:51 +00:00
|
|
|
munmap(buffer, st.st_size);
|
|
|
|
|
return ret;
|
2016-03-15 17:32:18 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
2016-05-23 13:55:57 +01:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mraa_to_upper(char* s)
|
|
|
|
|
{
|
|
|
|
|
char* t = s;
|
|
|
|
|
for (; *t; ++t) {
|
|
|
|
|
*t = toupper(*t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mraa_result_t
|
|
|
|
|
mraa_atoi(char* intStr, int* value)
|
|
|
|
|
{
|
|
|
|
|
char* end;
|
|
|
|
|
// here 10 determines the number base in which strol is to work
|
|
|
|
|
long val = strtol(intStr, &end, 10);
|
|
|
|
|
if (*end != '\0' || errno == ERANGE || end == intStr || val > INT_MAX || val < INT_MIN) {
|
|
|
|
|
*value = 0;
|
|
|
|
|
return MRAA_ERROR_UNSPECIFIED;
|
|
|
|
|
}
|
|
|
|
|
*value = (int) val;
|
|
|
|
|
return MRAA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mraa_result_t
|
|
|
|
|
mraa_init_io_helper(char** str, int* value, const char* delim)
|
|
|
|
|
{
|
|
|
|
|
// This function is a result of a repeated pattern within mraa_init_io
|
|
|
|
|
// when determining if a value can be derived from a string
|
|
|
|
|
char* token;
|
|
|
|
|
token = strsep(str, delim);
|
|
|
|
|
// check to see if empty string returned
|
|
|
|
|
if (token == NULL) {
|
|
|
|
|
*value = 0;
|
|
|
|
|
return MRAA_ERROR_NO_DATA_AVAILABLE;
|
|
|
|
|
}
|
|
|
|
|
return mraa_atoi(token, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void*
|
|
|
|
|
mraa_init_io(const char* desc)
|
|
|
|
|
{
|
|
|
|
|
const char* delim = "-";
|
|
|
|
|
int length = 0, raw = 0;
|
|
|
|
|
int pin = 0, id = 0;
|
|
|
|
|
// 256 denotes the maximum size of our buffer
|
|
|
|
|
// 8 denotes the maximum size of our type rounded to the nearest power of 2
|
|
|
|
|
// max size is 4 + 1 for the \0 = 5 rounded to 8
|
|
|
|
|
char buffer[256] = { 0 }, type[8] = { 0 };
|
|
|
|
|
char *token = 0, *str = 0;
|
2016-06-01 14:42:37 +01:00
|
|
|
if (desc == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2016-05-23 13:55:57 +01:00
|
|
|
length = strlen(desc);
|
|
|
|
|
// Check to see the length is less than or equal to 255 which means
|
|
|
|
|
// byte 256 is supposed to be \0
|
2016-06-01 14:42:37 +01:00
|
|
|
if (length > 255 || length == 0) {
|
2016-05-23 13:55:57 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
strncpy(buffer, desc, length);
|
|
|
|
|
|
|
|
|
|
str = buffer;
|
|
|
|
|
token = strsep(&str, delim);
|
|
|
|
|
length = strlen(token);
|
|
|
|
|
// Check to see they haven't given us a type whose length is greater than the
|
|
|
|
|
// largest type we know about
|
|
|
|
|
if (length > 4) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: An invalid IO type was provided");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
strncpy(type, token, length);
|
|
|
|
|
mraa_to_upper(type);
|
|
|
|
|
token = strsep(&str, delim);
|
|
|
|
|
// Check that they've given us more information than just the type
|
|
|
|
|
if (token == NULL) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Missing information after type");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// If we cannot convert the pin to a number maybe it says raw?
|
|
|
|
|
if (mraa_atoi(token, &pin) != MRAA_SUCCESS) {
|
|
|
|
|
mraa_to_upper(token);
|
|
|
|
|
if (strncmp(token, "RAW", 3)) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Description does not adhere to a known format");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
raw = 1;
|
|
|
|
|
}
|
|
|
|
|
if (!raw && str != NULL) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: More information than required was provided");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strncmp(type, "GPIO", 4) == 0) {
|
|
|
|
|
if (raw) {
|
|
|
|
|
if (mraa_init_io_helper(&str, &pin, delim) == MRAA_SUCCESS) {
|
|
|
|
|
return (void*) mraa_gpio_init_raw(pin);
|
|
|
|
|
}
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Invalid Raw description for GPIO");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_gpio_init(pin);
|
|
|
|
|
} else if (strncmp(type, "I2C", 3) == 0) {
|
|
|
|
|
if (raw) {
|
|
|
|
|
if (mraa_init_io_helper(&str, &pin, delim) == MRAA_SUCCESS) {
|
|
|
|
|
return (void*) mraa_i2c_init_raw(pin);
|
|
|
|
|
}
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Invalid Raw description for I2C");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_i2c_init(pin);
|
|
|
|
|
} else if (strncmp(type, "AIO", 3) == 0) {
|
|
|
|
|
if (raw) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Aio doesn't have a RAW mode");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_aio_init(pin);
|
|
|
|
|
} else if (strncmp(type, "PWM", 3) == 0) {
|
|
|
|
|
if (raw) {
|
|
|
|
|
if (mraa_init_io_helper(&str, &id, delim) != MRAA_SUCCESS) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Pwm, unable to convert the chip id string into a useable Int");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (mraa_init_io_helper(&str, &pin, delim) != MRAA_SUCCESS) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Pwm, unable to convert the pin string into a useable Int");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_pwm_init_raw(id, pin);
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_pwm_init(pin);
|
|
|
|
|
} else if (strncmp(type, "SPI", 3) == 0) {
|
|
|
|
|
if (raw) {
|
|
|
|
|
if (mraa_init_io_helper(&str, &id, delim) != MRAA_SUCCESS) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Spi, unable to convert the bus string into a useable Int");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (mraa_init_io_helper(&str, &pin, delim) != MRAA_SUCCESS) {
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Spi, unable to convert the cs string into a useable Int");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_spi_init_raw(id, pin);
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_spi_init(pin);
|
|
|
|
|
} else if (strncmp(type, "UART", 4) == 0) {
|
|
|
|
|
if (raw) {
|
|
|
|
|
return (void*) mraa_uart_init_raw(str);
|
|
|
|
|
}
|
|
|
|
|
return (void*) mraa_uart_init(pin);
|
|
|
|
|
}
|
|
|
|
|
syslog(LOG_ERR, "mraa_init_io: Invalid IO type given.");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|