static void transfer_cb(struct libusb_transfer *xfr) { int rc = 0; int len = 0; unsigned int i; /* All packets are 192 bytes. */ uint8_t* recv = malloc(PACKET_SIZE * xfr->num_iso_packets); uint8_t* recv_next = recv; for (i = 0; i < xfr->num_iso_packets; i++) { struct libusb_iso_packet_descriptor *pack = &xfr->iso_packet_desc[i]; if (pack->status != LIBUSB_TRANSFER_COMPLETED) { LOGE("Error (status %d: %s)\n", pack->status, libusb_error_name(pack->status)); continue; } const uint8_t *data = libusb_get_iso_packet_buffer_simple(xfr, i); /* PACKET_SIZE == 192 == pack->length */ memcpy(recv_next, data, PACKET_SIZE); recv_next += PACKET_SIZE; len += pack->length; } /* At this point, recv points to a buffer containing len bytes of audio. */ #if !defined(ANDROID) /* Lock around this write? */ if ((rc = write(outfd, recv, len)) < 0) { perror("Unable to write to descriptor"); } #endif free(recv); /* Sanity check. If this is true, we've overflowed the recv buffer. */ if (len > PACKET_SIZE * xfr->num_iso_packets) { LOGE("Error: incoming transfer had more data than we thought.\n"); return; } if ((rc = libusb_submit_transfer(xfr)) < 0) { LOGE("libusb_submit_transfer: %s.\n", libusb_error_name(rc)); } }
void unixUsbDriver::isoTimerTick(void){ timerCount++; char subString[3] = "th"; if(timerCount%10 == 1) strcpy(subString, "st"); if(timerCount%10 == 2) strcpy(subString, "nd"); if(timerCount%10 == 3) strcpy(subString, "rd"); if((timerCount<20) && (timerCount > 10)) strcpy(subString, "th"); //qDebug("\n\nThis is the %d%s Tick!", timerCount, subString); int n, error, earliest = MAX_OVERLAP; qint64 minFrame = 9223372036854775807; //max value for 64 bit signed unsigned int i, packetLength = 0; unsigned char* packetPointer; tcBlockMutex.lock(); for (n=0; n<NUM_FUTURE_CTX; n++){ if(allEndpointsComplete(n)){ //qDebug("Transfer %d is complete!!", n); if(transferCompleted[0][n].timeReceived < minFrame){ minFrame = transferCompleted[0][n].timeReceived; earliest = n; } } } if (earliest == MAX_OVERLAP){ tcBlockMutex.unlock(); //qDebug() << "Returning early..."; return; } //qDebug() << "Processing Ctx" << earliest; //Swap the buffers so that we override the oldest one. for (unsigned char k = 0; k< NUM_ISO_ENDPOINTS; k++){ unsigned char* temp = midBuffer_prev[k]; midBuffer_prev[k] = midBuffer_current[k]; midBuffer_current[k] = temp; } //Copy iso data into mid-buffer for(i=0;i<isoCtx[0][earliest]->num_iso_packets;i++){ for(unsigned char k=0; k<NUM_ISO_ENDPOINTS;k++){ packetPointer = libusb_get_iso_packet_buffer_simple(isoCtx[k][earliest], i); //qDebug() << packetLength; memcpy(&(midBuffer_current[k][packetLength]), packetPointer, isoCtx[k][earliest]->iso_packet_desc[i].actual_length); } packetLength += ISO_PACKET_SIZE; } packetLength = 0; //I don't really know why I use the same variable twice but hey //Read out from mid-buffer to out-buffer unsigned char *srcPtr; qint64 current_offset; for(i=0;i<isoCtx[0][earliest]->num_iso_packets;i++){ for(unsigned char k=0; k<NUM_ISO_ENDPOINTS;k++){ current_offset = midBufferOffsets[k] + i; if(current_offset >= 0){ srcPtr = &midBuffer_current[k][ISO_PACKET_SIZE * current_offset]; }else{ srcPtr = &midBuffer_prev[k][ISO_PACKET_SIZE * (ISO_PACKETS_PER_CTX + current_offset)]; } memcpy(&(outBuffers[currentWriteBuffer][packetLength]), srcPtr, ISO_PACKET_SIZE); packetLength += ISO_PACKET_SIZE; } } //qDebug() << "Data copy complete!"; //Control data for isoDriver bufferLengths[currentWriteBuffer] = packetLength; currentWriteBuffer = !currentWriteBuffer; //Setup next transfer for(unsigned char k=0; k<NUM_ISO_ENDPOINTS;k++){ transferCompleted[k][earliest].completed = false; if(shutdownMode){ error = libusb_cancel_transfer(isoCtx[k][earliest]); numCancelled++; qDebug() << "Cancelled" << earliest << k; qDebug() << "Total Cancelled =" << numCancelled; if(numCancelled == (NUM_FUTURE_CTX * NUM_ISO_ENDPOINTS)){ isoHandler->stopTime = true; } }else{ error = libusb_submit_transfer(isoCtx[k][earliest]); } if(error){ qDebug() << (shutdownMode ? "libusb_cancel_transfer FAILED" : "libusb_submit_transfer FAILED"); qDebug() << "ERROR" << libusb_error_name(error); } //else qDebug() << "isoCtx submitted successfully!"; } tcBlockMutex.unlock(); //qDebug() << "Calling upTick()"; upTick(); return; }
static void handle_completed_transfer(struct libusb_transfer *transfer){ int resubmit = 0; int signal_done = 0; if (transfer->endpoint == event_in_addr) { packet_handler(HCI_EVENT_PACKET, transfer-> buffer, transfer->actual_length); resubmit = 1; } else if (transfer->endpoint == acl_in_addr) { // log_info("-> acl"); packet_handler(HCI_ACL_DATA_PACKET, transfer-> buffer, transfer->actual_length); resubmit = 1; } else if (transfer->endpoint == sco_in_addr) { // log_info("handle_completed_transfer for SCO IN! num packets %u", transfer->NUM_ISO_PACKETS); int i; for (i = 0; i < transfer->num_iso_packets; i++) { struct libusb_iso_packet_descriptor *pack = &transfer->iso_packet_desc[i]; if (pack->status != LIBUSB_TRANSFER_COMPLETED) { log_error("Error: pack %u status %d\n", i, pack->status); continue; } if (!pack->actual_length) continue; uint8_t * data = libusb_get_iso_packet_buffer_simple(transfer, i); // printf_hexdump(data, pack->actual_length); // log_info("handle_isochronous_data,size %u/%u", pack->length, pack->actual_length); handle_isochronous_data(data, pack->actual_length); } resubmit = 1; } else if (transfer->endpoint == 0){ // log_info("command done, size %u", transfer->actual_length); usb_command_active = 0; signal_done = 1; } else if (transfer->endpoint == acl_out_addr){ // log_info("acl out done, size %u", transfer->actual_length); usb_acl_out_active = 0; signal_done = 1; } else if (transfer->endpoint == sco_out_addr){ log_info("sco out done, {{ %u/%u (%x)}, { %u/%u (%x)}, { %u/%u (%x)}}", transfer->iso_packet_desc[0].actual_length, transfer->iso_packet_desc[0].length, transfer->iso_packet_desc[0].status, transfer->iso_packet_desc[1].actual_length, transfer->iso_packet_desc[1].length, transfer->iso_packet_desc[1].status, transfer->iso_packet_desc[2].actual_length, transfer->iso_packet_desc[2].length, transfer->iso_packet_desc[2].status); if (!sco_ring_have_space()) { // if there isn't space, the last SCO send didn't emit a packet sent event signal_done = 1; } // decrease tab sco_ring_transfers_active--; // log_info("H2: sco out complete, num active num active %u", sco_ring_transfers_active); } else { log_info("usb_process_ds endpoint unknown %x", transfer->endpoint); } if (signal_done){ // notify upper stack that iit might be possible to send again uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0}; packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); } if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return; if (resubmit){ // Re-submit transfer transfer->user_data = NULL; int r = libusb_submit_transfer(transfer); if (r) { log_error("Error re-submitting transfer %d", r); } } }
/* Callback function called upon arrival of ISOC audio data */ static void aud_cap_callback(struct libusb_transfer *transfer) { static struct audio_packet packet; static int dead_counter = 0; static intptr_t prev_xfer_idx = -1; static uint32_t ts = 0; struct libusb_iso_packet_descriptor *descriptor; unsigned char* buffer; unsigned int i; intptr_t xfer_idx; assert(transfer != NULL); xfer_idx = (intptr_t) transfer->user_data; decr_active_transfers(); /* Check if audio just started. Reset static values in that case */ if(aud_first_transfer) { aud_first_transfer = 0; packet.size = 0; prev_xfer_idx = -1; } switch(transfer->status) { case LIBUSB_TRANSFER_COMPLETED: break; case LIBUSB_TRANSFER_CANCELLED: free_audio_transfer(aud_cfg.xfers, xfer_idx); TRACE2("Audio transfer cancelled\n"); return; case LIBUSB_TRANSFER_NO_DEVICE: free_audio_transfer(aud_cfg.xfers, xfer_idx); if(!audio_disconnected) { ERROR_NORET("The camera has been disconnected."); audio_disconnected = 1; } return; case LIBUSB_TRANSFER_ERROR: free_audio_transfer(aud_cfg.xfers, xfer_idx); if(!audio_disconnected) { ERROR_NORET("The audio USB transfer did not complete."); audio_disconnected = 1; } return; case LIBUSB_TRANSFER_TIMED_OUT: ERROR_NORET("The audio USB transfer timed-out."); if(aud_started && libusb_submit_transfer(transfer)>=0) incr_active_transfers(); else free_audio_transfer(aud_cfg.xfers, xfer_idx); return; case LIBUSB_TRANSFER_STALL: ERROR_NORET("The audio USB transfer stalled."); if(aud_started && libusb_submit_transfer(transfer)>=0) incr_active_transfers(); else free_audio_transfer(aud_cfg.xfers, xfer_idx); return; case LIBUSB_TRANSFER_OVERFLOW: ERROR_NORET("The audio USB transfer overflowed."); if(aud_started && libusb_submit_transfer(transfer)>=0) incr_active_transfers(); else free_audio_transfer(aud_cfg.xfers, xfer_idx); return; default: ERROR_NORET("Unknown audio USB transfer return status."); if(aud_started && libusb_submit_transfer(transfer)>=0) incr_active_transfers(); else free_audio_transfer(aud_cfg.xfers, xfer_idx); return; } /* Do nothing if the audio has been stopped */ if(aud_started == 0) { free_audio_transfer(aud_cfg.xfers, xfer_idx); return; } if(prev_xfer_idx >= 0 && xfer_idx != (prev_xfer_idx + 1) % (int)num_transfers) WARNING("Audio transfer discontinuity: expected %" PRIiPTR ", got %" PRIiPTR "\n", prev_xfer_idx + 1, xfer_idx); prev_xfer_idx = xfer_idx; #if DEBUG_AUDIO_CALLBACK > 0 /* Get time for further monitoring */ struct timeval tv_start, tv_end; struct timezone tz; int delta_time; static int max_delta_time = 0, time_counter = 0; gettimeofday(&tv_start,&tz); #endif /* Process audio packets */ for(i=0; i<packets_per_transfer; i++) { descriptor = &transfer->iso_packet_desc[i]; buffer = libusb_get_iso_packet_buffer_simple(transfer, i); if(descriptor->actual_length <= 0) { //if(packet.size > 0) { // SHOW(packet.size); // SHOW(aud_target_size); //} packet.size = 0; dead_counter++; if(dead_counter > 1000) { /* 1000 * 1ms = 1s */ TRACE( "####################################\n" " Audio seems dead!! \n" " No data has been received from the \n" " camera for one second \n" "####################################\n"); dead_counter = 0; audio_dead = 1; } continue; } dead_counter = 0; /* "Append" data to current audio 'packet' */ if(packet.size + descriptor->actual_length > aud_target_size) { WARNING("Received audio packet bigger (%i bytes) " "than targeted size (%i bytes). Skipping\n", packet.size + descriptor->actual_length, aud_target_size); packet.size = 0; continue; } if (packet.size == 0) { packet.buffer = buffer; } packet.size += descriptor->actual_length; aud_frame_count++; /* We have a full audio packet, let's process it */ if (packet.size >= aud_target_size) { #if DEBUG_AUDIO_QUEUE > 0 if(packet.size != aud_target_size) { WARNING("Received audio packet is %i bytes " "what does not match targeted size " "(%i bytes).\nLast transfer size " "was %i.", packet.size, aud_target_size, descriptor->actual_length); } #endif /* Handle buffer wrapping by memcpying the audio * wrapped at the beginning at the end of the audio buffer * ring, in the spare area allocated for that purpose * during setup_isoc_transfer() */ if (buffer < packet.buffer) { unsigned int packet_size = aud_cfg.format[aud_cfg.fmt_idx].pkt_size; /* Just in case: make sure we are not overflowing */ if((unsigned int) (buffer - abuf + descriptor->actual_length) > 10*packet_size) { SHOW(10*packet_size); SHOW((unsigned int) (buffer - abuf + descriptor->actual_length)); TRACE("buffer = %p\n", buffer); TRACE("abuf = %p\n", abuf); SHOW(descriptor->actual_length); packet.buffer = buffer; packet.size = descriptor->actual_length; continue; //assert(buffer - abuf + descriptor->actual_length <= 10*packet_size); } else { memcpy(abuf + packets_per_transfer*packet_size*num_transfers, abuf, buffer - abuf + descriptor->actual_length); } } packet.format = cur_aud_format; if(aud_cb == NULL) WARNING("Audio callback function not registered."); else { /* Create a timestamp here */ struct timeval tv; uint64_t ts64 = 0, tsec = 0, tusec = 0; audio_params_t param; gettimeofday(&tv, NULL); tsec = (uint64_t) tv.tv_sec; tusec = (uint64_t) tv.tv_usec; ts64 = (tsec*1000000 + tusec)*9/100; ts = (uint32_t) (ts64 & 0xffffffff); /* Run the registered audio callback */ aud_cb(packet.buffer, packet.size, packet.format, ts, aud_cb_user_data, ¶m); } packet.size = 0; } } #if DEBUG_AUDIO_CALLBACK > 0 /* Check how long the callback ran */ gettimeofday(&tv_end, &tz); time_counter++; delta_time = (1000000*tv_end.tv_sec + tv_end.tv_usec) - (1000000*tv_start.tv_sec + tv_start.tv_usec); if (delta_time > max_delta_time) { max_delta_time = delta_time; } if(time_counter > 50) { TRACE("Worst audio callback processing time = %i ms\n", max_delta_time/1000); time_counter = 0; max_delta_time = 0; } #endif /* Resubmit the URB */ if(aud_started && libusb_submit_transfer(transfer)>=0) incr_active_transfers(); else free_audio_transfer(aud_cfg.xfers, xfer_idx); }