⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fanstuff.cpp

📁 通过EC的SMBUS接口读取电池信息
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			}*/

			// protocol, address, command, len, data
			status = this->ECSMBusRead(this->ECSMBusBaseOffsetInERAM, PRTC_Read_Block, BATTERY_ADDRESS_IN_EC_SMBUS, 0x21, &ReturnLen, ReturnData);
			if( ReturnLen <= 32) 
			{
				for( i=0;i< ReturnLen;i++)
					sprintf(templist+strlen(templist), "%c", *(ReturnData+i));
			}
			else
					sprintf(templist+strlen(templist), "%s %x ", "error",status);

			
			templist[strlen(templist)-1]= '\0';
			sprintf(this->CurrentStatus, "(%s)", templist);
			::SetDlgItemText(this->hwndDialog, 8113, this->CurrentStatus);
			this->HasReadDeviceName = TRUE;
	}


	strcpy(templist, "");

	// protocol, address, command, len, data
	this->ECSMBusRead(this->ECSMBusBaseOffsetInERAM, PRTC_Read_Word, BATTERY_ADDRESS_IN_EC_SMBUS, CMD_Voltage, &ReturnLen, ReturnData);

	sprintf(templist+strlen(templist), "  v:%dmV   ", *(unsigned short*)ReturnData);

	// protocol, address, command, len, data
	this->ECSMBusRead(this->ECSMBusBaseOffsetInERAM, PRTC_Read_Word, BATTERY_ADDRESS_IN_EC_SMBUS, CMD_Current, &ReturnLen, ReturnData);

	sprintf(templist+strlen(templist), "I:%dmA   ", *(short*)ReturnData);

	// protocol, address, command, len, data
	this->ECSMBusRead(this->ECSMBusBaseOffsetInERAM, PRTC_Read_Word, BATTERY_ADDRESS_IN_EC_SMBUS, CMD_RemainingCapacity, &ReturnLen, ReturnData);

	sprintf(templist+strlen(templist), "C:%dmAh   ", *(unsigned short*)ReturnData);

	// protocol, address, command, len, data
	this->ECSMBusRead(this->ECSMBusBaseOffsetInERAM, PRTC_Read_Word, BATTERY_ADDRESS_IN_EC_SMBUS, CMD_FullChargeCapacity, &ReturnLen, ReturnData);

	sprintf(templist+strlen(templist), "FC:%dmAh   ", *(unsigned short*)ReturnData);

	templist[strlen(templist)-1]= '\0';
	sprintf(this->CurrentStatus, "(%s)", templist);
	::SetDlgItemText(this->hwndDialog, 8112, this->CurrentStatus);

}
	//
	// handle fan control according to mode
	//
/*
	this->CurrentModeFromDialog();

	switch (this->CurrentMode) {

		case 1: // Bios Auto
				if (this->State.FanCtrl!=0x080) 
					ok= this->SetFan("Mode switch", 0x80);
				break;


		case 2: // Smart
				this->SmartControl();
				break;


		case 3: // fixed manual
				::GetDlgItemText(this->hwndDialog, 8310, manlevel, sizeof(manlevel));

				if (isdigit(manlevel[0]) && atoi(manlevel)>=0 && atoi(manlevel)<=255) {

					if (this->State.FanCtrl!=atoi(manlevel)) {
						ok= this->SetFan("Manual", atoi(manlevel));
					}
					else 
						ok= true;
				}
				break;
	}

	this->PreviousMode= this->CurrentMode;
*/

	return ok;
}




//-------------------------------------------------------------------------
//  smart fan control depending on temperature
//-------------------------------------------------------------------------
int 
FANCONTROL::SmartControl(void)
{
	int ok= 0, i,
		newfanctrl= -1,	
		fanctrl= this->State.FanCtrl;	


	// if currently auto force initial fan speed according to rules
	if ((fanctrl & 0x80)!=0 && this->PreviousMode==1) {  
		fanctrl= -1;
		newfanctrl= 0;
	}

	// check for fan-up
	for (i= 0; this->SmartLevels[i].temp!=-1; i++) {
		if (this->MaxTemp>=this->SmartLevels[i].temp && this->SmartLevels[i].fan>fanctrl) 
			newfanctrl= this->SmartLevels[i].fan; 
	}

	// not uptriggered check for downtrigger (previous level hit)
	if (newfanctrl==-1) {	
		for (i= 0; this->SmartLevels[i].temp!=-1; i++) {
			if (this->MaxTemp<=this->SmartLevels[i].temp && this->SmartLevels[i].fan<fanctrl) {
				newfanctrl= this->SmartLevels[i].fan; 
				break;
			}
		}
	}

	// fan speed needs change?
	if (newfanctrl!=-1 && newfanctrl!=fanctrl) {

		if (newfanctrl==0x80) { // switch to BIOS-auto mode
		//	this->ModeToDialog(1); // bios
		}
			
		ok= this->SetFan("Smart", newfanctrl);			
	}

	return ok;
}



