aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_acm.c')
-rw-r--r--drivers/usb/gadget/f_acm.c137
1 files changed, 73 insertions, 64 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 1ae180baa597..4b7e33e5d9c6 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -715,13 +715,31 @@ fail:
715 return status; 715 return status;
716} 716}
717 717
718static struct f_acm *acm_alloc_basic_func(void) 718static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
719{
720 struct f_acm *acm = func_to_acm(f);
721
722 acm_string_defs[0].id = 0;
723 usb_free_all_descriptors(f);
724 if (acm->notify_req)
725 gs_free_req(acm->notify, acm->notify_req);
726}
727
728static void acm_free_func(struct usb_function *f)
729{
730 struct f_acm *acm = func_to_acm(f);
731
732 kfree(acm);
733}
734
735static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
719{ 736{
720 struct f_acm *acm; 737 struct f_serial_opts *opts;
738 struct f_acm *acm;
721 739
722 acm = kzalloc(sizeof(*acm), GFP_KERNEL); 740 acm = kzalloc(sizeof(*acm), GFP_KERNEL);
723 if (!acm) 741 if (!acm)
724 return NULL; 742 return ERR_PTR(-ENOMEM);
725 743
726 spin_lock_init(&acm->lock); 744 spin_lock_init(&acm->lock);
727 745
@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)
730 acm->port.send_break = acm_send_break; 748 acm->port.send_break = acm_send_break;
731 749
732 acm->port.func.name = "acm"; 750 acm->port.func.name = "acm";
751 acm->port.func.strings = acm_strings;
733 /* descriptors are per-instance copies */ 752 /* descriptors are per-instance copies */
734 acm->port.func.bind = acm_bind; 753 acm->port.func.bind = acm_bind;
735 acm->port.func.set_alt = acm_set_alt; 754 acm->port.func.set_alt = acm_set_alt;
736 acm->port.func.setup = acm_setup; 755 acm->port.func.setup = acm_setup;
737 acm->port.func.disable = acm_disable; 756 acm->port.func.disable = acm_disable;
738 757
739 return acm; 758 opts = container_of(fi, struct f_serial_opts, func_inst);
759 acm->port_num = opts->port_num;
760 acm->port.func.unbind = acm_unbind;
761 acm->port.func.free_func = acm_free_func;
762
763 return &acm->port.func;
740} 764}
741 765
742#ifdef USB_FACM_INCLUDED 766static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
743static void
744acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
745{ 767{
746 struct f_acm *acm = func_to_acm(f); 768 return container_of(to_config_group(item), struct f_serial_opts,
747 769 func_inst.group);
748 usb_free_all_descriptors(f);
749 if (acm->notify_req)
750 gs_free_req(acm->notify, acm->notify_req);
751 kfree(acm);
752} 770}
753 771
754/** 772CONFIGFS_ATTR_STRUCT(f_serial_opts);
755 * acm_bind_config - add a CDC ACM function to a configuration 773static ssize_t f_acm_attr_show(struct config_item *item,
756 * @c: the configuration to support the CDC ACM instance 774 struct configfs_attribute *attr,
757 * @port_num: /dev/ttyGS* port this interface will use 775 char *page)
758 * Context: single threaded during gadget setup
759 *
760 * Returns zero on success, else negative errno.
761 *
762 */
763int acm_bind_config(struct usb_configuration *c, u8 port_num)
764{ 776{
765 struct f_acm *acm; 777 struct f_serial_opts *opts = to_f_serial_opts(item);
766 int status; 778 struct f_serial_opts_attribute *f_serial_opts_attr =
767 779 container_of(attr, struct f_serial_opts_attribute, attr);
768 /* allocate and initialize one new instance */ 780 ssize_t ret = 0;
769 acm = acm_alloc_basic_func(); 781
770 if (!acm) 782 if (f_serial_opts_attr->show)
771 return -ENOMEM; 783 ret = f_serial_opts_attr->show(opts, page);
772 784 return ret;
773 acm->port_num = port_num;
774 acm->port.func.unbind = acm_old_unbind;
775
776 status = usb_add_function(c, &acm->port.func);
777 if (status)
778 kfree(acm);
779 return status;
780} 785}
781 786
782#else 787static void acm_attr_release(struct config_item *item)
783
784static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
785{ 788{
786 struct f_acm *acm = func_to_acm(f); 789 struct f_serial_opts *opts = to_f_serial_opts(item);
787 790
788 acm_string_defs[0].id = 0; 791 usb_put_function_instance(&opts->func_inst);
789 usb_free_all_descriptors(f);
790 if (acm->notify_req)
791 gs_free_req(acm->notify, acm->notify_req);
792} 792}
793 793
794static void acm_free_func(struct usb_function *f) 794static struct configfs_item_operations acm_item_ops = {
795{ 795 .release = acm_attr_release,
796 struct f_acm *acm = func_to_acm(f); 796 .show_attribute = f_acm_attr_show,
797};
797 798
798 kfree(acm); 799static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
800{
801 return sprintf(page, "%u\n", opts->port_num);
799} 802}
800 803
801static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) 804static struct f_serial_opts_attribute f_acm_port_num =
802{ 805 __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
803 struct f_serial_opts *opts;
804 struct f_acm *acm;
805 806
806 acm = acm_alloc_basic_func();
807 if (!acm)
808 return ERR_PTR(-ENOMEM);
809 807
810 opts = container_of(fi, struct f_serial_opts, func_inst); 808static struct configfs_attribute *acm_attrs[] = {
811 acm->port_num = opts->port_num; 809 &f_acm_port_num.attr,
812 acm->port.func.unbind = acm_unbind; 810 NULL,
813 acm->port.func.free_func = acm_free_func; 811};
814 812
815 return &acm->port.func; 813static struct config_item_type acm_func_type = {
816} 814 .ct_item_ops = &acm_item_ops,
815 .ct_attrs = acm_attrs,
816 .ct_owner = THIS_MODULE,
817};
817 818
818static void acm_free_instance(struct usb_function_instance *fi) 819static void acm_free_instance(struct usb_function_instance *fi)
819{ 820{
820 struct f_serial_opts *opts; 821 struct f_serial_opts *opts;
821 822
822 opts = container_of(fi, struct f_serial_opts, func_inst); 823 opts = container_of(fi, struct f_serial_opts, func_inst);
824 gserial_free_line(opts->port_num);
823 kfree(opts); 825 kfree(opts);
824} 826}
825 827
826static struct usb_function_instance *acm_alloc_instance(void) 828static struct usb_function_instance *acm_alloc_instance(void)
827{ 829{
828 struct f_serial_opts *opts; 830 struct f_serial_opts *opts;
831 int ret;
829 832
830 opts = kzalloc(sizeof(*opts), GFP_KERNEL); 833 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
831 if (!opts) 834 if (!opts)
832 return ERR_PTR(-ENOMEM); 835 return ERR_PTR(-ENOMEM);
833 opts->func_inst.free_func_inst = acm_free_instance; 836 opts->func_inst.free_func_inst = acm_free_instance;
837 ret = gserial_alloc_line(&opts->port_num);
838 if (ret) {
839 kfree(opts);
840 return ERR_PTR(ret);
841 }
842 config_group_init_type_name(&opts->func_inst.group, "",
843 &acm_func_type);
834 return &opts->func_inst; 844 return &opts->func_inst;
835} 845}
836DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); 846DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
837MODULE_LICENSE("GPL"); 847MODULE_LICENSE("GPL");
838#endif