Private
Public Access
2
0

usb: Skeleton platform code for FTDI FT4222 USB to i2c bridge

Signed-off-by: Henry Bruce <henry.bruce@intel.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
Henry Bruce
2015-05-27 15:36:46 -07:00
committed by Brendan Le Foll
parent 22a930e39e
commit 8f48df0533
15 changed files with 710 additions and 54 deletions

View File

@@ -54,6 +54,7 @@ option (BUILDSWIG "Build swig modules." ON)
option (BUILDSWIGPYTHON "Build swig python modules." ON)
option (BUILDSWIGNODE "Build swig node modules." ON)
option (BUILDSWIGJAVA "Build Java API." OFF)
option (USBPLAT "Detection USB platform." ON)
option (IPK "Generate IPK using CPack" OFF)
option (RPM "Generate RPM using CPack" OFF)
option (BUILDPYTHON3 "Use python3 for building/installing" OFF)

View File

@@ -29,6 +29,14 @@
#define MRAA_PLATFORM_NAME_MAX_SIZE 64
#define MRAA_PIN_NAME_SIZE 12
#define MRAA_SUB_PLATFORM_BIT_SHIFT 9
#define MRAA_SUB_PLATFORM_MASK (1<<MRAA_SUB_PLATFORM_BIT_SHIFT)
#define MRAA_IS_ON_SUB_PLATFORM(pin_or_bus) (((pin_or_bus)|MRAA_SUB_PLATFORM_MASK) != 0)
#define MRAA_USE_SUB_PLATFORM(pin_or_bus) ((pin_or_bus)|MRAA_SUB_PLATFORM_MASK)
#define MRAA_GET_SUB_PLATFORM_INDEX(pin_or_bus) ((pin_or_bus)&(~MRAA_SUB_PLATFORM_MASK))
/** @file
*
* This file defines the basic shared values for libmraa
@@ -176,6 +184,14 @@ int mraa_get_i2c_bus_id(unsigned int i2c_bus);
*/
char* mraa_get_pin_name(int pin);
/**
* Get default i2c bus, board must be initialised.
*
* @return int default i2c bus index
*/
int mraa_get_default_2c_bus();
#ifdef __cplusplus
}
#endif

View File

@@ -47,6 +47,9 @@ typedef enum {
MRAA_BANANA = 7, /**< Allwinner A20 based Banana Pi and Banana Pro */
MRAA_INTEL_NUC5 = 8, /**< The Intel 5th generations Broadwell NUCs */
// USB platform extenders start at 256
MRAA_FTDI_FT4222 = 256, /**< FTDI FT4222 USB to i2c bridge */
MRAA_UNKNOWN_PLATFORM =
99 /**< An unknown platform type, typically will load INTEL_GALILEO_GEN1 */
} mraa_platform_t;
@@ -231,6 +234,8 @@ typedef enum {
MRAA_UART_PARITY_SPACE = 4
} mraa_uart_parity_t;
#ifdef __cplusplus
}
#endif

View File

