static int presto_write(uint8_t *buf, uint32_t size) { #if BUILD_PRESTO_FTD2XX == 1 DWORD ftbytes; presto->status = FT_Write(presto->handle, buf, size, &ftbytes); if (presto->status != FT_OK) { LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status)); return ERROR_JTAG_DEVICE_ERROR; } #elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes; presto->retval = ftdi_write_data(&presto->ftdic, buf, size); if (presto->retval < 0) { LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic)); return ERROR_JTAG_DEVICE_ERROR; } ftbytes = presto->retval; #endif if (ftbytes != size) { LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", (unsigned)ftbytes, (unsigned)size); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; }
static int usbconn_ftd2xx_read (urj_usbconn_t *conn, uint8_t *buf, int len) { ftd2xx_param_t *p = conn->params; int cpy_len; FT_STATUS status = FT_OK; DWORD recvd = 0; urj_log (URJ_LOG_LEVEL_COMM, "%sread begin: len %d\n", module, len); if (!p->fc) return -1; /* flush send buffer to get all scheduled receive bytes */ if (usbconn_ftd2xx_flush (p) < 0) return -1; if (len == 0) return 0; /* check for number of remaining bytes in receive buffer */ cpy_len = p->recv_write_idx - p->recv_read_idx; if (cpy_len > len) cpy_len = len; len -= cpy_len; if (cpy_len > 0) { /* get data from the receive buffer */ memcpy (buf, &p->recv_buf[p->recv_read_idx], cpy_len); p->recv_read_idx += cpy_len; if (p->recv_read_idx == p->recv_write_idx) p->recv_read_idx = p->recv_write_idx = 0; } if (len > 0) { /* need to get more data directly from the device */ while (recvd == 0) if ((status = FT_Read (p->fc, &buf[cpy_len], len, &recvd)) != FT_OK) urj_error_set (URJ_ERROR_FTD, _("Error from FT_Read(): %s"), ftd2xx_status_string(status)); } urj_log (URJ_LOG_LEVEL_COMM, "%sread end : status %ld, length %d\n", module, status, cpy_len + len); return status != FT_OK ? -1 : cpy_len + len; }
static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf, unsigned size, uint32_t *bytes_read) { DWORD dw_bytes_read; FT_STATUS status; FT_HANDLE *ftdih = ublast_getftdih(low); status = FT_Read(*ftdih, buf, size, &dw_bytes_read); if (status != FT_OK) { *bytes_read = dw_bytes_read; LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_read = dw_bytes_read; return ERROR_OK; }
static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size, uint32_t *bytes_written) { FT_STATUS status; DWORD dw_bytes_written; FT_HANDLE *ftdih = ublast_getftdih(low); status = FT_Write(*ftdih, buf, size, &dw_bytes_written); if (status != FT_OK) { *bytes_written = dw_bytes_written; LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); return ERROR_JTAG_DEVICE_ERROR; } *bytes_written = dw_bytes_written; return ERROR_OK; }
static int presto_read(uint8_t *buf, uint32_t size) { #if BUILD_PRESTO_FTD2XX == 1 DWORD ftbytes; presto->status = FT_Read(presto->handle, buf, size, &ftbytes); if (presto->status != FT_OK) { LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status)); return ERROR_JTAG_DEVICE_ERROR; } #elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes = 0; struct timeval timeout, now; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, 1, 0); /* one second timeout */ while (ftbytes < size) { presto->retval = ftdi_read_data(&presto->ftdic, buf + ftbytes, size - ftbytes); if (presto->retval < 0) { LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic)); return ERROR_JTAG_DEVICE_ERROR; } ftbytes += presto->retval; gettimeofday(&now, NULL); if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) break; } #endif if (ftbytes != size) { /* this is just a warning, there might have been timeout when detecting PRESTO, *which is not fatal */ LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)", (unsigned)ftbytes, (unsigned)size); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; }
static int ublast_ftd2xx_init(struct ublast_lowlevel *low) { FT_STATUS status; FT_HANDLE *ftdih = ublast_getftdih(low); uint8_t latency_timer; LOG_INFO("usb blaster interface using FTD2XX"); /* Open by device description */ if (low->ublast_device_desc == NULL) { LOG_WARNING("no usb blaster device description specified, " "using default 'USB-Blaster'"); low->ublast_device_desc = "USB-Blaster"; } #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid); if (status != FT_OK) { LOG_WARNING("couldn't add %4.4x:%4.4x", low->ublast_vid, low->ublast_pid); } #endif status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION, ftdih); if (status != FT_OK) { DWORD num_devices; LOG_ERROR("unable to open ftdi device: %s", ftd2xx_status_string(status)); status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); if (status == FT_OK) { char **desc_array = malloc(sizeof(char *) * (num_devices + 1)); unsigned int i; for (i = 0; i < num_devices; i++) desc_array[i] = malloc(64); desc_array[num_devices] = NULL; status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); if (status == FT_OK) { LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); for (i = 0; i < num_devices; i++) LOG_ERROR("%i: %s", i, desc_array[i]); } for (i = 0; i < num_devices; i++) free(desc_array[i]); free(desc_array); } else { printf("ListDevices: NONE\n"); } return ERROR_JTAG_INIT_FAILED; } status = FT_SetLatencyTimer(*ftdih, 2); if (status != FT_OK) { LOG_ERROR("unable to set latency timer: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } status = FT_GetLatencyTimer(*ftdih, &latency_timer); if (status != FT_OK) { LOG_ERROR("unable to get latency timer: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("current latency timer: %i", latency_timer); status = FT_SetBitMode(*ftdih, 0x00, 0); if (status != FT_OK) { LOG_ERROR("unable to disable bit i/o mode: %s", ftd2xx_status_string(status)); return ERROR_JTAG_INIT_FAILED; } return ERROR_OK; }
static int presto_open_ftd2xx(char *req_serial) { uint32_t i; DWORD numdevs; DWORD vidpid; char devname[FT_DEVICE_NAME_LEN]; FT_DEVICE device; BYTE presto_data; DWORD ftbytes; presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; #if IS_WIN32 == 0 /* Add non-standard Vid/Pid to the linux driver */ presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID); if (presto->status != FT_OK) { LOG_ERROR("couldn't add PRESTO VID/PID"); exit(-1); } #endif presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY); if (presto->status != FT_OK) { LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status)); return ERROR_JTAG_DEVICE_ERROR; } LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs); for (i = 0; i < numdevs; i++) { presto->status = FT_Open(i, &(presto->handle)); if (presto->status != FT_OK) { /* this is not fatal, the device may be legitimately open by other process, *hence debug message only */ LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status)); continue; } LOG_DEBUG("FTDI device %i open", (int)i); presto->status = FT_GetDeviceInfo(presto->handle, &device, &vidpid, presto->serial, devname, NULL); if (presto->status == FT_OK) { if (vidpid == PRESTO_VID_PID && (req_serial == NULL || !strcmp(presto->serial, req_serial))) break; } else LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string( presto->status)); LOG_DEBUG("FTDI device %i does not match, closing", (int)i); FT_Close(presto->handle); presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; } if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */ presto->status = FT_SetLatencyTimer(presto->handle, 1); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetTimeouts(presto->handle, 100, 0); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0xD0; presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; /* delay between first write/read turnaround (after purge?) necessary * under Linux for unknown reason, * probably a bug in library threading */ usleep(100000); presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; if (ftbytes != 1) { LOG_DEBUG("PRESTO reset"); presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetBitMode(presto->handle, 0x80, 1); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_SetBaudRate(presto->handle, 9600); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0; for (i = 0; i < 4 * 62; i++) { presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; } usleep(100000); presto->status = FT_SetBitMode(presto->handle, 0x00, 0); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto_data = 0xD0; presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason, probably a bug in library threading */ usleep(100000); presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; if (ftbytes != 1) { LOG_DEBUG("PRESTO not responding"); return ERROR_JTAG_DEVICE_ERROR; } } presto->status = FT_SetTimeouts(presto->handle, 0, 0); if (presto->status != FT_OK) return ERROR_JTAG_DEVICE_ERROR; presto->status = FT_Write(presto->handle, &presto_init_seq, sizeof(presto_init_seq), &ftbytes); if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) return ERROR_JTAG_DEVICE_ERROR; return ERROR_OK; }
/** @return number of flushed bytes on success; -1 on error */ static int usbconn_ftd2xx_flush (ftd2xx_param_t *p) { FT_STATUS status; DWORD xferred; DWORD recvd = 0; if (!p->fc) return -1; urj_log (URJ_LOG_LEVEL_COMM, "%sflush begin:\n", module); urj_log (URJ_LOG_LEVEL_COMM, " send_buf_len %d, send_buffered %d\n", p->send_buf_len, p->send_buffered); urj_log (URJ_LOG_LEVEL_COMM, " recv_buf_len %d, to_recv %d\n", p->recv_buf_len, p->to_recv); urj_log (URJ_LOG_LEVEL_COMM, " recv_write_idx %d, recv_read_idx %d\n", p->recv_write_idx, p->recv_read_idx); if (p->send_buffered == 0) return 0; if ((status = FT_Write (p->fc, p->send_buf, p->send_buffered, &xferred)) != FT_OK) { urj_error_set (URJ_ERROR_FTD, _("FT_Write() failed: %s"), ftd2xx_status_string(status)); return -1; } if (xferred < p->send_buffered) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, _("Written fewer bytes than requested")); return -1; } p->send_buffered = 0; /* now read all scheduled receive bytes */ if (p->to_recv) { if (p->recv_write_idx + p->to_recv > p->recv_buf_len) { /* extend receive buffer */ p->recv_buf_len = p->recv_write_idx + p->to_recv; if (p->recv_buf) p->recv_buf = realloc (p->recv_buf, p->recv_buf_len); } if (!p->recv_buf) { urj_error_set (URJ_ERROR_ILLEGAL_STATE, _("Receive buffer does not exist")); return -1; } while (recvd == 0) if ((status = FT_Read (p->fc, &p->recv_buf[p->recv_write_idx], p->to_recv, &recvd)) != FT_OK) urj_error_set (URJ_ERROR_FTD, _("Error from FT_Read(): %s"), ftd2xx_status_string(status)); if (recvd < p->to_recv) urj_log (URJ_LOG_LEVEL_NORMAL, _("%s(): Received fewer bytes than requested.\n"), __func__); p->to_recv -= recvd; p->recv_write_idx += recvd; } urj_log (URJ_LOG_LEVEL_COMM, "%sflush end: status %ld, xferred %ld, recvd %ld\n", module, status, xferred, recvd); return status != FT_OK ? -1 : xferred; }