背光驱动程序设计
1. 这里硬件接口使用S3C2450的GPB1,即定时器1.
定时器的输入频率 = PCLK /{prescaler value + 1} / {divider value}。
首先设置prescaler value:
然后设置divider value:
2. 接着设置TOUT1的定时器PWM脉宽:
3. 设置完这些就可以开启TOUT1了。代码如下:
4. 背光亮度调节代码如下(将亮度设置为10个级别):
5.以上事情都做完了后,就可以编写通用的流接口程序了。由于程序比较简单,这里
仅贴上XXX_IOControl的代码如下:
RETAILMSG(lqm_bakdbg, (TEXT("[lqm:BKL] IOCTL code = %d/r/n"), dwCode));
switch (dwCode)
{
case IOCTL_POWER_CAPABILITIES: // determines device-specific capabilities
RETAILMSG(DBGBAK, (TEXT("[lqm:BKL] IOCTL_POWER_CAPABILITIES/r/n")));
if (pBufOut && dwLenOut >= sizeof (POWER_CAPABILITIES) && pdwActualOut)
{
__try
{
PPOWER_CAPABILITIES PowerCaps = (PPOWER_CAPABILITIES)pBufOut;
// Right now supports D0 (permanently on) and D4(off) only.
memset(PowerCaps, 0, sizeof(*PowerCaps));
PowerCaps->DeviceDx = 0x12; //support D0, D1, D4
*pdwActualOut = sizeof(*PowerCaps);
bRc = TRUE;
dwErr = ERROR_SUCCESS;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(DBGBAK1, (TEXT("<BKL> exception in ioctl/r/n")));
}
}
else
bRc = FALSE;
break;
case IOCTL_POWER_QUERY: // determines whether changing power state is feasible
RETAILMSG(DBGBAK, (TEXT("<BKL> Received IOCTL_POWER_QUERY/r/n")));
if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
{
// Return a good status on any valid query, since we are always ready to
// change power states (if asked for state we don't support, we move to next highest, eg D3->D4).
__try
{
CEDEVICE_POWER_STATE ReqDx = *(PCEDEVICE_POWER_STATE)pBufOut;
if (VALID_DX(ReqDx))
{
// This is a valid Dx state so return a good status.
bRc = TRUE;
dwErr = ERROR_SUCCESS;
}
else
{
bRc = FALSE;
}
RETAILMSG(DBGBAK, (TEXT("<BKL> IOCTL_POWER_QUERY %s/r/n"), dwErr == ERROR_SUCCESS ? (TEXT("succeeded")) : (TEXT("failed")) ));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(DBGBAK1, (TEXT("<BKL> Exception in ioctl/r/n")));
}
}
else
bRc = FALSE;
break;
case IOCTL_POWER_SET: // requests a change from one device power state to another
RETAILMSG(lqm_bakdbg, (TEXT("[lqm:BKL] Received IOCTL_POWER_SET/r/n")));
if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
{
__try
{
CEDEVICE_POWER_STATE ReqDx = *(PCEDEVICE_POWER_STATE)pBufOut;
if (VALID_DX(ReqDx))
{
RETAILMSG(lqm_bakdbg,(TEXT("[lqm:BKL] Received IOCTL_POWER_SET=%d/r/n"), ReqDx));
if( ReqDx == (CEDEVICE_POWER_STATE)D2 || ReqDx == (CEDEVICE_POWER_STATE)D3)
bklStatus = (CEDEVICE_POWER_STATE)D4;
else
bklStatus = ReqDx;
//SetEvent(g_evtBacklight);
// 调整亮度值后调用函数执行调整
BAK_hw_setBL();
*(PCEDEVICE_POWER_STATE) pBufOut = bklStatus;
*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
bRc = TRUE;
dwErr = ERROR_SUCCESS;
RETAILMSG(lqm_bakdbg, (TEXT("[lqm:BKL] IOCTL_POWER_SET to D%d /r/n"), ReqDx));
}
else
{
bRc = FALSE;
RETAILMSG(DBGBAK1, (TEXT("<BKL> Invalid state request D%d/r/n"), ReqDx));
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(DBGBAK1, (TEXT("<BKL> Exception in ioctl/r/n")));
}
}
else
{
bRc = FALSE;
}
break;
case IOCTL_POWER_GET: // gets the current device power state
RETAILMSG(DBGBAK, (TEXT("<BKL> Received IOCTL_POWER_GET/r/n/n")));
if (pBufOut != NULL && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
{
__try
{
*(PCEDEVICE_POWER_STATE)pBufOut = getBacklightStatus();
bRc = TRUE;
dwErr = ERROR_SUCCESS;
RETAILMSG(DBGBAK, (TEXT("<BKL> IOCTL_POWER_GET: passing back %u/r/n"), getBacklightStatus()));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
RETAILMSG(DBGBAK1, (TEXT("<BKL> Exception in ioctl/r/n")));
}
}
else
bRc = FALSE;
break;
// 背光亮度调节
case IOCTL_BACKLIGHT_ADJUST:
if (pBufOut != NULL && (dwLenOut>=sizeof(DWORD)))
{
DWORD dwBackLight = *((DWORD*)pBufOut);
if((BAK_LEVEL_MAX <dwBackLight) || (BAK_LEVEL_MIN > dwBackLight ))
{
*(DWORD*)pBufOut = ERROR_INVALID_PARAMETER;
*pdwActualOut = sizeof(DWORD);
bRc = FALSE;
}
else
{
BAK_AdjuctBacklightLevel(*(DWORD*)pBufOut);
// Adjust backlight level.
*(DWORD*)pBufOut = ERROR_SUCCESS;
*pdwActualOut = sizeof(DWORD);
bRc = TRUE;
}
}
else
{
bRc = FALSE;
}
break;
case IOCTL_BACKLIGHT_GETLEVEL:
if (pBufOut != NULL && (dwLenOut>=sizeof(DWORD)))
{
// Return the current backlight level.
*(DWORD*)pBufOut = l_dwBackLightLevel;
*pdwActualOut = sizeof(DWORD);
bRc = TRUE;
}
else
{
bRc = FALSE;
}
break;
}
return(bRc);
}
可以看到有如下几个case:
IOCTL_POWER_CAPABILITIES;
IOCTL_POWER_QUERY;
IOCTL_POWER_SET;
IOCTL_POWER_GET;
IOCTL_BACKLIGHT_ADJUST;
IOCTL_BACKLIGHT_GETLEVEL;
其中
IOCTL_POWER_CAPABILITIES:代表电源管理器请求设备驱动返回设备支持的电源状态及相关特征;
IOCTL_POWER_SET:请求驱动更新设备的电源状态;
IOCTL_POWER_QUERY:电源管理器询问设备是否准备好进行状态切换;
IOCTL_POWER_GET:请求驱动返回当前设备的电源状态;
IOCTL_BACKLIGHT_ADJUST:调节背光亮度的接口;
IOCTL_BACKLIGHT_GETLEVEL:获取背光亮度级别的接口。
部分接口的具体调用见下一篇,背光调节的应用程序设计。