dey-examples: remove old examples now superseeded by digiapix

This commit removes the following examples that were accessing
hardware interfaces:
 - dey-examples-adc
 - dey-examples-can
 - dey-examples-gpio-sysfs
 - dey-examples-spidev
 - dey-examples-watchdog

The recipe 'dey-examples-digiapix' builds similar examples that make
use of Digi's APIX for accessing the hardware. Add this recipe to images
 - dey-image-qt
 - core-image-base

Signed-off-by: Hector Palacios <hector.palacios@digi.com>

https://jira.digi.com/browse/DEL-5169
This commit is contained in:
Hector Palacios 2019-03-26 13:50:24 +01:00
parent 04aa734d75
commit 42d28c76cb
18 changed files with 6 additions and 2997 deletions

View File

@ -13,6 +13,10 @@ IMAGE_FEATURES += " \
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'dey-wireless', '', d)} \ ${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'dey-wireless', '', d)} \
" "
IMAGE_INSTALL = " \
dey-examples-digiapix \
"
# SDK features (for toolchains generated from an image with populate_sdk) # SDK features (for toolchains generated from an image with populate_sdk)
SDKIMAGE_FEATURES ?= "dev-pkgs dbg-pkgs staticdev-pkgs" SDKIMAGE_FEATURES ?= "dev-pkgs dbg-pkgs staticdev-pkgs"

View File

@ -58,4 +58,5 @@ export IMAGE_BASENAME = "dey-image-qt-${GRAPHICAL_BACKEND}"
CORE_IMAGE_EXTRA_INSTALL += " \ CORE_IMAGE_EXTRA_INSTALL += " \
${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'weston-init weston-examples gtk+3-demo clutter-1.0-examples', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'weston-init weston-examples gtk+3-demo clutter-1.0-examples', '', d)} \
${@bb.utils.contains('DISTRO_FEATURES', 'x11 wayland', 'weston-xwayland xterm', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'x11 wayland', 'weston-xwayland xterm', '', d)} \
dey-examples-digiapix \
" "

View File

@ -1,16 +0,0 @@
SUMMARY = "DEY examples: ADC test application"
SECTION = "examples"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
SRC_URI = "file://adc_sample"
S = "${WORKDIR}/adc_sample"
do_install() {
install -d ${D}${bindir}
install -m 0755 adc_sample ${D}${bindir}
}
PACKAGE_ARCH = "${MACHINE_ARCH}"
COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x)"

View File

@ -1,19 +0,0 @@
# Copyright (C) 2013-2018, Digi International Inc.
SUMMARY = "DEY examples: CAN bus test application"
SECTION = "examples"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
SRC_URI = "file://can_test"
S = "${WORKDIR}/can_test"
do_compile() {
${CC} -O2 -Wall ${LDFLAGS} can_test.c -o can_test -pthread
}
do_install() {
install -d ${D}${bindir}
install -m 0755 can_test ${D}${bindir}
}

View File

@ -1,19 +0,0 @@
# Copyright (C) 2013,2017 Digi International.
SUMMARY = "DEY examples: GPIO sysfs API test application"
SECTION = "examples"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
SRC_URI = "file://gpio_sysfs_test"
S = "${WORKDIR}/gpio_sysfs_test"
do_compile() {
${CC} -O2 -Wall ${LDFLAGS} gpio_sysfs_test.c sysfsgpio.c -o gpio_sysfs_test
}
do_install() {
install -d ${D}${bindir}
install -m 0755 gpio_sysfs_test ${D}${bindir}
}

View File

@ -1,21 +0,0 @@
# Copyright (C) 2013-2017, Digi International Inc.
SUMMARY = "DEY examples: SPI device driver test application"
SECTION = "examples"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
SRC_URI = "file://spidev_test"
S = "${WORKDIR}/spidev_test"
do_compile() {
${CC} -O2 -Wall ${LDFLAGS} spidev_test.c -o spidev_test
}
do_install() {
install -d ${D}${bindir}
install -m 0755 spidev_test ${D}${bindir}
}
PACKAGE_ARCH = "${MACHINE_ARCH}"

View File

@ -1,19 +0,0 @@
# Copyright (C) 2013,2017 Digi International.
SUMMARY = "DEY examples: watchdog test application"
SECTION = "examples"
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
SRC_URI = "file://watchdog_test"
S = "${WORKDIR}/watchdog_test"
do_compile() {
${CC} -O2 -Wall ${LDFLAGS} watchdog_test.c -o watchdog_test
}
do_install() {
install -d ${D}${bindir}
install -m 0755 watchdog_test ${D}${bindir}
}

View File

@ -1,11 +0,0 @@
CFLAGS = -Wall -g -D_GNU_SOURCE
all: adc_sample
adc_sample: adc_sample.o iio_utils.o
%.o: %.c iio_utils.h
.PHONY: clean
clean:
rm -f *.o adc_sample

View File

