OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [adv_jtag_bridge/] [cable_usbblaster.c] - Diff between revs 14 and 32

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 14 Rev 32
/* cable_usbblaster.c - Altera USB Blaster driver for the Advanced JTAG Bridge
/* cable_usbblaster.c - Altera USB Blaster driver for the Advanced JTAG Bridge
   Copyright (C) 2008 Nathan Yawn, nathan.yawn@opencores.org
   Copyright (C) 2008 - 2010 Nathan Yawn, nathan.yawn@opencores.org
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
 
 
#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/types.h>
#include <unistd.h>  // for usleep()
#include <unistd.h>  // for usleep()
#include <stdlib.h>  // for sleep()
#include <stdlib.h>  // for sleep()
#include <arpa/inet.h> // for htons()
#include <arpa/inet.h> // for htons()
 
#include <string.h>  // for memcpy()
 
 
#include "usb.h"  // libusb header
#include "usb.h"  // libusb header
#include "cable_common.h"
#include "cable_common.h"
#include "errcodes.h"
#include "errcodes.h"
 
 
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
 
 
// USB constants for the USB Blaster
// USB constants for the USB Blaster
// Valid endpoints: 0x81, 0x02, 0x06, 0x88
// Valid endpoints: 0x81, 0x02, 0x06, 0x88
#define EP2        0x02
#define EP2        0x02
#define EP1        0x81
#define EP1        0x81
#define ALTERA_VID 0x09FB
#define ALTERA_VID 0x09FB
#define ALTERA_PID 0x6001
#define ALTERA_PID 0x6001
 
 
//#define USB_TIMEOUT 500
//#define USB_TIMEOUT 500
#define USB_TIMEOUT 10000
#define USB_TIMEOUT 10000
 
 
 
 
// Bit meanings in the command byte sent to the USB-Blaster
// Bit meanings in the command byte sent to the USB-Blaster
#define USBBLASTER_CMD_TCK 0x01
#define USBBLASTER_CMD_TCK 0x01
#define USBBLASTER_CMD_TMS 0x02
#define USBBLASTER_CMD_TMS 0x02
#define USBBLASTER_CMD_nCE 0x04  /* should be left low */
#define USBBLASTER_CMD_nCE 0x04  /* should be left low */
#define USBBLASTER_CMD_nCS 0x08  /* must be set for byte-shift mode reads to work */
#define USBBLASTER_CMD_nCS 0x08  /* must be set for byte-shift mode reads to work */
#define USBBLASTER_CMD_TDI 0x10
#define USBBLASTER_CMD_TDI 0x10
#define USBBLASTER_CMD_OE  0x20  /* appears necessary to set it to make everything work */
#define USBBLASTER_CMD_OE  0x20  /* appears necessary to set it to make everything work */
#define USBBLASTER_CMD_READ 0x40
#define USBBLASTER_CMD_READ 0x40
#define USBBLASTER_CMD_BYTESHIFT 0x80
#define USBBLASTER_CMD_BYTESHIFT 0x80
 
 
 
 
static struct usb_device *usbblaster_device;
static struct usb_device *usbblaster_device;
 
static usb_dev_handle *h_device;
 
 
static char *data_out_scratchpad = NULL;
// libusb seems to give an error if we ask for a transfer larger than 64 bytes
static int data_out_scratchpad_size = 0;
// USBBlaster also has a max. single transaction of 63 bytes.
static char *data_in_scratchpad = NULL;
// So, size the max read and write to create 64-byte USB packets (reads have 2 useless bytes prepended)
static int data_in_scratchpad_size = 0;
#define USBBLASTER_MAX_WRITE 63
 
static char data_out_scratchpad[USBBLASTER_MAX_WRITE+1];
 
#define USBBLASTER_MAX_READ  62
 
static char data_in_scratchpad[USBBLASTER_MAX_READ+2];
 
 
 
int cable_usbblaster_open_cable(void);
 
void cable_usbblaster_close_cable(void);
 
