diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2016-04-29 18:58:16 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-05-02 17:35:45 -0700 |
commit | d37d50832564bb5fb7dc0f79ea1eb0faf160bd9c (patch) | |
tree | 392a7f0157bb2845fe614db3b2701f0aacd10bfd /extra | |
parent | 455767f08fe81dd8932e6868f748fea5ae50a30f (diff) | |
download | chrome-ec-d37d50832564bb5fb7dc0f79ea1eb0faf160bd9c.tar.gz |
usb_updater: shut down on errors more gracefully and simplify APIs
It might not matter much, but it is a good practice to explicitly
release USB resources when terminating the app which used them.
Also, make function signatures around the file simpler by introducing
a structure to carry common USB endpoint properties: device handle,
endpoint number and chunk size.
BRANCH=none
BUG=chrome-os-partner:52856
TEST=no change in functionality, upgrades on B1 still work fine,
upgrades on Kevin still very unreliable
Change-Id: I9157774a2f5591c70701ba822f20db6ba02e7029
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/341616
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'extra')
-rw-r--r-- | extra/usb_updater/usb_updater.c | 108 |
1 files changed, 53 insertions, 55 deletions
diff --git a/extra/usb_updater/usb_updater.c b/extra/usb_updater/usb_updater.c index 2b528779d2..588a176a27 100644 --- a/extra/usb_updater/usb_updater.c +++ b/extra/usb_updater/usb_updater.c @@ -32,6 +32,12 @@ #define SUBCLASS USB_SUBCLASS_GOOGLE_CR50 #define PROTOCOL USB_PROTOCOL_GOOGLE_CR50_NON_HC_FW_UPDATE +struct usb_endpoint { + struct libusb_device_handle *devh; + uint8_t ep_num; + int chunk_len; +}; + /* Globals */ static char *progname; static char *short_opts = ":d:h"; @@ -42,6 +48,14 @@ static const struct option long_opts[] = { {NULL, 0, NULL, 0}, }; +/* Release USB device and return error to the OS. */ +static void shut_down(struct usb_endpoint *uep) +{ + libusb_close(uep->devh); + libusb_exit(NULL); + exit(1); +} + static void usage(int errs) { printf("\nUsage: %s [options] ec.bin\n" @@ -99,15 +113,16 @@ static uint8_t *get_file_or_die(const char *filename, uint32_t *len_ptr) fprintf(stderr, "%s:%d, %s returned %d (%s)\n", __FILE__, __LINE__, \ m, r, libusb_strerror(r)) -static void xfer(struct libusb_device_handle *devh, uint8_t ep_num, - void *outbuf, int outlen, void *inbuf, int inlen) { +static void xfer(struct usb_endpoint *uep, void *outbuf, + int outlen, void *inbuf, int inlen) +{ int r, actual; /* Send data out */ if (outbuf && outlen) { actual = 0; - r = libusb_bulk_transfer(devh, ep_num, + r = libusb_bulk_transfer(uep->devh, uep->ep_num, outbuf, outlen, &actual, 1000); if (r < 0) { @@ -117,7 +132,7 @@ static void xfer(struct libusb_device_handle *devh, uint8_t ep_num, if (actual != outlen) { fprintf(stderr, "%s:%d, only sent %d/%d bytes\n", __FILE__, __LINE__, actual, outlen); - exit(1); + shut_down(uep); } } @@ -125,7 +140,7 @@ static void xfer(struct libusb_device_handle *devh, uint8_t ep_num, if (inbuf && inlen) { actual = 0; - r = libusb_bulk_transfer(devh, ep_num | 0x80, + r = libusb_bulk_transfer(uep->devh, uep->ep_num | 0x80, inbuf, inlen, &actual, 1000); if (r < 0) { @@ -135,7 +150,7 @@ static void xfer(struct libusb_device_handle *devh, uint8_t ep_num, if (actual != inlen) { fprintf(stderr, "%s:%d, only received %d/%d bytes\n", __FILE__, __LINE__, actual, inlen); - exit(1); + shut_down(uep); } } } @@ -143,7 +158,7 @@ static void xfer(struct libusb_device_handle *devh, uint8_t ep_num, /* Return 0 on error, since it's never gonna be EP 0 */ static int find_endpoint(const struct libusb_interface_descriptor *iface, - uint8_t *ep_num_ptr, int *chunk_len_ptr) + struct usb_endpoint *uep) { const struct libusb_endpoint_descriptor *ep; @@ -152,8 +167,8 @@ static int find_endpoint(const struct libusb_interface_descriptor *iface, iface->bInterfaceProtocol == PROTOCOL && iface->bNumEndpoints) { ep = &iface->endpoint[0]; - *ep_num_ptr = (ep->bEndpointAddress & 0x7f); - *chunk_len_ptr = ep->wMaxPacketSize; + uep->ep_num = ep->bEndpointAddress & 0x7f; + uep->chunk_len = ep->wMaxPacketSize; return 1; } @@ -161,8 +176,7 @@ static int find_endpoint(const struct libusb_interface_descriptor *iface, } /* Return -1 on error */ -static int find_interface(struct libusb_device_handle *devh, - uint8_t *ep_num_ptr, int *chunk_len_ptr) +static int find_interface(struct usb_endpoint *uep) { int iface_num = -1; int r, i, j; @@ -171,7 +185,7 @@ static int find_interface(struct libusb_device_handle *devh, const struct libusb_interface *iface0; const struct libusb_interface_descriptor *iface; - dev = libusb_get_device(devh); + dev = libusb_get_device(uep->devh); r = libusb_get_active_config_descriptor(dev, &conf); if (r < 0) { USB_ERROR("libusb_get_active_config_descriptor", r); @@ -182,7 +196,7 @@ static int find_interface(struct libusb_device_handle *devh, iface0 = &conf->interface[i]; for (j = 0; j < iface0->num_altsetting; j++) { iface = &iface0->altsetting[j]; - if (find_endpoint(iface, ep_num_ptr, chunk_len_ptr)) { + if (find_endpoint(iface, uep)) { iface_num = i; goto out; } @@ -218,12 +232,12 @@ static int parse_vidpid(const char *input, uint16_t *vid_ptr, uint16_t *pid_ptr) } -static struct libusb_device_handle *usb_findit(uint16_t vid, uint16_t pid, - uint8_t *ep_num, int *chunk_len) +static void usb_findit(uint16_t vid, uint16_t pid, struct usb_endpoint *uep) { - struct libusb_device_handle *devh; int iface_num, r; + memset(uep, 0, sizeof(*uep)); + r = libusb_init(NULL); if (r < 0) { USB_ERROR("libusb_init", r); @@ -232,34 +246,33 @@ static struct libusb_device_handle *usb_findit(uint16_t vid, uint16_t pid, printf("open_device %04x:%04x\n", vid, pid); /* NOTE: This doesn't handle multiple matches! */ - devh = libusb_open_device_with_vid_pid(NULL, vid, pid); - if (!devh) { + uep->devh = libusb_open_device_with_vid_pid(NULL, vid, pid); + if (!uep->devh) { fprintf(stderr, "can't find device\n"); exit(1); } - iface_num = find_interface(devh, ep_num, chunk_len); + iface_num = find_interface(uep); if (iface_num < 0) { fprintf(stderr, "USB FW update not supported by that device\n"); - exit(1); + shut_down(uep); } - if (!chunk_len) { + if (!uep->chunk_len) { fprintf(stderr, "wMaxPacketSize isn't valid\n"); - exit(1); + shut_down(uep); } printf("found interface %d endpoint %d, chunk_len %d\n", - iface_num, *ep_num, *chunk_len); + iface_num, uep->ep_num, uep->chunk_len); - libusb_set_auto_detach_kernel_driver(devh, 1); - r = libusb_claim_interface(devh, iface_num); + libusb_set_auto_detach_kernel_driver(uep->devh, 1); + r = libusb_claim_interface(uep->devh, iface_num); if (r < 0) { USB_ERROR("libusb_claim_interface", r); - exit(1); + shut_down(uep); } printf("READY\n-------\n"); - return devh; } #define SIGNED_TRANSFER_SIZE 1024 @@ -276,9 +289,8 @@ struct update_pdu { #define FLASH_BASE 0x40000 -static void transfer_and_reboot(struct libusb_device_handle *devh, - uint8_t *data, uint32_t data_len, - uint8_t ep_num, int chunk_len) +static void transfer_and_reboot(struct usb_endpoint *uep, + uint8_t *data, uint32_t data_len) { uint32_t out; uint32_t reply; @@ -291,7 +303,7 @@ static void transfer_and_reboot(struct libusb_device_handle *devh, memset(&updu, 0, sizeof(updu)); updu.block_size = htobe32(sizeof(updu)); - xfer(devh, ep_num, &updu, sizeof(updu), &reply, sizeof(reply)); + xfer(uep, &updu, sizeof(updu), &reply, sizeof(reply)); /* check the offset here. */ next_offset = be32toh(reply) - FLASH_BASE; printf("Updating at offset 0x%08x\n", next_offset); @@ -332,39 +344,27 @@ static void transfer_and_reboot(struct libusb_device_handle *devh, sizeof(updu.cmd.block_digest)); /* Now send the header. */ - xfer(devh, ep_num, &updu, sizeof(updu), NULL, 0); + xfer(uep, &updu, sizeof(updu), NULL, 0); /* Now send the block, chunk by chunk. */ transfer_data_ptr = data_ptr; for (transfer_size = 0; transfer_size < payload_size;) { int chunk_size; - chunk_size = MIN(chunk_len, + chunk_size = MIN(uep->chunk_len, payload_size - transfer_size); - xfer(devh, ep_num, transfer_data_ptr, chunk_size, + xfer(uep, transfer_data_ptr, chunk_size, NULL, 0); transfer_data_ptr += chunk_size; transfer_size += chunk_size; } /* Now get the reply. */ - xfer(devh, ep_num, NULL, 0, &reply, sizeof(reply)); + xfer(uep, NULL, 0, &reply, sizeof(reply)); if (reply) { fprintf(stderr, "error: status %#08x remaining %#08x\n", be32toh(reply), data_len); exit(1); } - /* - if (!IS_EXPECT_RW(in.status)) { - fprintf(stderr, "error: status 0x%08x offset 0x%08x\n", - in.status, in.offset); - exit(1); - } - */ - /* Block transferred and programmed successfully. */ - /* Show status occasionally - if (!(in.offset & 0x00003FFF)) - printf("offset 0x%x\n", in.offset); - */ data_len -= payload_size; data_ptr += payload_size; @@ -375,22 +375,20 @@ static void transfer_and_reboot(struct libusb_device_handle *devh, /* Send stop request, ignorign reply. */ out = htobe32(UPGRADE_DONE); - xfer(devh, ep_num, &out, sizeof(out), &reply, sizeof(reply)); + xfer(uep, &out, sizeof(out), &reply, sizeof(reply)); printf("reboot\n"); /* Send a second stop request, which should reboot without replying */ - xfer(devh, ep_num, &out, sizeof(out), 0, 0); + xfer(uep, &out, sizeof(out), 0, 0); } int main(int argc, char *argv[]) { - struct libusb_device_handle *devh; + struct usb_endpoint uep; int errorcnt; uint8_t *data = 0; uint32_t data_len = 0; - uint8_t ep_num = 0; - int chunk_len = 0; uint16_t vid = VID, pid = PID; int i; @@ -449,13 +447,13 @@ int main(int argc, char *argv[]) exit(1); } - devh = usb_findit(vid, pid, &ep_num, &chunk_len); + usb_findit(vid, pid, &uep); - transfer_and_reboot(devh, data, data_len, ep_num, chunk_len); + transfer_and_reboot(&uep, data, data_len); printf("bye\n"); free(data); - libusb_close(devh); + libusb_close(uep.devh); libusb_exit(NULL); return 0; |