@ -1,359 +0,0 @@
/*
* ConnectCore 6UL ADC sample application.
*
* Copyright (c) 2016 Digi International Inc.
* All rights reserved.
*
* Partially based on iio_event_monitor.c from the tools/iio directory, of the
* linux kernel.
*
* 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.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <sys/ioctl.h>
#include "iio_utils.h"
#define ARRAY_SIZE(v) (sizeof(v) / sizeof((v)[0]))
#define BUFFER_LEN 20
#define ADC_SAMPLE_USAGE \
"Usage:\n" \
"adc_sample -t ADC_type -c channel [options]\n\n"
#define ADC_SAMPLE_FULL_USAGE \
"Usage:\n" \
"adc_sample -t ADC_type -c channel [options]\n\n" \
"Options:\n" \
" -t : ADC_type ('MX6UL', 'MCA-CC6UL', 'MX8X', 'MCA-CC8X', 'IOEXP')\n" \
" -c : channel number to read from\n" \
" -n : Number of samples (default: 1)\n" \
" -d : Delay (in ms) between samples (default: 1000)\n" \
" -v : Show output in V (otherwise raw ADC value is shown)\n" \
" -h : help\n\n"
enum adc_type {
ADC_TYPE_UNKNOWN,
ADC_TYPE_MX6UL,
ADC_TYPE_MCA_CC6UL,
ADC_TYPE_MX8X,
ADC_TYPE_MCA_CC8X,
ADC_TYPE_IOEXP,
};
struct adc_data {
enum adc_type type;
const char *name;
const char *dev_name;
unsigned int nbits;
};
struct adc_data adc_list[] = {
{
.type = ADC_TYPE_MX6UL,
.name = "MX6UL",
.dev_name = "2198000.adc",
.nbits = 12,
},
{
.type = ADC_TYPE_MCA_CC6UL,
.name = "MCA-CC6UL",
.dev_name = "mca-cc6ul-adc",
.nbits = 12,
},
{
.type = ADC_TYPE_MX8X,
.name = "MX8X",
.dev_name = "5a880000.adc",
.nbits = 12,
},
{
.type = ADC_TYPE_MCA_CC8X,
.name = "MCA-CC8X",
.dev_name = "mca-cc8x-adc",
.nbits = 12,
},
{
.type = ADC_TYPE_IOEXP,
.name = "IOEXP",
.dev_name = "mca-ioexp-adc",
.nbits = 12,
},
};
typedef struct adc {
struct adc_data *data;
char *chrdev_name;
char *sysfs_file;
char *sysfs_dir;
int dev_num;
unsigned long channel;
double voltage_scale;
} adc_t;
static void show_usage(int full)
{
fprintf(stdout, "%s", full ?
ADC_SAMPLE_FULL_USAGE : ADC_SAMPLE_USAGE);
}
static struct adc_data *get_adc_data(const char *type_str)
{
struct adc_data *data = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(adc_list); i++) {
if (!strcmp(adc_list[i].name, type_str)) {
data = &adc_list[i];
break;
}
}
return data;
}
static int read_adc_sample_sysfs(adc_t *adc, long int *val)
{
int fd, ret;
char buffer[BUFFER_LEN];
fd = open(adc->sysfs_file, O_RDONLY);
if (fd < 0) {
fprintf(stdout, "%s: failed to open %s\n",
__func__, adc->sysfs_file);
ret = fd;
goto just_ret;
}
ret = read(fd, buffer, BUFFER_LEN);
if (ret < 0) {
fprintf(stdout, "%s: failed to read ADC sample from %s (%d)\n",
__func__, adc->sysfs_file, ret);
goto close_ret;
}
if (ret == 0) {
fprintf(stdout, "%s: no data available in %s\n",
__func__, adc->sysfs_file);
ret = -ENODATA;
goto close_ret;
}
*val = strtol(buffer, NULL, 10);
ret = 0;
close_ret:
close(fd);
just_ret:
return ret;
}
static int read_voltage_scale(adc_t *adc, double *val)
{
int fd, ret;
char buffer[BUFFER_LEN];
char *temp;
/* Read the voltage scale from the sysfs */
ret = asprintf(&temp, "%s/in_voltage_scale", adc->sysfs_dir);
if (ret < 0) {
fprintf(stdout, "%s: failed to allocate memory\n", __func__);
return -ENOMEM;
}
fd = open(temp, O_RDONLY);
if (fd < 0) {
fprintf(stdout, "%s: failed to open %s\n", __func__, temp);
ret = fd;
goto free_temp;
}
ret = read(fd, buffer, BUFFER_LEN);
if (ret < 0) {
fprintf(stdout, "%s: failed to voltage scale from %s (%d)\n",
__func__, temp, ret);
goto close_fd;
}
if (ret == 0) {
fprintf(stdout, "%s: no data available in %s\n", __func__, temp);
ret = -ENODATA;
goto close_fd;
}
*val = atof(buffer);
close_fd:
close(fd);
free_temp:
free(temp);
return ret;
}
int main(int argc, char **argv)
{
adc_t *adc;
unsigned long nsamples = 1;
unsigned long delay_ms = 1000;
long sample_val;
bool raw = true;
int ret, opt, i;
if (argc <= 2) {
show_usage(1);
return EXIT_FAILURE;
}
adc = malloc(sizeof(adc_t));
if (!adc) {
fprintf(stdout, "Failed to allocate memory\n");
ret = -ENOMEM;
goto error_ret;
}
memset(adc, 0, sizeof(adc_t));
adc->channel = ~0;
while ((opt = getopt(argc, argv, "t:n:d:c:vh")) > 0) {
switch (opt) {
case 't':
adc->data = get_adc_data(optarg);
if (!adc->data) {
fprintf(stdout, "Unknown ADC type %s\n", optarg);
show_usage(0);
ret = EXIT_FAILURE;
goto error_ret2;
}
break;
case 'n':
nsamples = strtoul(optarg, NULL, 10);
if (!nsamples) {
fprintf(stdout,
"Invalid number of samples parameter (%s)\n",
optarg);
show_usage(0);
ret = EXIT_FAILURE;
goto error_ret2;
}
break;
case 'd':
delay_ms = strtoul(optarg, NULL, 10);
if (!delay_ms) {
fprintf(stdout,
"Invalid inter sample delay parameter (%s)\n",
optarg);
show_usage(0);
ret = EXIT_FAILURE;
goto error_ret2;
}
break;
case 'c':
adc->channel = strtoul(optarg, NULL, 10);
break;
case 'v':
raw = false;
break;
case 'h':
show_usage(1);
return EXIT_SUCCESS;
default:
show_usage(0);
return EXIT_FAILURE;
}
}
/* Check that the application params provide what we need */
if (!adc->data || adc->data->type == ADC_TYPE_UNKNOWN) {
fprintf(stdout, "ADC type must be provided\n");
show_usage(1);
ret = EXIT_FAILURE;
goto error_ret2;
}
if (adc->channel == ~0) {
fprintf(stdout, "ADC channel must be provided\n");
show_usage(1);
ret = EXIT_FAILURE;
goto error_ret2;
}
adc->dev_num = find_type_by_name(adc->data->dev_name, "iio:device");
if (adc->dev_num < 0) {
fprintf(stdout, "Failed to find iio:device for %s\n",
adc->data->dev_name);
ret = -ENODEV;
goto error_ret2;
}
ret = asprintf(&adc->chrdev_name, "/dev/iio:device%d", adc->dev_num);
if (ret < 0) {
fprintf(stdout, "Failed to allocate memory\n");
ret = -ENOMEM;
goto error_ret2;
}
ret = asprintf(&adc->sysfs_dir, "/sys/bus/iio/devices/iio:device%d",
adc->dev_num);
if (ret < 0) {
fprintf(stdout, "Failed to allocate memory\n");
ret = -ENOMEM;
goto error_ret3;
}
ret = asprintf(&adc->sysfs_file, "%s/in_voltage%lu_raw",
adc->sysfs_dir, adc->channel);
if (ret < 0) {
fprintf(stdout, "Failed to allocate memory\n");
ret = -ENOMEM;
goto error_ret4;
}
if (!raw) {
ret = read_voltage_scale(adc, &adc->voltage_scale);
if (ret < 0) {
goto error_ret5;
}
}
for (i = 0; i < nsamples; i++) {
ret = read_adc_sample_sysfs(adc, &sample_val);
if (ret)
break;
if (raw) {
fprintf(stdout, "Sample %i: 0x%04x\n",
i, (unsigned int)sample_val);
} else {
fprintf(stdout, "Sample %i: %.2f V\n",
i, sample_val * adc->voltage_scale / 1000);
}
usleep(delay_ms * 1000);
}
error_ret5:
free(adc->sysfs_file);
error_ret4:
free(adc->sysfs_dir);
error_ret3:
free(adc->chrdev_name);
error_ret2:
free(adc);
error_ret:
return ret;
}

View File

