]> git.ozlabs.org Git - petitboot/blobdiff - petitboot.c
Print ststus message when booting
[petitboot] / petitboot.c
index d566e3ff188ff7dc8cf20d36b52545fe2e894205..6f2a386fe90cbc021fc4317b3d618eccb027add7 100644 (file)
@@ -1,3 +1,6 @@
+
+#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -5,6 +8,8 @@
 #include <unistd.h>
 #include <syscall.h>
 #include <assert.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
 
 #include <linux/input.h>
 
@@ -12,6 +17,7 @@
 
 #include <libtwin/twin.h>
 #include <libtwin/twin_linux_mouse.h>
+#include <libtwin/twin_linux_js.h>
 #include <libtwin/twin_png.h>
 #include <libtwin/twin_jpeg.h>
 
@@ -28,14 +34,17 @@ static twin_fbdev_t *pboot_fbdev;
 
 static twin_screen_t *pboot_screen;
 
-#define PBOOT_LEFT_PANE_SIZE           200
+#define PBOOT_INITIAL_MESSAGE          \
+       "keys: 0=safe 1=720p 2=1080i 3=1080p del=GameOS"
+
+#define PBOOT_LEFT_PANE_SIZE           160
 #define PBOOT_LEFT_PANE_COLOR          0x80000000
 #define PBOOT_LEFT_LINE_COLOR          0xff000000
 
 #define PBOOT_LEFT_FOCUS_WIDTH         80
 #define PBOOT_LEFT_FOCUS_HEIGHT                80
-#define PBOOT_LEFT_FOCUS_XOFF          60
-#define PBOOT_LEFT_FOCUS_YOFF          60
+#define PBOOT_LEFT_FOCUS_XOFF          40
+#define PBOOT_LEFT_FOCUS_YOFF          40
 #define PBOOT_LEFT_FOCUS_XRAD          (6 * TWIN_FIXED_ONE)
 #define PBOOT_LEFT_FOCUS_YRAD          (6 * TWIN_FIXED_ONE)
 
@@ -47,8 +56,8 @@ static twin_screen_t *pboot_screen;
 
 #define PBOOT_LEFT_ICON_WIDTH          64
 #define PBOOT_LEFT_ICON_HEIGHT         64
-#define PBOOT_LEFT_ICON_XOFF           70
-#define PBOOT_LEFT_ICON_YOFF           70
+#define PBOOT_LEFT_ICON_XOFF           50
+#define PBOOT_LEFT_ICON_YOFF           50
 #define PBOOT_LEFT_ICON_STRIDE         100
 
 #define PBOOT_RIGHT_OPTION_LMARGIN     30
@@ -60,7 +69,7 @@ static twin_screen_t *pboot_screen;
 #define PBOOT_RIGHT_SUBTITLE_TEXT_SIZE (18 * TWIN_FIXED_ONE)
 #define PBOOT_RIGHT_TITLE_XOFFSET      80
 #define PBOOT_RIGHT_TITLE_YOFFSET      30
-#define PBOOT_RIGHT_SUBTITLE_XOFFSET   200
+#define PBOOT_RIGHT_SUBTITLE_XOFFSET   100
 #define PBOOT_RIGHT_SUBTITLE_YOFFSET   50
 #define PBOOT_RIGHT_BADGE_XOFFSET      2
 #define PBOOT_RIGHT_BADGE_YOFFSET      0
@@ -71,6 +80,12 @@ static twin_screen_t *pboot_screen;
 
 #define PBOOT_FOCUS_COLOR              0x10404040
 
+#define PBOOT_STATUS_PANE_COLOR                0x60606060
+#define PBOOT_STATUS_PANE_HEIGHT       20
+#define PBOOT_STATUS_PANE_XYMARGIN     20
+#define PBOOT_STATUS_TEXT_MARGIN       10
+#define PBOOT_STATUS_TEXT_SIZE         (16 * TWIN_FIXED_ONE)
+#define PBOOT_STATUS_TEXT_COLOR                0xff000000
 
 typedef struct _pboot_option pboot_option_t;
 typedef struct _pboot_device pboot_device_t;
@@ -121,8 +136,40 @@ typedef struct _pboot_rpane {
        int             mouse_target;
 } pboot_rpane_t;
 
+typedef struct _pboot_spane {
+       twin_window_t   *window;
+       char            *text;
+} pboot_spane_t;
+
 static pboot_lpane_t   *pboot_lpane;
 static pboot_rpane_t   *pboot_rpane;
+static pboot_spane_t   *pboot_spane;
+
+/* control to keyboard mappings for the sixaxis controller */
+uint8_t sixaxis_map[] = {
+       0,              /*   0  Select          */
+       0,              /*   1  L3              */
+       0,              /*   2  R3              */
+       0,              /*   3  Start           */
+       KEY_UP,         /*   4  Dpad Up         */
+       KEY_RIGHT,      /*   5  Dpad Right      */
+       KEY_DOWN,       /*   6  Dpad Down       */
+       KEY_LEFT,       /*   7  Dpad Left       */
+       0,              /*   8  L2              */
+       0,              /*   9  R2              */
+       0,              /*  10  L1              */
+       0,              /*  11  R1              */
+       0,              /*  12  Triangle        */
+       KEY_ENTER,      /*  13  Circle          */
+       0,              /*  14  Cross           */
+       KEY_DELETE,     /*  15  Square          */
+       0,              /*  16  PS Button       */
+       0,              /*  17  nothing      */
+       0,              /*  18  nothing      */
+};
+
+
+static int pboot_vmode_change = -1;
 
 /* XXX move to twin */
 static inline twin_bool_t twin_rect_intersect(twin_rect_t r1,
@@ -271,7 +318,7 @@ static void pboot_rpane_draw(twin_window_t *window)
 static twin_time_t pboot_rfocus_timeout (twin_time_t now, void *closure)
 {
        int dir = 1, dist, pos;
-       const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 2, 3, 4, 5 };
+       const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 1, 2, 2, 3 };
 
        dist = abs(pboot_rpane->focus_target - pboot_rpane->focus_start);
        dir = dist > 5 ? 5 : dist;
@@ -413,6 +460,7 @@ static void pboot_choose_option(void)
        pboot_option_t *opt = &dev->options[pboot_rpane->focus_curindex];
 
        LOG("Selected device %s\n", opt->title);
+       pboot_message("booting %s...", opt->title);
 
        /* Give user feedback, make sure errors and panics will be seen */
        pboot_exec_option(opt->data);
@@ -502,12 +550,30 @@ int pboot_add_option(int devindex, const char *title,
 }
 
 
-static void pboot_set_device_select(int sel)
+static void pboot_set_device_select(int sel, int force)
 {
        LOG("%s: %d -> %d\n", __FUNCTION__, pboot_dev_sel, sel);
-       if (sel == pboot_dev_sel || sel >= pboot_dev_count)
+       if (!force && sel == pboot_dev_sel)
+               return;
+       if (sel >= pboot_dev_count)
                return;
        pboot_dev_sel = sel;
+       if (force) {
+               pboot_lpane->focus_curindex = sel;
+               if (sel < 0)
+                       pboot_lpane->focus_target = 0 - PBOOT_LEFT_FOCUS_HEIGHT;
+               else
+                       pboot_lpane->focus_target = PBOOT_LEFT_FOCUS_YOFF +
+                               PBOOT_LEFT_ICON_STRIDE * sel;
+               pboot_rpane->focus_box.bottom = pboot_lpane->focus_target;
+               pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
+                       PBOOT_RIGHT_FOCUS_HEIGHT;
+               twin_window_damage(pboot_lpane->window,
+                                  0, 0,
+                                  pboot_lpane->window->pixmap->width,
+                                  pboot_lpane->window->pixmap->height);
+               twin_window_queue_paint(pboot_lpane->window);
+       }
        pboot_rpane->focus_curindex = -1;
        pboot_rpane->mouse_target = -1;
        pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
@@ -519,15 +585,46 @@ static void pboot_set_device_select(int sel)
        twin_window_queue_paint(pboot_rpane->window);
 }
 
