diff options
Diffstat (limited to 'drivers/usb/gadget/android.c')
| -rw-r--r-- | drivers/usb/gadget/android.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index e5d8899b..efbfcfdc 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -25,6 +25,7 @@ #include <linux/utsname.h> #include <linux/platform_device.h> #include <linux/pm_qos.h> +#include <linux/reboot.h> #include <linux/of.h> #include <linux/usb/ch9.h> @@ -69,6 +70,7 @@ #include "u_qc_ether.c" #include "f_gsi.c" #include "f_mass_storage.h" +#include "f_usbnet.c" USB_ETHERNET_MODULE_PARAMETERS(); #include "debug.h" @@ -213,6 +215,8 @@ struct android_dev { /* A list node inside the android_dev_list */ struct list_head list_item; + /* reboot notifier */ + struct notifier_block android_reboot; }; struct android_configuration { @@ -2609,6 +2613,11 @@ static int mass_storage_function_init(struct android_usb_function *f, } fsg_mod_data.removable[0] = true; + +//lenovo sw yexh1, add for usb cdrom feature + fsg_mod_data.cdrom[0] = true; +//lenovo sw yexh1, end + fsg_config_from_params(&m_config, &fsg_mod_data, fsg_num_buffers); fsg_opts = fsg_opts_from_func_inst(config->f_ms_inst); ret = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers); @@ -3042,6 +3051,89 @@ static struct android_usb_function dpl_gsi_function = { .bind_config = dpl_gsi_function_bind_config, }; +static int usbnet_function_init(struct android_usb_function *f, + struct usb_composite_dev *cdev) +{ + struct usbnet_device *dev; + struct usbnet_context *context; + struct net_device *net_dev; + int ret; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + net_dev = alloc_netdev(sizeof(struct usbnet_context), + "usb%d", NET_NAME_UNKNOWN, usb_ether_setup); + if (!net_dev) { + pr_err("%s: alloc_netdev error\n", __func__); + return -EINVAL; + } + + ret = register_netdev(net_dev); + if (ret) { + pr_err("%s: register_netdev error\n", __func__); + free_netdev(net_dev); + return -EINVAL; + } + + ret = device_create_file(&net_dev->dev, &dev_attr_description); + if (ret < 0) { + pr_err("%s: sys file creation error\n", __func__); + unregister_netdev(net_dev); + free_netdev(net_dev); + return -EINVAL; + } + + context = netdev_priv(net_dev); + INIT_WORK(&context->usbnet_config_wq, usbnet_if_config); + + context->config = 0; + dev->net_ctxt = context; + + f->config = dev; + +#ifdef CONFIG_SWITCH + switch_dev_register(&usbnet_enable_device); +#endif + return 0; +} + +static void usbnet_function_cleanup(struct android_usb_function *f) +{ + struct usbnet_device *dev = f->config; + + usbnet_cleanup(dev); +#ifdef CONFIG_SWITCH + switch_dev_unregister(&usbnet_enable_device); +#endif +} + +static int usbnet_function_bind_config(struct android_usb_function *f, + struct usb_configuration *c) +{ + struct usbnet_device *dev = f->config; + + return usbnet_bind_config(dev, c); +} + +static int usbnet_function_ctrlrequest(struct android_usb_function *f, + struct usb_composite_dev *cdev, + const struct usb_ctrlrequest *c) +{ + struct usbnet_device *dev = f->config; + + return usbnet_ctrlrequest(dev, cdev, c); +} + +static struct android_usb_function usbnet_function = { + .name = "usbnet", + .init = usbnet_function_init, + .cleanup = usbnet_function_cleanup, + .bind_config = usbnet_function_bind_config, + .ctrlrequest = usbnet_function_ctrlrequest, +}; + static struct android_usb_function *supported_functions[] = { [ANDROID_FFS] = &ffs_function, [ANDROID_MBIM_BAM] = &mbim_function, @@ -3104,6 +3196,7 @@ static struct android_usb_function *default_functions[] = { #ifdef CONFIG_SND_RAWMIDI &midi_function, #endif + &usbnet_function, NULL }; @@ -3419,6 +3512,10 @@ functions_store(struct device *pdev, struct device_attribute *attr, strlcpy(buf, buff, sizeof(buf)); b = strim(buf); +//lenovo sw yexh1 add for print usb composite setting + pr_info("usb: %s\n", buff); +//lenovo sw yexh1 add end + while (b) { conf_str = strsep(&b, ":"); if (!conf_str) @@ -4070,6 +4167,52 @@ static int usb_diag_update_pid_and_serial_num(u32 pid, const char *snum) return 0; } +/* chenyb1 add factory feature begin*/ +static bool is_mmi_factory(void) +{ + struct device_node *np = of_find_node_by_path("/chosen"); + bool fact_cable = false; + + if (np) + fact_cable = of_property_read_bool(np, "mmi,factory-cable"); + + of_node_put(np); + return fact_cable; +} + +static void configure_mmi_factory(struct platform_device *pdev, + struct android_usb_platform_data *pdata) +{ + int prop_len = 0; + if (is_mmi_factory()) { + of_get_property(pdev->dev.of_node, + "mmi,pm-qos-latency-factory", + &prop_len); + if (prop_len == sizeof(pdata->pm_qos_latency)) { + pr_info("Overwrite pm_qos latency with factory mode\n"); + of_property_read_u32_array(pdev->dev.of_node, + "mmi,pm-qos-latency-factory", + pdata->pm_qos_latency, + prop_len/sizeof(*pdata->pm_qos_latency)); + } else { + pr_info("pm_qos latency for factory not specified\n"); + } + } +} + +static int android_reboot_notifier(struct notifier_block *nb, + unsigned long event, + void *unused) +{ + struct android_dev *dev = + container_of(nb, struct android_dev, android_reboot); + pr_err("Android reboot - de-enumerate\n"); + if (event == SYS_POWER_OFF) + usb_gadget_disconnect(dev->cdev->gadget); + return NOTIFY_DONE; +} +/* chenyb1 add factory feature end*/ + static int android_probe(struct platform_device *pdev) { struct android_usb_platform_data *pdata; @@ -4097,6 +4240,10 @@ static int android_probe(struct platform_device *pdev) pr_info("pm_qos latency not specified %d\n", prop_len); } +/* chenyb1 add factory feature begin*/ + configure_mmi_factory(pdev, pdata); +/* chenyb1 add factory feature end*/ + ret = of_property_read_u32(pdev->dev.of_node, "qcom,usb-core-id", &usb_core_id); @@ -4220,6 +4367,15 @@ static int android_probe(struct platform_device *pdev) } strlcpy(android_dev->pm_qos, "high", sizeof(android_dev->pm_qos)); + if (is_mmi_factory()) { + android_dev->android_reboot.notifier_call = + android_reboot_notifier; + android_dev->android_reboot.next = NULL; + android_dev->android_reboot.priority = 2; + ret = register_reboot_notifier(&android_dev->android_reboot); + if (ret) + dev_err(&pdev->dev, "register for reboot failed\n"); + } return ret; err_probe: android_destroy_device(android_dev); |
