diff options
author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2013-05-28 03:15:47 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-06-10 10:57:46 -0400 |
commit | b29002a157940752dfed2c488b2011f63f007d71 (patch) | |
tree | ca07b354cfb93af8a19613669ce32629a94869f9 /drivers/usb/gadget/f_eem.c | |
parent | 9c62ce83e4258bacc459faf57bf2ed83cce6be08 (diff) |
usb: gadget: f_eem: convert to new function interface with backward compatibility
Converting eem to the new function interface requires converting
the USB eem's function code and its users.
This patch converts the f_eem.c to the new function interface.
The file is now compiled into a separate usb_f_eem.ko module.
The old function interface is provided by means of a preprocessor
conditional directives. After all users are converted, the old interface
can be removed.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/f_eem.c')
-rw-r--r-- | drivers/usb/gadget/f_eem.c | 174 |
1 files changed, 138 insertions, 36 deletions
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index f4e0bbef602a..471acc824115 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c | |||
@@ -12,12 +12,14 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
17 | #include <linux/crc32.h> | 18 | #include <linux/crc32.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | 20 | ||
20 | #include "u_ether.h" | 21 | #include "u_ether.h" |
22 | #include "u_eem.h" | ||
21 | 23 | ||
22 | #define EEM_HLEN 2 | 24 | #define EEM_HLEN 2 |
23 | 25 | ||
@@ -40,7 +42,7 @@ static inline struct f_eem *func_to_eem(struct usb_function *f) | |||
40 | 42 | ||
41 | /* interface descriptor: */ | 43 | /* interface descriptor: */ |
42 | 44 | ||
43 | static struct usb_interface_descriptor eem_intf __initdata = { | 45 | static struct usb_interface_descriptor eem_intf = { |
44 | .bLength = sizeof eem_intf, | 46 | .bLength = sizeof eem_intf, |
45 | .bDescriptorType = USB_DT_INTERFACE, | 47 | .bDescriptorType = USB_DT_INTERFACE, |
46 | 48 | ||
@@ -54,7 +56,7 @@ static struct usb_interface_descriptor eem_intf __initdata = { | |||
54 | 56 | ||
55 | /* full speed support: */ | 57 | /* full speed support: */ |
56 | 58 | ||
57 | static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = { | 59 | static struct usb_endpoint_descriptor eem_fs_in_desc = { |
58 | .bLength = USB_DT_ENDPOINT_SIZE, | 60 | .bLength = USB_DT_ENDPOINT_SIZE, |
59 | .bDescriptorType = USB_DT_ENDPOINT, | 61 | .bDescriptorType = USB_DT_ENDPOINT, |
60 | 62 | ||
@@ -62,7 +64,7 @@ static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = { | |||
62 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 64 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
63 | }; | 65 | }; |
64 | 66 | ||
65 | static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = { | 67 | static struct usb_endpoint_descriptor eem_fs_out_desc = { |
66 | .bLength = USB_DT_ENDPOINT_SIZE, | 68 | .bLength = USB_DT_ENDPOINT_SIZE, |
67 | .bDescriptorType = USB_DT_ENDPOINT, | 69 | .bDescriptorType = USB_DT_ENDPOINT, |
68 | 70 | ||
@@ -70,7 +72,7 @@ static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = { | |||
70 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 72 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
71 | }; | 73 | }; |
72 | 74 | ||
73 | static struct usb_descriptor_header *eem_fs_function[] __initdata = { | 75 | static struct usb_descriptor_header *eem_fs_function[] = { |
74 | /* CDC EEM control descriptors */ | 76 | /* CDC EEM control descriptors */ |
75 | (struct usb_descriptor_header *) &eem_intf, | 77 | (struct usb_descriptor_header *) &eem_intf, |
76 | (struct usb_descriptor_header *) &eem_fs_in_desc, | 78 | (struct usb_descriptor_header *) &eem_fs_in_desc, |
@@ -80,7 +82,7 @@ static struct usb_descriptor_header *eem_fs_function[] __initdata = { | |||
80 | 82 | ||
81 | /* high speed support: */ | 83 | /* high speed support: */ |
82 | 84 | ||
83 | static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = { | 85 | static struct usb_endpoint_descriptor eem_hs_in_desc = { |
84 | .bLength = USB_DT_ENDPOINT_SIZE, | 86 | .bLength = USB_DT_ENDPOINT_SIZE, |
85 | .bDescriptorType = USB_DT_ENDPOINT, | 87 | .bDescriptorType = USB_DT_ENDPOINT, |
86 | 88 | ||
@@ -89,7 +91,7 @@ static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = { | |||
89 | .wMaxPacketSize = cpu_to_le16(512), | 91 | .wMaxPacketSize = cpu_to_le16(512), |
90 | }; | 92 | }; |
91 | 93 | ||
92 | static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = { | 94 | static struct usb_endpoint_descriptor eem_hs_out_desc = { |
93 | .bLength = USB_DT_ENDPOINT_SIZE, | 95 | .bLength = USB_DT_ENDPOINT_SIZE, |
94 | .bDescriptorType = USB_DT_ENDPOINT, | 96 | .bDescriptorType = USB_DT_ENDPOINT, |
95 | 97 | ||
@@ -98,7 +100,7 @@ static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = { | |||
98 | .wMaxPacketSize = cpu_to_le16(512), | 100 | .wMaxPacketSize = cpu_to_le16(512), |
99 | }; | 101 | }; |
100 | 102 | ||
101 | static struct usb_descriptor_header *eem_hs_function[] __initdata = { | 103 | static struct usb_descriptor_header *eem_hs_function[] = { |
102 | /* CDC EEM control descriptors */ | 104 | /* CDC EEM control descriptors */ |
103 | (struct usb_descriptor_header *) &eem_intf, | 105 | (struct usb_descriptor_header *) &eem_intf, |
104 | (struct usb_descriptor_header *) &eem_hs_in_desc, | 106 | (struct usb_descriptor_header *) &eem_hs_in_desc, |
@@ -108,7 +110,7 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = { | |||
108 | 110 | ||
109 | /* super speed support: */ | 111 | /* super speed support: */ |
110 | 112 | ||
111 | static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = { | 113 | static struct usb_endpoint_descriptor eem_ss_in_desc = { |
112 | .bLength = USB_DT_ENDPOINT_SIZE, | 114 | .bLength = USB_DT_ENDPOINT_SIZE, |
113 | .bDescriptorType = USB_DT_ENDPOINT, | 115 | .bDescriptorType = USB_DT_ENDPOINT, |
114 | 116 | ||
@@ -117,7 +119,7 @@ static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = { | |||
117 | .wMaxPacketSize = cpu_to_le16(1024), | 119 | .wMaxPacketSize = cpu_to_le16(1024), |
118 | }; | 120 | }; |
119 | 121 | ||
120 | static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = { | 122 | static struct usb_endpoint_descriptor eem_ss_out_desc = { |
121 | .bLength = USB_DT_ENDPOINT_SIZE, | 123 | .bLength = USB_DT_ENDPOINT_SIZE, |
122 | .bDescriptorType = USB_DT_ENDPOINT, | 124 | .bDescriptorType = USB_DT_ENDPOINT, |
123 | 125 | ||
@@ -126,7 +128,7 @@ static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = { | |||
126 | .wMaxPacketSize = cpu_to_le16(1024), | 128 | .wMaxPacketSize = cpu_to_le16(1024), |
127 | }; | 129 | }; |
128 | 130 | ||
129 | static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = { | 131 | static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc = { |
130 | .bLength = sizeof eem_ss_bulk_comp_desc, | 132 | .bLength = sizeof eem_ss_bulk_comp_desc, |
131 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 133 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
132 | 134 | ||
@@ -135,7 +137,7 @@ static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = { | |||
135 | /* .bmAttributes = 0, */ | 137 | /* .bmAttributes = 0, */ |
136 | }; | 138 | }; |
137 | 139 | ||
138 | static struct usb_descriptor_header *eem_ss_function[] __initdata = { | 140 | static struct usb_descriptor_header *eem_ss_function[] = { |
139 | /* CDC EEM control descriptors */ | 141 | /* CDC EEM control descriptors */ |
140 | (struct usb_descriptor_header *) &eem_intf, | 142 | (struct usb_descriptor_header *) &eem_intf, |
141 | (struct usb_descriptor_header *) &eem_ss_in_desc, | 143 | (struct usb_descriptor_header *) &eem_ss_in_desc, |
@@ -242,14 +244,44 @@ static void eem_disable(struct usb_function *f) | |||
242 | 244 | ||
243 | /* EEM function driver setup/binding */ | 245 | /* EEM function driver setup/binding */ |
244 | 246 | ||
245 | static int __init | 247 | static int eem_bind(struct usb_configuration *c, struct usb_function *f) |
246 | eem_bind(struct usb_configuration *c, struct usb_function *f) | ||
247 | { | 248 | { |
248 | struct usb_composite_dev *cdev = c->cdev; | 249 | struct usb_composite_dev *cdev = c->cdev; |
249 | struct f_eem *eem = func_to_eem(f); | 250 | struct f_eem *eem = func_to_eem(f); |
250 | int status; | 251 | int status; |
251 | struct usb_ep *ep; | 252 | struct usb_ep *ep; |
252 | 253 | ||
254 | #ifndef USB_FEEM_INCLUDED | ||
255 | struct f_eem_opts *eem_opts; | ||
256 | |||
257 | eem_opts = container_of(f->fi, struct f_eem_opts, func_inst); | ||
258 | /* | ||
259 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
260 | * configurations are bound in sequence with list_for_each_entry, | ||
261 | * in each configuration its functions are bound in sequence | ||
262 | * with list_for_each_entry, so we assume no race condition | ||
263 | * with regard to eem_opts->bound access | ||
264 | */ | ||
265 | if (!eem_opts->bound) { | ||
266 | gether_set_gadget(eem_opts->net, cdev->gadget); | ||
267 | status = gether_register_netdev(eem_opts->net); | ||
268 | if (status) | ||
269 | return status; | ||
270 | eem_opts->bound = true; | ||
271 | } | ||
272 | #endif | ||
273 | |||
274 | /* maybe allocate device-global string IDs */ | ||
275 | if (eem_string_defs[0].id == 0) { | ||
276 | |||
277 | /* control interface label */ | ||
278 | status = usb_string_id(c->cdev); | ||
279 | if (status < 0) | ||
280 | return status; | ||
281 | eem_string_defs[0].id = status; | ||
282 | eem_intf.iInterface = status; | ||
283 | } | ||
284 | |||
253 | /* allocate instance-specific interface IDs */ | 285 | /* allocate instance-specific interface IDs */ |
254 | status = usb_interface_id(c, f); | 286 | status = usb_interface_id(c, f); |
255 | if (status < 0) | 287 | if (status < 0) |
@@ -307,17 +339,6 @@ fail: | |||
307 | return status; | 339 | return status; |
308 | } | 340 | } |
309 | 341 | ||
310 | static void | ||
311 | eem_unbind(struct usb_configuration *c, struct usb_function *f) | ||
312 | { | ||
313 | struct f_eem *eem = func_to_eem(f); | ||
314 | |||
315 | DBG(c->cdev, "eem unbind\n"); | ||
316 | |||
317 | usb_free_all_descriptors(f); | ||
318 | kfree(eem); | ||
319 | } | ||
320 | |||
321 | static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) | 342 | static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) |
322 | { | 343 | { |
323 | struct sk_buff *skb = (struct sk_buff *)req->context; | 344 | struct sk_buff *skb = (struct sk_buff *)req->context; |
@@ -518,6 +539,18 @@ error: | |||
518 | return status; | 539 | return status; |
519 | } | 540 | } |
520 | 541 | ||
542 | #ifdef USB_FEEM_INCLUDED | ||
543 | |||
544 | static void eem_old_unbind(struct usb_configuration *c, struct usb_function *f) | ||
545 | { | ||
546 | struct f_eem *eem = func_to_eem(f); | ||
547 | |||
548 | DBG(c->cdev, "eem unbind\n"); | ||
549 | |||
550 | usb_free_all_descriptors(f); | ||
551 | kfree(eem); | ||
552 | } | ||
553 | |||
521 | /** | 554 | /** |
522 | * eem_bind_config - add CDC Ethernet (EEM) network link to a configuration | 555 | * eem_bind_config - add CDC Ethernet (EEM) network link to a configuration |
523 | * @c: the configuration to support the network link | 556 | * @c: the configuration to support the network link |
@@ -533,17 +566,6 @@ int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev) | |||
533 | struct f_eem *eem; | 566 | struct f_eem *eem; |
534 | int status; | 567 | int status; |
535 | 568 | ||
536 | /* maybe allocate device-global string IDs */ | ||
537 | if (eem_string_defs[0].id == 0) { | ||
538 | |||
539 | /* control interface label */ | ||
540 | status = usb_string_id(c->cdev); | ||
541 | if (status < 0) | ||
542 | return status; | ||
543 | eem_string_defs[0].id = status; | ||
544 | eem_intf.iInterface = status; | ||
545 | } | ||
546 | |||
547 | /* allocate and initialize one new instance */ | 569 | /* allocate and initialize one new instance */ |
548 | eem = kzalloc(sizeof *eem, GFP_KERNEL); | 570 | eem = kzalloc(sizeof *eem, GFP_KERNEL); |
549 | if (!eem) | 571 | if (!eem) |
@@ -556,7 +578,7 @@ int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev) | |||
556 | eem->port.func.strings = eem_strings; | 578 | eem->port.func.strings = eem_strings; |
557 | /* descriptors are per-instance copies */ | 579 | /* descriptors are per-instance copies */ |
558 | eem->port.func.bind = eem_bind; | 580 | eem->port.func.bind = eem_bind; |
559 | eem->port.func.unbind = eem_unbind; | 581 | eem->port.func.unbind = eem_old_unbind; |
560 | eem->port.func.set_alt = eem_set_alt; | 582 | eem->port.func.set_alt = eem_set_alt; |
561 | eem->port.func.setup = eem_setup; | 583 | eem->port.func.setup = eem_setup; |
562 | eem->port.func.disable = eem_disable; | 584 | eem->port.func.disable = eem_disable; |
@@ -570,3 +592,83 @@ int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev) | |||
570 | return status; | 592 | return status; |
571 | } | 593 | } |
572 | 594 | ||
595 | #else | ||
596 | |||
597 | static void eem_free_inst(struct usb_function_instance *f) | ||
598 | { | ||
599 | struct f_eem_opts *opts; | ||
600 | |||
601 | opts = container_of(f, struct f_eem_opts, func_inst); | ||
602 | if (opts->bound) | ||
603 | gether_cleanup(netdev_priv(opts->net)); | ||
604 | else | ||
605 | free_netdev(opts->net); | ||
606 | kfree(opts); | ||
607 | } | ||
608 | |||
609 | static struct usb_function_instance *eem_alloc_inst(void) | ||
610 | { | ||
611 | struct f_eem_opts *opts; | ||
612 | |||
613 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
614 | if (!opts) | ||
615 | return ERR_PTR(-ENOMEM); | ||
616 | opts->func_inst.free_func_inst = eem_free_inst; | ||
617 | opts->net = gether_setup_default(); | ||
618 | if (IS_ERR(opts->net)) | ||
619 | return ERR_CAST(opts->net); | ||
620 | |||
621 | return &opts->func_inst; | ||
622 | } | ||
623 | |||
624 | static void eem_free(struct usb_function *f) | ||
625 | { | ||
626 | struct f_eem *eem; | ||
627 | |||
628 | eem = func_to_eem(f); | ||
629 | kfree(eem); | ||
630 | } | ||
631 | |||
632 | static void eem_unbind(struct usb_configuration *c, struct usb_function *f) | ||
633 | { | ||
634 | DBG(c->cdev, "eem unbind\n"); | ||
635 | |||
636 | usb_free_all_descriptors(f); | ||
637 | } | ||
638 | |||
639 | struct usb_function *eem_alloc(struct usb_function_instance *fi) | ||
640 | { | ||
641 | struct f_eem *eem; | ||
642 | struct f_eem_opts *opts; | ||
643 | |||
644 | /* allocate and initialize one new instance */ | ||
645 | eem = kzalloc(sizeof(*eem), GFP_KERNEL); | ||
646 | if (!eem) | ||
647 | return ERR_PTR(-ENOMEM); | ||
648 | |||
649 | opts = container_of(fi, struct f_eem_opts, func_inst); | ||
650 | |||
651 | eem->port.ioport = netdev_priv(opts->net); | ||
652 | eem->port.cdc_filter = DEFAULT_FILTER; | ||
653 | |||
654 | eem->port.func.name = "cdc_eem"; | ||
655 | eem->port.func.strings = eem_strings; | ||
656 | /* descriptors are per-instance copies */ | ||
657 | eem->port.func.bind = eem_bind; | ||
658 | eem->port.func.unbind = eem_unbind; | ||
659 | eem->port.func.set_alt = eem_set_alt; | ||
660 | eem->port.func.setup = eem_setup; | ||
661 | eem->port.func.disable = eem_disable; | ||
662 | eem->port.func.free_func = eem_free; | ||
663 | eem->port.wrap = eem_wrap; | ||
664 | eem->port.unwrap = eem_unwrap; | ||
665 | eem->port.header_len = EEM_HLEN; | ||
666 | |||
667 | return &eem->port.func; | ||
668 | } | ||
669 | |||
670 | DECLARE_USB_FUNCTION_INIT(eem, eem_alloc_inst, eem_alloc); | ||
671 | MODULE_LICENSE("GPL"); | ||
672 | MODULE_AUTHOR("David Brownell"); | ||
673 | |||
674 | #endif | ||