@@ -410,3 +410,47 @@ returncode_t libtocksync_sensor_read(int* val) {
410410 return err;
411411}
412412```
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