//int cable_usbblaster_reopen_cable(void);
 
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/*-------------------------------------[ USB Blaster specific functions ]---*/
/*-------------------------------------[ USB Blaster specific functions ]---*/
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
 
 
 
 
static int usbblaster_start_interface(struct usb_dev_handle *xpcu)
static int usbblaster_start_interface(struct usb_dev_handle *xpcu)
{
{
  // Need to send a VENDOR request OUT, request = GET_STATUS
  // Need to send a VENDOR request OUT, request = GET_STATUS
  // Other parameters are ignored
  // Other parameters are ignored
  if(usb_control_msg(xpcu, (USB_ENDPOINT_OUT | USB_TYPE_VENDOR), USB_REQ_GET_STATUS,
  if(usb_control_msg(xpcu, (USB_ENDPOINT_OUT | USB_TYPE_VENDOR), USB_REQ_GET_STATUS,
                     0, 0, NULL, 0, 1000)<0)
                     0, 0, NULL, 0, 1000)<0)
    {
    {
      perror("usb_control_msg(start interface)");
      perror("usb_control_msg(start interface)");
      return APP_ERR_USB;
      return APP_ERR_USB;
    }
    }
 
 
  return APP_ERR_NONE;
  return APP_ERR_NONE;
}
}
 
 
 
 
static int usbblaster_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf)
static int usbblaster_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf)
{
{
  if(usb_control_msg(xpcu, 0xC0, 0x90, 0, 3, (char*)buf, 2, USB_TIMEOUT)<0)
  if(usb_control_msg(xpcu, 0xC0, 0x90, 0, 3, (char*)buf, 2, USB_TIMEOUT)<0)
    {
    {
      perror("usb_control_msg(0x90.0) (read_firmware_version)");
      perror("usb_control_msg(0x90.0) (read_firmware_version)");
      return APP_ERR_USB;
      return APP_ERR_USB;
    }
    }
 
 
  // Swap endian
  // Swap endian
  *buf = htons(*buf);
  *buf = htons(*buf);
  //*buf = (*buf << 8) | (*buf >> 8);
  //*buf = (*buf << 8) | (*buf >> 8);
 
 
  return APP_ERR_NONE;
  return APP_ERR_NONE;
}
}
 
 
 
 
 
 
static int usbblaster_enumerate_bus(void)
static int usbblaster_enumerate_bus(void)
{
{
  int             flag;  // for USB bus scanning stop condition
  int             flag;  // for USB bus scanning stop condition
  struct usb_bus *bus;   // pointer on the USB bus
  struct usb_bus *bus;   // pointer on the USB bus
 
 
  // board detection
  // board detection
  usb_init();
  usb_init();
  usb_find_busses();
  usb_find_busses();
  usb_find_devices();
  usb_find_devices();
 
 
  flag = 0;
  flag = 0;
 
 
  for (bus = usb_get_busses(); bus; bus = bus->next)
  for (bus = usb_get_busses(); bus; bus = bus->next)
  {
  {
    for (usbblaster_device = bus->devices; usbblaster_device; usbblaster_device = usbblaster_device->next)
    for (usbblaster_device = bus->devices; usbblaster_device; usbblaster_device = usbblaster_device->next)
    {
    {
      if (usbblaster_device->descriptor.idVendor  == ALTERA_VID &&
      if (usbblaster_device->descriptor.idVendor  == ALTERA_VID &&
          usbblaster_device->descriptor.idProduct == ALTERA_PID)
          usbblaster_device->descriptor.idProduct == ALTERA_PID)
      {
      {
              flag = 1;
              flag = 1;
              fprintf(stderr, "Found Altera USB-Blaster\n");
              fprintf(stderr, "Found Altera USB-Blaster\n");
              return APP_ERR_NONE;
              return APP_ERR_NONE;
      }
      }
    }
    }
    if (flag)
    if (flag)
      break;
      break;
  }
  }
 
 
  fprintf(stderr, "Failed to find USB-Blaster\n");
  fprintf(stderr, "Failed to find USB-Blaster\n");
  return APP_ERR_CABLENOTFOUND;
  return APP_ERR_CABLENOTFOUND;
}
}
 
 
 
 
int cable_usbblaster_init(){
int cable_usbblaster_init(){
  int err = APP_ERR_NONE;
  int err = APP_ERR_NONE;
 
 
  // Process to reset the usb blaster
  // Process to reset the usb blaster
  if(err |= usbblaster_enumerate_bus()) {
  if(err |= usbblaster_enumerate_bus()) {
    return err;
    return err;
  }
  }
 
 
  usb_dev_handle *h_device = usb_open(usbblaster_device);
  h_device = usb_open(usbblaster_device);
 
 
  if(h_device == NULL)
  if(h_device == NULL)
    {
    {
      fprintf(stderr, "Init failed to open USB device for reset\n");
      fprintf(stderr, "Init failed to open USB device for reset\n");
      return APP_ERR_USB;
      return APP_ERR_USB;
    }
    }
 
 
  if(usb_reset(h_device) != APP_ERR_NONE)
  if(usb_reset(h_device) != APP_ERR_NONE)
    fprintf(stderr, "Failed to reset USB Blaster\n");
    fprintf(stderr, "Failed to reset USB Blaster\n");
 
 
  usb_close(h_device);
  usb_close(h_device);
 
 
  // Wait for reset!!!
  // Wait for reset!!!
  sleep(1);
  sleep(1);
 
 
  // Do device initialization
  // Do device initialization
  if(err |= usbblaster_enumerate_bus())
  if(err |= usbblaster_enumerate_bus())
    return err;
    return err;
 
 
  h_device = usb_open(usbblaster_device);
  err = cable_usbblaster_open_cable();
  if(h_device == NULL)
  if(err != APP_ERR_NONE) return err;
    {
 
      fprintf(stderr, "Init failed to open USB device for initialization\n");
 
      return APP_ERR_USB;
 
    }
 
 
 
  // set the configuration
 
  if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue))
 
    {
 
      usb_close(h_device);
 
      fprintf(stderr, "USB-reset failed to set configuration\n");
 
      return APP_ERR_NONE;
 
    }
 
 
 
  while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
 
 
 
  //usb_clear_halt(h_device, EP1);
  //usb_clear_halt(h_device, EP1);
  //usb_clear_halt(h_device, EP2);
  //usb_clear_halt(h_device, EP2);
 
 
  // IMPORTANT:  DO NOT SEND A REQUEST TYPE "CLASS" OR TYPE "RESERVED".  This may stall the EP.
  // IMPORTANT:  DO NOT SEND A REQUEST TYPE "CLASS" OR TYPE "RESERVED".  This may stall the EP.
 
 
  // Some clones need this before they will start processing IN/OUT requests
  // Some clones need this before they will start processing IN/OUT requests
  if(usbblaster_start_interface(h_device) != APP_ERR_NONE)
  if(usbblaster_start_interface(h_device) != APP_ERR_NONE)
    fprintf(stderr, "Failed to start remote interface\n");
    fprintf(stderr, "Failed to start remote interface\n");
 
 
  uint16_t buf;
  uint16_t buf;
  if(err |= usbblaster_read_firmware_version(h_device, &buf))
  if(err |= usbblaster_read_firmware_version(h_device, &buf))
    {
    {
      usb_close(h_device);
      usb_close(h_device);
      fprintf(stderr, "Failed to read firmware version\n");
      fprintf(stderr, "Failed to read firmware version\n");
      return err;
      return err;
    }
    }
  else
  else
    {
    {
      printf("firmware version = 0x%04X (%u)\n", buf, buf);
      printf("firmware version = 0x%04X (%u)\n", buf, buf);
    }
    }
 
 
 
 
  // USB blaster is expecting us to read 2 bytes, which are useless to us...
  // USB blaster is expecting us to read 2 bytes, which are useless to us...
  char ret[2];
  char ret[2];
  int rv = usb_bulk_read(h_device, EP1, ret, 2, USB_TIMEOUT);
  int rv = usb_bulk_read(h_device, EP1, ret, 2, USB_TIMEOUT);
  if (rv < 0){  // But if we fail, who cares?
  if (rv < 0){  // But if we fail, who cares?
    fprintf(stderr, "\nWarning: Failed to read post-init bytes from the EP1 FIFO (%i):\n%s", rv, usb_strerror());
    fprintf(stderr, "\nWarning: Failed to read post-init bytes from the EP1 FIFO (%i):\n%s", rv, usb_strerror());
  }
  }
 
 
  if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){
 
    usb_close(h_device);
 
    fprintf(stderr, "USB-out failed to release interface\n");
 
    return APP_ERR_USB;
 
  }
 
 
 
  usb_close(h_device);
 
 
 
  data_out_scratchpad = (char *) malloc(64);
 
  data_out_scratchpad_size = 64;
 
  data_in_scratchpad = (char *) malloc(64);
 
  data_in_scratchpad_size = 64;
 
 
 
  return APP_ERR_NONE;
  return APP_ERR_NONE;
}
}
 
 
 
 
int cable_usbblaster_out(uint8_t value)
int cable_usbblaster_out(uint8_t value)
{
{
  int             rv;                  // to catch return values of functions
  int             rv;                  // to catch return values of functions
  usb_dev_handle *h_device;            // handle on the ubs device
 
  char out;
  char out;
  int err = APP_ERR_NONE;
  int err = APP_ERR_NONE;
 
 
  // open the device
  // open the device, if necessary
  h_device = usb_open(usbblaster_device);
 
  if (h_device == NULL){
  if (h_device == NULL){
    usb_close(h_device);
    rv = cable_usbblaster_open_cable();
    fprintf(stderr, "USB-out failed to open device\n");
    if(rv != APP_ERR_NONE) return rv;
    return APP_ERR_USB;
 
  }
  }
 
 
  // set the configuration
 
  if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue))
 
    {
 
      usb_close(h_device);
 
      fprintf(stderr, "USB-out failed to set configuration\n");
 
      return APP_ERR_USB;
 
    }
 
 
 
  // wait until device is ready
 
  while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
 
 
 
  out = (USBBLASTER_CMD_OE | USBBLASTER_CMD_nCS);  // Set output enable (appears necessary) and nCS (necessary for byte-shift reads)
  out = (USBBLASTER_CMD_OE | USBBLASTER_CMD_nCS);  // Set output enable (appears necessary) and nCS (necessary for byte-shift reads)
 
 
  // Translate to USB blaster protocol
  // Translate to USB blaster protocol
  // USB-Blaster has no TRST pin
  // USB-Blaster has no TRST pin
  if(value & TCLK_BIT)
  if(value & TCLK_BIT)
    out |= USBBLASTER_CMD_TCK;
    out |= USBBLASTER_CMD_TCK;
  if(value & TDI_BIT)
  if(value & TDI_BIT)
    out |= USBBLASTER_CMD_TDI;
    out |= USBBLASTER_CMD_TDI;
  if(value & TMS_BIT)
  if(value & TMS_BIT)
    out |= USBBLASTER_CMD_TMS;
    out |= USBBLASTER_CMD_TMS;
 
 
 
 
  rv = usb_bulk_write(h_device, EP2, &out, 1, USB_TIMEOUT);
  rv = usb_bulk_write(h_device, EP2, &out, 1, USB_TIMEOUT);
  if (rv != 1){
  if (rv != 1){
    fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror());
    fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror());
    err |= APP_ERR_USB;
    err |= APP_ERR_USB;
  }
  }
 
 
  // release the interface cleanly
 
  if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){
 
    fprintf(stderr, "Warning: failed to release usb interface after write\n");
 
    err |= APP_ERR_USB;
 
  }
 
 
 
  // close the device
 
  usb_close(h_device);
 
  return err;
  return err;
}
}
 
 
 
 
int cable_usbblaster_inout(uint8_t value, uint8_t *in_bit)
int cable_usbblaster_inout(uint8_t value, uint8_t *in_bit)
{
{
  int             rv;                  // to catch return values of functions
  int             rv;                  // to catch return values of functions
  usb_dev_handle *h_device;            // handle on the usb device
 
  char ret[3] = {0,0,0};               // Two useless bytes (0x31,0x60) always precede the useful byte
  char ret[3] = {0,0,0};               // Two useless bytes (0x31,0x60) always precede the useful byte
  char out;
  char out;
 
 
  out = (USBBLASTER_CMD_OE | USBBLASTER_CMD_nCS);  // Set output enable (?) and nCS (necessary for byte-shift reads)
  out = (USBBLASTER_CMD_OE | USBBLASTER_CMD_nCS);  // Set output enable (?) and nCS (necessary for byte-shift reads)
  out |=  USBBLASTER_CMD_READ;
  out |=  USBBLASTER_CMD_READ;
 
 
  // Translate to USB blaster protocol
  // Translate to USB blaster protocol
  // USB-Blaster has no TRST pin
  // USB-Blaster has no TRST pin
  if(value & TCLK_BIT)
  if(value & TCLK_BIT)
    out |= USBBLASTER_CMD_TCK;
    out |= USBBLASTER_CMD_TCK;
  if(value & TDI_BIT)
  if(value & TDI_BIT)
    out |= USBBLASTER_CMD_TDI;
    out |= USBBLASTER_CMD_TDI;
  if(value & TMS_BIT)
  if(value & TMS_BIT)
    out |= USBBLASTER_CMD_TMS;
    out |= USBBLASTER_CMD_TMS;
 
 
 
  // open the device, if necessary
  // open the device
 
  h_device = usb_open(usbblaster_device);
 
  if (h_device == NULL){
  if (h_device == NULL){
    return APP_ERR_USB;
    rv = cable_usbblaster_open_cable();
 
    if(rv != APP_ERR_NONE) return rv;
  }
  }
 
 
  // set the configuration
 
  if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue)){
 
    usb_close(h_device);
 
    return APP_ERR_USB;
 
  }
 
 
 
  // wait until device is ready
 
  while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
 
 
 
  // Send a read request
  // Send a read request
  rv = usb_bulk_write(h_device, EP2, &out, 1, USB_TIMEOUT);
  rv = usb_bulk_write(h_device, EP2, &out, 1, USB_TIMEOUT);
  if (rv != 1){
  if (rv != 1){
    fprintf(stderr, "\nFailed to write a read request to the EP2 FIFO:\n%s", usb_strerror());
    fprintf(stderr, "\nFailed to write a read request to the EP2 FIFO:\n%s", usb_strerror());
    usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
    cable_usbblaster_close_cable();
    usb_close(h_device);
 
    return APP_ERR_USB;
    return APP_ERR_USB;
  }
  }
 
 
 
 
  // receive the response
  // receive the response
  // Sometimes, we do a read but just get the useless 0x31,0x60 chars...
  // Sometimes, we do a read but just get the useless 0x31,0x60 chars...
  // retry until we get a 3rd byte (with real data), for a reasonable number of retries.
  // retry until we get a 3rd byte (with real data), for a reasonable number of retries.
  int retries = 0;
  int retries = 0;
  do {
  do {
    rv = usb_bulk_read(h_device, EP1, ret, 3, USB_TIMEOUT);
    rv = usb_bulk_read(h_device, EP1, ret, 3, USB_TIMEOUT);
    if (rv < 0){
    if (rv < 0){
      fprintf(stderr, "\nFailed to read from the EP1 FIFO (%i):\n%s", rv, usb_strerror());
      fprintf(stderr, "\nFailed to read from the EP1 FIFO (%i):\n%s", rv, usb_strerror());
      usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
      cable_usbblaster_close_cable();
      usb_close(h_device);
 
      return APP_ERR_USB;
      return APP_ERR_USB;
    }
    }
 
 
    // fprintf(stderr, "Read %i bytes: 0x%X, 0x%X, 0x%X\n", rv, ret[0], ret[1], ret[2]);
    // fprintf(stderr, "Read %i bytes: 0x%X, 0x%X, 0x%X\n", rv, ret[0], ret[1], ret[2]);
    retries++;
    retries++;
  }
  }
  while((rv < 3) && (retries < 20));
  while((rv < 3) && (retries < 20));
 
 
 
 
  // release the interface cleanly
 
  if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){
 
    fprintf(stderr, "Warning: failed to release USB interface after read\n");
 
    usb_close(h_device);
 
    return APP_ERR_USB;
 
  }
 
 
 
  // close the device
 
  usb_close(h_device);
 
 
 
  *in_bit = (ret[2] & 0x01); /* TDO is bit 0.  USB-Blaster may also set bit 1. */
  *in_bit = (ret[2] & 0x01); /* TDO is bit 0.  USB-Blaster may also set bit 1. */
  return APP_ERR_NONE;
  return APP_ERR_NONE;
}
}
 
 
 
 
// The usbblaster transfers the bits in the stream in the following order:
// The usbblaster transfers the bits in the stream in the following order:
// bit 0 of the first byte received ... bit 7 of the first byte received
// bit 0 of the first byte received ... bit 7 of the first byte received
// bit 0 of second byte received ... etc.
// bit 0 of second byte received ... etc.
int cable_usbblaster_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
int cable_usbblaster_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
  int             rv;                  // to catch return values of functions
  int             rv;                  // to catch return values of functions
  usb_dev_handle *h_device;            // handle on the ubs device
 
  unsigned int bytes_to_transfer, leftover_bit_length;
  unsigned int bytes_to_transfer, leftover_bit_length;
  uint32_t leftover_bits;
  uint32_t leftover_bits;
  unsigned char i;
  int bytes_remaining;
 
  char *xfer_ptr;
  int err = APP_ERR_NONE;
  int err = APP_ERR_NONE;
 
 
  //printf("cable_usbblaster_write_stream(0x%X, %d, %i)\n", stream, len, set_last_bit);
  debug("cable_usbblaster_write_stream(0x%X, %d, %i)\n", stream, len, set_last_bit);
 
 
  // This routine must transfer at least 8 bits.  Additionally, TMS (the last bit)
  // This routine must transfer at least 8 bits.  Additionally, TMS (the last bit)
  // cannot be set by 'byte shift mode'.  So we need at least 8 bits to transfer,
  // cannot be set by 'byte shift mode'.  So we need at least 8 bits to transfer,
  // plus one bit to send along with TMS.
  // plus one bit to send along with TMS.
  bytes_to_transfer = len_bits / 8;
  bytes_to_transfer = len_bits / 8;
  leftover_bit_length = len_bits - (bytes_to_transfer * 8);
  leftover_bit_length = len_bits - (bytes_to_transfer * 8);
 
 
  if((!leftover_bit_length) && set_last_bit) {
  if((!leftover_bit_length) && set_last_bit) {
    bytes_to_transfer -= 1;
    bytes_to_transfer -= 1;
    leftover_bit_length += 8;
    leftover_bit_length += 8;
  }
  }
 
 
  //printf("bytes_to_transfer: %d. leftover_bit_length: %d\n", bytes_to_transfer, leftover_bit_length);
  debug("bytes_to_transfer: %d. leftover_bit_length: %d\n", bytes_to_transfer, leftover_bit_length);
 
 
  // Not enough bits for high-speed transfer. bit-bang.
  // Not enough bits for high-speed transfer. bit-bang.
  if(bytes_to_transfer == 0) {
  if(bytes_to_transfer == 0) {
    return cable_common_write_stream(stream, len_bits, set_last_bit);
    return cable_common_write_stream(stream, len_bits, set_last_bit);
  }
  }
 
 
  // Bitbang functions leave clock high.  USBBlaster assumes clock low at the start of a burst.
  // Bitbang functions leave clock high.  USBBlaster assumes clock low at the start of a burst.
  // Lower the clock.
  err |= cable_usbblaster_out(0);  // Lower the clock.
  err |= cable_usbblaster_out(0);
 
 
 
  // Set leftover bits
  // Set leftover bits
  leftover_bits = (stream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF;
  leftover_bits = (stream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF;
 
 
  //printf("leftover_bits: 0x%X, LSB_first_xfer = %d\n", leftover_bits, LSB_first_xfer);
  debug("leftover_bits: 0x%X, LSB_first_xfer = %d\n", leftover_bits, LSB_first_xfer);
 
 
  // open the device
  // open the device, if necessary
  h_device = usb_open(usbblaster_device);
 
  if (h_device == NULL){
  if (h_device == NULL){
    usb_close(h_device);
    rv = cable_usbblaster_open_cable();
    fprintf(stderr, "USBBlaster_write_stream failed to open device\n");
    if(rv != APP_ERR_NONE) return rv;
    return APP_ERR_USB;
 
  }
  }
 
 
  // set the configuration
  bytes_remaining = bytes_to_transfer;
  if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue))
  xfer_ptr = (char *) stream;
 
  while(bytes_remaining > 0)
  {
  {
    usb_close(h_device);
      int bytes_this_xfer = (bytes_remaining > USBBLASTER_MAX_WRITE) ? USBBLASTER_MAX_WRITE:bytes_remaining;
    fprintf(stderr, "USBBlaster_write_stream failed to set configuration\n");
 
    return APP_ERR_USB;
 
  }
 
 
 
  // wait until device is ready
 
  while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
 
 
 
 
 
  // Copy stream into out.  Not pretty, but better than changing the interface to the upper layers;
      data_out_scratchpad[0] = USBBLASTER_CMD_BYTESHIFT | (bytes_this_xfer & 0x3F);
  // 32 bits are easier to work with than 8 bits in upper layers.
      memcpy(&data_out_scratchpad[1], xfer_ptr, bytes_this_xfer);
  if(data_out_scratchpad_size < (bytes_to_transfer+1)) {
 
    free(data_out_scratchpad);
 
    data_out_scratchpad = (char *) malloc(bytes_to_transfer+1);  // free/malloc instead of realloc will save copy time
 
    if(data_out_scratchpad == NULL) {
 
      usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
 
      usb_close(h_device);
 
      return APP_ERR_MALLOC;
 
    }
 
    data_out_scratchpad_size = bytes_to_transfer+1;
 
  }
 
 
 
  data_out_scratchpad[0] = USBBLASTER_CMD_BYTESHIFT | (bytes_to_transfer & 0x3F);
      /* printf("Data packet: ");
  for(i = 0; i < bytes_to_transfer; i++) {
 
    data_out_scratchpad[i+1] = (stream[i>>2] >> (8*(i&0x3))) & 0xFF;
 
  }
 
 
 
 
 
  /*
 
    printf("Data packet: ");
 
    for(i = 0; i <= bytes_to_transfer; i++)
    for(i = 0; i <= bytes_to_transfer; i++)
    printf("0x%X ", out[i]);
    printf("0x%X ", out[i]);
    printf("\n");
         printf("\n"); */
  */
 
 
 
  rv = usb_bulk_write(h_device, EP2, data_out_scratchpad, bytes_to_transfer+1, USB_TIMEOUT);
      rv = usb_bulk_write(h_device, EP2, data_out_scratchpad, bytes_this_xfer+1, USB_TIMEOUT);
  if (rv != (bytes_to_transfer+1)){
      if (rv != (bytes_this_xfer+1)){
    fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror());
    fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror());
    err |= APP_ERR_USB;
    err |= APP_ERR_USB;
 
        break;
  }
  }
 
 
  // release the interface cleanly
      bytes_remaining -= bytes_this_xfer;
  if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){
      xfer_ptr += bytes_this_xfer;
        fprintf(stderr, "Warning: failed to release usb interface after stream write\n");
 
  }
  }
 
 
  // close the device
 
  usb_close(h_device);
 
 
 
  // if we have a number of bits not divisible by 8, or we need to set TMS...
  // if we have a number of bits not divisible by 8, or we need to set TMS...
  if(leftover_bit_length != 0) {
  if(leftover_bit_length != 0) {
    //printf("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
    //printf("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
    return cable_common_write_stream(&leftover_bits, leftover_bit_length, set_last_bit);
    return cable_common_write_stream(&leftover_bits, leftover_bit_length, set_last_bit);
  }
  }
 
 
  return err;
  return err;
}
}
 
 
 
 
int cable_usbblaster_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
int cable_usbblaster_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
  int             rv;                  // to catch return values of functions
  int             rv;                  // to catch return values of functions
  usb_dev_handle *h_device;            // handle on the ubs device
  unsigned int bytes_received = 0, total_bytes_received = 0;
  unsigned int bytes_received = 0;
 
  unsigned int bytes_to_transfer, leftover_bit_length;
  unsigned int bytes_to_transfer, leftover_bit_length;
  uint32_t leftover_bits, leftovers_received = 0;
  uint32_t leftover_bits, leftovers_received = 0;
  unsigned char i;
  unsigned char i;
 
  int bytes_remaining;
 
  char *xfer_ptr;
  int retval = APP_ERR_NONE;
  int retval = APP_ERR_NONE;
 
 
  debug("cable_usbblaster_read_stream(0x%X, %d, %i)\n", outstream[0], len_bits, set_last_bit);
  debug("cable_usbblaster_read_stream(0x%X, %d, %i)\n", outstream[0], len_bits, set_last_bit);
 
 
  // This routine must transfer at least 8 bits.  Additionally, TMS (the last bit)
  // This routine must transfer at least 8 bits.  Additionally, TMS (the last bit)
  // cannot be set by 'byte shift mode'.  So we need at least 8 bits to transfer,
  // cannot be set by 'byte shift mode'.  So we need at least 8 bits to transfer,
  // plus one bit to send along with TMS.
  // plus one bit to send along with TMS.
  bytes_to_transfer = len_bits / 8;
  bytes_to_transfer = len_bits / 8;
  leftover_bit_length = len_bits - (bytes_to_transfer * 8);
  leftover_bit_length = len_bits - (bytes_to_transfer * 8);
 
 
  if((!leftover_bit_length) && set_last_bit) {
  if((!leftover_bit_length) && set_last_bit) {
    bytes_to_transfer -= 1;
    bytes_to_transfer -= 1;
    leftover_bit_length += 8;
    leftover_bit_length += 8;
  }
  }
 
 
  //printf("RD bytes_to_transfer: %d. leftover_bit_length: %d\n", bytes_to_transfer, leftover_bit_length);
  debug("RD bytes_to_transfer: %d. leftover_bit_length: %d\n", bytes_to_transfer, leftover_bit_length);
 
 
  // Not enough bits for high-speed transfer. bit-bang.
  // Not enough bits for high-speed transfer. bit-bang.
  if(bytes_to_transfer == 0) {
  if(bytes_to_transfer == 0) {
    return cable_common_read_stream(outstream, instream, len_bits, set_last_bit);
    return cable_common_read_stream(outstream, instream, len_bits, set_last_bit);
    //retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit);
 
  }
  }
 
 
  // Bitbang functions leave clock high.  USBBlaster assumes clock low at the start of a burst.
  // Bitbang functions leave clock high.  USBBlaster assumes clock low at the start of a burst.
  // Lower the clock.
  // Lower the clock.
  retval |= cable_usbblaster_out(0);
  retval |= cable_usbblaster_out(0);
 
 
  // Zero the input, since we add new data by logical-OR
  // Zero the input, since we add new data by logical-OR
  for(i = 0; i < (len_bits/32); i++)
  for(i = 0; i < (len_bits/32); i++)  instream[i] = 0;
    instream[i] = 0;
  if(len_bits % 32)                   instream[i] = 0;
  if(len_bits % 32)
 
    instream[i] = 0;
 
 
 
  // Set leftover bits
  // Set leftover bits
  leftover_bits = (outstream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF;
  leftover_bits = (outstream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF;
  debug("leftover_bits: 0x%X\n", leftover_bits);
  debug("leftover_bits: 0x%X\n", leftover_bits);
 
 
  // open the device
  // open the device, if necessary
  h_device = usb_open(usbblaster_device);
 
  if (h_device == NULL){
  if (h_device == NULL){
        usb_close(h_device);
    rv = cable_usbblaster_open_cable();
        fprintf(stderr, "USBBlaster_read_stream failed to open device\n");
    if(rv != APP_ERR_NONE) return rv;
        return APP_ERR_USB;
 
  }
  }
 
 
  // set the configuration
  // Transfer the data.  USBBlaster has a max transfer size of 64 bytes.
  if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue))
  bytes_remaining = bytes_to_transfer;
  {
  xfer_ptr = (char *) outstream;
        usb_close(h_device);
  total_bytes_received = 0;
        fprintf(stderr, "USBBlaster_read_stream failed to set configuration\n");
  while(bytes_remaining > 0)
        return APP_ERR_USB;
    {
  }
      int bytes_this_xfer = (bytes_remaining > USBBLASTER_MAX_READ) ? USBBLASTER_MAX_READ:bytes_remaining;
 
      data_out_scratchpad[0] = USBBLASTER_CMD_BYTESHIFT | USBBLASTER_CMD_READ | (bytes_this_xfer & 0x3F);
 
      memcpy(&data_out_scratchpad[1], xfer_ptr, bytes_this_xfer);
 
 
 
      /* debug("Data packet: ");
 
         for(i = 0; i <= bytes_to_transfer; i++) debug("0x%X ", data_out_scratchpad[i]);
 
         debug("\n"); */
 
 
  // wait until device is ready
      rv = usb_bulk_write(h_device, EP2, data_out_scratchpad, bytes_this_xfer+1, USB_TIMEOUT);
  while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
      if (rv != (bytes_this_xfer+1)){
 
 
 
 
 
 
  // Copy stream into out.  Not pretty, but better than changing the interface to the upper layers;
 
  // 32 bits are easier to work with than 8 bits in upper layers.
 
  if(data_out_scratchpad_size < (bytes_to_transfer+1)) {
 
    free(data_out_scratchpad);
 
    data_out_scratchpad = (char *) malloc(bytes_to_transfer+1);  // free/malloc instead of realloc will save copy time
 
    if(data_out_scratchpad == NULL) {
 
      usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
 
      usb_close(h_device);
 
      return APP_ERR_MALLOC;
 
    }
 
    data_out_scratchpad_size = bytes_to_transfer+1;
 
  }
 
 
 
  data_out_scratchpad[0] = USBBLASTER_CMD_BYTESHIFT | USBBLASTER_CMD_READ | (bytes_to_transfer & 0x3F);  // Set command byte
 
  for(i = 0; i < bytes_to_transfer; i++) {
 
    data_out_scratchpad[i+1] = (outstream[i>>2] >> (8*(i&0x3))) & 0xFF;
 
  }
 
 
 
  /*
 
  debug("Data packet: ");
 
  for(i = 0; i <= bytes_to_transfer; i++)
 
    debug("0x%X ", data_out_scratchpad[i]);
 
  debug("\n");
 
  */
 
 
 
  rv = usb_bulk_write(h_device, EP2, data_out_scratchpad, bytes_to_transfer+1, USB_TIMEOUT);
 
  if (rv != (bytes_to_transfer+1)){
 
    fprintf(stderr, "\nFailed to write to the EP2 FIFO (rv = %d):\n%s", rv, usb_strerror());
    fprintf(stderr, "\nFailed to write to the EP2 FIFO (rv = %d):\n%s", rv, usb_strerror());
    usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
        cable_usbblaster_close_cable();
    usb_close(h_device);
 
    return APP_ERR_USB;
    return APP_ERR_USB;
  }
      }
 
 
 
 
  // Make sure we have a big-enough buffer to hold the incoming data
 
  if(data_in_scratchpad_size < (bytes_to_transfer+2)) {
 
    free(data_in_scratchpad);
 
    data_in_scratchpad = (char *) malloc(bytes_to_transfer+2);  // free/malloc instead of realloc will save copy time
 
    if(data_in_scratchpad == NULL) {
 
      usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
 
      usb_close(h_device);
 
      return APP_ERR_MALLOC;
 
    }
 
    data_in_scratchpad_size = (bytes_to_transfer+2);
 
  }
 
 
 
  // receive the response
  // receive the response
  // Sometimes, we do a read but just get the useless 0x31,0x60 chars...
      // Sometimes, we do a read but just get the useless 0x31,0x60 chars...
  // retry until we get at least 3 bytes (with real data), for a reasonable number of retries.
      // retry until we get at least 3 bytes (with real data), for a reasonable number of retries.
  int retries = 0;
      int retries = 0;
  bytes_received = 0;
      bytes_received = 0;
  do {
  do {
    rv = usb_bulk_read(h_device, EP1, data_in_scratchpad, (bytes_to_transfer-bytes_received)+2, USB_TIMEOUT);
        debug("stream read, bytes_this_xfer = %i, bytes_received = %i\n", bytes_this_xfer, bytes_received);
 
        rv = usb_bulk_read(h_device, EP1, data_in_scratchpad, (bytes_this_xfer-bytes_received)+2, USB_TIMEOUT);
    if (rv < 0){
    if (rv < 0){
      fprintf(stderr, "\nFailed to read stream from the EP1 FIFO (%i):\n%s", rv, usb_strerror());
      fprintf(stderr, "\nFailed to read stream from the EP1 FIFO (%i):\n%s", rv, usb_strerror());
      usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber);
          cable_usbblaster_close_cable();
      usb_close(h_device);
 
      return APP_ERR_USB;
      return APP_ERR_USB;
    }
        }
 
 
    /*
        /* debug("Read %i bytes: ", rv);
    debug("Read %i bytes: ", rv);
 
    for(i = 0; i < rv; i++)
    for(i = 0; i < rv; i++)
      debug("0x%X ", data_in_scratchpad[i]);
      debug("0x%X ", data_in_scratchpad[i]);
    debug("\n");
           debug("\n"); */
    */
 
 
 
    if(rv > 2) retries = 0;
        if(rv > 2) retries = 0;
    else retries++;
        else retries++;
 
 
    /* Put the received bytes into the return stream.  */
        /* Put the received bytes into the return stream.  Works for either endian. */
    for(i = 0; i < (rv-2); i++) {
    for(i = 0; i < (rv-2); i++) {
      // Do size/type promotion before shift.  Must cast to unsigned, else the value may be
          // Do size/type promotion before shift.  Must cast to unsigned, else the value may be
      // sign-extended through the upper 16 bits of the uint32_t.
          // sign-extended through the upper 16 bits of the uint32_t.
      uint32_t tmp = (unsigned char) data_in_scratchpad[2+i];
      uint32_t tmp = (unsigned char) data_in_scratchpad[2+i];
      instream[(bytes_received+i)>>2] |= (tmp << ((i & 0x3)*8));
          instream[(total_bytes_received+i)>>2] |= (tmp << ((i & 0x3)*8));
    }
    }
 
 
    bytes_received += (rv-2);
    bytes_received += (rv-2);
 
        total_bytes_received += (rv-2);
  }
  }
  while((bytes_received < bytes_to_transfer) && (retries < 15));
      while((bytes_received < bytes_this_xfer) && (retries < 15));
 
 
 
 
  // release the interface cleanly
      bytes_remaining -= bytes_this_xfer;
  if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){
      xfer_ptr += bytes_this_xfer;
        fprintf(stderr, "Warning: failed to release usb interface after stream read\n");
 
  }
  }
 
 
  // close the device
 
  usb_close(h_device);
 
 
 
  // if we have a number of bits not divisible by 8
  // if we have a number of bits not divisible by 8
  if(leftover_bit_length != 0) {
  if(leftover_bit_length != 0) {
    debug("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
    debug("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit);
    retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit);
    retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit);
    instream[bytes_to_transfer>>2] |= (leftovers_received & 0xFF) << (8*(bytes_to_transfer & 0x3));
    instream[bytes_to_transfer>>2] |= (leftovers_received & 0xFF) << (8*(bytes_to_transfer & 0x3));
  }
  }
 
 
  return retval;
  return retval;
}
}
 
 
 
 
int cable_usbblaster_opt(int c, char *str)
int cable_usbblaster_opt(int c, char *str)
{
{
  fprintf(stderr, "Unknown parameter '%c'\n", c);
  fprintf(stderr, "Unknown parameter '%c'\n", c);
  return APP_ERR_BAD_PARAM;
  return APP_ERR_BAD_PARAM;
}
}
 
 
 
 
 
