1771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
29caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *Copyright (C) 2015 The Android Open Source Project
39caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *
49caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *Licensed under the Apache License, Version 2.0 (the "License");
59caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *you may not use this file except in compliance with the License.
69caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *You may obtain a copy of the License at
79caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *
89caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *     http://www.apache.org/licenses/LICENSE-2.0
99caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *
109caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *Unless required by applicable law or agreed to in writing, software
119caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *distributed under the License is distributed on an "AS IS" BASIS,
129caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *See the License for the specific language governing permissions and
149caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *limitations under the License.
1526f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury *
1626f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
1726f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * f1a6744b), and modified to suite the Chromium OS project.
1826f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury *
19771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Main libmpsse source file.
20771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
21771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Craig Heffner
22771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 27 December 2011
23771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
24771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
25771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <stdlib.h>
26771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <string.h>
27771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <stdint.h>
28771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <unistd.h>
29771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
3026f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury#include "trunks/ftdi/support.h"
31771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
32771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* List of known FT2232-based devices */
33771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct vid_pid supported_devices[] = {
34771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd"},
35771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd"},
36771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x6014, "FT232H Future Technology Devices International, Ltd"},
37771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
38771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* These devices are based on FT2232 chips, but have not been tested. */
39771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x8878, "Bus Blaster v2 (channel A)"},
40771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x8879, "Bus Blaster v2 (channel B)"},
41771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A"},
42771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0xCFF8, "Amontec JTAGkey"},
43771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x8A98, "TIAO Multi Protocol Adapter"},
44771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG"},
45771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY"},
46771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
47771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0, 0, NULL}};
48771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
49771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
50771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Opens and initializes the first FTDI device found.
51771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
52771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode      - Mode to open the device in. One of enum modes.
53771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq      - Clock frequency to use for the specified mode.
54771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - Specifies how data is clocked in/out (MSB, LSB).
55771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
563f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * Returns a pointer to an MPSSE context structure if succeeded, NULL otherwise.
57771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
58b9e482ca1162cccedcc0bbd9bd5ee9073372190dVadim Bendeburystruct mpsse_context* MPSSE(enum modes mode, int freq, int endianess) {
59771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int i = 0;
60771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  struct mpsse_context* mpsse = NULL;
61771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
62771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  for (i = 0; supported_devices[i].vid != 0; i++) {
634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    mpsse = Open(supported_devices[i].vid, supported_devices[i].pid, mode, freq,
644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                 endianess, IFACE_A, NULL, NULL);
653f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    if (mpsse) {
663f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      mpsse->description = supported_devices[i].description;
673f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      return mpsse;
68771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
69771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
70771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
713f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  return NULL;
72771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
73771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
74771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
75771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Open device by VID/PID
76771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
77771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @vid         - Device vendor ID.
78771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pid         - Device product ID.
79771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode        - MPSSE mode, one of enum modes.
80771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq        - Clock frequency to use for the specified mode.
81771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess   - Specifies how data is clocked in/out (MSB, LSB).
82771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @interface   - FTDI interface to use (IFACE_A - IFACE_D).
83771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @description - Device product description (set to NULL if not needed).
84771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @serial      - Device serial number (set to NULL if not needed).
85771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
863f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * Returns a pointer to an MPSSE context structure on success.
87771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
88771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct mpsse_context* Open(int vid,
89771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int pid,
90771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           enum modes mode,
91771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int freq,
92771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int endianess,
93771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int interface,
94771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           const char* description,
95771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           const char* serial) {
96771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return OpenIndex(vid, pid, mode, freq, endianess, interface, description,
97771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                   serial, 0);
98771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
99771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
100771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
101771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Open device by VID/PID/index
102771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
103771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @vid         - Device vendor ID.
104771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pid         - Device product ID.
105771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode        - MPSSE mode, one of enum modes.
106771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq        - Clock frequency to use for the specified mode.
107771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess   - Specifies how data is clocked in/out (MSB, LSB).
108771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @interface   - FTDI interface to use (IFACE_A - IFACE_D).
109771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @description - Device product description (set to NULL if not needed).
110771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @serial      - Device serial number (set to NULL if not needed).
111771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @index       - Device index (set to 0 if not needed).
112771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
113771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to an MPSSE context structure.
114771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On success, mpsse->open will be set to 1.
115771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On failure, mpsse->open will be set to 0.
116771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
117771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct mpsse_context* OpenIndex(int vid,
118771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int pid,
119771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                enum modes mode,
120771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int freq,
121771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int endianess,
122771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int interface,
123771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                const char* description,
124771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                const char* serial,
125771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int index) {
1261ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury  int status = 0;
127771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  struct mpsse_context* mpsse = NULL;
128771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
129771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  mpsse = malloc(sizeof(struct mpsse_context));
1303f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  if (!mpsse)
1313f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    return NULL;
1323f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1333f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  memset(mpsse, 0, sizeof(struct mpsse_context));
1343f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1353f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  /* Legacy; flushing is no longer needed, so disable it by default. */
1363f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  FlushAfterRead(mpsse, 0);
137771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1383f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  /* ftdilib initialization */
1393f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  if (ftdi_init(&mpsse->ftdi)) {
1403f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    free(mpsse);
1413f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    return NULL;
1423f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  }
1433f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1443f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  /* Set the FTDI interface  */
1453f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  ftdi_set_interface(&mpsse->ftdi, interface);
1463f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1473f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  /* Open the specified device */
1483f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  if (!ftdi_usb_open_desc_index(&mpsse->ftdi, vid, pid, description, serial,
1493f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury                                index)) {
1503f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    mpsse->mode = mode;
1513f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    mpsse->vid = vid;
1523f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    mpsse->pid = pid;
1533f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    mpsse->status = STOPPED;
1543f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    mpsse->endianess = endianess;
1553f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1563f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    /* Set the appropriate transfer size for the requested protocol */
1573f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    if (mpsse->mode == I2C)
1583f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      mpsse->xsize = I2C_TRANSFER_SIZE;
1593f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    else
1603f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      mpsse->xsize = SPI_RW_SIZE;
1613f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1623f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    status |= ftdi_usb_reset(&mpsse->ftdi);
1633f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    status |= ftdi_set_latency_timer(&mpsse->ftdi, LATENCY_MS);
1643f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    status |= ftdi_write_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE);
1653f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    status |= ftdi_read_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE);
1663f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    status |= ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET);
1673f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1683f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    if (status == 0) {
1693f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      /* Set the read and write timeout periods */
1703f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      set_timeouts(mpsse, USB_TIMEOUT);
1713f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1723f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      if (mpsse->mode != BITBANG) {
1733f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury        ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_MPSSE);
1743f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1753f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury        if (SetClock(mpsse, freq) == MPSSE_OK) {
1763f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury          if (SetMode(mpsse, endianess) == MPSSE_OK) {
1771ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury            mpsse->opened = 1;
1783f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1793f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury            /* Give the chip a few mS to initialize */
1803f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury            usleep(SETUP_DELAY);
1813f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
1823f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury            /*
1833f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury             * Not all FTDI chips support all the commands that SetMode may
1843f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury             * have sent.
1853f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury             * This clears out any errors from unsupported commands that
1863f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury             * might have been sent during set up.
187771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury             */
1883f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury            ftdi_usb_purge_buffers(&mpsse->ftdi);
189771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
190771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
1913f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury      } else {
1923f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury        /* Skip the setup functions if we're just operating in BITBANG mode
1933f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury         */
1943f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury        if (!ftdi_set_bitmode(&mpsse->ftdi, 0xFF, BITMODE_BITBANG))
1951ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury          mpsse->opened = 1;
196771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
197771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
198771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
199771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
2001ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury  if (mpsse && !mpsse->opened) {
2013f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    Close(mpsse);
2023f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    mpsse = NULL;
2033f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  }
2043f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury
205771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return mpsse;
206771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
207771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
208771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
209771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Closes the device, deinitializes libftdi, and frees the MPSSE context
210771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *pointer.
211771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
212771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
213771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
214771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
215771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
216771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid Close(struct mpsse_context* mpsse) {
2173f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  if (!mpsse)
2183f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury    return;
219771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
2201ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury  if (mpsse->opened) {
2211ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury    /* Shut these down only if initialization succeeded before. */
2221ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury    ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET);
2231ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury    ftdi_usb_close(&mpsse->ftdi);
2241ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury  }
2253f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  ftdi_deinit(&mpsse->ftdi);
2263f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury  free(mpsse);
227771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
228771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
229771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Enables bit-wise data transfers.
230771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Must be called after MPSSE() / Open() / OpenIndex().
231771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
232771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
233771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
234771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid EnableBitmode(struct mpsse_context* mpsse, int tf) {
235771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
236771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (tf) {
237771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tx |= MPSSE_BITMODE;
238771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->rx |= MPSSE_BITMODE;
239771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->txrx |= MPSSE_BITMODE;
240771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
241771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tx &= ~MPSSE_BITMODE;
242771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->rx &= ~MPSSE_BITMODE;
243771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->txrx &= ~MPSSE_BITMODE;
244771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
245771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
246771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
247771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
248771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
249771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the appropriate transmit and receive commands based on the requested
250771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *mode and byte order.
251771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
252771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse     - MPSSE context pointer.
253771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - MPSSE_MSB or MPSSE_LSB.
254771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
255771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
256771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
257771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
258771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetMode(struct mpsse_context* mpsse, int endianess) {
259771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_OK, i = 0, setup_commands_size = 0;
260c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t buf[CMD_SIZE] = {0};
261c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t setup_commands[CMD_SIZE * MAX_SETUP_COMMANDS] = {0};
262771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
263771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Do not call is_valid_context() here, as the FTDI chip may not be completely
264771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury   * configured when SetMode is called */
265771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse) {
266771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Read and write commands need to include endianess */
267771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->tx = MPSSE_DO_WRITE | endianess;
268771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->rx = MPSSE_DO_READ | endianess;
269771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->txrx = MPSSE_DO_WRITE | MPSSE_DO_READ | endianess;
270771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
271771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Clock, data out, chip select pins are outputs; all others are inputs. */
272771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->tris = DEFAULT_TRIS;
273771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
274771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Clock and chip select pins idle high; all others are low */
275771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->pidle = mpsse->pstart = mpsse->pstop = DEFAULT_PORT;
276771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
277771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* During reads and writes the chip select pin is brought low */
278771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->pstart &= ~CS;
279771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
280771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Disable FTDI internal loopback */
281771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    SetLoopback(mpsse, 0);
282771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
283771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Send ACKs by default */
284771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    SetAck(mpsse, ACK);
285771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
286771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Ensure adaptive clock is disabled */
287771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    setup_commands[setup_commands_size++] = DISABLE_ADAPTIVE_CLOCK;
288771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
289771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    switch (mpsse->mode) {
290771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI0:
291771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 0 clock idles low */
292771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle &= ~SK;
293771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart &= ~SK;
294771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop &= ~SK;
295771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 0 propogates data on the falling edge and read data on the
296771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * rising edge of the clock */
297771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx |= MPSSE_WRITE_NEG;
298771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx &= ~MPSSE_READ_NEG;
299771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_WRITE_NEG;
300771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_READ_NEG;
301771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
302771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI3:
303771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 3 clock idles high */
304771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle |= SK;
305771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart |= SK;
306771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Keep the clock low while the CS pin is brought high to ensure we
307771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * don't accidentally clock out an extra bit */
308771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop &= ~SK;
309771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 3 propogates data on the falling edge and read data on the
310771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * rising edge of the clock */
311771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx |= MPSSE_WRITE_NEG;
312771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx &= ~MPSSE_READ_NEG;
313771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_WRITE_NEG;
314771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_READ_NEG;
315771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
316771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI1:
317771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 1 clock idles low */
318771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle &= ~SK;
319771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Since this mode idles low, the start condition should ensure that the
320771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * clock is low */
321771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart &= ~SK;
322771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Even though we idle low in this mode, we need to keep the clock line
323771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * high when we set the CS pin high to prevent
324771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * an unintended clock cycle from being sent by the FT2232. This way,
325771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * the clock goes high, but does not go low until
326771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * after the CS pin goes high.
327771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         */
328771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop |= SK;
329771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Data read on falling clock edge */
330771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx |= MPSSE_READ_NEG;
331771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx &= ~MPSSE_WRITE_NEG;
332771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_READ_NEG;
333771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_WRITE_NEG;
334771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
335771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI2:
336771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI 2 clock idles high */
337771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle |= SK;
338771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart |= SK;
339771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop |= SK;
340771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Data read on falling clock edge */
341771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx |= MPSSE_READ_NEG;
342771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx &= ~MPSSE_WRITE_NEG;
343771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_READ_NEG;
344771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_WRITE_NEG;
345771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
346771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case I2C:
347771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* I2C propogates data on the falling clock edge and reads data on the
348771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * falling (or rising) clock edge */
349771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx |= MPSSE_WRITE_NEG;
350771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx &= ~MPSSE_READ_NEG;
351771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* In I2C, both the clock and the data lines idle high */
352771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle |= DO | DI;
353771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* I2C start bit == data line goes from high to low while clock line is
354771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * high */
355771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart &= ~DO & ~DI;
356771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* I2C stop bit == data line goes from low to high while clock line is
357771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * high - set data line low here, so the transition to the idle state
358771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * triggers the stop condition. */
359771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop &= ~DO & ~DI;
360771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Enable three phase clock to ensure that I2C data is available on both
361771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * the rising and falling clock edges */
362771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        setup_commands[setup_commands_size++] = ENABLE_3_PHASE_CLOCK;
363771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
364771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case GPIO:
365771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
366771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      default:
367771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_FAIL;
368771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
369771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
370771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Send any setup commands to the chip */
371771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK && setup_commands_size > 0) {
372771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval = raw_write(mpsse, setup_commands, setup_commands_size);
373771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
374771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
375771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK) {
376771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Set the idle pin states */
377771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      set_bits_low(mpsse, mpsse->pidle);
378771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
379771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* All GPIO pins are outputs, set low */
380771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->trish = 0xFF;
381771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->gpioh = 0x00;
382771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
383771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[i++] = SET_BITS_HIGH;
384771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[i++] = mpsse->gpioh;
385771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[i++] = mpsse->trish;
386771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
387771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval = raw_write(mpsse, buf, i);
388771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
389771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  } else {
390771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = MPSSE_FAIL;
391771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
392771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
393771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
394771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
395771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
396771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
397771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the appropriate divisor for the desired clock frequency.
398771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
399771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
400771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq  - Desired clock frequency in hertz.
401771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
402771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
403771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
404771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
405771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetClock(struct mpsse_context* mpsse, uint32_t freq) {
406771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
407771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  uint32_t system_clock = 0;
408771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  uint16_t divisor = 0;
409c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t buf[CMD_SIZE] = {0};
410771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
411771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Do not call is_valid_context() here, as the FTDI chip may not be completely
412771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury   * configured when SetClock is called */
413771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse) {
414771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (freq > SIX_MHZ) {
415771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = TCK_X5;
416771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      system_clock = SIXTY_MHZ;
417771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
418771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = TCK_D5;
419771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      system_clock = TWELVE_MHZ;
420771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
421771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
422771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (raw_write(mpsse, buf, 1) == MPSSE_OK) {
423771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (freq <= 0) {
424771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        divisor = 0xFFFF;
425771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      } else {
426771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        divisor = freq2div(system_clock, freq);
427771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
428771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
429771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = TCK_DIVISOR;
430771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[1] = (divisor & 0xFF);
431771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[2] = ((divisor >> 8) & 0xFF);
432771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
433771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (raw_write(mpsse, buf, 3) == MPSSE_OK) {
434771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->clock = div2freq(system_clock, divisor);
435771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_OK;
436771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
437771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
438771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
439771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
440771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
441771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
442771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
443771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
444771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Retrieves the last error string from libftdi.
445771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
446771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
447771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
448771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the last error string.
449771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
450771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyconst char* ErrorString(struct mpsse_context* mpsse) {
451771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse != NULL) {
452771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    return ftdi_get_error_string(&mpsse->ftdi);
453771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
454771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
455771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return NULL_CONTEXT_ERROR_MSG;
456771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
457771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
458771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
459771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Gets the currently configured clock rate.
460771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
461771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
462771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
463771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the existing clock rate in hertz.
464771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
465771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetClock(struct mpsse_context* mpsse) {
466771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int clock = 0;
467771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
468771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
469771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    clock = mpsse->clock;
470771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
471771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
472771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return clock;
473771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
474771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
475771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
476771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the vendor ID of the FTDI chip.
477771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
478771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
479771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
480771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the integer value of the vendor ID.
481771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
482771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetVid(struct mpsse_context* mpsse) {
483771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int vid = 0;
484771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
485771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
486771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    vid = mpsse->vid;
487771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
488771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
489771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return vid;
490771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
491771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
492771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
493771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the product ID of the FTDI chip.
494771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
495771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
496771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
497771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the integer value of the product ID.
498771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
499771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetPid(struct mpsse_context* mpsse) {
500771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int pid = 0;
501771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
502771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
503771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    pid = mpsse->pid;
504771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
505771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
506771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return pid;
507771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
508771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
509771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
510771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the description of the FTDI chip, if any.
511771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
512771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
513771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
514771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the description of the FTDI chip.
515771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
516771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyconst char* GetDescription(struct mpsse_context* mpsse) {
517771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char* description = NULL;
518771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
519771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
520771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    description = mpsse->description;
521771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
522771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
523771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return description;
524771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
525771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
526771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
527771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Enable / disable internal loopback.
528771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
529771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse  - MPSSE context pointer.
530771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @enable - Zero to disable loopback, 1 to enable loopback.
531771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
532771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
533771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
534771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
535771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetLoopback(struct mpsse_context* mpsse, int enable) {
536c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t buf[1] = {0};
537771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
538771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
539771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
540771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (enable) {
541771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = LOOPBACK_START;
542771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
543771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = LOOPBACK_END;
544771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
545771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
546771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = raw_write(mpsse, buf, 1);
547771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
548771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
549771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
550771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
551771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
552771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
553771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the idle state of the chip select pin. CS idles high by default.
554771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
555771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
556771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @idle  - Set to 1 to idle high, 0 to idle low.
557771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
558771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
559771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
560771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SetCSIdle(struct mpsse_context* mpsse, int idle) {
561771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
562771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (idle > 0) {
563771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Chip select idles high, active low */
564771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pidle |= CS;
565771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstop |= CS;
566771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstart &= ~CS;
567771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
568771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Chip select idles low, active high */
569771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pidle &= ~CS;
570771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstop &= ~CS;
571771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstart |= CS;
572771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
573771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
574771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
575771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
576771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
577771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
578771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
579771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Enables or disables flushing of the FTDI chip's RX buffers after each read
580771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *operation.
581771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Flushing is disable by default.
582771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
583771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
584771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @tf    - Set to 1 to enable flushing, or 0 to disable flushing.
585771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
586771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
587771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
588771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid FlushAfterRead(struct mpsse_context* mpsse, int tf) {
589771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  mpsse->flush_after_read = tf;
590771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
591771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
592771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
593771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
594771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data start condition.
595771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
596771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
597771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
598771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
599771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
600771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
601771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Start(struct mpsse_context* mpsse) {
602771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int status = MPSSE_OK;
603771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
604771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
605771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == I2C && mpsse->status == STARTED) {
606771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Set the default pin states while the clock is low since this is an I2C
607771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * repeated start condition */
608771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, (mpsse->pidle & ~SK));
609771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
610771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Make sure the pins are in their default idle state */
611771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, mpsse->pidle);
612771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
613771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
614771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Set the start condition */
615771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    status |= set_bits_low(mpsse, mpsse->pstart);
616771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
617771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /*
618771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * Hackish work around to properly support SPI mode 3.
619771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * SPI3 clock idles high, but needs to be set low before sending out
620771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * data to prevent unintenteded clock glitches from the FT2232.
621771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     */
622771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == SPI3) {
623771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, (mpsse->pstart & ~SK));
624771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
625771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /*
626771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * Hackish work around to properly support SPI mode 1.
627771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * SPI1 clock idles low, but needs to be set high before sending out
628771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * data to preven unintended clock glitches from the FT2232.
629771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     */
630771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    else if (mpsse->mode == SPI1) {
631771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, (mpsse->pstart | SK));
632771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
633771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
634771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STARTED;
635771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  } else {
636771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    status = MPSSE_FAIL;
637771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STOPPED;
638771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
639771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
640771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return status;
641771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
642771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
643771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
644771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Performs a bit-wise write of up to 8 bits at a time.
645771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
646771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
647771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @bits  - A byte containing the desired bits to write.
648771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - The number of bits from the 'bits' byte to write.
649771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
650771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success, MPSSE_FAIL on failure.
651771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
652f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardsonint WriteBits(struct mpsse_context* mpsse, char bits, size_t size) {
653c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t data[8] = {0};
654f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardson  size_t i = 0;
655f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardson  int retval = MPSSE_OK;
656771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
657771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (size > sizeof(data)) {
658771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    size = sizeof(data);
659771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
660771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
661771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Convert each bit in bits to an array of bytes */
662771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  for (i = 0; i < size; i++) {
663771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (bits & (1 << i)) {
664771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Be sure to honor endianess */
665771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (mpsse->endianess == LSB) {
666771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        data[i] = '\xFF';
667771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      } else {
668771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        data[size - i - 1] = '\xFF';
669771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
670771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
671771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
672771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
673771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Enable bit mode before writing, then disable it afterwards. */
674771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 1);
675771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  retval = Write(mpsse, data, size);
676771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 0);
677771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
678771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
679771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
680771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
681771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
682771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data out via the selected serial protocol.
683771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
684771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
685771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data  - Buffer of data to send.
686771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Size of data.
687771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
688771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
689771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
690771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
691f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardsonint Write(struct mpsse_context* mpsse, const void* vdata, int size) {
692f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardson  const uint8_t* data = vdata;
693c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t* buf = NULL;
694771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL, buf_size = 0, txsize = 0, n = 0;
695771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
696771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
697771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode) {
698771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      while (n < size) {
699771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        txsize = size - n;
700771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (txsize > mpsse->xsize) {
701771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          txsize = mpsse->xsize;
702771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
703771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
704771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /*
705771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * For I2C we need to send each byte individually so that we can
706771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * read back each individual ACK bit, so set the transmit size to 1.
707771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         */
708771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (mpsse->mode == I2C) {
709771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          txsize = 1;
710771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
711771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
712c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury        buf = build_block_buffer(mpsse, mpsse->tx, data + n, txsize, &buf_size);
713771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (buf) {
714771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          retval = raw_write(mpsse, buf, buf_size);
715771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          n += txsize;
716771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          free(buf);
717771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
718771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (retval == MPSSE_FAIL) {
719771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            break;
720771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
721771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
722771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          /* Read in the ACK bit and store it in mpsse->rack */
723771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (mpsse->mode == I2C) {
724c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury            raw_read(mpsse, (uint8_t*)&mpsse->rack, 1);
725771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
726771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        } else {
727771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          break;
728771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
729771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
730771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
731771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
732771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK && n == size) {
733771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval = MPSSE_OK;
734771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
735771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
736771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
737771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
738771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
739771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
740771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Performs a read. For internal use only; see Read() and ReadBits(). */
741f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardsonstatic uint8_t* InternalRead(struct mpsse_context* mpsse, int size) {
742c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t *data = NULL, *buf = NULL;
743c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t sbuf[SPI_RW_SIZE] = {0};
744771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int n = 0, rxsize = 0, data_size = 0, retval = 0;
745771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
746771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
747771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode) {
748771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf = malloc(size);
749771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (buf) {
750771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        memset(buf, 0, size);
751771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
752771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        while (n < size) {
753771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          rxsize = size - n;
754771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (rxsize > mpsse->xsize) {
755771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            rxsize = mpsse->xsize;
756771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
757771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
758771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          data = build_block_buffer(mpsse, mpsse->rx, sbuf, rxsize, &data_size);
759771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (data) {
760771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            retval = raw_write(mpsse, data, data_size);
761771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            free(data);
762771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
763771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            if (retval == MPSSE_OK) {
764771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              n += raw_read(mpsse, buf + n, rxsize);
765771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            } else {
766771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              break;
767771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            }
768771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          } else {
769771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            break;
770771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
771771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
772771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
773771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
774771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
775771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
776c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  return buf;
777771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
778771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
779771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
780771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads data over the selected serial protocol.
781771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
782771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
783771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Number of bytes to read.
784771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
785771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the read data on success.
786771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns NULL on failure.
787771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
788771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
789771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyswig_string_data Read(struct mpsse_context* mpsse, int size)
790771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
791c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendeburyuint8_t* Read(struct mpsse_context* mpsse, int size)
792771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
793771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury{
794c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t* buf = NULL;
795771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
796771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  buf = InternalRead(mpsse, size);
797771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
798771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
799771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  swig_string_data sdata = {0};
800771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.size = size;
801771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.data = buf;
802771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return sdata;
803771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
804771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return buf;
805771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
806771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
807771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
808771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
809771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Performs a bit-wise read of up to 8 bits.
810771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
811771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
812771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Number of bits to read.
813771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
814771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns an 8-bit byte containing the read bits.
815771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
816771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar ReadBits(struct mpsse_context* mpsse, int size) {
817771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char bits = 0;
818c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t* rdata = NULL;
819771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
820771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (size > 8) {
821771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    size = 8;
822771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
823771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
824771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 1);
825771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  rdata = InternalRead(mpsse, size);
826771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 0);
827771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
828771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (rdata) {
829771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* The last byte in rdata will have all the read bits set or unset as
830771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * needed. */
831771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    bits = rdata[size - 1];
832771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
833771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->endianess == MSB) {
834771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /*
835771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * In MSB mode, bits are sifted in from the left. If less than 8 bits were
836771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * read, we need to shift them left accordingly.
837771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       */
838771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      bits = bits << (8 - size);
839771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else if (mpsse->endianess == LSB) {
840771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /*
841771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * In LSB mode, bits are shifted in from the right. If less than 8 bits
842771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * were
843771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * read, we need to shift them right accordingly.
844771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       */
845771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      bits = bits >> (8 - size);
846771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
847771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
848771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    free(rdata);
849771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
850771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
851771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return bits;
852771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
853771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
854771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
855771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads and writes data over the selected serial protocol (SPI only).
856771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
857771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
858771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data  - Buffer containing bytes to write.
859771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Number of bytes to transfer.
860771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
861771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the read data on success.
862771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns NULL on failure.
863771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
864771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
865771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyswig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size)
866771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
867c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendeburyuint8_t* Transfer(struct mpsse_context* mpsse, uint8_t* data, int size)
868771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
869771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury{
870c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t *txdata = NULL, *buf = NULL;
871771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int n = 0, data_size = 0, rxsize = 0, retval = 0;
872771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
873771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
874771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Make sure we're configured for one of the SPI modes */
875771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode >= SPI0 && mpsse->mode <= SPI3) {
876771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf = malloc(size);
877771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (buf) {
878771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        memset(buf, 0, size);
879771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
880771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        while (n < size) {
881771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          /* When sending and recieving, FTDI chips don't seem to like large
882771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury           * data blocks. Limit the size of each block to SPI_TRANSFER_SIZE */
883771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          rxsize = size - n;
884771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (rxsize > SPI_TRANSFER_SIZE) {
885771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            rxsize = SPI_TRANSFER_SIZE;
886771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
887771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
8884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          txdata = build_block_buffer(mpsse, mpsse->txrx, data + n, rxsize,
8894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                      &data_size);
890771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (txdata) {
891771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            retval = raw_write(mpsse, txdata, data_size);
892771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            free(txdata);
893771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
894771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            if (retval == MPSSE_OK) {
895771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              n += raw_read(mpsse, (buf + n), rxsize);
896771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            } else {
897771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              break;
898771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            }
899771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          } else {
900771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            break;
901771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
902771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
903771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
904771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
905771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
906771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
907771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
908771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  swig_string_data sdata = {0};
909771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.size = n;
910771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.data = (char*)buf;
911771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return sdata;
912771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
913c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  return buf;
914771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
915771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
916771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
917771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
918771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the last received ACK bit.
919771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
920771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
921771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
922771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns either an ACK (0) or a NACK (1).
923771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
924771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetAck(struct mpsse_context* mpsse) {
925771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int ack = 0;
926771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
927771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
928771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    ack = (mpsse->rack & 0x01);
929771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
930771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
931771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return ack;
932771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
933771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
934771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
935771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the transmitted ACK bit.
936771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
937771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
938771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @ack   - 0 to send ACKs, 1 to send NACKs.
939771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
940771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
941771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
942771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SetAck(struct mpsse_context* mpsse, int ack) {
943771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
944771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (ack == NACK) {
945771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tack = 0xFF;
946771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
947771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tack = 0x00;
948771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
949771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
950771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
951771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
952771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
953771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
954771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
955771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Causes libmpsse to send ACKs after each read byte in I2C mode.
956771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
957771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
958771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
959771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
960771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
961771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SendAcks(struct mpsse_context* mpsse) {
962771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return SetAck(mpsse, ACK);
963771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
964771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
965771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
966771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Causes libmpsse to send NACKs after each read byte in I2C mode.
967771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
968771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
969771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
970771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
971771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
972771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SendNacks(struct mpsse_context* mpsse) {
973771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return SetAck(mpsse, NACK);
974771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
975771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
976771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
977771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data stop condition.
978771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
979771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
980771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
981771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
982771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
983771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
984771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Stop(struct mpsse_context* mpsse) {
985771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_OK;
986771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
987771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
988771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* In I2C mode, we need to ensure that the data line goes low while the
989771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * clock line is low to avoid sending an inadvertent start condition */
990771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == I2C) {
991771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval |= set_bits_low(mpsse, (mpsse->pidle & ~DO & ~SK));
992771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
993771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
994771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Send the stop condition */
995771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval |= set_bits_low(mpsse, mpsse->pstop);
996771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
997771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK) {
998771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Restore the pins to their idle states */
999771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval |= set_bits_low(mpsse, mpsse->pidle);
1000771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
1001771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1002771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STOPPED;
1003771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  } else {
1004771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = MPSSE_FAIL;
1005771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STOPPED;
1006771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1007771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1008771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1009771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1010771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1011771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1012771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the specified pin high.
1013771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1014771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1015771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin   - Pin number to set high.
1016771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1017771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
1018771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
1019771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1020771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinHigh(struct mpsse_context* mpsse, int pin) {
1021771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1022771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1023771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1024771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = gpio_write(mpsse, pin, HIGH);
1025771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1026771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1027771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1028771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1029771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1030771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1031771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the specified pin low.
1032771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1033771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1034771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin   - Pin number to set low.
1035771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1036771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
1037771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
1038771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1039771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinLow(struct mpsse_context* mpsse, int pin) {
1040771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1041771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1042771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1043771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = gpio_write(mpsse, pin, LOW);
1044771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1045771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1046771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1047771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1048771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1049771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1050771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the input/output direction of all pins. For use in BITBANG mode only.
1051771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1052771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse     - MPSSE context pointer.
1053771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @direction - Byte indicating input/output direction of each bit.  1 is out.
1054771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1055771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise.
1056771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1057771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetDirection(struct mpsse_context* mpsse, uint8_t direction) {
1058771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1059771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1060771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1061771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == BITBANG) {
1062771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (ftdi_set_bitmode(&mpsse->ftdi, direction, BITMODE_BITBANG) == 0) {
1063771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_OK;
1064771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
1065771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
1066771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1067771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1068771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1069771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1070771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1071771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1072771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the input/output value of all pins. For use in BITBANG mode only.
1073771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1074771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1075771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data  - Byte indicating bit hi/low value of each bit.
1076771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1077771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise.
1078771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1079771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint WritePins(struct mpsse_context* mpsse, uint8_t data) {
1080771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1081771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1082771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1083771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == BITBANG) {
1084771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (ftdi_write_data(&mpsse->ftdi, &data, 1) == 0) {
1085771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_OK;
1086771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
1087771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
1088771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1089771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1090771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1091771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1092771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1093771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1094771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads the state of the chip's pins. For use in BITBANG mode only.
1095771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1096771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1097771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1098771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a byte with the corresponding pin's bits set to 1 or 0.
1099771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1100771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint ReadPins(struct mpsse_context* mpsse) {
1101771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  uint8_t val = 0;
1102771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1103771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1104c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury    ftdi_read_pins((struct ftdi_context*)&mpsse->ftdi, (uint8_t*)&val);
1105771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1106771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1107771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return (int)val;
1108771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1109771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1110771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1111771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Checks if a specific pin is high or low. For use in BITBANG mode only.
1112771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1113771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1114771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin   - The pin number.
1115771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @state - The state of the pins, as returned by ReadPins.
1116771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *          If set to -1, ReadPins will automatically be called.
1117771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1118771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a 1 if the pin is high, 0 if the pin is low.
1119771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1120771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinState(struct mpsse_context* mpsse, int pin, int state) {
1121771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (state == -1) {
1122771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    state = ReadPins(mpsse);
1123771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1124771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1125771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert
1126771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury   * these defines into an absolute pin number. */
1127771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse->mode != BITBANG) {
1128771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    pin += NUM_GPIOL_PINS;
1129771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1130771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1131771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return ((state & (1 << pin)) >> pin);
1132771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1133771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1134771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1135771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Places all I/O pins into a tristate mode.
1136771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1137771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1138771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1139771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success, MPSSE_FAIL on failure.
1140771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1141771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Tristate(struct mpsse_context* mpsse) {
1142c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury  uint8_t cmd[CMD_SIZE] = {0};
1143771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1144771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Tristate the all I/O pins (FT232H only) */
1145771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  cmd[0] = TRISTATE_IO;
1146771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  cmd[1] = 0xFF;
1147771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  cmd[2] = 0xFF;
1148771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1149771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return raw_write(mpsse, cmd, sizeof(cmd));
1150771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1151