//-------------------------------------------------------------------------
//  set fan state via EC
//-------------------------------------------------------------------------
int 
FANCONTROL::SetFan(const char *source, int fanctrl, BOOL final)
{
	int ok= 0;
	char obuf[256]= "", obuf2[256], datebuf[128];

	if (this->FanBeepFreq && this->FanBeepDura)
		::Beep(this->FanBeepFreq, this->FanBeepDura);

	this->CurrentDateTimeLocalized(datebuf, sizeof(datebuf));

	
	sprintf(obuf+strlen(obuf), "%s: Set fan control to 0x%02x, ", source, fanctrl);
	sprintf(obuf+strlen(obuf), "Result: ");

	if (this->ActiveMode && !this->FinalSeen) {

		this->EcAccess.Lock();

		// set new fan level
		ok= this->WriteByteToEC(TP_ECOFFSET_FAN, fanctrl);

		// verify completion
		ok= this->ReadByteFromEC(TP_ECOFFSET_FAN, &this->State.FanCtrl);

		if (ok && final) 
			this->FinalSeen= true;	// prevent further changes when setting final mode

		this->EcAccess.Unlock();

		if (this->State.FanCtrl==fanctrl) {
			sprintf(obuf+strlen(obuf), "OK");
			ok= true;
		}
		else {
			sprintf(obuf+strlen(obuf), "COULD NOT SET FAN STATE!!!!");

			::Beep(880, 300);
			::Sleep(200);
			::Beep(880, 300);
			::Sleep(200);
			::Beep(880, 300);
			ok= false;
		}
	}
	else {
		sprintf(obuf+strlen(obuf), "CMD IGNORED (PASSIVE MODE)");
	}

	// display result
	sprintf(obuf2, "%s   (%s)", obuf, datebuf);
	::SetDlgItemText(this->hwndDialog, 8113, obuf2);

	this->Trace(this->CurrentStatus);
	this->Trace(obuf);

	if (!final)
		::PostMessage(this->hwndDialog, WM__GETDATA, 0, 0);

	return ok;
}



//-------------------------------------------------------------------------
//  read fan and temperatures from embedded controller
//-------------------------------------------------------------------------
int 
FANCONTROL::ReadEcStatus(FCSTATE *pfcstate)
{
	DWORD i, ok, rc= 0;

	FCSTATE sample= { 0, }, 
			sample2= { 0, };

	setzero(pfcstate, sizeof(*pfcstate));

	
	// reading from the EC seems to yield erratic results at times (probably
	// due to collision with other drivers reading from the port).  So try
	// up to three times to read two samples which look oka and have matching
	// value

	this->EcAccess.Lock();

	for (i= 0; i<3; i++) {
		ok= this->ReadEcRaw(&sample);
		if (ok) {
			ok= this->ReadEcRaw(&sample2);
			if (ok) {

				// match for identical fanctrl settings and temperature differences
				// of no more than 1癈
				BOOL match= sample.FanCtrl==sample2.FanCtrl;
				for (int j= 0; j<12 && match; j++) {
					if (sample.Sensors[j]>128 || sample2.Sensors[j]>128 ||
						abs(sample.Sensors[j]-sample2.Sensors[j])>1) {
						match= false;
					}
				}
				
				if (match) {	// looks good
					ok= true;
					break;
				}
				else {		// try again after short delay
					ok= false;
					::Sleep(200);
				}
			}
		}
	} 

	this->EcAccess.Unlock();

	if (ok) {
		memcpy(pfcstate, &sample, sizeof(*pfcstate));
	}

	return ok;
}



//-------------------------------------------------------------------------
//  read fan and temperatures from embedded controller
//-------------------------------------------------------------------------
int 
FANCONTROL::ReadEcRaw(FCSTATE *pfcstate)
{
	int i, idxtemp, ok;

	pfcstate->FanSpeedLo= 0;
	pfcstate->FanSpeedHi= 0;
	pfcstate->FanCtrl= -1;
	memset(pfcstate->Sensors, 0, sizeof(pfcstate->Sensors));

	
	ok= ReadByteFromEC(TP_ECOFFSET_FAN, &pfcstate->FanCtrl);

	if (ok)
		ok= ReadByteFromEC(TP_ECOFFSET_FANSPEED, &pfcstate->FanSpeedLo);

	if (ok)
		ok= ReadByteFromEC(TP_ECOFFSET_FANSPEED+1, &pfcstate->FanSpeedHi);

	idxtemp= 0;
	for (i= 0; i<8 && ok; i++) {	// temp sensors 0x78 - 0x7f
		ok= ReadByteFromEC(TP_ECOFFSET_TEMP0+i, &pfcstate->Sensors[idxtemp]);
		pfcstate->SensorAddr[idxtemp]= TP_ECOFFSET_TEMP0+i;
		pfcstate->SensorName[idxtemp]= gSensorNames[idxtemp];
		idxtemp++;
	}

	for (i= 0; i<4 && ok; i++) {	// temp sensors 0xC0 - 0xC4
		ok= ReadByteFromEC(TP_ECOFFSET_TEMP1+i, &pfcstate->Sensors[idxtemp]);
		pfcstate->SensorAddr[idxtemp]= TP_ECOFFSET_TEMP1+i;
		pfcstate->SensorName[idxtemp]= gSensorNames[idxtemp];
		idxtemp++;
	}

	return ok;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -