kernel: expose device_get_binding() to user mode

User mode may need to use this API to get a handle on
devices by name, expose as a system call. We impose
a maximum name length as the system call handler needs
to make a copy of the string passed in from user mode.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2018-11-12 10:25:12 -08:00 committed by Anas Nashif
commit 9d14874db1
2 changed files with 22 additions and 3 deletions

View file

@ -28,6 +28,7 @@
extern "C" {
#endif
#define Z_DEVICE_MAX_NAME_LEN 48
/**
* @def DEVICE_INIT
@ -37,7 +38,8 @@ extern "C" {
* @details This macro defines a device object that is automatically
* configured by the kernel during system initialization.
*
* @param dev_name Device name.
* @param dev_name Device name. This must be less than Z_DEVICE_MAX_NAME_LEN
* characters in order to be looked up from user mode with device_get_binding().
*
* @param drv_name The name this instance of the driver exposes to
* the system.
@ -248,7 +250,7 @@ void _sys_device_do_config_level(s32_t level);
*
* @return pointer to device structure; NULL if not found or cannot be used.
*/
struct device *device_get_binding(const char *name);
__syscall struct device *device_get_binding(const char *name);
/**
* @brief Device Power Management APIs
@ -436,6 +438,8 @@ int device_busy_check(struct device *chk_dev);
* @}
*/
#include <syscalls/device.h>
#ifdef __cplusplus
}
#endif

View file

@ -9,6 +9,7 @@
#include <device.h>
#include <misc/util.h>
#include <atomic.h>
#include <syscall_handler.h>
extern struct device __device_init_start[];
extern struct device __device_PRE_KERNEL_1_start[];
@ -56,7 +57,7 @@ void _sys_device_do_config_level(s32_t level)
}
}
struct device *device_get_binding(const char *name)
struct device *_impl_device_get_binding(const char *name)
{
struct device *info;
@ -85,6 +86,20 @@ struct device *device_get_binding(const char *name)
return NULL;
}
#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER(device_get_binding, name)
{
char name_copy[Z_DEVICE_MAX_NAME_LEN];
if (z_user_string_copy(name_copy, (char *)name, sizeof(name_copy))
!= 0) {
return 0;
}
return (u32_t)_impl_device_get_binding(name_copy);
}
#endif /* CONFIG_USERSPACE */
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
int device_pm_control_nop(struct device *unused_device,
u32_t unused_ctrl_command, void *unused_context)