1771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 2bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/* 3bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*Copyright (C) 2015 The Android Open Source Project 4bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/* 5bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*Licensed under the Apache License, Version 2.0 (the "License"); 6bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*you may not use this file except in compliance with the License. 7bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*You may obtain a copy of the License at 8bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/* 9bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/* http://www.apache.org/licenses/LICENSE-2.0 10bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/* 11bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*Unless required by applicable law or agreed to in writing, software 12bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*distributed under the License is distributed on an "AS IS" BASIS, 13bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*See the License for the specific language governing permissions and 15bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi/*limitations under the License. 16bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi */ 1726f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * 1826f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 1926f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * f1a6744b), and modified to suite the Chromium OS project. 2026f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * 21771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Internal functions used by libmpsse. 22771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 23771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Craig Heffner 24771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 27 December 2011 25771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 26771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <string.h> 27771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 2826f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury#include "trunks/ftdi/support.h" 29771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 30771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Write data to the FTDI chip */ 31c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendeburyint raw_write(struct mpsse_context* mpsse, uint8_t* buf, int size) { 324dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int retval = MPSSE_FAIL; 334dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 344dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode) { 354dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (ftdi_write_data(&mpsse->ftdi, buf, size) == size) { 364dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn retval = MPSSE_OK; 374dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 384dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 394dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 404dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return retval; 414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 424dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 434dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Read data from the FTDI chip */ 444dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int raw_read(struct mpsse_context* mpsse, uint8_t* buf, int size) { 454dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int n = 0, r = 0; 464dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 474dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode) { 484dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn while (n < size) { 494dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn r = ftdi_read_data(&mpsse->ftdi, buf, size); 504dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (r < 0) 514dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn break; 524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn n += r; 534dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 554dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->flush_after_read) { 564dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* 574dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * Make sure the buffers are cleared after a read or subsequent reads may 584dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn *fail. 594dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * 604dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * Is this needed anymore? It slows down repetitive read operations by 614dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn *~8%. 624dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn */ 634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn ftdi_usb_purge_rx_buffer(&mpsse->ftdi); 644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 664dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 674dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return n; 684dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 694dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 704dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Sets the read and write timeout periods for bulk usb data transfers. */ 714dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn void set_timeouts(struct mpsse_context* mpsse, int timeout) { 724dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode) { 734dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->ftdi.usb_read_timeout = timeout; 744dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->ftdi.usb_write_timeout = timeout; 754dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 764dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 774dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return; 784dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 794dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 804dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Convert a frequency to a clock divisor */ 814dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn uint16_t freq2div(uint32_t system_clock, uint32_t freq) { 824dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return (((system_clock / freq) / 2) - 1); 834dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 844dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 854dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Convert a clock divisor to a frequency */ 864dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn uint32_t div2freq(uint32_t system_clock, uint16_t div) { 874dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return (system_clock / ((1 + div) * 2)); 884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 904dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Builds a buffer of commands + data blocks */ 914dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn uint8_t* build_block_buffer(struct mpsse_context* mpsse, 924dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn uint8_t cmd, 934dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn const uint8_t* data, 944dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int size, 954dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int* buf_size) { 964dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn uint8_t* buf = NULL; 974dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int i = 0, j = 0, k = 0, dsize = 0, num_blocks = 0, total_size = 0, 984dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn xfer_size = 0; 994dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn uint16_t rsize = 0; 1004dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1014dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn *buf_size = 0; 1024dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1034dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Data block size is 1 in I2C, or when in bitmode */ 1044dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode == I2C || (cmd & MPSSE_BITMODE)) { 1054dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn xfer_size = 1; 1064dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else { 1074dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn xfer_size = mpsse->xsize; 1084dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1094dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1104dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn num_blocks = (size / xfer_size); 1114dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (size % xfer_size) { 1124dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn num_blocks++; 1134dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1144dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1154dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* The total size of the data will be the data size + the write command */ 1164dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn total_size = size + (CMD_SIZE * num_blocks); 1174dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1184dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* In I2C we have to add 3 additional commands per data block */ 1194dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode == I2C) { 1204dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn total_size += (CMD_SIZE * 3 * num_blocks); 1214dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1224dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1234dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf = malloc(total_size); 1244dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (buf) { 1254dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn memset(buf, 0, total_size); 1264dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1274dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn for (j = 0; j < num_blocks; j++) { 1284dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn dsize = size - k; 1294dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (dsize > xfer_size) { 1304dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn dsize = xfer_size; 1314dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1324dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1334dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* The reported size of this block is block size - 1 */ 1344dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn rsize = dsize - 1; 1354dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1364dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* For I2C we need to ensure that the clock pin is set low prior to 1374dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * clocking out data */ 1384dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode == I2C) { 1394dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = SET_BITS_LOW; 1404dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->pstart & ~SK; 1414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1424dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* On receive, we need to ensure that the data out line is set as an 1434dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * input to avoid contention on the bus */ 1444dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (cmd == mpsse->rx) { 1454dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->tris & ~DO; 1464dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else { 1474dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->tris; 1484dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1494dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1504dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1514dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Copy in the command for this block */ 1524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = cmd; 1534dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = (rsize & 0xFF); 1544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (!(cmd & MPSSE_BITMODE)) { 1554dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = ((rsize >> 8) & 0xFF); 1564dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1574dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1584dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* On a write, copy the data to transmit after the command */ 1594dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (cmd == mpsse->tx || cmd == mpsse->txrx) { 1604dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn memcpy(buf + i, data + k, dsize); 1614dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1624dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* i == offset into buf */ 1634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn i += dsize; 1644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* k == offset into data */ 1654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn k += dsize; 1664dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1674dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1684dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* In I2C mode we need to clock one ACK bit after each byte */ 1694dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode == I2C) { 1704dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* If we are receiving data, then we need to clock out an ACK for each 1714dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * byte */ 1724dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (cmd == mpsse->rx) { 1734dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = SET_BITS_LOW; 1744dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->pstart & ~SK; 1754dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->tris; 1764dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1774dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->tx | MPSSE_BITMODE; 1784dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = 0; 1794dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->tack; 1804dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1814dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* If we are sending data, then we need to clock in an ACK for each 1824dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * byte 1834dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn */ 1844dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn else if (cmd == mpsse->tx) { 1854dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Need to make data out an input to avoid contention on the bus when 1864dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn * the slave sends an ACK */ 1874dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = SET_BITS_LOW; 1884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->pstart & ~SK; 1894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->tris & ~DO; 1904dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1914dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = mpsse->rx | MPSSE_BITMODE; 1924dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = 0; 1934dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[i++] = SEND_IMMEDIATE; 1944dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1954dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1964dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 1974dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 1984dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn *buf_size = i; 1994dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2004dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2014dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return buf; 2024dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2034dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2044dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Set the low bit pins high/low */ 2054dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int set_bits_low(struct mpsse_context* mpsse, int port) { 2064dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn char buf[CMD_SIZE] = {0}; 2074dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2084dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[0] = SET_BITS_LOW; 2094dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[1] = port; 2104dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[2] = mpsse->tris; 2114dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2124dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf)); 2134dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2144dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2154dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Set the high bit pins high/low */ 2164dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int set_bits_high(struct mpsse_context* mpsse, int port) { 2174dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn char buf[CMD_SIZE] = {0}; 2184dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2194dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[0] = SET_BITS_HIGH; 2204dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[1] = port; 2214dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn buf[2] = mpsse->trish; 2224dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2234dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf)); 2244dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2254dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2264dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Set the GPIO pins high/low */ 2274dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int gpio_write(struct mpsse_context* mpsse, int pin, int direction) { 2284dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int retval = MPSSE_FAIL; 2294dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2304dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (mpsse->mode == BITBANG) { 2314dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (direction == HIGH) { 2324dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->bitbang |= (1 << pin); 2334dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else { 2344dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->bitbang &= ~(1 << pin); 2354dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2364dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2374dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (set_bits_high(mpsse, mpsse->bitbang) == MPSSE_OK) { 2384dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn retval = raw_write(mpsse, (uint8_t*)&mpsse->bitbang, 1); 2394dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2404dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else { 2414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* The first four pins can't be changed unless we are in a stopped status 2424dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn */ 2434dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (pin < NUM_GPIOL_PINS && mpsse->status == STOPPED) { 2444dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Convert pin number (0-3) to the corresponding pin bit */ 2454dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn pin = (GPIO0 << pin); 2464dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2474dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (direction == HIGH) { 2484dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->pstart |= pin; 2494dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->pidle |= pin; 2504dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->pstop |= pin; 2514dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else { 2524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->pstart &= ~pin; 2534dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->pidle &= ~pin; 2544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->pstop &= ~pin; 2554dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2564dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2574dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn retval = set_bits_low(mpsse, mpsse->pstop); 2584dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else if (pin >= NUM_GPIOL_PINS && pin < NUM_GPIO_PINS) { 2594dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Convert pin number (4 - 11) to the corresponding pin bit */ 2604dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn pin -= NUM_GPIOL_PINS; 2614dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2624dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn if (direction == HIGH) { 2634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->gpioh |= (1 << pin); 2644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } else { 2654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse->gpioh &= ~(1 << pin); 2664dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2674dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2684dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn retval = set_bits_high(mpsse, mpsse->gpioh); 2694dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2704dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2714dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2724dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return retval; 2734dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 2744dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn 2754dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn /* Checks if a given MPSSE context is valid. */ 2764dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn int is_valid_context(struct mpsse_context* mpsse) { 2774dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn return mpsse != NULL; 2784dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn } 279