static void cb_download(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; char response[RESPONSE_LEN]; strsep(&cmd, ":"); /*HACK: Zero terminate the command string*/ strlcpy(cmd, cmd, 9); download_size = simple_strtoul(cmd, NULL, 16); download_bytes = 0; printf("Starting download of %d bytes\n", download_size); if (0 == download_size) { sprintf(response, "FAILdata invalid size"); } else if (download_size > fb_cfg.transfer_buffer_size) { download_size = 0; sprintf(response, "FAILdata too large"); } else { sprintf(response, "DATA%08x", download_size); req->complete = rx_handler_dl_image; req->length = rx_bytes_expected(); if (req->length < ep->maxpacket) req->length = ep->maxpacket; } fastboot_tx_write_str(response); }
static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) { char response[RESPONSE_LEN]; unsigned int transfer_size = download_size - download_bytes; const unsigned char *buffer = req->buf; unsigned int buffer_size = req->actual; if (req->status != 0) { printf("Bad status: %d\n", req->status); return; } if (buffer_size < transfer_size) transfer_size = buffer_size; memcpy(fb_cfg.transfer_buffer + download_bytes, buffer, transfer_size); download_bytes += transfer_size; /* Check if transfer is done */ if (download_bytes >= download_size) { /* * Reset global transfer variable, keep download_bytes because * it will be used in the next possible flashing command */ download_size = 0; req->complete = rx_handler_command; req->length = EP_BUFFER_SIZE; sprintf(response, "OKAY"); fastboot_tx_write_str(response); printf("\ndownloading of %d bytes finished\n", download_bytes); } else { req->length = rx_bytes_expected(); if (req->length < ep->maxpacket) req->length = ep->maxpacket; } /*if (download_bytes && !(download_bytes % BYTES_PER_DOT)) { printf("."); if (!(download_bytes % (74 * BYTES_PER_DOT))) printf("\n"); }*/ req->actual = 0; usb_ep_queue(ep, req, 0); }
static void cb_write_lba(struct usb_ep *ep, struct usb_request *req) { ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, sizeof(struct fsg_bulk_cb_wrap)); struct f_rockusb *f_rkusb = get_rkusb(); int sector_count; memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); sector_count = (int)get_unaligned_be16(&cbw->CDB[7]); f_rkusb->lba = get_unaligned_be32(&cbw->CDB[2]); f_rkusb->dl_size = sector_count * 512; f_rkusb->dl_bytes = 0; f_rkusb->tag = cbw->tag; debug("require write %x bytes, %x sectors to lba %x\n", f_rkusb->dl_size, sector_count, f_rkusb->lba); if (f_rkusb->dl_size == 0) { rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_FAIL, USB_BULK_CS_WRAP_LEN); } else { req->complete = rx_handler_dl_image; req->length = rx_bytes_expected(ep); } }
/* usb_request complete call back to handle down load image */ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) { struct f_rockusb *f_rkusb = get_rkusb(); unsigned int transfer_size = 0; const unsigned char *buffer = req->buf; unsigned int buffer_size = req->actual; transfer_size = f_rkusb->dl_size - f_rkusb->dl_bytes; if (!f_rkusb->desc) { char *type = f_rkusb->dev_type; int index = f_rkusb->dev_index; f_rkusb->desc = blk_get_dev(type, index); if (!f_rkusb->desc || f_rkusb->desc->type == DEV_TYPE_UNKNOWN) { puts("invalid mmc device\n"); rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN); return; } } if (req->status != 0) { printf("Bad status: %d\n", req->status); rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN); return; } if (buffer_size < transfer_size) transfer_size = buffer_size; memcpy((void *)f_rkusb->buf, buffer, transfer_size); f_rkusb->dl_bytes += transfer_size; int blks = 0, blkcnt = transfer_size / 512; debug("dl %x bytes, %x blks, write lba %x, dl_size:%x, dl_bytes:%x, ", transfer_size, blkcnt, f_rkusb->lba, f_rkusb->dl_size, f_rkusb->dl_bytes); blks = blk_dwrite(f_rkusb->desc, f_rkusb->lba, blkcnt, f_rkusb->buf); if (blks != blkcnt) { printf("failed writing to device %s: %d\n", f_rkusb->dev_type, f_rkusb->dev_index); rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN); return; } f_rkusb->lba += blkcnt; /* Check if transfer is done */ if (f_rkusb->dl_bytes >= f_rkusb->dl_size) { req->complete = rx_handler_command; req->length = EP_BUFFER_SIZE; f_rkusb->buf = f_rkusb->buf_head; printf("transfer 0x%x bytes done\n", f_rkusb->dl_size); f_rkusb->dl_size = 0; rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD, USB_BULK_CS_WRAP_LEN); } else { req->length = rx_bytes_expected(ep); if (f_rkusb->buf == f_rkusb->buf_head) f_rkusb->buf = f_rkusb->buf_head + EP_BUFFER_SIZE; else f_rkusb->buf = f_rkusb->buf_head; debug("remain %x bytes, %x sectors\n", req->length, req->length / 512); } req->actual = 0; usb_ep_queue(ep, req, 0); }