In cases where there are no uses for read values only the write function exists. In value this can be either a NULL to indicate no error occurred during the access, or a pointer to a message describing the error. The messages are statically declared and do not change. Having dynamic values as part of the message violates reentrantancy rules. However a function can contain many different messages and return a pointer to any one of them.
Functions never send messages to the log or other output devices.
It is up to the calling function to determine what should be done with an error message. The functions generally assume their arguments are correct and little argument checking is done. If there is a situation where argument checking is desired a bad argument results in no operation being performed and the return of an error message. As part of the implementation the functions use storage which is visible only within the source module. When commanding hardware a function may provide arguments which are known from this storage.