@@ -410,3 +410,47 @@ returncode_t libtocksync_sensor_read(int* val) {
410
410
return err;
411
411
}
412
412
```
413
+
414
+ ### More Complicated Example:
415
+
416
+ Drivers that use allow buffers must un-allow the buffers after the operation
417
+ finishes.
418
+
419
+ ```c
420
+ #include "digest.h"
421
+ #include "syscalls/digest_syscalls.h"
422
+
423
+ returncode_t libtocksync_digest_compute(uint8_t* input_buffer,
424
+ uint32_t input_buffer_len,
425
+ uint8_t* output_buffer,
426
+ uint32_t output_buffer_len) {
427
+ returncode_t ret;
428
+
429
+ // First allow for input. If it fails, return.
430
+ ret = libtock_digest_set_readonly_allow(input_buffer, input_buffer_len);
431
+ if (ret != RETURNCODE_SUCCESS) return ret;
432
+
433
+ // Second allow for output. If it fails, unallow first buffer then return.
434
+ ret = libtock_digest_set_readwrite_allow(output_buffer, output_buffer_len);
435
+ if (ret != RETURNCODE_SUCCESS) goto exit1;
436
+
437
+ // Attempt the command. If it fails, unallow both buffers.
438
+ ret = libtock_digest_command_compute_digest();
439
+ if (err != RETURNCODE_SUCCESS) goto exit2;
440
+
441
+ // Wait for the digest to compute.
442
+ ret = libtock_digest_yield_wait_for(val);
443
+
444
+ exit2:
445
+ // Do the input unallow. We have to ignore the return value to 1) return the
446
+ // correct error of the actual failing operation if something happened, and
447
+ // 2) do the second unallow unconditionally.
448
+ libtock_digest_set_readonly_allow(NULL, 0);
449
+
450
+ exit1:
451
+ // Do the output unallow.
452
+ libtock_digest_set_readonly_allow(NULL, 0);
453
+
454
+ return ret;
455
+ }
456
+ ```
0 commit comments