ftdi_ft4222.c revision 7d3978fad94b70b4cb0dba9231b30870022f8563
1e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang/*
2e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Author: Henry Bruce <henry.bruce@intel.com>
3e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Copyright (c) 2015 Intel Corporation.
4e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *
5e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Permission is hereby granted, free of charge, to any person obtaining
6e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * a copy of this software and associated documentation files (the
7e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * "Software"), to deal in the Software without restriction, including
8e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * without limitation the rights to use, copy, modify, merge, publish,
9e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * distribute, sublicense, and/or sell copies of the Software, and to
10e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * permit persons to whom the Software is furnished to do so, subject to
11e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * the following conditions:
12e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *
13e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * The above copyright notice and this permission notice shall be
14e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * included in all copies or substantial portions of the Software.
15e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *
16e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang */
24e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
25e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <stdlib.h>
26e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <string.h>
27e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <time.h>
28e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <errno.h>
29e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "linux/i2c-dev.h"
30e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "common.h"
31e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "ftd2xx.h"
32e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "libft4222.h"
33e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "usb/ftdi_ft4222.h"
34e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
35e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#define PLATFORM_NAME "FTDI FT4222"
36e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#define I2CM_ERROR(status) (((status) &0x02) != 0)
37e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#define PCA9672_ADDR 0x20
38e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
39e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
407d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serbanstatic FT_HANDLE ftHandleGPIO = (FT_HANDLE) NULL; //GPIO Handle
417d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serbanstatic FT_HANDLE ftHandle = (FT_HANDLE) NULL; //I2C/SPI Handle
427d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serbanstatic GPIO_Dir pinDirection[] = {GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT};
43e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic int bus_speed = 400;
447d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serbanstatic int numI2cGpioExpanderPins;
45e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
46e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
47e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_init()
48e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
49e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_result_t mraaStatus = MRAA_SUCCESS;
50e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT_DEVICE_LIST_INFO_NODE* devInfo = NULL;
517d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    FT_STATUS ftStatus;
52e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    DWORD numDevs = 0;
53e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    int i;
54e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    int retCode = 0;
55e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
56e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ftStatus = FT_CreateDeviceInfoList(&numDevs);
57e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (ftStatus != FT_OK) {
58e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT_CreateDeviceInfoList failed: error code %d\n", ftStatus);
59e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
60e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
61e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
62e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
63e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (numDevs == 0) {
64e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "No FT4222 devices connected.\n");
65e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
66e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
67e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
68e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    devInfo = calloc((size_t) numDevs, sizeof(FT_DEVICE_LIST_INFO_NODE));
69e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (devInfo == NULL) {
70e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222 allocation failure.\n");
71e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
72e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
73e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
74e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
75e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ftStatus = FT_GetDeviceInfoList(devInfo, &numDevs);
76e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (ftStatus != FT_OK) {
77e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT_GetDeviceInfoList failed (error code %d)\n", (int) ftStatus);
78e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
79e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
80e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
81e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
82e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    /*
83e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            FT4222_Version ft4222Version;
84e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            FT4222_STATUS ft4222Status = FT4222_GetVersion(ftHandle, &ft4222Version);
85e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            if (FT4222_OK == ft4222Status){
86e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang                syslog(LOG_NOTICE, "FT4222_GetVersion %08X %08X\n", ft4222Version.chipVersion,
87e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang       ft4222Version.dllVersion);
88e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang             } else
89e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang                syslog(LOG_ERR, "FT4222_GetVersion failed with code %d", ft4222Status);
90e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    */
91e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
92e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    syslog(LOG_NOTICE, "FT_GetDeviceInfoList returned %d devices\n", numDevs);
937d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
947d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if(numDevs > 2) {
957d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        syslog(LOG_ERR, "CNFMODE not supported. Valid modes are 0 or 3.\n");
96e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
97e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
98e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
99e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
1007d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    // CNFMODE 0, GPIO interface available.
1017d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if(numDevs = 2) {
1027d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        ftStatus = FT_OpenEx((PVOID)(uintptr_t) devInfo[1].LocId, FT_OPEN_BY_LOCATION, &ftHandleGPIO);
1037d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (ftStatus != FT_OK) {
1047d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            syslog(LOG_ERR, "FT_OpenEx GPIO handle failed (error %d)\n", (int) ftStatus);
1057d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            mraaStatus = MRAA_ERROR_NO_RESOURCES;
1067d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            goto init_exit;
1077d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        }
1087d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
1097d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        // Disable Suspend and Wake on GPIO2 & GPIO3
1107d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        FT4222_SetSuspendOut(ftHandleGPIO, 0);
1117d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        FT4222_SetWakeUpInterrupt(ftHandleGPIO, 0);
1127d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
1137d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        ftStatus =  FT4222_GPIO_Init(ftHandleGPIO, pinDirection);
1147d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (ftStatus != FT_OK) {
1157d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            syslog(LOG_ERR, "FT4222_GPIO_Init failed (error %d)\n", (int) ftStatus);
1167d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            mraaStatus = MRAA_ERROR_NO_RESOURCES;
1177d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            goto init_exit;
1187d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        }
1197d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
1207d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
1217d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    // I2C or SPI interface.
1227d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    ftStatus = FT_OpenEx((PVOID)(uintptr_t) devInfo[0].LocId, FT_OPEN_BY_LOCATION, &ftHandle);
123e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (ftStatus != FT_OK) {
1247d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        syslog(LOG_ERR, "FT_OpenEx I2C handle failed (error %d)\n", (int) ftStatus);
125e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
126e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
127e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
128e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
1297d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    // Tell the FT4222 to be an I2C Master by default on init.
130e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, bus_speed);
131e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status) {
132e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
133e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
134e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
135e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
136e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
137e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Reset the I2CM registers to a known state.
138e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
139e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status) {
140e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
141e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraaStatus = MRAA_ERROR_NO_RESOURCES;
142e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        goto init_exit;
143e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
144e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
145e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhanginit_exit:
146e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (devInfo != NULL)
147e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        ;
148e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    free(devInfo);
149e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (mraaStatus == MRAA_SUCCESS)
150e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_NOTICE, "mraa_ftdi_ft4222_init completed successfully\n");
151e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return mraaStatus;
152e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
153e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
154e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
155e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
156e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_get_version(unsigned int* versionChip, unsigned int* versionLib)
157e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
158e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (ftHandle != NULL) {
159e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        FT4222_Version ft4222Version;
160e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        FT4222_STATUS ft4222Status = FT4222_GetVersion(ftHandle, &ft4222Version);
161e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        if (FT4222_OK == ft4222Status) {
162e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            *versionChip = (unsigned int) ft4222Version.chipVersion;
163e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            *versionLib = (unsigned int) ft4222Version.dllVersion;
164e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            syslog(LOG_NOTICE, "FT4222_GetVersion %08X %08X\n", *versionChip, *versionLib);
165e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return MRAA_SUCCESS;
166e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        } else {
167e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            syslog(LOG_ERR, "libmraa: FT4222_GetVersion failed (error %d)\n", (int) ft4222Status);
168e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return MRAA_ERROR_NO_RESOURCES;
169e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        }
170e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    } else {
171e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "libmraa: bad FT4222 handle\n");
172e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
173e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
174e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
175e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
176e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
177e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic int
178e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_read_internal(FT_HANDLE handle, uint8_t addr, uint8_t* data, int length)
179e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
180e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint16 bytesRead = 0;
181e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8 controllerStatus;
182e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // syslog(LOG_NOTICE, "FT4222_I2CMaster_Read(%#02X, %#02X)", addr, length);
183e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT4222_STATUS ft4222Status = FT4222_I2CMaster_Read(handle, addr, data, length, &bytesRead);
184e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ft4222Status = FT4222_I2CMaster_GetStatus(ftHandle, &controllerStatus);
185e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus)) {
186e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Read failed (error %d)\n", (int) ft4222Status);
187e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
188e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
189e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return bytesRead;
190e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
191e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
192e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic int
193e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_write_internal(FT_HANDLE handle, uint8_t addr, const uint8_t* data, int bytesToWrite)
194e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
195e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint16 bytesWritten = 0;
196e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8 controllerStatus;
197e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // syslog(LOG_NOTICE, "FT4222_I2CMaster_Write(%#02X, %#02X, %d)", addr, *data, bytesToWrite);
198e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT4222_STATUS ft4222Status =
199e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT4222_I2CMaster_Write(handle, addr, (uint8_t*) data, bytesToWrite, &bytesWritten);
200e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ft4222Status = FT4222_I2CMaster_GetStatus(ftHandle, &controllerStatus);
201e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status || I2CM_ERROR(controllerStatus)) {
202e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Write failed (error %d)\n", (int) ft4222Status);
203e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
204e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
205e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
206e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (bytesWritten != bytesToWrite)
207e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Write wrote %u of %u bytes.\n", bytesWritten, bytesToWrite);
208e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
209e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return bytesWritten;
210e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
211e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
2127d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban// Function detects known I2C expanders and returns the number of GPIO pins on expander
2137d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serbanstatic int
214e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_detect_io_expander()
215e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
216e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t data;
2177d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if(mraa_ftdi_ft4222_i2c_read_internal(ftHandle, PCA9672_ADDR, &data, 1) == 1) {
2187d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return 8;
2197d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
2207d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    return 0;
221e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
222e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
223e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
224e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang/******************* I2C functions *******************/
2257d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban// Function not currently mapped or used since we have virtual pin definitions
226e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_i2c_context
2277d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serbanmraa_ftdi_ft4222_i2c_init_raw_replace(unsigned int bus)
228e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
229e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Tell the FT4222 to be an I2C Master.
230e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, bus_speed);
231e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status) {
232e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
233e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
234e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
235e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
236e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Reset the I2CM registers to a known state.
237e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
238e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status) {
239e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
240e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
241e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
242e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
243e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_i2c_context dev = (mraa_i2c_context) malloc(sizeof(struct _i2c));
244e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev == NULL) {
245e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_CRIT, "i2c: Failed to allocate memory for context");
246e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
247e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
248e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
249e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->handle = ftHandle;
250e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->fh = -1;              // We don't use file descriptors
251e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->funcs = I2C_FUNC_I2C; // Advertise minimal i2c support as per
252e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang                               // https://www.kernel.org/doc/Documentation/i2c/functionality
253e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return dev;
254e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
255e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
256e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
257e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_init_bus_replace(mraa_i2c_context dev)
258e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
259e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Tell the FT4222 to be an I2C Master.
260e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FT4222_STATUS ft4222Status = FT4222_I2CMaster_Init(ftHandle, 400);
261e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status) {
262e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Init failed (error %d)!\n", ft4222Status);
263e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_NO_RESOURCES;
264e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
265e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
266e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Reset the I2CM registers to a known state.
267e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
268e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (FT4222_OK != ft4222Status) {
269e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "FT4222_I2CMaster_Reset failed (error %d)!\n", ft4222Status);
270e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_NO_RESOURCES;
271e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
272e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
2737d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    syslog(LOG_NOTICE, "I2C interface enabled GPIO0 and GPIO1 will be unavailable.\n");
2747d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
275e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->handle = ftHandle;
276e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->fh = -1;              // We don't use file descriptors
277e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->funcs = I2C_FUNC_I2C; // Advertise minimal i2c support as per
278e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang                               // https://www.kernel.org/doc/Documentation/i2c/functionality
279e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
280e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
281e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
282e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
283e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
284e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode)
285e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
286e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    switch (mode) {
287e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_I2C_STD: /**< up to 100Khz */
288e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            bus_speed = 100;
289e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
290e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        MRAA_I2C_FAST: /**< up to 400Khz */
291e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            bus_speed = 400;
292e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
293e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        MRAA_I2C_HIGH: /**< up to 3.4Mhz */
294e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            bus_speed = 3400;
295e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
296e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
297e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
298e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
299e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
300e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
301e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
302e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_address(mraa_i2c_context dev, uint8_t addr)
303e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
304e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->addr = (int) addr;
305e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return FT4222_I2CMaster_Init(ftHandle, bus_speed) == FT4222_OK ? MRAA_SUCCESS : MRAA_ERROR_NO_RESOURCES;
306e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
307e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
308e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
309e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic int
310e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_read(mraa_i2c_context dev, uint8_t* data, int length)
311e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
312e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, data, length);
313e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
314e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
315e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic uint8_t
316e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_read_byte(mraa_i2c_context dev)
317e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
3187d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    uint8_t data;
3197d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if (mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, &data, 1) == 1)
3207d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return data;
3217d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    else
3227d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return 0;
323e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
324e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
325e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
326e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic uint16_t
327e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_read_word_data(mraa_i2c_context dev, uint8_t command)
328e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
3297d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    uint8_t buf[2];
3307d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    uint16_t data;
3317d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if (mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, &command, 1) != 1)
3327d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return 0;
3337d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if (mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, buf, 2) != 2)
3347d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return 0;
3357d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    data = *(uint16_t*)buf;
3367d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    return data;
337e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
338e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
339e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic int
340e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_read_bytes_data(mraa_i2c_context dev, uint8_t command, uint8_t* data, int length)
341e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
3427d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if (mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, &command, 1) != 1)
3437d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return 0;
3447d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    return mraa_ftdi_ft4222_i2c_read_internal(dev->handle, dev->addr, data, length);
345e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
346e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
347e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
348e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
349e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWrite)
350e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
351e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint16 bytesWritten = mraa_ftdi_ft4222_i2c_write_internal(dev->handle, dev->addr, data, bytesToWrite);
352e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return bytesToWrite == bytesWritten ? MRAA_SUCCESS : MRAA_ERROR_INVALID_HANDLE;
353e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
354e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
355e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
356e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
357e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_write_byte(mraa_i2c_context dev, uint8_t data)
358e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
359e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return mraa_ftdi_ft4222_i2c_write(dev, &data, 1);
360e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
361e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
362e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
363e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic uint8_t
364e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_read_byte_data(mraa_i2c_context dev, uint8_t command)
365e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
366e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    const uint8_t reg_addr = command;
367e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t data;
368e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (mraa_ftdi_ft4222_i2c_write(dev, &reg_addr, 1) != MRAA_SUCCESS)
369e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
370e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (mraa_ftdi_ft4222_i2c_read(dev, &data, 1) != 1)
371e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
372e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return data;
373e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
374e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
375e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
376e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_write_byte_data(mraa_i2c_context dev, const uint8_t data, const uint8_t command)
377e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
378e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t buf[2];
379e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    buf[0] = command;
380e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    buf[1] = data;
381e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return mraa_ftdi_ft4222_i2c_write(dev, buf, 2);
382e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
383e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
384e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
385e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_write_word_data(mraa_i2c_context dev, const uint16_t data, const uint8_t command)
386e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
387e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t buf[3];
388e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    buf[0] = command;
389e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    buf[1] = (uint8_t) data;
390e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    buf[2] = (uint8_t)(data >> 8);
391e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return mraa_ftdi_ft4222_i2c_write(dev, buf, 3);
392e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
393e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
394e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
395e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_i2c_stop(mraa_i2c_context dev)
396e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
397e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
398e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
399e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
400e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang/******************* GPIO functions *******************/
401e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
402e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
403e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_init_internal_replace(int pin)
404e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
4057d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if ((pin - numI2cGpioExpanderPins) == 0 || (pin - numI2cGpioExpanderPins) == 1) {
4067d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        syslog(LOG_NOTICE, "Closing I2C interface to enable GPIO%d\n", pin);
4077d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
4087d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        /* Replace with call to SPI init when SPI is fully implemented */
4097d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        FT4222_STATUS ft4222Status = FT4222_SPIMaster_Init(ftHandle, SPI_IO_SINGLE, CLK_DIV_4, CLK_IDLE_HIGH, CLK_LEADING, 0x01);
4107d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (FT4222_OK != ft4222Status){
4117d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            syslog(LOG_ERR, "Failed to close I2C interface and start SPI (error %d)!\n", ft4222Status);
4127d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_ERROR_NO_RESOURCES;
4137d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        }
4147d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
415e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
416e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
417e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
418e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
419e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_mode_replace(mraa_gpio_context dev, mraa_gpio_mode_t mode)
420e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
421e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
422e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
423e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
424e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
425e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_edge_mode_replace(mraa_gpio_context dev, mraa_gpio_edge_t mode)
426e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
427e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
428e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
429e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
430e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic int
431e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_read_replace(mraa_gpio_context dev)
432e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
433e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t pin = dev->phy_pin;
434e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t mask = 1 << pin;
435e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t value;
4367d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
4377d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if(pin >= numI2cGpioExpanderPins) {
4387d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        // FTDI GPIO
4397d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        FT4222_STATUS ft4222Status = FT4222_GPIO_Read(ftHandleGPIO, (pin - numI2cGpioExpanderPins), (BOOL*)&value);
4407d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (FT4222_OK != ft4222Status) {
4417d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            syslog(LOG_ERR, "FT4222_GPIO_Read failed (error %d)!\n", ft4222Status);
4427d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return -1;
4437d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        }
4447d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return value;
4457d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
4467d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    else {
4477d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        // Expander GPIO
4487d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (mraa_ftdi_ft4222_i2c_read_internal(ftHandle, PCA9672_ADDR, &value, 1) != 1)
4497d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return -1;
4507d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        return (value & mask) == mask;
4517d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
452e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
453e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
454e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
455e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
456e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_write_replace(mraa_gpio_context dev, int write_value)
457e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
458e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t pin = dev->phy_pin;
459e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t mask = 1 << pin;
460e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    uint8_t value;
4617d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
4627d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    if(pin >= numI2cGpioExpanderPins) {
4637d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        // FTDI GPIO
4647d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        FT4222_STATUS ft4222Status = FT4222_GPIO_Write(ftHandleGPIO, (pin - numI2cGpioExpanderPins), write_value);
4657d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (FT4222_OK != ft4222Status) {
4667d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            syslog(LOG_ERR, "FT4222_GPIO_Write failed (error %d)!\n", ft4222Status);
4677d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_ERROR_UNSPECIFIED;
4687d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        }
4697d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
4707d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    else {
4717d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        // Expander GPIO
4727d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (mraa_ftdi_ft4222_i2c_read_internal(ftHandle, PCA9672_ADDR, &value, 1) != 1)
4737d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_ERROR_UNSPECIFIED;
4747d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (write_value == 1)
4757d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            value |= mask;
4767d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        else
4777d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            value &= (~mask);
4787d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        if (mraa_ftdi_ft4222_i2c_write_internal(ftHandle, PCA9672_ADDR, &value, 1) != 1)
4797d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_ERROR_UNSPECIFIED;
4807d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    }
4817d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
482e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
483e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
484e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
485e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_result_t
486e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t dir)
487e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
488e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    switch (dir) {
489e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_GPIO_IN:
4907d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            if (dev->phy_pin >= numI2cGpioExpanderPins) {
4917d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_INPUT;
4927d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK)
4937d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                    return MRAA_ERROR_UNSPECIFIED;
4947d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            }
4957d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_SUCCESS;
4967d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        case MRAA_GPIO_OUT:
4977d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            if (dev->phy_pin >= numI2cGpioExpanderPins) {
4987d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_OUTPUT;
4997d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK)
5007d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                    return MRAA_ERROR_UNSPECIFIED;
5017d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            }
5027d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_SUCCESS;
503e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_GPIO_OUT_HIGH:
5047d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            if (dev->phy_pin >= numI2cGpioExpanderPins) {
5057d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_OUTPUT;
5067d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK)
5077d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                    return MRAA_ERROR_UNSPECIFIED;
5087d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            }
509e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return mraa_ftdi_ft4222_gpio_write_replace(dev, 1);
510e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_GPIO_OUT_LOW:
5117d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            if (dev->phy_pin >= numI2cGpioExpanderPins) {
5127d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                pinDirection[dev->phy_pin - numI2cGpioExpanderPins] = GPIO_OUTPUT;
5137d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                if (FT4222_GPIO_Init(ftHandleGPIO, pinDirection) != FT4222_OK)
5147d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban                    return MRAA_ERROR_UNSPECIFIED;
5157d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            }
516e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return mraa_ftdi_ft4222_gpio_write_replace(dev, 0);
517e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        default:
5187d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            return MRAA_ERROR_INVALID_PARAMETER;
519e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
520e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
521e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
522e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic void
523e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_sleep_ms(unsigned long mseconds)
524e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
525e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    struct timespec sleepTime;
526e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
527e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sleepTime.tv_sec = mseconds / 1000;              // Number of seconds
528e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sleepTime.tv_nsec = (mseconds % 1000) * 1000000; // Convert fractional seconds to nanoseconds
529e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
530e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Iterate nanosleep in a loop until the total sleep time is the original
531e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // value of the seconds parameter
532e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    while ((nanosleep(&sleepTime, &sleepTime) != 0) && (errno == EINTR))
533e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        ;
534e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
535e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
536e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic void*
537e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_gpio_interrupt_handler_replace(mraa_gpio_context dev)
538e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
539e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    int prev_level = mraa_ftdi_ft4222_gpio_read_replace(dev);
540e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    while (1) {
541e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        int level = mraa_ftdi_ft4222_gpio_read_replace(dev);
5427d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        // MRAA_GPIO_EDGE_BOTH
543e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        if (level != prev_level) {
544e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            dev->isr(dev->isr_args);
545e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            prev_level = level;
546e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        }
547e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        // printf("mraa_ftdi_ft4222_gpio_interrupt_handler_replace\n");
548e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraa_ftdi_ft4222_sleep_ms(100);
549e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
550e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return NULL;
551e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
552e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
553e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic void
554e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_populate_i2c_func_table(mraa_adv_func_t* func_table)
555e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
556e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_init_bus_replace = &mraa_ftdi_ft4222_i2c_init_bus_replace;
557e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_set_frequency_replace = &mraa_ftdi_ft4222_i2c_frequency;
558e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_address_replace = &mraa_ftdi_ft4222_i2c_address;
559e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_read_replace = &mraa_ftdi_ft4222_i2c_read;
560e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_read_byte_replace = &mraa_ftdi_ft4222_i2c_read_byte;
561e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_read_byte_data_replace = &mraa_ftdi_ft4222_i2c_read_byte_data;
562e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_read_word_data_replace = &mraa_ftdi_ft4222_i2c_read_word_data;
563e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_read_bytes_data_replace = &mraa_ftdi_ft4222_i2c_read_bytes_data;
564e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_write_replace = &mraa_ftdi_ft4222_i2c_write;
565e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_write_byte_replace = &mraa_ftdi_ft4222_i2c_write_byte;
566e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_write_byte_data_replace = &mraa_ftdi_ft4222_i2c_write_byte_data;
567e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_write_word_data_replace = &mraa_ftdi_ft4222_i2c_write_word_data;
568e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->i2c_stop_replace = &mraa_ftdi_ft4222_i2c_stop;
569e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
570e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
571e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic void
572e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222_populate_gpio_func_table(mraa_adv_func_t* func_table)
573e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
574e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_init_internal_replace = &mraa_ftdi_ft4222_gpio_init_internal_replace;
575e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_mode_replace = &mraa_ftdi_ft4222_gpio_mode_replace;
576e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_edge_mode_replace = &mraa_ftdi_ft4222_gpio_edge_mode_replace;
577e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_dir_replace = &mraa_ftdi_ft4222_gpio_dir_replace;
578e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_read_replace = &mraa_ftdi_ft4222_gpio_read_replace;
579e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_write_replace = &mraa_ftdi_ft4222_gpio_write_replace;
580e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    func_table->gpio_interrupt_handler_replace = &mraa_ftdi_ft4222_gpio_interrupt_handler_replace;
581e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
582e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
583e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
584e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_board_t*
585e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_ftdi_ft4222()
586e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
587e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_board_t* sub_plat = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
588e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (sub_plat == NULL)
589e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
5907d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    numI2cGpioExpanderPins = mraa_ftdi_ft4222_detect_io_expander();
591e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    int pinIndex = 0;
5927d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    int numUsbPins = numI2cGpioExpanderPins + 4; // Add GPIO0/SDA, GPIO1/SCL, GPIO2, GPIO3
593e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->platform_name = PLATFORM_NAME;
594e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->phy_pin_count = numUsbPins;
5957d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->gpio_count = numUsbPins;
596e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_pininfo_t* pins = (mraa_pininfo_t*) malloc(sizeof(mraa_pininfo_t) * numUsbPins);
597e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (pins == NULL) {
598e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
599e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
600e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->pins = pins;
601e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
602e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Virtual gpio pins on i2c I/O expander.
603e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_pincapabilities_t pinCapsGpio = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
6047d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    for (pinIndex = 0; pinIndex < numI2cGpioExpanderPins; ++pinIndex) {
605e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        char name[8];
606e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        sprintf(name, "Pin%d", pinIndex);
607e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        strncpy(sub_plat->pins[pinIndex].name, name, 8);
608e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
6097d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        sub_plat->pins[pinIndex].gpio.mux_total = 0;
610e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
611e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
612e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    int bus = 0;
613e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->i2c_bus_count = 1;
614e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->def_i2c_bus = bus;
615e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->i2c_bus[bus].bus_id = bus;
616e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
6177d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    // I2c pins (these are virtual, entries are required to configure i2c layer)
6187d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    mraa_pincapabilities_t pinCapsI2c = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 };
6197d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    strncpy(sub_plat->pins[pinIndex].name, "SCL/GPIO0", 10);
620e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->pins[pinIndex].capabilites = pinCapsI2c;
6217d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
6227d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.mux_total = 0;
623e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->pins[pinIndex].i2c.mux_total = 0;
6247d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->i2c_bus[bus].scl = pinIndex;
625e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    pinIndex++;
6267d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    strncpy(sub_plat->pins[pinIndex].name, "SDA/GPIO1", 10);
627e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->pins[pinIndex].capabilites = pinCapsI2c;
6287d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
6297d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.mux_total = 0;
630e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->pins[pinIndex].i2c.mux_total = 0;
6317d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->i2c_bus[bus].sda = pinIndex;
6327d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    pinIndex++;
6337d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban
6347d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    // FTDI4222 gpio
6357d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    strncpy(sub_plat->pins[pinIndex].name, "GPIO2", 8);
6367d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
6377d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
6387d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.mux_total = 0;
6397d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    pinIndex++;
6407d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    strncpy(sub_plat->pins[pinIndex].name, "GPIO3", 8);
6417d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].capabilites = pinCapsGpio;
6427d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.pinmap = pinIndex;
6437d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    sub_plat->pins[pinIndex].gpio.mux_total = 0;
644e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
645e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // Set override functions
646e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_adv_func_t* func_table = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t));
647e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (func_table == NULL) {
648e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
649e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
650e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_ftdi_ft4222_populate_i2c_func_table(func_table);
6517d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban    mraa_ftdi_ft4222_populate_gpio_func_table(func_table);
652e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
653e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    sub_plat->adv_func = func_table;
654e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return sub_plat;
655e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
656