仓库迁移
This commit is contained in:
437
source/rt_thread/components/device/device.c
Normal file
437
source/rt_thread/components/device/device.c
Normal file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2007-01-21 Bernard the first version
|
||||
* 2010-05-04 Bernard add rt_device_init implementation
|
||||
* 2012-10-20 Bernard add device check in register function,
|
||||
* provided by Rob <rdent@iinet.net.au>
|
||||
* 2012-12-25 Bernard return RT_EOK if the device interface not exist.
|
||||
* 2013-07-09 Grissiom add ref_count support
|
||||
* 2016-04-02 Bernard fix the open_flag initialization issue.
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#if defined(RT_USING_POSIX)
|
||||
#include <rtdevice.h> /* for wqueue_init */
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_DEVICE
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
#define device_init (dev->ops->init)
|
||||
#define device_open (dev->ops->open)
|
||||
#define device_close (dev->ops->close)
|
||||
#define device_read (dev->ops->read)
|
||||
#define device_write (dev->ops->write)
|
||||
#define device_control (dev->ops->control)
|
||||
#else
|
||||
#define device_init (dev->init)
|
||||
#define device_open (dev->open)
|
||||
#define device_close (dev->close)
|
||||
#define device_read (dev->read)
|
||||
#define device_write (dev->write)
|
||||
#define device_control (dev->control)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function registers a device driver with specified name.
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param name the device driver's name
|
||||
* @param flags the capabilities flag of device
|
||||
*
|
||||
* @return the error code, RT_EOK on initialization successfully.
|
||||
*/
|
||||
rt_err_t rt_device_register(rt_device_t dev,
|
||||
const char *name,
|
||||
rt_uint16_t flags)
|
||||
{
|
||||
if (dev == RT_NULL)
|
||||
return -RT_ERROR;
|
||||
|
||||
if (rt_device_find(name) != RT_NULL)
|
||||
return -RT_ERROR;
|
||||
|
||||
rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
|
||||
dev->flag = flags;
|
||||
dev->ref_count = 0;
|
||||
dev->open_flag = 0;
|
||||
|
||||
#if defined(RT_USING_POSIX)
|
||||
dev->fops = RT_NULL;
|
||||
rt_wqueue_init(&(dev->wait_queue));
|
||||
#endif
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function removes a previously registered device driver
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_device_unregister(rt_device_t dev)
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
RT_ASSERT(rt_object_is_systemobject(&dev->parent));
|
||||
|
||||
rt_object_detach(&(dev->parent));
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes all registered device driver
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*
|
||||
* @deprecated since 1.2.x, this function is not needed because the initialization
|
||||
* of a device is performed when application opens it.
|
||||
*/
|
||||
rt_err_t rt_device_init_all(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function finds a device driver by specified name.
|
||||
*
|
||||
* @param name the device driver's name
|
||||
*
|
||||
* @return the registered device driver on successful, or RT_NULL on failure.
|
||||
*/
|
||||
rt_device_t rt_device_find(const char *name)
|
||||
{
|
||||
return (rt_device_t)rt_object_find(name, RT_Object_Class_Device);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
/**
|
||||
* This function creates a device object with user data size.
|
||||
*
|
||||
* @param type, the kind type of this device object.
|
||||
* @param attach_size, the size of user data.
|
||||
*
|
||||
* @return the allocated device object, or RT_NULL when failed.
|
||||
*/
|
||||
rt_device_t rt_device_create(int type, int attach_size)
|
||||
{
|
||||
int size;
|
||||
rt_device_t device;
|
||||
|
||||
size = RT_ALIGN(sizeof(struct rt_device), RT_ALIGN_SIZE);
|
||||
attach_size = RT_ALIGN(attach_size, RT_ALIGN_SIZE);
|
||||
/* use the total size */
|
||||
size += attach_size;
|
||||
|
||||
device = (rt_device_t)rt_malloc(size);
|
||||
if (device)
|
||||
{
|
||||
rt_memset(device, 0x0, sizeof(struct rt_device));
|
||||
device->type = (enum rt_device_class_type)type;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function destroy the specific device object.
|
||||
*
|
||||
* @param dev, the specific device object.
|
||||
*/
|
||||
void rt_device_destroy(rt_device_t dev)
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
RT_ASSERT(rt_object_is_systemobject(&dev->parent) == RT_FALSE);
|
||||
|
||||
rt_object_detach(&(dev->parent));
|
||||
|
||||
/* release this device object */
|
||||
rt_free(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will initialize the specified device
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
*
|
||||
* @return the result
|
||||
*/
|
||||
rt_err_t rt_device_init(rt_device_t dev)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
|
||||
/* get device_init handler */
|
||||
if (device_init != RT_NULL)
|
||||
{
|
||||
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
|
||||
{
|
||||
result = device_init(dev);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
rt_kprintf("To initialize device:%s failed. The error code is %d\n",
|
||||
dev->parent.name, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will open a device
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param oflag the flags for device open
|
||||
*
|
||||
* @return the result
|
||||
*/
|
||||
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
/* if device is not initialized, initialize it. */
|
||||
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
|
||||
{
|
||||
if (device_init != RT_NULL)
|
||||
{
|
||||
result = device_init(dev);
|
||||
if (result != RT_EOK)
|
||||
{
|
||||
rt_kprintf("To initialize device:%s failed. The error code is %d\n",
|
||||
dev->parent.name, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
|
||||
}
|
||||
|
||||
/* device is a stand alone device and opened */
|
||||
if ((dev->flag & RT_DEVICE_FLAG_STANDALONE) &&
|
||||
(dev->open_flag & RT_DEVICE_OFLAG_OPEN))
|
||||
{
|
||||
return -RT_EBUSY;
|
||||
}
|
||||
|
||||
/* call device_open interface */
|
||||
if (device_open != RT_NULL)
|
||||
{
|
||||
result = device_open(dev, oflag);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set open flag */
|
||||
dev->open_flag = (oflag & RT_DEVICE_OFLAG_MASK);
|
||||
}
|
||||
|
||||
/* set open flag */
|
||||
if (result == RT_EOK || result == -RT_ENOSYS)
|
||||
{
|
||||
dev->open_flag |= RT_DEVICE_OFLAG_OPEN;
|
||||
|
||||
dev->ref_count++;
|
||||
/* don't let bad things happen silently. If you are bitten by this assert,
|
||||
* please set the ref_count to a bigger type. */
|
||||
RT_ASSERT(dev->ref_count != 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will close a device
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
*
|
||||
* @return the result
|
||||
*/
|
||||
rt_err_t rt_device_close(rt_device_t dev)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
if (dev->ref_count == 0)
|
||||
return -RT_ERROR;
|
||||
|
||||
dev->ref_count--;
|
||||
|
||||
if (dev->ref_count != 0)
|
||||
return RT_EOK;
|
||||
|
||||
/* call device_close interface */
|
||||
if (device_close != RT_NULL)
|
||||
{
|
||||
result = device_close(dev);
|
||||
}
|
||||
|
||||
/* set open flag */
|
||||
if (result == RT_EOK || result == -RT_ENOSYS)
|
||||
dev->open_flag = RT_DEVICE_OFLAG_CLOSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will read some data from a device.
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param pos the position of reading
|
||||
* @param buffer the data buffer to save read data
|
||||
* @param size the size of buffer
|
||||
*
|
||||
* @return the actually read size on successful, otherwise negative returned.
|
||||
*
|
||||
* @note since 0.4.0, the unit of size/pos is a block for block device.
|
||||
*/
|
||||
rt_size_t rt_device_read(rt_device_t dev,
|
||||
rt_off_t pos,
|
||||
void *buffer,
|
||||
rt_size_t size)
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
if (dev->ref_count == 0)
|
||||
{
|
||||
rt_set_errno(-RT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call device_read interface */
|
||||
if (device_read != RT_NULL)
|
||||
{
|
||||
return device_read(dev, pos, buffer, size);
|
||||
}
|
||||
|
||||
/* set error code */
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will write some data to a device.
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param pos the position of written
|
||||
* @param buffer the data buffer to be written to device
|
||||
* @param size the size of buffer
|
||||
*
|
||||
* @return the actually written size on successful, otherwise negative returned.
|
||||
*
|
||||
* @note since 0.4.0, the unit of size/pos is a block for block device.
|
||||
*/
|
||||
rt_size_t rt_device_write(rt_device_t dev,
|
||||
rt_off_t pos,
|
||||
const void *buffer,
|
||||
rt_size_t size)
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
if (dev->ref_count == 0)
|
||||
{
|
||||
rt_set_errno(-RT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call device_write interface */
|
||||
if (device_write != RT_NULL)
|
||||
{
|
||||
return device_write(dev, pos, buffer, size);
|
||||
}
|
||||
|
||||
/* set error code */
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will perform a variety of control functions on devices.
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param cmd the command sent to device
|
||||
* @param arg the argument of command
|
||||
*
|
||||
* @return the result
|
||||
*/
|
||||
rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
/* call device_write interface */
|
||||
if (device_control != RT_NULL)
|
||||
{
|
||||
return device_control(dev, cmd, arg);
|
||||
}
|
||||
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will set the reception indication callback function. This callback function
|
||||
* is invoked when this device receives data.
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param rx_ind the indication callback function
|
||||
*
|
||||
* @return RT_EOK
|
||||
*/
|
||||
rt_err_t
|
||||
rt_device_set_rx_indicate(rt_device_t dev,
|
||||
rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size))
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
dev->rx_indicate = rx_ind;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will set the indication callback function when device has
|
||||
* written data to physical hardware.
|
||||
*
|
||||
* @param dev the pointer of device driver structure
|
||||
* @param tx_done the indication callback function
|
||||
*
|
||||
* @return RT_EOK
|
||||
*/
|
||||
rt_err_t
|
||||
rt_device_set_tx_complete(rt_device_t dev,
|
||||
rt_err_t (*tx_done)(rt_device_t dev, void *buffer))
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
|
||||
|
||||
dev->tx_complete = tx_done;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#endif
|
1141
source/rt_thread/components/finsh/cmd.c
Normal file
1141
source/rt_thread/components/finsh/cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
249
source/rt_thread/components/finsh/finsh.h
Normal file
249
source/rt_thread/components/finsh/finsh.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_H__
|
||||
#define __FINSH_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "finsh_api.h"
|
||||
|
||||
/* -- the beginning of option -- */
|
||||
#define FINSH_NAME_MAX 16 /* max length of identifier */
|
||||
#define FINSH_NODE_MAX 16 /* max number of node */
|
||||
|
||||
#define FINSH_HEAP_MAX 128 /* max length of heap */
|
||||
#define FINSH_STRING_MAX 128 /* max length of string */
|
||||
#define FINSH_VARIABLE_MAX 8 /* max number of variable */
|
||||
|
||||
#define FINSH_STACK_MAX 64 /* max stack size */
|
||||
#define FINSH_TEXT_MAX 128 /* max text segment size */
|
||||
|
||||
#define HEAP_ALIGNMENT 4 /* heap alignment */
|
||||
|
||||
#define FINSH_GET16(x) (*(x)) | (*((x)+1) << 8)
|
||||
#define FINSH_GET32(x) (rt_uint32_t)(*(x)) | ((rt_uint32_t)*((x)+1) << 8) | \
|
||||
((rt_uint32_t)*((x)+2) << 16) | ((rt_uint32_t)*((x)+3) << 24)
|
||||
|
||||
#define FINSH_SET16(x, v) \
|
||||
do \
|
||||
{ \
|
||||
*(x) = (v) & 0x00ff; \
|
||||
(*((x)+1)) = (v) >> 8; \
|
||||
} while ( 0 )
|
||||
|
||||
#define FINSH_SET32(x, v) \
|
||||
do \
|
||||
{ \
|
||||
*(x) = (rt_uint32_t)(v) & 0x000000ff; \
|
||||
(*((x)+1)) = ((rt_uint32_t)(v) >> 8) & 0x000000ff; \
|
||||
(*((x)+2)) = ((rt_uint32_t)(v) >> 16) & 0x000000ff; \
|
||||
(*((x)+3)) = ((rt_uint32_t)(v) >> 24); \
|
||||
} while ( 0 )
|
||||
|
||||
/* -- the end of option -- */
|
||||
|
||||
/* std header file */
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define FINSH_VERSION_MAJOR 1
|
||||
#define FINSH_VERSION_MINOR 0
|
||||
|
||||
/**
|
||||
* @addtogroup finsh
|
||||
*/
|
||||
/*@{*/
|
||||
#define FINSH_ERROR_OK 0 /**< No error */
|
||||
#define FINSH_ERROR_INVALID_TOKEN 1 /**< Invalid token */
|
||||
#define FINSH_ERROR_EXPECT_TYPE 2 /**< Expect a type */
|
||||
#define FINSH_ERROR_UNKNOWN_TYPE 3 /**< Unknown type */
|
||||
#define FINSH_ERROR_VARIABLE_EXIST 4 /**< Variable exist */
|
||||
#define FINSH_ERROR_EXPECT_OPERATOR 5 /**< Expect a operator */
|
||||
#define FINSH_ERROR_MEMORY_FULL 6 /**< Memory full */
|
||||
#define FINSH_ERROR_UNKNOWN_OP 7 /**< Unknown operator */
|
||||
#define FINSH_ERROR_UNKNOWN_NODE 8 /**< Unknown node */
|
||||
#define FINSH_ERROR_EXPECT_CHAR 9 /**< Expect a character */
|
||||
#define FINSH_ERROR_UNEXPECT_END 10 /**< Unexpect end */
|
||||
#define FINSH_ERROR_UNKNOWN_TOKEN 11 /**< Unknown token */
|
||||
#define FINSH_ERROR_NO_FLOAT 12 /**< Float not supported */
|
||||
#define FINSH_ERROR_UNKNOWN_SYMBOL 13 /**< Unknown symbol */
|
||||
#define FINSH_ERROR_NULL_NODE 14 /**< Null node */
|
||||
/*@}*/
|
||||
|
||||
/* system call item */
|
||||
struct finsh_syscall_item
|
||||
{
|
||||
struct finsh_syscall_item* next; /* next item */
|
||||
struct finsh_syscall syscall; /* syscall */
|
||||
};
|
||||
extern struct finsh_syscall_item *global_syscall_list;
|
||||
|
||||
/* system variable table */
|
||||
struct finsh_sysvar
|
||||
{
|
||||
const char* name; /* the name of variable */
|
||||
#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
|
||||
const char* desc; /* description of system variable */
|
||||
#endif
|
||||
uint8_t type; /* the type of variable */
|
||||
void* var ; /* the address of variable */
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
|
||||
struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call);
|
||||
struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call);
|
||||
#define FINSH_NEXT_SYSCALL(index) index=finsh_syscall_next(index)
|
||||
#define FINSH_NEXT_SYSVAR(index) index=finsh_sysvar_next(index)
|
||||
#else
|
||||
#define FINSH_NEXT_SYSCALL(index) index++
|
||||
#define FINSH_NEXT_SYSVAR(index) index++
|
||||
#endif
|
||||
|
||||
/* system variable item */
|
||||
struct finsh_sysvar_item
|
||||
{
|
||||
struct finsh_sysvar_item *next; /* next item */
|
||||
struct finsh_sysvar sysvar; /* system variable */
|
||||
};
|
||||
extern struct finsh_sysvar *_sysvar_table_begin, *_sysvar_table_end;
|
||||
extern struct finsh_sysvar_item* global_sysvar_list;
|
||||
|
||||
/* find out system variable, which should be implemented in user program */
|
||||
struct finsh_sysvar* finsh_sysvar_lookup(const char* name);
|
||||
|
||||
|
||||
struct finsh_token
|
||||
{
|
||||
char eof;
|
||||
char replay;
|
||||
|
||||
int position;
|
||||
uint8_t current_token;
|
||||
|
||||
union {
|
||||
char char_value;
|
||||
int int_value;
|
||||
long long_value;
|
||||
} value;
|
||||
uint8_t string[FINSH_STRING_MAX];
|
||||
|
||||
uint8_t* line;
|
||||
};
|
||||
|
||||
#define FINSH_IDTYPE_VAR 0x01
|
||||
#define FINSH_IDTYPE_SYSVAR 0x02
|
||||
#define FINSH_IDTYPE_SYSCALL 0x04
|
||||
#define FINSH_IDTYPE_ADDRESS 0x08
|
||||
struct finsh_node
|
||||
{
|
||||
uint8_t node_type; /* node node_type */
|
||||
uint8_t data_type; /* node data node_type */
|
||||
uint8_t idtype; /* id node information */
|
||||
|
||||
union { /* value node */
|
||||
char char_value;
|
||||
short short_value;
|
||||
int int_value;
|
||||
long long_value;
|
||||
void* ptr;
|
||||
} value;
|
||||
union
|
||||
{
|
||||
/* point to variable identifier or function identifier */
|
||||
struct finsh_var *var;
|
||||
struct finsh_sysvar *sysvar;
|
||||
struct finsh_syscall*syscall;
|
||||
}id;
|
||||
|
||||
/* sibling and child node */
|
||||
struct finsh_node *sibling, *child;
|
||||
};
|
||||
|
||||
struct finsh_parser
|
||||
{
|
||||
uint8_t* parser_string;
|
||||
|
||||
struct finsh_token token;
|
||||
struct finsh_node* root;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* The basic data type in finsh shell
|
||||
*/
|
||||
enum finsh_type {
|
||||
finsh_type_unknown = 0, /**< unknown data type */
|
||||
finsh_type_void, /**< void */
|
||||
finsh_type_voidp, /**< void pointer */
|
||||
finsh_type_char, /**< char */
|
||||
finsh_type_uchar, /**< unsigned char */
|
||||
finsh_type_charp, /**< char pointer */
|
||||
finsh_type_short, /**< short */
|
||||
finsh_type_ushort, /**< unsigned short */
|
||||
finsh_type_shortp, /**< short pointer */
|
||||
finsh_type_int, /**< int */
|
||||
finsh_type_uint, /**< unsigned int */
|
||||
finsh_type_intp, /**< int pointer */
|
||||
finsh_type_long, /**< long */
|
||||
finsh_type_ulong, /**< unsigned long */
|
||||
finsh_type_longp /**< long pointer */
|
||||
};
|
||||
|
||||
/* init finsh environment */
|
||||
int finsh_init(struct finsh_parser* parser);
|
||||
/* flush finsh node, text segment */
|
||||
int finsh_flush(struct finsh_parser* parser);
|
||||
/* reset all of finsh */
|
||||
int finsh_reset(struct finsh_parser* parser);
|
||||
#ifdef RT_USING_DEVICE
|
||||
void finsh_set_device(const char* device_name);
|
||||
#endif
|
||||
|
||||
/* run finsh parser to generate abstract synatx tree */
|
||||
void finsh_parser_run (struct finsh_parser* parser, const unsigned char* string);
|
||||
/* run compiler to compile abstract syntax tree */
|
||||
int finsh_compiler_run(struct finsh_node* node);
|
||||
/* run finsh virtual machine */
|
||||
void finsh_vm_run(void);
|
||||
|
||||
/* get variable value */
|
||||
struct finsh_var* finsh_var_lookup(const char* name);
|
||||
/* get bottom value of stack */
|
||||
long finsh_stack_bottom(void);
|
||||
|
||||
/* get error number of finsh */
|
||||
uint8_t finsh_errno(void);
|
||||
/* get error string */
|
||||
const char* finsh_error_string(uint8_t type);
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function appends a system call to finsh runtime environment
|
||||
* @param name the name of system call
|
||||
* @param func the function pointer of system call
|
||||
*/
|
||||
void finsh_syscall_append(const char* name, syscall_func func);
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function appends a system variable to finsh runtime environment
|
||||
* @param name the name of system variable
|
||||
* @param type the data type of system variable
|
||||
* @param addr the address of system variable
|
||||
*/
|
||||
void finsh_sysvar_append(const char* name, uint8_t type, void* addr);
|
||||
#endif
|
||||
#endif
|
220
source/rt_thread/components/finsh/finsh_api.h
Normal file
220
source/rt_thread/components/finsh/finsh_api.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef FINSH_API_H__
|
||||
#define FINSH_API_H__
|
||||
|
||||
#include "finsh_config.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma section("FSymTab$f",read)
|
||||
#pragma section("VSymTab",read)
|
||||
#endif
|
||||
|
||||
typedef long (*syscall_func)(void);
|
||||
|
||||
/* system call table */
|
||||
struct finsh_syscall
|
||||
{
|
||||
const char* name; /* the name of system call */
|
||||
#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
|
||||
const char* desc; /* description of system call */
|
||||
#endif
|
||||
syscall_func func; /* the function address of system call */
|
||||
};
|
||||
extern struct finsh_syscall *_syscall_table_begin, *_syscall_table_end;
|
||||
|
||||
/* find out system call, which should be implemented in user program */
|
||||
struct finsh_syscall* finsh_syscall_lookup(const char* name);
|
||||
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
|
||||
#ifdef __TI_COMPILER_VERSION__
|
||||
#define __TI_FINSH_EXPORT_FUNCTION(f) PRAGMA(DATA_SECTION(f,"FSymTab"))
|
||||
#define __TI_FINSH_EXPORT_VAR(v) PRAGMA(DATA_SECTION(v,"VSymTab"))
|
||||
#endif
|
||||
|
||||
#ifdef FINSH_USING_DESCRIPTION
|
||||
#ifdef _MSC_VER
|
||||
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
|
||||
const char __fsym_##cmd##_name[] = #cmd; \
|
||||
const char __fsym_##cmd##_desc[] = #desc; \
|
||||
__declspec(allocate("FSymTab$f")) \
|
||||
const struct finsh_syscall __fsym_##cmd = \
|
||||
{ \
|
||||
__fsym_##cmd##_name, \
|
||||
__fsym_##cmd##_desc, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
#pragma comment(linker, "/merge:FSymTab=mytext")
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
const char __vsym_##name##_desc[] = #desc; \
|
||||
__declspec(allocate("VSymTab")) \
|
||||
const struct finsh_sysvar __vsym_##name = \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
__vsym_##name##_desc, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
|
||||
#elif defined(__TI_COMPILER_VERSION__)
|
||||
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
|
||||
__TI_FINSH_EXPORT_FUNCTION(__fsym_##cmd); \
|
||||
const char __fsym_##cmd##_name[] = #cmd; \
|
||||
const char __fsym_##cmd##_desc[] = #desc; \
|
||||
const struct finsh_syscall __fsym_##cmd = \
|
||||
{ \
|
||||
__fsym_##cmd##_name, \
|
||||
__fsym_##cmd##_desc, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
__TI_FINSH_EXPORT_VAR(__vsym_##name); \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
const char __vsym_##name##_desc[] = #desc; \
|
||||
const struct finsh_sysvar __vsym_##name = \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
__vsym_##name##_desc, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
|
||||
#else
|
||||
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
|
||||
const char __fsym_##cmd##_name[] SECTION(".rodata.name") = #cmd; \
|
||||
const char __fsym_##cmd##_desc[] SECTION(".rodata.name") = #desc; \
|
||||
RT_USED const struct finsh_syscall __fsym_##cmd SECTION("FSymTab")= \
|
||||
{ \
|
||||
__fsym_##cmd##_name, \
|
||||
__fsym_##cmd##_desc, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
const char __vsym_##name##_name[] SECTION(".rodata.name") = #name; \
|
||||
const char __vsym_##name##_desc[] SECTION(".rodata.name") = #desc; \
|
||||
RT_USED const struct finsh_sysvar __vsym_##name SECTION("VSymTab")= \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
__vsym_##name##_desc, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
|
||||
#endif
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
|
||||
const char __fsym_##cmd##_name[] = #cmd; \
|
||||
__declspec(allocate("FSymTab$f")) \
|
||||
const struct finsh_syscall __fsym_##cmd = \
|
||||
{ \
|
||||
__fsym_##cmd##_name, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
#pragma comment(linker, "/merge:FSymTab=mytext")
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
__declspec(allocate("VSymTab")) const struct finsh_sysvar __vsym_##name = \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
|
||||
#elif defined(__TI_COMPILER_VERSION__)
|
||||
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
|
||||
__TI_FINSH_EXPORT_FUNCTION(__fsym_##cmd); \
|
||||
const char __fsym_##cmd##_name[] = #cmd; \
|
||||
const struct finsh_syscall __fsym_##cmd = \
|
||||
{ \
|
||||
__fsym_##cmd##_name, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
__TI_FINSH_EXPORT_VAR(__vsym_##name); \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
const struct finsh_sysvar __vsym_##name = \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
|
||||
#else
|
||||
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc) \
|
||||
const char __fsym_##cmd##_name[] = #cmd; \
|
||||
RT_USED const struct finsh_syscall __fsym_##cmd SECTION("FSymTab")= \
|
||||
{ \
|
||||
__fsym_##cmd##_name, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
RT_USED const struct finsh_sysvar __vsym_##name SECTION("VSymTab")= \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* end of FINSH_USING_DESCRIPTION */
|
||||
#endif /* end of FINSH_USING_SYMTAB */
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This macro exports a system function to finsh shell.
|
||||
*
|
||||
* @param name the name of function.
|
||||
* @param desc the description of function, which will show in help.
|
||||
*/
|
||||
#define FINSH_FUNCTION_EXPORT(name, desc) \
|
||||
FINSH_FUNCTION_EXPORT_CMD(name, name, desc)
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This macro exports a system function with an alias name to finsh shell.
|
||||
*
|
||||
* @param name the name of function.
|
||||
* @param alias the alias name of function.
|
||||
* @param desc the description of function, which will show in help.
|
||||
*/
|
||||
#define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc) \
|
||||
FINSH_FUNCTION_EXPORT_CMD(name, alias, desc)
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This macro exports a command to module shell.
|
||||
*
|
||||
* @param command the name of command.
|
||||
* @param desc the description of command, which will show in help.
|
||||
*/
|
||||
#ifdef FINSH_USING_MSH
|
||||
#define MSH_CMD_EXPORT(command, desc) \
|
||||
FINSH_FUNCTION_EXPORT_CMD(command, __cmd_##command, desc)
|
||||
#define MSH_CMD_EXPORT_ALIAS(command, alias, desc) \
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(command, __cmd_##alias, desc)
|
||||
#else
|
||||
#define MSH_CMD_EXPORT(command, desc)
|
||||
#define MSH_CMD_EXPORT_ALIAS(command, alias, desc)
|
||||
#endif
|
||||
|
||||
#endif
|
29
source/rt_thread/components/finsh/finsh_config.h
Normal file
29
source/rt_thread/components/finsh/finsh_config.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* FinSH config file */
|
||||
|
||||
#ifndef __MSH_CFG_H__
|
||||
#define __MSH_CFG_H__
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
#define RT_USING_FINSH
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_USING_MSH_ONLY
|
||||
// <h>FinSH Configuration
|
||||
// <o>the priority of finsh thread <1-30>
|
||||
// <i>the priority of finsh thread
|
||||
// <i>Default: 21
|
||||
#define FINSH_THREAD_PRIORITY 21
|
||||
// <o>the stack of finsh thread <1-4096>
|
||||
// <i>the stack of finsh thread
|
||||
// <i>Default: 4096 (4096Byte)
|
||||
#define FINSH_THREAD_STACK_SIZE 1024
|
||||
|
||||
#define FINSH_USING_SYMTAB
|
||||
// <c1>Enable command description
|
||||
// <i>Enable command description
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
// </c>
|
||||
// </h>
|
||||
|
||||
// <<< end of configuration section >>>
|
||||
#endif
|
||||
|
30
source/rt_thread/components/finsh/finsh_port.c
Normal file
30
source/rt_thread/components/finsh/finsh_port.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtconfig.h>
|
||||
|
||||
#ifndef RT_USING_FINSH
|
||||
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
|
||||
RT_WEAK char rt_hw_console_getchar(void)
|
||||
{
|
||||
/* Note: the initial value of ch must < 0 */
|
||||
int ch = -1;
|
||||
|
||||
#error "TODO 4: Read a char from the uart and assign it to 'ch'."
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
#endif /* RT_USING_FINSH */
|
||||
|
648
source/rt_thread/components/finsh/msh.c
Normal file
648
source/rt_thread/components/finsh/msh.c
Normal file
@@ -0,0 +1,648 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-03-30 Bernard the first verion for finsh
|
||||
* 2014-01-03 Bernard msh can execute module.
|
||||
* 2017-07-19 Aubr.Cool limit argc to RT_FINSH_ARG_MAX
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <finsh_config.h>
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
|
||||
#include "msh.h"
|
||||
#include <finsh.h>
|
||||
#include <shell.h>
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
#include <dfs_posix.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_MODULE
|
||||
#include <dlmodule.h>
|
||||
#endif
|
||||
|
||||
#ifndef FINSH_ARG_MAX
|
||||
#define FINSH_ARG_MAX 8
|
||||
#endif
|
||||
|
||||
typedef int (*cmd_function_t)(int argc, char **argv);
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
#ifdef FINSH_USING_MSH_ONLY
|
||||
rt_bool_t msh_is_used(void)
|
||||
{
|
||||
return RT_TRUE;
|
||||
}
|
||||
#else
|
||||
#ifdef FINSH_USING_MSH_DEFAULT
|
||||
static rt_bool_t __msh_state = RT_TRUE;
|
||||
#else
|
||||
static rt_bool_t __msh_state = RT_FALSE;
|
||||
#endif
|
||||
rt_bool_t msh_is_used(void)
|
||||
{
|
||||
return __msh_state;
|
||||
}
|
||||
|
||||
static int msh_exit(int argc, char **argv)
|
||||
{
|
||||
/* return to finsh shell mode */
|
||||
__msh_state = RT_FALSE;
|
||||
return 0;
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(msh_exit, __cmd_exit, return to RT-Thread shell mode.);
|
||||
|
||||
static int msh_enter(void)
|
||||
{
|
||||
/* enter module shell mode */
|
||||
__msh_state = RT_TRUE;
|
||||
return 0;
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(msh_enter, msh, use module shell);
|
||||
#endif
|
||||
|
||||
int msh_help(int argc, char **argv)
|
||||
{
|
||||
rt_kprintf("RT-Thread shell commands:\n");
|
||||
{
|
||||
struct finsh_syscall *index;
|
||||
|
||||
for (index = _syscall_table_begin;
|
||||
index < _syscall_table_end;
|
||||
FINSH_NEXT_SYSCALL(index))
|
||||
{
|
||||
if (strncmp(index->name, "__cmd_", 6) != 0) continue;
|
||||
#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
|
||||
rt_kprintf("%-16s - %s\n", &index->name[6], index->desc);
|
||||
#else
|
||||
rt_kprintf("%s ", &index->name[6]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(msh_help, __cmd_help, RT-Thread shell help.);
|
||||
|
||||
int cmd_ps(int argc, char **argv)
|
||||
{
|
||||
extern long list_thread(void);
|
||||
extern int list_module(void);
|
||||
|
||||
#ifdef RT_USING_MODULE
|
||||
if ((argc == 2) && (strcmp(argv[1], "-m") == 0))
|
||||
list_module();
|
||||
else
|
||||
#endif
|
||||
list_thread();
|
||||
return 0;
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(cmd_ps, __cmd_ps, List threads in the system.);
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
int cmd_free(int argc, char **argv)
|
||||
{
|
||||
extern void list_mem(void);
|
||||
extern void list_memheap(void);
|
||||
|
||||
#ifdef RT_USING_MEMHEAP_AS_HEAP
|
||||
list_memheap();
|
||||
#else
|
||||
list_mem();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(cmd_free, __cmd_free, Show the memory usage in the system.);
|
||||
#endif
|
||||
|
||||
static int msh_split(char *cmd, rt_size_t length, char *argv[FINSH_ARG_MAX])
|
||||
{
|
||||
char *ptr;
|
||||
rt_size_t position;
|
||||
rt_size_t argc;
|
||||
rt_size_t i;
|
||||
|
||||
ptr = cmd;
|
||||
position = 0; argc = 0;
|
||||
|
||||
while (position < length)
|
||||
{
|
||||
/* strip bank and tab */
|
||||
while ((*ptr == ' ' || *ptr == '\t') && position < length)
|
||||
{
|
||||
*ptr = '\0';
|
||||
ptr ++; position ++;
|
||||
}
|
||||
|
||||
if(argc >= FINSH_ARG_MAX)
|
||||
{
|
||||
rt_kprintf("Too many args ! We only Use:\n");
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
rt_kprintf("%s ", argv[i]);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (position >= length) break;
|
||||
|
||||
/* handle string */
|
||||
if (*ptr == '"')
|
||||
{
|
||||
ptr ++; position ++;
|
||||
argv[argc] = ptr; argc ++;
|
||||
|
||||
/* skip this string */
|
||||
while (*ptr != '"' && position < length)
|
||||
{
|
||||
if (*ptr == '\\')
|
||||
{
|
||||
if (*(ptr + 1) == '"')
|
||||
{
|
||||
ptr ++; position ++;
|
||||
}
|
||||
}
|
||||
ptr ++; position ++;
|
||||
}
|
||||
if (position >= length) break;
|
||||
|
||||
/* skip '"' */
|
||||
*ptr = '\0'; ptr ++; position ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
argv[argc] = ptr;
|
||||
argc ++;
|
||||
while ((*ptr != ' ' && *ptr != '\t') && position < length)
|
||||
{
|
||||
ptr ++; position ++;
|
||||
}
|
||||
if (position >= length) break;
|
||||
}
|
||||
}
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
static cmd_function_t msh_get_cmd(char *cmd, int size)
|
||||
{
|
||||
struct finsh_syscall *index;
|
||||
cmd_function_t cmd_func = RT_NULL;
|
||||
|
||||
for (index = _syscall_table_begin;
|
||||
index < _syscall_table_end;
|
||||
FINSH_NEXT_SYSCALL(index))
|
||||
{
|
||||
if (strncmp(index->name, "__cmd_", 6) != 0) continue;
|
||||
|
||||
if (strncmp(&index->name[6], cmd, size) == 0 &&
|
||||
index->name[6 + size] == '\0')
|
||||
{
|
||||
cmd_func = (cmd_function_t)index->func;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_func;
|
||||
}
|
||||
|
||||
#if defined(RT_USING_MODULE) && defined(RT_USING_DFS)
|
||||
/* Return 0 on module executed. Other value indicate error.
|
||||
*/
|
||||
int msh_exec_module(const char *cmd_line, int size)
|
||||
{
|
||||
int ret;
|
||||
int fd = -1;
|
||||
char *pg_name;
|
||||
int length, cmd_length = 0;
|
||||
|
||||
if (size == 0)
|
||||
return -RT_ERROR;
|
||||
/* get the length of command0 */
|
||||
while ((cmd_line[cmd_length] != ' ' && cmd_line[cmd_length] != '\t') && cmd_length < size)
|
||||
cmd_length ++;
|
||||
|
||||
/* get name length */
|
||||
length = cmd_length + 32;
|
||||
|
||||
/* allocate program name memory */
|
||||
pg_name = (char *) rt_malloc(length);
|
||||
if (pg_name == RT_NULL)
|
||||
return -RT_ENOMEM;
|
||||
|
||||
/* copy command0 */
|
||||
memcpy(pg_name, cmd_line, cmd_length);
|
||||
pg_name[cmd_length] = '\0';
|
||||
|
||||
if (strstr(pg_name, ".mo") != RT_NULL || strstr(pg_name, ".MO") != RT_NULL)
|
||||
{
|
||||
/* try to open program */
|
||||
fd = open(pg_name, O_RDONLY, 0);
|
||||
|
||||
/* search in /bin path */
|
||||
if (fd < 0)
|
||||
{
|
||||
rt_snprintf(pg_name, length - 1, "/bin/%.*s", cmd_length, cmd_line);
|
||||
fd = open(pg_name, O_RDONLY, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add .mo and open program */
|
||||
|
||||
/* try to open program */
|
||||
strcat(pg_name, ".mo");
|
||||
fd = open(pg_name, O_RDONLY, 0);
|
||||
|
||||
/* search in /bin path */
|
||||
if (fd < 0)
|
||||
{
|
||||
rt_snprintf(pg_name, length - 1, "/bin/%.*s.mo", cmd_length, cmd_line);
|
||||
fd = open(pg_name, O_RDONLY, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (fd >= 0)
|
||||
{
|
||||
/* found program */
|
||||
close(fd);
|
||||
dlmodule_exec(pg_name, cmd_line, size);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
rt_free(pg_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int system(const char *command)
|
||||
{
|
||||
int ret = -RT_ENOMEM;
|
||||
char *cmd = rt_strdup(command);
|
||||
|
||||
if (cmd)
|
||||
{
|
||||
ret = msh_exec(cmd, rt_strlen(cmd));
|
||||
rt_free(cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int _msh_exec_cmd(char *cmd, rt_size_t length, int *retp)
|
||||
{
|
||||
int argc;
|
||||
rt_size_t cmd0_size = 0;
|
||||
cmd_function_t cmd_func;
|
||||
char *argv[FINSH_ARG_MAX];
|
||||
|
||||
RT_ASSERT(cmd);
|
||||
RT_ASSERT(retp);
|
||||
|
||||
/* find the size of first command */
|
||||
while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
|
||||
cmd0_size ++;
|
||||
if (cmd0_size == 0)
|
||||
return -RT_ERROR;
|
||||
|
||||
cmd_func = msh_get_cmd(cmd, cmd0_size);
|
||||
if (cmd_func == RT_NULL)
|
||||
return -RT_ERROR;
|
||||
|
||||
/* split arguments */
|
||||
memset(argv, 0x00, sizeof(argv));
|
||||
argc = msh_split(cmd, length, argv);
|
||||
if (argc == 0)
|
||||
return -RT_ERROR;
|
||||
|
||||
/* exec this command */
|
||||
*retp = cmd_func(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(RT_USING_LWP) && defined(RT_USING_DFS)
|
||||
static int _msh_exec_lwp(char *cmd, rt_size_t length)
|
||||
{
|
||||
int argc;
|
||||
int cmd0_size = 0;
|
||||
char *argv[FINSH_ARG_MAX];
|
||||
int fd = -1;
|
||||
char *pg_name;
|
||||
|
||||
extern int exec(char*, int, char**);
|
||||
|
||||
/* find the size of first command */
|
||||
while ((cmd[cmd0_size] != ' ' && cmd[cmd0_size] != '\t') && cmd0_size < length)
|
||||
cmd0_size ++;
|
||||
if (cmd0_size == 0)
|
||||
return -1;
|
||||
|
||||
/* split arguments */
|
||||
rt_memset(argv, 0x00, sizeof(argv));
|
||||
argc = msh_split(cmd, length, argv);
|
||||
if (argc == 0)
|
||||
return -1;
|
||||
|
||||
pg_name = argv[0];
|
||||
/* try to open program */
|
||||
fd = open(pg_name, O_RDONLY, 0);
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
/* found program */
|
||||
close(fd);
|
||||
exec(pg_name, argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int msh_exec(char *cmd, rt_size_t length)
|
||||
{
|
||||
int cmd_ret;
|
||||
|
||||
/* strim the beginning of command */
|
||||
while ((length > 0) && (*cmd == ' ' || *cmd == '\t'))
|
||||
{
|
||||
cmd++;
|
||||
length--;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
/* Exec sequence:
|
||||
* 1. built-in command
|
||||
* 2. module(if enabled)
|
||||
*/
|
||||
if (_msh_exec_cmd(cmd, length, &cmd_ret) == 0)
|
||||
{
|
||||
return cmd_ret;
|
||||
}
|
||||
#ifdef RT_USING_DFS
|
||||
#ifdef DFS_USING_WORKDIR
|
||||
if (msh_exec_script(cmd, length) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_MODULE
|
||||
if (msh_exec_module(cmd, length) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
if (_msh_exec_lwp(cmd, length) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* truncate the cmd at the first space. */
|
||||
{
|
||||
char *tcmd;
|
||||
tcmd = cmd;
|
||||
while (*tcmd != ' ' && *tcmd != '\0')
|
||||
{
|
||||
tcmd++;
|
||||
}
|
||||
*tcmd = '\0';
|
||||
}
|
||||
rt_kprintf("%s: command not found.\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int str_common(const char *str1, const char *str2)
|
||||
{
|
||||
const char *str = str1;
|
||||
|
||||
while ((*str != 0) && (*str2 != 0) && (*str == *str2))
|
||||
{
|
||||
str ++;
|
||||
str2 ++;
|
||||
}
|
||||
|
||||
return (str - str1);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
void msh_auto_complete_path(char *path)
|
||||
{
|
||||
DIR *dir = RT_NULL;
|
||||
struct dirent *dirent = RT_NULL;
|
||||
char *full_path, *ptr, *index;
|
||||
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
full_path = (char *)rt_malloc(256);
|
||||
if (full_path == RT_NULL) return; /* out of memory */
|
||||
|
||||
if (*path != '/')
|
||||
{
|
||||
getcwd(full_path, 256);
|
||||
if (full_path[rt_strlen(full_path) - 1] != '/')
|
||||
strcat(full_path, "/");
|
||||
}
|
||||
else *full_path = '\0';
|
||||
|
||||
index = RT_NULL;
|
||||
ptr = path;
|
||||
for (;;)
|
||||
{
|
||||
if (*ptr == '/') index = ptr + 1;
|
||||
if (!*ptr) break;
|
||||
|
||||
ptr ++;
|
||||
}
|
||||
if (index == RT_NULL) index = path;
|
||||
|
||||
if (index != RT_NULL)
|
||||
{
|
||||
char *dest = index;
|
||||
|
||||
/* fill the parent path */
|
||||
ptr = full_path;
|
||||
while (*ptr) ptr ++;
|
||||
|
||||
for (index = path; index != dest;)
|
||||
*ptr++ = *index++;
|
||||
*ptr = '\0';
|
||||
|
||||
dir = opendir(full_path);
|
||||
if (dir == RT_NULL) /* open directory failed! */
|
||||
{
|
||||
rt_free(full_path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* restore the index position */
|
||||
index = dest;
|
||||
}
|
||||
|
||||
/* auto complete the file or directory name */
|
||||
if (*index == '\0') /* display all of files and directories */
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
dirent = readdir(dir);
|
||||
if (dirent == RT_NULL) break;
|
||||
|
||||
rt_kprintf("%s\n", dirent->d_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_size_t length, min_length;
|
||||
|
||||
min_length = 0;
|
||||
for (;;)
|
||||
{
|
||||
dirent = readdir(dir);
|
||||
if (dirent == RT_NULL) break;
|
||||
|
||||
/* matched the prefix string */
|
||||
if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
|
||||
{
|
||||
if (min_length == 0)
|
||||
{
|
||||
min_length = rt_strlen(dirent->d_name);
|
||||
/* save dirent name */
|
||||
strcpy(full_path, dirent->d_name);
|
||||
}
|
||||
|
||||
length = str_common(dirent->d_name, full_path);
|
||||
|
||||
if (length < min_length)
|
||||
{
|
||||
min_length = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (min_length)
|
||||
{
|
||||
if (min_length < rt_strlen(full_path))
|
||||
{
|
||||
/* list the candidate */
|
||||
rewinddir(dir);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
dirent = readdir(dir);
|
||||
if (dirent == RT_NULL) break;
|
||||
|
||||
if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0)
|
||||
rt_kprintf("%s\n", dirent->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
length = index - path;
|
||||
memcpy(index, full_path, min_length);
|
||||
path[length + min_length] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
rt_free(full_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
void msh_auto_complete(char *prefix)
|
||||
{
|
||||
int length, min_length;
|
||||
const char *name_ptr, *cmd_name;
|
||||
struct finsh_syscall *index;
|
||||
|
||||
min_length = 0;
|
||||
name_ptr = RT_NULL;
|
||||
|
||||
if (*prefix == '\0')
|
||||
{
|
||||
msh_help(0, RT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
/* check whether a spare in the command */
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = prefix + rt_strlen(prefix);
|
||||
while (ptr != prefix)
|
||||
{
|
||||
if (*ptr == ' ')
|
||||
{
|
||||
msh_auto_complete_path(ptr + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
ptr --;
|
||||
}
|
||||
#ifdef RT_USING_MODULE
|
||||
/* There is a chance that the user want to run the module directly. So
|
||||
* try to complete the file names. If the completed path is not a
|
||||
* module, the system won't crash anyway. */
|
||||
if (ptr == prefix)
|
||||
{
|
||||
msh_auto_complete_path(ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* checks in internal command */
|
||||
{
|
||||
for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
|
||||
{
|
||||
/* skip finsh shell function */
|
||||
if (strncmp(index->name, "__cmd_", 6) != 0) continue;
|
||||
|
||||
cmd_name = (const char *) &index->name[6];
|
||||
if (strncmp(prefix, cmd_name, strlen(prefix)) == 0)
|
||||
{
|
||||
if (min_length == 0)
|
||||
{
|
||||
/* set name_ptr */
|
||||
name_ptr = cmd_name;
|
||||
/* set initial length */
|
||||
min_length = strlen(name_ptr);
|
||||
}
|
||||
|
||||
length = str_common(name_ptr, cmd_name);
|
||||
if (length < min_length)
|
||||
min_length = length;
|
||||
|
||||
rt_kprintf("%s\n", cmd_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* auto complete string */
|
||||
if (name_ptr != NULL)
|
||||
{
|
||||
rt_strncpy(prefix, name_ptr, min_length);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FINSH_USING_MSH */
|
23
source/rt_thread/components/finsh/msh.h
Normal file
23
source/rt_thread/components/finsh/msh.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-03-30 Bernard the first verion for FinSH
|
||||
*/
|
||||
|
||||
#ifndef __M_SHELL__
|
||||
#define __M_SHELL__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
rt_bool_t msh_is_used(void);
|
||||
int msh_exec(char *cmd, rt_size_t length);
|
||||
void msh_auto_complete(char *prefix);
|
||||
|
||||
int msh_exec_module(const char *cmd_line, int size);
|
||||
int msh_exec_script(const char *cmd_line, int size);
|
||||
|
||||
#endif
|
904
source/rt_thread/components/finsh/shell.c
Normal file
904
source/rt_thread/components/finsh/shell.c
Normal file
@@ -0,0 +1,904 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-04-30 Bernard the first version for FinSH
|
||||
* 2006-05-08 Bernard change finsh thread stack to 2048
|
||||
* 2006-06-03 Bernard add support for skyeye
|
||||
* 2006-09-24 Bernard remove the code related with hardware
|
||||
* 2010-01-18 Bernard fix down then up key bug.
|
||||
* 2010-03-19 Bernard fix backspace issue and fix device read in shell.
|
||||
* 2010-04-01 Bernard add prompt output when start and remove the empty history
|
||||
* 2011-02-23 Bernard fix variable section end issue of finsh shell
|
||||
* initialization when use GNU GCC compiler.
|
||||
* 2016-11-26 armink add password authentication
|
||||
* 2018-07-02 aozima add custome prompt support.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <finsh_config.h>
|
||||
|
||||
#ifdef RT_USING_FINSH
|
||||
|
||||
#include "finsh.h"
|
||||
#include "shell.h"
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
#include "msh.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <stdio.h> /* for putchar */
|
||||
#endif
|
||||
|
||||
/* finsh thread */
|
||||
#ifndef RT_USING_HEAP
|
||||
static struct rt_thread finsh_thread;
|
||||
ALIGN(RT_ALIGN_SIZE)
|
||||
static char finsh_thread_stack[FINSH_THREAD_STACK_SIZE];
|
||||
struct finsh_shell _shell;
|
||||
#endif
|
||||
|
||||
/* finsh symtab */
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
struct finsh_syscall *_syscall_table_begin = NULL;
|
||||
struct finsh_syscall *_syscall_table_end = NULL;
|
||||
struct finsh_sysvar *_sysvar_table_begin = NULL;
|
||||
struct finsh_sysvar *_sysvar_table_end = NULL;
|
||||
#endif
|
||||
|
||||
struct finsh_shell *shell;
|
||||
static char *finsh_prompt_custom = RT_NULL;
|
||||
|
||||
#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
|
||||
struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call)
|
||||
{
|
||||
unsigned int *ptr;
|
||||
ptr = (unsigned int*) (call + 1);
|
||||
while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _syscall_table_end))
|
||||
ptr ++;
|
||||
|
||||
return (struct finsh_syscall*)ptr;
|
||||
}
|
||||
|
||||
struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call)
|
||||
{
|
||||
unsigned int *ptr;
|
||||
ptr = (unsigned int*) (call + 1);
|
||||
while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _sysvar_table_end))
|
||||
ptr ++;
|
||||
|
||||
return (struct finsh_sysvar*)ptr;
|
||||
}
|
||||
#endif /* defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__)) */
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
int finsh_set_prompt(const char * prompt)
|
||||
{
|
||||
if(finsh_prompt_custom)
|
||||
{
|
||||
rt_free(finsh_prompt_custom);
|
||||
finsh_prompt_custom = RT_NULL;
|
||||
}
|
||||
|
||||
/* strdup */
|
||||
if(prompt)
|
||||
{
|
||||
finsh_prompt_custom = (char *)rt_malloc(strlen(prompt)+1);
|
||||
if(finsh_prompt_custom)
|
||||
{
|
||||
strcpy(finsh_prompt_custom, prompt);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
#if defined(RT_USING_DFS)
|
||||
#include <dfs_posix.h>
|
||||
#endif /* RT_USING_DFS */
|
||||
|
||||
const char *finsh_get_prompt()
|
||||
{
|
||||
#define _MSH_PROMPT "msh "
|
||||
#define _PROMPT "finsh "
|
||||
static char finsh_prompt[RT_CONSOLEBUF_SIZE + 1] = {0};
|
||||
|
||||
/* check prompt mode */
|
||||
if (!shell->prompt_mode)
|
||||
{
|
||||
finsh_prompt[0] = '\0';
|
||||
return finsh_prompt;
|
||||
}
|
||||
|
||||
if(finsh_prompt_custom)
|
||||
{
|
||||
strncpy(finsh_prompt, finsh_prompt_custom, sizeof(finsh_prompt)-1);
|
||||
return finsh_prompt;
|
||||
}
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
if (msh_is_used()) strcpy(finsh_prompt, _MSH_PROMPT);
|
||||
else
|
||||
#endif
|
||||
strcpy(finsh_prompt, _PROMPT);
|
||||
|
||||
#if defined(RT_USING_DFS) && defined(DFS_USING_WORKDIR)
|
||||
/* get current working directory */
|
||||
getcwd(&finsh_prompt[rt_strlen(finsh_prompt)], RT_CONSOLEBUF_SIZE - rt_strlen(finsh_prompt));
|
||||
#endif
|
||||
|
||||
strcat(finsh_prompt, ">");
|
||||
|
||||
return finsh_prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function get the prompt mode of finsh shell.
|
||||
*
|
||||
* @return prompt the prompt mode, 0 disable prompt mode, other values enable prompt mode.
|
||||
*/
|
||||
rt_uint32_t finsh_get_prompt_mode(void)
|
||||
{
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
return shell->prompt_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function set the prompt mode of finsh shell.
|
||||
*
|
||||
* The parameter 0 disable prompt mode, other values enable prompt mode.
|
||||
*
|
||||
* @param prompt the prompt mode
|
||||
*/
|
||||
void finsh_set_prompt_mode(rt_uint32_t prompt_mode)
|
||||
{
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
shell->prompt_mode = prompt_mode;
|
||||
}
|
||||
|
||||
static int finsh_getchar(void)
|
||||
{
|
||||
#ifdef RT_USING_DEVICE
|
||||
#ifdef RT_USING_POSIX
|
||||
return getchar();
|
||||
#else
|
||||
char ch = 0;
|
||||
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
|
||||
if(shell->device)
|
||||
{
|
||||
while (rt_device_read(shell->device, -1, &ch, 1) != 1)
|
||||
rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);
|
||||
|
||||
return (int)ch;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
extern char rt_hw_console_getchar(void);
|
||||
return rt_hw_console_getchar();
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE)
|
||||
static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size)
|
||||
{
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
|
||||
/* release semaphore to let finsh thread rx data */
|
||||
rt_sem_release(&shell->rx_sem);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function sets the input device of finsh shell.
|
||||
*
|
||||
* @param device_name the name of new input device.
|
||||
*/
|
||||
void finsh_set_device(const char *device_name)
|
||||
{
|
||||
rt_device_t dev = RT_NULL;
|
||||
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
dev = rt_device_find(device_name);
|
||||
if (dev == RT_NULL)
|
||||
{
|
||||
rt_kprintf("finsh: can not find device: %s\n", device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check whether it's a same device */
|
||||
if (dev == shell->device) return;
|
||||
/* open this device and set the new device in finsh shell */
|
||||
if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | \
|
||||
RT_DEVICE_FLAG_STREAM) == RT_EOK)
|
||||
{
|
||||
if (shell->device != RT_NULL)
|
||||
{
|
||||
/* close old finsh device */
|
||||
rt_device_close(shell->device);
|
||||
rt_device_set_rx_indicate(shell->device, RT_NULL);
|
||||
}
|
||||
|
||||
/* clear line buffer before switch to new device */
|
||||
memset(shell->line, 0, sizeof(shell->line));
|
||||
shell->line_curpos = shell->line_position = 0;
|
||||
|
||||
shell->device = dev;
|
||||
rt_device_set_rx_indicate(dev, finsh_rx_ind);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function returns current finsh shell input device.
|
||||
*
|
||||
* @return the finsh shell input device name is returned.
|
||||
*/
|
||||
const char *finsh_get_device()
|
||||
{
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
return shell->device->parent.name;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function set the echo mode of finsh shell.
|
||||
*
|
||||
* FINSH_OPTION_ECHO=0x01 is echo mode, other values are none-echo mode.
|
||||
*
|
||||
* @param echo the echo mode
|
||||
*/
|
||||
void finsh_set_echo(rt_uint32_t echo)
|
||||
{
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
shell->echo_mode = (rt_uint8_t)echo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function gets the echo mode of finsh shell.
|
||||
*
|
||||
* @return the echo mode
|
||||
*/
|
||||
rt_uint32_t finsh_get_echo()
|
||||
{
|
||||
RT_ASSERT(shell != RT_NULL);
|
||||
|
||||
return shell->echo_mode;
|
||||
}
|
||||
|
||||
#ifdef FINSH_USING_AUTH
|
||||
/**
|
||||
* set a new password for finsh
|
||||
*
|
||||
* @param password new password
|
||||
*
|
||||
* @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than
|
||||
* FINSH_PASSWORD_MIN or greater than FINSH_PASSWORD_MAX
|
||||
*/
|
||||
rt_err_t finsh_set_password(const char *password) {
|
||||
rt_ubase_t level;
|
||||
rt_size_t pw_len = rt_strlen(password);
|
||||
|
||||
if (pw_len < FINSH_PASSWORD_MIN || pw_len > FINSH_PASSWORD_MAX)
|
||||
return -RT_ERROR;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
rt_strncpy(shell->password, password, FINSH_PASSWORD_MAX);
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the finsh password
|
||||
*
|
||||
* @return password
|
||||
*/
|
||||
const char *finsh_get_password(void)
|
||||
{
|
||||
return shell->password;
|
||||
}
|
||||
|
||||
static void finsh_wait_auth(void)
|
||||
{
|
||||
int ch;
|
||||
rt_bool_t input_finish = RT_FALSE;
|
||||
char password[FINSH_PASSWORD_MAX] = { 0 };
|
||||
rt_size_t cur_pos = 0;
|
||||
/* password not set */
|
||||
if (rt_strlen(finsh_get_password()) == 0) return;
|
||||
|
||||
while (1)
|
||||
{
|
||||
rt_kprintf("Password for login: ");
|
||||
while (!input_finish)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
/* read one character from device */
|
||||
ch = finsh_getchar();
|
||||
if (ch < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch >= ' ' && ch <= '~' && cur_pos < FINSH_PASSWORD_MAX)
|
||||
{
|
||||
/* change the printable characters to '*' */
|
||||
rt_kprintf("*");
|
||||
password[cur_pos++] = ch;
|
||||
}
|
||||
else if (ch == '\b' && cur_pos > 0)
|
||||
{
|
||||
/* backspace */
|
||||
cur_pos--;
|
||||
password[cur_pos] = '\0';
|
||||
rt_kprintf("\b \b");
|
||||
}
|
||||
else if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
rt_kprintf("\n");
|
||||
input_finish = RT_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rt_strncmp(shell->password, password, FINSH_PASSWORD_MAX)) return;
|
||||
else
|
||||
{
|
||||
/* authentication failed, delay 2S for retry */
|
||||
rt_thread_delay(2 * RT_TICK_PER_SECOND);
|
||||
rt_kprintf("Sorry, try again.\n");
|
||||
cur_pos = 0;
|
||||
input_finish = RT_FALSE;
|
||||
rt_memset(password, '\0', FINSH_PASSWORD_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* FINSH_USING_AUTH */
|
||||
|
||||
static void shell_auto_complete(char *prefix)
|
||||
{
|
||||
|
||||
rt_kprintf("\n");
|
||||
#ifdef FINSH_USING_MSH
|
||||
if (msh_is_used() == RT_TRUE)
|
||||
{
|
||||
msh_auto_complete(prefix);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef FINSH_USING_MSH_ONLY
|
||||
extern void list_prefix(char * prefix);
|
||||
list_prefix(prefix);
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_kprintf("%s%s", FINSH_PROMPT, prefix);
|
||||
}
|
||||
|
||||
#ifndef FINSH_USING_MSH_ONLY
|
||||
void finsh_run_line(struct finsh_parser *parser, const char *line)
|
||||
{
|
||||
const char *err_str;
|
||||
|
||||
if(shell->echo_mode)
|
||||
rt_kprintf("\n");
|
||||
finsh_parser_run(parser, (unsigned char *)line);
|
||||
|
||||
/* compile node root */
|
||||
if (finsh_errno() == 0)
|
||||
{
|
||||
finsh_compiler_run(parser->root);
|
||||
}
|
||||
else
|
||||
{
|
||||
err_str = finsh_error_string(finsh_errno());
|
||||
rt_kprintf("%s\n", err_str);
|
||||
}
|
||||
|
||||
/* run virtual machine */
|
||||
if (finsh_errno() == 0)
|
||||
{
|
||||
char ch;
|
||||
finsh_vm_run();
|
||||
|
||||
ch = (unsigned char)finsh_stack_bottom();
|
||||
if (ch > 0x20 && ch < 0x7e)
|
||||
{
|
||||
rt_kprintf("\t'%c', %d, 0x%08x\n",
|
||||
(unsigned char)finsh_stack_bottom(),
|
||||
(unsigned int)finsh_stack_bottom(),
|
||||
(unsigned int)finsh_stack_bottom());
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("\t%d, 0x%08x\n",
|
||||
(unsigned int)finsh_stack_bottom(),
|
||||
(unsigned int)finsh_stack_bottom());
|
||||
}
|
||||
}
|
||||
|
||||
finsh_flush(parser);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
static rt_bool_t shell_handle_history(struct finsh_shell *shell)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
int i;
|
||||
rt_kprintf("\r");
|
||||
|
||||
for (i = 0; i <= 60; i++)
|
||||
putchar(' ');
|
||||
rt_kprintf("\r");
|
||||
|
||||
#else
|
||||
rt_kprintf("\033[2K\r");
|
||||
#endif
|
||||
rt_kprintf("%s%s", FINSH_PROMPT, shell->line);
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
static void shell_push_history(struct finsh_shell *shell)
|
||||
{
|
||||
if (shell->line_position != 0)
|
||||
{
|
||||
/* push history */
|
||||
if (shell->history_count >= FINSH_HISTORY_LINES)
|
||||
{
|
||||
/* if current cmd is same as last cmd, don't push */
|
||||
if (memcmp(&shell->cmd_history[FINSH_HISTORY_LINES - 1], shell->line, FINSH_CMD_SIZE))
|
||||
{
|
||||
/* move history */
|
||||
int index;
|
||||
for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
|
||||
{
|
||||
memcpy(&shell->cmd_history[index][0],
|
||||
&shell->cmd_history[index + 1][0], FINSH_CMD_SIZE);
|
||||
}
|
||||
memset(&shell->cmd_history[index][0], 0, FINSH_CMD_SIZE);
|
||||
memcpy(&shell->cmd_history[index][0], shell->line, shell->line_position);
|
||||
|
||||
/* it's the maximum history */
|
||||
shell->history_count = FINSH_HISTORY_LINES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if current cmd is same as last cmd, don't push */
|
||||
if (shell->history_count == 0 || memcmp(&shell->cmd_history[shell->history_count - 1], shell->line, FINSH_CMD_SIZE))
|
||||
{
|
||||
shell->current_history = shell->history_count;
|
||||
memset(&shell->cmd_history[shell->history_count][0], 0, FINSH_CMD_SIZE);
|
||||
memcpy(&shell->cmd_history[shell->history_count][0], shell->line, shell->line_position);
|
||||
|
||||
/* increase count and set current history position */
|
||||
shell->history_count ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
shell->current_history = shell->history_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
void finsh_thread_entry(void *parameter)
|
||||
{
|
||||
int ch;
|
||||
|
||||
/* normal is echo mode */
|
||||
#ifndef FINSH_ECHO_DISABLE_DEFAULT
|
||||
shell->echo_mode = 1;
|
||||
#else
|
||||
shell->echo_mode = 0;
|
||||
#endif
|
||||
|
||||
#ifndef FINSH_USING_MSH_ONLY
|
||||
finsh_init(&shell->parser);
|
||||
#endif
|
||||
|
||||
#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE)
|
||||
/* set console device as shell device */
|
||||
if (shell->device == RT_NULL)
|
||||
{
|
||||
rt_device_t console = rt_console_get_device();
|
||||
if (console)
|
||||
{
|
||||
finsh_set_device(console->parent.name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FINSH_USING_AUTH
|
||||
/* set the default password when the password isn't setting */
|
||||
if (rt_strlen(finsh_get_password()) == 0)
|
||||
{
|
||||
if (finsh_set_password(FINSH_DEFAULT_PASSWORD) != RT_EOK)
|
||||
{
|
||||
rt_kprintf("Finsh password set failed.\n");
|
||||
}
|
||||
}
|
||||
/* waiting authenticate success */
|
||||
finsh_wait_auth();
|
||||
#endif
|
||||
|
||||
rt_kprintf(FINSH_PROMPT);
|
||||
|
||||
while (1)
|
||||
{
|
||||
ch = finsh_getchar();
|
||||
if (ch < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle control key
|
||||
* up key : 0x1b 0x5b 0x41
|
||||
* down key: 0x1b 0x5b 0x42
|
||||
* right key:0x1b 0x5b 0x43
|
||||
* left key: 0x1b 0x5b 0x44
|
||||
*/
|
||||
if (ch == 0x1b)
|
||||
{
|
||||
shell->stat = WAIT_SPEC_KEY;
|
||||
continue;
|
||||
}
|
||||
else if (shell->stat == WAIT_SPEC_KEY)
|
||||
{
|
||||
if (ch == 0x5b)
|
||||
{
|
||||
shell->stat = WAIT_FUNC_KEY;
|
||||
continue;
|
||||
}
|
||||
|
||||
shell->stat = WAIT_NORMAL;
|
||||
}
|
||||
else if (shell->stat == WAIT_FUNC_KEY)
|
||||
{
|
||||
shell->stat = WAIT_NORMAL;
|
||||
|
||||
if (ch == 0x41) /* up key */
|
||||
{
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
/* prev history */
|
||||
if (shell->current_history > 0)
|
||||
shell->current_history --;
|
||||
else
|
||||
{
|
||||
shell->current_history = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy the history command */
|
||||
memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
|
||||
FINSH_CMD_SIZE);
|
||||
shell->line_curpos = shell->line_position = strlen(shell->line);
|
||||
shell_handle_history(shell);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
else if (ch == 0x42) /* down key */
|
||||
{
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
/* next history */
|
||||
if (shell->current_history < shell->history_count - 1)
|
||||
shell->current_history ++;
|
||||
else
|
||||
{
|
||||
/* set to the end of history */
|
||||
if (shell->history_count != 0)
|
||||
shell->current_history = shell->history_count - 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
|
||||
FINSH_CMD_SIZE);
|
||||
shell->line_curpos = shell->line_position = strlen(shell->line);
|
||||
shell_handle_history(shell);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
else if (ch == 0x44) /* left key */
|
||||
{
|
||||
if (shell->line_curpos)
|
||||
{
|
||||
rt_kprintf("\b");
|
||||
shell->line_curpos --;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (ch == 0x43) /* right key */
|
||||
{
|
||||
if (shell->line_curpos < shell->line_position)
|
||||
{
|
||||
rt_kprintf("%c", shell->line[shell->line_curpos]);
|
||||
shell->line_curpos ++;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* received null or error */
|
||||
if (ch == '\0' || ch == 0xFF) continue;
|
||||
/* handle tab key */
|
||||
else if (ch == '\t')
|
||||
{
|
||||
int i;
|
||||
/* move the cursor to the beginning of line */
|
||||
for (i = 0; i < shell->line_curpos; i++)
|
||||
rt_kprintf("\b");
|
||||
|
||||
/* auto complete */
|
||||
shell_auto_complete(&shell->line[0]);
|
||||
/* re-calculate position */
|
||||
shell->line_curpos = shell->line_position = strlen(shell->line);
|
||||
|
||||
continue;
|
||||
}
|
||||
/* handle backspace key */
|
||||
else if (ch == 0x7f || ch == 0x08)
|
||||
{
|
||||
/* note that shell->line_curpos >= 0 */
|
||||
if (shell->line_curpos == 0)
|
||||
continue;
|
||||
|
||||
shell->line_position--;
|
||||
shell->line_curpos--;
|
||||
|
||||
if (shell->line_position > shell->line_curpos)
|
||||
{
|
||||
int i;
|
||||
|
||||
rt_memmove(&shell->line[shell->line_curpos],
|
||||
&shell->line[shell->line_curpos + 1],
|
||||
shell->line_position - shell->line_curpos);
|
||||
shell->line[shell->line_position] = 0;
|
||||
|
||||
rt_kprintf("\b%s \b", &shell->line[shell->line_curpos]);
|
||||
|
||||
/* move the cursor to the origin position */
|
||||
for (i = shell->line_curpos; i <= shell->line_position; i++)
|
||||
rt_kprintf("\b");
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("\b \b");
|
||||
shell->line[shell->line_position] = 0;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* handle end of line, break */
|
||||
if (ch == '\r' || ch == '\n')
|
||||
{
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
shell_push_history(shell);
|
||||
#endif
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
if (msh_is_used() == RT_TRUE)
|
||||
{
|
||||
if (shell->echo_mode)
|
||||
rt_kprintf("\n");
|
||||
msh_exec(shell->line, shell->line_position);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef FINSH_USING_MSH_ONLY
|
||||
/* add ';' and run the command line */
|
||||
shell->line[shell->line_position] = ';';
|
||||
|
||||
if (shell->line_position != 0) finsh_run_line(&shell->parser, shell->line);
|
||||
else
|
||||
if (shell->echo_mode) rt_kprintf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_kprintf(FINSH_PROMPT);
|
||||
memset(shell->line, 0, sizeof(shell->line));
|
||||
shell->line_curpos = shell->line_position = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* it's a large line, discard it */
|
||||
if (shell->line_position >= FINSH_CMD_SIZE)
|
||||
shell->line_position = 0;
|
||||
|
||||
/* normal character */
|
||||
if (shell->line_curpos < shell->line_position)
|
||||
{
|
||||
int i;
|
||||
|
||||
rt_memmove(&shell->line[shell->line_curpos + 1],
|
||||
&shell->line[shell->line_curpos],
|
||||
shell->line_position - shell->line_curpos);
|
||||
shell->line[shell->line_curpos] = ch;
|
||||
if (shell->echo_mode)
|
||||
rt_kprintf("%s", &shell->line[shell->line_curpos]);
|
||||
|
||||
/* move the cursor to new position */
|
||||
for (i = shell->line_curpos; i < shell->line_position; i++)
|
||||
rt_kprintf("\b");
|
||||
}
|
||||
else
|
||||
{
|
||||
shell->line[shell->line_position] = ch;
|
||||
if (shell->echo_mode)
|
||||
rt_kprintf("%c", ch);
|
||||
}
|
||||
|
||||
ch = 0;
|
||||
shell->line_position ++;
|
||||
shell->line_curpos++;
|
||||
if (shell->line_position >= FINSH_CMD_SIZE)
|
||||
{
|
||||
/* clear command line */
|
||||
shell->line_position = 0;
|
||||
shell->line_curpos = 0;
|
||||
}
|
||||
} /* end of device read */
|
||||
}
|
||||
|
||||
void finsh_system_function_init(const void *begin, const void *end)
|
||||
{
|
||||
_syscall_table_begin = (struct finsh_syscall *) begin;
|
||||
_syscall_table_end = (struct finsh_syscall *) end;
|
||||
}
|
||||
|
||||
void finsh_system_var_init(const void *begin, const void *end)
|
||||
{
|
||||
_sysvar_table_begin = (struct finsh_sysvar *) begin;
|
||||
_sysvar_table_end = (struct finsh_sysvar *) end;
|
||||
}
|
||||
|
||||
#if defined(__ICCARM__) || defined(__ICCRX__) /* for IAR compiler */
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
#pragma section="FSymTab"
|
||||
#pragma section="VSymTab"
|
||||
#endif
|
||||
#elif defined(__ADSPBLACKFIN__) /* for VisaulDSP++ Compiler*/
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
extern "asm" int __fsymtab_start;
|
||||
extern "asm" int __fsymtab_end;
|
||||
extern "asm" int __vsymtab_start;
|
||||
extern "asm" int __vsymtab_end;
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma section("FSymTab$a", read)
|
||||
const char __fsym_begin_name[] = "__start";
|
||||
const char __fsym_begin_desc[] = "begin of finsh";
|
||||
__declspec(allocate("FSymTab$a")) const struct finsh_syscall __fsym_begin =
|
||||
{
|
||||
__fsym_begin_name,
|
||||
__fsym_begin_desc,
|
||||
NULL
|
||||
};
|
||||
|
||||
#pragma section("FSymTab$z", read)
|
||||
const char __fsym_end_name[] = "__end";
|
||||
const char __fsym_end_desc[] = "end of finsh";
|
||||
__declspec(allocate("FSymTab$z")) const struct finsh_syscall __fsym_end =
|
||||
{
|
||||
__fsym_end_name,
|
||||
__fsym_end_desc,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @ingroup finsh
|
||||
*
|
||||
* This function will initialize finsh shell
|
||||
*/
|
||||
int finsh_system_init(void)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
rt_thread_t tid;
|
||||
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */
|
||||
extern const int FSymTab$$Base;
|
||||
extern const int FSymTab$$Limit;
|
||||
extern const int VSymTab$$Base;
|
||||
extern const int VSymTab$$Limit;
|
||||
finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit);
|
||||
#ifndef FINSH_USING_MSH_ONLY
|
||||
finsh_system_var_init(&VSymTab$$Base, &VSymTab$$Limit);
|
||||
#endif
|
||||
#elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */
|
||||
finsh_system_function_init(__section_begin("FSymTab"),
|
||||
__section_end("FSymTab"));
|
||||
finsh_system_var_init(__section_begin("VSymTab"),
|
||||
__section_end("VSymTab"));
|
||||
#elif defined (__GNUC__) || defined(__TI_COMPILER_VERSION__)
|
||||
/* GNU GCC Compiler and TI CCS */
|
||||
extern const int __fsymtab_start;
|
||||
extern const int __fsymtab_end;
|
||||
extern const int __vsymtab_start;
|
||||
extern const int __vsymtab_end;
|
||||
finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
|
||||
finsh_system_var_init(&__vsymtab_start, &__vsymtab_end);
|
||||
#elif defined(__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */
|
||||
finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
|
||||
finsh_system_var_init(&__vsymtab_start, &__vsymtab_end);
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned int *ptr_begin, *ptr_end;
|
||||
|
||||
if(shell)
|
||||
{
|
||||
rt_kprintf("finsh shell already init.\n");
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
ptr_begin = (unsigned int *)&__fsym_begin;
|
||||
ptr_begin += (sizeof(struct finsh_syscall) / sizeof(unsigned int));
|
||||
while (*ptr_begin == 0) ptr_begin ++;
|
||||
|
||||
ptr_end = (unsigned int *) &__fsym_end;
|
||||
ptr_end --;
|
||||
while (*ptr_end == 0) ptr_end --;
|
||||
|
||||
finsh_system_function_init(ptr_begin, ptr_end);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
/* create or set shell structure */
|
||||
shell = (struct finsh_shell *)rt_calloc(1, sizeof(struct finsh_shell));
|
||||
if (shell == RT_NULL)
|
||||
{
|
||||
rt_kprintf("no memory for shell\n");
|
||||
return -1;
|
||||
}
|
||||
tid = rt_thread_create(FINSH_THREAD_NAME,
|
||||
finsh_thread_entry, RT_NULL,
|
||||
FINSH_THREAD_STACK_SIZE, FINSH_THREAD_PRIORITY, 10);
|
||||
#else
|
||||
shell = &_shell;
|
||||
tid = &finsh_thread;
|
||||
result = rt_thread_init(&finsh_thread,
|
||||
FINSH_THREAD_NAME,
|
||||
finsh_thread_entry, RT_NULL,
|
||||
&finsh_thread_stack[0], sizeof(finsh_thread_stack),
|
||||
FINSH_THREAD_PRIORITY, 10);
|
||||
#endif /* RT_USING_HEAP */
|
||||
|
||||
rt_sem_init(&(shell->rx_sem), "shrx", 0, 0);
|
||||
finsh_set_prompt_mode(1);
|
||||
|
||||
if (tid != NULL && result == RT_EOK)
|
||||
rt_thread_startup(tid);
|
||||
return 0;
|
||||
}
|
||||
INIT_APP_EXPORT(finsh_system_init);
|
||||
|
||||
#endif /* RT_USING_FINSH */
|
||||
|
110
source/rt_thread/components/finsh/shell.h
Normal file
110
source/rt_thread/components/finsh/shell.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-06-02 Bernard Add finsh_get_prompt function declaration
|
||||
*/
|
||||
|
||||
#ifndef __SHELL_H__
|
||||
#define __SHELL_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "finsh.h"
|
||||
|
||||
#ifndef FINSH_THREAD_PRIORITY
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
#endif
|
||||
#ifndef FINSH_THREAD_STACK_SIZE
|
||||
#define FINSH_THREAD_STACK_SIZE 2048
|
||||
#endif
|
||||
#ifndef FINSH_CMD_SIZE
|
||||
#define FINSH_CMD_SIZE 80
|
||||
#endif
|
||||
|
||||
#define FINSH_OPTION_ECHO 0x01
|
||||
|
||||
#define FINSH_PROMPT finsh_get_prompt()
|
||||
const char* finsh_get_prompt(void);
|
||||
int finsh_set_prompt(const char * prompt);
|
||||
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
#ifndef FINSH_HISTORY_LINES
|
||||
#define FINSH_HISTORY_LINES 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FINSH_USING_AUTH
|
||||
#ifndef FINSH_PASSWORD_MAX
|
||||
#define FINSH_PASSWORD_MAX RT_NAME_MAX
|
||||
#endif
|
||||
#ifndef FINSH_PASSWORD_MIN
|
||||
#define FINSH_PASSWORD_MIN 6
|
||||
#endif
|
||||
#ifndef FINSH_DEFAULT_PASSWORD
|
||||
#define FINSH_DEFAULT_PASSWORD "rtthread"
|
||||
#endif
|
||||
#endif /* FINSH_USING_AUTH */
|
||||
|
||||
#ifndef FINSH_THREAD_NAME
|
||||
#define FINSH_THREAD_NAME "tshell"
|
||||
#endif
|
||||
|
||||
enum input_stat
|
||||
{
|
||||
WAIT_NORMAL,
|
||||
WAIT_SPEC_KEY,
|
||||
WAIT_FUNC_KEY,
|
||||
};
|
||||
struct finsh_shell
|
||||
{
|
||||
struct rt_semaphore rx_sem;
|
||||
|
||||
enum input_stat stat;
|
||||
|
||||
rt_uint8_t echo_mode:1;
|
||||
rt_uint8_t prompt_mode: 1;
|
||||
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
rt_uint16_t current_history;
|
||||
rt_uint16_t history_count;
|
||||
|
||||
char cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE];
|
||||
#endif
|
||||
|
||||
#ifndef FINSH_USING_MSH_ONLY
|
||||
struct finsh_parser parser;
|
||||
#endif
|
||||
|
||||
char line[FINSH_CMD_SIZE];
|
||||
rt_uint16_t line_position;
|
||||
rt_uint16_t line_curpos;
|
||||
|
||||
#if !defined(RT_USING_POSIX) && defined(RT_USING_DEVICE)
|
||||
rt_device_t device;
|
||||
#endif
|
||||
|
||||
#ifdef FINSH_USING_AUTH
|
||||
char password[FINSH_PASSWORD_MAX];
|
||||
#endif
|
||||
};
|
||||
|
||||
void finsh_set_echo(rt_uint32_t echo);
|
||||
rt_uint32_t finsh_get_echo(void);
|
||||
|
||||
int finsh_system_init(void);
|
||||
void finsh_set_device(const char* device_name);
|
||||
const char* finsh_get_device(void);
|
||||
|
||||
rt_uint32_t finsh_get_prompt_mode(void);
|
||||
void finsh_set_prompt_mode(rt_uint32_t prompt_mode);
|
||||
|
||||
#ifdef FINSH_USING_AUTH
|
||||
rt_err_t finsh_set_password(const char *password);
|
||||
const char *finsh_get_password(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user