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 #include #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();