tizen 2.3 release
[apps/livebox/livebox-viewer.git] / dynamicbox_viewer / src / fb_wayland.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <sys/mman.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <stddef.h>
27 #include <sys/shm.h>
28 #include <sys/ipc.h>
29
30 #include <dlog.h>
31 #include <dynamicbox_errno.h> /* For error code */
32 #include <dynamicbox_buffer.h>
33
34 #include "debug.h"
35 #include "util.h"
36 #include "fb.h"
37
38 int errno;
39
40 struct fb_info {
41     char *id;
42     int w;
43     int h;
44     int bufsz;
45     void *buffer;
46
47     int pixels;
48     int handle;
49 };
50
51 static struct {
52 } s_info = {
53 };
54
55 int fb_init(void *disp)
56 {
57     return 0;
58 }
59
60 int fb_fini(void)
61 {
62     return 0;
63 }
64
65 static inline void update_fb_size(struct fb_info *info)
66 {
67     info->bufsz = info->w * info->h * info->pixels;
68 }
69
70 static inline int sync_for_file(struct fb_info *info)
71 {
72     int fd;
73     struct buffer *buffer;
74
75     buffer = info->buffer;
76
77     if (!buffer) { /* Ignore this sync request */
78         return DBOX_STATUS_ERROR_NONE;
79     }
80
81     if (buffer->state != CREATED) {
82         ErrPrint("Invalid state of a FB\n");
83         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
84     }
85
86     if (buffer->type != DBOX_BUFFER_TYPE_FILE) {
87         ErrPrint("Invalid buffer\n");
88         return DBOX_STATUS_ERROR_NONE;
89     }
90
91     fd = open(util_uri_to_path(info->id), O_RDONLY);
92     if (fd < 0) {
93         ErrPrint("Failed to open a file (%s) because of (%s)\n",
94                 util_uri_to_path(info->id), strerror(errno));
95
96         /*!
97          * \note
98          * But return ZERO, even if we couldn't get a buffer file,
99          * the viewer can draw empty screen.
100          *
101          * and then update it after it gots update events
102          */
103         return DBOX_STATUS_ERROR_NONE;
104     }
105
106     if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
107         ErrPrint("read: %s\n", strerror(errno));
108         if (close(fd) < 0) {
109             ErrPrint("close: %s\n", strerror(errno));
110         }
111
112         /*!
113          * \note
114          * But return ZERO, even if we couldn't get a buffer file,
115          * the viewer can draw empty screen.
116          *
117          * and then update it after it gots update events
118          */
119         return DBOX_STATUS_ERROR_NONE;
120     }
121
122     if (close(fd) < 0) {
123         ErrPrint("close: %s\n", strerror(errno));
124     }
125     return DBOX_STATUS_ERROR_NONE;
126 }
127
128 int fb_sync(struct fb_info *info, int x, int y, int w, int h)
129 {
130     if (!info) {
131         ErrPrint("FB Handle is not valid\n");
132         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
133     }
134
135     if (!info->id || info->id[0] == '\0') {
136         DbgPrint("Ingore sync\n");
137         return DBOX_STATUS_ERROR_NONE;
138     }
139
140     if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
141         return sync_for_file(info);
142     } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
143     } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
144         /* No need to do sync */ 
145         return DBOX_STATUS_ERROR_NONE;
146     }
147
148     return DBOX_STATUS_ERROR_INVALID_PARAMETER;
149 }
150
151 struct fb_info *fb_create(const char *id, int w, int h)
152 {
153     struct fb_info *info;
154
155     if (!id || id[0] == '\0') {
156         ErrPrint("Invalid ID\n");
157         return NULL;
158     }
159
160     info = calloc(1, sizeof(*info));
161     if (!info) {
162         ErrPrint("Heap: %s\n", strerror(errno));
163         return NULL;
164     }
165
166     info->id = strdup(id);
167     if (!info->id) {
168         ErrPrint("Heap: %s\n", strerror(errno));
169         free(info);
170         return NULL;
171     }
172
173     info->pixels = sizeof(int);    /* Use the default pixels(depth) */
174
175     if (sscanf(info->id, SCHEMA_SHM "%d", &info->handle) == 1) {
176         DbgPrint("SHMID: %d is gotten\n", info->handle);
177     } else if (sscanf(info->id, SCHEMA_PIXMAP "%d:%d", &info->handle, &info->pixels) == 2) {
178         DbgPrint("PIXMAP-SHMID: %d is gotten (%d)\n", info->handle, info->pixels);
179         ErrPrint("Unsupported\n");
180         free(info);
181         return NULL;
182     } else {
183         info->handle = DBOX_STATUS_ERROR_INVALID_PARAMETER;
184     }
185
186     info->bufsz = 0;
187     info->buffer = NULL;
188     info->w = w;
189     info->h = h;
190
191     return info;
192 }
193
194 int fb_destroy(struct fb_info *info)
195 {
196     if (!info) {
197         ErrPrint("Handle is not valid\n");
198         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
199     }
200
201     if (info->buffer) {
202         struct buffer *buffer;
203         buffer = info->buffer;
204
205         buffer->info = NULL;
206     }
207
208     free(info->id);
209     free(info);
210     return DBOX_STATUS_ERROR_NONE;
211 }
212
213 int fb_is_created(struct fb_info *info)
214 {
215     if (!info) {
216         ErrPrint("Handle is not valid\n");
217         return 0;
218     }
219
220     if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->handle != 0) {
221         return 1;
222     } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM)) && info->handle > 0) {
223         return 1;
224     } else {
225         const char *path;
226         path = util_uri_to_path(info->id);
227         if (path && access(path, F_OK | R_OK) == 0) {
228             return 1;
229         } else {
230             ErrPrint("access: %s (%s)\n", strerror(errno), path);
231         }
232     }
233
234     return 0;
235 }
236
237 void *fb_acquire_buffer(struct fb_info *info)
238 {
239     struct buffer *buffer;
240
241     if (!info) {
242         ErrPrint("info == NIL\n");
243         dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
244         return NULL;
245     }
246
247     if (!info->buffer) {
248         if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
249             ErrPrint("Unsupported Type\n");
250             dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
251             return NULL;
252         } else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
253             update_fb_size(info);
254
255             buffer = calloc(1, sizeof(*buffer) + info->bufsz);
256             if (!buffer) {
257                 ErrPrint("Heap: %s\n", strerror(errno));
258                 info->bufsz = 0;
259                 dynamicbox_set_last_status(DBOX_STATUS_ERROR_OUT_OF_MEMORY);
260                 return NULL;
261             }
262
263             buffer->type = DBOX_BUFFER_TYPE_FILE;
264             buffer->refcnt = 0;
265             buffer->state = CREATED;
266             buffer->info = info;
267             info->buffer = buffer;
268
269             sync_for_file(info);
270         } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
271             buffer = shmat(info->handle, NULL, 0);
272             if (buffer == (void *)-1) {
273                 ErrPrint("shmat: %s (%d)\n", strerror(errno), info->handle);
274                 dynamicbox_set_last_status(DBOX_STATUS_ERROR_FAULT);
275                 return NULL;
276             }
277
278             return buffer->data;
279         } else {
280             ErrPrint("Buffer is not created (%s)\n", info->id);
281             dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
282             return NULL;
283         }
284     }
285
286     buffer = info->buffer;
287
288     switch (buffer->type) {
289         case DBOX_BUFFER_TYPE_FILE:
290             buffer->refcnt++;
291             break;
292         case DBOX_BUFFER_TYPE_PIXMAP:
293         default:
294             DbgPrint("Unknwon FP: %d\n", buffer->type);
295             dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
296             break;
297     }
298
299     return buffer->data;
300 }
301
302 int fb_release_buffer(void *data)
303 {
304     struct buffer *buffer;
305
306     if (!data) {
307         ErrPrint("buffer data == NIL\n");
308         dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
309         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
310     }
311
312     buffer = container_of(data, struct buffer, data);
313
314     if (buffer->state != CREATED) {
315         ErrPrint("Invalid handle\n");
316         dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
317         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
318     }
319
320     switch (buffer->type) {
321         case DBOX_BUFFER_TYPE_SHM:
322             if (shmdt(buffer) < 0) {
323                 ErrPrint("shmdt: %s\n", strerror(errno));
324             }
325             break;
326         case DBOX_BUFFER_TYPE_FILE:
327             buffer->refcnt--;
328             if (buffer->refcnt == 0) {
329                 struct fb_info *info;
330                 info = buffer->info;
331
332                 buffer->state = DBOX_FB_STATE_DESTROYED;
333                 free(buffer);
334
335                 if (info && info->buffer == buffer) {
336                     info->buffer = NULL;
337                 }
338             }
339             break;
340         case DBOX_BUFFER_TYPE_PIXMAP:
341         default:
342             ErrPrint("Unknwon buffer type\n");
343             dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
344             break;
345     }
346
347     return DBOX_STATUS_ERROR_NONE;
348 }
349
350 int fb_refcnt(void *data)
351 {
352     struct buffer *buffer;
353     struct shmid_ds buf;
354     int ret;
355
356     if (!data) {
357         dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
358         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
359     }
360
361     buffer = container_of(data, struct buffer, data);
362
363     if (buffer->state != CREATED) {
364         ErrPrint("Invalid handle\n");
365         dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
366         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
367     }
368
369     switch (buffer->type) {
370         case DBOX_BUFFER_TYPE_SHM:
371             if (shmctl(buffer->refcnt, IPC_STAT, &buf) < 0) {
372                 ErrPrint("Error: %s\n", strerror(errno));
373                 dynamicbox_set_last_status(DBOX_STATUS_ERROR_FAULT);
374                 return DBOX_STATUS_ERROR_FAULT;
375             }
376
377             ret = buf.shm_nattch;
378             break;
379         case DBOX_BUFFER_TYPE_FILE:
380             ret = buffer->refcnt;
381             break;
382         case DBOX_BUFFER_TYPE_PIXMAP:
383         default:
384             dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
385             ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
386             break;
387     }
388
389     return ret;
390 }
391
392 const char *fb_id(struct fb_info *info)
393 {
394     return info ? info->id : NULL;
395 }
396
397 int fb_get_size(struct fb_info *info, int *w, int *h)
398 {
399     if (!info) {
400         ErrPrint("Handle is not valid\n");
401         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
402     }
403
404     *w = info->w;
405     *h = info->h;
406     return DBOX_STATUS_ERROR_NONE;
407 }
408
409 int fb_size(struct fb_info *info)
410 {
411     if (!info) {
412         dynamicbox_set_last_status(DBOX_STATUS_ERROR_INVALID_PARAMETER);
413         return 0;
414     }
415
416     update_fb_size(info);
417
418     return info->bufsz;
419 }
420
421 int fb_type(struct fb_info *info)
422 {
423     struct buffer *buffer;
424
425     if (!info) {
426         return DBOX_BUFFER_TYPE_ERROR;
427     }
428
429     buffer = info->buffer;
430     if (!buffer) {
431         int type = DBOX_BUFFER_TYPE_ERROR;
432         /*!
433          * \note
434          * Try to get this from SCHEMA
435          */
436         if (info->id) {
437             if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
438                 type = DBOX_BUFFER_TYPE_FILE;
439             } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
440                 /* Unsupported type */
441             } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
442                 type = DBOX_BUFFER_TYPE_SHM;
443             }
444         }
445
446         return type;
447     }
448
449     return buffer->type;
450 }
451 /* End of a file */