@ -1,669 +0,0 @@
/* 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.
*/
#ifndef _IIO_UTILS_H
#define _IIO_UTILS_H
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <dirent.h>
#include <errno.h>
#include <ctype.h>
#include "iio_utils.h"
const char *iio_dir = "/sys/bus/iio/devices/";
static char * const iio_direction[] = {
"in",
"out",
};
/**
* iioutils_break_up_name() - extract generic name from full channel name
* @full_name: the full channel name
* @generic_name: the output generic channel name
**/
int iioutils_break_up_name(const char *full_name,
char **generic_name)
{
char *current;
char *w, *r;
char *working, *prefix = "";
int i;
for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
if (!strncmp(full_name, iio_direction[i],
strlen(iio_direction[i]))) {
prefix = iio_direction[i];
break;
}
current = strdup(full_name + strlen(prefix) + 1);
working = strtok(current, "_\0");
w = working;
r = working;
while (*r != '\0') {
if (!isdigit(*r)) {
*w = *r;
w++;
}
r++;
}
*w = '\0';
asprintf(generic_name, "%s_%s", prefix, working);
free(current);
return 0;
}
/**
* iioutils_get_type() - find and process _type attribute data
* @is_signed: output whether channel is signed
* @bytes: output how many bytes the channel storage occupies
* @mask: output a bit mask for the raw data
* @be: big endian
* @device_dir: the iio device directory
* @name: the channel name
* @generic_name: the channel type name
**/
int iioutils_get_type(unsigned *is_signed,
unsigned *bytes,
unsigned *bits_used,
unsigned *shift,
uint64_t *mask,
unsigned *be,
const char *device_dir,
const char *name,
const char *generic_name)
{
FILE *sysfsfp;
int ret;
DIR *dp;
char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
char signchar, endianchar;
unsigned padint;
const struct dirent *ent;
ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
if (ret < 0) {
ret = -ENOMEM;
goto error_ret;
}
ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_scan_el_dir;
}
ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_builtname;
}
dp = opendir(scan_el_dir);
if (dp == NULL) {
ret = -errno;
goto error_free_builtname_generic;
}
while (ent = readdir(dp), ent != NULL)
/*
* Do we allow devices to override a generic name with
* a specific one?
*/
if ((strcmp(builtname, ent->d_name) == 0) ||
(strcmp(builtname_generic, ent->d_name) == 0)) {
ret = asprintf(&filename,
"%s/%s", scan_el_dir, ent->d_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_closedir;
}
sysfsfp = fopen(filename, "r");
if (sysfsfp == NULL) {
printf("failed to open %s\n", filename);
ret = -errno;
goto error_free_filename;
}
ret = fscanf(sysfsfp,
"%ce:%c%u/%u>>%u",
&endianchar,
&signchar,
bits_used,
&padint, shift);
if (ret < 0) {
printf("failed to pass scan type description\n");
ret = -errno;
goto error_close_sysfsfp;
}
*be = (endianchar == 'b');
*bytes = padint / 8;
if (*bits_used == 64)
*mask = ~0;
else
*mask = (1 << *bits_used) - 1;
if (signchar == 's')
*is_signed = 1;
else
*is_signed = 0;
fclose(sysfsfp);
free(filename);
filename = 0;
sysfsfp = 0;
}
error_close_sysfsfp:
if (sysfsfp)
fclose(sysfsfp);
error_free_filename:
if (filename)
free(filename);
error_closedir:
closedir(dp);
error_free_builtname_generic:
free(builtname_generic);
error_free_builtname:
free(builtname);
error_free_scan_el_dir:
free(scan_el_dir);
error_ret:
return ret;
}
int iioutils_get_param_float(float *output,
const char *param_name,
const char *device_dir,
const char *name,
const char *generic_name)
{
FILE *sysfsfp;
int ret;
DIR *dp;
char *builtname, *builtname_generic;
char *filename = NULL;
const struct dirent *ent;
ret = asprintf(&builtname, "%s_%s", name, param_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_ret;
}
ret = asprintf(&builtname_generic,
"%s_%s", generic_name, param_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_free_builtname;
}
dp = opendir(device_dir);
if (dp == NULL) {
ret = -errno;
goto error_free_builtname_generic;
}
while (ent = readdir(dp), ent != NULL)
if ((strcmp(builtname, ent->d_name) == 0) ||
(strcmp(builtname_generic, ent->d_name) == 0)) {
ret = asprintf(&filename,
"%s/%s", device_dir, ent->d_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_closedir;
}
sysfsfp = fopen(filename, "r");
if (!sysfsfp) {
ret = -errno;
goto error_free_filename;
}
fscanf(sysfsfp, "%f", output);
break;
}
error_free_filename:
if (filename)
free(filename);
error_closedir:
closedir(dp);
error_free_builtname_generic:
free(builtname_generic);
error_free_builtname:
free(builtname);
error_ret:
return ret;
}
/**
* bsort_channel_array_by_index() - reorder so that the array is in index order
*
**/
void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
int cnt)
{
struct iio_channel_info temp;
int x, y;
for (x = 0; x < cnt; x++)
for (y = 0; y < (cnt - 1); y++)
if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
temp = (*ci_array)[y + 1];
(*ci_array)[y + 1] = (*ci_array)[y];
(*ci_array)[y] = temp;
}
}
/**
* build_channel_array() - function to figure out what channels are present
* @device_dir: the IIO device directory in sysfs
* @
**/
int build_channel_array(const char *device_dir,
struct iio_channel_info **ci_array,
int *counter)
{
DIR *dp;
FILE *sysfsfp;
int count, i;
struct iio_channel_info *current;
int ret;
const struct dirent *ent;
char *scan_el_dir;
char *filename;
*counter = 0;
ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
if (ret < 0) {
ret = -ENOMEM;
goto error_ret;
}
dp = opendir(scan_el_dir);
if (dp == NULL) {
ret = -errno;
goto error_free_name;
}
while (ent = readdir(dp), ent != NULL)
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
"_en") == 0) {
ret = asprintf(&filename,
"%s/%s", scan_el_dir, ent->d_name);
if (ret < 0) {
ret = -ENOMEM;
goto error_close_dir;
}
sysfsfp = fopen(filename, "r");
if (sysfsfp == NULL) {
ret = -errno;
free(filename);
goto error_close_dir;
}
fscanf(sysfsfp, "%i", &ret);
if (ret == 1)
(*counter)++;
fclose(sysfsfp);
free(filename);
}
*ci_array = malloc(sizeof(**ci_array) * (*counter));
if (*ci_array == NULL) {
ret = -ENOMEM;
goto error_close_dir;
}
seekdir(dp, 0);
count = 0;
while (ent = readdir(dp), ent != NULL) {
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
"_en") == 0) {
int current_enabled = 0;
current = &(*ci_array)[count++];
ret = asprintf(&filename,
"%s/%s", scan_el_dir, ent->d_name);
if (ret < 0) {
ret = -ENOMEM;
/* decrement count to avoid freeing name */
count--;
goto error_cleanup_array;
}
sysfsfp = fopen(filename, "r");
if (sysfsfp == NULL) {
free(filename);
ret = -errno;
goto error_cleanup_array;
}
fscanf(sysfsfp, "%i", &current_enabled);
fclose(sysfsfp);
if (!current_enabled) {
free(filename);
count--;
continue;
}
current->scale = 1.0;
current->offset = 0;
current->name = strndup(ent->d_name,
strlen(ent->d_name) -
strlen("_en"));
if (current->name == NULL) {
free(filename);
ret = -ENOMEM;
goto error_cleanup_array;
}
/* Get the generic and specific name elements */
ret = iioutils_break_up_name(current->name,
&current->generic_name);
if (ret) {
free(filename);
goto error_cleanup_array;
}
ret = asprintf(&filename,
"%s/%s_index",
scan_el_dir,
current->name);
if (ret < 0) {
free(filename);
ret = -ENOMEM;
goto error_cleanup_array;
}
sysfsfp = fopen(filename, "r");
fscanf(sysfsfp, "%u", &current->index);
fclose(sysfsfp);
free(filename);
/* Find the scale */
ret = iioutils_get_param_float(&current->scale,
"scale",
device_dir,
current->name,
current->generic_name);
if (ret < 0)
goto error_cleanup_array;
ret = iioutils_get_param_float(&current->offset,
"offset",
device_dir,
current->name,
current->generic_name);
if (ret < 0)
goto error_cleanup_array;
ret = iioutils_get_type(&current->is_signed,
&current->bytes,
&current->bits_used,
&current->shift,
&current->mask,
&current->be,
device_dir,
current->name,
current->generic_name);
}
}
closedir(dp);
/* reorder so that the array is in index order */
bsort_channel_array_by_index(ci_array, *counter);
return 0;
error_cleanup_array:
for (i = count - 1; i >= 0; i--)
free((*ci_array)[i].name);
free(*ci_array);
error_close_dir:
closedir(dp);
error_free_name:
free(scan_el_dir);
error_ret:
return ret;
}
/**
* find_type_by_name() - function to match top level types by name
* @name: top level type instance name
* @type: the type of top level instance being sort
*
* Typical types this is used for are device and trigger.
**/
int find_type_by_name(const char *name, const char *type)
{
const struct dirent *ent;
int number, numstrlen;
FILE *nameFile;
DIR *dp;
char thisname[IIO_MAX_NAME_LENGTH];
char *filename;
dp = opendir(iio_dir);
if (dp == NULL) {
printf("No industrialio devices available\n");
return -ENODEV;
}
while (ent = readdir(dp), ent != NULL) {
if (strcmp(ent->d_name, ".") != 0 &&
strcmp(ent->d_name, "..") != 0 &&
strlen(ent->d_name) > strlen(type) &&
strncmp(ent->d_name, type, strlen(type)) == 0) {
numstrlen = sscanf(ent->d_name + strlen(type),
"%d",
&number);
/* verify the next character is not a colon */
if (strncmp(ent->d_name + strlen(type) + numstrlen,
":",
1) != 0) {
filename = malloc(strlen(iio_dir)
+ strlen(type)
+ numstrlen
+ 6);
if (filename == NULL) {
closedir(dp);
return -ENOMEM;
}
sprintf(filename, "%s%s%d/name",
iio_dir,
type,
number);
nameFile = fopen(filename, "r");
if (!nameFile) {
free(filename);
continue;
}
free(filename);
fscanf(nameFile, "%s", thisname);
fclose(nameFile);
if (strcmp(name, thisname) == 0) {
closedir(dp);
return number;
}
}
}
}
closedir(dp);
return -ENODEV;
}
int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
{
int ret = 0;
FILE *sysfsfp;
int test;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL)
return -ENOMEM;
sprintf(temp, "%s/%s", basedir, filename);
sysfsfp = fopen(temp, "w");
if (sysfsfp == NULL) {
printf("failed to open %s\n", temp);
ret = -errno;
goto error_free;
}
fprintf(sysfsfp, "%d", val);
fclose(sysfsfp);
if (verify) {
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
printf("failed to open %s\n", temp);
ret = -errno;
goto error_free;
}
fscanf(sysfsfp, "%d", &test);
fclose(sysfsfp);
if (test != val) {
printf("Possible failure in int write %d to %s%s\n",
val,
basedir,
filename);
ret = -1;
}
}
error_free:
free(temp);
return ret;
}
int write_sysfs_int(char *filename, char *basedir, int val)
{
return _write_sysfs_int(filename, basedir, val, 0);
}
int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
{
return _write_sysfs_int(filename, basedir, val, 1);
}
int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
{
int ret = 0;
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL) {
printf("Memory allocation failed\n");
return -ENOMEM;
}
sprintf(temp, "%s/%s", basedir, filename);
sysfsfp = fopen(temp, "w");
if (sysfsfp == NULL) {
printf("Could not open %s\n", temp);
ret = -errno;
goto error_free;
}
fprintf(sysfsfp, "%s", val);
fclose(sysfsfp);
if (verify) {
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
printf("could not open file to verify\n");
ret = -errno;
goto error_free;
}
fscanf(sysfsfp, "%s", temp);
fclose(sysfsfp);
if (strcmp(temp, val) != 0) {
printf("Possible failure in string write of %s "
"Should be %s "
"written to %s\%s\n",
temp,
val,
basedir,
filename);
ret = -1;
}
}
error_free:
free(temp);
return ret;
}
/**
* 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)
{
return _write_sysfs_string(filename, basedir, val, 1);
}
int write_sysfs_string(char *filename, char *basedir, char *val)
{
return _write_sysfs_string(filename, basedir, val, 0);
}
int read_sysfs_posint(char *filename, char *basedir)
{
int ret;
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL) {
printf("Memory allocation failed");
return -ENOMEM;
}
sprintf(temp, "%s/%s", basedir, filename);
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
ret = -errno;
goto error_free;
}
fscanf(sysfsfp, "%d\n", &ret);
fclose(sysfsfp);
error_free:
free(temp);
return ret;
}
int read_sysfs_float(char *filename, char *basedir, float *val)
{
int ret = 0;
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL) {
printf("Memory allocation failed");
return -ENOMEM;
}
sprintf(temp, "%s/%s", basedir, filename);
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
ret = -errno;
goto error_free;
}
fscanf(sysfsfp, "%f\n", val);
fclose(sysfsfp);
error_free:
free(temp);
return ret;
}
int read_sysfs_string(const char *filename, const char *basedir, char *str)
{
int ret = 0;
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
if (temp == NULL) {
printf("Memory allocation failed");
return -ENOMEM;
}
sprintf(temp, "%s/%s", basedir, filename);
sysfsfp = fopen(temp, "r");
if (sysfsfp == NULL) {
ret = -errno;
goto error_free;
}
fscanf(sysfsfp, "%s\n", str);
fclose(sysfsfp);
error_free:
free(temp);
return ret;
}
#endif /* _IIO_UTILS_H */

