1 /*
2  * Copyright © 2009 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Zhenyu Wang <zhenyu.z.wang@intel.com>
25  *
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <pciaccess.h>
33 #include <err.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <dirent.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 
40 #include "intel_io.h"
41 #include "intel_reg.h"
42 #include "intel_chipset.h"
43 
44 #define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
45 
46 enum lid_status {
47 	LID_UNKNOWN = -1,
48 	LID_OPEN,
49 	LID_CLOSE,
50 };
51 
52 #define ACPI_BUTTON "/proc/acpi/button/"
53 #define ACPI_LID "/proc/acpi/button/lid/"
54 
i830_lvds_acpi_lid_state(void)55 static int i830_lvds_acpi_lid_state(void)
56 {
57 	int fd;
58 	DIR *button_dir;
59 	DIR *lid_dir;
60 	struct dirent *lid_dent;
61 	char *state_name;
62 	char state[64];
63 	enum lid_status ret = LID_UNKNOWN;
64 
65 	button_dir = opendir(ACPI_BUTTON);
66 	/* If acpi button driver is not loaded, bypass ACPI check method */
67 	if (button_dir == NULL)
68 		goto out;
69 	closedir(button_dir);
70 
71 	lid_dir = opendir(ACPI_LID);
72 
73 	/* no acpi lid object found */
74 	if (lid_dir == NULL)
75 		goto out;
76 
77 	while (1) {
78 		lid_dent = readdir(lid_dir);
79 		if (lid_dent == NULL) {
80 			/* no LID object */
81 			closedir(lid_dir);
82 			goto out;
83 		}
84 		if (strcmp(lid_dent->d_name, ".") &&
85 		    strcmp(lid_dent->d_name, "..")) {
86 			break;
87 		}
88 	}
89 	state_name = malloc(strlen(ACPI_LID) + strlen(lid_dent->d_name) + 7);
90 	memset(state_name, 0, strlen(ACPI_LID) + strlen(lid_dent->d_name) + 7);
91 	strcat(state_name, ACPI_LID);
92 	strcat(state_name, lid_dent->d_name);
93 	strcat(state_name, "/state");
94 
95 	closedir(lid_dir);
96 
97 	if ((fd = open(state_name, O_RDONLY)) == -1) {
98 		free(state_name);
99 		goto out;
100 	}
101 	free(state_name);
102 	if (read(fd, state, 64) == -1) {
103 		close(fd);
104 		goto out;
105 	}
106 	close(fd);
107 	if (strstr(state, "open"))
108 		ret = LID_OPEN;
109 	else if (strstr(state, "closed"))
110 		ret = LID_CLOSE;
111 	else			/* "unsupported" */
112 		ret = LID_UNKNOWN;
113 
114 out:
115 	return ret;
116 }
117 
main(int argc,char ** argv)118 int main(int argc, char **argv)
119 {
120 	int swf14, acpi_lid;
121 
122 	intel_mmio_use_pci_bar(intel_get_pci_device());
123 
124 	while (1) {
125 		swf14 = INREG(SWF14);
126 
127 		printf("Intel LVDS Lid status:\n");
128 		printf("\tSWF14(0x%x) : %s\n", swf14,
129 		       swf14 & SWF14_LID_STATUS_CLOSED ? "close" : "open");
130 
131 		acpi_lid = i830_lvds_acpi_lid_state();
132 		switch (acpi_lid) {
133 		case LID_UNKNOWN:
134 			printf("\tACPI Lid state : unknown\n");
135 			break;
136 		case LID_OPEN:
137 			printf("\tACPI Lid state : open\n");
138 			break;
139 		case LID_CLOSE:
140 			printf("\tACPI Lid state : close\n");
141 			break;
142 		}
143 		sleep(2);
144 	}
145 	return 0;
146 }
147