10d163575Sopenharmony_ci/* 20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 40d163575Sopenharmony_ci * 50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 60d163575Sopenharmony_ci * are permitted provided that the following conditions are met: 70d163575Sopenharmony_ci * 80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 90d163575Sopenharmony_ci * conditions and the following disclaimer. 100d163575Sopenharmony_ci * 110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 120d163575Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 130d163575Sopenharmony_ci * provided with the distribution. 140d163575Sopenharmony_ci * 150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 160d163575Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 170d163575Sopenharmony_ci * permission. 180d163575Sopenharmony_ci * 190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 300d163575Sopenharmony_ci */ 310d163575Sopenharmony_ci 320d163575Sopenharmony_ci#include "telnet_dev.h" 330d163575Sopenharmony_ci#ifdef LOSCFG_NET_TELNET 340d163575Sopenharmony_ci#include "unistd.h" 350d163575Sopenharmony_ci#include "stdlib.h" 360d163575Sopenharmony_ci#include "sys/ioctl.h" 370d163575Sopenharmony_ci#include "sys/types.h" 380d163575Sopenharmony_ci#include "pthread.h" 390d163575Sopenharmony_ci 400d163575Sopenharmony_ci#include "los_printf.h" 410d163575Sopenharmony_ci#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE 420d163575Sopenharmony_ci#include "los_swtmr_pri.h" 430d163575Sopenharmony_ci#endif 440d163575Sopenharmony_ci#include "los_sched_pri.h" 450d163575Sopenharmony_ci#include "console.h" 460d163575Sopenharmony_ci#include "lwip/opt.h" 470d163575Sopenharmony_ci#include "lwip/sockets.h" 480d163575Sopenharmony_ci#include "telnet_pri.h" 490d163575Sopenharmony_ci 500d163575Sopenharmony_ci#include "fs/driver.h" 510d163575Sopenharmony_ci 520d163575Sopenharmony_ci/* event: there are more commands left in the FIFO to run */ 530d163575Sopenharmony_ci#define TELNET_EVENT_MORE_CMD 0x01 540d163575Sopenharmony_ci#define TELNET_DEV_DRV_MODE 0666 550d163575Sopenharmony_ci 560d163575Sopenharmony_ciSTATIC TELNET_DEV_S g_telnetDev; 570d163575Sopenharmony_ciSTATIC EVENT_CB_S *g_event; 580d163575Sopenharmony_ciSTATIC struct Vnode *g_currentVnode; 590d163575Sopenharmony_ci 600d163575Sopenharmony_ciSTATIC INLINE TELNET_DEV_S *GetTelnetDevByFile(const struct file *file, BOOL isOpenOp) 610d163575Sopenharmony_ci{ 620d163575Sopenharmony_ci struct Vnode *telnetInode = NULL; 630d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 640d163575Sopenharmony_ci 650d163575Sopenharmony_ci if (file == NULL) { 660d163575Sopenharmony_ci return NULL; 670d163575Sopenharmony_ci } 680d163575Sopenharmony_ci telnetInode = file->f_vnode; 690d163575Sopenharmony_ci if (telnetInode == NULL) { 700d163575Sopenharmony_ci return NULL; 710d163575Sopenharmony_ci } 720d163575Sopenharmony_ci /* 730d163575Sopenharmony_ci * Check if the f_vnode is valid here for non-open ops (open is supposed to get invalid f_vnode): 740d163575Sopenharmony_ci * when telnet is disconnected, there still may be 'TelentShellTask' tasks trying to write 750d163575Sopenharmony_ci * to the file, but the file has illegal f_vnode because the file is used by others. 760d163575Sopenharmony_ci */ 770d163575Sopenharmony_ci if (!isOpenOp) { 780d163575Sopenharmony_ci if (telnetInode != g_currentVnode) { 790d163575Sopenharmony_ci return NULL; 800d163575Sopenharmony_ci } 810d163575Sopenharmony_ci } 820d163575Sopenharmony_ci telnetDev = (TELNET_DEV_S *)((struct drv_data*)telnetInode->data)->priv; 830d163575Sopenharmony_ci return telnetDev; 840d163575Sopenharmony_ci} 850d163575Sopenharmony_ci 860d163575Sopenharmony_ci/* 870d163575Sopenharmony_ci * Description : When receive user's input commands, first copy commands to the FIFO of the telnet device. 880d163575Sopenharmony_ci * Then, notify a command resolver task (an individual shell task) to take out and run commands. 890d163575Sopenharmony_ci * Return : -1 --- On failure 900d163575Sopenharmony_ci * Non-negative integer --- length of written commands 910d163575Sopenharmony_ci */ 920d163575Sopenharmony_ciINT32 TelnetTx(const CHAR *buf, UINT32 bufLen) 930d163575Sopenharmony_ci{ 940d163575Sopenharmony_ci UINT32 i; 950d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 960d163575Sopenharmony_ci 970d163575Sopenharmony_ci TelnetLock(); 980d163575Sopenharmony_ci 990d163575Sopenharmony_ci telnetDev = &g_telnetDev; 1000d163575Sopenharmony_ci if ((buf == NULL) || (telnetDev->cmdFifo == NULL)) { 1010d163575Sopenharmony_ci TelnetUnlock(); 1020d163575Sopenharmony_ci return -1; 1030d163575Sopenharmony_ci } 1040d163575Sopenharmony_ci 1050d163575Sopenharmony_ci /* size limited */ 1060d163575Sopenharmony_ci if (bufLen > telnetDev->cmdFifo->fifoNum) { 1070d163575Sopenharmony_ci bufLen = telnetDev->cmdFifo->fifoNum; 1080d163575Sopenharmony_ci } 1090d163575Sopenharmony_ci 1100d163575Sopenharmony_ci if (bufLen == 0) { 1110d163575Sopenharmony_ci TelnetUnlock(); 1120d163575Sopenharmony_ci return 0; 1130d163575Sopenharmony_ci } 1140d163575Sopenharmony_ci 1150d163575Sopenharmony_ci /* copy commands to the fifo of the telnet device */ 1160d163575Sopenharmony_ci for (i = 0; i < bufLen; i++) { 1170d163575Sopenharmony_ci telnetDev->cmdFifo->rxBuf[telnetDev->cmdFifo->rxIndex] = *buf; 1180d163575Sopenharmony_ci telnetDev->cmdFifo->rxIndex++; 1190d163575Sopenharmony_ci telnetDev->cmdFifo->rxIndex %= FIFO_MAX; 1200d163575Sopenharmony_ci buf++; 1210d163575Sopenharmony_ci } 1220d163575Sopenharmony_ci telnetDev->cmdFifo->fifoNum -= bufLen; 1230d163575Sopenharmony_ci 1240d163575Sopenharmony_ci if (telnetDev->eventPend) { 1250d163575Sopenharmony_ci /* signal that there are some works to do */ 1260d163575Sopenharmony_ci (VOID)LOS_EventWrite(&telnetDev->eventTelnet, TELNET_EVENT_MORE_CMD); 1270d163575Sopenharmony_ci } 1280d163575Sopenharmony_ci /* notify the command resolver task */ 1290d163575Sopenharmony_ci notify_poll(&telnetDev->wait); 1300d163575Sopenharmony_ci TelnetUnlock(); 1310d163575Sopenharmony_ci 1320d163575Sopenharmony_ci return (INT32)bufLen; 1330d163575Sopenharmony_ci} 1340d163575Sopenharmony_ci 1350d163575Sopenharmony_ci/* 1360d163575Sopenharmony_ci * Description : When open the telnet device, init the FIFO, wait queue etc. 1370d163575Sopenharmony_ci */ 1380d163575Sopenharmony_ciSTATIC INT32 TelnetOpen(struct file *file) 1390d163575Sopenharmony_ci{ 1400d163575Sopenharmony_ci struct wait_queue_head *wait = NULL; 1410d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 1420d163575Sopenharmony_ci 1430d163575Sopenharmony_ci TelnetLock(); 1440d163575Sopenharmony_ci 1450d163575Sopenharmony_ci telnetDev = GetTelnetDevByFile(file, TRUE); 1460d163575Sopenharmony_ci if (telnetDev == NULL) { 1470d163575Sopenharmony_ci TelnetUnlock(); 1480d163575Sopenharmony_ci return -1; 1490d163575Sopenharmony_ci } 1500d163575Sopenharmony_ci 1510d163575Sopenharmony_ci if (telnetDev->cmdFifo == NULL) { 1520d163575Sopenharmony_ci wait = &telnetDev->wait; 1530d163575Sopenharmony_ci (VOID)LOS_EventInit(&telnetDev->eventTelnet); 1540d163575Sopenharmony_ci g_event = &telnetDev->eventTelnet; 1550d163575Sopenharmony_ci telnetDev->cmdFifo = (TELNTE_FIFO_S *)malloc(sizeof(TELNTE_FIFO_S)); 1560d163575Sopenharmony_ci if (telnetDev->cmdFifo == NULL) { 1570d163575Sopenharmony_ci TelnetUnlock(); 1580d163575Sopenharmony_ci return -1; 1590d163575Sopenharmony_ci } 1600d163575Sopenharmony_ci (VOID)memset_s(telnetDev->cmdFifo, sizeof(TELNTE_FIFO_S), 0, sizeof(TELNTE_FIFO_S)); 1610d163575Sopenharmony_ci telnetDev->cmdFifo->fifoNum = FIFO_MAX; 1620d163575Sopenharmony_ci LOS_ListInit(&wait->poll_queue); 1630d163575Sopenharmony_ci } 1640d163575Sopenharmony_ci g_currentVnode = file->f_vnode; 1650d163575Sopenharmony_ci TelnetUnlock(); 1660d163575Sopenharmony_ci return 0; 1670d163575Sopenharmony_ci} 1680d163575Sopenharmony_ci 1690d163575Sopenharmony_ci/* 1700d163575Sopenharmony_ci * Description : When close the telnet device, free the FIFO, wait queue etc. 1710d163575Sopenharmony_ci */ 1720d163575Sopenharmony_ciSTATIC INT32 TelnetClose(struct file *file) 1730d163575Sopenharmony_ci{ 1740d163575Sopenharmony_ci struct wait_queue_head *wait = NULL; 1750d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 1760d163575Sopenharmony_ci 1770d163575Sopenharmony_ci TelnetLock(); 1780d163575Sopenharmony_ci 1790d163575Sopenharmony_ci telnetDev = GetTelnetDevByFile(file, FALSE); 1800d163575Sopenharmony_ci if (telnetDev != NULL) { 1810d163575Sopenharmony_ci wait = &telnetDev->wait; 1820d163575Sopenharmony_ci LOS_ListDelete(&wait->poll_queue); 1830d163575Sopenharmony_ci free(telnetDev->cmdFifo); 1840d163575Sopenharmony_ci telnetDev->cmdFifo = NULL; 1850d163575Sopenharmony_ci (VOID)LOS_EventDestroy(&telnetDev->eventTelnet); 1860d163575Sopenharmony_ci g_event = NULL; 1870d163575Sopenharmony_ci } 1880d163575Sopenharmony_ci g_currentVnode = NULL; 1890d163575Sopenharmony_ci TelnetUnlock(); 1900d163575Sopenharmony_ci return 0; 1910d163575Sopenharmony_ci} 1920d163575Sopenharmony_ci 1930d163575Sopenharmony_ci/* 1940d163575Sopenharmony_ci * Description : When a command resolver task tries to read the telnet device, 1950d163575Sopenharmony_ci * this method is called, and it will take out user's commands from the FIFO to run. 1960d163575Sopenharmony_ci * Return : -1 --- On failure 1970d163575Sopenharmony_ci * Non-negative integer --- length of commands taken out from the FIFO of the telnet device. 1980d163575Sopenharmony_ci */ 1990d163575Sopenharmony_ciSTATIC ssize_t TelnetRead(struct file *file, CHAR *buf, size_t bufLen) 2000d163575Sopenharmony_ci{ 2010d163575Sopenharmony_ci UINT32 i; 2020d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 2030d163575Sopenharmony_ci 2040d163575Sopenharmony_ci TelnetLock(); 2050d163575Sopenharmony_ci 2060d163575Sopenharmony_ci telnetDev = GetTelnetDevByFile(file, FALSE); 2070d163575Sopenharmony_ci if ((buf == NULL) || (telnetDev == NULL) || (telnetDev->cmdFifo == NULL)) { 2080d163575Sopenharmony_ci TelnetUnlock(); 2090d163575Sopenharmony_ci return -1; 2100d163575Sopenharmony_ci } 2110d163575Sopenharmony_ci 2120d163575Sopenharmony_ci if (telnetDev->eventPend) { 2130d163575Sopenharmony_ci TelnetUnlock(); 2140d163575Sopenharmony_ci (VOID)LOS_EventRead(g_event, TELNET_EVENT_MORE_CMD, LOS_WAITMODE_OR, LOS_WAIT_FOREVER); 2150d163575Sopenharmony_ci TelnetLock(); 2160d163575Sopenharmony_ci } 2170d163575Sopenharmony_ci 2180d163575Sopenharmony_ci if (bufLen > (FIFO_MAX - telnetDev->cmdFifo->fifoNum)) { 2190d163575Sopenharmony_ci bufLen = FIFO_MAX - telnetDev->cmdFifo->fifoNum; 2200d163575Sopenharmony_ci } 2210d163575Sopenharmony_ci 2220d163575Sopenharmony_ci for (i = 0; i < bufLen; i++) { 2230d163575Sopenharmony_ci *buf++ = telnetDev->cmdFifo->rxBuf[telnetDev->cmdFifo->rxOutIndex++]; 2240d163575Sopenharmony_ci if (telnetDev->cmdFifo->rxOutIndex >= FIFO_MAX) { 2250d163575Sopenharmony_ci telnetDev->cmdFifo->rxOutIndex = 0; 2260d163575Sopenharmony_ci } 2270d163575Sopenharmony_ci } 2280d163575Sopenharmony_ci telnetDev->cmdFifo->fifoNum += bufLen; 2290d163575Sopenharmony_ci /* check if no more commands left to run */ 2300d163575Sopenharmony_ci if (telnetDev->cmdFifo->fifoNum == FIFO_MAX) { 2310d163575Sopenharmony_ci (VOID)LOS_EventClear(&telnetDev->eventTelnet, ~TELNET_EVENT_MORE_CMD); 2320d163575Sopenharmony_ci } 2330d163575Sopenharmony_ci 2340d163575Sopenharmony_ci TelnetUnlock(); 2350d163575Sopenharmony_ci return (ssize_t)bufLen; 2360d163575Sopenharmony_ci} 2370d163575Sopenharmony_ci 2380d163575Sopenharmony_ci/* 2390d163575Sopenharmony_ci * Description : When a command resolver task tries to write command results to the telnet device, 2400d163575Sopenharmony_ci * just use lwIP send function to send out results. 2410d163575Sopenharmony_ci * Return : -1 --- buffer is NULL 2420d163575Sopenharmony_ci * Non-negative integer --- length of written data, maybe 0. 2430d163575Sopenharmony_ci */ 2440d163575Sopenharmony_ciSTATIC ssize_t TelnetWrite(struct file *file, const CHAR *buf, const size_t bufLen) 2450d163575Sopenharmony_ci{ 2460d163575Sopenharmony_ci INT32 ret = 0; 2470d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 2480d163575Sopenharmony_ci 2490d163575Sopenharmony_ci TelnetLock(); 2500d163575Sopenharmony_ci 2510d163575Sopenharmony_ci telnetDev = GetTelnetDevByFile(file, FALSE); 2520d163575Sopenharmony_ci if ((buf == NULL) || (telnetDev == NULL) || (telnetDev->cmdFifo == NULL)) { 2530d163575Sopenharmony_ci TelnetUnlock(); 2540d163575Sopenharmony_ci return -1; 2550d163575Sopenharmony_ci } 2560d163575Sopenharmony_ci 2570d163575Sopenharmony_ci if (OS_INT_ACTIVE) { 2580d163575Sopenharmony_ci TelnetUnlock(); 2590d163575Sopenharmony_ci return ret; 2600d163575Sopenharmony_ci } 2610d163575Sopenharmony_ci 2620d163575Sopenharmony_ci if (!OsPreemptable()) { 2630d163575Sopenharmony_ci TelnetUnlock(); 2640d163575Sopenharmony_ci return ret; 2650d163575Sopenharmony_ci } 2660d163575Sopenharmony_ci 2670d163575Sopenharmony_ci if (telnetDev->clientFd != 0) { 2680d163575Sopenharmony_ci#ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE 2690d163575Sopenharmony_ci /* DO NOT call blocking API in software timer task */ 2700d163575Sopenharmony_ci if (OsIsSwtmrTask(OsCurrTaskGet())) { 2710d163575Sopenharmony_ci TelnetUnlock(); 2720d163575Sopenharmony_ci return ret; 2730d163575Sopenharmony_ci } 2740d163575Sopenharmony_ci#endif 2750d163575Sopenharmony_ci ret = send(telnetDev->clientFd, buf, bufLen, 0); 2760d163575Sopenharmony_ci } 2770d163575Sopenharmony_ci TelnetUnlock(); 2780d163575Sopenharmony_ci return ret; 2790d163575Sopenharmony_ci} 2800d163575Sopenharmony_ci 2810d163575Sopenharmony_ciSTATIC INT32 TelnetIoctl(struct file *file, const INT32 cmd, unsigned long arg) 2820d163575Sopenharmony_ci{ 2830d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 2840d163575Sopenharmony_ci 2850d163575Sopenharmony_ci TelnetLock(); 2860d163575Sopenharmony_ci 2870d163575Sopenharmony_ci telnetDev = GetTelnetDevByFile(file, FALSE); 2880d163575Sopenharmony_ci if (telnetDev == NULL) { 2890d163575Sopenharmony_ci TelnetUnlock(); 2900d163575Sopenharmony_ci return -1; 2910d163575Sopenharmony_ci } 2920d163575Sopenharmony_ci 2930d163575Sopenharmony_ci if (cmd == CFG_TELNET_EVENT_PEND) { 2940d163575Sopenharmony_ci if (arg == 0) { 2950d163575Sopenharmony_ci telnetDev->eventPend = FALSE; 2960d163575Sopenharmony_ci (VOID)LOS_EventWrite(&(telnetDev->eventTelnet), TELNET_EVENT_MORE_CMD); 2970d163575Sopenharmony_ci (VOID)LOS_EventClear(&(telnetDev->eventTelnet), ~TELNET_EVENT_MORE_CMD); 2980d163575Sopenharmony_ci } else { 2990d163575Sopenharmony_ci telnetDev->eventPend = TRUE; 3000d163575Sopenharmony_ci } 3010d163575Sopenharmony_ci } else if (cmd == CFG_TELNET_SET_FD) { 3020d163575Sopenharmony_ci if (arg >= (FD_SETSIZE - 1)) { 3030d163575Sopenharmony_ci TelnetUnlock(); 3040d163575Sopenharmony_ci return -1; 3050d163575Sopenharmony_ci } 3060d163575Sopenharmony_ci telnetDev->clientFd = (INT32)arg; 3070d163575Sopenharmony_ci } 3080d163575Sopenharmony_ci TelnetUnlock(); 3090d163575Sopenharmony_ci return 0; 3100d163575Sopenharmony_ci} 3110d163575Sopenharmony_ci 3120d163575Sopenharmony_ciSTATIC INT32 TelnetPoll(struct file *file, poll_table *table) 3130d163575Sopenharmony_ci{ 3140d163575Sopenharmony_ci TELNET_DEV_S *telnetDev = NULL; 3150d163575Sopenharmony_ci 3160d163575Sopenharmony_ci TelnetLock(); 3170d163575Sopenharmony_ci 3180d163575Sopenharmony_ci telnetDev = GetTelnetDevByFile(file, FALSE); 3190d163575Sopenharmony_ci if ((telnetDev == NULL) || (telnetDev->cmdFifo == NULL)) { 3200d163575Sopenharmony_ci TelnetUnlock(); 3210d163575Sopenharmony_ci return -1; 3220d163575Sopenharmony_ci } 3230d163575Sopenharmony_ci 3240d163575Sopenharmony_ci poll_wait(file, &telnetDev->wait, table); 3250d163575Sopenharmony_ci 3260d163575Sopenharmony_ci /* check if there are some commands to run */ 3270d163575Sopenharmony_ci if (telnetDev->cmdFifo->fifoNum != FIFO_MAX) { 3280d163575Sopenharmony_ci TelnetUnlock(); 3290d163575Sopenharmony_ci return POLLIN | POLLRDNORM; 3300d163575Sopenharmony_ci } 3310d163575Sopenharmony_ci TelnetUnlock(); 3320d163575Sopenharmony_ci return 0; 3330d163575Sopenharmony_ci} 3340d163575Sopenharmony_ci 3350d163575Sopenharmony_ciSTATIC const struct file_operations_vfs g_telnetOps = { 3360d163575Sopenharmony_ci TelnetOpen, 3370d163575Sopenharmony_ci TelnetClose, 3380d163575Sopenharmony_ci TelnetRead, 3390d163575Sopenharmony_ci TelnetWrite, 3400d163575Sopenharmony_ci NULL, 3410d163575Sopenharmony_ci TelnetIoctl, 3420d163575Sopenharmony_ci NULL, 3430d163575Sopenharmony_ci#ifndef CONFIG_DISABLE_POLL 3440d163575Sopenharmony_ci TelnetPoll, 3450d163575Sopenharmony_ci#endif 3460d163575Sopenharmony_ci NULL, 3470d163575Sopenharmony_ci}; 3480d163575Sopenharmony_ci 3490d163575Sopenharmony_ci/* Once the telnet server stopped, remove the telnet device file. */ 3500d163575Sopenharmony_ciINT32 TelnetedUnregister(VOID) 3510d163575Sopenharmony_ci{ 3520d163575Sopenharmony_ci free(g_telnetDev.cmdFifo); 3530d163575Sopenharmony_ci g_telnetDev.cmdFifo = NULL; 3540d163575Sopenharmony_ci (VOID)unregister_driver(TELNET); 3550d163575Sopenharmony_ci 3560d163575Sopenharmony_ci return 0; 3570d163575Sopenharmony_ci} 3580d163575Sopenharmony_ci 3590d163575Sopenharmony_ci/* Once the telnet server started, setup the telnet device file. */ 3600d163575Sopenharmony_ciINT32 TelnetedRegister(VOID) 3610d163575Sopenharmony_ci{ 3620d163575Sopenharmony_ci INT32 ret; 3630d163575Sopenharmony_ci 3640d163575Sopenharmony_ci g_telnetDev.id = 0; 3650d163575Sopenharmony_ci g_telnetDev.cmdFifo = NULL; 3660d163575Sopenharmony_ci g_telnetDev.eventPend = TRUE; 3670d163575Sopenharmony_ci 3680d163575Sopenharmony_ci ret = register_driver(TELNET, &g_telnetOps, TELNET_DEV_DRV_MODE, &g_telnetDev); 3690d163575Sopenharmony_ci if (ret != 0) { 3700d163575Sopenharmony_ci PRINT_ERR("Telnet register driver error.\n"); 3710d163575Sopenharmony_ci } 3720d163575Sopenharmony_ci return ret; 3730d163575Sopenharmony_ci} 3740d163575Sopenharmony_ci 3750d163575Sopenharmony_ci/* When a telnet client connection established, update the output console for tasks. */ 3760d163575Sopenharmony_ciINT32 TelnetDevInit(INT32 clientFd) 3770d163575Sopenharmony_ci{ 3780d163575Sopenharmony_ci INT32 ret; 3790d163575Sopenharmony_ci 3800d163575Sopenharmony_ci if (clientFd < 0) { 3810d163575Sopenharmony_ci PRINT_ERR("Invalid telnet clientFd.\n"); 3820d163575Sopenharmony_ci return -1; 3830d163575Sopenharmony_ci } 3840d163575Sopenharmony_ci ret = system_console_init(TELNET); 3850d163575Sopenharmony_ci if (ret != 0) { 3860d163575Sopenharmony_ci PRINT_ERR("Telnet console init error.\n"); 3870d163575Sopenharmony_ci return ret; 3880d163575Sopenharmony_ci } 3890d163575Sopenharmony_ci ret = ioctl(STDIN_FILENO, CFG_TELNET_SET_FD, clientFd); 3900d163575Sopenharmony_ci if (ret != 0) { 3910d163575Sopenharmony_ci PRINT_ERR("Telnet device ioctl error.\n"); 3920d163575Sopenharmony_ci (VOID)system_console_deinit(TELNET); 3930d163575Sopenharmony_ci } 3940d163575Sopenharmony_ci return ret; 3950d163575Sopenharmony_ci} 3960d163575Sopenharmony_ci 3970d163575Sopenharmony_ci/* When closing the telnet client connection, reset the output console for tasks. */ 3980d163575Sopenharmony_ciINT32 TelnetDevDeinit(VOID) 3990d163575Sopenharmony_ci{ 4000d163575Sopenharmony_ci INT32 ret; 4010d163575Sopenharmony_ci 4020d163575Sopenharmony_ci ret = system_console_deinit(TELNET); 4030d163575Sopenharmony_ci if (ret != 0) { 4040d163575Sopenharmony_ci PRINT_ERR("Telnet console deinit error.\n"); 4050d163575Sopenharmony_ci } 4060d163575Sopenharmony_ci return ret; 4070d163575Sopenharmony_ci} 4080d163575Sopenharmony_ci#endif 4090d163575Sopenharmony_ci 410