📄 pmic_connectivity.cpp
字号:
ENTRY_MSG;
if (handle == (PMIC_CONVITY_HANDLE *)NULL)
{
/* Do not dereference a NULL pointer. */
return PMIC_ERROR;
}
/* We need a critical section here to avoid problems in case
* multiple calls to pmic_convity_open() are made since we can only
* allow one of them to succeed.
*/
EnterCriticalSection(&mutex);
/* Check the current device handle state and acquire the handle if
* it is available.
*/
if (convity.handleState != HANDLE_FREE)
{
/* Cannot open the PMIC connectivity hardware at this time or an invalid
* mode was requested.
*/
*handle = reset.handle;
}
else
{
/* Let's begin by acquiring the connectivity device handle. */
convity.handle = (PMIC_CONVITY_HANDLE)(&convity);
convity.handleState = HANDLE_IN_USE;
/* Then we can try to set the desired operating mode. */
param.op = OP_SET_MODE;
param.PARAMS.ifMode = mode;
DeviceIoControl(hPMI, PMIC_IOCTL_CONVT_OP, ¶m, sizeof(param),
&rc, sizeof(rc), NULL, NULL);
if (rc == PMIC_SUCCESS)
{
/* Successfully set the desired operating mode, now return the
* handle to the caller.
*/
*handle = convity.handle;
convity.mode = mode;
}
else
{
/* Failed to set the desired mode, return the handle to an unused
* state.
*/
convity.handle = reset.handle;
convity.handleState = reset.handleState;
*handle = reset.handle;
}
}
/* Exit the critical section. */
LeaveCriticalSection(&mutex);
EXIT_MSG;
return rc;
}
/*!
* Terminate further access to the PMIC connectivity hardware. Also allows
* another process to call pmic_convity_open() to gain access.
*
* @param handle device handle from open() call
*
* @return PMIC_SUCCESS if the close request was successful
*/
PMIC_STATUS PmicConvityClose(
const PMIC_CONVITY_HANDLE handle)
{
PMIC_STATUS rc = PMIC_ERROR;
ENTRY_MSG;
/* Begin a critical section here to avoid the possibility of race
* conditions if multiple threads happen to call this function and
* pmic_convity_open() at the same time.
*/
EnterCriticalSection(&mutex);
/* Confirm that the device handle matches the one assigned in the
* pmic_convity_open() call and then close the connection.
*/
if ((handle == convity.handle) &&
(convity.handleState == HANDLE_IN_USE))
{
rc = PMIC_SUCCESS;
/* Deregister for all existing callbacks if necessary and make sure
* that the event handling settings are consistent following the
* close operation.
*/
if (convity.callback != reset.callback)
{
/* Deregister the existing callback function and all registered
* events before we completely close the handle.
*/
rc = cleanup();
}
if (rc == PMIC_SUCCESS)
{
/* Mark the connectivity device handle as being closed. */
convity.handle = reset.handle;
convity.handleState = reset.handleState;
}
}
/* Exit the critical section. */
LeaveCriticalSection(&mutex);
EXIT_MSG;
return rc;
}
/*!
* Change the current operating mode of the PMIC connectivity hardware.
* The available connectivity operating modes is hardware dependent and
* consists of one or more of the following: USB (including USB On-the-Go),
* RS-232, and CEA-936. Requesting an operating mode that is not supported
* by the PMIC hardware will return PMIC_NOT_SUPPORTED.
*
* @param handle device handle from open() call
* @param mode desired operating mode
*
* @return PMIC_SUCCESS if the requested mode was successfully set
*/
PMIC_STATUS PmicConvitySetMode(
const PMIC_CONVITY_HANDLE handle,
const PMIC_CONVITY_MODE mode)
{
PMIC_STATUS rc = PMIC_ERROR;
ENTRY_MSG;
/* Use a critical section to maintain a consistent state. */
EnterCriticalSection(&mutex);
if ((handle == convity.handle) &&
(convity.handleState == HANDLE_IN_USE))
{
param.op = OP_SET_MODE;
param.PARAMS.ifMode = mode;
DeviceIoControl(hPMI, PMIC_IOCTL_CONVT_OP, ¶m, sizeof(param),
&rc, sizeof(rc), NULL, NULL);
if (rc == PMIC_SUCCESS)
{
convity.mode = mode;
}
}
/* Exit the critical section. */
LeaveCriticalSection(&mutex);
EXIT_MSG;
return rc;
}
/*!
* Get the current operating mode for the PMIC connectivity hardware.
*
* @param handle device handle from open() call
* @param mode the current PMIC connectivity operating mode
*
* @return PMIC_SUCCESS if the requested mode was successfully set
*/
PMIC_STATUS PmicConvityGetMode(
const PMIC_CONVITY_HANDLE handle,
PMIC_CONVITY_MODE *const mode)
{
PMIC_STATUS rc = PMIC_ERROR;
ENTRY_MSG;
/* Use a critical section to maintain a consistent state. */
EnterCriticalSection(&mutex);
if ((handle == convity.handle) &&
(convity.handleState == HANDLE_IN_USE) &&
(mode != (PMIC_CONVITY_MODE *)NULL))
{
*mode = convity.mode;
rc = PMIC_SUCCESS;
}
/* Exit the critical section. */
LeaveCriticalSection(&mutex);
EXIT_MSG;
return rc;
}
/*!
* Restore all registers to the initial power-on/reset state.
*
* @param handle device handle from open() call
*
* @return PMIC_SUCCESS if the reset was successful
*/
PMIC_STATUS PmicConvityReset(
const PMIC_CONVITY_HANDLE handle)
{
PMIC_STATUS rc = PMIC_ERROR;
ENTRY_MSG;
/* Use a critical section to maintain a consistent state. */
EnterCriticalSection(&mutex);
if ((handle == convity.handle) &&
(convity.handleState == HANDLE_IN_USE))
{
/* Reset the PMIC Connectivity register to it's power on state. */
param.op = OP_RESET;
DeviceIoControl(hPMI, PMIC_IOCTL_CONVT_OP, ¶m, sizeof(param),
&rc, sizeof(rc), NULL, NULL);
if (rc == PMIC_SUCCESS)
{
/* Also reset the device driver state data structure. */
convity = reset;
}
}
/* Exit the critical section. */
LeaveCriticalSection(&mutex);
EXIT_MSG;
return rc;
}
/*!
* Register a callback function that will be used to signal PMIC connectivity
* events. For example, the USB subsystem should register a callback function
* in order to be notified of device connect/disconnect events. Note, however,
* that non-USB events may also be signalled depending upon the PMIC hardware
* capabilities. Therefore, the callback function must be able to properly
* handle all of the possible events if support for non-USB peripherals is
* also to be included.
*
* @param handle device handle from open() call
* @param func a pointer to the callback function
* @param eventMask a mask selecting events to be notified
*
* @return PMIC_SUCCESS if the callback was successful registered
*/
PMIC_STATUS PmicConvitySetCallback(
const PMIC_CONVITY_HANDLE handle,
const PMIC_CONVITY_CALLBACK func,
const PMIC_CONVITY_EVENTS eventMask)
{
PMIC_STATUS rc = PMIC_ERROR;
int i;
ENTRY_MSG;
/* We need to start a critical section here to ensure a consistent state
* in case simultaneous calls to pmic_convity_set_callback() are made. In
* that case, we must serialize the calls to ensure that the "callback"
* and "eventMask" state variables are always consistent.
*
* Note that we don't actually need to acquire the spinlock until later
* when we are finally ready to update the "callback" and "eventMask"
* state variables which are shared with the interrupt handler.
*/
EnterCriticalSection(&mutex);
if ((handle == convity.handle) &&
(convity.handleState == HANDLE_IN_USE))
{
/* Return an error if either the callback function or event mask
* is not properly defined.
*
* It is also considered an error if a callback function has already
* been defined. If you wish to register for a new set of events,
* then you must first call pmic_convity_clear_callback() to
* deregister the existing callback function and list of events
* before trying to register a new callback function.
*/
if ((func == NULL) || (eventMask == 0) || (convity.callback != NULL) ||
(threadContinue != 0))
{
rc = PMIC_ERROR;
}
else
{
/* create all the events; start the thread.
* all the events are received. Only those for which there is a callback
* registered, are intimated.
*/
for (i = 0; i < NUM_CONVITY_INTR; i++)
{
/* create event for PMIC interrupt signaling
* pEventAttributes = NULL (must be NULL)
* bManualReset = FALSE => resets automatically to nonsignaled
* state after waiting thread released
* bInitialState = FALSE => initial state is non-signaled
* lpName = => object created with a name
*/
hEventTab[i] = CreateEvent(NULL, FALSE, FALSE, evtNames[i]);
/* check if CreateEvent failed */
if (hEventTab[i] == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("%s(): CreateEvent failed!\r\n"),
__WFUNCTION__));
cleanup();
goto ExitLoop;
}
/* Register for interrupts. */
if (PmicInterruptRegister(interruptTab[i], evtNames[i])!= PMIC_SUCCESS)
{
DEBUGMSG(ZONE_ERROR, (TEXT("%s(): PmicInterruptRegister failed!\r\n"),
__WFUNCTION__));
cleanup();
goto ExitLoop;
}
/* Make sure interrupt is unmasked */
if (PmicInterruptEnable(interruptTab[i]) != PMIC_SUCCESS)
{
DEBUGMSG(ZONE_ERROR, (TEXT("%s(): PmicInterruptEnable failed!\r\n"),
__WFUNCTION__));
cleanup();
goto ExitLoop;
}
}
/* Since same thread takes care of all the events,
* create one thread
*/
threadContinue = 1;
hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PmicConvityIsrThreadProc,
(LPVOID)0, 0, NULL);
if (!hThread)
{
DEBUGMSG(ZONE_ERROR, (TEXT("%s(): CreateThread failed!\r\n"),
__WFUNCTION__));
cleanup();
goto ExitLoop;
}
/* Successfully registered for all events. */
rc = PMIC_SUCCESS;
convity.callback = func;
convity.eventMask = eventMask;
}
}
ExitLoop:
/* Exit the critical section. */
LeaveCriticalSection(&mutex);
EXIT_MSG;
return rc;
}
/*!
* Clears the current callback function. If this function returns successfully
* then all future Connectivity events will only be handled by the default
* handler within the Connectivity driver.
*
* @param handle device handle from open() call
*
* @return PMIC_SUCCESS if the callback was successful cleared
*/
PMIC_STATUS PmicConvityClearCallback(
const PMIC_CONVITY_HANDLE handle)
{
PMIC_STATUS rc = PMIC_ERROR;
ENTRY_MSG;
/* Use a critical section to maintain a consistent state. */
EnterCriticalSection(&mutex);
if ((handle == convity.handle) &&
(convity.handleState == HANDLE_IN_USE))
{
rc = cleanup();
}
/* Exit the critical section. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -