Add PS3 countdown timer
[petitboot] / ui / common / ps3.c
1 /*
2  *  Copyright (C) 2009 Sony Computer Entertainment Inc.
3  *  Copyright 2009 Sony Corp.
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; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define _GNU_SOURCE
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/ioctl.h>
27 #include <ps3-flash.h>
28 #include <ps3-av.h>
29
30 #include "log/log.h"
31 #include "ui-system.h"
32 #include "ps3.h"
33
34 static const char flash_dev[] = "/dev/ps3flash";
35 static const char fb_dev[] = "/dev/fb0";
36
37 static const struct os_area_db_id id_default_item =
38 {
39         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
40         .key = 1,
41 };
42 static const struct os_area_db_id id_video_mode =
43 {
44         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
45         .key = OS_AREA_DB_KEY_VIDEO_MODE,    /* 2 */
46 };
47 static const struct os_area_db_id id_flags =
48 {
49         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
50         .key = 3,
51 };
52 static const struct os_area_db_id id_timeout =
53 {
54         .owner = OS_AREA_DB_OWNER_PETITBOOT, /* 3 */
55         .key = 4,
56 };
57
58 struct ps3_flash_ctx {
59         FILE *dev;
60         struct os_area_header header;
61         struct os_area_params params;
62         struct os_area_db db;
63 };
64
65 static void ps3_flash_close(struct ps3_flash_ctx *fc)
66 {
67         assert(fc->dev);
68
69         fclose(fc->dev);
70         fc->dev = NULL;
71 }
72
73 static int ps3_flash_open(struct ps3_flash_ctx *fc, const char *mode)
74 {
75         int result;
76
77         fc->dev = fopen(flash_dev, mode);
78
79         if (!fc->dev) {
80                 pb_log("%s: fopen failed: %s: %s\n", __func__, strerror(errno),
81                         flash_dev);
82                 return -1;
83         }
84
85         os_area_set_log_stream(pb_log_get_stream());
86
87         result = os_area_fixed_read(&fc->header, &fc->params, fc->dev);
88
89         if (result) {
90                 pb_log("%s: os_area_fixed_read failed: %s\n", __func__);
91                 goto fail;
92         }
93
94         return 0;
95
96 fail:
97         ps3_flash_close(fc);
98         return -1;
99 }
100
101 /**
102  * ps3_flash_get_values - Read values from the PS3 flash memory database.
103  *
104  * Returns zero on success.
105  */
106
107 int ps3_flash_get_values(struct ps3_flash_values *values)
108 {
109         int result;
110         int sum;
111         struct ps3_flash_ctx fc;
112         uint64_t tmp;
113
114         /* Set default values. */
115
116         values->default_item = 0;
117         values->timeout = ps3_timeout_forever;
118         values->video_mode = 1;
119
120         result = ps3_flash_open(&fc, "r");
121
122         if (result)
123                 goto done;
124
125         result = os_area_db_read(&fc.db, &fc.header, fc.dev);
126
127         ps3_flash_close(&fc);
128
129         if (result) {
130                 pb_log("%s: os_area_db_read failed: %s\n", __func__,
131                         strerror(errno));
132                 goto done;
133         }
134
135         sum = result = os_area_db_get(&fc.db, &id_default_item, &tmp);
136
137         if (!result)
138                 values->default_item = (uint32_t)tmp;
139
140         result = os_area_db_get(&fc.db, &id_timeout, &tmp);
141
142         if (!result)
143                 values->timeout = (uint8_t)tmp;
144
145         sum += result = os_area_db_get(&fc.db, &id_video_mode, &tmp);
146
147         if (!result)
148                 values->video_mode = (uint16_t)tmp;
149
150 done:
151         pb_log("%s: default_item: %x\n", __func__,
152                 (unsigned int)values->default_item);
153         pb_log("%s: timeout: %u\n", __func__,
154                 (unsigned int)values->timeout);
155         pb_log("%s: video_mode:   %u\n", __func__,
156                 (unsigned int)values->video_mode);
157
158         return (result || sum) ? -1 : 0;
159 }
160
161 /**
162  * ps3_flash_set_values - Writes values from the PS3 flash memory database.
163  *
164  * Formats the flash database before writing if a valid database if not found.
165  * Returns zero on success.
166  */
167
168 int ps3_flash_set_values(const struct ps3_flash_values *values)
169 {
170         int result;
171         struct ps3_flash_ctx fc;
172
173         pb_log("%s: default_item: %u\n", __func__, values->default_item);
174         pb_log("%s: video_mode:   %u\n", __func__, values->video_mode);
175
176         result = ps3_flash_open(&fc, "r+");
177
178         if (result)
179                 return result;
180
181         result = os_area_db_read(&fc.db, &fc.header, fc.dev);
182
183         if (result) {
184                 pb_log("%s: os_area_db_read failed: %s\n", __func__,
185                         strerror(errno));
186                 pb_log("%s: formating db\n", __func__);
187
188                 result = os_area_db_format(&fc.db, &fc.header, fc.dev);
189
190                 if (result) {
191                         pb_log("%s: db_format failed: %s\n", __func__,
192                                 strerror(errno));
193                         goto fail;
194                 }
195         }
196
197         /* timeout is currently read-only, set with ps3-bl-option */
198
199         result = os_area_db_set_32(&fc.db, &id_default_item,
200                 values->default_item);
201         result += os_area_db_set_16(&fc.db, &id_video_mode,
202                 values->video_mode);
203
204         result += os_area_db_write(&fc.db, &fc.header, fc.dev);
205
206         ps3_flash_close(&fc);
207         return result;
208
209 fail:
210         ps3_flash_close(&fc);
211         return -1;
212 }
213
214 /**
215  * ps3_video_ioctl - Low level ioctl helper.
216  *
217  * Use ps3_get_video_mode or ps3_set_video_mode().
218  */
219
220 static int ps3_video_ioctl(int request, unsigned int *mode_id)
221 {
222         int result;
223         int fd;
224
225         fd = open(fb_dev, O_RDWR);
226
227         if (fd < 0) {
228                 pb_log("%s: open failed: %s: %s\n", __func__, strerror(errno),
229                         fb_dev);
230                 return -1;
231         }
232
233         result = ioctl(fd, request, (unsigned long)mode_id);
234
235         close(fd);
236
237         if (result < 0) {
238                 pb_log("%s: ioctl failed: %s: %s\n", __func__, strerror(errno),
239                         fb_dev);
240                 return -1;
241         }
242
243         return 0;
244 }
245
246 /**
247  * ps3_set_video_mode - Set the PS3 video mode.
248  * @mode_id: The PS3 video mode_id as documented in the ps3-video-mode man page.
249  *
250  * Returns zero on success.
251  */
252
253 int ps3_set_video_mode(unsigned int mode_id)
254 {
255         pb_log("%s: %u\n", __func__, mode_id);
256         return ps3_video_ioctl(PS3FB_IOCTL_SETMODE, &mode_id);
257 }
258
259 /**
260  * ps3_set_video_mode - Get the current PS3 video mode.
261  * @mode_id: The PS3 video mode_id as documented in the ps3-video-mode man page.
262  *
263  * Returns zero on success.
264  */
265
266 int ps3_get_video_mode(unsigned int *mode_id)
267 {
268         int result;
269
270         *mode_id = 0;
271
272         result =  ps3_video_ioctl(PS3FB_IOCTL_GETMODE, mode_id);
273
274         pb_log("%s: %u\n", __func__, *mode_id);
275         return result;
276 }