Private
Public Access
2
0

ftdi_ft4222: Re-order pin numbering and support i2c switch

First four pins (0 to 3) are now built-in FTDI GPIO/I2C pins
If i2c GPIO expander is detected, next 8 pins (4 to 11) are its GPIO
If i2c switch is detected an extra 4 i2c busses are added

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
2016-01-05 13:34:37 -08:00
committed by Brendan Le Foll
parent ed0124cc70
commit 8c40842e4b
2 changed files with 313 additions and 181 deletions

View File

@@ -23,8 +23,41 @@ Supported GPIO expanders:
* PCA9555 * PCA9555
* PCF8575 * PCF8575
When a GPIO expander is present, the pins on the expander will be initialized Output from 'mraa-gpio list' would be as follows:
first and the 4 GPIO pins on the FT4222H are appended after. ~~~~~~~~~~~~~
512 IGPIO0/SCL0: GPIO I2C
513 IGPIO1/SDA0: GPIO I2C
514 INT-GPIO2: GPIO
515 INT-GPIO3: GPIO
~~~~~~~~~~~~~
When an I2C GPIO expander is present, the pins on the expander will appear after
the 4 FT4222H GPIO pins (i.e. starting at physical pin #4, logical pin #516).
~~~~~~~~~~~~~
512 IGPIO0/SCL0: GPIO I2C
513 IGPIO1/SDA0: GPIO I2C
514 INT-GPIO2: GPIO
515 INT-GPIO3: GPIO
516 EXP-GPIO0: GPIO
517 EXP-GPIO1: GPIO
518 EXP-GPIO2: GPIO
519 EXP-GPIO3: GPIO
520 EXP-GPIO4: GPIO
521 EXP-GPIO5: GPIO
522 EXP-GPIO6: GPIO
523 EXP-GPIO7: GPIO
~~~~~~~~~~~~~
If a PCA9545 I2C switch is detected an extra four I2C busses will appear,
representing the four downstream busses. Output from 'mraa-i2c list'
would be as follows:
~~~~~~~~~~~~~
Bus 512: id=00 type=ft4222 default
Bus 513: id=01 type=ft4222
Bus 514: id=02 type=ft4222
Bus 515: id=03 type=ft4222
Bus 516: id=04 type=ft4222
~~~~~~~~~~~~~
Please note that some mraa features might not be fully implemented yet and they Please note that some mraa features might not be fully implemented yet and they
are still under development (e.g. SPI replacement functions). are still under development (e.g. SPI replacement functions).

View File

@@ -25,6 +25,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <sys/time.h>
#include <errno.h> #include <errno.h>
#include "linux/i2c-dev.h" #include "linux/i2c-dev.h"
#include "common.h" #include "common.h"
@@ -35,18 +36,26 @@
#define PLATFORM_NAME "FTDI FT4222" #define PLATFORM_NAME "FTDI FT4222"
#define I2CM_ERROR(status) (((status) &0x02) != 0) #define I2CM_ERROR(status) (((status) &0x02) != 0)
#define PCA9672_ADDR 0x20 #define PCA9672_ADDR 0x20
#define PCA9545_ADDR 0x70
#define PCA9672_PINS 8
#define PCA9545_BUSSES 4
#define GPIO_PORT_IO_RESET GPIO_PORT2
#define GPIO_PORT_IO_STATUS GPIO_PORT3
static FT_HANDLE ftHandleGpio = (FT_HANDLE) NULL; //GPIO Handle
static FT_HANDLE ftHandleGPIO = (FT_HANDLE) NULL; //GPIO Handle static FT_HANDLE ftHandleI2c = (FT_HANDLE) NULL; //I2C/SPI Handle
static FT_HANDLE ftHandle = (FT_HANDLE) NULL; //I2C/SPI Handle static FT_HANDLE ftHandleSpi = (FT_HANDLE) NULL; //I2C/SPI Handle
static GPIO_Dir pinDirection[] = {GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT}; static GPIO_Dir pinDirection[] = {GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT};
static int bus_speed = 400; static int bus_speed = 400;
static int numI2cGpioExpanderPins; static int numFt4222GpioPins = 4;
static int numI2cGpioExpanderPins = 8;
static int numI2cSwitchBusses = 4;
static int currentI2cBus = 0;
mraa_result_t mraa_result_t
mraa_ftdi_ft4222_init() mraa_ftdi_ft4222_init()
{ {
mraa_result_t mraaStatus = MRAA_SUCCESS; mraa_result_t mraaStatus = MRAA_ERROR_NO_RESOURCES;
FT_DEVICE_LIST_INFO_NODE* devInfo = NULL; FT_DEVICE_LIST_INFO_NODE* devInfo = NULL;
FT_STATUS ftStatus; FT_STATUS ftStatus;
DWORD numDevs = 0; DWORD numDevs = 0;
@@ -56,96 +65,87 @@ mraa_ftdi_ft4222_init()
ftStatus = FT_CreateDeviceInfoList(&numDevs); ftStatus = FT_CreateDeviceInfoList(&numDevs);
if (ftStatus != FT_OK) { if (ftStatus != FT_OK) {
syslog(LOG_ERR, "FT_CreateDeviceInfoList failed: error code %d\n", ftStatus); 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; goto init_exit;
} }
devInfo = calloc((size_t) numDevs, sizeof(FT_DEVICE_LIST_INFO_NODE)); devInfo = calloc((size_t) numDevs, sizeof(FT_DEVICE_LIST_INFO_NODE));
if (devInfo == NULL) { if (devInfo == NULL) {
syslog(LOG_ERR, "FT4222 allocation failure.\n"); syslog(LOG_ERR, "FT4222 allocation failure.\n");
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit; goto init_exit;
} }
ftStatus = FT_GetDeviceInfoList(devInfo, &numDevs); ftStatus = FT_GetDeviceInfoList(devInfo, &numDevs);
syslog(LOG_NOTICE, "FT_GetDeviceInfoList returned %d devices\n", numDevs);
if (ftStatus != FT_OK) { if (ftStatus != FT_OK) {
syslog(LOG_ERR, "FT_GetDeviceInfoList failed (error code %d)\n", (int) ftStatus); syslog(LOG_ERR, "FT_GetDeviceInfoList failed (error code %d)\n", (int) ftStatus);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit; goto init_exit;
} }
if (numDevs < 2) {
/* syslog(LOG_ERR, "No FT4222 devices connected.\n");
FT4222_Version ft4222Version; goto init_exit;
FT4222_STATUS ft4222Status = FT4222_GetVersion(ftHandle, &ft4222Version); }
if (FT4222_OK == ft4222Status){
syslog(LOG_NOTICE, "FT4222_GetVersion %08X %08X\n", ft4222Version.chipVersion,
ft4222Version.dllVersion);
} else
syslog(LOG_ERR, "FT4222_GetVersion failed with code %d", ft4222Status);
*/
syslog(LOG_NOTICE, "FT_GetDeviceInfoList returned %d devices\n", numDevs);
if(numDevs > 2) { if(numDevs > 2) {
syslog(LOG_ERR, "CNFMODE not supported. Valid modes are 0 or 3.\n"); syslog(LOG_ERR, "CNFMODE not supported. Valid modes are 0 or 3.\n");
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit; goto init_exit;
} }
// CNFMODE 0, GPIO interface available. // FIXME: Assumes just one physical FTDI device present
if(numDevs = 2) { DWORD locationIdI2c = 0;
ftStatus = FT_OpenEx((PVOID)(uintptr_t) devInfo[1].LocId, FT_OPEN_BY_LOCATION, &ftHandleGPIO); DWORD locationIdGpio = 0;
if (ftStatus != FT_OK) { if (devInfo[0].Type == FT_DEVICE_4222H_0)
syslog(LOG_ERR, "FT_OpenEx GPIO handle failed (error %d)\n", (int) ftStatus); locationIdI2c = devInfo[0].LocId;
mraaStatus = MRAA_ERROR_NO_RESOURCES; if (devInfo[1].Type == FT_DEVICE_4222H_0)
goto init_exit; locationIdGpio = devInfo[1].LocId;
}
// Disable Suspend and Wake on GPIO2 & GPIO3 if (locationIdI2c == 0) {
FT4222_SetSuspendOut(ftHandleGPIO, 0); syslog(LOG_ERR, "FT_GetDeviceInfoList contains no I2C controllers\n");
FT4222_SetWakeUpInterrupt(ftHandleGPIO, 0); goto init_exit;
ftStatus = FT4222_GPIO_Init(ftHandleGPIO, pinDirection);
if (ftStatus != FT_OK) {
syslog(LOG_ERR, "FT4222_GPIO_Init failed (error %d)\n", (int) ftStatus);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit;
}
} }
// I2C or SPI interface. if (locationIdGpio == 0) {
ftStatus = FT_OpenEx((PVOID)(uintptr_t) devInfo[0].LocId, FT_OPEN_BY_LOCATION, &ftHandle); syslog(LOG_ERR, "FT_GetDeviceInfoList contains no GPIO controllers\n");
goto init_exit;
}
ftStatus = FT_OpenEx((PVOID)(uintptr_t) locationIdI2c, FT_OPEN_BY_LOCATION, &ftHandleI2c);
if (ftStatus != FT_OK) { if (ftStatus != FT_OK) {
syslog(LOG_ERR, "FT_OpenEx I2C handle failed (error %d)\n", (int) ftStatus); syslog(LOG_ERR, "FT_OpenEx failed (error %d)\n", (int) ftStatus);
goto init_exit;
}
ftStatus = FT_OpenEx((PVOID)(uintptr_t) locationIdGpio, FT_OPEN_BY_LOCATION, &ftHandleGpio);
if (ftStatus != FT_OK) {
syslog(LOG_ERR, "FT_OpenEx failed (error %d)\n", (int) ftStatus);
goto init_exit;
}
FT4222_SetSuspendOut(ftHandleGpio, 0);
FT4222_SetWakeUpInterrupt(ftHandleGpio, 0);
ftStatus = FT4222_GPIO_Init(ftHandleGpio, pinDirection);
if (ftStatus != FT_OK) {
syslog(LOG_ERR, "FT4222_GPIO_Init failed (error %d)\n", (int) ftStatus);
mraaStatus = MRAA_ERROR_NO_RESOURCES; mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit; goto init_exit;
} }
// Tell the FT4222 to be an I2C Master by default on init. // Tell the FT4222 to be an I2C Master by default on init.
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, bus_speed); FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandleI2c, bus_speed);
if (FT4222_OK != ft4222Status) { if (FT4222_OK != ft4222Status) {
syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status); syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit; goto init_exit;
} }
// Reset the I2CM registers to a known state. ft4222Status = FT4222_I2CMaster_Reset(ftHandleI2c);
ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
if (FT4222_OK != ft4222Status) { if (FT4222_OK != ft4222Status) {
syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status); syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
mraaStatus = MRAA_ERROR_NO_RESOURCES;
goto init_exit; goto init_exit;
} }
mraaStatus = MRAA_SUCCESS;
init_exit: init_exit:
if (devInfo != NULL) if (devInfo != NULL)
; free(devInfo);
free(devInfo);
if (mraaStatus == MRAA_SUCCESS) if (mraaStatus == MRAA_SUCCESS)
syslog(LOG_NOTICE, "mraa_ftdi_ft4222_init completed successfully\n"); syslog(LOG_NOTICE, "mraa_ftdi_ft4222_init completed successfully\n");
return mraaStatus; return mraaStatus;
@@ -155,25 +155,27 @@ init_exit:
mraa_result_t mraa_result_t
mraa_ftdi_ft4222_get_version(unsigned int* versionChip, unsigned int* versionLib) mraa_ftdi_ft4222_get_version(unsigned int* versionChip, unsigned int* versionLib)
{ {
if (ftHandle != NULL) { if (ftHandleI2c != NULL) {
FT4222_Version ft4222Version; FT4222_Version ft4222Version;
FT4222_STATUS ft4222Status = FT4222_GetVersion(ftHandle, &ft4222Version); FT4222_STATUS ft4222Status = FT4222_GetVersion(ftHandleI2c, &ft4222Version);
if (FT4222_OK == ft4222Status) { if (FT4222_OK == ft4222Status) {
*versionChip = (unsigned int) ft4222Version.chipVersion; *versionChip = (unsigned int) ft4222Version.chipVersion;
*versionLib = (unsigned int) ft4222Version.dllVersion; *versionLib = (unsigned int) ft4222Version.dllVersion;
syslog(LOG_NOTICE, "FT4222_GetVersion %08X %08X\n", *versionChip, *versionLib); syslog(LOG_NOTICE, "FT4222_GetVersion %08X %08X\n", *versionChip, *versionLib);
return MRAA_SUCCESS; return MRAA_SUCCESS;
} else { } else {
syslog(LOG_ERR, "libmraa: FT4222_GetVersion failed (error %d)\n", (int) ft4222Status); syslog(LOG_ERR, "FT4222_GetVersion failed (error %d)\n", (int) ft4222Status);
return MRAA_ERROR_NO_RESOURCES; return MRAA_ERROR_NO_RESOURCES;
} }
} else { } else {
syslog(LOG_ERR, "libmraa: bad FT4222 handle\n"); syslog(LOG_ERR, "Bad FT4222 handle\n");
return MRAA_ERROR_INVALID_HANDLE; return MRAA_ERROR_INVALID_HANDLE;
} }
} }
/******************* Private I2C functions *******************/
static int static int
mraa_ftdi_ft4222_i2c_read_internal(FT_HANDLE handle, uint8_t addr, uint8_t* data, int length) mraa_ftdi_ft4222_i2c_read_internal(FT_HANDLE handle, uint8_t addr, uint8_t* data, int length)
{ {
@@ -181,9 +183,10 @@ mraa_ftdi_ft4222_i2c_read_internal(FT_HANDLE handle, uint8_t addr, uint8_t* data
uint8 controllerStatus; uint8 controllerStatus;
// syslog(LOG_NOTICE, "FT4222_I2CMaster_Read(%#02X, %#02X)", addr, length); // syslog(LOG_NOTICE, "FT4222_I2CMaster_Read(%#02X, %#02X)", addr, length);
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Read(handle, addr, data, length, &bytesRead); FT4222_STATUS ft4222Status = FT4222_I2CMaster_Read(handle, addr, data, length, &bytesRead);
ft4222Status = FT4222_I2CMaster_GetStatus(ftHandle, &controllerStatus); ft4222Status = FT4222_I2CMaster_GetStatus(ftHandleI2c, &controllerStatus);
if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus)) { if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus)) {
syslog(LOG_ERR, "FT4222_I2CMaster_Read failed (error %d)\n", (int) ft4222Status); syslog(LOG_ERR, "FT4222_I2CMaster_Read failed for address %#02x\n", addr);
FT4222_I2CMaster_Reset(handle);
return 0; return 0;
} }
return bytesRead; return bytesRead;
@@ -195,11 +198,11 @@ mraa_ftdi_ft4222_i2c_write_internal(FT_HANDLE handle, uint8_t addr, const uint8_
uint16 bytesWritten = 0; uint16 bytesWritten = 0;
uint8 controllerStatus; uint8 controllerStatus;
// syslog(LOG_NOTICE, "FT4222_I2CMaster_Write(%#02X, %#02X, %d)", addr, *data, bytesToWrite); // syslog(LOG_NOTICE, "FT4222_I2CMaster_Write(%#02X, %#02X, %d)", addr, *data, bytesToWrite);
FT4222_STATUS ft4222Status = FT4222_STATUS ft4222Status = FT4222_I2CMaster_Write(handle, addr, (uint8_t*) data, bytesToWrite, &bytesWritten);
FT4222_I2CMaster_Write(handle, addr, (uint8_t*) data, bytesToWrite, &bytesWritten); ft4222Status = FT4222_I2CMaster_GetStatus(ftHandleI2c, &controllerStatus);
ft4222Status = FT4222_I2CMaster_GetStatus(ftHandle, &controllerStatus);
if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus)) { if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus)) {
syslog(LOG_ERR, "FT4222_I2CMaster_Write failed (error %d)\n", (int) ft4222Status); syslog(LOG_ERR, "FT4222_I2CMaster_Write failed address %#02x\n", addr);
FT4222_I2CMaster_Reset(handle);
return 0; return 0;
} }
@@ -209,70 +212,136 @@ mraa_ftdi_ft4222_i2c_write_internal(FT_HANDLE handle, uint8_t addr, const uint8_
return bytesWritten; return bytesWritten;
} }
// Function detects known I2C expanders and returns the number of GPIO pins on expander
// Function detects known I2C I/O expanders and returns the number of GPIO pins on expander
static int static int
mraa_ftdi_ft4222_detect_io_expander() mraa_ftdi_ft4222_detect_io_expander()
{ {
uint8_t data; uint8_t data;
if(mraa_ftdi_ft4222_i2c_read_internal(ftHandle, PCA9672_ADDR, &data, 1) == 1) { if(mraa_ftdi_ft4222_i2c_read_internal(ftHandleI2c, PCA9672_ADDR, &data, 1) == 1) {
return 8; return PCA9672_PINS;
} }
return 0; return 0;
} }
/******************* I2C functions *******************/ static mraa_boolean_t
// Function not currently mapped or used since we have virtual pin definitions mraa_ftdi_ft4222_is_internal_gpio(int pin)
static mraa_i2c_context
mraa_ftdi_ft4222_i2c_init_raw_replace(unsigned int bus)
{ {
// Tell the FT4222 to be an I2C Master. return pin < numFt4222GpioPins;
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
ftdi_ft4222_set_internal_gpio_dir(int pin, GPIO_Dir direction)
{
pinDirection[pin] = direction;
if (FT4222_GPIO_Init(ftHandleGpio, pinDirection) != FT4222_OK)
return MRAA_ERROR_UNSPECIFIED;
else
return MRAA_SUCCESS;
}
// Function detects known I2C switches and returns the number of busses.
// On startup switch is disabled so default bus will be integrated i2c bus.
static int
mraa_ftdi_ft4222_detect_i2c_switch()
{
uint8_t data;
if(mraa_ftdi_ft4222_i2c_read_internal(ftHandleI2c, PCA9545_ADDR, &data, 1) == 1) {
data = 0;
return mraa_ftdi_ft4222_i2c_write_internal(ftHandleI2c, PCA9545_ADDR, &data, 1) == 1 ? PCA9545_BUSSES : 0;
}
return 0;
}
static mraa_result_t
mraa_ftdi_ft4222_i2c_select_bus(int bus)
{
if (bus != currentI2cBus) {
uint8_t data;
if (bus == 0)
data = 0;
else
data = 1 << (bus-1);
if (mraa_ftdi_ft4222_i2c_write_internal(ftHandleI2c, PCA9545_ADDR, &data, 1) == 1)
currentI2cBus = bus;
else
return MRAA_ERROR_UNSPECIFIED;
}
return MRAA_SUCCESS;
}
static int
mraa_ftdi_ft4222_i2c_context_read(mraa_i2c_context dev, uint8_t* data, int length)
{
if (mraa_ftdi_ft4222_i2c_select_bus(dev->busnum) == MRAA_SUCCESS)
return mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, data, length);
else
return 0;
}
static int
mraa_ftdi_ft4222_i2c_context_write(mraa_i2c_context dev, uint8_t* data, int length)
{
if (mraa_ftdi_ft4222_i2c_select_bus(dev->busnum) == MRAA_SUCCESS)
return mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, data, length);
else
return 0;
}
static void
mraa_ftdi_ft4222_sleep_ms(unsigned long mseconds)
{
struct timespec sleepTime;
sleepTime.tv_sec = mseconds / 1000; // Number of seconds
sleepTime.tv_nsec = (mseconds % 1000) * 1000000; // Convert fractional seconds to nanoseconds
// Iterate nanosleep in a loop until the total sleep time is the original
// value of the seconds parameter
while ((nanosleep(&sleepTime, &sleepTime) != 0) && (errno == EINTR))
;
}
static unsigned int
mraa_ftdi_ft4222_get_tick_count_ms()
{
static unsigned int startTick = 0;
unsigned int ticks;
struct timeval now;
gettimeofday(&now, NULL);
ticks = now.tv_sec * 1000;
ticks += now.tv_usec / 1000;
if (startTick == 0)
startTick = ticks;
return ticks - startTick;
}
/******************* I2C functions *******************/
static mraa_result_t static mraa_result_t
mraa_ftdi_ft4222_i2c_init_bus_replace(mraa_i2c_context dev) mraa_ftdi_ft4222_i2c_init_bus_replace(mraa_i2c_context dev)
{ {
// Tell the FT4222 to be an I2C Master. // Tell the FT4222 to be an I2C Master.
FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, 400); FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandleI2c, bus_speed);
if (FT4222_OK != ft4222Status) { if (FT4222_OK != ft4222Status) {
syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status); syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
return MRAA_ERROR_NO_RESOURCES; return MRAA_ERROR_NO_RESOURCES;
} }
// Reset the I2CM registers to a known state. // Reset the I2CM registers to a known state.
ft4222Status = FT4222_I2CMaster_Reset(ftHandle); ft4222Status = FT4222_I2CMaster_Reset(ftHandleI2c);
if (FT4222_OK != ft4222Status) { if (FT4222_OK != ft4222Status) {
syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status); syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
return MRAA_ERROR_NO_RESOURCES; return MRAA_ERROR_NO_RESOURCES;
} }
syslog(LOG_NOTICE, "I2C interface enabled GPIO0 and GPIO1 will be unavailable.\n"); syslog(LOG_NOTICE, "I2C interface enabled GPIO0 and GPIO1 will be unavailable.\n");
dev->handle = ftHandleI2c;
dev->handle = ftHandle;
dev->fh = -1; // We don't use file descriptors dev->fh = -1; // We don't use file descriptors
dev->funcs = I2C_FUNC_I2C; // Advertise minimal i2c support as per dev->funcs = I2C_FUNC_I2C; // Advertise minimal i2c support as per
// https://www.kernel.org/doc/Documentation/i2c/functionality // https://www.kernel.org/doc/Documentation/i2c/functionality
@@ -294,7 +363,7 @@ mraa_ftdi_ft4222_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode)
bus_speed = 3400; bus_speed = 3400;
break; break;
} }
return MRAA_SUCCESS; return FT4222_I2CMaster_Init(ftHandleI2c, bus_speed) == FT4222_OK ? MRAA_SUCCESS : MRAA_ERROR_NO_RESOURCES;
} }
@@ -302,7 +371,7 @@ static mraa_result_t
mraa_ftdi_ft4222_i2c_address(mraa_i2c_context dev, uint8_t addr) mraa_ftdi_ft4222_i2c_address(mraa_i2c_context dev, uint8_t addr)
{ {
dev->addr = (int) addr; dev->addr = (int) addr;
return FT4222_I2CMaster_Init(ftHandle, bus_speed) == FT4222_OK ? MRAA_SUCCESS : MRAA_ERROR_NO_RESOURCES; return MRAA_SUCCESS;
} }
@@ -316,7 +385,7 @@ static uint8_t
mraa_ftdi_ft4222_i2c_read_byte(mraa_i2c_context dev) mraa_ftdi_ft4222_i2c_read_byte(mraa_i2c_context dev)
{ {
uint8_t data; uint8_t data;
if (mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, &data, 1) == 1) if (mraa_ftdi_ft4222_i2c_context_read(dev, &data, 1) == 1)
return data; return data;
else else
return 0; return 0;
@@ -328,9 +397,9 @@ mraa_ftdi_ft4222_i2c_read_word_data(mraa_i2c_context dev, uint8_t command)
{ {
uint8_t buf[2]; uint8_t buf[2];
uint16_t data; uint16_t data;
if (mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, &command, 1) != 1) if (mraa_ftdi_ft4222_i2c_context_write(dev, &command, 1) != 1)
return 0; return 0;
if (mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, buf, 2) != 2) if (mraa_ftdi_ft4222_i2c_context_read(dev, buf, 2) != 2)
return 0; return 0;
data = *(uint16_t*)buf; data = *(uint16_t*)buf;
return data; return data;
@@ -339,16 +408,16 @@ mraa_ftdi_ft4222_i2c_read_word_data(mraa_i2c_context dev, uint8_t command)
static int static int
mraa_ftdi_ft4222_i2c_read_bytes_data(mraa_i2c_context dev, uint8_t command, uint8_t* data, int length) mraa_ftdi_ft4222_i2c_read_bytes_data(mraa_i2c_context dev, uint8_t command, uint8_t* data, int length)
{ {
if (mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, &command, 1) != 1) if (mraa_ftdi_ft4222_i2c_context_write(dev, &command, 1) != 1)
return 0; return 0;
return mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, data, length); return mraa_ftdi_ft4222_i2c_context_read(dev, data, length);
} }
static mraa_result_t static mraa_result_t
mraa_ftdi_ft4222_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWrite) mraa_ftdi_ft4222_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWrite)
{ {
uint16 bytesWritten = mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, data, bytesToWrite); uint16 bytesWritten = mraa_ftdi_ft4222_i2c_context_write(dev, (uint8_t*)data, bytesToWrite);
return bytesToWrite == bytesWritten ? MRAA_SUCCESS : MRAA_ERROR_INVALID_HANDLE; return bytesToWrite == bytesWritten ? MRAA_SUCCESS : MRAA_ERROR_INVALID_HANDLE;
} }
@@ -402,11 +471,12 @@ mraa_ftdi_ft4222_i2c_stop(mraa_i2c_context dev)
static mraa_result_t static mraa_result_t
mraa_ftdi_ft4222_gpio_init_internal_replace(mraa_gpio_context dev, int pin) mraa_ftdi_ft4222_gpio_init_internal_replace(mraa_gpio_context dev, int pin)
{ {
if ((pin - numI2cGpioExpanderPins) == 0 || (pin - numI2cGpioExpanderPins) == 1) { dev->phy_pin = (pin < numFt4222GpioPins) ? pin : pin - numFt4222GpioPins;
if (pin < 2) {
syslog(LOG_NOTICE, "Closing I2C interface to enable GPIO%d\n", pin); syslog(LOG_NOTICE, "Closing I2C interface to enable GPIO%d\n", pin);
/* Replace with call to SPI init when SPI is fully implemented */ /* Replace with call to SPI init when SPI is fully implemented */
FT4222_STATUS ft4222Status = FT4222_SPIMaster_Init(ftHandle, SPI_IO_SINGLE, CLK_DIV_4, CLK_IDLE_HIGH, CLK_LEADING, 0x01); FT4222_STATUS ft4222Status = FT4222_SPIMaster_Init(ftHandleSpi, SPI_IO_SINGLE, CLK_DIV_4, CLK_IDLE_HIGH, CLK_LEADING, 0x01);
if (FT4222_OK != ft4222Status){ if (FT4222_OK != ft4222Status){
syslog(LOG_ERR, "Failed to close I2C interface and start SPI (error %d)!\n", ft4222Status); syslog(LOG_ERR, "Failed to close I2C interface and start SPI (error %d)!\n", ft4222Status);
return MRAA_ERROR_NO_RESOURCES; return MRAA_ERROR_NO_RESOURCES;
@@ -430,13 +500,11 @@ mraa_ftdi_ft4222_gpio_edge_mode_replace(mraa_gpio_context dev, mraa_gpio_edge_t
static int static int
mraa_ftdi_ft4222_gpio_read_replace(mraa_gpio_context dev) mraa_ftdi_ft4222_gpio_read_replace(mraa_gpio_context dev)
{ {
uint8_t pin = dev->phy_pin; uint8_t pin = dev->pin;
uint8_t mask = 1 << pin; if (mraa_ftdi_ft4222_is_internal_gpio(pin)) {
uint8_t value;
if(pin >= numI2cGpioExpanderPins) {
// FTDI GPIO // FTDI GPIO
FT4222_STATUS ft4222Status = FT4222_GPIO_Read(ftHandleGPIO, (pin - numI2cGpioExpanderPins), (BOOL*)&value); BOOL value;
FT4222_STATUS ft4222Status = FT4222_GPIO_Read(ftHandleGpio, dev->phy_pin, &value);
if (FT4222_OK != ft4222Status) { if (FT4222_OK != ft4222Status) {
syslog(LOG_ERR, "FT4222_GPIO_Read failed (error %d)!\n", ft4222Status); syslog(LOG_ERR, "FT4222_GPIO_Read failed (error %d)!\n", ft4222Status);
return -1; return -1;
@@ -445,7 +513,9 @@ mraa_ftdi_ft4222_gpio_read_replace(mraa_gpio_context dev)
} }
else { else {
// Expander GPIO // Expander GPIO
if (mraa_ftdi_ft4222_i2c_read_internal(ftHandle, PCA9672_ADDR, &value, 1) != 1) uint8_t mask = 1 << dev->phy_pin;
uint8_t value;
if (mraa_ftdi_ft4222_i2c_read_internal(ftHandleI2c, PCA9672_ADDR, &value, 1) != 1)
return -1; return -1;
return (value & mask) == mask; return (value & mask) == mask;
} }
@@ -455,13 +525,10 @@ mraa_ftdi_ft4222_gpio_read_replace(mraa_gpio_context dev)
static mraa_result_t static mraa_result_t
mraa_ftdi_ft4222_gpio_write_replace(mraa_gpio_context dev, int write_value) mraa_ftdi_ft4222_gpio_write_replace(mraa_gpio_context dev, int write_value)
{ {
uint8_t pin = dev->phy_pin; uint8_t pin = dev->pin;
uint8_t mask = 1 << pin; if (mraa_ftdi_ft4222_is_internal_gpio(pin)) {
uint8_t value;
if(pin >= numI2cGpioExpanderPins) {
// FTDI GPIO // FTDI GPIO
FT4222_STATUS ft4222Status = FT4222_GPIO_Write(ftHandleGPIO, (pin - numI2cGpioExpanderPins), write_value); FT4222_STATUS ft4222Status = FT4222_GPIO_Write(ftHandleGpio, dev->phy_pin, write_value);
if (FT4222_OK != ft4222Status) { if (FT4222_OK != ft4222Status) {
syslog(LOG_ERR, "FT4222_GPIO_Write failed (error %d)!\n", ft4222Status); syslog(LOG_ERR, "FT4222_GPIO_Write failed (error %d)!\n", ft4222Status);
return MRAA_ERROR_UNSPECIFIED; return MRAA_ERROR_UNSPECIFIED;
@@ -469,16 +536,17 @@ mraa_ftdi_ft4222_gpio_write_replace(mraa_gpio_context dev, int write_value)
} }
else { else {
// Expander GPIO // Expander GPIO
if (mraa_ftdi_ft4222_i2c_read_internal(ftHandle, PCA9672_ADDR, &value, 1) != 1) uint8_t mask = 1 << dev->phy_pin;
uint8_t value;
if (mraa_ftdi_ft4222_i2c_read_internal(ftHandleI2c, PCA9672_ADDR, &value, 1) != 1)
return MRAA_ERROR_UNSPECIFIED; return MRAA_ERROR_UNSPECIFIED;
if (write_value == 1) if (write_value == 1)
value |= mask; value |= mask;
else else
value &= (~mask); value &= (~mask);
if (mraa_ftdi_ft4222_i2c_write_internal(ftHandle, PCA9672_ADDR, &value, 1) != 1) if (mraa_ftdi_ft4222_i2c_write_internal(ftHandleI2c, PCA9672_ADDR, &value, 1) != 1)
return MRAA_ERROR_UNSPECIFIED; return MRAA_ERROR_UNSPECIFIED;
} }
return MRAA_SUCCESS; return MRAA_SUCCESS;
} }
@@ -487,30 +555,24 @@ mraa_ftdi_ft4222_gpio_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t dir)
{ {
switch (dir) { switch (dir) {
case MRAA_GPIO_IN: case MRAA_GPIO_IN:
if (dev->phy_pin >= numI2cGpioExpanderPins) { if (mraa_ftdi_ft4222_is_internal_gpio(dev->pin))
pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_INPUT; return ftdi_ft4222_set_internal_gpio_dir(dev->phy_pin, GPIO_INPUT);
if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK) else
return MRAA_ERROR_UNSPECIFIED; return mraa_ftdi_ft4222_gpio_write_replace(dev, 1);
}
return MRAA_SUCCESS;
case MRAA_GPIO_OUT: case MRAA_GPIO_OUT:
if (dev->phy_pin >= numI2cGpioExpanderPins) { if (mraa_ftdi_ft4222_is_internal_gpio(dev->pin))
pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_OUTPUT; return ftdi_ft4222_set_internal_gpio_dir(dev->phy_pin, GPIO_OUTPUT);
if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK) else
return MRAA_ERROR_UNSPECIFIED; return MRAA_SUCCESS;
}
return MRAA_SUCCESS;
case MRAA_GPIO_OUT_HIGH: case MRAA_GPIO_OUT_HIGH:
if (dev->phy_pin >= numI2cGpioExpanderPins) { if (mraa_ftdi_ft4222_is_internal_gpio(dev->pin)) {
pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_OUTPUT; if (ftdi_ft4222_set_internal_gpio_dir(dev->phy_pin, GPIO_OUTPUT) != MRAA_SUCCESS)
if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK)
return MRAA_ERROR_UNSPECIFIED; return MRAA_ERROR_UNSPECIFIED;
} }
return mraa_ftdi_ft4222_gpio_write_replace(dev, 1); return mraa_ftdi_ft4222_gpio_write_replace(dev, 1);
case MRAA_GPIO_OUT_LOW: case MRAA_GPIO_OUT_LOW:
if (dev->phy_pin >= numI2cGpioExpanderPins) { if (mraa_ftdi_ft4222_is_internal_gpio(dev->pin)) {
pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_OUTPUT; if (ftdi_ft4222_set_internal_gpio_dir(dev->phy_pin, GPIO_OUTPUT) != MRAA_SUCCESS)
if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK)
return MRAA_ERROR_UNSPECIFIED; return MRAA_ERROR_UNSPECIFIED;
} }
return mraa_ftdi_ft4222_gpio_write_replace(dev, 0); return mraa_ftdi_ft4222_gpio_write_replace(dev, 0);
@@ -519,23 +581,37 @@ mraa_ftdi_ft4222_gpio_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t dir)
} }
} }
static void
mraa_ftdi_ft4222_sleep_ms(unsigned long mseconds)
{
struct timespec sleepTime;
sleepTime.tv_sec = mseconds / 1000; // Number of seconds
sleepTime.tv_nsec = (mseconds % 1000) * 1000000; // Convert fractional seconds to nanoseconds
// Iterate nanosleep in a loop until the total sleep time is the original
// value of the seconds parameter
while ((nanosleep(&sleepTime, &sleepTime) != 0) && (errno == EINTR))
;
}
static void* static void*
mraa_ftdi_ft4222_gpio_interrupt_handler_replace(mraa_gpio_context dev) mraa_ftdi_ft4222_gpio_interrupt_handler_replace(mraa_gpio_context dev)
{ {
#ifdef USE_FT4222_GPIO_TRIGGER
// FIXME: Use big buffer; shouldn't be more than this many events to read
GPIO_Trigger event_buf[256];
int prev_level = mraa_ftdi_ft4222_gpio_read_replace(dev);
while (1) {
uint16 num_events = 0;
FT4222_STATUS status = FT4222_GPIO_GetTriggerStatus(ftHandleGpio, GPIO_PORT_IO_STATUS, &num_events);
if (status != FT4222_OK)
printf("FT4222_GPIO_GetTriggerStatus failed with code %d\n", status);
printf("%u: FT4222_GPIO_GetTriggerStatus Events = %d\n", mraa_ftdi_ft4222_get_tick_count_ms(), num_events);
if (num_events > 0) {
int level = mraa_ftdi_ft4222_gpio_read_replace(dev);
uint16 num_events_read;
FT4222_GPIO_ReadTriggerQueue(ftHandleGpio, GPIO_PORT_IO_STATUS, event_buf, num_events, &num_events_read);
// printf("%u: FT4222_GPIO_ReadTriggerQueue Events= %d\n", mraa_ftdi_ft4222_get_tick_count_ms(), num_events_read);
printf("%u: level = %d\n", mraa_ftdi_ft4222_get_tick_count_ms(), level);
if (level != prev_level) {
dev->isr(dev->isr_args);
prev_level = level;
}
}
mraa_ftdi_ft4222_sleep_ms(20);
// int level = mraa_ftdi_ft4222_gpio_read_replace(dev);
// printf("level = %d\n", level);
}
#else
int prev_level = mraa_ftdi_ft4222_gpio_read_replace(dev); int prev_level = mraa_ftdi_ft4222_gpio_read_replace(dev);
while (1) { while (1) {
int level = mraa_ftdi_ft4222_gpio_read_replace(dev); int level = mraa_ftdi_ft4222_gpio_read_replace(dev);
@@ -544,9 +620,9 @@ mraa_ftdi_ft4222_gpio_interrupt_handler_replace(mraa_gpio_context dev)
dev->isr(dev->isr_args); dev->isr(dev->isr_args);
prev_level = level; prev_level = level;
} }
// printf("mraa_ftdi_ft4222_gpio_interrupt_handler_replace\n");
mraa_ftdi_ft4222_sleep_ms(100); mraa_ftdi_ft4222_sleep_ms(100);
} }
#endif
return NULL; return NULL;
} }
@@ -589,42 +665,38 @@ mraa_ftdi_ft4222()
return NULL; return NULL;
numI2cGpioExpanderPins = mraa_ftdi_ft4222_detect_io_expander(); numI2cGpioExpanderPins = mraa_ftdi_ft4222_detect_io_expander();
int pinIndex = 0; int pinIndex = 0;
int numUsbPins = numI2cGpioExpanderPins + 4; // Add GPIO0/SDA, GPIO1/SCL, GPIO2, GPIO3 int numUsbGpio = numFt4222GpioPins + numI2cGpioExpanderPins;
int numI2cBusses = 1 + mraa_ftdi_ft4222_detect_i2c_switch();
int numUsbPins = numUsbGpio + 2 * (numI2cBusses-1); // Add SDA and SCL for each i2c switch bus
mraa_pincapabilities_t pinCapsI2c = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 1, 0, 0 };
mraa_pincapabilities_t pinCapsI2cGpio = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 };
mraa_pincapabilities_t pinCapsGpio = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
sub_plat->platform_name = PLATFORM_NAME; sub_plat->platform_name = PLATFORM_NAME;
sub_plat->phy_pin_count = numUsbPins; sub_plat->phy_pin_count = numUsbPins;
sub_plat->gpio_count = numUsbPins; sub_plat->gpio_count = numUsbGpio;
mraa_pininfo_t* pins = (mraa_pininfo_t*) malloc(sizeof(mraa_pininfo_t) * numUsbPins); mraa_pininfo_t* pins = (mraa_pininfo_t*) malloc(sizeof(mraa_pininfo_t) * numUsbPins);
if (pins == NULL) { if (pins == NULL) {
return NULL; return NULL;
} }
sub_plat->pins = pins; 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 < numI2cGpioExpanderPins; ++pinIndex) {
char name[8];
sprintf(name, "Pin%d", pinIndex);
strncpy(sub_plat->pins[pinIndex].name, name, 8);
sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
sub_plat->pins[pinIndex].gpio.mux_total = 0;
}
int bus = 0; int bus = 0;
sub_plat->i2c_bus_count = 1; sub_plat->i2c_bus_count = numI2cBusses;
sub_plat->def_i2c_bus = bus; sub_plat->def_i2c_bus = bus;
sub_plat->i2c_bus[bus].bus_id = bus; sub_plat->i2c_bus[bus].bus_id = bus;
// I2c pins (these are virtual, entries are required to configure i2c layer) // I2c pins (these are virtual, entries are required to configure i2c layer)
mraa_pincapabilities_t pinCapsI2c = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }; // We currently assume that GPIO 0/1 are reserved for i2c operation
strncpy(sub_plat->pins[pinIndex].name, "SCL/GPIO0", 10); strncpy(sub_plat->pins[pinIndex].name, "IGPIO0/SCL0", MRAA_PIN_NAME_SIZE);
sub_plat->pins[pinIndex].capabilites = pinCapsI2c; sub_plat->pins[pinIndex].capabilites = pinCapsI2cGpio;
sub_plat->pins[pinIndex].gpio.pinmap = pinIndex; sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
sub_plat->pins[pinIndex].gpio.mux_total = 0; sub_plat->pins[pinIndex].gpio.mux_total = 0;
sub_plat->pins[pinIndex].i2c.mux_total = 0; sub_plat->pins[pinIndex].i2c.mux_total = 0;
sub_plat->i2c_bus[bus].scl = pinIndex; sub_plat->i2c_bus[bus].scl = pinIndex;
pinIndex++; pinIndex++;
strncpy(sub_plat->pins[pinIndex].name, "SDA/GPIO1", 10); strncpy(sub_plat->pins[pinIndex].name, "IGPIO1/SDA0", MRAA_PIN_NAME_SIZE);
sub_plat->pins[pinIndex].capabilites = pinCapsI2c; sub_plat->pins[pinIndex].capabilites = pinCapsI2cGpio;
sub_plat->pins[pinIndex].gpio.pinmap = pinIndex; sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
sub_plat->pins[pinIndex].gpio.mux_total = 0; sub_plat->pins[pinIndex].gpio.mux_total = 0;
sub_plat->pins[pinIndex].i2c.mux_total = 0; sub_plat->pins[pinIndex].i2c.mux_total = 0;
@@ -632,15 +704,42 @@ mraa_ftdi_ft4222()
pinIndex++; pinIndex++;
// FTDI4222 gpio // FTDI4222 gpio
strncpy(sub_plat->pins[pinIndex].name, "GPIO2", 8); strncpy(sub_plat->pins[pinIndex].name, "INT-GPIO2", MRAA_PIN_NAME_SIZE);
sub_plat->pins[pinIndex].capabilites = pinCapsGpio; sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
sub_plat->pins[pinIndex].gpio.pinmap = pinIndex; sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
sub_plat->pins[pinIndex].gpio.mux_total = 0; sub_plat->pins[pinIndex].gpio.mux_total = 0;
pinIndex++; pinIndex++;
strncpy(sub_plat->pins[pinIndex].name, "GPIO3", 8); strncpy(sub_plat->pins[pinIndex].name, "INT-GPIO3", MRAA_PIN_NAME_SIZE);
sub_plat->pins[pinIndex].capabilites = pinCapsGpio; sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
sub_plat->pins[pinIndex].gpio.pinmap = pinIndex; sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
sub_plat->pins[pinIndex].gpio.mux_total = 0; sub_plat->pins[pinIndex].gpio.mux_total = 0;
pinIndex++;
// Virtual gpio pins on i2c I/O expander.
int i;
for (i = 0; i < numI2cGpioExpanderPins; ++i) {
snprintf(sub_plat->pins[pinIndex].name, MRAA_PIN_NAME_SIZE, "EXP-GPIO%d", i);
sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
sub_plat->pins[pinIndex].gpio.mux_total = 0;
pinIndex++;
}
// Now add any extra i2c busses behind i2c switch
for (bus = 1; bus < numI2cBusses; ++bus) {
sub_plat->i2c_bus[bus].bus_id = bus;
sub_plat->pins[pinIndex].i2c.mux_total = 0;
snprintf(sub_plat->pins[pinIndex].name, MRAA_PIN_NAME_SIZE, "SDA%d", bus);
sub_plat->pins[pinIndex].capabilites = pinCapsI2c;
sub_plat->i2c_bus[bus].sda = pinIndex;
pinIndex++;
snprintf(sub_plat->pins[pinIndex].name, MRAA_PIN_NAME_SIZE, "SCL%d", bus);
sub_plat->pins[pinIndex].capabilites = pinCapsI2c;
sub_plat->pins[pinIndex].i2c.mux_total = 0;
sub_plat->i2c_bus[bus].scl = pinIndex;
pinIndex++;
}
// Set override functions // Set override functions
mraa_adv_func_t* func_table = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t)); mraa_adv_func_t* func_table = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t));