View File

@ -1,71 +0,0 @@
#ifndef _IIO_UTILS_H_
#define _IIO_UTILS_H_
/* 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.
*/
#include <stdint.h>
/* Made up value to limit allocation sizes */
#define IIO_MAX_NAME_LENGTH 30
#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
#define FORMAT_TYPE_FILE "%s_type"
extern const char *iio_dir;
/**
* struct iio_channel_info - information about a given channel
* @name: channel name
* @generic_name: general name for channel type
* @scale: scale factor to be applied for conversion to si units
* @offset: offset to be applied for conversion to si units
* @index: the channel index in the buffer output
* @bytes: number of bytes occupied in buffer output
* @mask: a bit mask for the raw output
* @is_signed: is the raw value stored signed
* @enabled: is this channel enabled
**/
struct iio_channel_info {
char *name;
char *generic_name;
float scale;
float offset;
unsigned index;
unsigned bytes;
unsigned bits_used;
unsigned shift;
uint64_t mask;
unsigned be;
unsigned is_signed;
unsigned location;
};
int iioutils_break_up_name(const char *full_name, char **generic_name);
int iioutils_get_type(unsigned *is_signed, unsigned *bytes,
unsigned *bits_used, unsigned *shift,
uint64_t *mask, unsigned *be,
const char *device_dir, const char *name,
const char *generic_name);
int iioutils_get_param_float(float *output, const char *param_name,
const char *device_dir, const char *name,
const char *generic_name);
void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
int build_channel_array(const char *device_dir,
struct iio_channel_info **ci_array, int *counter);
int find_type_by_name(const char *name, const char *type);
int write_sysfs_int(char *filename, char *basedir, int val);
int write_sysfs_int_and_verify(char *filename, char *basedir, int val);
int write_sysfs_string_and_verify(char *filename, char *basedir, char *val);
int write_sysfs_string(char *filename, char *basedir, char *val);
int read_sysfs_posint(char *filename, char *basedir);
int read_sysfs_float(char *filename, char *basedir, float *val);
int read_sysfs_string(const char *filename, const char *basedir, char *str);
#endif /* _IIO_UTILS_H_ */

View File