@@ -47,8 +47,23 @@ typedef struct {
mraa_result_t (*gpio_mmap_setup) (mraa_gpio_context dev, mraa_boolean_t en);
mraa_result_t (*i2c_init_pre) (unsigned int bus);
mraa_result_t (*i2c_init_bus_replace) (mraa_i2c_context dev);
mraa_i2c_context (*i2c_init_raw_replace) (unsigned int bus);
mraa_result_t (*i2c_init_post) (mraa_i2c_context dev);
mraa_result_t (*i2c_set_frequency_replace) (mraa_i2c_context dev, mraa_i2c_mode_t mode);
mraa_result_t (*i2c_address_replace) (mraa_i2c_context dev, uint8_t addr);
int (*i2c_read_replace) (mraa_i2c_context dev, uint8_t* data, int length);
uint8_t (*i2c_read_byte_replace) (mraa_i2c_context dev);
uint8_t (*i2c_read_byte_data_replace) (mraa_i2c_context dev, const uint8_t command);
uint16_t (*i2c_read_word_data_replace) (mraa_i2c_context dev, const uint8_t command);
int (*i2c_read_bytes_data_replace) (mraa_i2c_context dev, uint8_t command, uint8_t* data, int length);
mraa_result_t (*i2c_write_replace) (mraa_i2c_context dev, const uint8_t* data, int length);
mraa_result_t (*i2c_write_byte_replace) (mraa_i2c_context dev, uint8_t data);
mraa_result_t (*i2c_write_byte_data_replace) (mraa_i2c_context dev, const uint8_t data, const uint8_t command);
mraa_result_t (*i2c_write_word_data_replace) (mraa_i2c_context dev, const uint16_t data, const uint8_t command);
mraa_result_t (*i2c_stop_replace) (mraa_i2c_context dev);
mraa_result_t (*aio_get_valid_fp) (mraa_aio_context dev);
mraa_result_t (*aio_init_pre) (unsigned int aio);

51
include/mraa_func.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Author: Henry Bruce <henry.bruce@intel.com>
* Copyright (c) 2015 Intel Corporation.
*
* 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.
*/
#pragma once
#include "common.h"
#include "mraa.h"
#include "types.h"
typedef struct {
mraa_i2c_context (*i2c_init_raw) (unsigned int bus);
mraa_result_t (*i2c_frequency) (mraa_i2c_context dev, mraa_i2c_mode_t mode);
mraa_result_t (*i2c_address) (mraa_i2c_context dev, uint8_t addr);
int (*i2c_read) (mraa_i2c_context dev, uint8_t* data, int length);
uint8_t (*i2c_read_byte) (mraa_i2c_context dev);
uint8_t (*i2c_read_byte_data) (mraa_i2c_context dev, const uint8_t command);
uint16_t (*i2c_read_word_data) (mraa_i2c_context dev, const uint8_t command);
int (*i2c_read_bytes_data) (mraa_i2c_context dev, uint8_t command, uint8_t* data, int length);
mraa_result_t (*i2c_write) (mraa_i2c_context dev, const uint8_t* data, int length);
mraa_result_t (*i2c_write_byte) (mraa_i2c_context dev, const uint8_t data);
mraa_result_t (*i2c_write_byte_data) (mraa_i2c_context dev, const uint8_t data, const uint8_t command);
mraa_result_t (*i2c_write_word_data) (mraa_i2c_context dev, const uint16_t data, const uint8_t command);
mraa_result_t (*i2c_stop) (mraa_i2c_context dev);
} mraa_i2c_func_t;
typedef struct {
mraa_i2c_func_t* i2c;
} mraa_func_t;

View File

@@ -59,6 +59,13 @@ mraa_platform_t mraa_x86_platform();
*/
mraa_platform_t mraa_arm_platform();
/**
* runtime detect running usb platform extender
*
* @return mraa_platform_t of the detected platform extender
*/
mraa_platform_t mraa_usb_platform_extender(mraa_board_t* board);
/**
* helper function to check if file exists
*

View File

@@ -27,6 +27,8 @@
#include "common.h"
#include "mraa.h"
#include "mraa_func.h"
#include "mraa_adv_func.h"
// general status failures for internal functions
#define MRAA_PLATFORM_NO_INIT -3
@@ -59,7 +61,9 @@ struct _i2c {
int busnum; /**< the bus number of the /dev/i2c-* device */
int fh; /**< the file handle to the /dev/i2c-* device */
int addr; /**< the address of the i2c slave */
unsigned long funcs;
unsigned long funcs; /**< /dev/i2c-* device capabilities as per https://www.kernel.org/doc/Documentation/i2c/functionality */
void *handle; /**< generic handle for non-standard drivers that don't use file descriptors */
mraa_adv_func_t* func_table;
/*@}*/
};
@@ -189,6 +193,7 @@ typedef struct {
unsigned int bus_id; /**< ID as exposed in the system */
unsigned int scl; /**< i2c SCL */
unsigned int sda; /**< i2c SDA */
// mraa_drv_api_t drv_type; /**< Driver type */
/*@}*/
} mraa_i2c_bus_t;
@@ -222,7 +227,8 @@ typedef struct {
/**
* A Structure representing a platform/board.
*/
typedef struct {
typedef struct _board_t {
/*@{*/
unsigned int phy_pin_count; /**< The Total IO pins on board */
unsigned int gpio_count; /**< GPIO Count */
@@ -243,5 +249,9 @@ typedef struct {
int pwm_min_period; /**< Minimum period in us */
const char* platform_name; /**< Platform Name pointer */
mraa_pininfo_t* pins; /**< Pointer to pin array */
mraa_adv_func_t* adv_func; /**< Pointer to advanced function disptach table */
struct _board_t* sub_platform; /**< Pointer to sub platform */
/*@}*/
} mraa_board_t;

40
include/usb/ftdi_ft4222.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* Author: Henry Bruce <henry.bruce@intel.com>
* Copyright (c) 2015 Intel Corporation.
*
* 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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "mraa_internal.h"
mraa_result_t mraa_ftdi_ft4222_init();
mraa_result_t mraa_ftdi_ft4222_get_version(unsigned int* versionChip, unsigned int* versionLib);
mraa_board_t* mraa_ftdi_ft4222(mraa_board_t* board);
#ifdef __cplusplus
}
#endif

View File

@@ -35,6 +35,8 @@ set (mraa_LIB_ARM_SRCS_NOAUTO
${PROJECT_SOURCE_DIR}/src/arm/banana.c
)
set (mraa_LIBS ${CMAKE_THREAD_LIBS_INIT})
if (X86PLAT)
add_subdirectory(x86)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DX86PLAT=1")
@@ -45,6 +47,13 @@ if (ARMPLAT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DARMPLAT=1")
endif()
if (USBPLAT)
add_subdirectory(usb)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSBPLAT=1")
set (mraa_LIBS ${mraa_LIBS} ft4222)
endif()
set (mraa_LIB_SRCS
${mraa_LIB_PLAT_SRCS_NOAUTO}
# autogenerated version file
@@ -57,7 +66,9 @@ set (mraa_LIB_GLOB_HEADERS
)
add_library (mraa SHARED ${mraa_LIB_SRCS})
target_link_libraries (mraa ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (mraa ${mraa_LIBS})
set_target_properties(
mraa

View File

@@ -37,6 +37,10 @@
#include <sys/ioctl.h>
#include "linux/i2c-dev.h"
// FIXME: Nasty macro to test for presence of function in context structure function table
#define IS_FUNC_DEFINED(dev, func) (dev != NULL && dev->func_table != NULL && dev->func_table->func != NULL)
typedef union i2c_smbus_data_union {
uint8_t byte; ///< data byte
unsigned short word; ///< data short word
@@ -51,6 +55,9 @@ typedef struct i2c_smbus_ioctl_data_struct {
i2c_smbus_data_t* data; ///< data
} i2c_smbus_ioctl_data_t;
static mraa_adv_func_t* func_table;
int
mraa_i2c_smbus_access(int fh, uint8_t read_write, uint8_t command, int size, i2c_smbus_data_t* data)
{
@@ -67,71 +74,94 @@ mraa_i2c_smbus_access(int fh, uint8_t read_write, uint8_t command, int size, i2c
mraa_i2c_context
mraa_i2c_init(int bus)
{
if (plat == NULL) {
mraa_board_t* board = plat;
if (board == NULL) {
syslog(LOG_ERR, "i2c: Platform Not Initialised");
return NULL;
}
if (plat->i2c_bus_count == 0) {
if (MRAA_IS_ON_SUB_PLATFORM(bus)) {
syslog(LOG_NOTICE, "i2c: Using sub platform");
board = board->sub_platform;
if (board == NULL) {
syslog(LOG_ERR, "i2c: Sub platform Not Initialised");
return NULL;
}
bus = MRAA_GET_SUB_PLATFORM_INDEX(bus);
}
if (board->i2c_bus_count == 0) {
syslog(LOG_ERR, "No i2c buses defined in platform");
return NULL;
}
if (bus >= plat->i2c_bus_count) {
if (bus >= board->i2c_bus_count) {
syslog(LOG_ERR, "Above i2c bus count");
return NULL;
}
if (plat->i2c_bus[bus].bus_id == -1) {
if (board->i2c_bus[bus].bus_id == -1) {
syslog(LOG_ERR, "Invalid i2c bus, moving to default i2c bus");
bus = plat->def_i2c_bus;
bus = board->def_i2c_bus;
}
int pos = plat->i2c_bus[bus].sda;
if (plat->pins[pos].i2c.mux_total > 0) {
if (mraa_setup_mux_mapped(plat->pins[pos].i2c) != MRAA_SUCCESS) {
int pos = board->i2c_bus[bus].sda;
if (board->pins[pos].i2c.mux_total > 0) {
if (mraa_setup_mux_mapped(board->pins[pos].i2c) != MRAA_SUCCESS) {
syslog(LOG_ERR, "i2c: Failed to set-up i2c sda multiplexer");
return NULL;
}
}
pos = plat->i2c_bus[bus].scl;
if (plat->pins[pos].i2c.mux_total > 0) {
if (mraa_setup_mux_mapped(plat->pins[pos].i2c) != MRAA_SUCCESS) {
pos = board->i2c_bus[bus].scl;
if (board->pins[pos].i2c.mux_total > 0) {
if (mraa_setup_mux_mapped(board->pins[pos].i2c) != MRAA_SUCCESS) {
syslog(LOG_ERR, "i2c: Failed to set-up i2c scl multiplexer");
return NULL;
}
}
return mraa_i2c_init_raw((unsigned int) plat->i2c_bus[bus].bus_id);
// FIXME: use global func_table variable to access advanced function table without changing i2c_init_raw() signature
func_table = board->adv_func;
return mraa_i2c_init_raw((unsigned int) board->i2c_bus[bus].bus_id);
}
mraa_i2c_context
mraa_i2c_init_raw(unsigned int bus)
{
if (advance_func->i2c_init_pre != NULL) {
if (advance_func->i2c_init_pre(bus) != MRAA_SUCCESS)
return NULL;
}
mraa_i2c_context dev = (mraa_i2c_context) malloc(sizeof(struct _i2c));
if (dev == NULL) {
syslog(LOG_CRIT, "i2c: Failed to allocate memory for context");
return NULL;
}
char filepath[32];
dev->func_table = func_table;
dev->busnum = bus;
snprintf(filepath, 32, "/dev/i2c-%u", bus);
if ((dev->fh = open(filepath, O_RDWR)) < 1) {
syslog(LOG_ERR, "i2c: Failed to open requested i2c port %s", filepath);
}
syslog(LOG_DEBUG, "i2c: Opened i2c bus %s", filepath);
if (ioctl(dev->fh, I2C_FUNCS, &dev->funcs) < 0) {
syslog(LOG_CRIT, "i2c: Failed to get I2C_FUNC map from device");
dev->funcs = 0;
if (IS_FUNC_DEFINED(dev, i2c_init_pre)) {
if (func_table->i2c_init_pre(bus) != MRAA_SUCCESS)
return NULL;
}
if (!IS_FUNC_DEFINED(dev, i2c_init_bus_replace)) {
char filepath[32];
snprintf(filepath, 32, "/dev/i2c-%u", bus);
if ((dev->fh = open(filepath, O_RDWR)) < 1) {
syslog(LOG_ERR, "i2c: Failed to open requested i2c port %s", filepath);
}
syslog(LOG_DEBUG, "i2c: Opened i2c bus %s", filepath);
if (ioctl(dev->fh, I2C_FUNCS, &dev->funcs) < 0) {
syslog(LOG_CRIT, "i2c: Failed to get I2C_FUNC map from device");
dev->funcs = 0;
}
} else {
if (dev->func_table->i2c_init_bus_replace(dev) != MRAA_SUCCESS) {
free(dev);
return NULL;
}
}
if (advance_func->i2c_init_post != NULL) {
mraa_result_t ret = advance_func->i2c_init_post(dev);
if (IS_FUNC_DEFINED(dev, i2c_init_post)) {
mraa_result_t ret = dev->func_table->i2c_init_post(dev);
if (ret != MRAA_SUCCESS) {
free(dev);
return NULL;
@@ -143,8 +173,8 @@ mraa_i2c_init_raw(unsigned int bus)
mraa_result_t
mraa_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode)
{
if (advance_func->i2c_set_frequency_replace != NULL) {
return advance_func->i2c_set_frequency_replace(dev, mode);
if (IS_FUNC_DEFINED(dev, i2c_set_frequency_replace)) {
return dev->func_table->i2c_set_frequency_replace(dev, mode);
}
return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
}
@@ -152,11 +182,16 @@ mraa_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode)
int
mraa_i2c_read(mraa_i2c_context dev, uint8_t* data, int length)
{
// this is the read(3) syscall not mraa_i2c_read()
if (read(dev->fh, data, length) == length) {
return length;
}
return 0;
int bytes_read = 0;
if (!IS_FUNC_DEFINED(dev, i2c_read_replace)) {
// this is the read(3) syscall not mraa_i2c_read()
bytes_read = read(dev->fh, data, length);
} else
bytes_read = dev->func_table->i2c_read_replace(dev, data, length);
if (bytes_read == length)
return length;
else
return 0;
}
uint8_t
@@ -240,11 +275,14 @@ mraa_i2c_write(mraa_i2c_context dev, const uint8_t* data, int length)
mraa_result_t
mraa_i2c_write_byte(mraa_i2c_context dev, const uint8_t data)
{
if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, NULL) < 0) {
syslog(LOG_ERR, "i2c: Failed to write");
return MRAA_ERROR_INVALID_HANDLE;
}
return MRAA_SUCCESS;
if (!IS_FUNC_DEFINED(dev, i2c_write_byte_replace)) {
if (mraa_i2c_smbus_access(dev->fh, I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, NULL) < 0) {
syslog(LOG_ERR, "i2c: Failed to write");
return MRAA_ERROR_INVALID_HANDLE;
}
return MRAA_SUCCESS;
} else
return dev->func_table->i2c_write_byte_replace(dev, data);
}
mraa_result_t
@@ -277,11 +315,14 @@ mraa_result_t
mraa_i2c_address(mraa_i2c_context dev, uint8_t addr)
{
dev->addr = (int) addr;
if (ioctl(dev->fh, I2C_SLAVE_FORCE, addr) < 0) {
syslog(LOG_ERR, "i2c: Failed to set slave address %d", addr);
return MRAA_ERROR_INVALID_HANDLE;
}
return MRAA_SUCCESS;
if (dev->func_table->i2c_init_bus_replace == NULL) {
if (ioctl(dev->fh, I2C_SLAVE_FORCE, addr) < 0) {
syslog(LOG_ERR, "i2c: Failed to set slave address %d", addr);
return MRAA_ERROR_INVALID_HANDLE;
}
return MRAA_SUCCESS;
} else
return dev->func_table->i2c_address_replace(dev, addr);
}
mraa_result_t

View File

@@ -97,17 +97,29 @@ mraa_init()
Py_InitializeEx(0);
PyEval_InitThreads();
#endif
advance_func = (mraa_adv_func_t*) malloc(sizeof(mraa_adv_func_t));
memset(advance_func, 0, sizeof(mraa_adv_func_t));
#if defined(X86PLAT)
#ifdef X86PLAT
// Use runtime x86 platform detection
platform_type = mraa_x86_platform();
#elif defined(ARMPLAT)
#ifdef USBPLAT
// This is a platform extender so create null base platform if one doesn't already exist
if (plat == NULL) {
plat = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
plat->platform_name = "Null platform";
if (plat != NULL) {
int usb_platform_type = mraa_usb_platform_extender(plat);
if (platform_type == MRAA_UNKNOWN_PLATFORM)
platform_type = usb_platform_type;
}
}
#endif
#if defined(ARMPLAT)
// Use runtime ARM platform detection
platform_type = mraa_arm_platform();
#else
#error mraa_ARCH NOTHING
#endif
if (plat == NULL) {
@@ -115,7 +127,7 @@ mraa_init()
return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
}
syslog(LOG_INFO, "libmraa initialised for platform '%s' of type %d", mraa_get_platform_name(), platform_type);
syslog(LOG_NOTICE, "libmraa initialised for platform '%s' of type %d", mraa_get_platform_name(), platform_type);
return MRAA_SUCCESS;
}
@@ -355,6 +367,17 @@ mraa_get_pin_name(int pin)
return (char*) plat->pins[pin].name;
}
int
mraa_get_default_i2c_bus()
{
if (plat == NULL) {
return -1;
} else
return plat->def_i2c_bus;
}
mraa_boolean_t
mraa_file_exist(const char* filename)
{

7
src/usb/CMakeLists.txt Normal file
View File

@@ -0,0 +1,7 @@
message (INFO " - Adding USB platforms")
set (mraa_LIB_SRCS_NOAUTO ${mraa_LIB_SRCS_NOAUTO}
${PROJECT_SOURCE_DIR}/src/usb/usb.c
${PROJECT_SOURCE_DIR}/src/usb/ftdi_ft4222.c
PARENT_SCOPE
)

377
src/usb/ftdi_ft4222.c Normal file
View File

@@ -0,0 +1,377 @@
/*
* Author: Henry Bruce <henry.bruce@intel.com>
* Copyright (c) 2015 Intel Corporation.
*
* 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.
*/
#include <stdlib.h>
#include <string.h>
#include "linux/i2c-dev.h"
#include "common.h"
#include "ftd2xx.h"
#include "libft4222.h"
#include "usb/ftdi_ft4222.h"
#define PLATFORM_NAME "FTDI FT4222"
#define I2CM_ERROR(status) (((status) & 0x02) != 0)
static FT_HANDLE ftHandle = (FT_HANDLE)NULL;
static int bus_speed = 400;
mraa_result_t
mraa_ftdi_ft4222_init()
{
mraa_result_t mraaStatus = MRAA_SUCCESS;
FT_STATUS ftStatus;
FT_DEVICE_LIST_INFO_NODE *devInfo = NULL;
DWORD numDevs = 0;
int i;
int retCode = 0;
ftStatus = FT_CreateDeviceInfoList(&numDevs);
if (ftStatus != FT_OK)
{
syslog(LOG_ERR, "FT_CreateDeviceInfoList failed: error code %d\n", ftStatus);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit;
}
if (numDevs == 0)
{
syslog(LOG_ERR, "No FT4222 devices connected.\n");
goto init_exit;
}
devInfo = calloc((size_t)numDevs, sizeof(FT_DEVICE_LIST_INFO_NODE));
if (devInfo == NULL)
{
syslog(LOG_ERR, "FT4222 allocation failure.\n");
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit;
}
ftStatus = FT_GetDeviceInfoList(devInfo, &numDevs);
if (ftStatus != FT_OK)
{
syslog(LOG_ERR, "FT_GetDeviceInfoList failed (error code %d)\n", (int)ftStatus);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit;
}
syslog(LOG_INFO, "FT_GetDeviceInfoList returned %d devices\n", numDevs);
DWORD locationId;
int bus = 0;
if (numDevs > bus && devInfo[bus].Type == FT_DEVICE_4222H_3) {
locationId = devInfo[bus].LocId;
} else {
syslog(LOG_ERR, "FT_GetDeviceInfoList contains no valid devices\n");
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit;
}
ftStatus = FT_OpenEx((PVOID)(uintptr_t)locationId, FT_OPEN_BY_LOCATION, &ftHandle);
if (ftStatus != FT_OK)
{
syslog(LOG_ERR, "FT_OpenEx failed (error %d)\n", (int)ftStatus);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit;
}
init_exit:
if (devInfo != NULL);
free(devInfo);
if (mraaStatus == MRAA_SUCCESS)
syslog(LOG_NOTICE, "mraa_ftdi_ft4222_init completed successfully\n");
return mraaStatus;
}
mraa_result_t
mraa_ftdi_ft4222_get_version(unsigned int* versionChip, unsigned int* versionLib)
{
if (ftHandle != NULL) {
FT4222_Version ft4222Version;
FT4222_STATUS ft4222Status = FT4222_GetVersion(ftHandle, &ft4222Version);
if (FT4222_OK == ft4222Status){
*versionChip = (unsigned int)ft4222Version.chipVersion;
*versionLib = (unsigned int)ft4222Version.dllVersion;
syslog(LOG_NOTICE, "FT4222_GetVersion %08X %08X\n", *versionChip, *versionLib);
return MRAA_SUCCESS;
} else {
syslog(LOG_ERR, "libmraa: FT4222_GetVersion failed (error %d)\n", (int)ft4222Status);
return MRAA_ERROR_NO_RESOURCES;
}
} else {
syslog(LOG_ERR, "libmraa: bad FT4222 handle\n");
return MRAA_ERROR_INVALID_HANDLE;
}
}
mraa_i2c_context
mraa_ftdi_ft4222_i2c_init_raw(unsigned int bus)
{
// Tell the FT4222 to be an I2C Master.
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, bus_speed);
if (FT4222_OK != ft4222Status)
{
syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
return NULL;
}
// Reset the I2CM registers to a known state.
ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
if (FT4222_OK != ft4222Status)
{
syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
return NULL;
}
mraa_i2c_context dev = (mraa_i2c_context) malloc(sizeof(struct _i2c));
if (dev == NULL) {
syslog(LOG_CRIT, "i2c: Failed to allocate memory for context");
return NULL;
}
dev->handle = ftHandle;
dev->fh = -1; // We don't use file descriptors
dev->funcs = I2C_FUNC_I2C; // Advertise minimal i2c support as per https://www.kernel.org/doc/Documentation/i2c/functionality
return dev;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_init_bus_replace(mraa_i2c_context dev)
{
// Tell the FT4222 to be an I2C Master.
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, 400);
if (FT4222_OK != ft4222Status)
{
syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
return MRAA_ERROR_NO_RESOURCES;
}
// Reset the I2CM registers to a known state.
ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
if (FT4222_OK != ft4222Status)
{
syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
return MRAA_ERROR_NO_RESOURCES;
}
dev->handle = ftHandle;
dev->fh = -1; // We don't use file descriptors
dev->funcs = I2C_FUNC_I2C; // Advertise minimal i2c support as per https://www.kernel.org/doc/Documentation/i2c/functionality
return MRAA_SUCCESS;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode)
{
return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_address(mraa_i2c_context dev, uint8_t addr)
{
dev->addr = (int) addr;
return FT4222_I2CMaster_Init(ftHandle, bus_speed) == FT4222_OK ? MRAA_SUCCESS : MRAA_ERROR_NO_RESOURCES;
}
static int
mraa_ftdi_ft4222_i2c_read(mraa_i2c_context dev, uint8_t* data, int length)
{
uint16 bytesRead = 0;
uint8 controllerStatus;
syslog(LOG_NOTICE, "FT4222_I2CMaster_Read(%02X, %d)", dev->addr, length);
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Read(dev->handle, dev->addr, data, length, &bytesRead);
ft4222Status = FT4222_I2CMaster_GetStatus(ftHandle, &controllerStatus);
if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus))
{
syslog(LOG_ERR, "FT4222_I2CMaster_Read failed (error %d)\n", (int)ft4222Status);
return 0;
}
return bytesRead;
}
static uint8_t
mraa_ftdi_ft4222_i2c_read_byte(mraa_i2c_context dev)
{
return 0;
}
static uint8_t
mraa_ftdi_ft4222_i2c_read_byte_data(mraa_i2c_context dev, uint8_t command)
{
return 0;
}
static uint16_t
mraa_ftdi_ft4222_i2c_read_word_data(mraa_i2c_context dev, uint8_t command)
{
return 0;
}
static int
mraa_ftdi_ft4222_i2c_read_bytes_data(mraa_i2c_context dev, uint8_t command, uint8_t* data, int length)
{
return -1;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWrite)
{
uint16 bytesWritten = 0;
uint8 controllerStatus;
syslog(LOG_NOTICE, "FT4222_I2CMaster_Write(%#02X, %#02X, %d)", dev->addr, *data, bytesToWrite);
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Write(dev->handle, dev->addr, (uint8_t*)data, bytesToWrite, &bytesWritten);
ft4222Status = FT4222_I2CMaster_GetStatus(ftHandle, &controllerStatus);
if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus))
{
syslog(LOG_ERR, "FT4222_I2CMaster_Write failed (error %d)\n", (int)ft4222Status);
return MRAA_ERROR_INVALID_HANDLE;
}
if (bytesWritten != bytesToWrite)
syslog(LOG_ERR, "FT4222_I2CMaster_Write wrote %u of %u bytes.\n", bytesWritten, bytesToWrite);
return bytesToWrite == bytesWritten ? MRAA_SUCCESS : MRAA_ERROR_INVALID_HANDLE;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_write_byte(mraa_i2c_context dev, uint8_t data)
{
return mraa_ftdi_ft4222_i2c_write(dev, &data, 1);
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_write_byte_data(mraa_i2c_context dev, const uint8_t data, const uint8_t command)
{
mraa_result_t status = mraa_ftdi_ft4222_i2c_write_byte(dev, command);
if (status == MRAA_SUCCESS)
return mraa_ftdi_ft4222_i2c_write_byte(dev, data);
else
return status;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_write_word_data(mraa_i2c_context dev, const uint16_t data, const uint8_t command)
{
mraa_result_t status = mraa_ftdi_ft4222_i2c_write_byte(dev, command);
if (status == MRAA_SUCCESS)
return mraa_ftdi_ft4222_i2c_write(dev, (const uint8_t*)&data, 2);
else
return status;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_stop(mraa_i2c_context dev)
{
return MRAA_SUCCESS;
}
mraa_adv_func_t*
mraa_i2c_ft4222_create_func_table()
{
mraa_adv_func_t* func_table = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t));
if (func_table != NULL) {
// func_table->i2c_init_raw_replace = &mraa_ftdi_ft4222_i2c_init_raw;
func_table->i2c_init_bus_replace = &mraa_ftdi_ft4222_i2c_init_bus_replace;
func_table->i2c_set_frequency_replace = &mraa_ftdi_ft4222_i2c_frequency;
func_table->i2c_address_replace = &mraa_ftdi_ft4222_i2c_address;
func_table->i2c_read_replace = &mraa_ftdi_ft4222_i2c_read;
func_table->i2c_read_byte_replace = &mraa_ftdi_ft4222_i2c_read_byte;
func_table->i2c_read_byte_data_replace = &mraa_ftdi_ft4222_i2c_read_byte_data;
func_table->i2c_read_word_data_replace = &mraa_ftdi_ft4222_i2c_read_word_data;
func_table->i2c_read_bytes_data_replace = &mraa_ftdi_ft4222_i2c_read_bytes_data;
func_table->i2c_write_replace = &mraa_ftdi_ft4222_i2c_write;
func_table->i2c_write_byte_replace = &mraa_ftdi_ft4222_i2c_write_byte;
func_table->i2c_write_byte_data_replace = &mraa_ftdi_ft4222_i2c_write_byte_data;
func_table->i2c_write_word_data_replace = &mraa_ftdi_ft4222_i2c_write_word_data;
func_table->i2c_stop_replace = &mraa_ftdi_ft4222_i2c_stop;
}
return func_table;
}
mraa_board_t*
mraa_ftdi_ft4222(mraa_board_t* board)
{
if (plat == NULL)
return NULL;
mraa_board_t* sub_plat = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
if (sub_plat == NULL)
return NULL;
int pinIndex = 0;
int numUsbGpio = 0;
int numUsbPins = numUsbGpio + 2; // Add SDA and SCL
sub_plat->platform_name = PLATFORM_NAME;
sub_plat->phy_pin_count = numUsbPins;
sub_plat->gpio_count = numUsbGpio;
mraa_pininfo_t* pins = (mraa_pininfo_t*) malloc(sizeof(mraa_pininfo_t) * numUsbPins);
if (pins == NULL) {
return NULL;
}
sub_plat->pins = pins;
// Virtual gpio pins on i2c I/O expander.
mraa_pincapabilities_t pinCapsGpio = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
for (pinIndex=0; pinIndex < numUsbGpio; ++pinIndex) {
char name[8];
sprintf(name, "Pin%d", pinIndex);
strncpy(sub_plat->pins[pinIndex].name, name, 8);
sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
}
int bus = 0;
sub_plat->i2c_bus_count = 1;
sub_plat->def_i2c_bus = bus;
sub_plat->i2c_bus[bus].bus_id = bus;
// sub_plat->i2c_bus[bus].drv_type = drv_type;
// i2c pins (these are virtual, entries are required to configure i2c layer)
mraa_pincapabilities_t pinCapsI2c = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 1, 0, 0 };
strncpy(sub_plat->pins[pinIndex].name, "SDA", 8);
sub_plat->pins[pinIndex].capabilites = pinCapsI2c;
sub_plat->pins[pinIndex].i2c.mux_total = 0;
sub_plat->i2c_bus[bus].sda = pinIndex;
pinIndex++;
strncpy(sub_plat->pins[pinIndex].name, "SCL", 8);
sub_plat->pins[pinIndex].capabilites = pinCapsI2c;
sub_plat->pins[pinIndex].i2c.mux_total = 0;
sub_plat->i2c_bus[bus].scl = pinIndex;
// Set override functions
sub_plat->adv_func = mraa_i2c_ft4222_create_func_table();
board->sub_platform = sub_plat;
return sub_plat;
}

51
src/usb/usb.c Normal file
View File

@@ -0,0 +1,51 @@
/*
* Author: Henry Bruce <henry.bruce@intel.com>
* Copyright (c) 2015 Intel Corporation.
*
* 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.
*/
#include <stdlib.h>
#include <string.h>
#include "mraa_internal.h"
#include "usb/ftdi_ft4222.h"
mraa_platform_t
mraa_usb_platform_extender(mraa_board_t* board)
{
mraa_platform_t platform_type = MRAA_UNKNOWN_PLATFORM;
if (mraa_ftdi_ft4222_init() == MRAA_SUCCESS) {
unsigned int versionChip, versionLib;
if (mraa_ftdi_ft4222_get_version(&versionChip, &versionLib) == MRAA_SUCCESS) {
// TODO: Add ft4222 version checks
platform_type = MRAA_FTDI_FT4222;
}
}
switch (platform_type) {
case MRAA_FTDI_FT4222:
mraa_ftdi_ft4222(board);
break;
default:
syslog(LOG_ERR, "Unknown USB Platform Extender, currently not supported by MRAA");
}
return platform_type;
}

View File

@@ -1116,7 +1116,8 @@ mraa_intel_edison_miniboard(mraa_board_t* b)
mraa_board_t*
mraa_intel_edison_fab_c()
{
mraa_board_t* b = (mraa_board_t*) malloc(sizeof(mraa_board_t));
// mraa_board_t* b = (mraa_board_t*) malloc(sizeof(mraa_board_t));
mraa_board_t* b = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
if (b == NULL) {
return NULL;
}