diff options
author | Nikias Bassen | 2009-08-02 06:42:00 +0200 |
---|---|---|
committer | Nikias Bassen | 2009-08-02 06:42:00 +0200 |
commit | 3d517f6879b0c476a2e1ac9a55bb7d436977e3b6 (patch) | |
tree | 381e2286a4f205e48c6888458959669a256f4658 /src/usbmux.c | |
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.
Diffstat (limited to 'src/usbmux.c')
-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; } } |