예제 #1
0
static int tegra_onetouch_remove(struct platform_device *pdev)
{
	struct tegra_onetouch_driver_data *onetouch = platform_get_drvdata(pdev);

#ifdef CONFIG_HAS_EARLYSUSPEND
        unregister_early_suspend(&onetouch->early_suspend);
#endif
	onetouch->shutdown = 1;

	NvOdmOneTouchInterruptMask(onetouch->hOneTouchDevice, NV_TRUE);
	NvOdmOsSleepMS(50);

	NvOdmOsSemaphoreDestroy(onetouch->semaphore);
#if defined(CONFIG_MACH_STAR_SKT_REV_E) || defined(CONFIG_MACH_STAR_SKT_REV_F)
	NvOdmOsMutexDestroy(onetouch->hMutex);
#endif

	NvOdmOneTouchDeviceClose(onetouch->hOneTouchDevice);

	/* FIXME How to destroy the thread? Maybe we should use workqueues? */
	input_unregister_device(onetouch->input_dev);
	/* NvOsSemaphoreDestroy(onetouch->semaphore); */
	input_unregister_device(onetouch->input_dev);
	kfree(onetouch);
	return 0;
}
예제 #2
0
void
NvOdmGyroAccelClose(NvOdmGyroAccelHandle hDevice)
{
	if (NULL != hDevice) {
		if (NULL != hDevice->SemaphoreForINT &&
				NULL != hDevice->hGpioINT &&
				NULL != hDevice->hPinINT &&
				NULL != hDevice->hGpioInterrupt)
		{
			NvOdmGpioInterruptUnregister(hDevice->hGpioINT,
					hDevice->hPinINT,
					hDevice->hGpioInterrupt);
			NvOdmOsSemaphoreDestroy(hDevice->SemaphoreForINT);
			NvOdmGpioReleasePinHandle(hDevice->hGpioINT, hDevice->hPinINT);
			NvOdmGpioClose(hDevice->hGpioINT);
		}
		NvGyroAccelI2CClose(hDevice->hOdmI2C);
#if 1
		printk(" ## MPU3050  : [%s:%d] \n",__FUNCTION__, __LINE__) ;
#endif

		// Power off accelermeter
		NvGyroAccelSetPowerRail(hDevice->hPmu, hDevice->VddId, NV_FALSE);
		if (hDevice->hPmu) {
			//NvGyroAccelSetPowerOn(0);
			NvOdmServicesPmuClose(hDevice->hPmu);
		}

		return;
	}
}
예제 #3
0
static void tegra_onetouch_shutdown(struct  platform_device *pdev)
{
	struct tegra_onetouch_driver_data *onetouch = platform_get_drvdata(pdev);
 
	printk("[ONETOUCH] tegra_onetouch_shutdown() \n");

#ifdef CONFIG_HAS_EARLYSUSPEND
	unregister_early_suspend(&onetouch->early_suspend);
#endif
	onetouch->shutdown = 1;

	NvOdmOneTouchInterruptMask(onetouch->hOneTouchDevice, NV_TRUE);
	NvOdmOsSleepMS(50);

	NvOdmOsSemaphoreDestroy(onetouch->semaphore);
#if defined(CONFIG_MACH_STAR_SKT_REV_E) || defined(CONFIG_MACH_STAR_SKT_REV_F)
	NvOdmOsMutexDestroy(onetouch->hMutex);
#endif

	NvOdmOneTouchDeviceClose(onetouch->hOneTouchDevice);

	input_unregister_device(onetouch->input_dev);
	kfree(onetouch);
	return;
}
예제 #4
0
void
NvOdmAccelClose(NvOdmAccelHandle hDevice)
{
    if(NULL != hDevice)
    {
        if(NULL != hDevice->SemaphoreForINT &&
           NULL != hDevice->hGpioINT &&
           NULL != hDevice->hPinINT &&
           NULL != hDevice->hGpioInterrupt)
        {
            NvOdmGpioInterruptUnregister(hDevice->hGpioINT,
                                         hDevice->hPinINT,
                                         hDevice->hGpioInterrupt);
            NvOdmOsSemaphoreDestroy(hDevice->SemaphoreForINT);   
            NvOdmGpioReleasePinHandle(hDevice->hGpioINT, hDevice->hPinINT);
            NvOdmGpioClose(hDevice->hGpioINT);
        }
        NvAccelerometerI2CClose(hDevice->hOdmI2C);

        // Power off accelermeter
        NvAccelerometerSetPowerRail(hDevice->hPmu, hDevice->VddId, NV_FALSE);
        if (hDevice->hPmu)
        {
            //NvAccelerometerSetPowerOn(0);
            NvOdmServicesPmuClose(hDevice->hPmu);
        }
        
        return;
    }
}
void NvOdmCirDeInit(void)
{
	
    (void)NvEcUnregisterForEvents(s_hEcEventRegistration);
    s_hEcEventRegistration = NULL;

    s_CirDeinit = NV_TRUE;
    NvOdmOsSemaphoreSignal(s_hCirKeyScanRecvSema);
    NvOdmOsSemaphoreDestroy(s_hCirKeyScanRecvSema);
    s_hCirKeyScanRecvSema = NULL;

    NvEcClose(s_NvEcHandle);
    s_NvEcHandle = NULL;
}
NvBool NvOdmCirInit(void) /*jolen 0701*/
{
    NvError NvStatus = NvError_Success;

    /* get nvec handle */
    NvStatus = NvEcOpen(&s_NvEcHandle, 0 /* instance */);
    if (NvStatus != NvError_Success)
    {
        goto fail;
    }
    /* create semaphore which can be used to send scan codes to the clients */
    s_hCirKeyScanRecvSema = NvOdmOsSemaphoreCreate(0);
    if (!s_hCirKeyScanRecvSema)
    {
        goto cleanup;
    }

    /* register for CIR events */
    NvStatus = NvEcRegisterForEvents(
                    s_NvEcHandle,       // nvec handle
                    &s_hEcEventRegistration,
                    (NvOsSemaphoreHandle)s_hCirKeyScanRecvSema,
                    sizeof(EventTypes)/sizeof(NvEcEventType),
                    EventTypes, // receive Ir remote scan codes
                    1,          // currently buffer only 1 packet from ECI at a time
                    sizeof(NvEcEvent));
    if (NvStatus != NvError_Success)
    {
        goto cleanup;
    }

    /* success */
    return NV_TRUE;

cleanup:
    (void)NvEcUnregisterForEvents(s_hEcEventRegistration);
    s_hEcEventRegistration = NULL;

    NvOdmOsSemaphoreDestroy(s_hCirKeyScanRecvSema);
    s_hCirKeyScanRecvSema = NULL;

    NvEcClose(s_NvEcHandle);
fail:
    s_NvEcHandle = NULL;

    return NV_FALSE;
}
예제 #7
0
/*
 * Connect semaphore with interrupt pins according to your configuration.
 */
