diff options
Diffstat (limited to 'utils/hwstub/lib/hwstub.c')
-rw-r--r-- | utils/hwstub/lib/hwstub.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c index 6ae0400a66..d3908585da 100644 --- a/utils/hwstub/lib/hwstub.c +++ b/utils/hwstub/lib/hwstub.c | |||
@@ -140,7 +140,8 @@ int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz) | |||
140 | HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000); | 140 | HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000); |
141 | } | 141 | } |
142 | 142 | ||
143 | static int _hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | 143 | static int _hwstub_read(struct hwstub_device_t *dev, uint8_t breq, uint32_t addr, |
144 | void *buf, size_t sz) | ||
144 | { | 145 | { |
145 | struct hwstub_read_req_t read; | 146 | struct hwstub_read_req_t read; |
146 | read.dAddress = addr; | 147 | read.dAddress = addr; |
@@ -151,10 +152,11 @@ static int _hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, s | |||
151 | return -1; | 152 | return -1; |
152 | return libusb_control_transfer(dev->handle, | 153 | return libusb_control_transfer(dev->handle, |
153 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, | 154 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, |
154 | HWSTUB_READ2, dev->id++, dev->intf, buf, sz, 1000); | 155 | breq, dev->id++, dev->intf, buf, sz, 1000); |
155 | } | 156 | } |
156 | 157 | ||
157 | static int _hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | 158 | static int _hwstub_write(struct hwstub_device_t *dev, uint8_t breq, uint32_t addr, |
159 | const void *buf, size_t sz) | ||
158 | { | 160 | { |
159 | size_t hdr_sz = sizeof(struct hwstub_write_req_t); | 161 | size_t hdr_sz = sizeof(struct hwstub_write_req_t); |
160 | struct hwstub_write_req_t *req = malloc(sz + hdr_sz); | 162 | struct hwstub_write_req_t *req = malloc(sz + hdr_sz); |
@@ -162,18 +164,34 @@ static int _hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, | |||
162 | memcpy(req + 1, buf, sz); | 164 | memcpy(req + 1, buf, sz); |
163 | int size = libusb_control_transfer(dev->handle, | 165 | int size = libusb_control_transfer(dev->handle, |
164 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, | 166 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, |
165 | HWSTUB_WRITE, dev->id++, dev->intf, (void *)req, sz + hdr_sz, 1000); | 167 | breq, dev->id++, dev->intf, (void *)req, sz + hdr_sz, 1000); |
166 | free(req); | 168 | free(req); |
167 | return size - hdr_sz; | 169 | return size - hdr_sz; |
168 | } | 170 | } |
169 | 171 | ||
172 | int hwstub_read_atomic(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | ||
173 | { | ||
174 | /* reject any read greater than the buffer, it makes no sense anyway */ | ||
175 | if(sz > dev->buf_sz) | ||
176 | return -1; | ||
177 | return _hwstub_read(dev, HWSTUB_READ2_ATOMIC, addr, buf, sz); | ||
178 | } | ||
179 | |||
180 | int hwstub_write_atomic(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz) | ||
181 | { | ||
182 | /* reject any write greater than the buffer, it makes no sense anyway */ | ||
183 | if(sz + sizeof(struct hwstub_write_req_t) > dev->buf_sz) | ||
184 | return -1; | ||
185 | return _hwstub_write(dev, HWSTUB_WRITE_ATOMIC, addr, buf, sz); | ||
186 | } | ||
187 | |||
170 | /* Intermediate function which make sure we don't overflow the device buffer */ | 188 | /* Intermediate function which make sure we don't overflow the device buffer */ |
171 | int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | 189 | int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) |
172 | { | 190 | { |
173 | int cnt = 0; | 191 | int cnt = 0; |
174 | while(sz > 0) | 192 | while(sz > 0) |
175 | { | 193 | { |
176 | int xfer = _hwstub_read(dev, addr, buf, MIN(sz, dev->buf_sz)); | 194 | int xfer = _hwstub_read(dev, HWSTUB_READ2, addr, buf, MIN(sz, dev->buf_sz)); |
177 | if(xfer < 0) | 195 | if(xfer < 0) |
178 | return xfer; | 196 | return xfer; |
179 | sz -= xfer; | 197 | sz -= xfer; |
@@ -185,13 +203,13 @@ int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz | |||
185 | } | 203 | } |
186 | 204 | ||
187 | /* Intermediate function which make sure we don't overflow the device buffer */ | 205 | /* Intermediate function which make sure we don't overflow the device buffer */ |
188 | int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | 206 | int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz) |
189 | { | 207 | { |
190 | int cnt = 0; | 208 | int cnt = 0; |
191 | while(sz > 0) | 209 | while(sz > 0) |
192 | { | 210 | { |
193 | int xfer = _hwstub_write(dev, addr, buf, MIN(sz, dev->buf_sz - | 211 | int xfer = _hwstub_write(dev, HWSTUB_WRITE, addr, buf, |
194 | sizeof(struct hwstub_write_req_t))); | 212 | MIN(sz, dev->buf_sz - sizeof(struct hwstub_write_req_t))); |
195 | if(xfer < 0) | 213 | if(xfer < 0) |
196 | return xfer; | 214 | return xfer; |
197 | sz -= xfer; | 215 | sz -= xfer; |
@@ -207,6 +225,12 @@ int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *bu | |||
207 | return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz); | 225 | return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz); |
208 | } | 226 | } |
209 | 227 | ||
228 | int hwstub_rw_mem_atomic(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) | ||
229 | { | ||
230 | return read ? hwstub_read_atomic(dev, addr, buf, sz) : | ||
231 | hwstub_write_atomic(dev, addr, buf, sz); | ||
232 | } | ||
233 | |||
210 | int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags) | 234 | int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags) |
211 | { | 235 | { |
212 | struct hwstub_exec_req_t exec; | 236 | struct hwstub_exec_req_t exec; |