static void gser_unbind(struct usb_configuration *c, struct usb_function *f) { #ifdef CONFIG_MODEM_SUPPORT struct f_gser *gser = func_to_gser(f); #endif if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); #ifdef CONFIG_MODEM_SUPPORT gs_free_req(gser->notify, gser->notify_req); #endif kfree(func_to_gser(f)); }
static void gser_free(struct usb_function *f) { struct f_gser *serial; serial = func_to_gser(f); kfree(serial); gser_next_free_port--; }
static void gser_unbind(struct usb_configuration *c, struct usb_function *f) { #ifdef CONFIG_MODEM_SUPPORT struct f_gser *gser = func_to_gser(f); #endif #ifdef FEATURE_PANTECH_MODEM_REOPEN_DELAY //tarial bug fix [execute work queue fail after changing usb mode] cancel_delayed_work_sync(&gser->connect_work); #endif if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); #ifdef CONFIG_MODEM_SUPPORT gs_free_req(gser->notify, gser->notify_req); #endif kfree(func_to_gser(f)); }
static void gser_unbind(struct usb_configuration *c, struct usb_function *f) { #ifdef CONFIG_MODEM_SUPPORT struct f_gser *gser = func_to_gser(f); #endif usb_free_all_descriptors(f); #ifdef CONFIG_MODEM_SUPPORT gs_free_req(gser->notify, gser->notify_req); #endif }
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; int rc = 0; /* we know alt == 0, so this is an activation or a reset */ #ifdef CONFIG_MODEM_SUPPORT if (gser->notify->driver_data) { DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num); usb_ep_disable(gser->notify); } if (!gser->notify->desc) { if (config_ep_by_speed(cdev->gadget, f, gser->notify)) { gser->notify->desc = NULL; return -EINVAL; } } rc = usb_ep_enable(gser->notify); if (rc) { ERROR(cdev, "can't enable %s, result %d\n", gser->notify->name, rc); return rc; } gser->notify->driver_data = gser; #endif if (gser->port.in->driver_data) { DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num); gport_disconnect(gser); } if (!gser->port.in->desc || !gser->port.out->desc) { DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || config_ep_by_speed(cdev->gadget, f, gser->port.out)) { gser->port.in->desc = NULL; gser->port.out->desc = NULL; return -EINVAL; } } gport_connect(gser); gser->online = 1; #if defined(CONFIG_USB_AT) gserial_ports[gser->port_num].enable = gser->online; #endif return rc; }
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; int rc = 0; /* we know alt == 0, so this is an activation or a reset */ #ifdef CONFIG_MODEM_SUPPORT if (gser->notify->driver_data) { DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num); usb_ep_disable(gser->notify); } if (!gser->notify->desc) { if (config_ep_by_speed(cdev->gadget, f, gser->notify)) { gser->notify->desc = NULL; return -EINVAL; } } rc = usb_ep_enable(gser->notify); if (rc) { ERROR(cdev, "can't enable %s, result %d\n", gser->notify->name, rc); return rc; } gser->notify->driver_data = gser; #endif if (gser->port.in->driver_data) { DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num); gport_disconnect(gser); } if (!gser->port.in->desc || !gser->port.out->desc) { DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || config_ep_by_speed(cdev->gadget, f, gser->port.out)) { gser->port.in->desc = NULL; gser->port.out->desc = NULL; return -EINVAL; } } #ifdef FEATURE_PANTECH_MODEM_REOPEN_DELAY schedule_delayed_work(&gser->connect_work, msecs_to_jiffies(50)); #else gport_connect(gser); #endif gser->online = 1; #ifdef CONFIG_ANDROID_PANTECH_USB_MANAGER usb_interface_enum_cb(ACM_TYPE_FLAG); #endif return rc; }
static void gser_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_gser *gser = func_to_gser(f); if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); if (gser->port.out) gser->port.out->driver_data = NULL; if (gser->port.in) gser->port.in->driver_data = NULL; #ifdef CONFIG_MODEM_SUPPORT if (gser->notify) { gs_free_req(gser->notify, gser->notify_req); gser->notify->driver_data = NULL; } #endif kfree(func_to_gser(f)); }
static void gser_unbind(struct usb_configuration *c, struct usb_function *f) { #ifdef CONFIG_MODEM_SUPPORT struct f_gser *gser = func_to_gser(f); #endif if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); #ifdef CONFIG_MODEM_SUPPORT gs_free_req(gser->notify, gser->notify_req); #endif kfree(func_to_gser(f)); // << FerryWu, 2012/08/07, Fix strings table of USB descriptor gser_string_defs[0].id = 0; #ifdef CONFIG_MODEM_SUPPORT modem_string_defs[0].id = 0; nmea_string_defs[0].id = 0; #endif // >> FerryWu, 2012/08/07, Fix strings table of USB descriptor }
static void gser_disable(struct usb_function *f) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num); gport_disconnect(gser); #ifdef CONFIG_MODEM_SUPPORT usb_ep_fifo_flush(gser->notify); usb_ep_disable(gser->notify); #endif gser->online = 0; }
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; int rc = 0; /* we know alt == 0, so this is an activation or a reset */ #ifdef CONFIG_MODEM_SUPPORT if (gser->notify->driver_data) { DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num); usb_ep_disable(gser->notify); } gser->notify_desc = ep_choose(cdev->gadget, gser->hs.notify, gser->fs.notify); rc = usb_ep_enable(gser->notify, gser->notify_desc); if (rc) { ERROR(cdev, "can't enable %s, result %d\n", gser->notify->name, rc); return rc; } gser->notify->driver_data = gser; #endif if (gser->port.in->driver_data) { DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num); gport_disconnect(gser); } else { DBG(cdev, "activate generic data ttyGS%d\n", gser->port_num); } gser->port.in_desc = ep_choose(cdev->gadget, gser->hs.in, gser->fs.in); gser->port.out_desc = ep_choose(cdev->gadget, gser->hs.out, gser->fs.out); gport_connect(gser); gser->online = 1; gserial_ports[gser->port_num].enable = gser->online; return rc; }
static int gser_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_gser *gser = func_to_gser(f); int status; struct usb_ep *ep; /* allocate instance-specific interface IDs */ status = usb_interface_id(c, f); if (status < 0) goto fail; gser->data_id = status; gser_interface_desc.bInterfaceNumber = status; status = -ENODEV; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc); if (!ep) goto fail; gser->port.in = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc); if (!ep) goto fail; gser->port.out = ep; ep->driver_data = cdev; /* claim */ #ifdef CONFIG_MODEM_SUPPORT ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc); if (!ep) goto fail; gser->notify = ep; ep->driver_data = cdev; /* claim */ /* allocate notification */ gser->notify_req = gs_alloc_req(ep, sizeof(struct usb_cdc_notification) + 2, GFP_KERNEL); if (!gser->notify_req) goto fail; gser->notify_req->complete = gser_notify_complete; gser->notify_req->context = gser; #endif /* copy descriptors, and track endpoint copies */ f->descriptors = usb_copy_descriptors(gser_fs_function); if (!f->descriptors) goto fail; /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ if (gadget_is_dualspeed(c->cdev->gadget)) { gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; #ifdef CONFIG_MODEM_SUPPORT gser_hs_notify_desc.bEndpointAddress = gser_fs_notify_desc.bEndpointAddress; #endif /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(gser_hs_function); if (!f->hs_descriptors) goto fail; } if (gadget_is_superspeed(c->cdev->gadget)) { gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; /* copy descriptors, and track endpoint copies */ f->ss_descriptors = usb_copy_descriptors(gser_ss_function); if (!f->ss_descriptors) goto fail; } DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", gser->port_num, gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", gser->port.in->name, gser->port.out->name); return 0; fail: if (f->descriptors) usb_free_descriptors(f->descriptors); #ifdef CONFIG_MODEM_SUPPORT if (gser->notify_req) gs_free_req(gser->notify, gser->notify_req); /* we might as well release our claims on endpoints */ if (gser->notify) gser->notify->driver_data = NULL; #endif /* we might as well release our claims on endpoints */ if (gser->port.out) gser->port.out->driver_data = NULL; if (gser->port.in) gser->port.in->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); return status; }
static int gser_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; struct usb_request *req = cdev->req; int value = -EOPNOTSUPP; u16 w_index = le16_to_cpu(ctrl->wIndex); u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { /* SET_LINE_CODING ... just read and save what the host sends */ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) | USB_CDC_REQ_SET_LINE_CODING: if (w_length != sizeof(struct usb_cdc_line_coding)) goto invalid; value = w_length; cdev->gadget->ep0->driver_data = gser; req->complete = gser_complete_set_line_coding; break; /* GET_LINE_CODING ... return what host sent, or initial value */ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) | USB_CDC_REQ_GET_LINE_CODING: value = min_t(unsigned, w_length, sizeof(struct usb_cdc_line_coding)); memcpy(req->buf, &gser->port_line_coding, value); break; /* SET_CONTROL_LINE_STATE ... save what the host sent */ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) | USB_CDC_REQ_SET_CONTROL_LINE_STATE: value = 0; gser->port_handshake_bits = w_value; if (gser->port.notify_modem) { unsigned port_num = gserial_ports[gser->port_num].client_port_num; gser->port.notify_modem(&gser->port, port_num, w_value); } break; default: invalid: DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); } /* respond with data transfer or status phase? */ if (value >= 0) { DBG(cdev, "gser ttyGS%d req%02x.%02x v%04x i%04x l%d\n", gser->port_num, ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); req->zero = 0; req->length = value; value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); if (value < 0) ERROR(cdev, "gser response on ttyGS%d, err %d\n", gser->port_num, value); } /* device either stalls (value < 0) or reports success */ return value; }
static int gser_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_gser *gser = func_to_gser(f); int status; struct usb_ep *ep; /* allocate instance-specific interface IDs */ #if defined(CONFIG_ANDROID_PANTECH_USB) // if((pantech_usb_carrier != CARRIER_QUALCOMM) && b_pantech_usb_module){ if(pantech_usb_carrier != CARRIER_QUALCOMM){ gser_fs_function = pantech_gser_fs_function; gser_hs_function = pantech_gser_hs_function; status = usb_interface_id(c, f); if (status < 0) goto fail; gser->data_id = status; //data_id : cdc interface number gser_acm_cdc_interface_desc.bInterfaceNumber = status; #if defined(FEATURE_ANDROID_PANTECH_USB_IAD) gser_interface_assoc_desc.bFirstInterface = status; #endif //acm interface status = usb_interface_id(c, f); if (status < 0) goto fail; gser_acm_data_interface_desc.bInterfaceNumber = status; }else{ gser_fs_function = qualcomm_gser_fs_function; gser_hs_function = qualcomm_gser_hs_function; status = usb_interface_id(c, f); if (status < 0) goto fail; gser->data_id = status; gser_interface_desc.bInterfaceNumber = status; } #else status = usb_interface_id(c, f); if (status < 0) goto fail; gser->data_id = status; gser_interface_desc.bInterfaceNumber = status; #endif status = -ENODEV; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc); if (!ep) goto fail; gser->port.in = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc); if (!ep) goto fail; gser->port.out = ep; ep->driver_data = cdev; /* claim */ #ifdef CONFIG_MODEM_SUPPORT ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc); if (!ep) goto fail; gser->notify = ep; ep->driver_data = cdev; /* claim */ /* allocate notification */ gser->notify_req = gs_alloc_req(ep, sizeof(struct usb_cdc_notification) + 2, GFP_KERNEL); if (!gser->notify_req) goto fail; gser->notify_req->complete = gser_notify_complete; gser->notify_req->context = gser; #endif /* copy descriptors, and track endpoint copies */ f->descriptors = usb_copy_descriptors(gser_fs_function); if (!f->descriptors) goto fail; gser->fs.in = usb_find_endpoint(gser_fs_function, f->descriptors, &gser_fs_in_desc); gser->fs.out = usb_find_endpoint(gser_fs_function, f->descriptors, &gser_fs_out_desc); #ifdef CONFIG_MODEM_SUPPORT gser->fs.notify = usb_find_endpoint(gser_fs_function, f->descriptors, &gser_fs_notify_desc); #endif /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ if (gadget_is_dualspeed(c->cdev->gadget)) { gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; #ifdef CONFIG_MODEM_SUPPORT gser_hs_notify_desc.bEndpointAddress = gser_fs_notify_desc.bEndpointAddress; #endif /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(gser_hs_function); if (!f->hs_descriptors) goto fail; gser->hs.in = usb_find_endpoint(gser_hs_function, f->hs_descriptors, &gser_hs_in_desc); gser->hs.out = usb_find_endpoint(gser_hs_function, f->hs_descriptors, &gser_hs_out_desc); #ifdef CONFIG_MODEM_SUPPORT gser->hs.notify = usb_find_endpoint(gser_hs_function, f->hs_descriptors, &gser_hs_notify_desc); #endif } DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", gser->port_num, gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", gser->port.in->name, gser->port.out->name); return 0; fail: if (f->descriptors) usb_free_descriptors(f->descriptors); #ifdef CONFIG_MODEM_SUPPORT if (gser->notify_req) gs_free_req(gser->notify, gser->notify_req); /* we might as well release our claims on endpoints */ if (gser->notify) gser->notify->driver_data = NULL; #endif /* we might as well release our claims on endpoints */ if (gser->port.out) gser->port.out->driver_data = NULL; if (gser->port.in) gser->port.in->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); return status; }
static int gser_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_gser *gser = func_to_gser(f); int status; struct usb_ep *ep; status = usb_interface_id(c, f); if (status < 0) goto fail; gser->data_id = status; gser_interface_desc.bInterfaceNumber = status; status = -ENODEV; ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc); if (!ep) goto fail; gser->port.in = ep; ep->driver_data = cdev; ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc); if (!ep) goto fail; gser->port.out = ep; ep->driver_data = cdev; #ifdef CONFIG_MODEM_SUPPORT ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc); if (!ep) goto fail; gser->notify = ep; ep->driver_data = cdev; gser->notify_req = gs_alloc_req(ep, sizeof(struct usb_cdc_notification) + 2, GFP_KERNEL); if (!gser->notify_req) goto fail; gser->notify_req->complete = gser_notify_complete; gser->notify_req->context = gser; #endif f->descriptors = usb_copy_descriptors(gser_fs_function); if (!f->descriptors) goto fail; if (gadget_is_dualspeed(c->cdev->gadget)) { gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; #ifdef CONFIG_MODEM_SUPPORT gser_hs_notify_desc.bEndpointAddress = gser_fs_notify_desc.bEndpointAddress; #endif f->hs_descriptors = usb_copy_descriptors(gser_hs_function); if (!f->hs_descriptors) goto fail; } DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", gser->port_num, gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", gser->port.in->name, gser->port.out->name); return 0; fail: if (f->descriptors) usb_free_descriptors(f->descriptors); #ifdef CONFIG_MODEM_SUPPORT if (gser->notify_req) gs_free_req(gser->notify, gser->notify_req); if (gser->notify) gser->notify->driver_data = NULL; #endif if (gser->port.out) gser->port.out->driver_data = NULL; if (gser->port.in) gser->port.in->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); return status; }
static int gser_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_gser *gser = func_to_gser(f); int status; struct usb_ep *ep; /* allocate instance-specific interface IDs */ status = usb_interface_id(c, f); if (status < 0) goto fail; #ifdef CONFIG_LGE_USB_GADGET_DRIVER gser_iad_descriptor.bFirstInterface = status; gser_control_interface_desc.bInterfaceNumber = status; gser_union_desc .bMasterInterface0 = status; status = usb_interface_id(c, f); if (status < 0) goto fail; gser->data_id = status; // [START] seunghun.kim : temp_modify for using LG_USB_MODEM on ES3 by f_serial gser_data_interface_desc.bInterfaceNumber = status; gser_union_desc.bSlaveInterface0 = status; gser_call_mgmt_descriptor.bDataInterface = status; #else gser->data_id = status; gser_interface_desc.bInterfaceNumber = status; // [START] seunghun.kim : temp_modify for using LG_USB_MODEM on ES3 by f_serial #endif // [END] seunghun.kim : temp_modify for using LG_USB_MODEM on ES3 by f_serial status = -ENODEV; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc); if (!ep) goto fail; gser->port.in = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc); if (!ep) goto fail; gser->port.out = ep; ep->driver_data = cdev; /* claim */ #ifdef CONFIG_MODEM_SUPPORT ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc); if (!ep) goto fail; gser->notify = ep; ep->driver_data = cdev; /* claim */ /* allocate notification */ #ifdef CONFIG_LGE_USB_GADGET_DRIVER gser->notify_req = gs_alloc_req(ep, sizeof(struct usb_cdc_notification) + 8, GFP_KERNEL); #else gser->notify_req = gs_alloc_req(ep, sizeof(struct usb_cdc_notification) + 2, GFP_KERNEL); #endif if (!gser->notify_req) goto fail; gser->notify_req->complete = gser_notify_complete; gser->notify_req->context = gser; #endif /* copy descriptors, and track endpoint copies */ f->descriptors = usb_copy_descriptors(gser_fs_function); if (!f->descriptors) goto fail; gser->fs.in = usb_find_endpoint(gser_fs_function, f->descriptors, &gser_fs_in_desc); gser->fs.out = usb_find_endpoint(gser_fs_function, f->descriptors, &gser_fs_out_desc); #ifdef CONFIG_MODEM_SUPPORT gser->fs.notify = usb_find_endpoint(gser_fs_function, f->descriptors, &gser_fs_notify_desc); #endif /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ if (gadget_is_dualspeed(c->cdev->gadget)) { gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; #ifdef CONFIG_MODEM_SUPPORT gser_hs_notify_desc.bEndpointAddress = gser_fs_notify_desc.bEndpointAddress; #endif /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(gser_hs_function); gser->hs.in = usb_find_endpoint(gser_hs_function, f->hs_descriptors, &gser_hs_in_desc); gser->hs.out = usb_find_endpoint(gser_hs_function, f->hs_descriptors, &gser_hs_out_desc); #ifdef CONFIG_MODEM_SUPPORT gser->hs.notify = usb_find_endpoint(gser_hs_function, f->hs_descriptors, &gser_hs_notify_desc); #endif } DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", gser->port_num, gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", gser->port.in->name, gser->port.out->name); return 0; fail: #ifdef CONFIG_MODEM_SUPPORT if (gser->notify_req) gs_free_req(gser->notify, gser->notify_req); /* we might as well release our claims on endpoints */ if (gser->notify) gser->notify->driver_data = NULL; #endif /* we might as well release our claims on endpoints */ if (gser->port.out) gser->port.out->driver_data = NULL; if (gser->port.in) gser->port.in->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); return status; }