diff --git a/qdl.c b/qdl.c index 7ba1991..106b19a 100644 --- a/qdl.c +++ b/qdl.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,10 @@ static void print_usage(void) __progname); } +enum { + OPT_OUT_CHUNK_SIZE = 1000, +}; + int main(int argc, char **argv) { char *prog_mbn, *storage="ufs"; @@ -115,12 +120,13 @@ int main(int argc, char **argv) int ret; int opt; bool qdl_finalize_provisioning = false; - + long out_chunk_size; static struct option options[] = { {"debug", no_argument, 0, 'd'}, {"include", required_argument, 0, 'i'}, {"finalize-provisioning", no_argument, 0, 'l'}, + {"out-chunk-size", required_argument, 0, OPT_OUT_CHUNK_SIZE }, {"serial", required_argument, 0, 'S'}, {"storage", required_argument, 0, 's'}, {0, 0, 0, 0} @@ -137,6 +143,10 @@ int main(int argc, char **argv) case 'l': qdl_finalize_provisioning = true; break; + case OPT_OUT_CHUNK_SIZE: + out_chunk_size = strtol(optarg, NULL, 10); + qdl_set_out_chunk_size(&qdl, out_chunk_size); + break; case 's': storage = optarg; break; diff --git a/qdl.h b/qdl.h index 9d6d58d..c2ed0d7 100644 --- a/qdl.h +++ b/qdl.h @@ -21,6 +21,7 @@ struct qdl_device { size_t in_maxpktsize; size_t out_maxpktsize; + size_t out_chunk_size; char *mappings[MAPPING_SZ]; // array index is the id from the device }; @@ -28,6 +29,7 @@ struct qdl_device { int qdl_open(struct qdl_device *qdl, const char *serial); int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout); int qdl_write(struct qdl_device *qdl, const void *buf, size_t len); +void qdl_set_out_chunk_size(struct qdl_device *qdl, long size); int firehose_run(struct qdl_device *qdl, const char *incdir, const char *storage); int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, diff --git a/usb.c b/usb.c index 381cfa3..cda5e74 100644 --- a/usb.c +++ b/usb.c @@ -10,6 +10,8 @@ #include "qdl.h" +#define DEFAULT_OUT_CHUNK_SIZE (1024 * 1024) + /* * libusb commit f0cce43f882d ("core: Fix definition and use of enum * libusb_transfer_type") split transfer type and endpoint transfer types. @@ -141,6 +143,20 @@ static int qdl_try_open(libusb_device *dev, struct qdl_device *qdl, const char * qdl->in_maxpktsize = in_size; qdl->out_maxpktsize = out_size; + if (qdl->out_chunk_size && qdl->out_chunk_size % out_size) { + fprintf(stderr, + "WARNING: requested out-chunk-size must be multiple of the device's wMaxPacketSize %ld, using %ld\n", + out_size, out_size); + qdl->out_chunk_size = out_size; + } else if (!qdl->out_chunk_size) { + qdl->out_chunk_size = DEFAULT_OUT_CHUNK_SIZE; + } + + if (qdl_debug) { + fprintf(stderr, "USB: using out-chunk-size of %ld\n", + qdl->out_chunk_size); + } + return 1; } @@ -215,7 +231,7 @@ int qdl_write(struct qdl_device *qdl, const void *buf, size_t len) int ret; while (len > 0) { - xfer = (len > qdl->out_maxpktsize) ? qdl->out_maxpktsize : len; + xfer = (len > qdl->out_chunk_size) ? qdl->out_chunk_size : len; ret = libusb_bulk_transfer(qdl->usb_handle, qdl->out_ep, data, xfer, &actual, 1000); @@ -239,3 +255,8 @@ int qdl_write(struct qdl_device *qdl, const void *buf, size_t len) return count; } + +void qdl_set_out_chunk_size(struct qdl_device *qdl, long size) +{ + qdl->out_chunk_size = size; +}