From 46188c726b70547e7eebcd386a72becfac300597 Mon Sep 17 00:00:00 2001
From: Andreas Eversberg <jolly@eversberg.eu>
Date: Thu, 26 Sep 2013 09:40:23 +0200
Subject: [PATCH 1/2] Menu App to select highram images from phone's flash
 memory

---
 src/target/firmware/Makefile         |    3 +-
 src/target/firmware/apps/menu/main.c |  353 ++++++++++++++++++++++++++++++++++
 2 files changed, 355 insertions(+), 1 deletion(-)
 create mode 100644 src/target/firmware/apps/menu/main.c

diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile
index 42f7ad4..0f4120f 100644
--- a/src/target/firmware/Makefile
+++ b/src/target/firmware/Makefile
@@ -84,11 +84,12 @@ BOARD_se_j100_ENVIRONMENTS=$(compal_COMMON_ENVIRONMENTS)
 #
 
 # List of all applications (meant to be overridden on command line)
-APPLICATIONS?=hello_world compal_dsp_dump layer1 loader rssi
+APPLICATIONS?=hello_world compal_dsp_dump layer1 loader rssi menu
 
 # Applications specific env requirements
 APP_loader_ENVIRONMENTS=compalram highram
 APP_rssi_ENVIRONMENTS=* -compalram
+APP_menu_ENVIRONMENTS=* -highram
 
 # Various objects that are currently linked into all applications
 FLASH_OBJS=flash/cfi_flash.o
