diff --git a/components/drivers/serial/serial_tty.c b/components/drivers/serial/serial_tty.c index 98e7ee652df..6c7b8d1a605 100644 --- a/components/drivers/serial/serial_tty.c +++ b/components/drivers/serial/serial_tty.c @@ -402,3 +402,66 @@ static int _tty_workqueue_init(void) return RT_EOK; } INIT_PREV_EXPORT(_tty_workqueue_init); + +static rt_err_t _match_tty_iter(struct rt_object *obj, void *data) +{ + rt_device_t target = *(rt_device_t *)data; + rt_device_t device = rt_container_of(obj, struct rt_device, parent); + if (device->type == RT_Device_Class_Char) + { + lwp_tty_t tp; + if (rt_strncmp(obj->name, "tty"TTY_NAME_PREFIX, + sizeof("tty"TTY_NAME_PREFIX) - 1) == 0) + { + struct serial_tty_context *softc; + + tp = rt_container_of(device, struct lwp_tty, parent); + softc = tty_softc(tp); + + if (&softc->parent->parent == target) + { + /* matched, early return */ + *(rt_device_t *)data = device; + return 1; + } + } + } + + return RT_EOK; +} + +/** + * @brief The default console is only a backup device with lowest priority. + * It's always recommended to scratch the console from the boot arguments. + * And dont forget to register the device with a higher priority. + */ +static int _default_console_setup(void) +{ + rt_err_t rc; + rt_device_t bakdev; + rt_device_t ttydev; + + bakdev = rt_console_get_device(); + if (!bakdev) + { + return -RT_ENOENT; + } + + ttydev = bakdev; + rt_object_for_each(RT_Object_Class_Device, _match_tty_iter, &ttydev); + + if (ttydev != bakdev) + { + LOG_I("Using /dev/%.*s as default console", RT_NAME_MAX, ttydev->parent.name); + lwp_console_register_backend(ttydev, LWP_CONSOLE_LOWEST_PRIOR); + rc = RT_EOK; + } + else + { + rc = -RT_EINVAL; + } + + return rc; +} + +INIT_COMPONENT_EXPORT(_default_console_setup); diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index 87629cc890c..c33bbfdc5f3 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -17,7 +17,7 @@ */ #define DBG_TAG "lwp" -#define DBG_LVL DBG_WARNING +#define DBG_LVL DBG_INFO #include #include @@ -62,29 +62,6 @@ static const char elf_magic[] = {0x7f, 'E', 'L', 'F'}; extern char working_directory[]; #endif -/** - * @brief The default console is only a backup device with lowest priority. - * It's always recommended to scratch the console from the boot arguments. - * And dont forget to register the device with a higher priority. - */ -static rt_err_t lwp_default_console_setup(void) -{ - rt_device_t bakdev = rt_device_find("ttyS0"); - rt_err_t rc; - - if (bakdev) - { - lwp_console_register_backend(bakdev, LWP_CONSOLE_LOWEST_PRIOR); - rc = RT_EOK; - } - else - { - rc = -RT_EINVAL; - } - - return rc; -} - static int lwp_component_init(void) { int rc; @@ -104,10 +81,6 @@ static int lwp_component_init(void) { LOG_E("%s: lwp_futex_init() failed", __func__); } - else if ((rc = lwp_default_console_setup()) != RT_EOK) - { - LOG_E("%s: lwp_default_console_setup() failed", __func__); - } return rc; } INIT_COMPONENT_EXPORT(lwp_component_init); diff --git a/components/lwp/terminal/terminal.h b/components/lwp/terminal/terminal.h index df0dc04128d..69ed66d5ff2 100644 --- a/components/lwp/terminal/terminal.h +++ b/components/lwp/terminal/terminal.h @@ -212,9 +212,8 @@ void tty_rel_gone(struct lwp_tty *tp); #define tty_lock_notrecused(tp) (rt_mutex_get_hold(tty_getlock(tp)) == 1) #define tty_assert_locked(tp) RT_ASSERT(tty_lock_owned(tp)) #define tty_lock_assert(tp, option) \ - (((option) == (MA_OWNED | MA_NOTRECURSED)) \ - ? (tty_lock_owned(tp) && tty_lock_notrecused(tp)) \ - : rt_assert_handler("Operation not allowed", __func__, __LINE__)) + RT_ASSERT(((option) == (MA_OWNED | MA_NOTRECURSED)) && \ + (tty_lock_owned(tp) && tty_lock_notrecused(tp))) /* System messages. */ int tty_checkoutq(struct lwp_tty *tp); diff --git a/include/rtdef.h b/include/rtdef.h index 06fcfcb8b88..f0918d5dd67 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -355,6 +355,15 @@ struct rt_object }; typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */ +/** + * iterator of rt_object_for_each() + * + * data is the data passing in to rt_object_for_each(). iterator can return + * RT_EOK to continue the iteration; or any positive value to break the loop + * successfully; or any negative errno to break the loop on failure. + */ +typedef rt_err_t (*rt_object_iter_t)(rt_object_t object, void *data); + /** * The object type can be one of the follows with specific * macros enabled: diff --git a/include/rtthread.h b/include/rtthread.h index c2174cce423..1cad47931ab 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -75,6 +75,7 @@ rt_err_t rt_custom_object_destroy(rt_object_t obj); #endif /* RT_USING_HEAP */ rt_bool_t rt_object_is_systemobject(rt_object_t object); rt_uint8_t rt_object_get_type(rt_object_t object); +rt_err_t rt_object_for_each(rt_uint8_t type, rt_object_iter_t iter, void *data); rt_object_t rt_object_find(const char *name, rt_uint8_t type); rt_err_t rt_object_get_name(rt_object_t object, char *name, rt_uint8_t name_size); diff --git a/src/object.c b/src/object.c index bdb69364ce3..ae62be1fa33 100644 --- a/src/object.c +++ b/src/object.c @@ -575,29 +575,32 @@ rt_uint8_t rt_object_get_type(rt_object_t object) } /** - * @brief This function will find specified name object from object + * @brief This function will iterate through each object from object * container. * - * @param name is the specified name of object. - * * @param type is the type of object + * @param iter is the iterator + * @param data is the specified data passed to iterator * - * @return the found object or RT_NULL if there is no this object - * in object container. + * @return RT_EOK on succeed, otherwise the error from `iter` * * @note this function shall not be invoked in interrupt status. */ -rt_object_t rt_object_find(const char *name, rt_uint8_t type) +rt_err_t rt_object_for_each(rt_uint8_t type, rt_object_iter_t iter, void *data) { struct rt_object *object = RT_NULL; struct rt_list_node *node = RT_NULL; struct rt_object_information *information = RT_NULL; rt_base_t level; + rt_err_t error; information = rt_object_get_information((enum rt_object_class_type)type); /* parameter check */ - if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL; + if (information == RT_NULL) + { + return -RT_EINVAL; + } /* which is invoke in interrupt status */ RT_DEBUG_NOT_IN_INTERRUPT; @@ -609,16 +612,62 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type) rt_list_for_each(node, &(information->object_list)) { object = rt_list_entry(node, struct rt_object, list); - if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0) + if ((error = iter(object, data)) != RT_EOK) { rt_spin_unlock_irqrestore(&(information->spinlock), level); - return object; + return error >= 0 ? RT_EOK : error; } } rt_spin_unlock_irqrestore(&(information->spinlock), level); + return RT_EOK; +} + +static rt_err_t _match_name(struct rt_object *obj, void *data) +{ + const char *name = *(const char **)data; + if (rt_strncmp(obj->name, name, RT_NAME_MAX) == 0) + { + *(rt_object_t *)data = obj; + + /* notify an early break of loop, but not on error */ + return 1; + } + + return RT_EOK; +} + +/** + * @brief This function will find specified name object from object + * container. + * + * @param name is the specified name of object. + * + * @param type is the type of object + * + * @return the found object or RT_NULL if there is no this object + * in object container. + * + * @note this function shall not be invoked in interrupt status. + */ +rt_object_t rt_object_find(const char *name, rt_uint8_t type) +{ + void *data = (void *)name; + + /* parameter check */ + if (name == RT_NULL) return RT_NULL; + + /* which is invoke in interrupt status */ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_object_for_each(type, _match_name, &data); + if (data != name) + { + return data; + } + return RT_NULL; }