Add Display HAL and Touchscreen HAL
[platform/adaptation/RPI3/device-manager-plugin-RPI3.git] / hw / touchscreen / touchscreen.c
1 /*
2  * device-node
3  *
4  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <linux/limits.h>
25 #include <dirent.h>
26 #include <fcntl.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <sys/utsname.h>
32
33 #include <hw/touchscreen.h>
34 #include "../shared.h"
35
36 #define TURNON_TOUCHSCREEN     1
37 #define TURNOFF_TOUCHSCREEN    0
38
39 #define MODULES_FILE_NAME       "/proc/modules"
40 #define MODULE_KO_NAME          "rpi-ft5406.ko"
41 #define MODULE_NAME                     "rpi_ft5406"
42
43 #define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
44 #define delete_module(name, flags) syscall(__NR_delete_module, name, flags)
45
46 static int find_module(char *name)
47 {
48         FILE *fp = fopen(MODULES_FILE_NAME, "rt");
49         if (fp == NULL) {
50                 _E("Can not open file(%s).\n", MODULES_FILE_NAME);
51                 return -ENOENT;
52         }
53
54         int found = 0;
55         char mod_str[256];
56         char mod_name[256];
57         for (; fgets(mod_str, sizeof(mod_str), fp); ) {
58                 sscanf(mod_str, "%s ", mod_name);
59                 if (strcmp(mod_name, name) == 0) {
60                         _E("[%s]\t%s", mod_name, mod_str);
61                         found = 1;
62                         break;
63                 }
64         }
65
66         fclose(fp);
67
68         return found;
69 }
70
71 static int get_module_path(char *name, char *path)
72 {
73         struct utsname utsn;
74
75         int ret = uname(&utsn);
76         if (ret != 0)
77                 return ret;
78
79         sprintf(path, "/lib/modules/%s/%s", utsn.release, name);
80
81         return 0;
82 }
83
84 static int ins_module(char *name)
85 {
86         char path[512];
87
88         if (get_module_path(name, path) != 0)
89                 return -EEXIST;
90
91         int fd = open(path, O_RDONLY);
92         if (fd < 0) {
93                 _E("Can not open module(%s).\n", path);
94                 return -EEXIST;
95         }
96
97         struct stat st;
98         int ret = fstat(fd, &st);
99         if (ret < 0) {
100                 _E("Module fstat error(%s).\n", path);
101                 close(fd);
102                 return -EIO;
103         }
104
105         size_t image_size = st.st_size;
106         void *image = malloc(image_size);
107         if (image == NULL) {
108                 _E("Memory allocation errorr.\n");
109                 close(fd);
110                 return -ENOMEM;
111         }
112
113         ssize_t size = read(fd, image, image_size);
114         if (size != image_size) {
115                 _E("Module file read error(%d).\n", size);
116                 free(image);
117                 close(fd);
118                 return -EIO;
119         }
120         close(fd);
121
122         ret = init_module(image, image_size, "");
123         if (ret < 0) {
124                 _E("init_module error(%d).\n", ret);
125                 free(image);
126                 return -EIO;
127         }
128         free(image);
129
130         return 0;
131 }
132
133 static int rm_module(char *name)
134 {
135         int ret = delete_module(name, O_NONBLOCK);
136         if (ret != 0) {
137                 _E("delete_module error(%d).\n", ret);
138                 return -EIO;
139         }
140
141         return 0;
142 }
143
144
145 static int touchscreen_get_state(enum touchscreen_state *state)
146 {
147         int ret;
148
149         if (!state)
150                 return -EINVAL;
151
152         ret = find_module(MODULE_NAME);
153         if (ret < 0) {
154                 _E("Failed to get touchscreen state (%d)", ret);
155                 return ret;
156         }
157
158         switch (ret) {
159                 case TURNOFF_TOUCHSCREEN:
160                         *state = TOUCHSCREEN_OFF;
161                         break;
162                 case TURNON_TOUCHSCREEN:
163                         *state = TOUCHSCREEN_ON;
164                         break;
165         }
166
167         return 0;
168 }
169
170 static int touchscreen_set_state(enum touchscreen_state state)
171 {
172         int ret = 0;
173
174         switch (state) {
175                 case TOUCHSCREEN_OFF:
176                         ret = rm_module(MODULE_NAME);
177                         break;
178                 case TOUCHSCREEN_ON:
179                         ret = ins_module(MODULE_KO_NAME);
180                         break;
181                 default:
182                         _E("Invalid input (%d)", state);
183                         return -EINVAL;
184         }
185
186         return ret;
187 }
188
189 static int touchscreen_open(struct hw_info *info,
190                 const char *id, struct hw_common **common)
191 {
192         struct touchscreen_device *touchscreen_dev;
193
194         if (!info || !common)
195                 return -EINVAL;
196
197         touchscreen_dev = calloc(1, sizeof(struct touchscreen_device));
198         if (!touchscreen_dev)
199                 return -ENOMEM;
200
201         touchscreen_dev->common.info = info;
202         touchscreen_dev->get_state = touchscreen_get_state;
203         touchscreen_dev->set_state = touchscreen_set_state;
204
205         *common = (struct hw_common *)touchscreen_dev;
206         return 0;
207 }
208
209 static int touchscreen_close(struct hw_common *common)
210 {
211         if (!common)
212                 return -EINVAL;
213
214         free(common);
215         return 0;
216 }
217
218 HARDWARE_MODULE_STRUCTURE = {
219         .magic = HARDWARE_INFO_TAG,
220         .hal_version = HARDWARE_INFO_VERSION,
221         .device_version = TOUCHSCREEN_HARDWARE_DEVICE_VERSION,
222         .id = TOUCHSCREEN_HARDWARE_DEVICE_ID,
223         .name = "touchscreen",
224         .open = touchscreen_open,
225         .close = touchscreen_close,
226 };