6f56edee105a734339a9e94ac6b0361ace8b06e7
[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         printf ("flashlight_get_status()\n");
40
41         if (flashlight == NULL) {
42                 printf ("flashlight_get_status: flashlight context is not valid\n");
43                 return ENOCONTEXT;
44         }
45
46         if (flashlight->fd == -1) {
47                 printf ("flashlight_get_status: device not openned\n");
48                 return ENODEVICE;
49         }
50
51         *status = 0;
52
53         /* check short circuit fault */
54         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_SCP;
55         if (ioctl (flashlight->fd, VIDIOC_G_CTRL, &ctrl) == -1) {
56                 printf ("flashlight_set_intensity: cannot get circuit fault status (%s)\n", strerror (errno));
57                 return EGENERROR;
58         }
59
60         if (ctrl.value)
61                 *status |= FLASHLIGHT_STATUS_SHORT_CIRCUT_FAULT;
62         else
63                 *status &= ~FLASHLIGHT_STATUS_SHORT_CIRCUT_FAULT;
64
65         /* check overtemperature fault */
66         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_OT;
67         if (ioctl (flashlight->fd, VIDIOC_G_CTRL, &ctrl) == -1) {
68                 printf ("flashlight_set_intensity: cannot get overtemperature fault status (%s)\n", strerror (errno));
69                 return EGENERROR;
70         }
71
72         if (ctrl.value)
73                 *status |= FLASHLIGHT_STATUS_OVERTEMPERATURE_FAULT;
74         else
75                 *status &= ~FLASHLIGHT_STATUS_OVERTEMPERATURE_FAULT;
76
77         /* check timeout fault */
78         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_TMR;
79         if (ioctl (flashlight->fd, VIDIOC_G_CTRL, &ctrl) == -1) {
80                 printf ("flashlight_set_intensity: cannot get timeout fault status (%s)\n", strerror (errno));
81                 return EGENERROR;
82         }
83
84         if (ctrl.value)
85                 *status |= FLASHLIGHT_STATUS_TIMEOUT_FAULT;
86         else
87                 *status &= ~FLASHLIGHT_STATUS_TIMEOUT_FAULT;
88
89         /* check overtemperature fault */
90         ctrl.id = V4L2_CID_FLASH_ADP1653_FAULT_OV;
91         if (ioctl (flashlight->fd, VIDIOC_G_CTRL, &ctrl) == -1) {
92                 printf ("flashlight_set_intensity: cannot get overvoltage fault status (%s)\n", strerror (errno));
93                 return EGENERROR;
94         }
95
96         if (ctrl.value)
97                 *status |= FLASHLIGHT_STATUS_OVERVOLTAGE_FAULT;
98         else
99                 *status &= ~FLASHLIGHT_STATUS_OVERVOLTAGE_FAULT;
100
101         return ENOERROR;
102 }
103
104 int flashlight_set_intensity (FlashlightContext_t *flashlight, int intensity)
105 {
106         struct v4l2_control ctrl;
107
108         printf ("flashlight_set_intensity(%d)\n", intensity);
109
110         if (flashlight == NULL) {
111                 printf ("flashlight_set_intensity: flashlight context is not valid\n");
112                 return ENOCONTEXT;
113         }
114
115         if (flashlight->fd == -1) {
116                 printf ("flashlight_set_intensity: device not openned\n");
117                 return ENODEVICE;
118         }
119
120         if (intensity > flashlight->max_intensity)
121                 intensity = flashlight->max_intensity;
122
123         ctrl.id = V4L2_CID_TORCH_INTENSITY;
124         ctrl.value = intensity;
125
126         if (ioctl (flashlight->fd, VIDIOC_S_CTRL, &ctrl) == -1) {
127                 printf ("flashlight_set_intensity: cannot set intensity (%s)\n", strerror (errno));
128                 return EGENERROR;
129         }
130
131         return ENOERROR;
132 }
133
134 int flashlight_get_intensity (FlashlightContext_t *flashlight, int *intensity)
135 {
136         struct v4l2_control ctrl;
137
138         printf ("flashlight_get_intensity()\n");
139
140         if (flashlight == NULL) {
141                 printf ("flashlight_get_intensity: flashlight context is not valid\n");
142                 return ENOCONTEXT;
143         }
144
145         if (flashlight->fd == -1) {
146                 printf ("flashlight_get_intensity: device not openned\n");
147                 return ENODEVICE;
148         }
149
150         ctrl.id = V4L2_CID_TORCH_INTENSITY;
151
152         if (ioctl (flashlight->fd, VIDIOC_G_CTRL, &ctrl) == -1) {
153                 printf ("flashlight_get_intensity: cannot get intensity (%s)\n", strerror (errno));
154                 return EGENERROR;
155         }
156
157         *intensity = ctrl.value;
158         return ENOERROR;
159 }
160
161 int flashlight_open (FlashlightContext_t *flashlight, const char *device_name)
162 {
163         struct v4l2_queryctrl ctrl;
164         struct stat st;
165
166         printf ("flashlight_open(%s)\n", device_name);
167
168         if (flashlight == NULL) {
169                 printf ("flashlight_open: flashlight context is not valid\n");
170                 return ENOCONTEXT;
171         }
172
173         if (device_name == NULL) {
174                 printf ("flashlight_open: device name not specified\n");
175                 return EGENERROR;
176         }
177
178         memcpy (flashlight->device_name, device_name, sizeof(flashlight->device_name));
179
180         if (stat (flashlight->device_name, &st) == -1) {
181                 printf ("flashlight_open: cannot identify '%s' (%s)\n", flashlight->device_name, strerror (errno));
182                 return EGENERROR;
183         }
184
185         /* check it device_name is real device */
186         if (!S_ISCHR (st.st_mode)) {
187                 printf ("flashlight_open: %s is no device\n", flashlight->device_name);
188                 return EGENERROR;
189         }
190
191         flashlight->fd = open (flashlight->device_name, O_RDWR /* required */ | O_NONBLOCK, 0);
192
193         if (flashlight->fd == -1) {
194                 printf ("flashlight_open: cannot open '%s' (%s)\n", flashlight->device_name, strerror (errno));
195                 return ENODEVICE;
196         }
197
198         /* query from driver minimal and maximal flashlight intensity */
199         ctrl.id = V4L2_CID_TORCH_INTENSITY;
200         if (ioctl (flashlight->fd, VIDIOC_QUERYCTRL, &ctrl) == -1) {
201                 printf ("flashlight_open: cannot get minimal and maximal flashlight intensity (%s)\n", strerror (errno));
202                 return EGENERROR;
203         }
204
205         flashlight->min_intensity = ctrl.minimum;
206         flashlight->max_intensity = ctrl.maximum;
207
208         return ENOERROR;
209 }
210
211 int flashlight_close (FlashlightContext_t *flashlight)
212 {
213         printf ("flashlight_close()\n");
214
215         if (flashlight == NULL) {
216                 printf ("flashlight_close: flashlight context is not valid\n");
217                 return ENOCONTEXT;
218         }
219
220         if (flashlight->fd != -1) {
221                 if (close (flashlight->fd) == -1) {
222                         printf ("flashlight_close: cannot close device '%s' (%s)\n", flashlight->device_name, strerror (errno));
223                         return ENODEVICE;
224                 }
225         }
226
227         flashlight->fd = -1;
228         return ENOERROR;
229 }
230
231 int flashlight_init (FlashlightContext_t **pRefContext)
232 {
233         FlashlightContext_t *flashlight = NULL;
234
235         printf ("flashlight_init()\n");
236
237         if (*pRefContext != NULL) {
238                 printf("flashlight_init: expecting zero pointer context '*pRefContext'\n");
239                 return EGENERROR;
240         }
241
242         /* allocate memory for context structure */
243         flashlight = malloc (sizeof (FlashlightContext_t));
244         if (flashlight == NULL) {
245                 printf ("flashlight_init: unable to allocate memory for context\n");
246                 return ENOCONTEXT;
247         }
248
249         *pRefContext = flashlight;
250
251         /* initialize default values */
252         memset (flashlight, 0x00, sizeof (FlashlightContext_t));
253         flashlight->fd = -1;
254
255         /* from adp1653.c */
256         flashlight->min_intensity = 0;
257         flashlight->max_intensity = 11;
258
259         return ENOERROR;
260 }
261
262 int flashlight_deinit (FlashlightContext_t *flashlight)
263 {
264         int intensity = 0;
265
266         printf ("flashlight_deinit()\n");
267
268         if (flashlight == NULL) {
269                 printf ("flashlight_deinit: flashlight context is not valid\n");
270                 return ENOCONTEXT;
271         }
272
273         if (flashlight->fd != -1) {
274                 /* check if flashlight isn't enabled before closing device */
275                 if (flashlight_get_intensity (flashlight, &intensity) == -1)
276                         return EGENERROR;
277
278                 if (intensity > 0) {
279                         if (flashlight_set_intensity (flashlight, 0) == -1)
280                                 return EGENERROR;
281                 }
282
283                 if (flashlight_close(flashlight))
284                         return EGENERROR;
285         }
286
287         /* free allocated memory */
288         free (flashlight);
289
290         return ENOERROR;
291 }