|
8 | 8 | package net.codecrete.usb.common; |
9 | 9 |
|
10 | 10 | import net.codecrete.usb.UsbDirection; |
| 11 | +import net.codecrete.usb.UsbException; |
11 | 12 | import org.jetbrains.annotations.NotNull; |
12 | 13 |
|
13 | 14 | import java.io.IOException; |
14 | 15 | import java.io.OutputStream; |
15 | 16 | import java.lang.foreign.Arena; |
16 | 17 | import java.lang.foreign.MemorySegment; |
17 | 18 | import java.util.Arrays; |
| 19 | +import java.util.Objects; |
18 | 20 | import java.util.concurrent.ArrayBlockingQueue; |
19 | 21 | import java.util.concurrent.TimeUnit; |
20 | 22 |
|
| 23 | +import static net.codecrete.usb.common.EndpointStreams.toIOException; |
| 24 | + |
21 | 25 | import static java.lang.System.Logger.Level.WARNING; |
22 | 26 | import static java.lang.foreign.ValueLayout.JAVA_BYTE; |
23 | 27 |
|
@@ -239,41 +243,57 @@ private Transfer pollAvailableTransfer(long deadline) { |
239 | 243 |
|
240 | 244 | @Override |
241 | 245 | public void write(int b) throws IOException { |
242 | | - checkIsOpen(); |
| 246 | + ensureOpen(); |
243 | 247 |
|
244 | | - currentTransfer.data().set(JAVA_BYTE, writeOffset, (byte) b); |
245 | | - writeOffset += 1; |
246 | | - if (writeOffset == transferSize) |
247 | | - submitTransfer(writeOffset); |
| 248 | + try { |
| 249 | + currentTransfer.data().set(JAVA_BYTE, writeOffset, (byte) b); |
| 250 | + writeOffset += 1; |
| 251 | + if (writeOffset == transferSize) |
| 252 | + submitTransfer(writeOffset); |
| 253 | + |
| 254 | + } catch (UsbException e) { |
| 255 | + throw toIOException(e); |
| 256 | + } |
248 | 257 | } |
249 | 258 |
|
250 | 259 | @Override |
251 | 260 | public void write(byte @NotNull [] b, int off, int len) throws IOException { |
252 | | - checkIsOpen(); |
| 261 | + Objects.checkFromIndexSize(off, len, b.length); |
| 262 | + ensureOpen(); |
253 | 263 |
|
254 | | - while (len > 0) { |
255 | | - var chunkSize = Math.min(len, transferSize - writeOffset); |
256 | | - MemorySegment.copy(b, off, currentTransfer.data(), JAVA_BYTE, writeOffset, chunkSize); |
257 | | - writeOffset += chunkSize; |
258 | | - off += chunkSize; |
259 | | - len -= chunkSize; |
| 264 | + try { |
| 265 | + while (len > 0) { |
| 266 | + var chunkSize = Math.min(len, transferSize - writeOffset); |
| 267 | + MemorySegment.copy(b, off, currentTransfer.data(), JAVA_BYTE, writeOffset, chunkSize); |
| 268 | + writeOffset += chunkSize; |
| 269 | + off += chunkSize; |
| 270 | + len -= chunkSize; |
| 271 | + |
| 272 | + if (writeOffset == transferSize) |
| 273 | + submitTransfer(writeOffset); |
| 274 | + } |
260 | 275 |
|
261 | | - if (writeOffset == transferSize) |
262 | | - submitTransfer(writeOffset); |
| 276 | + } catch (UsbException e) { |
| 277 | + throw toIOException(e); |
263 | 278 | } |
264 | 279 | } |
265 | 280 |
|
266 | 281 | @Override |
267 | 282 | public void flush() throws IOException { |
268 | | - checkIsOpen(); |
| 283 | + ensureOpen(); |
269 | 284 |
|
270 | | - if (writeOffset > 0) |
271 | | - submitTransfer(writeOffset); |
| 285 | + try { |
| 286 | + if (writeOffset > 0) |
| 287 | + submitTransfer(writeOffset); |
| 288 | + |
| 289 | + if (needsZlp) |
| 290 | + submitTransfer(0); |
272 | 291 |
|
273 | | - if (needsZlp) |
274 | | - submitTransfer(0); |
| 292 | + waitForOutstandingTransfers(); |
275 | 293 |
|
276 | | - waitForOutstandingTransfers(); |
| 294 | + } catch (UsbException e) { |
| 295 | + throw toIOException(e); |
| 296 | + } |
277 | 297 | } |
278 | 298 |
|
279 | 299 | /** |
@@ -387,8 +407,8 @@ private synchronized void onCompletion(Transfer transfer) { |
387 | 407 | protected void configureEndpoint() { |
388 | 408 | } |
389 | 409 |
|
390 | | - private void checkIsOpen() throws IOException { |
| 410 | + private void ensureOpen() throws IOException { |
391 | 411 | if (isClosed()) |
392 | | - throw new IOException("endpoint output stream has been closed"); |
| 412 | + throw new IOException("output stream has been closed"); |
393 | 413 | } |
394 | 414 | } |
0 commit comments