/** * Close the USB port and reset the sequencer logic. * * @param devc The struct containing private per-device-instance data. * * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments. */ static int close_usb_reset_sequencer(struct dev_context *devc) { /* Magic sequence of bytes for resetting the sequencer logic. */ uint8_t buf[8] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; int ret; /* Note: Caller checked that devc and devc->ftdic != NULL. */ if (devc->ftdic->usb_dev) { /* Reset the sequencer logic, then wait 100ms. */ sr_dbg("Resetting sequencer logic."); (void) cv_write(devc, buf, 8); /* Ignore errors. */ g_usleep(100 * 1000); /* Purge FTDI buffers, then reset and close the FTDI device. */ sr_dbg("Purging buffers, resetting+closing FTDI device."); /* Log errors, but ignore them (i.e., don't abort). */ if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) sr_err("Failed to purge FTDI buffers (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); if ((ret = ftdi_usb_reset(devc->ftdic)) < 0) sr_err("Failed to reset FTDI device (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); if ((ret = ftdi_usb_close(devc->ftdic)) < 0) sr_err("Failed to close FTDI device (%d): %s.", ret, ftdi_get_error_string(devc->ftdic)); } /* Close USB device, deinitialize and free the FTDI context. */ ftdi_free(devc->ftdic); devc->ftdic = NULL; return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; uint8_t buf[8]; int bytes_to_write, bytes_written; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; if (!(devc = sdi->priv)) { sr_err("sdi->priv was NULL."); return SR_ERR_BUG; } if (!devc->ftdic) { sr_err("devc->ftdic was NULL."); return SR_ERR_BUG; } devc->divcount = cv_samplerate_to_divcount(sdi, devc->cur_samplerate); if (devc->divcount == 0xff) { sr_err("Invalid divcount/samplerate."); return SR_ERR; } if (cv_convert_trigger(sdi) != SR_OK) { sr_err("Failed to configure trigger."); return SR_ERR; } /* Fill acquisition parameters into buf[]. */ if (devc->prof->model == CHRONOVU_LA8) { buf[0] = devc->divcount; buf[1] = 0xff; /* This byte must always be 0xff. */ buf[2] = devc->trigger_pattern & 0xff; buf[3] = devc->trigger_mask & 0xff; bytes_to_write = 4; } else { buf[0] = devc->divcount; buf[1] = 0xff; /* This byte must always be 0xff. */ buf[2] = (devc->trigger_pattern & 0xff00) >> 8; /* LSB */ buf[3] = (devc->trigger_pattern & 0x00ff) >> 0; /* MSB */ buf[4] = (devc->trigger_mask & 0xff00) >> 8; /* LSB */ buf[5] = (devc->trigger_mask & 0x00ff) >> 0; /* MSB */ buf[6] = (devc->trigger_edgemask & 0xff00) >> 8; /* LSB */ buf[7] = (devc->trigger_edgemask & 0x00ff) >> 0; /* MSB */ bytes_to_write = 8; } /* Start acquisition. */ bytes_written = cv_write(devc, buf, bytes_to_write); if (bytes_written < 0 || bytes_written != bytes_to_write) { sr_err("Acquisition failed to start."); return SR_ERR; } sr_dbg("Hardware acquisition started successfully."); devc->cb_data = cb_data; /* Send header packet to the session bus. */ std_session_send_df_header(sdi, LOG_PREFIX); /* Time when we should be done (for detecting trigger timeouts). */ devc->done = (devc->divcount + 1) * devc->prof->trigger_constant + g_get_monotonic_time() + (10 * G_TIME_SPAN_SECOND); devc->block_counter = 0; devc->trigger_found = 0; /* Hook up a dummy handler to receive data from the device. */ sr_session_source_add(sdi->session, -1, G_IO_IN, 0, receive_data, (void *)sdi); return SR_OK; }