diff --git a/src/target/firmware/apps/menu/main.c b/src/target/firmware/apps/menu/main.c
new file mode 100644
index 0000000..47aadc4
--- /dev/null
+++ b/src/target/firmware/apps/menu/main.c
@@ -0,0 +1,353 @@
+/* Menu for Calypso Phone to load applicatios from flash */
+
+/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <debug.h>
+#include <memory.h>
+#include <delay.h>
+#include <byteorder.h>
+#include <rffe.h>
+#include <keypad.h>
+#include <board.h>
+#include <abb/twl3025.h>
+#include <rf/trf6151.h>
+#include <calypso/clock.h>
+#include <calypso/tpu.h>
+#include <calypso/tsp.h>
+#include <calypso/dsp.h>
+#include <calypso/irq.h>
+#include <calypso/misc.h>
+#include <calypso/timer.h>
+#include <comm/sercomm.h>
+#include <comm/timer.h>
+#include <uart.h>
+#include <fb/framebuffer.h>
+#include <battery/battery.h>
+#include <asm/system.h>
+
+#define RAM 0x00820000
+#define MAGIC 0x0083ff00
+
+enum key_codes key_code = KEY_INV;
+static volatile enum key_states key_state;
+
+int cursor = 0, scroll_apps = 0;
+
+struct apps {
+	char name[16];
+	void *start;
+	int len;
+} apps[32];
+
+int _memcmp(char *s1, char *s2, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (*s1 < *s2)
+			return -1;
+		if (*s1 > *s2)
+			return 1;
+		s1++;
+		s2++;
+	}
+
+	return 0;
+}
+
+static void locate_apps(void)
+{
+	int i, j, k;
+	char *p;
+
+	memset(apps, 0, sizeof(apps));
+
+	for (j = 0, i = 0x010000; i < 0x200000; i += 0x10000) {
+		p = (char *)i;
+		/* check for highram header: "highram:" */
+		if (!!_memcmp(p, "highram:", 8))
+			continue;
+		p += 8;
+		/* check for app name after header: "highram:<name>\n" */
+		printf("found highram image at flash mem address 0x%p\n",
+			(char *)i);
+		for (k = 0; k < (int)sizeof(apps[j].name) - 1; k++) {
+			if (p[k] == '\n')
+				break;
+		}
+		if (k == sizeof(apps[j].name) - 3) {
+			printf("skipping: corrupt highram header, no '\\n' "
+				"after image name or name more larger than %d "
+				"digits\n", (int)sizeof(apps[j].name) - 3);
+				continue;
+		}
+		if (j < 9)
+			apps[j].name[0] = '1' + j;
+		else if (j == 9)
+			apps[j].name[0] = '0';
+		else
+			apps[j].name[0] = ' ';
+		apps[j].name[1] = ' ';
+		memcpy(apps[j].name + 2, p, k);
+		apps[j].len = 0x20000;
+		p += k + 1;
+		/* p points to highram image after header */
+		apps[j].start = p;
+		j++;
+	}
+}
+
+static void wait_key_release(void)
+{
+	/* wait for key release */
+	while (key_state == PRESSED) {
+		delay_ms(10);
+		keypad_poll();
+	}
+}
+
+static void load_app(void)
+{
+	static int i;
+	static void (*f) (void) = (void (*)(void))RAM;
+
+	wait_key_release();
+
+	local_irq_disable();
+
+	for (i = 0; i < apps[cursor].len; i++)
+		((unsigned char *)RAM)[i] = ((unsigned char *)apps[cursor].start)[i];
+	f();
+}
+
+/* UI */
+
+static void refresh_display(void)
+{
+#if 0
+	char text[16];
+	int bat = battery_info.battery_percent;
+#endif
+	int i;
+
+	fb_clear();
+
+	/* header */
+	fb_setbg(FB_COLOR_WHITE);
+	if (1) {
+		fb_setfg(FB_COLOR_BLUE);
+		fb_setfont(FB_FONT_HELVR08);
+		fb_gotoxy(0, 7);
+		fb_putstr("Osmocom Menu", -1);
+		fb_setfg(FB_COLOR_RGB(0xc0, 0xc0, 0x00));
+		fb_setfont(FB_FONT_SYMBOLS);
+#if 0
+		fb_gotoxy(framebuffer->width - 15, 8);
+		if (bat >= 100 && (battery_info.flags & BATTERY_CHG_ENABLED)
+		 && !(battery_info.flags & BATTERY_CHARGING))
+			fb_putstr("@HHBC", framebuffer->width);
+		else {
+			sprintf(text, "@%c%c%cC", (bat >= 30) ? 'B':'A',
+				(bat >= 60) ? 'B':'A', (bat >= 90) ? 'B':'A');
+			fb_putstr(text, framebuffer->width);
+		}
+#endif
+		fb_gotoxy(0, 8);
+		fb_putstr("GGEGG", framebuffer->width);
+		fb_setfg(FB_COLOR_GREEN);
+		fb_gotoxy(0, 10);
+		fb_boxto(framebuffer->width - 1, 10);
+	}
+	fb_setfg(FB_COLOR_BLACK);
+	fb_setfont(FB_FONT_C64);
+
+
+	for (i = 0; i < 5; i++) {
+		if (!apps[scroll_apps + i].name)
+			break;
+		if (scroll_apps + i == cursor) {
+			fb_setfg(FB_COLOR_WHITE);
+			fb_setbg(FB_COLOR_BLUE);
+		}
+		fb_gotoxy(0, 20 + i * 10);
+		fb_putstr(apps[scroll_apps + i].name,
+			framebuffer->width);
+		if (scroll_apps + i == cursor) {
+			fb_setfg(FB_COLOR_BLACK);
+			fb_setbg(FB_COLOR_WHITE);
+		}
+	}
+	if (i == 0) {
+		fb_gotoxy(0, 50);
+		fb_putstr("No apps!", -1);
+	}
+
+	fb_flush();
+}
+
+static void handle_key_code()
+{
+	if (key_code == KEY_INV)
+		return;
+
+	switch (key_code) {
+	case KEY_1:
+	case KEY_2:
+	case KEY_3:
+	case KEY_4:
+	case KEY_5:
+	case KEY_6:
+	case KEY_7:
+	case KEY_8:
+	case KEY_9:
+		if (apps[key_code - KEY_1].len) {
+			cursor = key_code - KEY_1;
+			load_app();
+		}
+		break;
+	case KEY_0:
+		if (apps[9].len) {
+			cursor = 9;
+			load_app();
+		}
+		break;
+	case KEY_UP:
+		if (cursor == 0)
+			return;
+		cursor--;
+		if (cursor < scroll_apps)
+			scroll_apps = cursor;
+		refresh_display();
+		break;
+	case KEY_DOWN:
+		if (!apps[cursor + 1].name[0])
+			return;
+		cursor++;
+		if (cursor >= scroll_apps + 5)
+			scroll_apps = cursor - 4;
+		refresh_display();
+		break;
+	case KEY_OK:
+		if (apps[cursor].len)
+			load_app();
+		break;
+	case KEY_POWER:
+		wait_key_release();
+		twl3025_power_off();
+		break;
+	default:
+		break;
+	}
+
+	key_code = KEY_INV;
+}
+
+/* Main Program */
+const char *hr = "======================================================================\n";
+
+static void key_handler(enum key_codes code, enum key_states state)
+{
+	key_state = state;
+
+	if (state != PRESSED)
+		return;
+
+	key_code = code;
+}
+
+extern void putchar_asm(uint32_t c);
+
+static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 };
+
+int main(void)
+{
+	int i;
+
+	/* Simulate a compal loader saying "ACK" */
+	for (i = 0; i < (int)sizeof(phone_ack); i++) {
+		putchar_asm(phone_ack[i]);
+	}
+
+	board_init(0);
+
+	puts("\n\nOsmocomBB Menu (revision " GIT_REVISION ")\n");
+	puts(hr);
+
+	fb_clear();
+
+	fb_setfg(FB_COLOR_BLACK);
+	fb_setbg(FB_COLOR_WHITE);
+	fb_setfont(FB_FONT_HELVB14);
+
+	fb_gotoxy(2,20);
+	fb_putstr("menu",framebuffer->width-4);
+
+	fb_setfg(FB_COLOR_RED);
+	fb_setbg(FB_COLOR_BLUE);
+
+	fb_gotoxy(2,25);
+	fb_boxto(framebuffer->width-3,38);
+
+	fb_setfg(FB_COLOR_WHITE);
+	fb_setfont(FB_FONT_HELVR08);
+	fb_gotoxy(8,33);
+	fb_putstr("osmocom-bb",framebuffer->width-4);
+
+	fb_flush();
+
+	/* Dump device identification */
+	dump_dev_id();
+	puts(hr);
+
+	/* Dump clock config before PLL set */
+	calypso_clk_dump();
+	puts(hr);
+
+	keypad_set_handler(&key_handler);
+
+	/* Dump clock config after PLL set */
+	calypso_clk_dump();
+	puts(hr);
+
+//	display_unset_attr(DISP_ATTR_INVERT);
+
+	locate_apps();
+
+	while (1) {
+		for (i = 0; i < 50; i++) {
+			keypad_poll();
+			delay_ms(10);
+			osmo_timers_update();
+			handle_key_code();
+		}
+		refresh_display();
+	}
+
+	/* NOT REACHED */
+
+	twl3025_power_off();
+}
+
-- 
1.7.10.4

