summaryrefslogtreecommitdiffstats
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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,
822 pthread_mutex_lock(&client->mutex); 822 pthread_mutex_lock(&client->mutex);
823 823
824 int sendresult = 0; 824 int sendresult = 0;
825 int fullsendresult = 0;
825 uint32_t blocksize = 0; 826 uint32_t blocksize = 0;
826 if (client->wr_window <= 0) { 827 if (client->wr_window <= 0) {
827 struct timespec ts; 828 struct timespec ts;
@@ -840,20 +841,67 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,
840 // client->scnt and client->ocnt should already be in host notation... 841 // client->scnt and client->ocnt should already be in host notation...
841 // we don't need to change them juuuust yet. 842 // we don't need to change them juuuust yet.
842 char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding 843 char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding
844 const char *dataptr = data;
845 uint32_t curlen = datalen;
846 uint32_t packetsize = blocksize;
847
848 // BEGIN HACK
849 if ((blocksize % 128) == 0) {
850 int cutoff = 28;
851 // HACK: we need to split up the packet because of an unresolved
852 // usb communication issue aka 'N*128 problem' or 'N*512 problem'
853 log_debug_msg("%s: HACK: splitting packet, two send_to_device calls will follow\n");
854 packetsize = blocksize - cutoff;
855 curlen = datalen - cutoff;
856 client->header->length = packetsize;
857 client->header->length16 = packetsize;
858 hton_header(client->header);
859 memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
860 memcpy(buffer + sizeof(usbmux_tcp_header), dataptr, curlen);
861
862 log_debug_msg("%s: send_to_device(%d --> %d) window = %d\n", __func__,
863 ntohs(client->header->sport),
864 ntohs(client->header->dport),
865 ntohs(client->header->window));
866 sendresult = send_to_device(client->device, buffer, packetsize);
867 fullsendresult = sendresult;
868
869 // revert header fields that have been swapped before trying to send
870 ntoh_header(client->header);
871
872 // update counts ONLY if the send succeeded.
873 if ((uint32_t) sendresult == packetsize) {
874 // Re-calculate scnt
875 client->header->scnt += curlen;
876 client->wr_window -= packetsize;
877 } else {
878 goto err_cond;
879 }
880
881 dataptr += curlen;
882 curlen = cutoff;
883 packetsize = sizeof(usbmux_tcp_header) + curlen;
884 // fix fullsendresult to not include the header length to make
885 // setting *sent_bytes work properly
886 fullsendresult -= sizeof(usbmux_tcp_header);
887 }
888 // END HACK
889
843 // Set the length 890 // Set the length
844 client->header->length = blocksize; 891 client->header->length = packetsize;
845 client->header->length16 = blocksize; 892 client->header->length16 = packetsize;
846 893
847 // Put header into big-endian notation 894 // Put header into big-endian notation
848 hton_header(client->header); 895 hton_header(client->header);
849 // Concatenation of stuff in the buffer. 896 // Concatenation of stuff in the buffer.
850 memcpy(buffer, client->header, sizeof(usbmux_tcp_header)); 897 memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
851 memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen); 898 memcpy(buffer + sizeof(usbmux_tcp_header), dataptr, curlen);
852 899
853 log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__, 900 log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__,
854 ntohs(client->header->sport), 901 ntohs(client->header->sport),
855 ntohs(client->header->dport)); 902 ntohs(client->header->dport));
856 sendresult = send_to_device(client->device, buffer, blocksize); 903 sendresult = send_to_device(client->device, buffer, packetsize);
904 fullsendresult += sendresult;
857 // Now that we've sent it off, we can clean up after our sloppy selves. 905 // Now that we've sent it off, we can clean up after our sloppy selves.
858 if (buffer) 906 if (buffer)
859 free(buffer); 907 free(buffer);
@@ -862,12 +910,13 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,
862 ntoh_header(client->header); 910 ntoh_header(client->header);
863 911
864 // update counts ONLY if the send succeeded. 912 // update counts ONLY if the send succeeded.
865 if ((uint32_t) sendresult == blocksize) { 913 if ((uint32_t) sendresult == packetsize) {
866 // Re-calculate scnt 914 // Re-calculate scnt
867 client->header->scnt += datalen; 915 client->header->scnt += curlen;
868 client->wr_window -= blocksize; 916 client->wr_window -= packetsize;
869 } 917 }
870 918
919err_cond:
871 pthread_mutex_unlock(&client->mutex); 920 pthread_mutex_unlock(&client->mutex);
872 921
873 if (sendresult == -ETIMEDOUT || sendresult == 0) { 922 if (sendresult == -ETIMEDOUT || sendresult == 0) {
@@ -876,14 +925,14 @@ int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,
876 return -ETIMEDOUT; 925 return -ETIMEDOUT;
877 } else if (sendresult < 0) { 926 } else if (sendresult < 0) {
878 return sendresult; 927 return sendresult;
879 } else if ((uint32_t) sendresult == blocksize) { 928 } else if ((uint32_t) fullsendresult == blocksize) {
880 // actual number of data bytes sent. 929 // actual number of data bytes sent.
881 *sent_bytes = sendresult - sizeof(usbmux_tcp_header); 930 *sent_bytes = fullsendresult - sizeof(usbmux_tcp_header);
882 return 0; 931 return 0;
883 } else { 932 } else {
884 fprintf(stderr, 933 fprintf(stderr,
885 "usbsend managed to dump a packet that is not full size. %d of %d\n", 934 "usbsend managed to dump a packet that is not full size. %d of %d\n",
886 sendresult, blocksize); 935 sendresult, packetsize);
887 return -EBADMSG; 936 return -EBADMSG;
888 } 937 }
889} 938}