+static void pboot_create_rpane(void)
+{
+       pboot_rpane = calloc(1, sizeof(pboot_rpane_t));
+       assert(pboot_rpane);
+
+       pboot_rpane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
+                                                TwinWindowPlain,
+                                                PBOOT_LEFT_PANE_SIZE, 0,
+                                                pboot_screen->width -
+                                                  PBOOT_LEFT_PANE_SIZE,
+                                                pboot_screen->height);
+       assert(pboot_rpane->window);
+
+       pboot_rpane->window->draw = pboot_rpane_draw;
+       pboot_rpane->window->event = pboot_rpane_event;
+       pboot_rpane->window->client_data = pboot_rpane;
+
+       pboot_rpane->focus_curindex = -1;
+       pboot_rpane->focus_box.left = PBOOT_RIGHT_FOCUS_XOFF;
+       pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
+       pboot_rpane->focus_box.right = pboot_rpane->window->pixmap->width -
+               2 * PBOOT_RIGHT_FOCUS_XOFF;
+       pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
+               PBOOT_RIGHT_FOCUS_HEIGHT;
+       pboot_rpane->mouse_target = -1;
+       twin_window_show(pboot_rpane->window);
+       twin_window_queue_paint(pboot_rpane->window);
+}
+
+
 static twin_time_t pboot_lfocus_timeout (twin_time_t now, void *closure)
 {
        int dir = 1, dist, pos;
-       const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 2, 3, 4, 5 };
+       const int accel[11] = { 7, 4, 2, 1, 1, 1, 1, 1, 2, 2, 3 };
 
        dist = abs(pboot_lpane->focus_target - pboot_lpane->focus_start);
+       dir = dist > 2 ? 2 : dist;
        pos = pboot_lpane->focus_target - (int)pboot_lpane->focus_box.top;
        if (pos == 0) {
-               pboot_set_device_select(pboot_lpane->focus_curindex);
+               pboot_set_device_select(pboot_lpane->focus_curindex, 0);
                return -1;
        }
        if (pos < 0) {
@@ -642,6 +739,11 @@ static twin_bool_t pboot_lpane_event (twin_window_t            *window,
        return TWIN_FALSE;
 }
 
+static void pboot_quit(void)
+{
+       kill(0, SIGINT);
+}
+
 twin_bool_t pboot_event_filter(twin_screen_t       *screen,
                               twin_event_t         *event)
 {
@@ -656,7 +758,47 @@ twin_bool_t pboot_event_filter(twin_screen_t           *screen,
                                               pboot_cursor_hx,
                                               pboot_cursor_hy);
                break;
+       case TwinEventJoyButton:
+               /* map joystick events into key events */
+               if (event->u.js.control >= sizeof(sixaxis_map))
+                       break;
+
+               event->u.key.key = sixaxis_map[event->u.js.control];
+               if (event->u.js.value == 0) {
+                       event->kind = TwinEventKeyUp;
+                       break;
+               } else {
+                       event->kind = TwinEventKeyDown;
+               }
+
+               /* fall through.. */
        case TwinEventKeyDown:
+               switch(event->u.key.key) {
+               /* Gross hack for video modes, need something better ! */
+               case KEY_0:
+                       pboot_vmode_change = 0; /* auto */
+                       pboot_quit();
+                       return TWIN_TRUE;
+               case KEY_1:
+                       pboot_vmode_change = 3; /* 720p */
+                       pboot_quit();
+                       return TWIN_TRUE;
+               case KEY_2:
+                       pboot_vmode_change = 4; /* 1080i */
+                       pboot_quit();
+                       return TWIN_TRUE;
+               case KEY_3:
+                       pboot_vmode_change = 5; /* 1080p */
+                       pboot_quit();
+                       return TWIN_TRUE;
+
+               /* Another gross hack for booting back to gameos */
+               case KEY_BACKSPACE:
+               case KEY_DELETE:
+                       pboot_message("booting to GameOS");
+                       system(BOOT_GAMEOS_BIN);
+                       pboot_quit();
+               }
        case TwinEventKeyUp:
                twin_screen_set_cursor(pboot_screen, NULL, 0, 0);
                break;
@@ -732,9 +874,8 @@ static void pboot_lpane_draw(twin_window_t *window)
        twin_path_destroy(path);
 }
 
-static void pboot_create_panels(void)
+static void pboot_create_lpane(void)
 {
-       /* left pane */
        pboot_lpane = calloc(1, sizeof(pboot_lpane_t));
        assert(pboot_lpane);
 
@@ -756,32 +897,76 @@ static void pboot_create_panels(void)
                PBOOT_LEFT_FOCUS_HEIGHT;
        pboot_lpane->mouse_target = -1;
        twin_window_show(pboot_lpane->window);
+       twin_window_queue_paint(pboot_lpane->window);
+}
 
-       /* right pane */
-       pboot_rpane = calloc(1, sizeof(pboot_rpane_t));
-       assert(pboot_rpane);
+static void pboot_spane_draw(twin_window_t *window)
+{
+       twin_pixmap_t   *px = window->pixmap;
+       pboot_spane_t   *spane = window->client_data;
+       twin_path_t     *path;
+       twin_fixed_t    tx, ty;
 
-       pboot_rpane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
-                                                TwinWindowPlain,
-                                                PBOOT_LEFT_PANE_SIZE, 0,
-                                                pboot_screen->width -
-                                                  PBOOT_LEFT_PANE_SIZE,
-                                                pboot_screen->height);
-       assert(pboot_rpane->window);
+       /* Fill background */
+       twin_fill(px, PBOOT_STATUS_PANE_COLOR, TWIN_SOURCE,
+                 0, 0, px->width, px->height);
 
-       pboot_rpane->window->draw = pboot_rpane_draw;
-       pboot_rpane->window->event = pboot_rpane_event;
-       pboot_rpane->window->client_data = pboot_rpane;
+       path = twin_path_create();
+       assert(path);
 
-       pboot_rpane->focus_curindex = -1;
-       pboot_rpane->focus_box.left = PBOOT_RIGHT_FOCUS_XOFF;
-       pboot_rpane->focus_box.top = -2*PBOOT_RIGHT_FOCUS_HEIGHT;
-       pboot_rpane->focus_box.right = pboot_rpane->window->pixmap->width -
-               2 * PBOOT_RIGHT_FOCUS_XOFF;
-       pboot_rpane->focus_box.bottom = pboot_rpane->focus_box.top +
-               PBOOT_RIGHT_FOCUS_HEIGHT;
-       pboot_rpane->mouse_target = -1;
-       twin_window_show(pboot_rpane->window);
+       twin_path_set_font_size(path, PBOOT_STATUS_TEXT_SIZE);
+       twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
+       tx = twin_int_to_fixed(PBOOT_STATUS_TEXT_MARGIN);
+       ty = twin_int_to_fixed(PBOOT_STATUS_PANE_HEIGHT - 2);
+       twin_path_move (path, tx, ty);
+       twin_path_utf8 (path, spane->text);
+       twin_paint_path (px, PBOOT_STATUS_TEXT_COLOR, path);
+
+       twin_path_destroy(path);
+}
+
+void pboot_message(const char *fmt, ...)
+{
+       va_list ap;
+       char *msg;
+
+       if (pboot_spane->text)
+               free(pboot_spane->text);
+
+       va_start(ap, fmt);
+       vasprintf(&msg, fmt, ap);
+       va_end(ap);
+
+       pboot_spane->text = msg;
+       twin_window_damage(pboot_spane->window,
+                          0, 0,
+                          pboot_spane->window->pixmap->width,
+                          pboot_spane->window->pixmap->height);
+       twin_window_queue_paint(pboot_spane->window);
+}
+
+static void pboot_create_spane(void)
+{
+       pboot_spane = calloc(1, sizeof(pboot_spane_t));
+       assert(pboot_spane);
+
+       pboot_spane->window = twin_window_create(pboot_screen, TWIN_ARGB32,
+                                                TwinWindowPlain,
+                                                PBOOT_LEFT_PANE_SIZE +
+                                                 PBOOT_STATUS_PANE_XYMARGIN,
+                                                pboot_screen->height - 
+                                                 PBOOT_STATUS_PANE_HEIGHT,
+                                                pboot_screen->width -
+                                                 PBOOT_LEFT_PANE_SIZE -
+                                                 2*PBOOT_STATUS_PANE_XYMARGIN,
+                                                PBOOT_STATUS_PANE_HEIGHT);
+       assert(pboot_spane->window);
+
+       pboot_spane->window->draw = pboot_spane_draw;
+       pboot_spane->window->client_data = pboot_spane;
+       pboot_spane->text = strdup(PBOOT_INITIAL_MESSAGE);
+       twin_window_show(pboot_spane->window);
+       twin_window_queue_paint(pboot_spane->window);
 }
 
 int pboot_add_device(const char *dev_id, const char *name,
@@ -818,8 +1003,8 @@ int pboot_add_device(const char *dev_id, const char *name,
 
 int pboot_remove_device(const char *dev_id)
 {
-       int             i, new_dev_index;
        pboot_device_t  *dev = NULL;
+       int             i, newsel = pboot_dev_sel;
 
        /* find the matching device */
        for (i = 0; i < pboot_dev_count; i++) {
@@ -832,22 +1017,16 @@ int pboot_remove_device(const char *dev_id)
        if (!dev)
                return TWIN_FALSE;
 
-       /* select the newly-focussed device */
-       if (i == pboot_dev_count - 1)
-               new_dev_index = i - 1;
-       else
-               new_dev_index = i + 1;
-
        memmove(pboot_devices + i, pboot_devices + i + 1,
                        sizeof(*pboot_devices) * (pboot_dev_count + i - 1));
-
        pboot_devices[--pboot_dev_count] = NULL;
 
-       pboot_set_device_select(new_dev_index);
-       twin_window_damage(pboot_lpane->window,
-                          dev->box.left, dev->box.top,
-                          dev->box.right, dev->box.bottom);
-       twin_window_queue_paint(pboot_lpane->window);
+       /* select the newly-focussed device */
+       if (pboot_dev_sel > i)
+               newsel = pboot_dev_sel - 1;
+       else if (pboot_dev_sel == i && i >= pboot_dev_count)
+                       newsel = pboot_dev_count - 1;
+       pboot_set_device_select(newsel, 1);
 
        /* todo: free device & options */
 
@@ -899,12 +1078,22 @@ static void pboot_make_background(void)
        twin_screen_set_background(pboot_screen, scaledpic);
 }
 
+#define PS3FB_IOCTL_SETMODE          _IOW('r',  1, int)
+#define PS3FB_IOCTL_GETMODE          _IOR('r',  2, int)
+
 static void exitfunc(void)
 {
 #ifndef _USE_X11
        if (pboot_fbdev)
                twin_fbdev_destroy(pboot_fbdev);
        pboot_fbdev = NULL;
+       if (pboot_vmode_change != -1) {
+               int fd = open("/dev/fb0", O_RDWR);
+               if (fd >= 0)
+                       ioctl(fd, PS3FB_IOCTL_SETMODE,
+                             (unsigned long)&pboot_vmode_change);
+               close(fd);
+       }
 #endif
 }
 
@@ -962,9 +1151,10 @@ int main(int argc, char **argv)
        }
        pboot_screen = pboot_fbdev->screen;
        twin_linux_mouse_create(NULL, pboot_screen);
+       twin_linux_js_create(pboot_screen);
 
        if (pboot_fbdev != NULL) {
-               char *cursor_path = artwork_pathname("cursor");
+               char *cursor_path = artwork_pathname("cursor.gz");
                pboot_cursor = twin_load_X_cursor(cursor_path, 2,
                                                  &pboot_cursor_hx,
                                                  &pboot_cursor_hy);
@@ -979,9 +1169,9 @@ int main(int argc, char **argv)
        pboot_make_background();
 
        /* Init more stuffs */
-       pboot_create_panels();
-       twin_window_queue_paint(pboot_lpane->window);
-       twin_window_queue_paint(pboot_rpane->window);
+       pboot_create_lpane();
+       pboot_create_rpane();
+       pboot_create_spane();
 
        if (!pboot_start_device_discovery(udev_trigger)) {
                LOG("Couldn't start device discovery!\n");