NvBool NvAccelerometerConnectSemaphore(NvOdmAccelHandle hDevice)
{
    NvOdmGpioPinMode mode; 
    NvOdmInterruptHandler callback = (NvOdmInterruptHandler)GpioInterruptHandler;
         
    hDevice->hGpioINT = (NvOdmServicesGpioHandle)NvOdmGpioOpen();
    if(!(hDevice->hGpioINT))
    {
        //NVODMACCELEROMETER_PRINTF("NvOdm Accelerometer : NvOdmGpioOpen Error \n");
        return NV_FALSE;
    }

    hDevice->hPinINT = NvOdmGpioAcquirePinHandle(hDevice->hGpioINT, 
                                                 hDevice->GPIOPortINT, 
                                                 hDevice->GPIOPinINT);

    hDevice->SemaphoreForINT = NvOdmOsSemaphoreCreate(0);

    if(!(hDevice->SemaphoreForINT))
    {
        //NVODMACCELEROMETER_PRINTF("NvOdm Accelerometer : NvOdmOsSemaphoreCreate Error \n");
        NvOdmGpioClose(hDevice->hGpioINT);
        return NV_FALSE;
    }
          
    mode = NvOdmGpioPinMode_InputInterruptHigh;
    
    if (NvOdmGpioInterruptRegister(hDevice->hGpioINT, &hDevice->hGpioInterrupt,
        hDevice->hPinINT, mode, callback, hDevice, NV_DEBOUNCE_TIME_MS) == NV_FALSE)
    {
        return NV_FALSE;
    }

    if(!(hDevice->hGpioInterrupt))
    {
        //NVODMACCELEROMETER_PRINTF("NvOdm Accelerometer : NvOdmGpioInterruptRegister Error \n");
        NvOdmGpioClose(hDevice->hGpioINT);
        NvOdmOsSemaphoreDestroy(hDevice->SemaphoreForINT);
        return NV_FALSE;
    }
    
    return NV_TRUE;
}
static NvBool ConnectSemaphore(NvOdmEcompassHandle hDevice)
{
    NvOdmGpioPinMode mode;
    NvOdmInterruptHandler callback =
        (NvOdmInterruptHandler)GpioInterruptHandler;

    hDevice->hGpioINT = (NvOdmServicesGpioHandle)NvOdmGpioOpen();
    if (!(hDevice->hGpioINT))
    {
        NVODMECOMPASS_PRINTF(("AKM8975 compass driver: NvOdmGpioOpenError \n"));
        return NV_FALSE;
    }

    hDevice->hPinINT = NvOdmGpioAcquirePinHandle(hDevice->hGpioINT,
                           hDevice->GPIOPortINT,
                           hDevice->GPIOPinINT);
    hDevice->SemaphoreForINT = NvOdmOsSemaphoreCreate(0);

    if (!(hDevice->SemaphoreForINT))
    {
        NVODMECOMPASS_PRINTF(( "AKM8975 compass driver: NvOdmOsSemaphoreCreate Error \n"));
        NvOdmGpioClose(hDevice->hGpioINT);
        return NV_FALSE;
    }

    mode = NvOdmGpioPinMode_InputInterruptHigh;
    if (NvOdmGpioInterruptRegister(hDevice->hGpioINT,
        &hDevice->hGpioInterrupt, hDevice->hPinINT, mode, callback,
        hDevice, NV_DEBOUNCE_TIME_MS) == NV_FALSE)
    {
        return NV_FALSE;
    }
	
    if (!(hDevice->hGpioInterrupt))
    {
        NVODMECOMPASS_PRINTF(("AKM8975 compass driver: NvOdm Ecompass NvOdmGpioInterruptRegister Error \n"));
        NvOdmGpioClose(hDevice->hGpioINT);
        NvOdmOsSemaphoreDestroy(hDevice->SemaphoreForINT);
        return NV_FALSE;
    }
    return NV_TRUE;
}
예제 #9
0
NvBool NvGyroAccelConnectSemaphore(NvOdmGyroAccelHandle hDevice)
{
	NvOdmGpioPinMode mode;
	NvOdmInterruptHandler callback = (NvOdmInterruptHandler)GpioInterruptHandler;
	printk(" ## MPU3050 : NvGyroAccelConnectSemaphore \n") ;
	hDevice->hGpioINT = (NvOdmServicesGpioHandle)NvOdmGpioOpen();

	if (!(hDevice->hGpioINT)) {
		printk("## NvOdm GyroAccel : NvOdmGpioOpen Error ##  \n");
		return NV_FALSE;
	}

	hDevice->hPinINT = NvOdmGpioAcquirePinHandle(hDevice->hGpioINT,
			hDevice->GPIOPortINT,
			hDevice->GPIOPinINT);

	hDevice->SemaphoreForINT = NvOdmOsSemaphoreCreate(0);

	if (!(hDevice->SemaphoreForINT)) {
		printk("## NvOdm GyroAccel : NvOdmOsSemaphoreCreate Error ## \n");
		NvOdmGpioClose(hDevice->hGpioINT);
		return NV_FALSE;
	}

	mode = NvOdmGpioPinMode_InputInterruptHigh;

	if (NvOdmGpioInterruptRegister(hDevice->hGpioINT, &hDevice->hGpioInterrupt,
				hDevice->hPinINT, mode, callback, hDevice, NV_DEBOUNCE_TIME_MS) == NV_FALSE)
	{
		printk("NvOdm GyroAccel : cannot register interrupt.\n") ;
		return NV_FALSE;
	}

	if (!(hDevice->hGpioInterrupt)) {
		NvOdmGpioClose(hDevice->hGpioINT);
		NvOdmOsSemaphoreDestroy(hDevice->SemaphoreForINT);
		return NV_FALSE;
	}

	return NV_TRUE;
}
void NvOdmKeyboardDeInit(void)
{
#if WAKE_FROM_KEYBOARD
	NvRmGpioInterruptUnregister(s_hGpioGlobal, s_hRmGlobal, hOdm->GpioIntrHandle);
	hOdm->GpioIntrHandle = NULL;
	NvRmGpioReleasePinHandles(s_hGpioGlobal, &hOdm->hPin, hOdm->PinCount);
	hOdm->PinCount = 0;
	NvOdmOsFree(hOdm);
	hOdm = NULL;
#endif

    (void)NvEcUnregisterForEvents(s_hEcEventRegistration);
    s_hEcEventRegistration = NULL;

    s_KeyboardDeinit = NV_TRUE;
    NvOdmOsSemaphoreSignal(s_hKbcKeyScanRecvSema);
    NvOdmOsSemaphoreDestroy(s_hKbcKeyScanRecvSema);
    s_hKbcKeyScanRecvSema = NULL;

    NvEcClose(s_NvEcHandle);
    s_NvEcHandle = NULL;
}
예제 #11
0
static int __devexit headset_switch_remove(struct platform_device *pdev)
{

	struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);

	cancel_work_sync(&switch_data->work);
	

    //remove interrupt
    NvOdmGpioInterruptUnregister(
        s_hGpio, s_hHeadphoneGpioPin, s_hGpioIntr_Headphone);
    NvOdmGpioReleasePinHandle(s_hGpio, s_hHeadphoneGpioPin);
    s_hHeadphoneGpioPin = NULL;

    //remove thread
    //terminate thread 
    g_DetectThread_exit = 1;
    if ( g_hDetectEventSema )
        NvOdmOsSemaphoreSignal( g_hDetectEventSema );
    
    if( !g_hDetectThread )
        NvOdmOsThreadJoin( g_hDetectThread );
    g_hDetectThread = NULL;

    if ( g_hDetectEventSema )
    {
        NvOdmOsSemaphoreDestroy( g_hDetectEventSema );
        g_hDetectEventSema = 0;
    }

    switch_dev_unregister(&switch_data->sdev);
	kfree(switch_data);


	return 0;
}
예제 #12
0
static int __init tegra_onetouch_probe(struct platform_device *pdev)
{
	struct tegra_onetouch_driver_data *onetouch = NULL;
	struct input_dev *input_dev = NULL;
	int err;
//	NvOdmTouchCapabilities *caps;

	printk("[ONETOUCH] tegra_onetouch_probe start\n");
	onetouch = kzalloc(sizeof(struct tegra_onetouch_driver_data), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (input_dev == NULL || onetouch == NULL) {
		input_free_device(input_dev);
		kfree(onetouch);
		err = -ENOMEM;
		pr_err("tegra_onetouch_probe: Failed to allocate input device\n");
		return err;
	}
	
#if defined(CONFIG_MACH_STAR_SKT_REV_E) || defined(CONFIG_MACH_STAR_SKT_REV_F)
    onetouch->hMutex = NvOdmOsMutexCreate();
#endif
	onetouch->semaphore = NvOdmOsSemaphoreCreate(0);
	if (!onetouch->semaphore) {
		err = -1;
		pr_err("tegra_onetouch_probe: Semaphore creation failed\n");
		goto err_semaphore_create_failed;
	}

// 20100423 [email protected] for Touch Interrupt Issue at booting [START]
#ifdef FEATURE_LGE_TOUCH_CUSTOMIZE
	onetouch->bPollingMode = NV_FALSE;
	if (!NvOdmOneTouchDeviceOpen(&onetouch->hOneTouchDevice, &onetouch->semaphore)) {
		err = -1;
		pr_err("tegra_onetouch_probe: NvOdmOneTouchDeviceOpen failed\n");
		goto err_open_failed;
	}
#else
	if (!NvOdmOneTouchDeviceOpen(&onetouch->hOneTouchDevice)) {
		err = -1;
		pr_err("tegra_onetouch_probe: NvOdmOneTouchDeviceOpen failed\n");
		goto err_open_failed;
	}
	onetouch->bPollingMode = NV_FALSE;
	if (!NvOdmTouchEnableInterrupt(onetouch->hOneTouchDevice, onetouch->semaphore)) {
		err = -1;
		pr_err("tegra_onetouch_probe: Interrupt failed, polling mode\n");
		onetouch->bPollingMode = NV_TRUE;
		onetouch->pollingIntervalMS = 10;
	}
#endif /* FEATURE_LGE_TOUCH_CUSTOMIZE */
// 20100423 [email protected] for Touch Interrupt Issue at booting [END]

	onetouch->task =
		kthread_create(tegra_onetouch_thread, onetouch, "tegra_onetouch_thread");

	if(onetouch->task == NULL) {
		err = -1;
		goto err_kthread_create_failed;
	}
	wake_up_process( onetouch->task );

	onetouch->input_dev = input_dev;
	onetouch->input_dev->name = NVODM_TOUCH_NAME;

	/* Will generate sync at the end of all input */
	set_bit(EV_SYN, onetouch->input_dev->evbit);
	/* Event is key input type */
	set_bit(EV_KEY, onetouch->input_dev->evbit);
	/* virtual key is BTN_TOUCH */
	set_bit(BTN_TOUCH, onetouch->input_dev->keybit);

	set_bit(KEY_MENU, onetouch->input_dev->keybit);
//	set_bit(KEY_HOME, onetouch->input_dev->keybit);
	set_bit(KEY_BACK, onetouch->input_dev->keybit);
//	set_bit(KEY_SEARCH, onetouch->input_dev->keybit);
	set_bit(KEY_REJECT, onetouch->input_dev->keybit);

	platform_set_drvdata(pdev, onetouch);

	err = input_register_device(input_dev);
	if (err)
	{
		pr_err("tegra_onetouch_probe: Unable to register input device\n");
		goto err_input_register_device_failed;
	}

#ifdef CONFIG_HAS_EARLYSUSPEND
        onetouch->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
        onetouch->early_suspend.suspend = tegra_onetouch_early_suspend;
        onetouch->early_suspend.resume = tegra_onetouch_late_resume;
        register_early_suspend(&onetouch->early_suspend);
#endif

	printk(KERN_INFO NVODM_TOUCH_NAME ": Successfully registered the ODM onetouch driver %x\n", (NvU32)onetouch->hOneTouchDevice);
	return 0;

	input_unregister_device(input_dev);
	
err_input_register_device_failed:
	NvOdmOneTouchDeviceClose(onetouch->hOneTouchDevice);
err_kthread_create_failed:
	/* FIXME How to destroy the thread? Maybe we should use workqueues? */
err_open_failed:
	NvOdmOsSemaphoreDestroy(onetouch->semaphore);
#if defined(CONFIG_MACH_STAR_SKT_REV_E) || defined(CONFIG_MACH_STAR_SKT_REV_F)
	NvOdmOsMutexDestroy(onetouch->hMutex);
#endif
err_semaphore_create_failed:
	kfree(onetouch);
	input_free_device(input_dev);
	return err;
}
NvBool NvOdmKeyboardInit(void)
{
    NvError NvStatus = NvError_Success;
    NvEcRequest Request = {0};
    NvEcResponse Response = {0};

    /* get nvec handle */
    NvStatus = NvEcOpen(&s_NvEcHandle, 0 /* instance */);
    if (NvStatus != NvError_Success)
    {
        goto fail;
    }

    /* reset the EC to start the keyboard scanning */
    Request.PacketType = NvEcPacketType_Request;
    Request.RequestType = NvEcRequestResponseType_Keyboard;
    Request.RequestSubtype = (NvEcRequestResponseSubtype) NvEcKeyboardSubtype_Enable;
    Request.NumPayloadBytes = 0;

    NvStatus = NvEcSendRequest(s_NvEcHandle, &Request, &Response, sizeof(Request), sizeof(Response));
    if (NvStatus != NvError_Success)
    {
        goto cleanup;
    }

    /* check if command passed */
    if (Response.Status != NvEcStatus_Success)
    {
        goto cleanup;
    }

#if WAKE_FROM_KEYBOARD
	hOdm = NvOdmOsAlloc(sizeof(NvOdmKbdContext));
	if (!hOdm) {
		goto cleanup;
	}

	/* Check the supported GPIOs */
	hOdm->GpioPinInfo = NvOdmQueryGpioPinMap(NvOdmGpioPinGroup_EmbeddedController,
					0, &hOdm->PinCount);

	NvRmGpioAcquirePinHandle(s_hGpioGlobal,
		hOdm->GpioPinInfo->Port,
		hOdm->GpioPinInfo->Pin,
		&hOdm->hPin);
	if (!hOdm->hPin) {
		goto cleanup;
	}

	/* register to receive GPIO events */
	NvStatus = NvRmGpioInterruptRegister(s_hGpioGlobal,
		s_hRmGlobal,
		hOdm->hPin,
		(NvOsInterruptHandler)GpioInterruptHandler,
		NvRmGpioPinMode_InputData,
		hOdm,
		&hOdm->GpioIntrHandle,
		DEBOUNCE_TIME_MS);
	if (NvStatus != NvError_Success) {
		goto cleanup;
	}

	NvStatus = NvRmGpioInterruptEnable(hOdm->GpioIntrHandle);
	if (NvStatus != NvError_Success) {
		goto cleanup;
	}

	/* enable keyboard as wake up source */
	Request.PacketType = NvEcPacketType_Request;
	Request.RequestType = NvEcRequestResponseType_Keyboard;
	Request.RequestSubtype = (NvEcRequestResponseSubtype)
	NvEcKeyboardSubtype_ConfigureWake;
	Request.NumPayloadBytes = 2;
	Request.Payload[0] = NVEC_KEYBOARD_WAKE_ENABLE_0_ACTION_ENABLE;
	Request.Payload[1] = NVEC_KEYBOARD_EVENT_TYPE_0_ANY_KEY_PRESS_ENABLE;

	NvStatus = NvEcSendRequest(s_NvEcHandle,
		&Request,
		&Response,
		sizeof(Request),
		sizeof(Response));
	if (NvStatus != NvError_Success) {
		goto cleanup;
        }

	if (Response.Status != NvEcStatus_Success) {
		goto cleanup;
	}

        /* enable key reporting on wake up */
	Request.PacketType = NvEcPacketType_Request;
	Request.RequestType = NvEcRequestResponseType_Keyboard;
	Request.RequestSubtype = (NvEcRequestResponseSubtype)
	NvEcKeyboardSubtype_ConfigureWakeKeyReport;
	Request.NumPayloadBytes = 1;
	Request.Payload[0] = NVEC_KEYBOARD_REPORT_WAKE_KEY_0_ACTION_ENABLE;

	NvStatus = NvEcSendRequest(s_NvEcHandle,
		&Request,
		&Response,
		sizeof(Request),
		sizeof(Response));
	if (NvStatus != NvError_Success) {
		goto cleanup;
        }

	if (Response.Status != NvEcStatus_Success) {
		goto cleanup;
	}
#endif

    /* create semaphore which can be used to send scan codes to the clients */
    s_hKbcKeyScanRecvSema = NvOdmOsSemaphoreCreate(0);
    if (!s_hKbcKeyScanRecvSema)
    {
        goto cleanup;
    }

    /* register for keyboard events */
    NvStatus = NvEcRegisterForEvents(
                    s_NvEcHandle,       // nvec handle
                    &s_hEcEventRegistration,
                    (NvOsSemaphoreHandle)s_hKbcKeyScanRecvSema,
                    sizeof(EventTypes)/sizeof(NvEcEventType),
                    EventTypes, // receive keyboard scan codes
                    1,          // currently buffer only 1 packet from ECI at a time
                    sizeof(NvEcEvent));
    if (NvStatus != NvError_Success)
    {
        goto cleanup;
    }

    /* success */
    return NV_TRUE;

cleanup:
#if WAKE_FROM_KEYBOARD
	NvRmGpioInterruptUnregister(s_hGpioGlobal, s_hRmGlobal, hOdm->GpioIntrHandle);
	hOdm->GpioIntrHandle = NULL;
	NvRmGpioReleasePinHandles(s_hGpioGlobal, &hOdm->hPin, hOdm->PinCount);
	NvOdmOsFree(hOdm);
	hOdm = NULL;
#endif
    (void)NvEcUnregisterForEvents(s_hEcEventRegistration);
    s_hEcEventRegistration = NULL;

    NvOdmOsSemaphoreDestroy(s_hKbcKeyScanRecvSema);
    s_hKbcKeyScanRecvSema = NULL;

    NvEcClose(s_NvEcHandle);
fail:
    s_NvEcHandle = NULL;

    return NV_FALSE;
}