summaryrefslogtreecommitdiff
path: root/rbutil/jztool/src/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/jztool/src/usb.c')
-rw-r--r--rbutil/jztool/src/usb.c64
1 files changed, 63 insertions, 1 deletions
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 @@
30#define VR_PROGRAM_START1 4 30#define VR_PROGRAM_START1 4
31#define VR_PROGRAM_START2 5 31#define VR_PROGRAM_START2 5
32 32
33/** \brief Open a USB device
34 * \param jz Context
35 * \param devptr Returns pointer to the USB device upon success
36 * \param vend_id USB vendor ID
37 * \param prod_id USB product ID
38 * \return either JZ_SUCCESS if device was opened, or an error below
39 * \retval JZ_ERR_OUT_OF_MEMORY malloc failed
40 * \retval JZ_ERR_USB libusb error (details are logged)
41 * \retval JZ_ERR_NO_DEVICE can't unambiguously find the device
42 */
33int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t prod_id) 43int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t prod_id)
34{ 44{
35 int rc; 45 int rc;
@@ -80,7 +90,7 @@ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t p
80 } 90 }
81 91
82 if(dev_index < 0) { 92 if(dev_index < 0) {
83 jz_log(jz, JZ_LOG_ERROR, "No device with ID %04x:%05x found", 93 jz_log(jz, JZ_LOG_ERROR, "No device with ID %04x:%04x found",
84 (unsigned int)vend_id, (unsigned int)prod_id); 94 (unsigned int)vend_id, (unsigned int)prod_id);
85 rc = JZ_ERR_NO_DEVICE; 95 rc = JZ_ERR_NO_DEVICE;
86 goto error; 96 goto error;
@@ -100,6 +110,8 @@ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t p
100 goto error; 110 goto error;
101 } 111 }
102 112
113 jz_log(jz, JZ_LOG_DEBUG, "Opened device (%p, ID %04x:%04x)",
114 dev, (unsigned int)vend_id, (unsigned int)prod_id);
103 dev->jz = jz; 115 dev->jz = jz;
104 dev->handle = usb_handle; 116 dev->handle = usb_handle;
105 *devptr = dev; 117 *devptr = dev;
@@ -119,14 +131,20 @@ int jz_usb_open(jz_context* jz, jz_usbdev** devptr, uint16_t vend_id, uint16_t p
119 goto exit; 131 goto exit;
120} 132}
121 133
134/** \brief Close a USB device
135 * \param dev Device to close; memory will be freed automatically
136 */
122void jz_usb_close(jz_usbdev* dev) 137void jz_usb_close(jz_usbdev* dev)
123{ 138{
139 jz_log(dev->jz, JZ_LOG_DEBUG, "Closing device (%p)", dev);
124 libusb_release_interface(dev->handle, 0); 140 libusb_release_interface(dev->handle, 0);
125 libusb_close(dev->handle); 141 libusb_close(dev->handle);
126 jz_context_unref_libusb(dev->jz); 142 jz_context_unref_libusb(dev->jz);
127 free(dev); 143 free(dev);
128} 144}
129 145
146// Does an Ingenic-specific vendor request
147// Written with X1000 in mind but other Ingenic CPUs have the same commands
130static int jz_usb_vendor_req(jz_usbdev* dev, int req, uint32_t arg) 148static int jz_usb_vendor_req(jz_usbdev* dev, int req, uint32_t arg)
131{ 149{
132 int rc = libusb_control_transfer(dev->handle, 150 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)
137 jz_log(dev->jz, JZ_LOG_ERROR, "libusb_control_transfer: %s", libusb_strerror(rc)); 155 jz_log(dev->jz, JZ_LOG_ERROR, "libusb_control_transfer: %s", libusb_strerror(rc));
138 rc = JZ_ERR_USB; 156 rc = JZ_ERR_USB;
139 } else { 157 } else {
158 static const char* req_names[] = {
159 "GET_CPU_INFO",
160 "SET_DATA_ADDRESS",
161 "SET_DATA_LENGTH",
162 "FLUSH_CACHES",
163 "PROGRAM_START1",
164 "PROGRAM_START2",
165 };
166
167 jz_log(dev->jz, JZ_LOG_DEBUG, "Issued %s %08lu",
168 req_names[req], (unsigned long)arg);
140 rc = JZ_SUCCESS; 169 rc = JZ_SUCCESS;
141 } 170 }
142 171
143 return rc; 172 return rc;
144} 173}
145 174
175// Bulk transfer wrapper
146static int jz_usb_transfer(jz_usbdev* dev, bool write, size_t len, void* buf) 176static int jz_usb_transfer(jz_usbdev* dev, bool write, size_t len, void* buf)
147{ 177{
148 int xfered = 0; 178 int xfered = 0;
@@ -156,12 +186,16 @@ static int jz_usb_transfer(jz_usbdev* dev, bool write, size_t len, void* buf)
156 jz_log(dev->jz, JZ_LOG_ERROR, "libusb_bulk_transfer: incorrect amount of data transfered"); 186 jz_log(dev->jz, JZ_LOG_ERROR, "libusb_bulk_transfer: incorrect amount of data transfered");
157 rc = JZ_ERR_USB; 187 rc = JZ_ERR_USB;
158 } else { 188 } else {
189 jz_log(dev->jz, JZ_LOG_DEBUG, "Transferred %zu bytes %s",
190 len, write ? "to device" : "from device");
159 rc = JZ_SUCCESS; 191 rc = JZ_SUCCESS;
160 } 192 }
161 193
162 return rc; 194 return rc;
163} 195}
164 196
197// Memory send/receive primitive, performs the necessary vendor requests
198// and then tranfers data using the bulk endpoint
165static int jz_usb_sendrecv(jz_usbdev* dev, bool write, uint32_t addr, 199static int jz_usb_sendrecv(jz_usbdev* dev, bool write, uint32_t addr,
166 size_t len, void* data) 200 size_t len, void* data)
167{ 201{
@@ -177,26 +211,54 @@ static int jz_usb_sendrecv(jz_usbdev* dev, bool write, uint32_t addr,
177 return jz_usb_transfer(dev, write, len, data); 211 return jz_usb_transfer(dev, write, len, data);
178} 212}
179 213
214/** \brief Write data to device memory
215 * \param dev USB device
216 * \param addr Address where data should be written
217 * \param len Length of the data, in bytes, should be positive
218 * \param data Data buffer
219 * \return either JZ_SUCCESS on success or a failure code
220 */
180int jz_usb_send(jz_usbdev* dev, uint32_t addr, size_t len, const void* data) 221int jz_usb_send(jz_usbdev* dev, uint32_t addr, size_t len, const void* data)
181{ 222{
182 return jz_usb_sendrecv(dev, true, addr, len, (void*)data); 223 return jz_usb_sendrecv(dev, true, addr, len, (void*)data);
183} 224}
184 225
226/** \brief Read data to device memory
227 * \param dev USB device
228 * \param addr Address to read from
229 * \param len Length of the data, in bytes, should be positive
230 * \param data Data buffer
231 * \return either JZ_SUCCESS on success or a failure code
232 */
185int jz_usb_recv(jz_usbdev* dev, uint32_t addr, size_t len, void* data) 233int jz_usb_recv(jz_usbdev* dev, uint32_t addr, size_t len, void* data)
186{ 234{
187 return jz_usb_sendrecv(dev, false, addr, len, data); 235 return jz_usb_sendrecv(dev, false, addr, len, data);
188} 236}
189 237
238/** \brief Execute stage1 program jumping to the specified address
239 * \param dev USB device
240 * \param addr Address to begin execution at
241 * \return either JZ_SUCCESS on success or a failure code
242 */
190int jz_usb_start1(jz_usbdev* dev, uint32_t addr) 243int jz_usb_start1(jz_usbdev* dev, uint32_t addr)
191{ 244{
192 return jz_usb_vendor_req(dev, VR_PROGRAM_START1, addr); 245 return jz_usb_vendor_req(dev, VR_PROGRAM_START1, addr);
193} 246}
194 247
248/** \brief Execute stage2 program jumping to the specified address
249 * \param dev USB device
250 * \param addr Address to begin execution at
251 * \return either JZ_SUCCESS on success or a failure code
252 */
195int jz_usb_start2(jz_usbdev* dev, uint32_t addr) 253int jz_usb_start2(jz_usbdev* dev, uint32_t addr)
196{ 254{
197 return jz_usb_vendor_req(dev, VR_PROGRAM_START2, addr); 255 return jz_usb_vendor_req(dev, VR_PROGRAM_START2, addr);
198} 256}
199 257
258/** \brief Ask device to flush CPU caches
259 * \param dev USB device
260 * \return either JZ_SUCCESS on success or a failure code
261 */
200int jz_usb_flush_caches(jz_usbdev* dev) 262int jz_usb_flush_caches(jz_usbdev* dev)
201{ 263{
202 return jz_usb_vendor_req(dev, VR_FLUSH_CACHES, 0); 264 return jz_usb_vendor_req(dev, VR_FLUSH_CACHES, 0);