📄 wncandevio.c
字号:
}
/************************************************************************
*
* wncDevIODelete - device delete routine
*
* This routine is only for debugging purposes to test the VxWorks I/O System
*
* RETURNS: OK or ERROR
*
* ERRNO: N/A
*
*/
int wncDevIODelete
(
WNCAN_DEVIO_DRVINFO* wncDev, /* pointer to device descriptor */
char* name /* device or channel name */
)
{
/* Debugging only */
logMsg("wncDevIODelete() called\n", 0,0,0,0,0,0);
return OK;
}
#endif /* DEVIO_DEBUG */
/************************************************************************
*
* wncDevIOOpen - device open routine
*
* This routine opens a CAN device or CAN channel for access using the VxWorks
* I/O System via the returned file descriptor
*
* RETURNS: identifier of opened CAN device or channel
*
* ERRNO: ELOOP
*
*/
int wncDevIOOpen
(
WNCAN_DEVIO_DRVINFO* wncDrv, /* pointer to driver descriptor */
char* name, /* device or channel name */
int flags, /* device or channel access */
int mode /* not used */
)
{
WNCAN_DEVIO_FDINFO* fdInfo = NULL;
STATUS status = ERROR; /* pessimistic */
/*
How to determine if opening CAN device or channel:
-- device is named /boardName/controller#
-- channel is named /boardName/controller#/channel#
-- User's call to open() results in I/O System searching its internal device
list using that entire name or an initial substring of that name
-- The matching substring is removed and the remaining part of the original
name argument is passed to THIS function
-- For a CAN device, the name argument to this function is a null string.
For a CAN channel, the name argument to this function is "/channel#".
*/
/* lock device */
semTake(wncDrv->mutex, WAIT_FOREVER);
/* Open CAN device */
if ((name == NULL) || (!*name))
{
WNCAN_DEVICE *canDev;
int bufSize;
/* Check flags argument */
if (flags != O_RDWR)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: Invalid flags argument for CAN device \n",
0,0,0,0,0,0);
#endif
goto ErrorExit;
}
/* Call WNCAN API to open CAN device */
canDev = CAN_Open (wncDrv->boardType, wncDrv->boardIdx, wncDrv->ctlrIdx);
status = CAN_Init (canDev);
if (status == ERROR)
goto ErrorExit;
/* install interrupt handler */
CAN_InstallISRCallback(canDev, wncDevIOIsrHandler);
/* allow all interrupts */
CAN_SetIntMask(canDev, WNCAN_INT_ALL);
CAN_EnableInt(canDev);
/* update devIO info */
wncDrv->isDeviceOpen = TRUE;
wncDrv->wncDevice = canDev;
/* Allocate and initialize DevIO file descriptor structure */
fdInfo = (WNCAN_DEVIO_FDINFO *) WNCDEV_MALLOC(sizeof(WNCAN_DEVIO_FDINFO));
if (fdInfo == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: malloc() failed for "
"WNCAN_DEVIO_FDINFO struct\n", 0,0,0,0,0,0);
#endif
goto ErrorExit;
}
fdInfo->wnDevIODrv = wncDrv;
fdInfo->devType = FD_WNCAN_DEVICE;
/* initialize select's wakeup list */
selWakeupListInit(&fdInfo->selWakeupList);
/* allocate array of infos for each channel */
bufSize = sizeof(WNCAN_DEVIO_FDINFO*)*CAN_GetNumChannels(canDev);
fdInfo->fdtype.device.chnInfo = (WNCAN_DEVIO_FDINFO**)WNCDEV_MALLOC(bufSize);
if (fdInfo->fdtype.device.chnInfo == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: malloc() failed for "
"WNCAN_DEVIO_FDINFO* array\n", 0,0,0,0,0,0);
#endif
goto ErrorExit;
}
/* store into can dev pointer */
WNCDRV_PUT_DEVICEINFO(wncDrv, fdInfo);
}
/* Open CAN channel */
else
{
WNCAN_DEVIO_FDINFO *pDevInfo = NULL;
int ringBufSize = 0;
/* Check flags argument */
if ( !((flags == O_RDWR) || (flags == O_RDONLY) || (flags == O_WRONLY)) )
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: Invalid flags argument for CAN channel\n",
0,0,0,0,0,0);
#endif
goto ErrorExit;
}
/* Ensure that CAN device is open */
if (wncDrv->isDeviceOpen == FALSE)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: CAN device not open\n", 0,0,0,0,0,0);
#endif
goto ErrorExit;
}
/* Allocate and initialize DevIO file descriptor structure */
fdInfo = (WNCAN_DEVIO_FDINFO *) WNCDEV_MALLOC(sizeof(WNCAN_DEVIO_FDINFO));
if (fdInfo == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: malloc() failed for "
"WNCAN_DEVIO_FDINFO struct\n", 0,0,0,0,0,0);
#endif
goto ErrorExit;
}
fdInfo->wnDevIODrv = wncDrv;
fdInfo->devType = FD_WNCAN_CHANNEL;
/* initialize select's wakeup list */
selWakeupListInit(&fdInfo->selWakeupList);
/* Create input and output data buffers as indicated by flags argument */
if ( (flags == O_RDWR) || (flags == O_RDONLY) )
{
/* Create input ring buffer */
ringBufSize = wncUtilCalcRingBufSize (WNCAN_DEFAULT_RINGBUF_SIZE);
fdInfo->fdtype.channel.inputBuf = rngCreate (ringBufSize);
if (fdInfo->fdtype.channel.inputBuf == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: Could not create input ring buffer\n",
0,0,0,0,0,0);
#endif
goto ErrorExit;
}
fdInfo->fdtype.channel.intType = WNCAN_INT_RX;
}
else
fdInfo->fdtype.channel.inputBuf = NULL;
if ( (flags == O_RDWR) || (flags == O_WRONLY) )
{
/* Create output ring buffer */
ringBufSize = wncUtilCalcRingBufSize (WNCAN_DEFAULT_RINGBUF_SIZE);
fdInfo->fdtype.channel.outputBuf = rngCreate (ringBufSize);
if (fdInfo->fdtype.channel.outputBuf == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOOpen() ERROR: Could not create output ring buffer\n",
0,0,0,0,0,0);
#endif
/*
* If creation of outputBuf failed but inputBuf succeeded,
* delete inputBuf before proceeding
*/
if((flags == O_RDWR) && (fdInfo->fdtype.channel.inputBuf))
rngDelete (fdInfo->fdtype.channel.inputBuf);
goto ErrorExit;
}
fdInfo->fdtype.channel.intType = WNCAN_INT_TX;
}
else
fdInfo->fdtype.channel.outputBuf = NULL;
/* Finish initializing DevIO file descriptor struct */
fdInfo->fdtype.channel.enabled = TRUE;
fdInfo->fdtype.channel.flag = flags;
/* skip leading slash */
fdInfo->fdtype.channel.channel = (UINT32) stringToUlong(&name[1]);
/* store this channel's info into the device's info */
pDevInfo = WNCDRV_GET_DEVICEINFO(wncDrv);
pDevInfo->fdtype.device.chnInfo[fdInfo->fdtype.channel.channel] = fdInfo;
/* Indicate in DevIO driver struct that a channel was opened */
wncDrv->numOpenChans++;
}
/* unlock device */
semGive(wncDrv->mutex);
/*
Return pointer to file descriptor struct so that the I/O system can save
and automatically use as argument for all subsequent calls to close(),
read(), write(), and ioctl() functions
*/
return (int) fdInfo;
/* Set errno used by VxWorks for failed open() */
ErrorExit:
errnoSet (ELOOP);
/* de-allocate memory, if needed */
if (fdInfo)
WNCDEV_FREE((char*)fdInfo);
/* unlock device */
semGive(wncDrv->mutex);
return ERROR;
}
/************************************************************************
*
* wncDevIOClose - device close routine
*
* This routine closes the specified CAN device or CAN channel. In order to
* close a device, all channels on that device must be previously closed.
*
* RETURNS: OK or ERROR
*
* ERRNO: S_ioLib_DEVICE_ERROR
*
*/
STATUS wncDevIOClose
(
WNCAN_DEVIO_FDINFO* fdInfo /* pointer to DevIO file descriptor */
)
{
WNCAN_DEVIO_DRVINFO* wncDrv = NULL;
WNCAN_DEVICE* canDev = NULL;
STATUS status = ERROR;
if (fdInfo == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOClose() ERROR: Null DevIO file descriptor\n",
0,0,0,0,0,0);
#endif
return status;
}
wncDrv = fdInfo->wnDevIODrv;
if (wncDrv == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOClose() ERROR: Null DevIO driver pointer\n",
0,0,0,0,0,0);
#endif
return status;
}
canDev = wncDrv->wncDevice;
if (canDev == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIOClose() ERROR: Null device pointer\n",
0,0,0,0,0,0);
#endif
return status;
}
/* lock device */
semTake(wncDrv->mutex, WAIT_FOREVER);
/* Close CAN channel */
if (fdInfo->devType == FD_WNCAN_CHANNEL)
{
WNCAN_DEVIO_FDINFO *pDevInfo = NULL;
/* Call WNCAN API functions to close channel */
status = CAN_DisableChannel (canDev, fdInfo->fdtype.channel.channel);
if (status == OK)
{
status=CAN_FreeChannel (canDev, fdInfo->fdtype.channel.channel);
if (status == OK)
{
/* Delete ring buffers */
if (fdInfo->fdtype.channel.inputBuf)
rngDelete (fdInfo->fdtype.channel.inputBuf);
fdInfo->fdtype.channel.inputBuf = 0;
if (fdInfo->fdtype.channel.outputBuf)
rngDelete (fdInfo->fdtype.channel.outputBuf);
fdInfo->fdtype.channel.outputBuf = 0;
/* remove channel's info from the device's info */
pDevInfo = WNCDRV_GET_DEVICEINFO(wncDrv);
pDevInfo->fdtype.device.chnInfo[fdInfo->fdtype.channel.channel] =NULL;
/* Cleanup DevIO file descriptor struct */
fdInfo->wnDevIODrv = NULL;
fdInfo->devType = FD_WNCAN_NONE;
fdInfo->fdtype.channel.enabled = FALSE;
fdInfo->fdtype.channel.flag = 0;
fdInfo->fdtype.channel.channel = 0;
/* release wake up list */
selWakeupListTerm(&fdInfo->selWakeupList);
/* Free DevIO file descriptor struct */
WNCDEV_FREE((char*)fdInfo);
fdInfo = NULL;
/* Decrement open channel counter */
wncDrv->numOpenChans--;
}
#if DEVIO_DEBUG
else
{
logMsg("wncDevIOClose() ERROR: channel free failed on channel num %d\n",
fdInfo->fdtype.channel.channel,0,0,0,0,0);
}
#endif
}
#if DEVIO_DEBUG
else
{
logMsg("wncDevIOClose() ERROR: channel disable failed on channel num %d\n",
fdInfo->fdtype.channel.channel,0,0,0,0,0);
}
#endif
}
/* Close CAN device */
else if (fdInfo->devType == FD_WNCAN_DEVICE)
{
/* Ensure that user has closed any open channels */
if (wncDrv->numOpenChans > 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIOClose() ERROR: CAN device still has open channels\n",
0,0,0,0,0,0);
#endif
errnoSet (S_ioLib_DEVICE_ERROR);
status = ERROR;
}
else
{
/* Call WNCAN API functions for closing device */
CAN_TxAbort (canDev);
CAN_Stop (canDev);
CAN_DisableInt (canDev);
/* Close the device */
CAN_Close (canDev);
/* free internal struct memory */
WNCDEV_FREE((char*)fdInfo->fdtype.device.chnInfo);
/* release wake up list */
selWakeupListTerm(&fdInfo->selWakeupList);
/* Free DevIO file descriptor struct */
WNCDEV_FREE((char*)fdInfo);
fdInfo = NULL;
wncDrv->isDeviceOpen = FALSE;
status = OK;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -