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));
	}
}
Beispiel #2
0
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);
        }
    }   
}
Beispiel #4
0
/* 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, &param);
			}
			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);
}