diff --git a/apps/gui/usb_screen.c b/apps/gui/usb_screen.c
index 019aec6..bbca8b0 100644
--- a/apps/gui/usb_screen.c
+++ b/apps/gui/usb_screen.c
@@ -37,7 +37,8 @@
#include "led.h"
#include "appevents.h"
#include "usb_screen.h"
-
+#include "icon.h"
+#include "list.h"
#ifdef HAVE_LCD_BITMAP
#include "bitmaps/usblogo.h"
#endif
@@ -326,3 +327,131 @@ void gui_usb_screen_run(void)
}
+struct usbmenuitem {
+ bool enabled;
+ char *text;
+};
+
+static struct usbmenuitem items[] = {
+ [0] = { true, "Connect" },
+ [1] = { false, "Battery Charge Only" },
+ [2] = { true, " -- Storage Drivers -- " },
+ [3] = { true, "Mass Storage" },
+ [4] = { false, "MTP" },
+ [5] = { true, "-- HID Drivers -- " },
+ [6] = { false, "Desktop mode" },
+ [7] = { false, "Presentation mode" },
+ [8] = { true, "Media Player mode" },
+ [9] = { false, "Battery Charge Only" },
+};
+const char * usblist_get_name(int selected_item, void * data,
+ char * buffer, size_t buffer_len)
+{
+ return items[selected_item].text;
+}
+enum themable_icons usblist_get_icon(int selected_item, void * data)
+{
+ switch (selected_item)
+ {
+ /* no icons ever */
+ case 0:
+ case 1:
+ case 2:
+ case 5:
+ return Icon_Submenu;
+ default:
+ return items[selected_item].enabled ? Icon_Cursor : Icon_NOICON;
+ }
+}
+void usb_connection_gui(void)
+{
+ bool done = false;
+ struct gui_synclist lists;
+ int i, action, selection;
+ FOR_NB_SCREENS(i)
+ viewportmanager_theme_enable(i, true, NULL);
+
+
+ gui_synclist_init(&lists, usblist_get_name, NULL,
+ false, 1, NULL);
+ gui_synclist_set_title(&lists, "Usb Connection Menu", Icon_Rockbox);
+ gui_synclist_set_icon_callback(&lists, usblist_get_icon);
+ gui_synclist_set_nb_items(&lists, 10);
+ gui_synclist_select_item(&lists, 0);
+
+
+ while (!done)
+ {
+ gui_synclist_draw(&lists);
+ list_do_action(CONTEXT_STD, HZ,
+ &lists, &action, LIST_WRAP_UNLESS_HELD);
+ switch (action)
+ {
+ case ACTION_STD_OK:
+ /* fix the toggles or run the screen */
+ selection = gui_synclist_get_sel_pos(&lists);
+ switch (selection)
+ {
+ case 0: /* run! */
+ done = true;
+ break;
+ case 1: /* battery only */
+ break;
+ case 2: /* headers, do nothing */
+ case 5:
+ break;
+ case 3: /* storage modes */
+ case 4:
+ if (!items[selection].enabled)
+ {
+ items[selection==3?4:3].enabled = false;
+ items[selection].enabled = true;
+ }
+ else
+ items[selection].enabled = false;
+ break;
+ case 6: /* HID modes */
+ case 7:
+ case 8:
+ case 9:
+ if (!items[selection].enabled)
+ {
+ for (i=6;i<=9;i++)
+ {
+ if (i == selection)
+ items[i].enabled = true;
+ else
+ items[i].enabled = false;
+ }
+ }
+ else
+ items[selection].enabled = false;
+ break;
+ } /* switch() */
+ break;
+ } /* switch(action) */
+ }
+#ifdef USB_ENABLE_STORAGE
+ usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, items[3].enabled);
+ splashf(HZ, "MSC %s", items[3].enabled?"Yes":"no");
+#endif
+#ifdef USB_ENABLE_HID
+ bool hid_enabled = false;
+ for (i=6;i<=9;i++)
+ {
+ if (items[i].enabled)
+ hid_enabled = true;
+ }
+ usb_core_enable_driver(USB_DRIVER_HID, hid_enabled);
+ splashf(HZ, "HID %s", hid_enabled?"Yes":"no");
+#endif
+#ifdef USB_ENABLE_CHARGING_ONLY
+ usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false);
+#endif
+ usb_core_enable_driver(USB_DRIVER_MTP, items[4].enabled);
+ splashf(HZ, "MTP %s", items[4].enabled?"Yes":"no");
+
+ FOR_NB_SCREENS(i)
+ viewportmanager_theme_undo(i, true);
+ usb_allow_connection();
+}
diff --git a/apps/misc.c b/apps/misc.c
index f9c6116..55c7660 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -29,6 +29,7 @@
#include <stdarg.h>
#include <stdio.h>
#else
+#include "usb.h"
#include "sprintf.h"
#include "lang.h"
#include "dir.h"
@@ -567,6 +568,9 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
talk_force_enqueue_next();
}
break;
+ case SYS_USB_ATTACHED:
+ usb_connection_gui();
+ break;
case SYS_USB_CONNECTED:
if (callback != NULL)
callback(parameter);
diff --git a/apps/settings.h b/apps/settings.h
index fc44caa..98f60d3 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -109,6 +109,26 @@ enum
TRIG_TYPE_NEW_FILE
};
+#ifdef HAVE_USBSTACK
+enum {
+ USB_SCREENSHOT = 0,
+ USB_MENU,
+#ifdef USB_ENABLE_STORAGE
+ USB_MSC,
+#endif
+#ifdef USB_ENABLE_MTP
+ USB_MTP,
+#endif
+#ifdef USB_ENABLE_HID
+ USB_HID,
+#endif
+#ifdef USB_ENABLE_CHARGING_ONLY
+ USB_BATTERYONLY,
+#endif
+ USB_NUM_OPTIONS
+}
+#endif
+
#ifdef HAVE_CROSSFADE
enum {
CROSSFADE_ENABLE_OFF = 0,
@@ -139,7 +159,6 @@ enum
NUM_REPEAT_MODES
};
-
/* dir filter options */
/* Note: Any new filter modes need to be added before NUM_FILTER_MODES.
* Any new rockbox browse filter modes (accessible through the menu)
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h
index a476130..42827e4 100644
--- a/firmware/export/kernel.h
+++ b/firmware/export/kernel.h
@@ -61,13 +61,14 @@
#define SYS_EVENT_ID(e) ((e) & ~(SYS_EVENT|SYS_EVENT_CLS_MASK))
#define SYS_TIMEOUT MAKE_SYS_EVENT(SYS_EVENT_CLS_QUEUE, 0)
-#define SYS_USB_CONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 0)
-#define SYS_USB_CONNECTED_ACK MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 1)
-#define SYS_USB_DISCONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 2)
-#define SYS_USB_DISCONNECTED_ACK MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 3)
-#define SYS_USB_LUN_LOCKED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 4)
-#define SYS_USB_READ_DATA MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 5)
-#define SYS_USB_WRITE_DATA MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 6)
+#define SYS_USB_ATTACHED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 0)
+#define SYS_USB_CONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 1)
+#define SYS_USB_CONNECTED_ACK MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 2)
+#define SYS_USB_DISCONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 3)
+#define SYS_USB_DISCONNECTED_ACK MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 4)
+#define SYS_USB_LUN_LOCKED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 5)
+#define SYS_USB_READ_DATA MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 6)
+#define SYS_USB_WRITE_DATA MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 7)
#define SYS_POWEROFF MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 0)
#define SYS_CHARGER_CONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 1)
#define SYS_CHARGER_DISCONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 2)
diff --git a/firmware/usb.c b/firmware/usb.c
index 13e273a..96269f4 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -222,6 +222,13 @@ static inline bool usb_reboot_button(void)
static bool usb_hid = true;
#endif
+extern struct event_queue button_queue;
+static bool ready_for_connect;
+void usb_allow_connection(void)
+{
+ ready_for_connect = true;
+}
+
static void usb_thread(void)
{
int num_acks_to_expect = 0;
@@ -263,43 +270,17 @@ static void usb_thread(void)
break;
#endif /* USB_DETECT_BY_DRV */
case USB_INSERTED:
-#ifdef HAVE_LCD_BITMAP
- if(do_screendump_instead_of_usb)
- {
- usb_state = USB_SCREENDUMP;
- screen_dump();
-#ifdef HAVE_REMOTE_LCD
- remote_screen_dump();
-#endif
- break;
- }
-#endif
-#ifdef HAVE_USB_POWER
- if(usb_power_button())
+ /* inject an event into the button queue so the main thread
+ * will run the USB-UI code and return after the desired
+ * drivers are enabled */
+ ready_for_connect = false;
+ queue_send(&button_queue, SYS_USB_ATTACHED, NULL);
+ usb_state = USB_POWERED;
+ while (!ready_for_connect)
{
- /* Only charging is desired */
- usb_state = USB_POWERED;
+ sleep(HZ/10);
}
- else
-#endif /* HAVE_USB_POWER */
#ifdef HAVE_USBSTACK
- {
-#ifdef HAVE_USB_POWER
- /* Set the state to USB_POWERED for now. If permission to connect
- * by threads and storage is granted it will be changed to
- * USB_CONNECTED. */
- usb_state = USB_POWERED;
-#endif
-#ifdef USB_ENABLE_STORAGE
- usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true);
-#endif
-#ifdef USB_ENABLE_HID
- usb_core_enable_driver(USB_DRIVER_HID, usb_hid);
-#endif
-#ifdef USB_ENABLE_CHARGING_ONLY
- usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false);
-#endif
- }
/* Check any drivers enabled at this point for exclusive storage
* access requirements. */
exclusive_storage_access = usb_core_any_exclusive_storage();