int cable_usbblaster_open_cable(void)
 
{
 
  // open the device
 
  h_device = usb_open(usbblaster_device);
 
  if (h_device == NULL){
 
        fprintf(stderr, "USBBlaster driver failed to open device\n");
 
        return APP_ERR_USB;
 
  }
 
 
 
  // set the configuration
 
  if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue))
 
  {
 
        usb_close(h_device);
 
        h_device = NULL;
 
        fprintf(stderr, "USBBlaster driver failed to set configuration\n");
 
        return APP_ERR_USB;
 
  }
 
 
 
  // wait until device is ready
 
  // *** TODO: add timeout
 
  while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber));
 
 
 
  return APP_ERR_NONE;
 
}
 
 
 
 
 
void cable_usbblaster_close_cable(void)
 
{
 
  if(h_device != NULL) {
 
    // release the interface cleanly
 
    if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){
 
      fprintf(stderr, "Warning: failed to release usb interface\n");
 
    }
 
 
 
    // close the device
 
    usb_close(h_device);
 
    h_device = NULL;
 
  }
 
 
 
  return;
 
}
 
 
 
/*
 
int cable_usbblaster_reopen_cable(void)
 
{
 
  cable_usbblaster_close_cable();
 
  return cable_usbblaster_open_cable();
 
}
 
*/
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.