FalconCommLibUSB::~FalconCommLibUSB() { libusb_free_transfer(in_transfer); libusb_free_transfer(out_transfer); delete m_tv; }
FCDevice::Transfer::~Transfer() { libusb_free_transfer(transfer); }
/* read the content of SPI device to buf, make sure the buf is big enough before call */ int32_t ch341SpiRead(uint8_t *buf, uint32_t add, uint32_t len) { uint8_t out[CH341_MAX_PACKET_LEN]; uint8_t in[CH341_PACKET_LENGTH]; if (devHandle == NULL) return -1; /* what subtracted is: 1. first cs package, 2. leading command for every other packages, * 3. second package contains read flash command and 3 bytes address */ const uint32_t max_payload = CH341_MAX_PACKET_LEN - CH341_PACKET_LENGTH - CH341_MAX_PACKETS + 1 - 4; uint32_t tmp, pkg_len, pkg_count; struct libusb_transfer *xferBulkIn, *xferBulkOut; uint32_t idx = 0; uint32_t ret = 0; int32_t old_counter; struct timeval tv = {0, 100}; memset(out, 0xff, CH341_MAX_PACKET_LEN); for (int i = 1; i < CH341_MAX_PACKETS; ++i) // fill CH341A_CMD_SPI_STREAM for every packet out[i * CH341_PACKET_LENGTH] = CH341A_CMD_SPI_STREAM; memset(in, 0x00, CH341_PACKET_LENGTH); xferBulkIn = libusb_alloc_transfer(0); xferBulkOut = libusb_alloc_transfer(0); while (len > 0) { ch341SpiCs(out, true); idx = CH341_PACKET_LENGTH + 1; out[idx++] = 0xC0; // byte swapped command for Flash Read tmp = add; for (int i = 0; i < 3; ++i) { // starting address of next read out[idx++] = swapByte((tmp >> 16) & 0xFF); tmp <<= 8; } if (len > max_payload) { pkg_len = CH341_MAX_PACKET_LEN; pkg_count = CH341_MAX_PACKETS - 1; len -= max_payload; add += max_payload; } else { pkg_count = (len + 4) / (CH341_PACKET_LENGTH - 1); if ((len + 4) % (CH341_PACKET_LENGTH - 1)) pkg_count ++; pkg_len = (pkg_count) * CH341_PACKET_LENGTH + ((len + 4) % (CH341_PACKET_LENGTH - 1)) + 1; len = 0; } bulkin_count = 0; libusb_fill_bulk_transfer(xferBulkIn, devHandle, BULK_READ_ENDPOINT, in, CH341_PACKET_LENGTH, cbBulkIn, buf, DEFAULT_TIMEOUT); buf += max_payload; // advance user's pointer libusb_submit_transfer(xferBulkIn); libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, out, pkg_len, cbBulkOut, NULL, DEFAULT_TIMEOUT); libusb_submit_transfer(xferBulkOut); old_counter = bulkin_count; while (bulkin_count < pkg_count) { libusb_handle_events_timeout(NULL, &tv); if (bulkin_count == -1) { // encountered error len = 0; ret = -1; break; } if (old_counter != bulkin_count) { // new package came if (bulkin_count != pkg_count) libusb_submit_transfer(xferBulkIn); // resubmit bulk in request old_counter = bulkin_count; } } ch341SpiCs(out, false); ret = usbTransfer(__func__, BULK_WRITE_ENDPOINT, out, 3); if (ret < 0) break; if (force_stop == 1) { // user hit ctrl+C force_stop = 0; if (len > 0) fprintf(stderr, "User hit Ctrl+C, reading unfinished.\n"); break; } } libusb_free_transfer(xferBulkIn); libusb_free_transfer(xferBulkOut); return ret; }
/////////////////////////////////////////////////////////////////////////////// ///@author Nicolae Bodislav ///@brief Writes data from the USB device on bulk. ///@param [in]p_pData - the buffer that contains the data to write ///@param [in]p_nLength - size of the data contained in the buffer ///@retval how many bytes were actually written; or < 0 for error /////////////////////////////////////////////////////////////////////////////// int CUSBLink::WriteBulk(const unsigned char* p_pData, uint32_t p_nLength) { m_nCb = 0; m_nTrasferedLength = 0; if(p_nLength > MAX_LENGTH) { NLOG_ERR("[CUSBLink][WriteBulk] To much data to write. Maz is %d", MAX_LENGTH); return -1; } if(m_pDevh == NULL) { NLOG_ERR("[CUSBLink][WriteBulk] Device not open."); return -1; } int rez = libusb_claim_interface(m_pDevh, 0); if (rez < 0) { NLOG_ERR("[CUSBLink][WriteBulk] USB_claim_interface error %d\n", rez); return -2; } m_enumDealoc = CUSBLink::INTERFACE; m_pData_transfer = NULL; m_pData_transfer = libusb_alloc_transfer(0); if (!m_pData_transfer) { NLOG_ERR("[CUSBLink][WriteBulk] Transfer couldn't be allocated."); return -ENOMEM; } libusb_fill_bulk_transfer(m_pData_transfer, m_pDevh, m_cWriteEndpoint, (unsigned char*)p_pData, p_nLength, Cb_TransferRead, this, 1000); m_enumDealoc = CUSBLink::TRANSFER; rez = libusb_submit_transfer(m_pData_transfer); if (rez < 0) { NLOG_ERR("[CUSBLink][WriteBulk] Transfer couldn't be submitted."); libusb_cancel_transfer(m_pData_transfer); m_enumDealoc = CUSBLink::INTERFACE; while (!m_nCb) { rez = libusb_handle_events(m_pContex); if (rez < 0) { break; } } libusb_free_transfer(m_pData_transfer); return -1; } while (!m_nCb) { rez = libusb_handle_events(m_pContex); if (rez < 0) { libusb_free_transfer(m_pData_transfer); return -1; } } if (m_bRawLog) { NLOG_DBG_HEX("[CUSBLink][WriteBulk] Wrote packet:", p_pData, m_nTrasferedLength); } return m_nTrasferedLength; }
static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, int *transferred, unsigned int timeout, unsigned char type) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, bulk_transfer_cb, &completed, timeout); transfer->type = type; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0) break; libusb_free_transfer(transfer); return r; } } *transferred = transfer->actual_length; switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = 0; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_OVERFLOW: r = LIBUSB_ERROR_OVERFLOW; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct sr_dev_driver *di = sdi->driver; struct drv_context *drvc; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *src; struct sr_usb_dev_inst *usb; GVariant *gvar, *rational[2]; const uint64_t *si; int req_len, buf_len, len, ret; unsigned char buf[9]; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; drvc = di->context; devc = sdi->priv; usb = sdi->conn; devc->num_samples = 0; std_session_send_df_header(sdi); if (devc->data_source == DATA_SOURCE_LIVE) { /* Force configuration. */ kecheng_kc_330b_configure(sdi); if (kecheng_kc_330b_status_get(sdi, &ret) != SR_OK) return SR_ERR; if (ret != DEVICE_ACTIVE) { sr_err("Device is inactive"); /* Still continue though, since the device will * just return 30.0 until the user hits the button * on the device -- and then start feeding good * samples back. */ } } else { if (kecheng_kc_330b_log_info_get(sdi, buf) != SR_OK) return SR_ERR; devc->mqflags = buf[4] ? SR_MQFLAG_SPL_TIME_WEIGHT_S : SR_MQFLAG_SPL_TIME_WEIGHT_F; devc->mqflags |= buf[5] ? SR_MQFLAG_SPL_FREQ_WEIGHT_C : SR_MQFLAG_SPL_FREQ_WEIGHT_A; devc->stored_samples = (buf[7] << 8) | buf[8]; if (devc->stored_samples == 0) { /* Notify frontend of empty log by sending start/end packets. */ std_session_send_df_end(sdi); return SR_OK; } if (devc->limit_samples && devc->limit_samples < devc->stored_samples) devc->stored_samples = devc->limit_samples; si = kecheng_kc_330b_sample_intervals[buf[1]]; rational[0] = g_variant_new_uint64(si[0]); rational[1] = g_variant_new_uint64(si[1]); gvar = g_variant_new_tuple(rational, 2); src = sr_config_new(SR_CONF_SAMPLE_INTERVAL, gvar); packet.type = SR_DF_META; packet.payload = &meta; meta.config = g_slist_append(NULL, src); sr_session_send(sdi, &packet); g_free(src); } if (!(devc->xfer = libusb_alloc_transfer(0))) return SR_ERR; usb_source_add(sdi->session, drvc->sr_ctx, 10, kecheng_kc_330b_handle_events, (void *)sdi); if (devc->data_source == DATA_SOURCE_LIVE) { buf[0] = CMD_GET_LIVE_SPL; buf_len = 1; devc->state = LIVE_SPL_WAIT; devc->last_live_request = g_get_monotonic_time() / 1000; req_len = 3; } else { buf[0] = CMD_GET_LOG_DATA; buf[1] = 0; buf[2] = 0; buf_len = 4; devc->state = LOG_DATA_WAIT; if (devc->stored_samples < 63) buf[3] = devc->stored_samples; else buf[3] = 63; /* Command ack byte + 2 bytes per sample. */ req_len = 1 + buf[3] * 2; } ret = libusb_bulk_transfer(usb->devhdl, EP_OUT, buf, buf_len, &len, 5); if (ret != 0 || len != 1) { sr_dbg("Failed to start acquisition: %s", libusb_error_name(ret)); libusb_free_transfer(devc->xfer); return SR_ERR; } libusb_fill_bulk_transfer(devc->xfer, usb->devhdl, EP_IN, devc->buf, req_len, kecheng_kc_330b_receive_transfer, (void *)sdi, 15); if (libusb_submit_transfer(devc->xfer) != 0) { libusb_free_transfer(devc->xfer); return SR_ERR; } return SR_OK; }
int main(void) { struct sigaction sigact; int r = 1; exit_sem = sem_open (SEM_NAME, O_CREAT, 0); if (!exit_sem) { fprintf(stderr, "failed to initialise semaphore error %d", errno); exit(1); } /* only using this semaphore in this process so go ahead and unlink it now */ sem_unlink (SEM_NAME); r = libusb_init(NULL); if (r < 0) { fprintf(stderr, "failed to initialise libusb\n"); exit(1); } r = find_dpfp_device(); if (r < 0) { fprintf(stderr, "Could not find/open device\n"); goto out; } r = libusb_claim_interface(devh, 0); if (r < 0) { fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r)); goto out; } printf("claimed interface\n"); r = print_f0_data(); if (r < 0) goto out_release; r = do_init(); if (r < 0) goto out_deinit; /* async from here onwards */ sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL); if (r) goto out_deinit; r = alloc_transfers(); if (r < 0) { request_exit(1); pthread_join(poll_thread, NULL); goto out_deinit; } r = init_capture(); if (r < 0) { request_exit(1); pthread_join(poll_thread, NULL); goto out_deinit; } while (!do_exit) sem_wait(exit_sem); printf("shutting down...\n"); pthread_join(poll_thread, NULL); r = libusb_cancel_transfer(irq_transfer); if (r < 0) { request_exit(1); goto out_deinit; } r = libusb_cancel_transfer(img_transfer); if (r < 0) { request_exit(1); goto out_deinit; } while (img_transfer || irq_transfer) if (libusb_handle_events(NULL) < 0) break; if (do_exit == 1) r = 0; else r = 1; out_deinit: libusb_free_transfer(img_transfer); libusb_free_transfer(irq_transfer); set_mode(0); set_hwstat(0x80); out_release: libusb_release_interface(devh, 0); out: libusb_close(devh); libusb_exit(NULL); return r >= 0 ? r : -r; }
static int usb_close(void *transport_config){ int c; // @TODO: remove all run loops! switch (libusb_state){ case LIB_USB_CLOSED: break; case LIB_USB_TRANSFERS_ALLOCATED: libusb_state = LIB_USB_INTERFACE_CLAIMED; if(usb_timer_active) { run_loop_remove_timer(&usb_timer); usb_timer_active = 0; } // Cancel any asynchronous transfers for (c = 0 ; c < ASYNC_BUFFERS ; c++) { libusb_cancel_transfer(event_in_transfer[c]); libusb_cancel_transfer(acl_in_transfer[c]); #ifdef HAVE_SCO libusb_cancel_transfer(sco_in_transfer[c]); #endif } /* TODO - find a better way to ensure that all transfers have completed */ struct timeval tv; memset(&tv, 0, sizeof(struct timeval)); libusb_handle_events_timeout(NULL, &tv); if (doing_pollfds){ int r; for (r = 0 ; r < num_pollfds ; r++) { data_source_t *ds = &pollfd_data_sources[r]; run_loop_remove_data_source(ds); } free(pollfd_data_sources); pollfd_data_sources = NULL; num_pollfds = 0; doing_pollfds = 0; } case LIB_USB_INTERFACE_CLAIMED: for (c = 0 ; c < ASYNC_BUFFERS ; c++) { if (event_in_transfer[c]) libusb_free_transfer(event_in_transfer[c]); if (acl_in_transfer[c]) libusb_free_transfer(acl_in_transfer[c]); #ifdef HAVE_SCO if (sco_in_transfer[c]) libusb_free_transfer(sco_in_transfer[c]); #endif } // TODO free control and acl out transfers libusb_release_interface(handle, 0); case LIB_USB_DEVICE_OPENDED: libusb_close(handle); case LIB_USB_OPENED: libusb_exit(NULL); } libusb_state = LIB_USB_CLOSED; handle = NULL; return 0; }
void FalconCommLibUSB::cb_in(struct libusb_transfer *transfer) { ((FalconCommLibUSB*)transfer->user_data)->setSent(); libusb_free_transfer(transfer); }
static void state_activate_cb(struct libusb_transfer *transfer) { struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = ssm->priv; struct vfs0050_dev *vfs_dev = dev->priv; switch (ssm->cur_state) { case M_ACTIVATE_1_SINGLE_READ: //check bytes are 0x00 and 0x00 if (vfs_dev->tmpbuf[0] != 0x00 || vfs_dev->tmpbuf[1] != 0x00) { fp_dbg("unexpected bytes back from endpoint in M_ACTIVATE_1_SINGLE_READ"); libusb_free_transfer(transfer); fpi_ssm_jump_to_state(ssm, M_ACTIVATE_START); break; } libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; case M_ACTIVATE_2_SEND: vfs_dev->activate_offset += transfer->actual_length; if (vfs_dev->activate_offset == sizeof(vfs0050_activate2)) { //finished sending this activation section fpi_ssm_next_state(ssm); break; } fpi_ssm_jump_to_state(ssm, M_ACTIVATE_2_SEND); break; case M_ACTIVATE_EP1_DRAIN: //just draining this data, not sure what it does yet. if (transfer->actual_length < 64) { libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; } libusb_free_transfer(transfer); fpi_ssm_jump_to_state(ssm, M_ACTIVATE_EP1_DRAIN); break; case M_ACTIVATE_EP3_INT1: if (transfer->actual_length != 5) { fp_dbg("unexpected length for interrupt transfer in M_ACTIVATE_EP3_INT1"); //TODO: fail here, exit ssm } fpi_ssm_next_state(ssm); break; case M_ACTIVATE_AWAIT_FINGER: //if we got here, it's time to read fingerprint data. //interrupt data should be 02 00 0e 00 f0 if (vfs_dev->is_active) { if (transfer->actual_length != 5) { fp_dbg("unexpected length for interrupt transfer in M_ACTIVATE_AWAIT_FINGER"); //TODO: fail here, exit ssm. } if (memcmp(vfs_dev->tmpbuf, vfs0050_valid_interrupt, 5) != 0) { fp_dbg("invalid interrupt data in M_ACTIVATE_AWAIT_FINGER"); //TODO: fail here, exit ssm. } fpi_imgdev_report_finger_status(dev, TRUE); //report finger on to libfprint fpi_ssm_next_state(ssm); } else { fpi_ssm_mark_completed(ssm); //break fall through } break; case M_ACTIVATE_RECEIVE_FINGERPRINT: if (transfer->actual_length == 0) { libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; } vfs_dev->scanbuf_idx += transfer->actual_length; libusb_free_transfer(transfer); fpi_ssm_jump_to_state(ssm, M_ACTIVATE_RECEIVE_FINGERPRINT); break; default: libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; } }
static void generic_async_cb(struct libusb_transfer *t) { libusb_free_transfer(t); }
~Transfer() { libusb_free_transfer(xfer_); if (pack_) { pack_->destroy(); } }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { GSList *usb_devices, *devices, *l; struct drv_context *drvc; struct sr_dev_inst *sdi; struct dev_context *devc; struct sr_usb_dev_inst *usb; struct device_info dev_info; unsigned int i; int ret; (void)options; devices = NULL; drvc = di->context; drvc->instances = NULL; usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, USB_VID_PID); if (!usb_devices) return NULL; for (l = usb_devices; l; l = l->next) { usb = l->data; if ((ret = sl2_get_device_info(*usb, &dev_info)) < 0) { sr_warn("Failed to get device information: %d.", ret); sr_usb_dev_inst_free(usb); continue; } devc = g_malloc0(sizeof(struct dev_context)); if (!(devc->xfer_in = libusb_alloc_transfer(0))) { sr_err("Transfer malloc failed."); sr_usb_dev_inst_free(usb); g_free(devc); continue; } if (!(devc->xfer_out = libusb_alloc_transfer(0))) { sr_err("Transfer malloc failed."); sr_usb_dev_inst_free(usb); libusb_free_transfer(devc->xfer_in); g_free(devc); continue; } sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_NAME); sdi->model = g_strdup(MODEL_NAME); sdi->version = g_strdup_printf("%u.%u", dev_info.fw_ver_major, dev_info.fw_ver_minor); sdi->serial_num = g_strdup_printf("%d", dev_info.serial); sdi->priv = devc; sdi->driver = di; sdi->inst_type = SR_INST_USB; sdi->conn = usb; for (i = 0; i < ARRAY_SIZE(channel_names); i++) devc->channels[i] = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_names[i]); devc->state = STATE_IDLE; devc->next_state = STATE_IDLE; /* Set default samplerate. */ sl2_set_samplerate(sdi, DEFAULT_SAMPLERATE); /* Set default capture ratio. */ devc->capture_ratio = 0; /* Set default after trigger delay. */ devc->after_trigger_delay = 0; memset(devc->xfer_buf_in, 0, LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH); memset(devc->xfer_buf_out, 0, LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH); libusb_fill_control_setup(devc->xfer_buf_in, USB_REQUEST_TYPE_IN, USB_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE, PACKET_LENGTH); libusb_fill_control_setup(devc->xfer_buf_out, USB_REQUEST_TYPE_OUT, USB_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE, PACKET_LENGTH); devc->xfer_data_in = devc->xfer_buf_in + LIBUSB_CONTROL_SETUP_SIZE; devc->xfer_data_out = devc->xfer_buf_out + LIBUSB_CONTROL_SETUP_SIZE; drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); } g_slist_free(usb_devices); return devices; }
static int lusb_init_stream(void *driver, struct bladerf_stream *stream, size_t num_transfers) { int status = 0; size_t i; struct lusb_stream_data *stream_data; /* Fill in backend stream information */ stream_data = malloc(sizeof(struct lusb_stream_data)); if (!stream_data) { return BLADERF_ERR_MEM; } /* Backend stream information */ stream->backend_data = stream_data; stream_data->transfers = NULL; stream_data->transfer_status = NULL; stream_data->num_transfers = num_transfers; stream_data->num_avail = 0; stream_data->i = 0; stream_data->transfers = malloc(num_transfers * sizeof(struct libusb_transfer *)); if (stream_data->transfers == NULL) { log_error("Failed to allocate libusb tranfers\n"); status = BLADERF_ERR_MEM; goto error; } stream_data->transfer_status = calloc(num_transfers, sizeof(transfer_status)); if (stream_data->transfer_status == NULL) { log_error("Failed to allocated libusb transfer status array\n"); status = BLADERF_ERR_MEM; goto error; } /* Create the libusb transfers */ for (i = 0; i < stream_data->num_transfers; i++) { stream_data->transfers[i] = libusb_alloc_transfer(0); /* Upon error, start tearing down anything we've started allocating * and report that the stream is in a bad state */ if (stream_data->transfers[i] == NULL) { /* Note: <= 0 not appropriate as we're dealing * with an unsigned index */ while (i > 0) { if (--i) { libusb_free_transfer(stream_data->transfers[i]); stream_data->transfers[i] = NULL; stream_data->transfer_status[i] = TRANSFER_UNINITIALIZED; stream_data->num_avail--; } } status = BLADERF_ERR_MEM; break; } else { stream_data->transfer_status[i] = TRANSFER_AVAIL; stream_data->num_avail++; } } error: if (status != 0) { free(stream_data->transfer_status); free(stream_data->transfers); free(stream_data); stream->backend_data = NULL; } return status; }
void receive_transfer(struct libusb_transfer *transfer) { /* TODO: these statics have to move to fx2_device struct */ static int num_samples = 0; static int empty_transfer_count = 0; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; struct fx2_device *fx2; int cur_buflen, trigger_offset, i; unsigned char *cur_buf, *new_buf; /* hw_stop_acquisition() is telling us to stop. */ if (transfer == NULL) num_samples = -1; /* * If acquisition has already ended, just free any queued up * transfer that come in. */ if (num_samples == -1) { if (transfer) libusb_free_transfer(transfer); return; } sr_info("saleae: receive_transfer(): status %d received %d bytes", transfer->status, transfer->actual_length); /* Save incoming transfer before reusing the transfer struct. */ cur_buf = transfer->buffer; cur_buflen = transfer->actual_length; fx2 = transfer->user_data; /* Fire off a new request. */ if (!(new_buf = g_try_malloc(4096))) { sr_err("saleae: %s: new_buf malloc failed", __func__); // return SR_ERR_MALLOC; return; /* FIXME */ } transfer->buffer = new_buf; transfer->length = 4096; if (libusb_submit_transfer(transfer) != 0) { /* TODO: Stop session? */ sr_warn("eek"); } if (cur_buflen == 0) { empty_transfer_count++; if (empty_transfer_count > MAX_EMPTY_TRANSFERS) { /* * The FX2 gave up. End the acquisition, the frontend * will work out that the samplecount is short. */ hw_stop_acquisition(-1, fx2->session_data); } return; } else { empty_transfer_count = 0; } trigger_offset = 0; if (fx2->trigger_stage >= 0) { for (i = 0; i < cur_buflen; i++) { if ((cur_buf[i] & fx2->trigger_mask[fx2->trigger_stage]) == fx2->trigger_value[fx2->trigger_stage]) { /* Match on this trigger stage. */ fx2->trigger_buffer[fx2->trigger_stage] = cur_buf[i]; fx2->trigger_stage++; if (fx2->trigger_stage == NUM_TRIGGER_STAGES || fx2->trigger_mask[fx2->trigger_stage] == 0) { /* Match on all trigger stages, we're done. */ trigger_offset = i + 1; /* * TODO: Send pre-trigger buffer to session bus. * Tell the frontend we hit the trigger here. */ packet.type = SR_DF_TRIGGER; packet.timeoffset = (num_samples + i) * fx2->period_ps; packet.duration = 0; packet.payload = NULL; sr_session_bus(fx2->session_data, &packet); /* * Send the samples that triggered it, since we're * skipping past them. */ packet.type = SR_DF_LOGIC; packet.timeoffset = (num_samples + i) * fx2->period_ps; packet.duration = fx2->trigger_stage * fx2->period_ps; packet.payload = &logic; logic.length = fx2->trigger_stage; logic.unitsize = 1; logic.data = fx2->trigger_buffer; sr_session_bus(fx2->session_data, &packet); fx2->trigger_stage = TRIGGER_FIRED; break; } return; } /* * We had a match before, but not in the next sample. However, we may * have a match on this stage in the next bit -- trigger on 0001 will * fail on seeing 00001, so we need to go back to stage 0 -- but at * the next sample from the one that matched originally, which the * counter increment at the end of the loop takes care of. */ if (fx2->trigger_stage > 0) { i -= fx2->trigger_stage; if (i < -1) i = -1; /* Oops, went back past this buffer. */ /* Reset trigger stage. */ fx2->trigger_stage = 0; } } } if (fx2->trigger_stage == TRIGGER_FIRED) { /* Send the incoming transfer to the session bus. */ packet.type = SR_DF_LOGIC; packet.timeoffset = num_samples * fx2->period_ps; packet.duration = cur_buflen * fx2->period_ps; packet.payload = &logic; logic.length = cur_buflen - trigger_offset; logic.unitsize = 1; logic.data = cur_buf + trigger_offset; sr_session_bus(fx2->session_data, &packet); g_free(cur_buf); num_samples += cur_buflen; if (fx2->limit_samples && (unsigned int) num_samples > fx2->limit_samples) { hw_stop_acquisition(-1, fx2->session_data); } } else { /* * TODO: Buffer pre-trigger data in capture * ratio-sized buffer. */ } }
/* * Called by libusb (as triggered by handle_event()) when a transfer comes in. * Only channel data comes in asynchronously, and all transfers for this are * queued up beforehand, so this just needs to chuck the incoming data onto * the libsigrok session bus. */ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) { struct sr_dev_inst *sdi; struct dev_context *devc; sdi = transfer->user_data; devc = sdi->priv; if (devc->dev_state == FLUSH) { g_free(transfer->buffer); libusb_free_transfer(transfer); devc->dev_state = CAPTURE; devc->aq_started = g_get_monotonic_time(); read_channel(sdi, data_amount(sdi)); return; } if (devc->dev_state != CAPTURE) return; if (!devc->sample_buf) { devc->sample_buf_size = 10; devc->sample_buf = g_try_malloc(devc->sample_buf_size * sizeof(transfer)); devc->sample_buf_write = 0; } if (devc->sample_buf_write >= devc->sample_buf_size) { devc->sample_buf_size += 10; devc->sample_buf = g_try_realloc(devc->sample_buf, devc->sample_buf_size * sizeof(transfer)); if (!devc->sample_buf) { sr_err("Sample buffer malloc failed."); devc->dev_state = STOPPING; return; } } devc->sample_buf[devc->sample_buf_write++] = transfer; devc->samp_received += transfer->actual_length / NUM_CHANNELS; sr_spew("receive_transfer(): calculated samplerate == %" PRIu64 "ks/s", (uint64_t)(transfer->actual_length * 1000 / (g_get_monotonic_time() - devc->read_start_ts + 1) / NUM_CHANNELS)); sr_spew("receive_transfer(): status %s received %d bytes.", libusb_error_name(transfer->status), transfer->actual_length); if (transfer->actual_length == 0) /* Nothing to send to the bus. */ return; if (devc->limit_samples && devc->samp_received >= devc->limit_samples) { sr_info("Requested number of samples reached, stopping. %" PRIu64 " <= %" PRIu64, devc->limit_samples, devc->samp_received); send_data(sdi, devc->sample_buf, devc->limit_samples); sdi->driver->dev_acquisition_stop(sdi); } else if (devc->limit_msec && (g_get_monotonic_time() - devc->aq_started) / 1000 >= devc->limit_msec) { sr_info("Requested time limit reached, stopping. %d <= %d", (uint32_t)devc->limit_msec, (uint32_t)(g_get_monotonic_time() - devc->aq_started) / 1000); send_data(sdi, devc->sample_buf, devc->samp_received); g_free(devc->sample_buf); devc->sample_buf = NULL; sdi->driver->dev_acquisition_stop(sdi); } else { read_channel(sdi, data_amount(sdi)); } }
static int hw_start_acquisition(int device_index, gpointer session_data) { struct sr_device_instance *sdi; struct sr_datafeed_packet *packet; struct sr_datafeed_header *header; struct fx2_device *fx2; struct libusb_transfer *transfer; const struct libusb_pollfd **lupfd; int size, i; unsigned char *buf; if (!(sdi = sr_get_device_instance(device_instances, device_index))) return SR_ERR; fx2 = sdi->priv; fx2->session_data = session_data; if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) { sr_err("saleae: %s: packet malloc failed", __func__); return SR_ERR_MALLOC; } if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) { sr_err("saleae: %s: header malloc failed", __func__); return SR_ERR_MALLOC; } /* Start with 2K transfer, subsequently increased to 4K. */ size = 2048; for (i = 0; i < NUM_SIMUL_TRANSFERS; i++) { if (!(buf = g_try_malloc(size))) { sr_err("saleae: %s: buf malloc failed", __func__); return SR_ERR_MALLOC; } transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, sdi->usb->devhdl, 2 | LIBUSB_ENDPOINT_IN, buf, size, receive_transfer, fx2, 40); if (libusb_submit_transfer(transfer) != 0) { /* TODO: Free them all. */ libusb_free_transfer(transfer); g_free(buf); return SR_ERR; } size = 4096; } lupfd = libusb_get_pollfds(usb_context); for (i = 0; lupfd[i]; i++) sr_source_add(lupfd[i]->fd, lupfd[i]->events, 40, receive_data, NULL); free(lupfd); packet->type = SR_DF_HEADER; packet->payload = header; header->feed_version = 1; gettimeofday(&header->starttime, NULL); header->samplerate = fx2->cur_samplerate; header->num_logic_probes = fx2->profile->num_probes; header->num_analog_probes = 0; sr_session_bus(session_data, packet); g_free(header); g_free(packet); return SR_OK; }
void usb_transfer_destroy(USBTransfer *usb_transfer) { struct timeval tv; time_t start; time_t now; int rc; log_debug("Destroying %s transfer %p (%p) for %s", usb_transfer_get_type_name(usb_transfer->type, false), usb_transfer, usb_transfer->handle, usb_transfer->usb_stack->base.name); if (usb_transfer->submitted) { usb_transfer->completed = false; usb_transfer->cancelled = true; rc = libusb_cancel_transfer(usb_transfer->handle); // if libusb_cancel_transfer fails with LIBUSB_ERROR_NO_DEVICE if the // device was disconnected before the transfer could be cancelled. but // the transfer might be cancelled anyway and we need to wait for the // transfer to complete. this can result in waiting for a transfer that // might not complete anymore. but if we don't wait for the transfer to // complete if it actually will complete then the libusb_device_handle // might be closed before the transfer completes. this results in a // crash by NULL pointer dereference because libusb assumes that the // libusb_device_handle is not closed as long as there are submitted // transfers. if (rc < 0 && rc != LIBUSB_ERROR_NO_DEVICE) { log_warn("Could not cancel pending %s transfer %p (%p) for %s: %s (%d)", usb_transfer_get_type_name(usb_transfer->type, false), usb_transfer, usb_transfer->handle, usb_transfer->usb_stack->base.name, usb_get_error_name(rc), rc); } else { tv.tv_sec = 0; tv.tv_usec = 0; start = time(NULL); now = start; // FIXME: don't wait 1 second per transfer while (!usb_transfer->completed && now >= start && now < start + 1) { rc = libusb_handle_events_timeout(usb_transfer->usb_stack->context, &tv); if (rc < 0) { log_error("Could not handle USB events during %s transfer %p (%p) cancellation for %s: %s (%d)", usb_transfer_get_type_name(usb_transfer->type, false), usb_transfer, usb_transfer->handle, usb_transfer->usb_stack->base.name, usb_get_error_name(rc), rc); } now = time(NULL); } if (!usb_transfer->completed) { log_warn("Attempt to cancel pending %s transfer %p (%p) for %s timed out", usb_transfer_get_type_name(usb_transfer->type, false), usb_transfer, usb_transfer->handle, usb_transfer->usb_stack->base.name); } } } if (!usb_transfer->submitted) { libusb_free_transfer(usb_transfer->handle); } else { log_warn("Leaking pending %s transfer %p (%p) for %s", usb_transfer_get_type_name(usb_transfer->type, false), usb_transfer, usb_transfer->handle, usb_transfer->usb_stack->base.name); } }
EnttecDMXDevice::Transfer::~Transfer() { libusb_free_transfer(transfer); }
static int start_transfers(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_usb_dev_inst *usb; struct sr_trigger *trigger; struct libusb_transfer *transfer; unsigned int i, num_transfers; int timeout, ret; unsigned char *buf; size_t size; devc = sdi->priv; usb = sdi->conn; devc->sent_samples = 0; devc->acq_aborted = FALSE; devc->empty_transfer_count = 0; if ((trigger = sr_session_trigger_get(sdi->session))) { int pre_trigger_samples = 0; if (devc->limit_samples > 0) pre_trigger_samples = (devc->capture_ratio * devc->limit_samples) / 100; devc->stl = soft_trigger_logic_new(sdi, trigger, pre_trigger_samples); if (!devc->stl) return SR_ERR_MALLOC; devc->trigger_fired = FALSE; } else devc->trigger_fired = TRUE; num_transfers = get_number_of_transfers(devc); size = get_buffer_size(devc); devc->submitted_transfers = 0; devc->transfers = g_try_malloc0(sizeof(*devc->transfers) * num_transfers); if (!devc->transfers) { sr_err("USB transfers malloc failed."); return SR_ERR_MALLOC; } timeout = get_timeout(devc); devc->num_transfers = num_transfers; for (i = 0; i < num_transfers; i++) { if (!(buf = g_try_malloc(size))) { sr_err("USB transfer buffer malloc failed."); return SR_ERR_MALLOC; } transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, usb->devhdl, 2 | LIBUSB_ENDPOINT_IN, buf, size, receive_transfer, (void *)sdi, timeout); sr_info("submitting transfer: %d", i); if ((ret = libusb_submit_transfer(transfer)) != 0) { sr_err("Failed to submit transfer: %s.", libusb_error_name(ret)); libusb_free_transfer(transfer); g_free(buf); fx2lafw_abort_acquisition(devc); return SR_ERR; } devc->transfers[i] = transfer; devc->submitted_transfers++; } /* * If this device has analog channels and at least one of them is * enabled, use mso_send_data_proc() to properly handle the analog * data. Otherwise use la_send_data_proc(). */ if (g_slist_length(devc->enabled_analog_channels) > 0) devc->send_data_proc = mso_send_data_proc; else devc->send_data_proc = la_send_data_proc; std_session_send_df_header(sdi); return SR_OK; }
/////////////////////////////////////////////////////////////////////////////// ///@author Nicolae Bodislav ///@brief Reads data from the USB device on bulk. ///@param [out]p_pData - Buffer to store output data ///@param [in]p_nLegth - Size of the output buffer ///@param [in]p_nMiliSec - How much to wait for data before abandoning the read operation ///@retval size of the data written in the output buffer or < 0 for error /////////////////////////////////////////////////////////////////////////////// int CUSBLink::ReadBulk(unsigned char* p_pData, uint32_t p_nLegth, unsigned int p_nMiliSec /*= 10*/ ) { m_nCb = 0; m_nTrasferedLength = 0; if(m_pDevh == NULL) { NLOG_ERR("[CUSBLink][ReadBulk] Device not open."); return -1; } int rez = libusb_claim_interface(m_pDevh, 0); if (rez < 0) { NLOG_ERR("[CUSBLink][ReadBulk] Couldn't claim interface."); return -1; } m_enumDealoc = CUSBLink::INTERFACE; m_pData_transfer = NULL; m_pData_transfer = libusb_alloc_transfer(0); if (!m_pData_transfer) { NLOG_ERR("[CUSBLink][ReadBulk] Transfer couldn't be allocated."); return -ENOMEM; } m_pDev = libusb_get_device(m_pDevh); int max_packet_size = libusb_get_max_packet_size(m_pDev, m_cReadEndpoint); libusb_fill_bulk_transfer(m_pData_transfer, m_pDevh, m_cReadEndpoint, m_pData, max_packet_size, Cb_TransferRead, this, p_nMiliSec); m_enumDealoc = CUSBLink::TRANSFER; rez = libusb_submit_transfer(m_pData_transfer); if (rez < 0) { NLOG_ERR("[CUSBLink][ReadBulk] Transfer couldn't be submitted."); libusb_cancel_transfer(m_pData_transfer); m_enumDealoc = CUSBLink::INTERFACE; while (!m_nCb) { rez = libusb_handle_events(m_pContex); if (rez < 0) { break; } } libusb_free_transfer(m_pData_transfer); return -1; } while (!m_nCb) { rez = libusb_handle_events(m_pContex); if (rez < 0) { libusb_free_transfer(m_pData_transfer); return -1; } } if(m_bHaveData) { if(m_nTrasferedLength > 0) { memcpy(p_pData, m_pData, m_nTrasferedLength); if (m_bRawLog) { NLOG_DBG_HEX("[CUSBLink][ReadBulk] Received packet:", m_pData, m_nTrasferedLength); } } else p_pData = NULL; } return m_nTrasferedLength; }
UsbEndPoint::~UsbEndPoint() { libusb_free_transfer(_transfer); }
int main(void) { struct sigaction sigact; int r = 1; r = libusb_init(NULL); if (r < 0) { fprintf(stderr, "failed to initialise libusb\n"); exit(1); } r = find_dpfp_device(); if (r < 0) { fprintf(stderr, "Could not find/open device\n"); goto out; } r = libusb_claim_interface(devh, 0); if (r < 0) { fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r)); goto out; } printf("claimed interface\n"); r = print_f0_data(); if (r < 0) goto out_release; r = do_init(); if (r < 0) goto out_deinit; sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL); if (r) goto out_deinit; r = alloc_transfers(); if (r < 0) { request_exit(1); pthread_join(poll_thread, NULL); goto out_deinit; } r = init_capture(); if (r < 0) { request_exit(1); pthread_join(poll_thread, NULL); goto out_deinit; } while (!do_exit) { pthread_mutex_lock(&exit_cond_lock); pthread_cond_wait(&exit_cond, &exit_cond_lock); pthread_mutex_unlock(&exit_cond_lock); } printf("shutting down...\n"); pthread_join(poll_thread, NULL); r = libusb_cancel_transfer(irq_transfer); if (r < 0) { request_exit(1); goto out_deinit; } r = libusb_cancel_transfer(img_transfer); if (r < 0) { request_exit(1); goto out_deinit; } while (img_transfer || irq_transfer) if (libusb_handle_events(NULL) < 0) break; if (do_exit == 1) r = 0; else r = 1; out_deinit: libusb_free_transfer(img_transfer); libusb_free_transfer(irq_transfer); set_mode(0); set_hwstat(0x80); out_release: libusb_release_interface(devh, 0); out: libusb_close(devh); libusb_exit(NULL); return r >= 0 ? r : -r; }
int slogic_execute_recording(struct slogic_handle *handle, struct slogic_recording *recording) { /* TODO: validate recording */ int retval =0; struct libusb_transfer *transfer; unsigned char *buffer; int counter; int ret; struct slogic_internal_recording *internal_recording = allocate_internal_recording(handle, recording); /* * TODO: We probably want to tune the transfer buffer size to a sane * default based on the sampling rate. If transfer_buffer_size is * samples per second / 10 we can expect 10 transfers per second which * should be sufficient for a user application to be responsive while * not having too many transfers per second. * - Trygve */ log_printf(&logger, DEBUG, "Starting recording...\n"); log_printf(&logger, DEBUG, "Transfer buffers: %d\n", internal_recording->n_transfer_buffers); log_printf(&logger, DEBUG, "Transfer buffer size: %zu\n", handle->transfer_buffer_size); log_printf(&logger, DEBUG, "Transfer timeout: %u\n", handle->transfer_timeout); /* Pre-allocate transfers */ for (counter = 0; counter < internal_recording->n_transfer_buffers; counter++) { buffer = malloc(handle->transfer_buffer_size); assert(buffer); transfer = libusb_alloc_transfer(0); if (transfer == NULL) { log_printf(&logger, ERR, "libusb_alloc_transfer failed\n"); recording->recording_state = UNKNOWN; retval = 1; return retval; } libusb_fill_bulk_transfer(transfer, handle->device_handle, STREAMING_DATA_IN_ENDPOINT, buffer, handle->transfer_buffer_size, slogic_read_samples_callback, &internal_recording->transfers[counter], handle->transfer_timeout); internal_recording->transfers[counter].internal_recording = internal_recording; internal_recording->transfers[counter].transfer = transfer; } recording->recording_state = WARMING_UP; internal_recording->done = false; /* Submit all transfers */ for (counter = 0; counter < internal_recording->n_transfer_buffers; counter++) { internal_recording->transfers[counter].seq = tcounter++; ret = libusb_submit_transfer(internal_recording->transfers[counter].transfer); if (ret) { log_printf(&logger, ERR, "libusb_submit_transfer: %s\n", usbutil_error_to_string(ret)); recording->recording_state = UNKNOWN; retval =1; return retval; } } log_printf(&logger, DEBUG, "sample_delay=%d\n", recording->sample_rate->sample_delay); struct timeval start; assert(gettimeofday(&start, NULL) == 0); struct timeval timeout = { 1, 0 }; while (!internal_recording->done) { ret = libusb_handle_events_timeout(handle->context, &timeout); if (ret) { log_printf(&logger, ERR, "libusb_handle_events: %s\n", usbutil_error_to_string(ret)); break; } } struct timeval end; assert(gettimeofday(&end, NULL) == 0); for (counter = 0; counter < internal_recording->n_transfer_buffers; counter++) { libusb_cancel_transfer(internal_recording->transfers[counter].transfer); libusb_free_transfer(internal_recording->transfers[counter].transfer); internal_recording->transfers[counter].transfer = NULL; } if (internal_recording->recording->recording_state != COMPLETED_SUCCESSFULLY) { log_printf(&logger, ERR, "FAIL! recording_state=%d\n", internal_recording->recording->recording_state); retval =1; } else { log_printf(&logger, DEBUG, "SUCCESS!\n"); } log_printf(&logger, DEBUG, "Total number of samples read: %i\n", internal_recording->sample_count); log_printf(&logger, DEBUG, "Total number of transfers: %i\n", internal_recording->transfer_counter); int sec = end.tv_sec - start.tv_sec; int usec = (end.tv_usec - start.tv_usec) / 1000; if (usec < 0) { sec--; usec = 1 - usec; } log_printf(&logger, DEBUG, "Time elapsed: %d.%03ds\n", sec, usec); free_internal_recording(internal_recording); return retval; }
/** \ingroup syncio * Perform a USB control transfer. * * The direction of the transfer is inferred from the bmRequestType field of * the setup packet. * * The wValue, wIndex and wLength fields values should be given in host-endian * byte order. * * \param dev_handle a handle for the device to communicate with * \param bmRequestType the request type field for the setup packet * \param bRequest the request field for the setup packet * \param wValue the value field for the setup packet * \param wIndex the index field for the setup packet * \param data a suitably-sized data buffer for either input or output * (depending on direction bits within bmRequestType) * \param wLength the length field for the setup packet. The data buffer should * be at least this size. * \param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. * \returns on success, the number of bytes actually transferred * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the * device * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failures */ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); unsigned char *buffer; int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); if (!buffer) { libusb_free_transfer(transfer); return LIBUSB_ERROR_NO_MEM; } libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); libusb_fill_control_transfer(transfer, dev_handle, buffer, ctrl_transfer_cb, &completed, timeout); transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0) break; libusb_free_transfer(transfer); return r; } } if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) memcpy(data, libusb_control_transfer_get_data(transfer), transfer->actual_length); switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = transfer->actual_length; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; case LIBUSB_TRANSFER_OVERFLOW: r = LIBUSB_ERROR_OVERFLOW; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
/* * Called by libusb (as triggered by handle_event()) when a transfer comes in. * Only channel data comes in asynchronously, and all transfers for this are * queued up beforehand, so this just needs to chuck the incoming data onto * the libsigrok session bus. */ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) { struct sr_datafeed_packet packet; struct sr_dev_inst *sdi; struct dev_context *devc; int num_samples, pre; sdi = transfer->user_data; devc = sdi->priv; sr_spew("receive_transfer(): status %d received %d bytes.", transfer->status, transfer->actual_length); if (transfer->actual_length == 0) /* Nothing to send to the bus. */ return; num_samples = transfer->actual_length / 2; sr_spew("Got %d-%d/%d samples in frame.", devc->samp_received + 1, devc->samp_received + num_samples, devc->framesize); /* * The device always sends a full frame, but the beginning of the frame * doesn't represent the trigger point. The offset at which the trigger * happened came in with the capture state, so we need to start sending * from there up the session bus. The samples in the frame buffer * before that trigger point came after the end of the device's frame * buffer was reached, and it wrapped around to overwrite up until the * trigger point. */ if (devc->samp_received < devc->trigger_offset) { /* Trigger point not yet reached. */ if (devc->samp_received + num_samples < devc->trigger_offset) { /* The entire chunk is before the trigger point. */ memcpy(devc->framebuf + devc->samp_buffered * 2, transfer->buffer, num_samples * 2); devc->samp_buffered += num_samples; } else { /* * This chunk hits or overruns the trigger point. * Store the part before the trigger fired, and * send the rest up to the session bus. */ pre = devc->trigger_offset - devc->samp_received; memcpy(devc->framebuf + devc->samp_buffered * 2, transfer->buffer, pre * 2); devc->samp_buffered += pre; /* The rest of this chunk starts with the trigger point. */ sr_dbg("Reached trigger point, %d samples buffered.", devc->samp_buffered); /* Avoid the corner case where the chunk ended at * exactly the trigger point. */ if (num_samples > pre) send_chunk(sdi, transfer->buffer + pre * 2, num_samples - pre); } } else { /* Already past the trigger point, just send it all out. */ send_chunk(sdi, transfer->buffer, num_samples); } devc->samp_received += num_samples; /* Everything in this transfer was either copied to the buffer or * sent to the session bus. */ g_free(transfer->buffer); libusb_free_transfer(transfer); if (devc->samp_received >= devc->framesize) { /* That was the last chunk in this frame. Send the buffered * pre-trigger samples out now, in one big chunk. */ sr_dbg("End of frame, sending %d pre-trigger buffered samples.", devc->samp_buffered); send_chunk(sdi, devc->framebuf, devc->samp_buffered); /* Mark the end of this frame. */ packet.type = SR_DF_FRAME_END; sr_session_send(devc->cb_data, &packet); if (devc->limit_frames && ++devc->num_frames == devc->limit_frames) { /* Terminate session */ devc->dev_state = STOPPING; } else { devc->dev_state = NEW_CAPTURE; } } }
USBBuffer::~USBBuffer() { libusb_free_transfer(mTransfer); delete[] mBuffer; }
static void WriteAsyncCallback(struct libusb_transfer *transfer) { free(transfer->buffer); libusb_free_transfer(transfer); }
/* write buffer(*buf) to SPI flash */ int32_t ch341SpiWrite(uint8_t *buf, uint32_t add, uint32_t len) { uint8_t out[WRITE_PAYLOAD_LENGTH]; uint8_t in[CH341_PACKET_LENGTH]; uint32_t tmp, pkg_count; struct libusb_transfer *xferBulkIn, *xferBulkOut; uint32_t idx = 0; uint32_t ret; int32_t old_counter; struct timeval tv = {0, 100}; if (devHandle == NULL) return -1; memset(out, 0xff, WRITE_PAYLOAD_LENGTH); xferBulkIn = libusb_alloc_transfer(0); xferBulkOut = libusb_alloc_transfer(0); while (len > 0) { out[0] = 0x06; // Write enable ret = ch341SpiStream(out, in, 1); ch341SpiCs(out, true); idx = CH341_PACKET_LENGTH; out[idx++] = CH341A_CMD_SPI_STREAM; out[idx++] = 0x40; // byte swapped command for Flash Page Write tmp = add; for (int i = 0; i < 3; ++i) { // starting address of next write out[idx++] = swapByte((tmp >> 16) & 0xFF); tmp <<= 8; } tmp = 0; pkg_count = 1; while ((idx < WRITE_PAYLOAD_LENGTH) && (len > tmp)) { if (idx % CH341_PACKET_LENGTH == 0) { out[idx++] = CH341A_CMD_SPI_STREAM; pkg_count ++; } else { out[idx++] = swapByte(*buf++); tmp++; if (((add + tmp) & 0xFF) == 0) // cross page boundary break; } } len -= tmp; add += tmp; bulkin_count = 0; libusb_fill_bulk_transfer(xferBulkIn, devHandle, BULK_READ_ENDPOINT, in, CH341_PACKET_LENGTH, cbBulkIn, NULL, DEFAULT_TIMEOUT); libusb_submit_transfer(xferBulkIn); libusb_fill_bulk_transfer(xferBulkOut, devHandle, BULK_WRITE_ENDPOINT, out, idx, cbBulkOut, NULL, DEFAULT_TIMEOUT); libusb_submit_transfer(xferBulkOut); old_counter = bulkin_count; ret = 0; while (bulkin_count < pkg_count) { libusb_handle_events_timeout(NULL, &tv); if (bulkin_count == -1) { // encountered error ret = -1; break; } if (old_counter != bulkin_count) { // new package came if (bulkin_count != pkg_count) libusb_submit_transfer(xferBulkIn); // resubmit bulk in request old_counter = bulkin_count; } } if (ret < 0) break; ch341SpiCs(out, false); ret = usbTransfer(__func__, BULK_WRITE_ENDPOINT, out, 3); if (ret < 0) break; out[0] = 0x04; // Write disable ret = ch341SpiStream(out, in, 1); do { ret = ch341ReadStatus(); if (ret != 0) libusb_handle_events_timeout(NULL, &tv); } while(ret != 0); if (force_stop == 1) { // user hit ctrl+C force_stop = 0; if (len > 0) fprintf(stderr, "User hit Ctrl+C, writing unfinished.\n"); break; } } libusb_free_transfer(xferBulkIn); libusb_free_transfer(xferBulkOut); return ret; }
int main (int argc, char **argv) { bool daemonize = false; while (true) { int c; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {"daemon", no_argument, NULL, 'd'}, {"fork", no_argument, NULL, 'f'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "hvd", long_options, NULL); if (c == -1) break; switch (c) { case 'h': print_usage(argv[0]); exit(EXIT_SUCCESS); case 'v': msg("HAMA MCE remote event client v%s for XBMC\n", VERSION); exit(EXIT_SUCCESS); case 'd': daemonize = true; break; default: print_usage(argv[0]); exit(EXIT_FAILURE); } } if (optind < (argc - 1)) { err("%s: too many arguments\n", argv[0]); exit(EXIT_FAILURE); } struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_handler = handle_exit; PCHK(sigaction(SIGINT, &sa, NULL)); PCHK(sigaction(SIGTERM, &sa, NULL)); libusb_context *ctx; libusb_device_handle *dev; struct libusb_transfer *transfer0x81 = libusb_alloc_transfer(0); struct libusb_transfer *transfer0x82 = libusb_alloc_transfer(0); unsigned char buf0x81 [8]; unsigned char buf0x82 [5]; UCHK(libusb_init(&ctx)); if (!(dev = libusb_open_device_with_vid_pid(ctx, 0x05a4, 0x9881))) { err("%s: No HAMA MCE remote control found.\n", argv[0]); exit(EXIT_FAILURE); } int exit_code = EXIT_SUCCESS; if (libusb_kernel_driver_active(dev, 0)) UCHK(libusb_detach_kernel_driver(dev, 0)); if (libusb_kernel_driver_active(dev, 1)) UCHK(libusb_detach_kernel_driver(dev, 1)); UCHK(libusb_claim_interface(dev, 0)); UCHK(libusb_claim_interface(dev, 1)); libusb_fill_interrupt_transfer(transfer0x81, dev, 0x81, buf0x81, sizeof(buf0x81), transfer0x81_cb, NULL, 215); UCHK(libusb_submit_transfer(transfer0x81)); libusb_fill_interrupt_transfer(transfer0x82, dev, 0x82, buf0x82, sizeof(buf0x82), transfer0x82_cb, NULL, 200); UCHK(libusb_submit_transfer(transfer0x82)); msg("Connected HAMA MCE Remote\n"); xbmc.SendHELO("HAMA MCE Remote", ICON_NONE); if (daemonize) { if (daemon(0,0) == -1) { err("Failed to fork\n"); perror(argv[0]); exit_code = EXIT_FAILURE; goto exit; } } while (!(disconnected || quit)) { UCHK(libusb_handle_events(ctx)); } exit: if (disconnected) { msg("Disconnected HAMA MCE Remote\n"); xbmc.SendNOTIFICATION("Disconnected", "HAMA MCE Remote", ICON_NONE); } else { msg("Closing HAMA MCE Remote\n"); xbmc.SendNOTIFICATION("Closing", "HAMA MCE Remote", ICON_NONE); } libusb_free_transfer(transfer0x81); libusb_free_transfer(transfer0x82); if (!disconnected) { // Release the remote back to the system UCHK(libusb_release_interface(dev, 0)); UCHK(libusb_release_interface(dev, 1)); UCHK(libusb_attach_kernel_driver(dev, 0)); UCHK(libusb_attach_kernel_driver(dev, 1)); } libusb_close(dev); libusb_exit(ctx); exit(exit_code); }