Initial import of code
[flashlight-appl] / src / flashlight_lib.c
1 /*
2  *  Flashlight applet (widget) for Maemo.
3  *  Copyright (C) 2009 Roman Moravcik
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <sys/ioctl.h>
29
30 #include <asm/types.h>
31 #include <linux/videodev2.h>
32
33 #include "flashlight_lib.h"
34
35 int flashlight_get_status (FlashlightContext_t *flashlight, int *status)
36 {
37         struct v4l2_control ctrl;
38
39         if (flashlight == NULL) {
40                 printf ("flashlight_get_status: flashlight context is not valid\n");
41                 return -1;
42         }
43
44         if (flashlight->fd == -1) {
45                 printf ("flashlight_get_status: device not openned\n");
46                 return -1;
47         }
48
49         *status = 0;
50
51         /* check short circuit fault */
52         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_SCP;
53         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
54                 printf ("flashlight_set_intensity: cannot get circuit fault status (%s)\n", strerror (errno));
55                 return -1;
56         }
57
58         if (ctrl.id)
59                 *status |= FLASHLIGHT_STATUS_SHORT_CIRCUT_FAULT;
60         else
61                 *status &= ~FLASHLIGHT_STATUS_SHORT_CIRCUT_FAULT;
62
63         /* check overtemperature fault */
64         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_OT;
65         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
66                 printf ("flashlight_set_intensity: cannot get overtemperature fault status (%s)\n", strerror (errno));
67                 return -1;
68         }
69
70         if (ctrl.id)
71                 *status |= FLASHLIGHT_STATUS_OVERTEMPERATURE_FAULT;
72         else
73                 *status &= ~FLASHLIGHT_STATUS_OVERTEMPERATURE_FAULT;
74
75         /* check timeout fault */
76         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_TMR;
77         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
78                 printf ("flashlight_set_intensity: cannot get timeout fault status (%s)\n", strerror (errno));
79                 return -1;
80         }
81
82         if (ctrl.id)
83                 *status |= FLASHLIGHT_STATUS_TIMEOUT_FAULT;
84         else
85                 *status &= ~FLASHLIGHT_STATUS_TIMEOUT_FAULT;
86
87         /* check overtemperature fault */
88         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_OV;
89         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
90                 printf ("flashlight_set_intensity: cannot get overvoltage fault status (%s)\n", strerror (errno));
91                 return -1;
92         }
93
94         if (ctrl.id)
95                 *status |= FLASHLIGHT_STATUS_OVERVOLTAGE_FAULT;
96         else
97                 *status &= ~FLASHLIGHT_STATUS_OVERVOLTAGE_FAULT;
98
99         return 0;
100 }
101
102 int flashlight_set_intensity (FlashlightContext_t *flashlight, int intensity)
103 {
104         struct v4l2_control ctrl;
105
106         if (flashlight == NULL) {
107                 printf ("flashlight_set_intensity: flashlight context is not valid\n");
108                 return -1;
109         }
110
111         if (flashlight->fd == -1) {
112                 printf ("flashlight_set_intensity: device not openned\n");
113                 return -1;
114         }
115
116         if (intensity > flashlight->max_intensity)
117                 intensity = flashlight->max_intensity;
118
119         ctrl.id = V4L2_CID_TORCH_INTENSITY;
120         ctrl.value = intensity;
121
122         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
123                 printf ("flashlight_set_intensity: cannot set intensity (%s)\n", strerror (errno));
124                 return -1;
125         }
126
127         return 0;
128 }
129
130 int flashlight_get_intensity (FlashlightContext_t *flashlight, int *intensity)
131 {
132         struct v4l2_control ctrl;
133
134         if (flashlight == NULL) {
135                 printf ("flashlight_get_intensity: flashlight context is not valid\n");
136                 return -1;
137         }
138
139         if (flashlight->fd == -1) {
140                 printf ("flashlight_get_intensity: device not openned\n");
141                 return -1;
142         }
143
144         ctrl.id = V4L2_CID_TORCH_INTENSITY;
145
146         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
147                 printf ("flashlight_get_intensity: cannot get intensity (%s)\n", strerror (errno));
148                 return -1;
149         }
150
151         *intensity = ctrl.value;
152         return 0;
153 }
154
155 int flashlight_open (FlashlightContext_t *flashlight, const char *device_name)
156 {
157         struct v4l2_queryctrl ctrl;
158         struct stat st;
159
160         if (flashlight == NULL) {
161                 printf ("flashlight_open: flashlight context is not valid\n");
162                 return -1;
163         }
164
165         if (device_name == NULL) {
166                 printf ("flashlight_open: device name not specified\n");
167                 return -1;
168         }
169
170         memcpy (flashlight->device_name, device_name, sizeof(flashlight->device_name));
171
172         if (stat (flashlight->device_name, &st) == -1) {
173                 printf ("flashlight_open: cannot identify '%s' (%s)\n", flashlight->device_name, strerror (errno));
174                 return -1;
175         }
176
177         /* check it device_name is real device */
178         if (!S_ISCHR (st.st_mode)) {
179                 printf ("flashlight_open: %s is no device\n", flashlight->device_name);
180                 return -1;
181         }
182
183         flashlight->fd = open (flashlight->device_name, O_RDWR /* required */ | O_NONBLOCK, 0);
184
185         if (flashlight->fd == -1) {
186                 printf ("flashlight_open: cannot open '%s' (%s)\n", flashlight->device_name, strerror (errno));
187                 return -1;
188         }
189
190         /* query from driver minimal and maximal flashlight intensity */
191         ctrl.id = V4L2_CID_TORCH_INTENSITY;
192         if (ioctl (flashlight->fd, VIDIOC_QUERYCTRL, &ctrl) == -1) {
193                 printf ("flashlight_open: cannot get minimal and maximal flashlight intensity (%s)\n", strerror (errno));
194                 return -1;
195         }
196
197         flashlight->min_intensity = ctrl.minimum;
198         flashlight->max_intensity = ctrl.maximum;
199
200         return 0;
201 }
202
203 int flashlight_close (FlashlightContext_t *flashlight)
204 {
205         if (flashlight == NULL) {
206                 printf ("flashlight_close: flashlight context is not valid\n");
207                 return -1;
208         }
209
210         if (flashlight->fd != -1) {
211                 if (close (flashlight->fd) == -1) {
212                         printf ("flashlight_close: cannot close device '%s' (%s)\n", flashlight->device_name, strerror (errno));
213                         return -1;
214                 }
215         }
216
217         flashlight->fd = -1;
218         return 0;
219 }
220
221 int flashlight_init (FlashlightContext_t **pRefContext)
222 {
223         FlashlightContext_t *flashlight = NULL;
224
225         if (*pRefContext != NULL) {
226                 printf("flashlight_init: expecting zero pointer context '*pRefContext'\n");
227                 return -1;
228         }
229
230         /* allocate memory for context structure */
231         flashlight = malloc (sizeof (FlashlightContext_t));
232         if (flashlight == NULL) {
233                 printf ("flashlight_init: unable to allocate memory for context\n");
234                 return -1;
235         }
236
237         *pRefContext = flashlight;
238
239         /* initialize default values */
240         memset (flashlight, 0x00, sizeof (FlashlightContext_t));
241         flashlight->fd = -1;
242
243         /* from adp1653.c */
244         flashlight->min_intensity = 0;
245         flashlight->max_intensity = 11;
246
247         return 0;
248 }
249
250 int flashlight_deinit (FlashlightContext_t *flashlight)
251 {
252         int intensity = 0;
253
254         if (flashlight == NULL) {
255                 printf ("flashlight_deinit: flashlight context is not valid\n");
256                 return -1;
257         }
258
259         if (flashlight->fd != -1) {
260                 /* check if flashlight isn't enabled before closing device */
261                 if (flashlight_get_intensity (flashlight, &intensity) == -1)
262                         return -1;
263
264                 if (intensity > 0) {
265                         if (flashlight_set_intensity (flashlight, 0) == -1)
266                                 return -1;
267                 }
268
269                 if (flashlight_close(flashlight))
270                         return -1;
271         }
272
273         /* free allocated memory */
274         free (flashlight);
275
276         return 0;
277 }