@ -1,571 +0,0 @@
/*
* can_test.c
*
* Copyright (C) 2009-2013 by Digi International Inc.
* All rights reserved.
*
* Description: CAN bus test application
*
* Based on canecho.c from socket-can project with following notice:
*
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Volkswagen nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* The provided data structures and external interfaces from this code
* are not restricted to be used by modules with a GPL compatible license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <net/if.h>
#include <getopt.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/can.h>
#include <linux/can/raw.h>
/* Application infos */
#define APP_NAME "can_test"
#define APP_VERSION "2.0"
#define pr_error(...) do { myprintf(ERROR, __VA_ARGS__); } while(0)
#define pr_warning(...) do { myprintf(WARNING, __VA_ARGS__); } while(0)
#define pr_info(...) do { myprintf(INFO, __VA_ARGS__); } while(0)
#define pr_debug(...) do { myprintf(DEBUG, __VA_ARGS__); } while(0)
#define pr_naked(...) do { printf(__VA_ARGS__); } while(0)
#define CAN_FRAME_SIZE sizeof(struct can_frame)
/* Operation modes */
typedef enum can_mode {
MODE_RECEIVER = 0,
MODE_TRANSMITTER,
} can_mode_t;
/* Used for the configuration varaible st.verbose */
typedef enum verbosity_t {
ERROR = 0,
WARNING,
INFO,
DEBUG,
} verbosity_t;
static verbosity_t selected_verbosity;
/* Internal structure */
struct opts_t {
char *iface;
canid_t *canids;
double *tx_rates;
int ids;
int extended;
unsigned char pattern;
int same_pattern;
can_mode_t mode;
int bytes;
unsigned long loops;
pthread_t *threads;
int xdelay;
};
static struct opts_t *main_opts;
/*
* Return the current time in seconds, using a double precision number.
* This code is coming from NetPipe (used for the time meassurement)
*/
inline static double now(void)
{
struct timeval tp;
gettimeofday(&tp, NULL);
return ((double)tp.tv_sec + (double)tp.tv_usec * 1e-6);
}
inline static void myprintf(verbosity_t level, const char *format, ...)
{
va_list lst;
char *marke;
int weg = 0;
if (level > selected_verbosity)
return;
switch (level) {
case ERROR:
marke = "ERROR";
weg = 1;
break;
case WARNING:
marke = "WARNING";
break;
case INFO:
marke = "INFO";
break;
case DEBUG:
marke = "DEBUG";
break;
default:
marke = "UNKNOW";
weg = 1;
break;
}
printf("[ %s ] ", marke);
va_start(lst, format);
vprintf(format, lst);
va_end(lst);
if (weg)
fflush(stdout);
}
static void print_version(void)
{
pr_naked("CAN test application v%s\n", APP_VERSION);
}
static void print_usage(void)
{
fprintf(stdout, "Usage: %s [OPTIONS]\n"
"%s %s Copyright Digi International Inc.\n\n"
"Data transfer using CAN-sockets\n"
"\n"
" -m, --master Run the test as master (trasmitter)\n"
" -D, --tx-delay= Delay (in usec.) between each TX frame\n"
" -i, --ids= IDs to use for the test (in hex)\n"
" -E, --extended Enables the extended ID support\n"
" -d, --device= Interface to use (e.g. can0)\n"
" -b, --bytes= Number of the data bytes per CAN-frame\n"
" -l, --loops= Number of test loops to execute\n"
" -p, --pattern= Data pattern to use (in hex)\n"
" -v, --verbosity= Verbosity level (3: loud | 0: quiet)\n"
" -V, --version Show version and exit\n"
" -h, --help Display usage information\n\n",
APP_NAME, APP_NAME, APP_VERSION);
}
/*
* Parse the input options and return the structure with the parse options.
* By errors return NULL
*/
static struct opts_t *process_options(int argc, char *argv[])
{
int opt_index, opt;
static const char *short_options = "mD:d:i:Ed:b:l:p:v:Vh";
struct opts_t *retval;
char *str1, *token;
char *savearg = NULL;
int cnt;
static const struct option long_options[] = {
{"master", no_argument, NULL, 'm'},
{"tx-delay", required_argument, NULL, 'D'},
{"ids", required_argument, NULL, 'i'},
{"extended", no_argument, NULL, 'E'},
{"device", required_argument, NULL, 'd'},
{"bytes", required_argument, NULL, 'b'},
{"loops", required_argument, NULL, 'l'},
{"pattern", required_argument, NULL, 'p'},
{"verbosity", required_argument, NULL, 'v'},
{"version", no_argument, NULL, 'V'},
{"help", no_argument, NULL, 'h'},
{0, 0, 0, 0},
};
/* Allocate the space for the internal data structure */
retval = calloc(1, sizeof(struct opts_t));
if (!retval) {
pr_error("calloc failed, %s\n", strerror(errno));
return NULL;
}
for (opt_index = 0;;) {
opt = getopt_long(argc, argv, short_options, long_options, &opt_index);
if (opt == EOF)
break;
switch (opt) {
case 'm':
retval->mode = MODE_TRANSMITTER;
break;
case 'D':
retval->xdelay = atoi(optarg);
break;
case 'i':
/* Obtain a copy of the passed argument first */
savearg = malloc(strlen(optarg) + 1);
if (!savearg) {
pr_error("malloc failed, %s\n", strerror(errno));
goto err_free_mem;
}
strncpy(savearg, optarg, strlen(optarg));
for (cnt = 0, str1 = optarg; (token = strtok(str1, ",")); str1 = NULL)
cnt++;
retval->canids = calloc(cnt, sizeof(canid_t));
retval->threads = calloc(cnt, sizeof(pthread_t));
retval->tx_rates = calloc(cnt, sizeof(ulong));
if (!retval->canids || !retval->threads || !retval->tx_rates) {
pr_error("calloc failed, %s\n", strerror(errno));
goto err_free_mem;
}
for (cnt = 0, str1 = savearg; (token = strtok(str1, ",")); str1 = NULL)
*(retval->canids + cnt++) = strtol(token, NULL, 16);
retval->ids = cnt;
/* Free savearg */
free(savearg);
savearg = NULL;
break;
case 'd':
retval->iface = optarg;
break;
case 'v':
selected_verbosity = atoi(optarg);
break;
case 'b':
retval->bytes = atoi(optarg);
break;
case 'l':
retval->loops = atol(optarg);
break;
case 'p':
retval->pattern = (unsigned char)strtol(optarg, NULL, 16);
retval->same_pattern = 1;
break;
case 'E':
retval->extended = 1;
break;
case 'V':
print_version();
goto err_free_mem;
case '?':
fprintf(stderr, "Unknown option -- %c\n", opt);
/* FALLTHROUGH */
case 'h':
default:
print_usage();
goto err_free_mem;
}
}
/* Sanity checks */
if (retval->bytes > 8) {
pr_error("Invalid data length %i\n", retval->bytes);
goto err_free_mem;
}
if (!retval->loops) {
pr_error("A valid number of test loops is required\n");
goto err_free_mem;
}
if (!retval->iface) {
pr_error("Need a CAN device for the test\n");
goto err_free_mem;
}
/* Print the information about the started mode */
if (retval->mode == MODE_TRANSMITTER)
pr_naked("Running the test as TRANSMITTER\n");
else
pr_naked("Running the test as RECEIVER\n");
pr_info("Testing with %i loops\n", retval->loops);
return retval;
err_free_mem:
free(savearg);
free(retval->threads);
free(retval->canids);
free(retval->tx_rates);
free(retval);
return NULL;
}
/*
* Depending on the selected command line options, the below function configures
* the CAN-frames in two different modes:
* - With a modified incremented frame Id (RTR or extended ID)
* - Modified data pattern (incremented with 0x11)
*/
static void update_frame(struct opts_t *opts, struct can_frame *frame, canid_t id,
unsigned char pattern)
{
frame->can_id = (opts->extended) ? (id | CAN_EFF_FLAG) : (id);
frame->can_dlc = opts->bytes;
/* Now update the data bytes of the frame */
memset(frame->data, pattern, opts->bytes);
}
/* Dump the content of a CAN-frame */
inline static void dump_frame(struct can_frame *frame, const char *name)
{
int cnt;
pr_naked("%s: ID 0x%03x | DLC 0x%02x | DATA ", name, frame->can_id, frame->can_dlc);
for (cnt = 0; cnt < frame->can_dlc; cnt++)
pr_naked("0x%02x ", frame->data[cnt]);
pr_naked("\n");
}
/* Return zero if the frames are equal, otherwise one */
static int compare_frames(struct can_frame *rcv, struct can_frame *exp)
{
if (rcv->can_id != exp->can_id)
return 1;
if (rcv->can_dlc != exp->can_dlc)
return 1;
return memcmp(rcv->data, exp->data, rcv->can_dlc);
}
static int xmit_frame(int sock, struct can_frame *frame)
{
return write(sock, frame, CAN_FRAME_SIZE);
}
/* The argument must be the CAN-ID for this thread */
static void *xmit_thread(void *arg)
{
int sock, fl;
int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
struct sockaddr_can addr;
struct ifreq ifr;
int loop, retop;
canid_t id;
struct can_frame txframe, rxframe;
struct can_filter rfilter;
unsigned char pattern;
double jetzt, time_delta;
ulong rate = 0;
/* Create the socket first */
if ((sock = socket(family, type, proto)) < 0) {
pr_error("socket() failed, %s\n", strerror(errno));
return NULL;
}
id = (canid_t) arg;
/* Check ID length */
if (id >= (1 << 29)) {
pr_error("ID 0x%x exceeds max number of bits (normal=11, extended=29)\n");
close(sock);
return NULL;
}
if (id >= (1 << 11) && !main_opts->extended) {
pr_error("ID 0x%x requires extended mode. Enable extended mode with '-E' option\n");
close(sock);
return NULL;
}
/*
* If started in receiver mode, then set the correct filter first.
* According to the documentation from (@TODO: Link) the filter matches if:
* <received id> & mask = id & mask
*/
if (main_opts->mode != MODE_TRANSMITTER) {
rfilter.can_id = id;
rfilter.can_mask = (main_opts->extended) ? CAN_EFF_MASK : CAN_SFF_MASK;
retop = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER,
&rfilter, /* sizeof(struct can_filter) */ 8);
if (retop) {
pr_error("Socket setup failed, %s\n", strerror(errno));
goto close_socket;
}
}
strcpy(ifr.ifr_name, main_opts->iface);
retop = ioctl(sock, SIOCGIFINDEX, &ifr);
if (retop < 0) {
pr_error("The IOCTL for `%s' failed, %s\n", main_opts->iface, strerror(errno));
goto close_socket;
}
addr.can_ifindex = ifr.ifr_ifindex;
addr.can_family = family;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
pr_error("bind() failed, %s\n", strerror(errno));
goto close_socket;
}
/* Configure the socket correctly */
fl = fcntl(sock, F_GETFD);
if (fcntl(sock, F_SETFD, fl | O_SYNC | O_NDELAY | O_NOCTTY | FD_CLOEXEC) == -1) {
pr_error("Socket config failed, %s\n", strerror(errno));
goto close_socket;
}
/* Set the initial pattern first */
pattern = main_opts->pattern;
jetzt = now();
for (loop = 1; loop <= main_opts->loops; loop++) {
/* Increment the pattern if not pattern was passed */
if (!main_opts->same_pattern)
pattern++;
/*
* Update the next CAN-frame
* The transmitter will send the frame and the receiver expects it
*/
update_frame(main_opts, &txframe, id, pattern);
/* In the transmitter mode only send the CAN-frame */
if (main_opts->mode == MODE_TRANSMITTER) {
pr_debug("Going to transmit the frame %i with the ID 0x%x\n",
loop, txframe.can_id);
retop = xmit_frame(sock, &txframe);
if (retop < 0) {
pr_error("write() returned with errors, %s\n", strerror(errno));
goto close_socket;
} else if (retop != CAN_FRAME_SIZE) {
pr_error("Couldn't send the %i bytes (%i sent)\n",
CAN_FRAME_SIZE, retop);
goto close_socket;
}
if (main_opts->xdelay)
usleep(main_opts->xdelay);
} else {
retop = read(sock, &rxframe, CAN_FRAME_SIZE);
if (retop < 0) {
pr_error("Read of CAN frame failed (loop %i), %s\n",
loop, strerror(errno));
goto close_socket;
}
/*
* Since we need to wait for the transmitter, restart the
* internal timer
*/
if (loop == 1)
jetzt = now();
pr_debug("Frame %i with ID 0x%x received\n", loop, rxframe.can_id);
if (compare_frames(&txframe, &rxframe)) {
pr_error("Different CAN-frames at loop %i\n", loop);
dump_frame(&txframe, "\t* EXPECTED");
dump_frame(&rxframe, "\t* RECEIVED");
goto close_socket;
}
}
}
/* Print some infos about the executed test */
time_delta = now() - jetzt;
if (main_opts->mode == MODE_TRANSMITTER) {
rate = main_opts->loops * main_opts->bytes / (time_delta);
pr_naked("ID 0x%03x : %lu Bps\n", id, rate);
} else
pr_naked("ID 0x%03x : %.4lg seconds\n", id, time_delta);
close_socket:
close(sock);
return (void *)rate;
}
int main(int argc, char **argv)
{
int retval = -1;
int cnt;
canid_t id;
pthread_t *thr;
/* Create the internal options */
if (!(main_opts = process_options(argc, argv)))
return EXIT_FAILURE;
/* And start the test threads */
for (cnt = 0; cnt < main_opts->ids; cnt++) {
id = *(main_opts->canids + cnt);
thr = main_opts->threads + cnt;
pr_info("Starting the thread for the ID 0x%x\n", id);
pthread_create(thr, NULL, xmit_thread, (void *)id);
}
/* Now wait for the threads */
for (cnt = 0; cnt < main_opts->ids; cnt++) {
/* @TODO: Pass the pointer for obtaining the transfer rate */
pthread_join(*(main_opts->threads + cnt), NULL);
}
/* @TODO: Print some test results: min and max values, etc. */
if (main_opts->mode == MODE_TRANSMITTER) {
}
retval = EXIT_SUCCESS;
free(main_opts->tx_rates);
free(main_opts->canids);
free(main_opts->threads);
free(main_opts);
return retval;
}

