summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2009-08-02 06:42:00 +0200
committerGravatar Nikias Bassen2009-08-02 06:42:00 +0200
commit3d517f6879b0c476a2e1ac9a55bb7d436977e3b6 (patch)
tree381e2286a4f205e48c6888458959669a256f4658
parent50a85a4c8b50a9884ddd5530132995dc962ebb13 (diff)
downloadusbmuxd-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.c69
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;
}
}