From cc22df198d0ccb64dfdfe0c2f247f7d86b7fd750 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 11 May 2021 13:25:26 +0100 Subject: jztool: Support new M3K bootloader Change-Id: Ia2d96893a9a5c77deb71c1fe32ae5a0585093f5b --- rbutil/jztool/src/usb.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) (limited to 'rbutil/jztool/src/usb.c') diff --git a/rbutil/jztool/src/usb.c b/rbutil/jztool/src/usb.c index 7e4a5f3388..c101f2be77 100644 --- a/rbutil/jztool/src/usb.c +++ b/rbutil/jztool/src/usb.c @@ -30,6 +30,16 @@ #define VR_PROGRAM_START1 4 #define VR_PROGRAM_START2 5 +/** \brief Open a USB device + * \param jz Context + * \param devptr Returns pointer to the USB device upon success + * \param vend_id USB vendor ID + * \param prod_id USB product ID + * \return either JZ_SUCCESS if device was opened, or an error below + * \retval JZ_ERR_OUT_OF_MEMORY malloc failed + * \retval JZ_ERR_USB libusb error (details are logged) + * \retval JZ_ERR_NO_DEVICE can't unambiguously find the device + */ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t prod_id) { int rc; @@ -80,7 +90,7 @@ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t p } if(dev_index < 0) { - jz_log(jz, JZ_LOG_ERROR, "No device with ID %04x:%05x found", + jz_log(jz, JZ_LOG_ERROR, "No device with ID %04x:%04x found", (unsigned int)vend_id, (unsigned int)prod_id); rc = JZ_ERR_NO_DEVICE; goto error; @@ -100,6 +110,8 @@ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t p goto error; } + jz_log(jz, JZ_LOG_DEBUG, "Opened device (%p, ID %04x:%04x)", + dev, (unsigned int)vend_id, (unsigned int)prod_id); dev->jz = jz; dev->handle = usb_handle; *devptr = dev; @@ -119,14 +131,20 @@ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t p goto exit; } +/** \brief Close a USB device + * \param dev Device to close; memory will be freed automatically + */ void jz_usb_close(jz_usbdev* dev) { + jz_log(dev->jz, JZ_LOG_DEBUG, "Closing device (%p)", dev); libusb_release_interface(dev->handle, 0); libusb_close(dev->handle); jz_context_unref_libusb(dev->jz); free(dev); } +// Does an Ingenic-specific vendor request +// Written with X1000 in mind but other Ingenic CPUs have the same commands static int jz_usb_vendor_req(jz_usbdev* dev, int req, uint32_t arg) { int rc = libusb_control_transfer(dev->handle, @@ -137,12 +155,24 @@ static int jz_usb_vendor_req(jz_usbdev* dev, int req, uint32_t arg) jz_log(dev->jz, JZ_LOG_ERROR, "libusb_control_transfer: %s", libusb_strerror(rc)); rc = JZ_ERR_USB; } else { + static const char* req_names[] = { + "GET_CPU_INFO", + "SET_DATA_ADDRESS", + "SET_DATA_LENGTH", + "FLUSH_CACHES", + "PROGRAM_START1", + "PROGRAM_START2", + }; + + jz_log(dev->jz, JZ_LOG_DEBUG, "Issued %s %08lu", + req_names[req], (unsigned long)arg); rc = JZ_SUCCESS; } return rc; } +// Bulk transfer wrapper static int jz_usb_transfer(jz_usbdev* dev, bool write, size_t len, void* buf) { int xfered = 0; @@ -156,12 +186,16 @@ static int jz_usb_transfer(jz_usbdev* dev, bool write, size_t len, void* buf) jz_log(dev->jz, JZ_LOG_ERROR, "libusb_bulk_transfer: incorrect amount of data transfered"); rc = JZ_ERR_USB; } else { + jz_log(dev->jz, JZ_LOG_DEBUG, "Transferred %zu bytes %s", + len, write ? "to device" : "from device"); rc = JZ_SUCCESS; } return rc; } +// Memory send/receive primitive, performs the necessary vendor requests +// and then tranfers data using the bulk endpoint static int jz_usb_sendrecv(jz_usbdev* dev, bool write, uint32_t addr, size_t len, void* data) { @@ -177,26 +211,54 @@ static int jz_usb_sendrecv(jz_usbdev* dev, bool write, uint32_t addr, return jz_usb_transfer(dev, write, len, data); } +/** \brief Write data to device memory + * \param dev USB device + * \param addr Address where data should be written + * \param len Length of the data, in bytes, should be positive + * \param data Data buffer + * \return either JZ_SUCCESS on success or a failure code + */ int jz_usb_send(jz_usbdev* dev, uint32_t addr, size_t len, const void* data) { return jz_usb_sendrecv(dev, true, addr, len, (void*)data); } +/** \brief Read data to device memory + * \param dev USB device + * \param addr Address to read from + * \param len Length of the data, in bytes, should be positive + * \param data Data buffer + * \return either JZ_SUCCESS on success or a failure code + */ int jz_usb_recv(jz_usbdev* dev, uint32_t addr, size_t len, void* data) { return jz_usb_sendrecv(dev, false, addr, len, data); } +/** \brief Execute stage1 program jumping to the specified address + * \param dev USB device + * \param addr Address to begin execution at + * \return either JZ_SUCCESS on success or a failure code + */ int jz_usb_start1(jz_usbdev* dev, uint32_t addr) { return jz_usb_vendor_req(dev, VR_PROGRAM_START1, addr); } +/** \brief Execute stage2 program jumping to the specified address + * \param dev USB device + * \param addr Address to begin execution at + * \return either JZ_SUCCESS on success or a failure code + */ int jz_usb_start2(jz_usbdev* dev, uint32_t addr) { return jz_usb_vendor_req(dev, VR_PROGRAM_START2, addr); } +/** \brief Ask device to flush CPU caches + * \param dev USB device + * \return either JZ_SUCCESS on success or a failure code + */ int jz_usb_flush_caches(jz_usbdev* dev) { return jz_usb_vendor_req(dev, VR_FLUSH_CACHES, 0); -- cgit v1.2.3