View File

@ -1,144 +0,0 @@
/*
* gpio_sysfs_test.c
*
* Copyright (C) 2011 by Digi International Inc.
* All rights reserved.
*
* 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.
*
* Description: GPIO SYSFS test application
*
*/
#include "sysfsgpio.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
static int run = 1;
#define ABORT_ON_ERROR(fn) if( fn < 0 ) abort()
#define RETURN_ON_ERROR(fn) if( fn < 0 ) return
void signal_handler(int sig)
{
switch (sig) {
case SIGHUP:
printf("hangup signal catched\n");
break;
case SIGTERM:
printf("terminate signal catched\n");
break;
case SIGINT:
printf("Interrupt signal catched\n");
break;
default:
printf("signal %d catched\n", sig);
break;
}
run = 0;
}
void print_settings(unsigned int gpio)
{
unsigned int active_low;
char edge[MAX_LEN];
sysfs_gpio_get_active_low(gpio, &active_low);
sysfs_gpio_get_edge(gpio, edge, sizeof(edge));
printf("GPIO %d: Active %s and %s edge\n", gpio, active_low ? "low"
: "high", edge);
}
int gpio_sysfs_test_loop(unsigned int gpioin, unsigned int gpiout, int loops)
{
int i;
int value = 0;
if (!run)
return -1;
print_settings(gpioin);
printf("Press the button (for %d events):\n",loops);
for (i = 0; (i < loops) && run; i++) {
ABORT_ON_ERROR (sysfs_gpio_poll(gpioin,-1 /* no timeout */));
ABORT_ON_ERROR(sysfs_gpio_set_value(gpiout,!value));
value = !value;
printf("Press %d\n", i+1);
}
return 0;
}
void poll_test(unsigned int gpioin, unsigned int gpioout)
{
char buf[MAX_LEN]="";
ABORT_ON_ERROR ( sysfs_gpio_set_direction( gpioin , 0 /* in */) );
ABORT_ON_ERROR ( sysfs_gpio_set_direction( gpioout , 1 /* out */) );
// Active low and rising edge
ABORT_ON_ERROR( sysfs_gpio_set_active_low( gpioin, 1 /*low*/) );
ABORT_ON_ERROR ( sysfs_gpio_set_edge( gpioin, "rising") );
RETURN_ON_ERROR( gpio_sysfs_test_loop(gpioin,gpioout,10) );
// Active low and falling edge
ABORT_ON_ERROR ( sysfs_gpio_set_edge( gpioin, "falling") );
RETURN_ON_ERROR( gpio_sysfs_test_loop(gpioin,gpioout,10) );
// Active low and both edges
ABORT_ON_ERROR ( sysfs_gpio_set_edge( gpioin, "both") );
sysfs_gpio_get_edge( gpioin , buf, sizeof(buf) );
if( !strcmp(buf,"both") )
RETURN_ON_ERROR( gpio_sysfs_test_loop(gpioin,gpioout,10) );
// Active high and rising edge
ABORT_ON_ERROR( sysfs_gpio_set_active_low( gpioin, 0 /*high*/) );
ABORT_ON_ERROR ( sysfs_gpio_set_edge( gpioin, "rising") );
RETURN_ON_ERROR( gpio_sysfs_test_loop(gpioin,gpioout,10) );
// Active high and falling edge
ABORT_ON_ERROR ( sysfs_gpio_set_edge( gpioin, "falling") );
RETURN_ON_ERROR( gpio_sysfs_test_loop(gpioin,gpioout,10) );
// Active high and both edges
ABORT_ON_ERROR ( sysfs_gpio_set_edge( gpioin, "both") );
sysfs_gpio_get_edge( gpioin , buf, sizeof(buf) );
if( !strcmp(buf,"both") )
RETURN_ON_ERROR( gpio_sysfs_test_loop(gpioin,gpioout,10) );
}
int main(int argc, char **argv, char **envp)
{
int gpioin;
int gpioout = -1;
if (argc < 2) {
printf("Usage: gpio-sysfs-test <gpio_in> [gpio_out]\n\n");
printf("Where gpio_in is a pushbutton and gpio_out an optional LED.\n");
exit(-1);
}
gpioin = atoi(argv[1]);
if(argv[2])
gpioout = atoi(argv[2]);
ABORT_ON_ERROR (sysfs_gpio_export(gpioin) );
ABORT_ON_ERROR (sysfs_gpio_export(gpioout) );
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGHUP, signal_handler);
poll_test(gpioin, gpioout);
sysfs_gpio_unexport(gpioin);
sysfs_gpio_unexport(gpioout);
return 0;
}

View File

@ -1,351 +0,0 @@
/*
* sysfsgpio.c
*
* Copyright (C) 2011 by Digi International Inc.
* All rights reserved.
*
* 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.
*
* Description: GPIO SYSFS API library.
*
*/
#include <poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "sysfsgpio.h"
int sysfs_gpio_export(int gpio)
{
int fd, len;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
if (fd < 0) {
perror("Error on GPIO export\n");
return fd;
}
len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
}
int sysfs_gpio_unexport(int gpio)
{
int fd, len;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
if (fd < 0) {
perror("Error on GPIO unexport");
return fd;
}
len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
}
int sysfs_gpio_set_direction(int gpio, unsigned int out)
{
int fd, len;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("Error setting GPIO direction\n");
return fd;
}
if (out)
write(fd, "out", 4);
else
write(fd, "in", 3);
close(fd);
return 0;
}
int sysfs_gpio_get_direction(int gpio, char * dir, int len)
{
int fd, length;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
length = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction",
gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("Error getting GPIO direction\n");
return fd;
}
memset(dir,0,len);
read(fd, dir, len);
dir[strlen(dir) - 1] = '\0';
if (strcmp(dir, "out") && strcmp(dir, "in")) {
perror("Error getting direction\n");
}
close(fd);
return 0;
}
int sysfs_gpio_set_active_low(int gpio, unsigned int low)
{
int fd, len;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/active_low", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("Error setting GPIO value\n");
return fd;
}
snprintf(buf, sizeof(buf), "%s", low ? "1" : "0");
write(fd, buf, 2);
close(fd);
return 0;
}
int sysfs_gpio_get_active_low(int gpio, unsigned int *value)
{
int fd, len;
char buf[MAX_LEN];
char ch;
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/active_low", gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("Error getting GPIO value\n");
return fd;
}
read(fd, &ch, 1);
if (ch != '0') {
*value = 1;
}
else {
*value = 0;
}
close(fd);
return 0;
}
int sysfs_gpio_set_value(int gpio, unsigned int value)
{
int fd, len;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("Error setting GPIO value\n");
return fd;
}
snprintf(buf, sizeof(buf), "%s", value ? "1" : "0");
write(fd, buf, 2);
close(fd);
return 0;
}
int sysfs_gpio_get_value(int gpio, unsigned int *value)
{
int fd, len;
char buf[MAX_LEN];
char ch;
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("Error getting GPIO value\n");
return fd;
}
read(fd, &ch, 1);
if (ch != '0') {
*value = 1;
}
else {
*value = 0;
}
close(fd);
return 0;
}
static int sysfs_gpio_fset_value(int fd, unsigned int value)
{
char buf[MAX_LEN];
snprintf(buf, sizeof(buf), "%s", value ? "1" : "0");
write(fd, buf, 2);
return fd;
}
static int sysfs_gpio_fget_value(int fd, unsigned int *value)
{
char buf;
read(fd, &buf, sizeof(char));
if (buf != '0') {
*value = 1;
}
else {
*value = 0;
}
return fd;
}
int sysfs_gpio_set_edge(int gpio, char *edge)
{
int fd, len;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("Error setting GPIO edge\n");
return fd;
}
write(fd, edge, strlen(edge) + 1);
close(fd);
return 0;
}
int sysfs_gpio_get_edge(int gpio, char *edge, int len)
{
int fd, length;
char buf[MAX_LEN];
if( gpio < 0 )
return 0;
length = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("Error setting GPIO edge\n");
return fd;
}
memset(edge,0,len);
read(fd, edge, len);
//Remove trailing newline
edge[strlen(edge) - 1] = '\0';
close(fd);
return 0;
}
int sysfs_gpio_poll(int gpio, unsigned int timeout)
{
int fd, len;
char buf[MAX_LEN];
struct pollfd pfd;
int ret = 0;
unsigned int inval;
if( gpio < 0 )
return 0;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("Error on GPIO open\n");
ret = -1;
goto error;
}
/* Edge triggers are relative to the last read by the application
* and not to the start of poll. Read here to avoid poll returning
* immediately.*/
read(fd, &buf, sizeof(char));
memset((void*) &pfd, 0, sizeof(pfd));
pfd.fd = fd;
pfd.events = POLLPRI;
ret = poll(&pfd, 1, timeout);
if (ret > 0) {
if (pfd.revents & POLLNVAL) {
printf("Return error event %x\n", pfd.revents);
ret = -1;
}
else if ((pfd.revents & POLLPRI)) {
sysfs_gpio_fget_value(fd, &inval);
}
else {
printf("Unhandled event %x\n", pfd.revents);
ret = -1;
}
}
else if (ret == 0) {
printf("Timeout on poll\n");
}
else {
perror("Error on poll\n");
ret = -1;
;
}
close(fd);
error: return ret;
}

