diff options
Diffstat (limited to 'drivers/usb/gadget/f_rndis.c')
-rw-r--r-- | drivers/usb/gadget/f_rndis.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index c11761ce5113..04a47b47cf35 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -675,6 +675,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) int status; struct usb_ep *ep; +#ifndef USB_FRNDIS_INCLUDED struct f_rndis_opts *rndis_opts; if (!can_support_rndis(c)) @@ -696,7 +697,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) return status; rndis_opts->bound = true; } - +#endif us = usb_gstrings_attach(cdev, rndis_strings, ARRAY_SIZE(rndis_string_defs)); if (IS_ERR(us)) @@ -781,6 +782,13 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) rndis->port.open = rndis_open; rndis->port.close = rndis_close; +#ifdef USB_FRNDIS_INCLUDED + status = rndis_register(rndis_response_available, rndis); + if (status < 0) + goto fail; + rndis->config = status; +#endif + rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); rndis_set_host_mac(rndis->config, rndis->ethaddr); @@ -822,6 +830,66 @@ fail: return status; } +#ifdef USB_FRNDIS_INCLUDED + +static void +rndis_old_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct f_rndis *rndis = func_to_rndis(f); + + rndis_deregister(rndis->config); + + usb_free_all_descriptors(f); + + kfree(rndis->notify_req->buf); + usb_ep_free_request(rndis->notify, rndis->notify_req); + + kfree(rndis); +} + +int +rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + u32 vendorID, const char *manufacturer, struct eth_dev *dev) +{ + struct f_rndis *rndis; + int status; + + /* allocate and initialize one new instance */ + status = -ENOMEM; + rndis = kzalloc(sizeof *rndis, GFP_KERNEL); + if (!rndis) + goto fail; + + memcpy(rndis->ethaddr, ethaddr, ETH_ALEN); + rndis->vendorID = vendorID; + rndis->manufacturer = manufacturer; + + rndis->port.ioport = dev; + /* RNDIS activates when the host changes this filter */ + rndis->port.cdc_filter = 0; + + /* RNDIS has special (and complex) framing */ + rndis->port.header_len = sizeof(struct rndis_packet_msg_type); + rndis->port.wrap = rndis_add_header; + rndis->port.unwrap = rndis_rm_hdr; + + rndis->port.func.name = "rndis"; + /* descriptors are per-instance copies */ + rndis->port.func.bind = rndis_bind; + rndis->port.func.unbind = rndis_old_unbind; + rndis->port.func.set_alt = rndis_set_alt; + rndis->port.func.setup = rndis_setup; + rndis->port.func.disable = rndis_disable; + + status = usb_add_function(c, &rndis->port.func); + if (status) + kfree(rndis); +fail: + return status; +} + +#else + void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net) { struct f_rndis_opts *opts; @@ -1002,3 +1070,5 @@ module_exit(rndis_mod_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Brownell"); + +#endif |