LCOV - code coverage report
Current view: top level - /home/runner/zephyrproject/zephyr/kernel - device.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 0.0 % 32 0
Test Date: 2026-03-12 12:01:18 Functions: 0.0 % 6 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 28 0

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * Copyright (c) 2015-2016 Intel Corporation.
       3                 :             :  *
       4                 :             :  * SPDX-License-Identifier: Apache-2.0
       5                 :             :  */
       6                 :             : 
       7                 :             : #include <errno.h>
       8                 :             : #include <stddef.h>
       9                 :             : #include <string.h>
      10                 :             : #include <zephyr/device.h>
      11                 :             : #include <zephyr/sys/atomic.h>
      12                 :             : #include <zephyr/sys/iterable_sections.h>
      13                 :             : #include <zephyr/sys/kobject.h>
      14                 :             : #include <zephyr/internal/syscall_handler.h>
      15                 :             : #include <zephyr/toolchain.h>
      16                 :             : #include <zephyr/pm/device_runtime.h>
      17                 :             : 
      18                 :           0 : int do_device_init(const struct device *dev)
      19                 :             : {
      20                 :           0 :         int rc = 0;
      21                 :             : 
      22         [ #  # ]:           0 :         if (dev->ops.init != NULL) {
      23                 :           0 :                 rc = dev->ops.init(dev);
      24                 :             :                 /* If initialization failed, record in dev->state->init_res
      25                 :             :                  * the POSITIVE value of the resulting errno
      26                 :             :                  */
      27         [ #  # ]:           0 :                 if (rc != 0) {
      28                 :             :                         /* device's init function should return:
      29                 :             :                          *   0 on success
      30                 :             :                          *   a negative value on failure (-errno)
      31                 :             :                          * errno value maps to an uint8_t range as of now.
      32                 :             :                          */
      33         [ #  # ]:           0 :                         __ASSERT(rc >= -UINT8_MAX && rc < 0, "device %s init: invalid error (%d)",
      34                 :             :                                  dev->name, rc);
      35                 :             : 
      36                 :           0 :                         if (rc < 0) {
      37                 :           0 :                                 rc = -rc;
      38                 :             :                         }
      39                 :             :                         /* handle error value overflow in production
      40                 :             :                          * this is likely a bug in the device's init function. Signals it
      41                 :             :                          */
      42                 :           0 :                         if (rc > UINT8_MAX) {
      43                 :             :                                 rc = UINT8_MAX;
      44                 :             :                         }
      45                 :           0 :                         dev->state->init_res = rc;
      46                 :             :                 }
      47                 :             :         }
      48                 :             : 
      49                 :             :         /* device initialization has been invoked */
      50                 :           0 :         dev->state->initialized = true;
      51                 :             : 
      52                 :           0 :         if (rc == 0) {
      53                 :             :                 /* Run automatic device runtime enablement */
      54                 :             :                 (void)pm_device_runtime_auto_enable(dev);
      55                 :             :         }
      56                 :             : 
      57                 :             :         /* here, the value of rc is either 0 or +errno
      58                 :             :          * flip the sign to return a negative value on failure as expected
      59                 :             :          */
      60                 :           0 :         return -rc;
      61                 :             : }
      62                 :             : 
      63                 :           0 : int z_impl_device_init(const struct device *dev)
      64                 :             : {
      65         [ #  # ]:           0 :         if (dev->state->initialized) {
      66                 :             :                 return -EALREADY;
      67                 :             :         }
      68                 :             : 
      69                 :           0 :         return do_device_init(dev);
      70                 :             : }
      71                 :             : 
      72                 :             : #ifdef CONFIG_USERSPACE
      73                 :             : static inline int z_vrfy_device_init(const struct device *dev)
      74                 :             : {
      75                 :             :         K_OOPS(K_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY));
      76                 :             : 
      77                 :             :         return z_impl_device_init(dev);
      78                 :             : }
      79                 :             : #include <zephyr/syscalls/device_init_mrsh.c>
      80                 :             : #endif
      81                 :             : 
      82                 :             : 
      83                 :           0 : const struct device *z_impl_device_get_binding(const char *name)
      84                 :             : {
      85                 :             :         /* A null string identifies no device.  So does an empty
      86                 :             :          * string.
      87                 :             :          */
      88   [ #  #  #  # ]:           0 :         if ((name == NULL) || (name[0] == '\0')) {
      89                 :             :                 return NULL;
      90                 :             :         }
      91                 :             : 
      92                 :             :         /* Return NULL if the device matching 'name' is not ready. */
      93   [ #  #  #  # ]:           0 :         STRUCT_SECTION_FOREACH(device, dev) {
      94   [ #  #  #  # ]:           0 :                 if ((dev->name == name) || (strcmp(name, dev->name) == 0)) {
      95         [ #  # ]:           0 :                         return z_impl_device_is_ready(dev) ? dev : NULL;
      96                 :             :                 }
      97                 :             :         }
      98                 :             : 
      99                 :             :         return NULL;
     100                 :             : }
     101                 :             : 
     102                 :             : #ifdef CONFIG_USERSPACE
     103                 :             : static inline const struct device *z_vrfy_device_get_binding(const char *name)
     104                 :             : {
     105                 :             :         char name_copy[Z_DEVICE_MAX_NAME_LEN];
     106                 :             : 
     107                 :             :         if (k_usermode_string_copy(name_copy, name, sizeof(name_copy))
     108                 :             :             != 0) {
     109                 :             :                 return NULL;
     110                 :             :         }
     111                 :             : 
     112                 :             :         return z_impl_device_get_binding(name_copy);
     113                 :             : }
     114                 :             : #include <zephyr/syscalls/device_get_binding_mrsh.c>
     115                 :             : 
     116                 :             : static inline bool z_vrfy_device_is_ready(const struct device *dev)
     117                 :             : {
     118                 :             :         K_OOPS(K_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY));
     119                 :             : 
     120                 :             :         return z_impl_device_is_ready(dev);
     121                 :             : }
     122                 :             : #include <zephyr/syscalls/device_is_ready_mrsh.c>
     123                 :             : #endif /* CONFIG_USERSPACE */
     124                 :             : 
     125                 :             : #ifdef CONFIG_DEVICE_DT_METADATA
     126                 :             : const struct device *z_impl_device_get_by_dt_nodelabel(const char *nodelabel)
     127                 :             : {
     128                 :             :         /* For consistency with device_get_binding(). */
     129                 :             :         if ((nodelabel == NULL) || (nodelabel[0] == '\0')) {
     130                 :             :                 return NULL;
     131                 :             :         }
     132                 :             : 
     133                 :             :         /* Unlike device_get_binding(), which has a history of being
     134                 :             :          * used in application code, we don't expect
     135                 :             :          * device_get_by_dt_nodelabel() to be used outside of
     136                 :             :          * scenarios where a human is in the loop. The shell is the
     137                 :             :          * main expected use case. Therefore, nodelabel is probably
     138                 :             :          * not the same pointer as any of the entry->nodelabel
     139                 :             :          * elements. We therefore skip the pointer comparison that
     140                 :             :          * device_get_binding() does.
     141                 :             :          */
     142                 :             :         STRUCT_SECTION_FOREACH(device, dev) {
     143                 :             :                 const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev);
     144                 :             : 
     145                 :             :                 if (!z_impl_device_is_ready(dev) || nl == NULL) {
     146                 :             :                         continue;
     147                 :             :                 }
     148                 :             : 
     149                 :             :                 for (size_t i = 0; i < nl->num_nodelabels; i++) {
     150                 :             :                         const char *dev_nodelabel = nl->nodelabels[i];
     151                 :             : 
     152                 :             :                         if (strcmp(nodelabel, dev_nodelabel) == 0) {
     153                 :             :                                 return dev;
     154                 :             :                         }
     155                 :             :                 }
     156                 :             :         }
     157                 :             : 
     158                 :             :         return NULL;
     159                 :             : }
     160                 :             : 
     161                 :             : #ifdef CONFIG_USERSPACE
     162                 :             : static inline const struct device *z_vrfy_device_get_by_dt_nodelabel(const char *nodelabel)
     163                 :             : {
     164                 :             :         char nl_copy[Z_DEVICE_MAX_NODELABEL_LEN];
     165                 :             : 
     166                 :             :         if (k_usermode_string_copy(nl_copy, (char *)nodelabel, sizeof(nl_copy)) != 0) {
     167                 :             :                 return NULL;
     168                 :             :         }
     169                 :             : 
     170                 :             :         return z_impl_device_get_by_dt_nodelabel(nl_copy);
     171                 :             : }
     172                 :             : #include <zephyr/syscalls/device_get_by_dt_nodelabel_mrsh.c>
     173                 :             : #endif /* CONFIG_USERSPACE */
     174                 :             : #endif /* CONFIG_DEVICE_DT_METADATA */
     175                 :             : 
     176                 :           0 : size_t z_device_get_all_static(struct device const **devices)
     177                 :             : {
     178                 :           0 :         size_t cnt;
     179                 :             : 
     180                 :           0 :         STRUCT_SECTION_GET(device, 0, devices);
     181                 :           0 :         STRUCT_SECTION_COUNT(device, &cnt);
     182                 :             : 
     183                 :           0 :         return cnt;
     184                 :             : }
     185                 :             : 
     186                 :           0 : bool z_impl_device_is_ready(const struct device *dev)
     187                 :             : {
     188                 :             :         /*
     189                 :             :          * if an invalid device pointer is passed as argument, this call
     190                 :             :          * reports the `device` as not ready for usage.
     191                 :             :          */
     192         [ #  # ]:           0 :         if (dev == NULL) {
     193                 :             :                 return false;
     194                 :             :         }
     195                 :             : 
     196   [ #  #  #  # ]:           0 :         return dev->state->initialized && (dev->state->init_res == 0U);
     197                 :             : }
     198                 :             : 
     199                 :           0 : int z_impl_device_deinit(const struct device *dev)
     200                 :             : {
     201                 :             : #ifdef CONFIG_DEVICE_DEINIT_SUPPORT
     202                 :             :         int ret;
     203                 :             : 
     204                 :             :         if (!dev->state->initialized) {
     205                 :             :                 return -EPERM;
     206                 :             :         }
     207                 :             : 
     208                 :             :         if (dev->ops.deinit == NULL) {
     209                 :             :                 return -ENOTSUP;
     210                 :             :         }
     211                 :             : 
     212                 :             :         ret = dev->ops.deinit(dev);
     213                 :             :         if (ret < 0) {
     214                 :             :                 return ret;
     215                 :             :         }
     216                 :             : 
     217                 :             :         dev->state->initialized = false;
     218                 :             : 
     219                 :             :         return 0;
     220                 :             : #else
     221                 :           0 :         ARG_UNUSED(dev);
     222                 :           0 :         return -ENOTSUP;
     223                 :             : #endif /* CONFIG_DEVICE_DEINIT_SUPPORT */
     224                 :             : }
     225                 :             : 
     226                 :             : #ifdef CONFIG_USERSPACE
     227                 :             : static inline int z_vrfy_device_deinit(const struct device *dev)
     228                 :             : {
     229                 :             :         K_OOPS(K_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY));
     230                 :             : 
     231                 :             :         return z_impl_device_deinit(dev);
     232                 :             : }
     233                 :             : #include <zephyr/syscalls/device_deinit_mrsh.c>
     234                 :             : #endif
     235                 :             : 
     236                 :             : #ifdef CONFIG_DEVICE_DEPS
     237                 :             : 
     238                 :             : static int device_visitor(const device_handle_t *handles,
     239                 :             :                            size_t handle_count,
     240                 :             :                            device_visitor_callback_t visitor_cb,
     241                 :             :                            void *context)
     242                 :             : {
     243                 :             :         /* Iterate over fixed devices */
     244                 :             :         for (size_t i = 0; i < handle_count; ++i) {
     245                 :             :                 device_handle_t dh = handles[i];
     246                 :             :                 const struct device *rdev = device_from_handle(dh);
     247                 :             :                 int rc = visitor_cb(rdev, context);
     248                 :             : 
     249                 :             :                 if (rc < 0) {
     250                 :             :                         return rc;
     251                 :             :                 }
     252                 :             :         }
     253                 :             : 
     254                 :             :         return handle_count;
     255                 :             : }
     256                 :             : 
     257                 :             : int device_required_foreach(const struct device *dev,
     258                 :             :                             device_visitor_callback_t visitor_cb,
     259                 :             :                             void *context)
     260                 :             : {
     261                 :             :         size_t handle_count = 0;
     262                 :             :         const device_handle_t *handles = device_required_handles_get(dev, &handle_count);
     263                 :             : 
     264                 :             :         return device_visitor(handles, handle_count, visitor_cb, context);
     265                 :             : }
     266                 :             : 
     267                 :             : int device_supported_foreach(const struct device *dev,
     268                 :             :                              device_visitor_callback_t visitor_cb,
     269                 :             :                              void *context)
     270                 :             : {
     271                 :             :         size_t handle_count = 0;
     272                 :             :         const device_handle_t *handles = device_supported_handles_get(dev, &handle_count);
     273                 :             : 
     274                 :             :         return device_visitor(handles, handle_count, visitor_cb, context);
     275                 :             : }
     276                 :             : 
     277                 :             : #endif /* CONFIG_DEVICE_DEPS */
        

Generated by: LCOV version 2.0-1