static struct usb_gadget_translator *gadget_translator;
static struct usb_client *usb_client;
-static unsigned current_mode;
struct extcon_ops extcon_usb_ops;
return -ENODEV;
}
-int usb_change_mode(unsigned mode)
+static int usb_change_gadget(unsigned mode)
{
struct usb_gadget_id gadget_id;
struct usb_gadget *gadget;
goto out;
}
- current_mode = mode;
+ usb_state_set_selected_mode(mode);
+ _I("USB gadget changed (%d)", mode);
+
out:
return ret;
no_hal:
return -ENODEV;
}
+static int usb_enable(unsigned int mode)
+{
+ int ret;
+ unsigned int selected;
+
+ selected = usb_state_get_selected_mode();
+
+ if (usb_state_get_connection() != USB_CONNECTED) {
+ _E("Failed to enable usb gadget (USB cable is not connected)");
+ return -ENOTSUP;
+ }
+
+ if (usb_state_get_current_mode() != USB_FUNCTION_NONE)
+ usb_state_update_state(USB_CONNECTED, USB_FUNCTION_NONE);
+
+ if (mode != selected)
+ usb_change_gadget(mode);
+
+ ret = usb_config_enable();
+ if (ret < 0) {
+ _E("Failed to enable usb config (%d)", ret);
+ return ret;
+ }
+
+ usb_state_update_state(USB_CONNECTED, mode);
+ pm_lock_internal(INTERNAL_LOCK_USB,
+ LCD_OFF, STAY_CUR_STATE, 0);
+
+ return 0;
+}
+
+static int usb_disable(void)
+{
+ int ret;
+
+ if (usb_state_get_current_mode() != USB_FUNCTION_NONE) {
+ if (usb_state_get_connection() == USB_CONNECTED)
+ usb_state_update_state(USB_CONNECTED, USB_FUNCTION_NONE);
+ else
+ usb_state_update_state(USB_DISCONNECTED, USB_FUNCTION_NONE);
+ }
+
+ ret = usb_config_disable();
+ if (ret != 0)
+ _E("Failed to disable usb config (%d)", ret);
+
+ pm_unlock_internal(INTERNAL_LOCK_USB,
+ LCD_OFF, STAY_CUR_STATE);
+
+ return 0;
+}
+
+int usb_change_mode(unsigned mode)
+{
+ int ret;
+ unsigned int curr = usb_state_get_current_mode();
+
+ if (curr != USB_FUNCTION_NONE) {
+ usb_operation_stop(curr);
+
+ ret = usb_disable();
+ if (ret < 0) {
+ _E("Failed to disable current usb mode");
+ return ret;
+ }
+ }
+
+ ret = usb_change_gadget(mode);
+ if (ret < 0) {
+ _E("Failed to change gadget (%d)", ret);
+ mode = usb_state_get_selected_mode();
+ }
+
+ if (usb_state_get_connection() == USB_CONNECTED) {
+ ret = usb_enable(mode);
+ if (ret < 0) {
+ _E("Failed to enable usb mode (%d)");
+ return ret;
+ }
+
+ usb_operation_start(mode);
+ }
+
+ return 0;
+}
+
+static int usb_connected(void)
+{
+ int ret;
+ unsigned int mode = usb_state_get_selected_mode();
+
+ usb_state_update_state(USB_CONNECTED, USB_FUNCTION_NONE);
+
+ ret = usb_enable(mode);
+ if (ret < 0) {
+ _E("Failed to enable usb gadget (gadget:%d, ret:%d)", mode, ret);
+ return ret;
+ }
+
+ usb_operation_start(mode);
+
+ return 0;
+}
+
+static int usb_disconnected(void)
+{
+ usb_operation_stop(usb_state_get_current_mode());
+
+ usb_state_update_state(USB_DISCONNECTED, USB_FUNCTION_NONE);
+
+ return usb_disable();
+}
+
static int usb_state_changed(int status)
{
static int old = -1; /* to update at the first time */
- unsigned mode;
int ret;
_I("USB state is changed from (%d) to (%d)", old, status);
switch (status) {
case USB_CONNECTED:
_I("USB cable is connected");
- usb_state_update_state(USB_CONNECTED, USB_FUNCTION_NONE);
- mode = usb_state_get_selected_mode();
- if (mode != current_mode)
- usb_change_mode(mode);
-
- ret = usb_config_enable();
- if (ret < 0) {
- _E("Failed to enable usb config (%d)", ret);
- break;
- }
- usb_operation_start(mode);
- usb_state_update_state(USB_CONNECTED, mode);
- pm_lock_internal(INTERNAL_LOCK_USB,
- LCD_OFF, STAY_CUR_STATE, 0);
+ ret = usb_connected();
break;
case USB_DISCONNECTED:
_I("USB cable is disconnected");
- usb_operation_stop(usb_state_get_current_mode());
- usb_state_update_state(USB_DISCONNECTED, USB_FUNCTION_NONE);
-
- ret = usb_config_disable();
- if (ret != 0)
- _E("Failed to disable usb config (%d)", ret);
- pm_unlock_internal(INTERNAL_LOCK_USB,
- LCD_OFF, STAY_CUR_STATE);
+ ret = usb_disconnected();
break;
default:
_E("Invalid USB state(%d)", status);