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

📄 apm.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include </386/include/ureg.h>typedef struct Ureg Ureg;#include <auth.h>#include <fcall.h>#include <thread.h>#include <9p.h>enum {	/* power mgmt event codes */	NotifyStandbyRequest		= 0x0001,	NotifySuspendRequest		= 0x0002,	NotifyNormalResume 		= 0x0003,	NotifyCriticalResume		= 0x0004,	NotifyBatteryLow			= 0x0005,	NotifyPowerStatusChange	= 0x0006,	NotifyUpdateTime			= 0x0007,	NotifyCriticalSuspend		= 0x0008,	NotifyUserStandbyRequest	= 0x0009,	NotifyUserSuspendRequest	= 0x000A,	NotifyStandbyResume		= 0x000B,	NotifyCapabilitiesChange		= 0x000C,	/* power device ids: add device number or All */	DevBios					= 0x0000,	DevAll					= 0x0001,	DevDisplay				= 0x0100,	DevStorage				= 0x0200,	DevLpt					= 0x0300,	DevEia					= 0x0400,	DevNetwork				= 0x0500,	DevPCMCIA				= 0x0600,	DevBattery				= 0x8000,		All					= 0x00FF,	DevMask					= 0xFF00,	/* power states */	PowerEnabled				= 0x0000,	PowerStandby				= 0x0001,	PowerSuspend				= 0x0002,	PowerOff					= 0x0003,	/* apm commands */	CmdInstallationCheck		= 0x5300,	CmdRealModeConnect		= 0x5301,	CmdProtMode16Connect		= 0x5302,	CmdProtMode32Connect		= 0x5303,	CmdDisconnect			= 0x5304,	CmdCpuIdle				= 0x5305,	CmdCpuBusy				= 0x5306,	CmdSetPowerState			= 0x5307,	CmdSetPowerMgmt	= 0x5308,	  DisablePowerMgmt	= 0x0000,		/* CX */	  EnablePowerMgmt	= 0x0001,	CmdRestoreDefaults			= 0x5309,	CmdGetPowerStatus			= 0x530A,	CmdGetPMEvent			= 0x530B,	CmdGetPowerState			= 0x530C,	CmdGetPowerMgmt			= 0x530D,	CmdDriverVersion			= 0x530E,	/* like CmdDisconnect but doesn't lose the interface */	CmdGagePowerMgmt	= 0x530F,	  DisengagePowerMgmt	= 0x0000,	/* CX */	  EngagePowerManagemenet	= 0x0001,	CmdGetCapabilities			= 0x5310,	  CapStandby				= 0x0001,	  CapSuspend				= 0x0002,	  CapTimerResumeStandby	= 0x0004,	  CapTimerResumeSuspend	= 0x0008,	  CapRingResumeStandby		= 0x0010,	  CapRingResumeSuspend	= 0x0020,	  CapPcmciaResumeStandby	= 0x0040,	  CapPcmciaResumeSuspend	= 0x0080,	  CapSlowCpu				= 0x0100,	CmdResumeTimer			= 0x5311,	  DisableResumeTimer		= 0x00,		/* CL */	  GetResumeTimer			= 0x01,	  SetResumeTimer			= 0x02,	CmdResumeOnRing			= 0x5312,	  DisableResumeOnRing		= 0x0000,		/* CX */	  EnableResumeOnRing		= 0x0001,	  GetResumeOnRing			= 0x0002,	CmdTimerRequests			= 0x5313,	  DisableTimerRequests		= 0x0000,		/* CX */	  EnableTimerRequests		= 0x0001,	  GetTimerRequests			= 0x0002,};static char* eventstr[] = {[NotifyStandbyRequest]	"system standby request",[NotifySuspendRequest]	"system suspend request",[NotifyNormalResume]	"normal resume",[NotifyCriticalResume]	"critical resume",[NotifyBatteryLow]		"battery low",[NotifyPowerStatusChange]	"power status change",[NotifyUpdateTime]		"update time",[NotifyCriticalSuspend]	"critical suspend",[NotifyUserStandbyRequest]	"user standby request",[NotifyUserSuspendRequest]	"user suspend request",[NotifyCapabilitiesChange]	"capabilities change",};static char*apmevent(int e){	static char buf[32];	if(0 <= e && e < nelem(eventstr) && eventstr[e])		return eventstr[e];		sprint(buf, "event 0x%ux", (uint)e);	return buf;}static char *error[256] = {[0x01]	"power mgmt disabled",[0x02]	"real mode connection already established",[0x03]	"interface not connected",[0x05]	"16-bit protected mode connection already established",[0x06]	"16-bit protected mode interface not supported",[0x07]	"32-bit protected mode interface already established",[0x08]	"32-bit protected mode interface not supported",[0x09]	"unrecognized device id",[0x0A]	"parameter value out of range",[0x0B]	"interface not engaged",[0x0C]	"function not supported",[0x0D]	"resume timer disabled",[0x60]	"unable to enter requested state",[0x80]	"no power mgmt events pending",[0x86]	"apm not present",};static char*apmerror(int id){	char *e;	static char buf[64];	if(e = error[id&0xFF])		return e;	sprint(buf, "unknown error %x", id);	return buf;}QLock apmlock;int apmdebug;static int_apmcall(int fd, Ureg *u){if(apmdebug) fprint(2, "call ax 0x%lux bx 0x%lux cx 0x%lux\n",	u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF);	seek(fd, 0, 0);	if(write(fd, u, sizeof *u) != sizeof *u)		return -1;	seek(fd, 0, 0);	if(read(fd, u, sizeof *u) != sizeof *u)		return -1;if(apmdebug) fprint(2, "flags 0x%lux ax 0x%lux bx 0x%lux cx 0x%lux\n",	u->flags&0xFFFF, u->ax&0xFFFF, u->bx&0xFFFF, u->cx&0xFFFF);	if(u->flags & 1) {	/* carry flag */		werrstr("%s", apmerror(u->ax>>8));		return -1;	}	return 0;}static intapmcall(int fd, Ureg *u){	int r;	qlock(&apmlock);	r = _apmcall(fd, u);	qunlock(&apmlock);	return r;}typedef struct Apm Apm;typedef struct Battery Battery;struct Battery {	int status;	int percent;	int time;};enum {	Mbattery = 4,};struct Apm {	int fd;	int verhi;	int verlo;	int acstatus;	int nbattery;	int capabilities;	Battery battery[Mbattery];};enum {	AcUnknown = 0,		/* Apm.acstatus */	AcOffline,	AcOnline,	AcBackup,	BatteryUnknown = 0,	/* Battery.status */	BatteryHigh,	BatteryLow,	BatteryCritical,	BatteryCharging,};static char*acstatusstr[] = {[AcUnknown]	"unknown",[AcOffline]	"offline",[AcOnline]	"online",[AcBackup]	"backup",};static char*batterystatusstr[] = {[BatteryUnknown] "unknown",[BatteryHigh]	"high",[BatteryLow]	"low",[BatteryCritical]	"critical",[BatteryCharging]	"charging",};static char*powerstatestr[] = {[PowerOff]	"off",[PowerSuspend]	"suspend",[PowerStandby]	"standby",[PowerEnabled]	"on",};static char*xstatus(char **str, int nstr, int x){	if(0 <= x && x < nstr && str[x])		return str[x];	return "unknown";}static char*batterystatus(int b){	return xstatus(batterystatusstr, nelem(batterystatusstr), b);}static char*powerstate(int s){	return xstatus(powerstatestr, nelem(powerstatestr), s);}static char*acstatus(int a){	return xstatus(acstatusstr, nelem(acstatusstr), a);}	  static intapmversion(Apm *apm){	Ureg u;	u.ax = CmdDriverVersion;	u.bx = 0x0000;	u.cx = 0x0102;	if(apmcall(apm->fd, &u) < 0)		return -1;	apm->verhi = u.cx>>8;	apm->verlo = u.cx & 0xFF;	return u.cx;}static intapmcpuidle(Apm *apm){	Ureg u;	u.ax = CmdCpuIdle;	return apmcall(apm->fd, &u);}static intapmcpubusy(Apm *apm){	Ureg u;	u.ax = CmdCpuBusy;	return apmcall(apm->fd, &u);}static intapmsetpowerstate(Apm *apm, int dev, int state){	Ureg u;	u.ax = CmdSetPowerState;	u.bx = dev;	u.cx = state;	return apmcall(apm->fd, &u);}static intapmsetpowermgmt(Apm *apm, int dev, int state){	Ureg u;	u.ax = CmdSetPowerMgmt;	u.bx = dev;	u.cx = state;	return apmcall(apm->fd, &u);}static intapmrestoredefaults(Apm *apm, int dev){	Ureg u;	u.ax = CmdRestoreDefaults;	u.bx = dev;	return apmcall(apm->fd, &u);}static intapmgetpowerstatus(Apm *apm, int dev){	Battery *b;	Ureg u;	if(dev == DevAll)		b = &apm->battery[0];	else if((dev & DevMask) == DevBattery) {		if(dev - DevBattery < nelem(apm->battery))			b = &apm->battery[dev - DevBattery];		else			b = nil;	} else {		werrstr("bad device number");		return -1;	}	u.ax = CmdGetPowerStatus;	u.bx = dev;	if(apmcall(apm->fd, &u) < 0)		return -1;	if((dev & DevMask) == DevBattery)		apm->nbattery = u.si;	switch(u.bx>>8) {	case 0x00:		apm->acstatus = AcOffline;		break;	case 0x01:		apm->acstatus = AcOnline;		break;	case 0x02:		apm->acstatus = AcBackup;		break;	default:		apm->acstatus = AcUnknown;		break;	}	if(b != nil) {		switch(u.bx&0xFF) {		case 0x00:			b->status = BatteryHigh;			break;		case 0x01:			b->status = BatteryLow;			break;		case 0x02:			b->status = BatteryCritical;			break;		case 0x03:			b->status = BatteryCharging;			break;		default:			b->status = BatteryUnknown;			break;		}		if((u.cx & 0xFF) == 0xFF)			b->percent = -1;		else			b->percent = u.cx & 0xFF;		if((u.dx&0xFFFF) == 0xFFFF)			b->time = -1;		else if(u.dx & 0x8000)			b->time = 60*(u.dx & 0x7FFF);		else			b->time = u.dx & 0x7FFF;	}	return 0;}static intapmgetevent(Apm *apm){	Ureg u;	u.ax = CmdGetPMEvent;	u.bx = 0;	u.cx = 0;	//when u.bx == NotifyNormalResume or NotifyCriticalResume,	//u.cx & 1 indicates PCMCIA socket was on while suspended,	//u.cx & 1 == 0 indicates was off.	if(apmcall(apm->fd, &u) < 0)		return -1;	return u.bx;}static intapmgetpowerstate(Apm *apm, int dev){	Ureg u;	u.ax = CmdGetPowerState;	u.bx = dev;	u.cx = 0;	if(apmcall(apm->fd, &u) < 0)		return -1;	return u.cx;}static intapmgetpowermgmt(Apm *apm, int dev){	Ureg u;	u.ax = CmdGetPowerMgmt;	u.bx = dev;	if(apmcall(apm->fd, &u) < 0)		return -1;	return u.cx;}static intapmgetcapabilities(Apm *apm){	Ureg u;	u.ax = CmdGetCapabilities;	u.bx = DevBios;	if(apmcall(apm->fd, &u) < 0)		return -1;	apm->nbattery = u.bx & 0xFF;	apm->capabilities &= ~0xFFFF;	apm->capabilities |= u.cx;	return 0;}static intapminstallationcheck(Apm *apm){	Ureg u;	u.ax = CmdInstallationCheck;	u.bx = DevBios;	if(apmcall(apm->fd, &u) < 0)		return -1;	if(u.cx & 0x0004)		apm->capabilities |= CapSlowCpu;	else		apm->capabilities &= ~CapSlowCpu;	return 0;}voidapmsetdisplaystate(Apm *apm, int s){	apmsetpowerstate(apm, DevDisplay, s);}voidapmblank(Apm *apm){	apmsetdisplaystate(apm, PowerStandby);}voidapmunblank(Apm *apm){	apmsetdisplaystate(apm, PowerEnabled);}voidapmsuspend(Apm *apm){	apmsetpowerstate(apm, DevAll, PowerSuspend);}Apm apm;voidpowerprint(void){	print("%s", ctime(time(0)));	if(apmgetpowerstatus(&apm, DevAll) == 0) {		print("%d batteries\n", apm.nbattery);		print("battery 0: status %s percent %d time %d:%.2d\n",			batterystatus(apm.battery[0].status), apm.battery[0].percent,			apm.battery[0].time/60, apm.battery[0].time%60);	}}void*erealloc(void *v, ulong n){	v = realloc(v, n);	if(v == nil)		sysfatal("out of memory reallocating %lud", n);	setmalloctag(v, getcallerpc(&v));	return v;}void*emalloc(ulong n){	void *v;	v = malloc(n);	if(v == nil)		sysfatal("out of memory allocating %lud", n);	memset(v, 0, n);	setmalloctag(v, getcallerpc(&n));	return v;}char*estrdup(char *s){	int l;	char *t;	if (s == nil)		return nil;	l = strlen(s)+1;	t = emalloc(l);	memcpy(t, s, l);	setmalloctag(t, getcallerpc(&s));	return t;}char*

⌨️ 快捷键说明

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