WINCE背光驱动

来源:互联网 发布:ubuntu恢复删除的文件 编辑:程序博客网 时间:2024/05/02 01:34
 在大多2440开发板WINCE 5.0 的BSP中,SMDK2440/DRIVERS/backlite目录下一般都有背光驱动。开机时确实可以打印"!!!!!!!!!!!! BACKLIGHT ON !!!!!!!!!!!!,如果没有操作大概1分钟后也可以打印!!!!!!!!!!!! BACKLIGHT OFF !!!!!!!!!!!!。但打印 OFF后,就算有触发事件(在触摸屏上点击)也不会打印"!!!!!!!!!!!! BACKLIGHT ON !!!!!!!!!!!!。

      当你好好分析驱动中的以下这3个Event时:

g_evtSignal[0] = CreateEvent(NULL, FALSE, FALSE, szevtBacklightChange);
g_evtSignal[1] = CreateEvent(NULL, FALSE, FALSE, szevtUserInput);
g_evtSignal[BL_POWEREVT] = CreateEvent(NULL, FALSE, FALSE, szevtPowerChanged);

尤其是第二个,好像又没有问题。其实这个驱动大体是正确的,修改后的源程序(不完整严密,例如没有创建线程语句)如下:

      //  Globals
const TCHAR szevtBacklightChange[] = TEXT("BackLightChangeEvent");
const TCHAR szevtPowerChanged[] = TEXT("PowerChangedEvent");
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");


const TCHAR szregRootKey[] = TEXT("ControlPanel//Backlight");
const TCHAR szregBatteryTimeout[] = TEXT("BatteryTimeout");
const TCHAR szregACTimeout[] = TEXT("ACTimeout");
const TCHAR szregBatteryAuto[] = TEXT("BacklightOnTap");
const TCHAR szregACAuto[] = TEXT("ACBacklightOnTap");


HANDLE   g_evtSignal[NUM_EVENTS];   //NUM_EVENTS为3
volatile IOPreg * v_pIOPregs = (IOPreg * )IOP_BASE;  /* GPIO 寄存器对应的虚拟地址 */
BLStruct g_BLInfo;  //  Global structure

void BL_On(BOOL bOn)   // turn on/off the backlight
{
      if(bOn)

      {
            if (g_BLInfo.m_dwStatus != BL_ON)
            {
                  g_BLInfo.m_dwStatus = BL_ON; 
                  v_pIOPregs->rGPBDAT&=0x6FF;//打开LED
                  RETAILMSG(1,(TEXT("!!!!!!!!!!!! BACKLIGHT ON !!!!!!!!!!!!/r/n")));
            }
       }
       else

       {
             if (g_BLInfo.m_dwStatus != BL_OFF)
             {
                   g_BLInfo.m_dwStatus = BL_OFF; 
                   v_pIOPregs->rGPBDAT|=0x100;//关闭LED
                   RETAILMSG(1,(TEXT("!!!!!!!!!!!! BACKLIGHT OFF !!!!!!!!!!!!/r/n")));
             }
       }
}

 

void BL_PowerOn(BOOL bInit)    // restore power to the backlight

       BL_On(TRUE);
}


BOOL  BacklightInitialize()  // Perform all one-time initialization of the backlight
{
       BOOL    bRet = TRUE;

       RETAILMSG(1, (TEXT("BacklightInitialize/r/n")));

       BL_PowerOn(TRUE);

       v_pIOPregs->rGPBCON &=0x3C03FF;
       v_pIOPregs->rGPBCON |=0x15400;
       v_pIOPregs->rGPBUP &=0x61F;  //开背光
       return bRet;
}


void BL_ReadRegistry(BLStruct *pBLInfo)   //  Utility function to read from registry for the parameters
{
       HKEY    hKey;
       LONG    lResult;
       DWORD   dwType;
       DWORD   dwVal;
       DWORD   dwLen;

       lResult = RegOpenKeyEx(HKEY_CURRENT_USER, szregRootKey, 0, KEY_ALL_ACCESS, &hKey);
       if(ERROR_SUCCESS == lResult)

       {
             dwType = REG_DWORD; 
             dwLen = sizeof(DWORD);

             lResult = RegQueryValueEx(hKey, szregBatteryTimeout, NULL, &dwType, (LPBYTE)&dwVal, &dwLen);
             if(ERROR_SUCCESS == lResult)

             {
                   pBLInfo->m_dwBatteryTimeout = dwVal;
             }  

             lResult = RegQueryValueEx(hKey, szregACTimeout, NULL, &dwType, (LPBYTE)&dwVal, &dwLen);
             if(ERROR_SUCCESS == lResult)

             { 
                   pBLInfo->m_dwACTimeout = dwVal;
             }

             lResult = RegQueryValueEx(hKey, szregBatteryAuto, NULL, &dwType, (LPBYTE)&dwVal, &dwLen);
             if(ERROR_SUCCESS == lResult)

             { 
                   pBLInfo->m_bBatteryAuto = (BOOL) dwVal; 
             }

             lResult = RegQueryValueEx(hKey, szregACAuto, NULL, &dwType, (LPBYTE)&dwVal, &dwLen);
             if(ERROR_SUCCESS == lResult)

             {
                   pBLInfo->m_bACAuto = (BOOL) dwVal;
             }

             RegCloseKey(hKey);
      }
      else

      {
             RETAILMSG(1, (TEXT("BAK : HKEY_CURRENT_USER//%s key doesn't exist!/r/n"), szregRootKey));
      }


BOOL BL_Init()   // initialize the backlight
{
    //  Set up all the events we need. 
      g_evtSignal[0] = CreateEvent(NULL, FALSE, FALSE, szevtBacklightChange);
      g_evtSignal[1] = CreateEvent(NULL, FALSE, FALSE, szevtUserInput);
      g_evtSignal[BL_POWEREVT] = CreateEvent(NULL, FALSE, FALSE, szevtPowerChanged);
      if(!g_evtSignal[0] || !g_evtSignal[1] || !g_evtSignal[2])

      {
            BL_Deinit();
            return FALSE;
      }
      DEBUGMSG (1,(TEXT("BL_Init()  and  SetGPIO/n/r"))); 
      return TRUE;
}

 

void BL_Deinit()   // uninitialize the backlight
{
       int i;

       RETAILMSG(1, (TEXT("BAK : BL_Deinit!/r/n"))); 
       for(i=0; i<NUM_EVENTS; i++)       //  Clean up

       {
             if(g_evtSignal[i])

             {
                   CloseHandle(g_evtSignal[i]);
             }
       }
}

 

/*The backlight handling is done by a thread, which monitors those three event and performs some actions based on the parameters specified  */
DWORD BL_MonitorThread(PVOID pParms)   // backlight service thread
{
      DWORD   dwResult;
      DWORD   dwTimeout;
    
      g_BLInfo.m_bACAuto = TRUE;
      g_BLInfo.m_bBatteryAuto = TRUE;
      g_BLInfo.m_dwBatteryTimeout = 20;   // 20 Seconds
      g_BLInfo.m_dwACTimeout = 60;       // 1 minutes

      BL_ReadRegistry(&g_BLInfo);      //  Now read from the registry to see what they say
    
      if(!BL_Init())  //  Initialize BL
      {
            RETAILMSG(1, (TEXT("BL_Init() Failed! Exit from BL_MonitorThread!/r/n")));
            return 0; 
      }
      while(1)
      {
            __try
            {  

//  If we are using AC now, use m_dwACTimeout as the timeout,otherwise use m_dwBatteryTimeout
                  if(IsACOn())

                  {
                        dwTimeout = g_BLInfo.m_dwACTimeout * 1000;
                  }
                  else

                  {
                        dwTimeout = g_BLInfo.m_dwBatteryTimeout * 1000;
                  }

                  //  However, if user wants BL on all the time, we have to let him
                  //  do that. Or if we come back here, and BL is off, we want to 
                  //  put this thread to sleep until other event happens.
                  if(dwTimeout == 0 || g_BLInfo.m_dwStatus == BL_OFF)

                  {
                         dwTimeout = INFINITE;
                  }

                  //  Now let's wait for either there is an update on registry, or
                  //  there is user action on the device, or there is activity on
                  //  AC power supply.
                  dwResult = WaitForMultipleObjects(NUM_EVENTS, &g_evtSignal[0], FALSE, dwTimeout);

                  if(WAIT_OBJECT_0 == dwResult)   //背光时延被改变
                  { 
                         //  All we need to do is to read from registry and update the tick count
                         BL_ReadRegistry(&g_BLInfo); 
                         //  Always turn on the Backlight after a change to registry
                         BL_On(TRUE); 
                  }
                  else if(dwResult == WAIT_OBJECT_0+1)
                  {
                         //User activity, depending on the situation, we may / may not update the tick count 
                         if(IsACOn())
                         {
                              if(g_BLInfo.m_bACAuto)

                              {
                                    BL_On(TRUE); 
                              }
                         }
                         else

                         {
                               if(g_BLInfo.m_bBatteryAuto)

                               {
                                     BL_On(TRUE);
                               }
                         }  
                   }
                   else if(dwResult == WAIT_OBJECT_0+2)

                   { 
                         //  When AC is plugged or un-plugged, we don't really need to do anything
                         //  We continue the loop. The correct timeout value will be assigned at
                         //  the top of the while loop.
                         RETAILMSG(1, (TEXT("BackLight Thread: power changed!/r/n")));
                   }
                   else if(dwResult == WAIT_TIMEOUT)

                   {
                         //  Time out, let's turn the device off 
                         RETAILMSG(1, (TEXT("Timeout, turn off the backlight!/r/n")));
                         BL_On(FALSE);
                   }
            }
             __except(EXCEPTION_EXECUTE_HANDLER)

            {
                   RETAILMSG(1, (TEXT("an exception is raised in BL_MonitorThread... /r/n")));
            }
      } //while
}

 

另补充对应的IOCTL处理函数:

BOOL BKL_IOControl(DWORD dwOpenContext, DWORD dwIoControlCode, LPBYTE lpInBuf, DWORD nInBufSize, LPBYTE lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned)
{
       DWORD dwErr = ERROR_INVALID_PARAMETER;
       // Verify context
       if(! dwOpenContext)
       {
              RETAILMSG(ZONE_ERROR, (L"ERROR: BKL_Deinit: "L"Incorrect context paramer/r/n" ));
              return FALSE;
       }

       switch (dwIoControlCode)
       {
              case IOCTL_POWER_CAPABILITIES: 
                     RETAILMSG(ZONE_BACKLIGHT, (TEXT("BKL: IOCTL_POWER_CAPABILITIES/r/n")));
                     ................;
                     break;
              case IOCTL_POWER_QUERY: // determines whether changing power state is feasible
                     RETAILMSG(ZONE_BACKLIGHT,(TEXT("BKL: Received IOCTL_POWER_QUERY/r/n")));
                     ...............;
                     break;
              case IOCTL_POWER_SET: // requests a change from one device power state to another
                     RETAILMSG(ZONE_BACKLIGHT,(TEXT("BKL: Received IOCTL_POWER_SET/r/n")));
                     ..............;
                     break;
              case IOCTL_POWER_GET: // gets the current device power state
                     RETAILMSG(ZONE_BACKLIGHT,(TEXT("BKL: Received IOCTL_POWER_GET/r/n")));

                     ..............;
                     break;
              default:    
                     dwErr = BacklightIOControl(pBKLinfo->dwPddContext, dwIoControlCode, lpInBuf, nInBufSize, lpOutBuf, nOutBufSize, lpBytesReturned);
                     RETAILMSG(ZONE_BACKLIGHT,(TEXT("BacklightIOControl IOCTL code %u/r/n"), dwIoControlCode));
                     break;
        }
}

//对补充的IOCTL码处理

DWORD BacklightIOControl(DWORD dwOpenContext, DWORD dwIoControlCode, LPBYTE lpInBuf, DWORD nInBufSize, LPBYTE lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned)
{
        DWORD ret = ERROR_SUCCESS;
        switch(dwIoControlCode)
        {
               case BLK_IOCTL_SET_BRIGHTNESS:
               ..........................;
               break;
               case BLK_IOCTL_GET_BRIGHTNESS:
               ..........................;
               break;
               case BLK_IOCTL_GET_MINFREQ:
               ..........................;
               break;
               case BLK_IOCTL_SET_MINFREQ:
               ..........................;
               break;
               default:
                     ret = !ERROR_SUCCESS;
               break;
       }
       return ret;
}

 

参考原文:http://blog.csdn.net/cy757/archive/2008/08/07/2783730.aspx