diff options
| author | 2009-08-02 06:42:00 +0200 | |
|---|---|---|
| committer | 2009-08-02 06:42:00 +0200 | |
| commit | 3d517f6879b0c476a2e1ac9a55bb7d436977e3b6 (patch) | |
| tree | 381e2286a4f205e48c6888458959669a256f4658 | |
| parent | 50a85a4c8b50a9884ddd5530132995dc962ebb13 (diff) | |
| download | usbmuxd-3d517f6879b0c476a2e1ac9a55bb7d436977e3b6.tar.gz usbmuxd-3d517f6879b0c476a2e1ac9a55bb7d436977e3b6.tar.bz2 | |
Workaround for usb communication issue aka 'N*128 problem' or 'N*512 problem'
For some strange reason packets that are N*128 bytes long via USB 1.1,
or N*512 bytes long via USB 2.0, the device will not send an answer and
any following packet will cause a connection reset.
See this as a workaround until the usb issue has been resolved.
| -rw-r--r-- | src/usbmux.c | 69 | 
1 files changed, 59 insertions, 10 deletions
| diff --git a/src/usbmux.c b/src/usbmux.c index 1d6497e..2157e05 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -822,6 +822,7 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,  	pthread_mutex_lock(&client->mutex);  	int sendresult = 0; +	int fullsendresult = 0;  	uint32_t blocksize = 0;  	if (client->wr_window <= 0) {  		struct timespec ts; @@ -840,20 +841,67 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,  	// client->scnt and client->ocnt should already be in host notation...  	// we don't need to change them juuuust yet.   	char *buffer = (char *) malloc(blocksize + 2);	// allow 2 bytes of safety padding +	const char *dataptr = data; +	uint32_t curlen = datalen; +	uint32_t packetsize = blocksize; + +	// BEGIN HACK +	if ((blocksize % 128) == 0) { +	    int cutoff = 28; +	    // HACK: we need to split up the packet because of an unresolved +	    // usb communication issue aka 'N*128 problem' or 'N*512 problem' +	    log_debug_msg("%s: HACK: splitting packet, two send_to_device calls will follow\n"); +	    packetsize = blocksize - cutoff; +	    curlen = datalen - cutoff; +	    client->header->length = packetsize; +	    client->header->length16 = packetsize; +	    hton_header(client->header); +	    memcpy(buffer, client->header, sizeof(usbmux_tcp_header)); +	    memcpy(buffer + sizeof(usbmux_tcp_header), dataptr, curlen); + +	    log_debug_msg("%s: send_to_device(%d --> %d) window = %d\n", __func__, +				  ntohs(client->header->sport), +				  ntohs(client->header->dport), +				  ntohs(client->header->window)); +	    sendresult = send_to_device(client->device, buffer, packetsize); +	    fullsendresult = sendresult; + +	    // revert header fields that have been swapped before trying to send +	    ntoh_header(client->header); + +	    // update counts ONLY if the send succeeded. +	    if ((uint32_t) sendresult == packetsize) { +		// Re-calculate scnt +		client->header->scnt += curlen; +		client->wr_window -= packetsize; +	    } else { +		goto err_cond; +	    } + +	    dataptr += curlen; +	    curlen = cutoff; +	    packetsize = sizeof(usbmux_tcp_header) + curlen; +	    // fix fullsendresult to not include the header length to make +	    //  setting *sent_bytes work properly +	    fullsendresult -= sizeof(usbmux_tcp_header); +	} +	// END HACK +  	// Set the length -	client->header->length = blocksize; -	client->header->length16 = blocksize; +	client->header->length = packetsize; +	client->header->length16 = packetsize;  	// Put header into big-endian notation  	hton_header(client->header);  	// Concatenation of stuff in the buffer.  	memcpy(buffer, client->header, sizeof(usbmux_tcp_header)); -	memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen); +	memcpy(buffer + sizeof(usbmux_tcp_header), dataptr, curlen);  	log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__,  				  ntohs(client->header->sport),  				  ntohs(client->header->dport)); -	sendresult = send_to_device(client->device, buffer, blocksize); +	sendresult = send_to_device(client->device, buffer, packetsize); +	fullsendresult += sendresult;  	// Now that we've sent it off, we can clean up after our sloppy selves.  	if (buffer)  		free(buffer); @@ -862,12 +910,13 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,  	ntoh_header(client->header);  	// update counts ONLY if the send succeeded. -	if ((uint32_t) sendresult == blocksize) { +	if ((uint32_t) sendresult == packetsize) {  		// Re-calculate scnt -		client->header->scnt += datalen; -		client->wr_window -= blocksize; +		client->header->scnt += curlen; +		client->wr_window -= packetsize;  	} +err_cond:  	pthread_mutex_unlock(&client->mutex);  	if (sendresult == -ETIMEDOUT || sendresult == 0) { @@ -876,14 +925,14 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,  		return -ETIMEDOUT;  	} else if (sendresult < 0) {  		return sendresult; -	} else if ((uint32_t) sendresult == blocksize) { +	} else if ((uint32_t) fullsendresult == blocksize) {  		// actual number of data bytes sent. -		*sent_bytes = sendresult - sizeof(usbmux_tcp_header); +		*sent_bytes = fullsendresult - sizeof(usbmux_tcp_header);  		return 0;  	} else {  		fprintf(stderr,  				"usbsend managed to dump a packet that is not full size. %d of %d\n", -				sendresult, blocksize); +				sendresult, packetsize);  		return -EBADMSG;  	}  } | 