View File

@ -1,38 +0,0 @@
/*
* sysfsgpio.h
*
* Copyright (C) 2011 by Digi International Inc.
* All rights reserved.
*
* 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.
*
* Description: GPIO SYSFS API header file.
*
*/
#ifndef SYSFSGPIO_H_
#define SYSFSGPIO_H_
#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define MAX_LEN 64
int sysfs_gpio_export(int gpio);
int sysfs_gpio_unexport(int gpio);
int sysfs_gpio_set_direction(int gpio, unsigned int out);
int sysfs_gpio_get_direction(int gpio, char * dir, int len);
int sysfs_gpio_set_active_low(int gpio, unsigned int low);
int sysfs_gpio_get_active_low(int gpio, unsigned int *value);
int sysfs_gpio_set_value(int gpio, unsigned int value);
int sysfs_gpio_get_value(int gpio, unsigned int *value);
int sysfs_gpio_set_edge(int gpio, char *edge);
int sysfs_gpio_get_edge(int gpio, char *edge, int len);
int sysfs_gpio_poll(int gpio, unsigned int timeout);
#endif /* SYSFSGPIO_H_ */

View File

@ -1,483 +0,0 @@
/*
* SPI testing utility (using spidev driver)
*
* Copyright (c) 2007 MontaVista Software, Inc.
* Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
*
* 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.
*
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static void pabort(const char *s)
{
perror(s);
abort();
}
static const char *device = "/dev/spidev1.1";
static uint32_t mode;
static uint8_t bits = 8;
static char *input_file;
static char *output_file;
static uint32_t speed = 500000;
static uint16_t delay;
static int verbose;
static int transfer_size;
static int iterations;
static int interval = 5; /* interval in seconds for showing transfer rate */
uint8_t default_tx[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x0D,
};
uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
char *input_tx;
static void hex_dump(const void *src, size_t length, size_t line_size,
char *prefix)
{
int i = 0;
const unsigned char *address = src;
const unsigned char *line = address;
unsigned char c;
printf("%s | ", prefix);
while (length-- > 0) {
printf("%02X ", *address++);
if (!(++i % line_size) || (length == 0 && i % line_size)) {
if (length == 0) {
while (i++ % line_size)
printf("__ ");
}
printf(" | "); /* right close */
while (line < address) {
c = *line++;
printf("%c", (c < 33 || c == 255) ? 0x2E : c);
}
printf("\n");
if (length > 0)
printf("%s | ", prefix);
}
}
}
/*
* Unescape - process hexadecimal escape character
* converts shell input "\x23" -> 0x23
*/
static int unescape(char *_dst, char *_src, size_t len)
{
int ret = 0;
int match;
char *src = _src;
char *dst = _dst;
unsigned int ch;
while (*src) {
if (*src == '\\' && *(src+1) == 'x') {
match = sscanf(src + 2, "%2x", &ch);
if (!match)
pabort("malformed input string");
src += 4;
*dst++ = (unsigned char)ch;
} else {
*dst++ = *src++;
}
ret++;
}
return ret;
}
static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
int ret;
int out_fd;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = len,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
if (mode & SPI_TX_QUAD)
tr.tx_nbits = 4;
else if (mode & SPI_TX_DUAL)
tr.tx_nbits = 2;
if (mode & SPI_RX_QUAD)
tr.rx_nbits = 4;
else if (mode & SPI_RX_DUAL)
tr.rx_nbits = 2;
if (!(mode & SPI_LOOP)) {
if (mode & (SPI_TX_QUAD | SPI_TX_DUAL))
tr.rx_buf = 0;
else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL))
tr.tx_buf = 0;
}
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
if (verbose)
hex_dump(tx, len, 32, "TX");
if (output_file) {
out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (out_fd < 0)
pabort("could not open output file");
ret = write(out_fd, rx, len);
if (ret != len)
pabort("not all bytes written to output file");
close(out_fd);
}
if (verbose)
hex_dump(rx, len, 32, "RX");
}
static void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3vpNR24SI]\n", prog);
puts(" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -b --bpw bits per word\n"
" -i --input input data from a file (e.g. \"test.bin\")\n"
" -o --output output data to a file (e.g. \"results.bin\")\n"
" -l --loop loopback\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
" -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n"
" -3 --3wire SI/SO signals shared\n"
" -v --verbose Verbose (show tx buffer)\n"
" -p Send data (e.g. \"1234\\xde\\xad\")\n"
" -N --no-cs no chip select\n"
" -R --ready slave pulls low to pause\n"
" -2 --dual dual transfer\n"
" -4 --quad quad transfer\n"
" -S --size transfer size\n"
" -I --iter iterations\n");
exit(1);
}
static void parse_opts(int argc, char *argv[])
{
while (1) {
static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
{ "input", 1, 0, 'i' },
{ "output", 1, 0, 'o' },
{ "loop", 0, 0, 'l' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "lsb", 0, 0, 'L' },
{ "cs-high", 0, 0, 'C' },
{ "3wire", 0, 0, '3' },
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ "dual", 0, 0, '2' },
{ "verbose", 0, 0, 'v' },
{ "quad", 0, 0, '4' },
{ "size", 1, 0, 'S' },
{ "iter", 1, 0, 'I' },
{ NULL, 0, 0, 0 },
};
int c;
c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR24p:vS:I:",
lopts, NULL);
if (c == -1)
break;
switch (c) {
case 'D':
device = optarg;
break;
case 's':
speed = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 'b':
bits = atoi(optarg);
break;
case 'i':
input_file = optarg;
break;
case 'o':
output_file = optarg;
break;
case 'l':
mode |= SPI_LOOP;
break;
case 'H':
mode |= SPI_CPHA;
break;
case 'O':
mode |= SPI_CPOL;
break;
case 'L':
mode |= SPI_LSB_FIRST;
break;
case 'C':
mode |= SPI_CS_HIGH;
break;
case '3':
mode |= SPI_3WIRE;
break;
case 'N':
mode |= SPI_NO_CS;
break;
case 'v':
verbose = 1;
break;
case 'R':
mode |= SPI_READY;
break;
case 'p':
input_tx = optarg;
break;
case '2':
mode |= SPI_TX_DUAL;
break;
case '4':
mode |= SPI_TX_QUAD;
break;
case 'S':
transfer_size = atoi(optarg);
break;
case 'I':
iterations = atoi(optarg);
break;
default:
print_usage(argv[0]);
break;
}
}
if (mode & SPI_LOOP) {
if (mode & SPI_TX_DUAL)
mode |= SPI_RX_DUAL;
if (mode & SPI_TX_QUAD)
mode |= SPI_RX_QUAD;
}
}
static void transfer_escaped_string(int fd, char *str)
{
size_t size = strlen(str);
uint8_t *tx;
uint8_t *rx;
tx = malloc(size);
if (!tx)
pabort("can't allocate tx buffer");
rx = malloc(size);
if (!rx)
pabort("can't allocate rx buffer");
size = unescape((char *)tx, str, size);
transfer(fd, tx, rx, size);
free(rx);
free(tx);
}
static void transfer_file(int fd, char *filename)
{
ssize_t bytes;
struct stat sb;
int tx_fd;
uint8_t *tx;
uint8_t *rx;
if (stat(filename, &sb) == -1)
pabort("can't stat input file");
tx_fd = open(filename, O_RDONLY);
if (tx_fd < 0)
pabort("can't open input file");
tx = malloc(sb.st_size);
if (!tx)
pabort("can't allocate tx buffer");
rx = malloc(sb.st_size);
if (!rx)
pabort("can't allocate rx buffer");
bytes = read(tx_fd, tx, sb.st_size);
if (bytes != sb.st_size)
pabort("failed to read input file");
transfer(fd, tx, rx, sb.st_size);
free(rx);
free(tx);
close(tx_fd);
}
static uint64_t _read_count;
static uint64_t _write_count;
static void show_transfer_rate(void)
{
static uint64_t prev_read_count, prev_write_count;
double rx_rate, tx_rate;
rx_rate = ((_read_count - prev_read_count) * 8) / (interval*1000.0);
tx_rate = ((_write_count - prev_write_count) * 8) / (interval*1000.0);
printf("rate: tx %.1fkbps, rx %.1fkbps\n", rx_rate, tx_rate);
prev_read_count = _read_count;
prev_write_count = _write_count;
}
static void transfer_buf(int fd, int len)
{
uint8_t *tx;
uint8_t *rx;
int i;
tx = malloc(len);
if (!tx)
pabort("can't allocate tx buffer");
for (i = 0; i < len; i++)
tx[i] = random();
rx = malloc(len);
if (!rx)
pabort("can't allocate rx buffer");
transfer(fd, tx, rx, len);
_write_count += len;
_read_count += len;
if (mode & SPI_LOOP) {
if (memcmp(tx, rx, len)) {
fprintf(stderr, "transfer error !\n");
hex_dump(tx, len, 32, "TX");
hex_dump(rx, len, 32, "RX");
exit(1);
}
}
free(rx);
free(tx);
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
parse_opts(argc, argv);
fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
printf("spi mode: 0x%x\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
if (input_tx && input_file)
pabort("only one of -p and --input may be selected");
if (input_tx)
transfer_escaped_string(fd, input_tx);
else if (input_file)
transfer_file(fd, input_file);
else if (transfer_size) {
struct timespec last_stat;
clock_gettime(CLOCK_MONOTONIC, &last_stat);
while (iterations-- > 0) {
struct timespec current;
transfer_buf(fd, transfer_size);
clock_gettime(CLOCK_MONOTONIC, &current);
if (current.tv_sec - last_stat.tv_sec > interval) {
show_transfer_rate();
last_stat = current;
}
}
printf("total: tx %.1fKB, rx %.1fKB\n",
_write_count/1024.0, _read_count/1024.0);
} else
transfer(fd, default_tx, default_rx, sizeof(default_tx));
close(fd);
return ret;
}

View File

@ -1,199 +0,0 @@
/*
* watchdog_test.c
*
* Copyright (C) 2009-2013 by Digi International Inc.
* All rights reserved.
*
* 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.
*
* Description: Watchdog test application
*
*/
#include <fcntl.h>
#include <linux/types.h>
#include <linux/watchdog.h> /* WDIOC_SETTIMEOUT */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define PROGRAM "wd_test"
#define VERSION "2.0"
#define WD_DEVICE_FILE "/dev/watchdog"
#define wd_test_usage \
"[-t timeout (2)] [-d dead | disable (dead)] [-s write | ioctl (write)] [-n test_time (60)]\n"
#define wd_test_full_usage \
"wd_test [options]\n\n" \
"Tests the hardware watchdog\n" \
"Options:\n" \
" -t : timeout in seconds (default 2)\n" \
" -d : dead | disable, action when the test finishs (default dead)\n" \
" -s : write | ioctl, system call used to kick the watchdog (default write)\n" \
" -n : test duration in seconds (default 60)\n" \
" -h : help\n\n"
/*
* Function: wd_test_banner
* Description: print message
*/
static void wd_test_banner(void)
{
fprintf(stdout, "%s %s Copyright Digi International Inc.\n\n"
"Watchdog test/demo application\n\n", PROGRAM, VERSION);
}
/*
* Function: exit_error
* Description: print error message and exit
*/
static void exit_error(char *error_msg, int exit_val)
{
if (error_msg != NULL)
fprintf(stderr, "%s", error_msg);
exit(exit_val);
}
/*
* Function: show_usage_exit
* Description: print usage information and exit
*/
static void show_usage_exit(int exit_val, int full)
{
if (full) {
wd_test_banner();
fprintf(stdout, "%s", wd_test_full_usage);
} else {
fprintf(stdout, "%s", wd_test_usage);
}
exit_error(NULL, exit_val);
}
/*
* Function: wd_keep_alive
* Description: kick the watchdog using write or ioctl depending on the parameter
*/
static void wd_keep_alive(int fd, int system_call)
{
int dummy;
if (system_call) {
if (ioctl(fd, WDIOC_KEEPALIVE, &dummy) < 0) {
perror("ioctl");
printf("Unable to kick the watchdog.\n");
}
} else {
write(fd, "\0", 1);
}
}
/*
* Function: main
* Description: application's main function
*/
int main(int argc, char *argv[])
{
int opt;
int wd_timeout = 2;
int wd_disable = 0;
int wd_syscall = 0;
int wd_test_time = 60;
int wd_fd;
if (argc > 1) {
while ((opt = getopt(argc, argv, "t:d:s:n:h")) > 0) {
switch (opt) {
case 't':
wd_timeout = atoi(optarg);
break;
case 'n':
wd_test_time = atoi(optarg);
break;
case 'd':
if (!strcmp(optarg, "dead")) {
wd_disable = 0;
} else if (!strcmp(optarg, "disable")) {
wd_disable = 1;
} else {
show_usage_exit(EXIT_FAILURE, 0);
}
break;
case 's':
if (!strcmp(optarg, "write")) {
wd_syscall = 0;
} else if (!strcmp(optarg, "ioctl")) {
wd_syscall = 1;
} else {
show_usage_exit(EXIT_FAILURE, 0);
}
break;
case 'h':
default:
show_usage_exit((opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE, 1);
}
}
}
wd_test_banner();
/* Open watchdog, this will start the watchdog counters */
wd_fd = open(WD_DEVICE_FILE, O_RDWR);
if (wd_fd < 0) {
perror(WD_DEVICE_FILE);
exit(EXIT_FAILURE);
}
printf("Watchdog (%s) opened and started\n", WD_DEVICE_FILE);
if (ioctl(wd_fd, WDIOC_SETTIMEOUT, &wd_timeout) < 0) {
perror("ioctl");
close(wd_fd);
show_usage_exit(EXIT_FAILURE, 0);
}
printf(" -Setting watchdog timeout to %d (sec)\n", wd_timeout);
printf(" -Test will finish with %s\n",
wd_disable ? "watchdog disabled" : "board reset");
printf("\n");
while (wd_test_time) {
wd_keep_alive(wd_fd, wd_syscall);
sleep(1);
wd_test_time--;
printf("\r Remaining time: %d ", wd_test_time);
fflush(stdout);
}
/* Kick it for the last time, so that the last sleep() does
* not affect the programmed reset time.
*/
wd_keep_alive(wd_fd, wd_syscall);
printf("\n\n");
if (wd_disable) {
wd_timeout = WDIOS_DISABLECARD;
if (ioctl(wd_fd, WDIOC_SETOPTIONS, &wd_timeout) < 0) {
perror("ioctl");
printf("Unable to disable watchdog. System will reset\n");
}
else {
printf("Disabling watchdog\n");
}
} else {
printf("Sayonara baby...");
}
printf("\n");
fflush(stdout);
close(wd_fd);
return EXIT_SUCCESS;
}

View File

@ -1,4 +1,4 @@
# Copyright (C) 2013-2018, Digi International Inc. # Copyright (C) 2013-2019, Digi International Inc.
SUMMARY = "DEY examples packagegroup" SUMMARY = "DEY examples packagegroup"
@ -15,13 +15,9 @@ RDEPENDS_${PN} = "\
${@bb.utils.contains("MACHINE_FEATURES", "bluetooth", "dey-examples-hdp", "", d)} \ ${@bb.utils.contains("MACHINE_FEATURES", "bluetooth", "dey-examples-hdp", "", d)} \
${@bb.utils.contains("MACHINE_FEATURES", "cryptochip", "dey-examples-cryptochip", "", d)} \ ${@bb.utils.contains("MACHINE_FEATURES", "cryptochip", "dey-examples-cryptochip", "", d)} \
awsiotsdk-demo \ awsiotsdk-demo \
dey-examples-can \
dey-examples-cloudconnector \ dey-examples-cloudconnector \
dey-examples-digiapix \ dey-examples-digiapix \
dey-examples-gpio-sysfs \
dey-examples-rtc \ dey-examples-rtc \
dey-examples-spidev \
dey-examples-watchdog \
" "
RDEPENDS_${PN}_append_ccimx6 = "\ RDEPENDS_${PN}_append_ccimx6 = "\
@ -30,13 +26,11 @@ RDEPENDS_${PN}_append_ccimx6 = "\
" "
RDEPENDS_${PN}_append_ccimx6ul = "\ RDEPENDS_${PN}_append_ccimx6ul = "\
dey-examples-adc \
dey-examples-adc-cmp \ dey-examples-adc-cmp \
dey-examples-tamper \ dey-examples-tamper \
" "
RDEPENDS_${PN}_append_ccimx8x = "\ RDEPENDS_${PN}_append_ccimx8x = "\
dey-examples-adc \
dey-examples-adc-cmp \ dey-examples-adc-cmp \
dey-examples-tamper \ dey-examples-tamper \
dey-examples-v4l2 \ dey-examples-v4l2 \