aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_ecm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_ecm.c')
-rw-r--r--drivers/usb/gadget/f_ecm.c197
1 files changed, 182 insertions, 15 deletions
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index abf8a31ae146..5d3561ea1c15 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -14,10 +14,13 @@
14 14
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/module.h>
17#include <linux/device.h> 18#include <linux/device.h>
18#include <linux/etherdevice.h> 19#include <linux/etherdevice.h>
19 20
20#include "u_ether.h" 21#include "u_ether.h"
22#include "u_ether_configfs.h"
23#include "u_ecm.h"
21 24
22 25
23/* 26/*
@@ -684,9 +687,44 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
684{ 687{
685 struct usb_composite_dev *cdev = c->cdev; 688 struct usb_composite_dev *cdev = c->cdev;
686 struct f_ecm *ecm = func_to_ecm(f); 689 struct f_ecm *ecm = func_to_ecm(f);
690 struct usb_string *us;
687 int status; 691 int status;
688 struct usb_ep *ep; 692 struct usb_ep *ep;
689 693
694#ifndef USBF_ECM_INCLUDED
695 struct f_ecm_opts *ecm_opts;
696
697 if (!can_support_ecm(cdev->gadget))
698 return -EINVAL;
699
700 ecm_opts = container_of(f->fi, struct f_ecm_opts, func_inst);
701
702 /*
703 * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
704 * configurations are bound in sequence with list_for_each_entry,
705 * in each configuration its functions are bound in sequence
706 * with list_for_each_entry, so we assume no race condition
707 * with regard to ecm_opts->bound access
708 */
709 if (!ecm_opts->bound) {
710 mutex_lock(&ecm_opts->lock);
711 gether_set_gadget(ecm_opts->net, cdev->gadget);
712 status = gether_register_netdev(ecm_opts->net);
713 mutex_unlock(&ecm_opts->lock);
714 if (status)
715 return status;
716 ecm_opts->bound = true;
717 }
718#endif
719 us = usb_gstrings_attach(cdev, ecm_strings,
720 ARRAY_SIZE(ecm_string_defs));
721 if (IS_ERR(us))
722 return PTR_ERR(us);
723 ecm_control_intf.iInterface = us[0].id;
724 ecm_data_intf.iInterface = us[2].id;
725 ecm_desc.iMACAddress = us[1].id;
726 ecm_iad_descriptor.iFunction = us[3].id;
727
690 /* allocate instance-specific interface IDs */ 728 /* allocate instance-specific interface IDs */
691 status = usb_interface_id(c, f); 729 status = usb_interface_id(c, f);
692 if (status < 0) 730 if (status < 0)
@@ -796,14 +834,15 @@ fail:
796 return status; 834 return status;
797} 835}
798 836
837#ifdef USBF_ECM_INCLUDED
838
799static void 839static void
800ecm_unbind(struct usb_configuration *c, struct usb_function *f) 840ecm_old_unbind(struct usb_configuration *c, struct usb_function *f)
801{ 841{
802 struct f_ecm *ecm = func_to_ecm(f); 842 struct f_ecm *ecm = func_to_ecm(f);
803 843
804 DBG(c->cdev, "ecm unbind\n"); 844 DBG(c->cdev, "ecm unbind\n");
805 845
806 ecm_string_defs[0].id = 0;
807 usb_free_all_descriptors(f); 846 usb_free_all_descriptors(f);
808 847
809 kfree(ecm->notify_req->buf); 848 kfree(ecm->notify_req->buf);
@@ -834,17 +873,6 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
834 if (!can_support_ecm(c->cdev->gadget) || !ethaddr) 873 if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
835 return -EINVAL; 874 return -EINVAL;
836 875
837 if (ecm_string_defs[0].id == 0) {
838 status = usb_string_ids_tab(c->cdev, ecm_string_defs);
839 if (status)
840 return status;
841
842 ecm_control_intf.iInterface = ecm_string_defs[0].id;
843 ecm_data_intf.iInterface = ecm_string_defs[2].id;
844 ecm_desc.iMACAddress = ecm_string_defs[1].id;
845 ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
846 }
847
848 /* allocate and initialize one new instance */ 876 /* allocate and initialize one new instance */
849 ecm = kzalloc(sizeof *ecm, GFP_KERNEL); 877 ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
850 if (!ecm) 878 if (!ecm)
@@ -858,10 +886,9 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
858 ecm->port.cdc_filter = DEFAULT_FILTER; 886 ecm->port.cdc_filter = DEFAULT_FILTER;
859 887
860 ecm->port.func.name = "cdc_ethernet"; 888 ecm->port.func.name = "cdc_ethernet";
861 ecm->port.func.strings = ecm_strings;
862 /* descriptors are per-instance copies */ 889 /* descriptors are per-instance copies */
863 ecm->port.func.bind = ecm_bind; 890 ecm->port.func.bind = ecm_bind;
864 ecm->port.func.unbind = ecm_unbind; 891 ecm->port.func.unbind = ecm_old_unbind;
865 ecm->port.func.set_alt = ecm_set_alt; 892 ecm->port.func.set_alt = ecm_set_alt;
866 ecm->port.func.get_alt = ecm_get_alt; 893 ecm->port.func.get_alt = ecm_get_alt;
867 ecm->port.func.setup = ecm_setup; 894 ecm->port.func.setup = ecm_setup;
@@ -872,3 +899,143 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
872 kfree(ecm); 899 kfree(ecm);
873 return status; 900 return status;
874} 901}
902
903#else
904
905static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item)
906{
907 return container_of(to_config_group(item), struct f_ecm_opts,
908 func_inst.group);
909}
910
911/* f_ecm_item_ops */
912USB_ETHERNET_CONFIGFS_ITEM(ecm);
913
914/* f_ecm_opts_dev_addr */
915USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ecm);
916
917/* f_ecm_opts_host_addr */
918USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ecm);
919
920/* f_ecm_opts_qmult */
921USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm);
922
923/* f_ecm_opts_ifname */
924USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm);
925
926static struct configfs_attribute *ecm_attrs[] = {
927 &f_ecm_opts_dev_addr.attr,
928 &f_ecm_opts_host_addr.attr,
929 &f_ecm_opts_qmult.attr,
930 &f_ecm_opts_ifname.attr,
931 NULL,
932};
933
934static struct config_item_type ecm_func_type = {
935 .ct_item_ops = &ecm_item_ops,
936 .ct_attrs = ecm_attrs,
937 .ct_owner = THIS_MODULE,
938};
939
940static void ecm_free_inst(struct usb_function_instance *f)
941{
942 struct f_ecm_opts *opts;
943
944 opts = container_of(f, struct f_ecm_opts, func_inst);
945 if (opts->bound)
946 gether_cleanup(netdev_priv(opts->net));
947 else
948 free_netdev(opts->net);
949 kfree(opts);
950}
951
952static struct usb_function_instance *ecm_alloc_inst(void)
953{
954 struct f_ecm_opts *opts;
955
956 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
957 if (!opts)
958 return ERR_PTR(-ENOMEM);
959 mutex_init(&opts->lock);
960 opts->func_inst.free_func_inst = ecm_free_inst;
961 opts->net = gether_setup_default();
962 if (IS_ERR(opts->net))
963 return ERR_PTR(PTR_ERR(opts->net));
964
965 config_group_init_type_name(&opts->func_inst.group, "", &ecm_func_type);
966
967 return &opts->func_inst;
968}
969
970static void ecm_free(struct usb_function *f)
971{
972 struct f_ecm *ecm;
973 struct f_ecm_opts *opts;
974
975 ecm = func_to_ecm(f);
976 opts = container_of(f->fi, struct f_ecm_opts, func_inst);
977 kfree(ecm);
978 mutex_lock(&opts->lock);
979 opts->refcnt--;
980 mutex_unlock(&opts->lock);
981}
982
983static void ecm_unbind(struct usb_configuration *c, struct usb_function *f)
984{
985 struct f_ecm *ecm = func_to_ecm(f);
986
987 DBG(c->cdev, "ecm unbind\n");
988
989 usb_free_all_descriptors(f);
990
991 kfree(ecm->notify_req->buf);
992 usb_ep_free_request(ecm->notify, ecm->notify_req);
993}
994
995struct usb_function *ecm_alloc(struct usb_function_instance *fi)
996{
997 struct f_ecm *ecm;
998 struct f_ecm_opts *opts;
999 int status;
1000
1001 /* allocate and initialize one new instance */
1002 ecm = kzalloc(sizeof(*ecm), GFP_KERNEL);
1003 if (!ecm)
1004 return ERR_PTR(-ENOMEM);
1005
1006 opts = container_of(fi, struct f_ecm_opts, func_inst);
1007 mutex_lock(&opts->lock);
1008 opts->refcnt++;
1009
1010 /* export host's Ethernet address in CDC format */
1011 status = gether_get_host_addr_cdc(opts->net, ecm->ethaddr,
1012 sizeof(ecm->ethaddr));
1013 if (status < 12) {
1014 kfree(ecm);
1015 mutex_unlock(&opts->lock);
1016 return ERR_PTR(-EINVAL);
1017 }
1018 ecm_string_defs[1].s = ecm->ethaddr;
1019
1020 ecm->port.ioport = netdev_priv(opts->net);
1021 mutex_unlock(&opts->lock);
1022 ecm->port.cdc_filter = DEFAULT_FILTER;
1023
1024 ecm->port.func.name = "cdc_ethernet";
1025 /* descriptors are per-instance copies */
1026 ecm->port.func.bind = ecm_bind;
1027 ecm->port.func.unbind = ecm_unbind;
1028 ecm->port.func.set_alt = ecm_set_alt;
1029 ecm->port.func.get_alt = ecm_get_alt;
1030 ecm->port.func.setup = ecm_setup;
1031 ecm->port.func.disable = ecm_disable;
1032 ecm->port.func.free_func = ecm_free;
1033
1034 return &ecm->port.func;
1035}
1036
1037DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc);
1038MODULE_LICENSE("GPL");
1039MODULE_AUTHOR("David Brownell");
1040
1041#endif