[smart] select console device dynamically (#8949)
* [smart] select console device dynamically - Fixed compiler warning on terminal subsystem for `components/lwp/terminal/terminal.h` - Updated default console setup to dynamically select an appropriate tty device based on the configured console device name. Signed-off-by: Shell <smokewood@qq.com> * fixup: remove useless codes --------- Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
parent
3d30b56c86
commit
f2d6325b43
|
@ -404,3 +404,66 @@ static int _tty_workqueue_init(void)
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
INIT_PREV_EXPORT(_tty_workqueue_init);
|
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);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DBG_TAG "lwp"
|
#define DBG_TAG "lwp"
|
||||||
#define DBG_LVL DBG_WARNING
|
#define DBG_LVL DBG_INFO
|
||||||
#include <rtdbg.h>
|
#include <rtdbg.h>
|
||||||
|
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
|
@ -62,29 +62,6 @@ static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
|
||||||
extern char working_directory[];
|
extern char working_directory[];
|
||||||
#endif
|
#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)
|
static int lwp_component_init(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -104,10 +81,6 @@ static int lwp_component_init(void)
|
||||||
{
|
{
|
||||||
LOG_E("%s: lwp_futex_init() failed", __func__);
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
INIT_COMPONENT_EXPORT(lwp_component_init);
|
INIT_COMPONENT_EXPORT(lwp_component_init);
|
||||||
|
|
|
@ -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_lock_notrecused(tp) (rt_mutex_get_hold(tty_getlock(tp)) == 1)
|
||||||
#define tty_assert_locked(tp) RT_ASSERT(tty_lock_owned(tp))
|
#define tty_assert_locked(tp) RT_ASSERT(tty_lock_owned(tp))
|
||||||
#define tty_lock_assert(tp, option) \
|
#define tty_lock_assert(tp, option) \
|
||||||
(((option) == (MA_OWNED | MA_NOTRECURSED)) \
|
RT_ASSERT(((option) == (MA_OWNED | MA_NOTRECURSED)) && \
|
||||||
? (tty_lock_owned(tp) && tty_lock_notrecused(tp)) \
|
(tty_lock_owned(tp) && tty_lock_notrecused(tp)))
|
||||||
: rt_assert_handler("Operation not allowed", __func__, __LINE__))
|
|
||||||
|
|
||||||
/* System messages. */
|
/* System messages. */
|
||||||
int tty_checkoutq(struct lwp_tty *tp);
|
int tty_checkoutq(struct lwp_tty *tp);
|
||||||
|
|
|
@ -355,6 +355,15 @@ struct rt_object
|
||||||
};
|
};
|
||||||
typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */
|
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
|
* The object type can be one of the follows with specific
|
||||||
* macros enabled:
|
* macros enabled:
|
||||||
|
|
|
@ -75,6 +75,7 @@ rt_err_t rt_custom_object_destroy(rt_object_t obj);
|
||||||
#endif /* RT_USING_HEAP */
|
#endif /* RT_USING_HEAP */
|
||||||
rt_bool_t rt_object_is_systemobject(rt_object_t object);
|
rt_bool_t rt_object_is_systemobject(rt_object_t object);
|
||||||
rt_uint8_t rt_object_get_type(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_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);
|
rt_err_t rt_object_get_name(rt_object_t object, char *name, rt_uint8_t name_size);
|
||||||
|
|
||||||
|
|
91
src/object.c
91
src/object.c
|
@ -574,6 +574,71 @@ rt_uint8_t rt_object_get_type(rt_object_t object)
|
||||||
return object->type & ~RT_Object_Class_Static;
|
return object->type & ~RT_Object_Class_Static;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function will iterate through each object from object
|
||||||
|
* container.
|
||||||
|
*
|
||||||
|
* @param type is the type of object
|
||||||
|
* @param iter is the iterator
|
||||||
|
* @param data is the specified data passed to iterator
|
||||||
|
*
|
||||||
|
* @return RT_EOK on succeed, otherwise the error from `iter`
|
||||||
|
*
|
||||||
|
* @note this function shall not be invoked in interrupt status.
|
||||||
|
*/
|
||||||
|
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 (information == RT_NULL)
|
||||||
|
{
|
||||||
|
return -RT_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* which is invoke in interrupt status */
|
||||||
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
||||||
|
|
||||||
|
/* enter critical */
|
||||||
|
level = rt_spin_lock_irqsave(&(information->spinlock));
|
||||||
|
|
||||||
|
/* try to find object */
|
||||||
|
rt_list_for_each(node, &(information->object_list))
|
||||||
|
{
|
||||||
|
object = rt_list_entry(node, struct rt_object, list);
|
||||||
|
if ((error = iter(object, data)) != RT_EOK)
|
||||||
|
{
|
||||||
|
rt_spin_unlock_irqrestore(&(information->spinlock), level);
|
||||||
|
|
||||||
|
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
|
* @brief This function will find specified name object from object
|
||||||
* container.
|
* container.
|
||||||
|
@ -589,35 +654,19 @@ rt_uint8_t rt_object_get_type(rt_object_t object)
|
||||||
*/
|
*/
|
||||||
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
|
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
|
||||||
{
|
{
|
||||||
struct rt_object *object = RT_NULL;
|
void *data = (void *)name;
|
||||||
struct rt_list_node *node = RT_NULL;
|
|
||||||
struct rt_object_information *information = RT_NULL;
|
|
||||||
rt_base_t level;
|
|
||||||
|
|
||||||
information = rt_object_get_information((enum rt_object_class_type)type);
|
|
||||||
|
|
||||||
/* parameter check */
|
/* parameter check */
|
||||||
if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
|
if (name == RT_NULL) return RT_NULL;
|
||||||
|
|
||||||
/* which is invoke in interrupt status */
|
/* which is invoke in interrupt status */
|
||||||
RT_DEBUG_NOT_IN_INTERRUPT;
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
||||||
|
|
||||||
/* enter critical */
|
rt_object_for_each(type, _match_name, &data);
|
||||||
level = rt_spin_lock_irqsave(&(information->spinlock));
|
if (data != name)
|
||||||
|
|
||||||
/* try to find object */
|
|
||||||
rt_list_for_each(node, &(information->object_list))
|
|
||||||
{
|
{
|
||||||
object = rt_list_entry(node, struct rt_object, list);
|
return data;
|
||||||
if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
|
|
||||||
{
|
|
||||||
rt_spin_unlock_irqrestore(&(information->spinlock), level);
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
rt_spin_unlock_irqrestore(&(information->spinlock), level);
|
|
||||||
|
|
||||||
return RT_NULL;
|
return RT_NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue