📄 ptydrv.c
字号:
/* ptyDrv.c - pseudo-terminal driver *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01w,12mar99,p_m Fixed SPR 9124 by mentioning that there is no way to delete a pty device.01v,03feb93,jdi documentation cleanup for 5.1.01u,13nov92,dnw added include of semLibP.h01t,21oct92,jdi removed mangen SECTION designation.01s,18jul92,smb Changed errno.h to errnoLib.h.01r,04jul92,jcf scalable/ANSI/cleanup effort.01q,26may92,rrr the tree shuffle01p,19nov91,rrr shut up some ansi warnings.01o,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed includes to have absolute path from h/ -changed VOID to void -changed copyright notice01n,05apr91,jdi documentation -- removed header parens and x-ref numbers; doc review by rdc.01m,27feb91,jaa documentation update.01l,26jun90,jcf changed semaphore type for 5.0. Embedded semaphore.01k,23mar90,dab removed ptyMasterDelete() and ptySlaveDelete().01j,15feb90,dab added ptyMasterDelete() and ptySlaveDelete(). documentation.01i,30may88,dnw changed to v4 names.01h,04may88,jcf changed semaphores to be consistent with new semLib.01g,06nov87,ecs documentation.01f,24oct87,gae added pty{Master,Slave}Close() so that reads on corresponding would return 0/ERROR.01e,20oct87,gae made ptyDrv() return correct status on succesive calls. documentation.01d,25mar87,jlf documentation01c,21dec86,dnw changed to not get include files from default directories.01b,02jul86,jlf documentation01a,01apr86,rdc wrotten.*//*The pseudo-terminal driver provides a tty-like interface between a master andslave process, typically in network applications. The master processsimulates the "hardware" side of the driver (e.g., a USART serial chip), whilethe slave process is the application program that normally talks to the driver.USER-CALLABLE ROUTINESMost of the routines in this driver are accessible only through the I/Osystem. However, the following routines must be called directly: ptyDrv() toinitialize the driver, and ptyDevCreate() to create devices.INITIALIZING THE DRIVERBefore using the driver, it must be initialized by calling ptyDrv().This routine must be called before any reads, writes, or calls toptyDevCreate().CREATING PSEUDO-TERMINAL DEVICESBefore a pseudo-terminal can be used, it must be created by callingptyDevCreate():.CS STATUS ptyDevCreate ( char *name, /@ name of pseudo terminal @/ int rdBufSize, /@ size of terminal read buffer @/ int wrtBufSize /@ size of write buffer @/ ).CEFor instance, to create the device pair "/pty/0.M" and "/pty/0.S",with read and write buffer sizes of 512 bytes, the proper call would be:.CS ptyDevCreate ("/pty/0.", 512, 512);.CEWhen ptyDevCreate() is called, two devices are created, a master andslave. One is called <name>M and the other <name>S. They canthen be opened by the master and slave processes. Data written to themaster device can then be read on the slave device, and vice versa. Callsto ioctl() may be made to either device, but they should only apply to theslave side, since the master and slave are the same device.IOCTL FUNCTIONSPseudo-terminal drivers respond to the same ioctl() functions used bytty devices. These functions are defined in ioLib.h and documented inthe manual entry for tyLib.CAVEATPseudo-terminal devices cannot be deleted and the associated memory cannotbe reclaimed.INCLUDE FILES: ioLib.h, ptyDrv.hSEE ALSO: tyLib,.pG "I/O System"*/#include "vxWorks.h"#include "ioLib.h"#include "iosLib.h"#include "semLib.h"#include "stdlib.h"#include "wdLib.h"#include "tyLib.h"#include "string.h"#include "errnoLib.h"#include "private/semLibP.h"typedef struct /* PSEUDO_DEV */ { TY_DEV tyDev; DEV_HDR slaveDev; SEMAPHORE masterReadSyncSem; BOOL ateof; } PSEUDO_DEV;/* local variables */LOCAL int ptySlaveDrvNum; /* driver number assigned to slave driver */LOCAL int ptyMasterDrvNum; /* driver number assigned to master drv *//* forward static functions */static int ptyMasterOpen (PSEUDO_DEV *pPseudoDev, char *name, int mode);static int ptySlaveOpen (PSEUDO_DEV *pPseudoDev, char *name, int mode);static STATUS ptySlaveClose (PSEUDO_DEV *pPseudoDev);static STATUS ptyMasterClose (PSEUDO_DEV *pPseudoDev);static int ptySlaveRead (PSEUDO_DEV *pPseudoDev, char *buffer, int maxbytes);static int ptyMasterRead (PSEUDO_DEV *pPseudoDev, char *buffer, int maxbytes);static int ptySlaveWrite (PSEUDO_DEV *pPseudoDev, char *buffer, int nbytes);static int ptyMasterWrite (PSEUDO_DEV *pPseudoDev, char *buffer, int nbytes);static STATUS ptySlaveIoctl (PSEUDO_DEV *pPseudoDev, int request, int arg);static STATUS ptyMasterIoctl (PSEUDO_DEV *pPseudoDev, int request, int arg);static void ptyMasterStartup (PSEUDO_DEV *pPseudoDev);/********************************************************************************* ptyDrv - initialize the pseudo-terminal driver** This routine initializes the pseudo-terminal driver.* It must be called before any other routine in this module.** RETURNS: OK, or ERROR if the master or slave devices cannot be installed.*/STATUS ptyDrv (void) { static BOOL done; /* FALSE = not done, TRUE = done */ static STATUS status; if (!done) { done = TRUE; ptySlaveDrvNum = iosDrvInstall (ptySlaveOpen, (FUNCPTR) NULL, ptySlaveOpen, ptySlaveClose, ptySlaveRead, ptySlaveWrite, ptySlaveIoctl); ptyMasterDrvNum = iosDrvInstall (ptyMasterOpen, (FUNCPTR) NULL, ptyMasterOpen, ptyMasterClose, ptyMasterRead, ptyMasterWrite, ptyMasterIoctl); status = (ptySlaveDrvNum != ERROR && ptyMasterDrvNum != ERROR) ? OK : ERROR; } return (status); }/********************************************************************************* ptyDevCreate - create a pseudo terminal** This routine creates a master and slave device which can then be opened by* the master and slave processes. The master process simulates the "hardware"* side of the driver, while the slave process is the application program that* normally talks to a tty driver. Data written to the master device can then* be read on the slave device, and vice versa.** RETURNS: OK, or ERROR if memory is insufficient.*/STATUS ptyDevCreate ( char *name, /* name of pseudo terminal */ int rdBufSize, /* size of terminal read buffer */ int wrtBufSize /* size of write buffer */ ) { STATUS status; char nameBuf [MAX_FILENAME_LENGTH]; PSEUDO_DEV *pPseudoDev; if (ptySlaveDrvNum < 1 || ptyMasterDrvNum < 1) { errnoSet (S_ioLib_NO_DRIVER); return (ERROR); } pPseudoDev = (PSEUDO_DEV *) malloc (sizeof (PSEUDO_DEV)); if (pPseudoDev == NULL) return (ERROR); /* initialize device descriptor */ if (tyDevInit ((TY_DEV_ID) pPseudoDev, rdBufSize, wrtBufSize, (FUNCPTR)ptyMasterStartup) != OK) { free ((char *)pPseudoDev); return (ERROR); } semBInit (&pPseudoDev->masterReadSyncSem, SEM_Q_PRIORITY, SEM_EMPTY); /* add Slave and Master devices */ strcpy (nameBuf, name); strcat (nameBuf, "S"); status = iosDevAdd (&pPseudoDev->slaveDev, nameBuf, ptySlaveDrvNum); if (status == OK) { strcpy (nameBuf, name); strcat (nameBuf, "M"); status = iosDevAdd ((DEV_HDR *) pPseudoDev, nameBuf, ptyMasterDrvNum); } return (status); }/********************************************************************************* ptyMasterOpen - open the Master side of a pseudo terminal** ARGSUSED1*/LOCAL int ptyMasterOpen ( PSEUDO_DEV *pPseudoDev, char *name, int mode ) { return ((int) pPseudoDev); }/********************************************************************************* ptySlaveOpen - open the Slave side of a pseudo terminal** ARGSUSED1*/LOCAL int ptySlaveOpen ( PSEUDO_DEV *pPseudoDev, char *name, int mode ) { return ((int) pPseudoDev - (OFFSET(PSEUDO_DEV, slaveDev))); }/********************************************************************************* ptySlaveClose -** Closing the slave side should cause the master to read 0 bytes.*/LOCAL STATUS ptySlaveClose ( PSEUDO_DEV *pPseudoDev ) { pPseudoDev->ateof = FALSE; /* indicate to master read of close */ semGive (&pPseudoDev->masterReadSyncSem); return (OK); }/********************************************************************************* ptyMasterClose -** Closing the master side will cause the slave's read to return ERROR.*/LOCAL STATUS ptyMasterClose ( PSEUDO_DEV *pPseudoDev ) { tyIoctl ((TY_DEV_ID) pPseudoDev, FIOCANCEL, 0 /*XXX*/); return (OK); }/********************************************************************************* ptySlaveRead - slave read routine** The slave device simply calls tyRead to get data out of the ring buffer.** RETURNS: whatever tyRead returns (number of bytes actually read)*/LOCAL int ptySlaveRead ( PSEUDO_DEV *pPseudoDev, char *buffer, int maxbytes ) { return (tyRead ((TY_DEV_ID) pPseudoDev, buffer, maxbytes)); }/********************************************************************************* ptyMasterRead - master read routine** The master read routine calls tyITx to empty the pseudo terminal's buffer.** RETURNS: number of characters actually read*/LOCAL int ptyMasterRead ( FAST PSEUDO_DEV *pPseudoDev, char *buffer, /* where to return characters read */ int maxbytes ) { FAST int i; char ch; pPseudoDev->ateof = TRUE; for (i = 0; i == 0;) { while ((i < maxbytes) && (tyITx ((TY_DEV_ID) pPseudoDev, &ch) == OK)) buffer [i++] = ch; if (!pPseudoDev->ateof) break; if (i == 0) semTake (&pPseudoDev->masterReadSyncSem, WAIT_FOREVER); } return (i); }/********************************************************************************* ptySlaveWrite - pseudo terminal Slave write routine** This routine simply calls tyWrite.** RETURNS: whatever tyWrite returns (number of bytes actually written)*/LOCAL int ptySlaveWrite ( PSEUDO_DEV *pPseudoDev, char *buffer, int nbytes ) { return (tyWrite ((TY_DEV_ID) pPseudoDev, buffer, nbytes)); }/********************************************************************************* ptyMasterWrite - pseudo terminal Master write routine** This routine calls tyIRd to put data in the pseudo terminals ring buffer.** RETURNS: nbytes*/LOCAL int ptyMasterWrite ( PSEUDO_DEV *pPseudoDev, char *buffer, int nbytes ) { FAST int i; for (i = 0; i < nbytes; i++) (void)tyIRd ((TY_DEV_ID) pPseudoDev, buffer [i]); return (i); }/********************************************************************************* ptySlaveIoctl - special device control*/LOCAL STATUS ptySlaveIoctl ( PSEUDO_DEV *pPseudoDev, /* device to control */ int request, /* request code */ int arg /* some argument */ ) { return (tyIoctl ((TY_DEV_ID) pPseudoDev, request, arg)); }/********************************************************************************* ptyMasterIoctl - special device control*/LOCAL STATUS ptyMasterIoctl ( PSEUDO_DEV *pPseudoDev, /* device to control */ int request, /* request code */ int arg /* some argument */ ) { return (tyIoctl ((TY_DEV_ID) pPseudoDev, request, arg)); }/********************************************************************************* ptyMasterStartup - start up the Master read routine*/LOCAL void ptyMasterStartup ( PSEUDO_DEV *pPseudoDev ) { semGive (&pPseudoDev->masterReadSyncSem); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -