Home | History | Annotate | Download | only in ftdi
      1 /*
      2 /*
      3 /*Copyright (C) 2015 The Android Open Source Project
      4 /*
      5 /*Licensed under the Apache License, Version 2.0 (the "License");
      6 /*you may not use this file except in compliance with the License.
      7 /*You may obtain a copy of the License at
      8 /*
      9 /*     http://www.apache.org/licenses/LICENSE-2.0
     10 /*
     11 /*Unless required by applicable law or agreed to in writing, software
     12 /*distributed under the License is distributed on an "AS IS" BASIS,
     13 /*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 /*See the License for the specific language governing permissions and
     15 /*limitations under the License.
     16  */
     17  *
     18  * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
     19  * f1a6744b), and modified to suite the Chromium OS project.
     20  *
     21  * Internal functions used by libmpsse.
     22  *
     23  * Craig Heffner
     24  * 27 December 2011
     25  */
     26 
     27 #include <string.h>
     28 
     29 #include "trunks/ftdi/support.h"
     30 
     31 /* Write data to the FTDI chip */
     32 int raw_write(struct mpsse_context* mpsse, uint8_t* buf, int size) {
     33   int retval = MPSSE_FAIL;
     34 
     35   if (mpsse->mode) {
     36     if (ftdi_write_data(&mpsse->ftdi, buf, size) == size) {
     37       retval = MPSSE_OK;
     38     }
     39   }
     40 
     41   return retval;
     42 }
     43 
     44 /* Read data from the FTDI chip */
     45 int raw_read(struct mpsse_context* mpsse, uint8_t* buf, int size) {
     46   int n = 0, r = 0;
     47 
     48   if (mpsse->mode) {
     49     while (n < size) {
     50       r = ftdi_read_data(&mpsse->ftdi, buf, size);
     51       if (r < 0)
     52         break;
     53       n += r;
     54     }
     55 
     56     if (mpsse->flush_after_read) {
     57       /*
     58        * Make sure the buffers are cleared after a read or subsequent reads may
     59        *fail.
     60        *
     61        * Is this needed anymore? It slows down repetitive read operations by
     62        *~8%.
     63        */
     64       ftdi_usb_purge_rx_buffer(&mpsse->ftdi);
     65     }
     66   }
     67 
     68   return n;
     69 }
     70 
     71 /* Sets the read and write timeout periods for bulk usb data transfers. */
     72 void set_timeouts(struct mpsse_context* mpsse, int timeout) {
     73   if (mpsse->mode) {
     74     mpsse->ftdi.usb_read_timeout = timeout;
     75     mpsse->ftdi.usb_write_timeout = timeout;
     76   }
     77 
     78   return;
     79 }
     80 
     81 /* Convert a frequency to a clock divisor */
     82 uint16_t freq2div(uint32_t system_clock, uint32_t freq) {
     83   return (((system_clock / freq) / 2) - 1);
     84 }
     85 
     86 /* Convert a clock divisor to a frequency */
     87 uint32_t div2freq(uint32_t system_clock, uint16_t div) {
     88   return (system_clock / ((1 + div) * 2));
     89 }
     90 
     91 /* Builds a buffer of commands + data blocks */
     92 uint8_t* build_block_buffer(struct mpsse_context* mpsse,
     93                                   uint8_t cmd,
     94                                   const uint8_t* data,
     95                                   int size,
     96                                   int* buf_size) {
     97   uint8_t* buf = NULL;
     98   int i = 0, j = 0, k = 0, dsize = 0, num_blocks = 0, total_size = 0,
     99       xfer_size = 0;
    100   uint16_t rsize = 0;
    101 
    102   *buf_size = 0;
    103 
    104   /* Data block size is 1 in I2C, or when in bitmode */
    105   if (mpsse->mode == I2C || (cmd & MPSSE_BITMODE)) {
    106     xfer_size = 1;
    107   } else {
    108     xfer_size = mpsse->xsize;
    109   }
    110 
    111   num_blocks = (size / xfer_size);
    112   if (size % xfer_size) {
    113     num_blocks++;
    114   }
    115 
    116   /* The total size of the data will be the data size + the write command */
    117   total_size = size + (CMD_SIZE * num_blocks);
    118 
    119   /* In I2C we have to add 3 additional commands per data block */
    120   if (mpsse->mode == I2C) {
    121     total_size += (CMD_SIZE * 3 * num_blocks);
    122   }
    123 
    124   buf = malloc(total_size);
    125   if (buf) {
    126     memset(buf, 0, total_size);
    127 
    128     for (j = 0; j < num_blocks; j++) {
    129       dsize = size - k;
    130       if (dsize > xfer_size) {
    131         dsize = xfer_size;
    132       }
    133 
    134       /* The reported size of this block is block size - 1 */
    135       rsize = dsize - 1;
    136 
    137       /* For I2C we need to ensure that the clock pin is set low prior to
    138        * clocking out data */
    139       if (mpsse->mode == I2C) {
    140         buf[i++] = SET_BITS_LOW;
    141         buf[i++] = mpsse->pstart & ~SK;
    142 
    143         /* On receive, we need to ensure that the data out line is set as an
    144          * input to avoid contention on the bus */
    145         if (cmd == mpsse->rx) {
    146           buf[i++] = mpsse->tris & ~DO;
    147         } else {
    148           buf[i++] = mpsse->tris;
    149         }
    150       }
    151 
    152       /* Copy in the command for this block */
    153       buf[i++] = cmd;
    154       buf[i++] = (rsize & 0xFF);
    155       if (!(cmd & MPSSE_BITMODE)) {
    156         buf[i++] = ((rsize >> 8) & 0xFF);
    157       }
    158 
    159       /* On a write, copy the data to transmit after the command */
    160       if (cmd == mpsse->tx || cmd == mpsse->txrx) {
    161         memcpy(buf + i, data + k, dsize);
    162 
    163         /* i == offset into buf */
    164         i += dsize;
    165         /* k == offset into data */
    166         k += dsize;
    167       }
    168 
    169       /* In I2C mode we need to clock one ACK bit after each byte */
    170       if (mpsse->mode == I2C) {
    171         /* If we are receiving data, then we need to clock out an ACK for each
    172          * byte */
    173         if (cmd == mpsse->rx) {
    174           buf[i++] = SET_BITS_LOW;
    175           buf[i++] = mpsse->pstart & ~SK;
    176           buf[i++] = mpsse->tris;
    177 
    178           buf[i++] = mpsse->tx | MPSSE_BITMODE;
    179           buf[i++] = 0;
    180           buf[i++] = mpsse->tack;
    181         }
    182         /* If we are sending data, then we need to clock in an ACK for each byte
    183            */
    184         else if (cmd == mpsse->tx) {
    185           /* Need to make data out an input to avoid contention on the bus when
    186            * the slave sends an ACK */
    187           buf[i++] = SET_BITS_LOW;
    188           buf[i++] = mpsse->pstart & ~SK;
    189           buf[i++] = mpsse->tris & ~DO;
    190 
    191           buf[i++] = mpsse->rx | MPSSE_BITMODE;
    192           buf[i++] = 0;
    193           buf[i++] = SEND_IMMEDIATE;
    194         }
    195       }
    196     }
    197 
    198     *buf_size = i;
    199   }
    200 
    201   return buf;
    202 }
    203 
    204 /* Set the low bit pins high/low */
    205 int set_bits_low(struct mpsse_context* mpsse, int port) {
    206   char buf[CMD_SIZE] = {0};
    207 
    208   buf[0] = SET_BITS_LOW;
    209   buf[1] = port;
    210   buf[2] = mpsse->tris;
    211 
    212   return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf));
    213 }
    214 
    215 /* Set the high bit pins high/low */
    216 int set_bits_high(struct mpsse_context* mpsse, int port) {
    217   char buf[CMD_SIZE] = {0};
    218 
    219   buf[0] = SET_BITS_HIGH;
    220   buf[1] = port;
    221   buf[2] = mpsse->trish;
    222 
    223   return raw_write(mpsse, (uint8_t*)&buf, sizeof(buf));
    224 }
    225 
    226 /* Set the GPIO pins high/low */
    227 int gpio_write(struct mpsse_context* mpsse, int pin, int direction) {
    228   int retval = MPSSE_FAIL;
    229 
    230   if (mpsse->mode == BITBANG) {
    231     if (direction == HIGH) {
    232       mpsse->bitbang |= (1 << pin);
    233     } else {
    234       mpsse->bitbang &= ~(1 << pin);
    235     }
    236 
    237     if (set_bits_high(mpsse, mpsse->bitbang) == MPSSE_OK) {
    238       retval = raw_write(mpsse, (uint8_t*)&mpsse->bitbang, 1);
    239     }
    240   } else {
    241     /* The first four pins can't be changed unless we are in a stopped status */
    242     if (pin < NUM_GPIOL_PINS && mpsse->status == STOPPED) {
    243       /* Convert pin number (0-3) to the corresponding pin bit */
    244       pin = (GPIO0 << pin);
    245 
    246       if (direction == HIGH) {
    247         mpsse->pstart |= pin;
    248         mpsse->pidle |= pin;
    249         mpsse->pstop |= pin;
    250       } else {
    251         mpsse->pstart &= ~pin;
    252         mpsse->pidle &= ~pin;
    253         mpsse->pstop &= ~pin;
    254       }
    255 
    256       retval = set_bits_low(mpsse, mpsse->pstop);
    257     } else if (pin >= NUM_GPIOL_PINS && pin < NUM_GPIO_PINS) {
    258       /* Convert pin number (4 - 11) to the corresponding pin bit */
    259       pin -= NUM_GPIOL_PINS;
    260 
    261       if (direction == HIGH) {
    262         mpsse->gpioh |= (1 << pin);
    263       } else {
    264         mpsse->gpioh &= ~(1 << pin);
    265       }
    266 
    267       retval = set_bits_high(mpsse, mpsse->gpioh);
    268     }
    269   }
    270 
    271   return retval;
    272 }
    273 
    274 /* Checks if a given MPSSE context is valid. */
    275 int is_valid_context(struct mpsse_context* mpsse) {
    276   return mpsse != NULL;
    277 }
    278