int rawbulk_function_bind(struct usb_configuration *c, struct usb_function *f) { int rc, ifnum; struct rawbulk_function *fn = function_to_rbf(f); struct usb_gadget *gadget = c->cdev->gadget; struct usb_ep *ep_out, *ep_in; printk("%s\n", __func__); rc = usb_interface_id(c, f); if (rc < 0) return rc; ifnum = rc; fn->interface.bInterfaceNumber = cpu_to_le16(ifnum); ep_out = usb_ep_autoconfig(gadget, (struct usb_endpoint_descriptor *) fn->fs_descs[BULKOUT_DESC]); if (!ep_out) { printk(KERN_ERR "%s %d config ep_out error \n", __FUNCTION__,__LINE__); return -ENOMEM; } ep_in = usb_ep_autoconfig(gadget, (struct usb_endpoint_descriptor *) fn->fs_descs[BULKIN_DESC]); if (!ep_in) { usb_ep_disable(ep_out); printk(KERN_ERR "%s %d config ep_in error \n", __FUNCTION__,__LINE__); return -ENOMEM; } ep_out->driver_data = fn; ep_in->driver_data = fn; fn->bulk_out = ep_out; fn->bulk_in = ep_in; #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 100)) f->fs_descriptors = usb_copy_descriptors(fn->fs_descs); if (unlikely(!f->fs_descriptors)) return -ENOMEM; #else f->descriptors = usb_copy_descriptors(fn->fs_descs); if (unlikely(!f->descriptors)) return -ENOMEM; #endif if (gadget_is_dualspeed(gadget)) { fn->hs_bulkin_endpoint.bEndpointAddress = fn->fs_bulkin_endpoint.bEndpointAddress; fn->hs_bulkout_endpoint.bEndpointAddress = fn->fs_bulkout_endpoint.bEndpointAddress; } fn->cdev = c->cdev; fn->activated = 0; return rawbulk_bind_function(fn->transfer_id, f, ep_out, ep_in, rawbulk_auto_reconnect); }
int f_cloner_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct cloner *cloner = func_to_cloner(f); debug_cond(BURNNER_DEBUG,"f_cloner_bind\n"); intf_desc.bInterfaceNumber = usb_interface_id(c, f); if(intf_desc.bInterfaceNumber < 0 ) return intf_desc.bInterfaceNumber; cloner->ep0 = cdev->gadget->ep0; cloner->ep0req = cdev->req; cloner->gadget = cdev->gadget; cloner->ack = 0; cloner->cdev = cdev; cloner->cmd = (union cmd *)cloner->ep0req->buf; if (gadget_is_dualspeed(cdev->gadget)) { hs_bulk_in_desc.bEndpointAddress = fs_bulk_in_desc.bEndpointAddress; hs_bulk_out_desc.bEndpointAddress = fs_bulk_out_desc.bEndpointAddress; } cdev->req->context = cloner; cloner->ep_in = usb_ep_autoconfig(cdev->gadget, &fs_bulk_in_desc); cloner->ep_out = usb_ep_autoconfig(cdev->gadget, &fs_bulk_out_desc); cloner->write_req = usb_ep_alloc_request(cloner->ep_out,0); cloner->args_req = usb_ep_alloc_request(cloner->ep_out,0); cloner->read_req = usb_ep_alloc_request(cloner->ep_in,0); cloner->buf_size = 1024*1024; cloner->buf = malloc(1024*1024); cloner->write_req->complete = handle_write; cloner->write_req->buf = cloner->buf; cloner->write_req->length = 1024*1024; cloner->write_req->context = cloner; cloner->args_req->complete = handle_write; cloner->args_req->buf = cloner->args; cloner->args_req->length = ARGS_LEN; cloner->args_req->context = cloner; cloner->read_req->complete = handle_read_complete; cloner->read_req->buf = cloner->buf; cloner->read_req->length = 1024*1024; cloner->read_req->context = cloner; return 0; }
static int dtf_allocate_interface_ids( struct usb_configuration *c, struct usb_function *f ) { int id; struct dtf_dev *dev = func_to_dtf(f); _dbgmsg( "IN\n" ); /* Allocate Interface ID: PipeGroup1 communication interface */ _dbgmsg_gadget( "usb_interface_id\n" ); id = usb_interface_id(c, f); _dbgmsg( "usb_interface_id() = %d\n", id ); if( id < 0 ) return id; dev->pg.mCtrl_id = id; id = 0; /* fixed interface number */ vPg1_intf_comm_desc.bInterfaceNumber = id; vPg1_union_desc.bMasterInterface0 = id; /* Allocate Interface ID: PipeGroup1 bulk interface */ _dbgmsg_gadget( "usb_interface_id\n" ); id = usb_interface_id(c, f); _dbgmsg( "usb_interface_id() = %d(%d)\n", id, vPg1_intf_comm_desc.bInterfaceNumber ); if( id < 0 ) return id; dev->pg.mData_id = id; id = 1; /* fixed interface number */ vPg1_intf_bulk_desc.bInterfaceNumber = id; vPg1_union_desc.bSlaveInterface0 = id; vPg1_call_mng.bDataInterface = id; _dbgmsg( "usb_interface_id() = %d(%d)\n", id, vPg1_intf_bulk_desc.bInterfaceNumber ); _dbgmsg( "OUT\n" ); return 0; }
/* config the rockusb device*/ static int rockusb_bind(struct usb_configuration *c, struct usb_function *f) { int id; struct usb_gadget *gadget = c->cdev->gadget; struct f_rockusb *f_rkusb = func_to_rockusb(f); const char *s; id = usb_interface_id(c, f); if (id < 0) return id; interface_desc.bInterfaceNumber = id; id = usb_string_id(c->cdev); if (id < 0) return id; rkusb_string_defs[0].id = id; interface_desc.iInterface = id; f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in); if (!f_rkusb->in_ep) return -ENODEV; f_rkusb->in_ep->driver_data = c->cdev; f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out); if (!f_rkusb->out_ep) return -ENODEV; f_rkusb->out_ep->driver_data = c->cdev; f->descriptors = rkusb_fs_function; if (gadget_is_dualspeed(gadget)) { hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; f->hs_descriptors = rkusb_hs_function; } s = env_get("serial#"); if (s) g_dnl_set_serialnumber((char *)s); return 0; }
static int acc_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct acc_dev *dev = func_to_dev(f); int id; int ret; DBG(cdev, "acc_function_bind dev: %p\n", dev); dev->start_requested = 0; /* allocate interface ID(s) */ id = usb_interface_id(c, f); if (id < 0) return id; acc_interface_desc.bInterfaceNumber = id; /* allocate endpoints */ ret = create_bulk_endpoints(dev, &acc_fullspeed_in_desc, &acc_fullspeed_out_desc); if (ret) return ret; /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { acc_highspeed_in_desc.bEndpointAddress = acc_fullspeed_in_desc.bEndpointAddress; acc_highspeed_out_desc.bEndpointAddress = acc_fullspeed_out_desc.bEndpointAddress; } DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", f->name, dev->ep_in->name, dev->ep_out->name); return 0; }
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 */ #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 __init uvc_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct uvc_device *uvc = to_uvc(f); struct usb_ep *ep; int ret = -EINVAL; INFO(cdev, "uvc_function_bind\n"); /* sanity check the streaming endpoint module parameters */ if (streaming_interval < 1) streaming_interval = 1; if (streaming_interval > 16) streaming_interval = 16; if (streaming_mult > 2) streaming_mult = 2; if (streaming_maxburst > 15) streaming_maxburst = 15; /* * fill in the FS video streaming specific descriptors from the * module parameters */ uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ? 1023 : streaming_maxpacket; uvc_fs_streaming_ep.bInterval = streaming_interval; /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep); if (!ep) { INFO(cdev, "Unable to allocate control EP\n"); goto error; } uvc->control_ep = ep; ep->driver_data = uvc; ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); if (!ep) { INFO(cdev, "Unable to allocate streaming EP\n"); goto error; } uvc->video.ep = ep; ep->driver_data = uvc; /* Allocate interface IDs. */ if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_iad.bFirstInterface = ret; uvc_control_intf.bInterfaceNumber = ret; uvc->control_intf = ret; if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_streaming_intf_alt0.bInterfaceNumber = ret; uvc_streaming_intf_alt1.bInterfaceNumber = ret; uvc->streaming_intf = ret; /* sanity check the streaming endpoint module parameters */ if (streaming_maxpacket > 1024) streaming_maxpacket = 1024; /* Copy descriptors for FS. */ f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); /* support high speed hardware */ if (gadget_is_dualspeed(cdev->gadget)) { /* * Fill in the HS descriptors from the module parameters for the * Video Streaming endpoint. * NOTE: We assume that the user knows what they are doing and * won't give parameters that their UDC doesn't support. */ uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; uvc_hs_streaming_ep.bInterval = streaming_interval; uvc_hs_streaming_ep.bEndpointAddress = uvc_fs_streaming_ep.bEndpointAddress; /* Copy descriptors. */ f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); } /* support super speed hardware */ if (gadget_is_superspeed(c->cdev->gadget)) { /* * Fill in the SS descriptors from the module parameters for the * Video Streaming endpoint. * NOTE: We assume that the user knows what they are doing and * won't give parameters that their UDC doesn't support. */ uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; uvc_ss_streaming_ep.bInterval = streaming_interval; uvc_ss_streaming_comp.bmAttributes = streaming_mult; uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; uvc_ss_streaming_comp.wBytesPerInterval = streaming_maxpacket * (streaming_mult + 1) * (streaming_maxburst + 1); uvc_ss_streaming_ep.bEndpointAddress = uvc_fs_streaming_ep.bEndpointAddress; /* Copy descriptors. */ f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); } /* Preallocate control endpoint request. */ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); if (uvc->control_req == NULL || uvc->control_buf == NULL) { ret = -ENOMEM; goto error; } uvc->control_req->buf = uvc->control_buf; uvc->control_req->complete = uvc_function_ep0_complete; uvc->control_req->context = uvc; /* Avoid letting this gadget enumerate until the userspace server is * active. */ if ((ret = usb_function_deactivate(f)) < 0) goto error; /* Initialise video. */ ret = uvc_video_init(&uvc->video); if (ret < 0) goto error; /* Register a V4L2 device. */ ret = uvc_register_video(uvc); if (ret < 0) { printk(KERN_INFO "Unable to register video device\n"); goto error; } return 0; error: uvc_function_unbind(c, f); return ret; }
static int __init uvc_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct uvc_device *uvc = to_uvc(f); unsigned int max_packet_mult; unsigned int max_packet_size; struct usb_ep *ep; int ret = -EINVAL; INFO(cdev, "uvc_function_bind\n"); /* Sanity check the streaming endpoint module parameters. */ streaming_interval = clamp(streaming_interval, 1U, 16U); streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U); streaming_maxburst = min(streaming_maxburst, 15U); /* Fill in the FS/HS/SS Video Streaming specific descriptors from the * module parameters. * * NOTE: We assume that the user knows what they are doing and won't * give parameters that their UDC doesn't support. */ if (streaming_maxpacket <= 1024) { max_packet_mult = 1; max_packet_size = streaming_maxpacket; } else if (streaming_maxpacket <= 2048) { max_packet_mult = 2; max_packet_size = streaming_maxpacket / 2; } else { max_packet_mult = 3; max_packet_size = streaming_maxpacket / 3; } uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U); uvc_fs_streaming_ep.bInterval = streaming_interval; uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size; uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11); uvc_hs_streaming_ep.bInterval = streaming_interval; uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size; uvc_ss_streaming_ep.bInterval = streaming_interval; uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; uvc_ss_streaming_comp.wBytesPerInterval = max_packet_size * max_packet_mult * streaming_maxburst; /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { INFO(cdev, "Unable to allocate control EP\n"); goto error; } uvc->control_ep = ep; ep->driver_data = uvc; if (gadget_is_superspeed(c->cdev->gadget)) ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, &uvc_ss_streaming_comp); else if (gadget_is_dualspeed(cdev->gadget)) ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); else ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); if (!ep) { INFO(cdev, "Unable to allocate streaming EP\n"); goto error; } uvc->video.ep = ep; ep->driver_data = uvc; uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; /* Allocate interface IDs. */ if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_iad.bFirstInterface = ret; uvc_control_intf.bInterfaceNumber = ret; uvc->control_intf = ret; if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_streaming_intf_alt0.bInterfaceNumber = ret; uvc_streaming_intf_alt1.bInterfaceNumber = ret; uvc->streaming_intf = ret; /* Copy descriptors */ f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); if (gadget_is_dualspeed(cdev->gadget)) f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); if (gadget_is_superspeed(c->cdev->gadget)) f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); /* Preallocate control endpoint request. */ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); if (uvc->control_req == NULL || uvc->control_buf == NULL) { ret = -ENOMEM; goto error; } uvc->control_req->buf = uvc->control_buf; uvc->control_req->complete = uvc_function_ep0_complete; uvc->control_req->context = uvc; /* Avoid letting this gadget enumerate until the userspace server is * active. */ if ((ret = usb_function_deactivate(f)) < 0) goto error; if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { printk(KERN_INFO "v4l2_device_register failed\n"); goto error; } /* Initialise video. */ ret = uvc_video_init(&uvc->video); if (ret < 0) goto error; /* Register a V4L2 device. */ ret = uvc_register_video(uvc); if (ret < 0) { printk(KERN_INFO "Unable to register video device\n"); goto error; } return 0; error: v4l2_device_unregister(&uvc->v4l2_dev); if (uvc->vdev) video_device_release(uvc->vdev); if (uvc->control_ep) uvc->control_ep->driver_data = NULL; if (uvc->video.ep) uvc->video.ep->driver_data = NULL; if (uvc->control_req) { usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); kfree(uvc->control_buf); } usb_free_all_descriptors(f); return ret; }
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; }
static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_gadget *gadget = c->cdev->gadget; struct f_thor *f_thor = func_to_thor(f); struct thor_dev *dev; struct usb_ep *ep; int status; thor_func = f_thor; dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev)); if (!dev) return -ENOMEM; memset(dev, 0, sizeof(*dev)); dev->gadget = gadget; f_thor->dev = dev; debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n", __func__, c, f); debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev); /* EP0 */ /* preallocate control response and buffer */ dev->req = usb_ep_alloc_request(gadget->ep0, 0); if (!dev->req) { status = -ENOMEM; goto fail; } dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, THOR_PACKET_SIZE); if (!dev->req->buf) { status = -ENOMEM; goto fail; } dev->req->complete = thor_setup_complete; /* DYNAMIC interface numbers assignments */ status = usb_interface_id(c, f); if (status < 0) goto fail; thor_downloader_intf_int.bInterfaceNumber = status; thor_downloader_cdc_union.bMasterInterface0 = status; status = usb_interface_id(c, f); if (status < 0) goto fail; thor_downloader_intf_data.bInterfaceNumber = status; thor_downloader_cdc_union.bSlaveInterface0 = status; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(gadget, &fs_in_desc); if (!ep) { status = -ENODEV; goto fail; } if (gadget_is_dualspeed(gadget)) { hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress; } dev->in_ep = ep; /* Store IN EP for enabling @ setup */ ep->driver_data = dev; ep = usb_ep_autoconfig(gadget, &fs_out_desc); if (!ep) { status = -ENODEV; goto fail; } if (gadget_is_dualspeed(gadget)) hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress; dev->out_ep = ep; /* Store OUT EP for enabling @ setup */ ep->driver_data = dev; ep = usb_ep_autoconfig(gadget, &fs_int_desc); if (!ep) { status = -ENODEV; goto fail; } dev->int_ep = ep; ep->driver_data = dev; if (gadget_is_dualspeed(gadget)) { hs_int_desc.bEndpointAddress = fs_int_desc.bEndpointAddress; f->hs_descriptors = (struct usb_descriptor_header **) &hs_thor_downloader_function; if (!f->hs_descriptors) goto fail; } debug("%s: out_ep:%p out_req:%p\n", __func__, dev->out_ep, dev->out_req); return 0; fail: free(dev); return status; }
static int hidg_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_ep *ep; struct f_hidg *hidg = func_to_hidg(f); int status; dev_t dev; pr_info("%s: creating device %p\n", __func__, hidg); /* allocate instance-specific interface IDs, and patch descriptors */ status = usb_interface_id(c, f); if (status < 0) goto fail; hidg_interface_desc.bInterfaceNumber = status; /* allocate instance-specific endpoints */ status = -ENODEV; ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc); if (!ep) goto fail; ep->driver_data = c->cdev; /* claim */ hidg->in_ep = ep; /* preallocate request and buffer */ status = -ENOMEM; hidg->req = usb_ep_alloc_request(hidg->in_ep, GFP_KERNEL); if (!hidg->req) goto fail; hidg->req->buf = kmalloc(hidg->report_length, GFP_KERNEL); if (!hidg->req->buf) goto fail; /* set descriptor dynamic values */ hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; hidg_hs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; hidg_desc.desc[0].wDescriptorLength = cpu_to_le16(hidg->report_desc_length); hidg->set_report_buff = NULL; hidg_hs_in_ep_desc.bEndpointAddress = hidg_fs_in_ep_desc.bEndpointAddress; status = usb_assign_descriptors(f, hidg_fs_descriptors, hidg_hs_descriptors, NULL); if (status) goto fail; mutex_init(&hidg->lock); spin_lock_init(&hidg->spinlock); init_waitqueue_head(&hidg->write_queue); init_waitqueue_head(&hidg->read_queue); /* create char device */ cdev_init(&hidg->cdev, &f_hidg_fops); dev = MKDEV(major, hidg->minor); status = cdev_add(&hidg->cdev, dev, 1); if (status) goto fail; device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor); hacky_device_list_add(hidg); return 0; fail: ERROR(f->config->cdev, "hidg_bind FAILED\n"); if (hidg->req != NULL) { kfree(hidg->req->buf); if (hidg->in_ep != NULL) usb_ep_free_request(hidg->in_ep, hidg->req); } usb_free_all_descriptors(f); return status; }
/* ACM function driver setup/binding */ static int acm_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_acm *acm = func_to_acm(f); struct usb_string *us; int status; struct usb_ep *ep; acm_string_defs[ACM_CTRL_IDX].s = acm->ctrl_string_buf; acm_string_defs[ACM_DATA_IDX].s = acm->data_string_buf; acm_string_defs[ACM_IAD_IDX].s = acm->iad_string_buf; /* maybe allocate device-global string IDs, and patch descriptors */ us = usb_gstrings_attach(cdev, acm_strings, ARRAY_SIZE(acm_string_defs)); if (IS_ERR(us)) return PTR_ERR(us); acm_control_interface_desc.iInterface = us[ACM_CTRL_IDX].id; acm_data_interface_desc.iInterface = us[ACM_DATA_IDX].id; acm_iad_descriptor.iFunction = us[ACM_IAD_IDX].id; acm_iad_descriptor.bFunctionProtocol = acm->iad_proto; acm_control_interface_desc.bInterfaceProtocol = acm->ctrl_intf_proto; /* allocate instance-specific interface IDs, and patch descriptors */ status = usb_interface_id(c, f); if (status < 0) goto fail; acm->ctrl_id = status; acm_iad_descriptor.bFirstInterface = status; acm_control_interface_desc.bInterfaceNumber = status; acm_union_desc .bMasterInterface0 = status; status = usb_interface_id(c, f); if (status < 0) goto fail; acm->data_id = status; acm_data_interface_desc.bInterfaceNumber = status; acm_union_desc.bSlaveInterface0 = status; acm_call_mgmt_descriptor.bDataInterface = status; status = -ENODEV; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); if (!ep) goto fail; acm->port.in = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); if (!ep) goto fail; acm->port.out = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); if (!ep) goto fail; acm->notify = ep; ep->driver_data = cdev; /* claim */ /* allocate notification */ acm->notify_req = gs_alloc_req(ep, sizeof(struct usb_cdc_notification) + 2, GFP_KERNEL); if (!acm->notify_req) goto fail; acm->notify_req->complete = acm_cdc_notify_complete; acm->notify_req->context = acm; /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; acm_hs_notify_desc.bEndpointAddress = acm_fs_notify_desc.bEndpointAddress; acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function, acm_ss_function); if (status) goto fail; DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", acm->port_num, gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", acm->port.in->name, acm->port.out->name, acm->notify->name); return 0; fail: if (acm->notify_req) { gs_free_req(acm->notify, acm->notify_req); acm->notify_req = NULL; } /* we might as well release our claims on endpoints */ if (acm->notify) acm->notify->driver_data = NULL; if (acm->port.out) acm->port.out->driver_data = NULL; if (acm->port.in) acm->port.in->driver_data = NULL; ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); return status; }
static int mtp_function_bind(struct usb_configuration *c, struct usb_function *f) { int n, rc, id; struct usb_ep *ep; struct usb_request *req; struct proc_dir_entry *mtp_proc = NULL; spin_lock_init(&g_usb_mtp_context.lock); g_usb_mtp_context.cdev = c->cdev; /* allocate interface ID(s) */ id = usb_interface_id(c, f); if (id < 0) return id; intf_desc.bInterfaceNumber = id; /* Find all the endpoints we will use */ ep = usb_ep_autoconfig(g_usb_mtp_context.cdev->gadget, &fs_bulk_in_desc); if (!ep) { mtp_err("auto-configure hs_bulk_in_desc error\n"); goto autoconf_fail; } ep->driver_data = &g_usb_mtp_context; g_usb_mtp_context.bulk_in = ep; ep = usb_ep_autoconfig(g_usb_mtp_context.cdev->gadget, &fs_bulk_out_desc); if (!ep) { mtp_err("auto-configure hs_bulk_out_desc error\n"); goto autoconf_fail; } ep->driver_data = &g_usb_mtp_context; g_usb_mtp_context.bulk_out = ep; ep = usb_ep_autoconfig(g_usb_mtp_context.cdev->gadget, &fs_intr_in_desc); if (!ep) { mtp_err("auto-configure hs_intr_in_desc error\n"); goto autoconf_fail; } ep->driver_data = &g_usb_mtp_context; g_usb_mtp_context.intr_in = ep; if (gadget_is_dualspeed(g_usb_mtp_context.cdev->gadget)) { /* Assume endpoint addresses are the same for both speeds */ hs_bulk_in_desc.bEndpointAddress = fs_bulk_in_desc.bEndpointAddress; hs_bulk_out_desc.bEndpointAddress = fs_bulk_out_desc.bEndpointAddress; hs_intr_in_desc.bEndpointAddress = fs_intr_in_desc.bEndpointAddress; } rc = -ENOMEM; for (n = 0; n < MAX_BULK_RX_REQ_NUM; n++) { req = req_new(g_usb_mtp_context.bulk_out, BULK_BUFFER_SIZE); if (!req) goto autoconf_fail; pending_reqs[n] = req; req->complete = mtp_out_complete; req_put(&g_usb_mtp_context.rx_reqs, req); } for (n = 0; n < MAX_BULK_TX_REQ_NUM; n++) { req = req_new(g_usb_mtp_context.bulk_in, BULK_BUFFER_SIZE); if (!req) goto autoconf_fail; req->complete = mtp_in_complete; req_put(&g_usb_mtp_context.tx_reqs, req); } for (n = 0; n < MAX_CTL_RX_REQ_NUM; n++) ctl_req_put(&g_usb_mtp_context.ctl_rx_reqs, &ctl_reqs[n]); g_usb_mtp_context.int_tx_req = req_new(g_usb_mtp_context.intr_in, BULK_BUFFER_SIZE); if (!g_usb_mtp_context.int_tx_req) goto autoconf_fail; g_usb_mtp_context.intr_in_busy = 0; g_usb_mtp_context.int_tx_req->complete = mtp_int_complete; g_usb_mtp_context.ctl_tx_req = req_new(g_usb_mtp_context.cdev->gadget->ep0, 512); if (!g_usb_mtp_context.ctl_tx_req) goto autoconf_fail; misc_register(&mtp_device); mtp_proc = create_proc_entry("mtpctl", 0666, 0); if (!mtp_proc) { mtp_err("creating /proc/mtpctl failed\n"); goto autoconf_fail; } mtp_proc->proc_fops = &mtp_ctl_fops; return 0; autoconf_fail: rc = -ENOTSUPP; mtp_function_unbind(c, f); return rc; }
static int uvc_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct uvc_device *uvc = to_uvc(f); struct usb_string *us; unsigned int max_packet_mult; unsigned int max_packet_size; struct usb_ep *ep; struct f_uvc_opts *opts; int ret = -EINVAL; INFO(cdev, "uvc_function_bind\n"); opts = fi_to_f_uvc_opts(f->fi); /* Sanity check the streaming endpoint module parameters. */ opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U); opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U); opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); /* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */ if (opts->streaming_maxburst && (opts->streaming_maxpacket % 1024) != 0) { opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024); INFO(cdev, "overriding streaming_maxpacket to %d\n", opts->streaming_maxpacket); } /* Fill in the FS/HS/SS Video Streaming specific descriptors from the * module parameters. * * NOTE: We assume that the user knows what they are doing and won't * give parameters that their UDC doesn't support. */ if (opts->streaming_maxpacket <= 1024) { max_packet_mult = 1; max_packet_size = opts->streaming_maxpacket; } else if (opts->streaming_maxpacket <= 2048) { max_packet_mult = 2; max_packet_size = opts->streaming_maxpacket / 2; } else { max_packet_mult = 3; max_packet_size = opts->streaming_maxpacket / 3; } uvc_fs_streaming_ep.wMaxPacketSize = cpu_to_le16(min(opts->streaming_maxpacket, 1023U)); uvc_fs_streaming_ep.bInterval = opts->streaming_interval; uvc_hs_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); uvc_hs_streaming_ep.bInterval = opts->streaming_interval; uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); uvc_ss_streaming_ep.bInterval = opts->streaming_interval; uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; uvc_ss_streaming_comp.wBytesPerInterval = cpu_to_le16(max_packet_size * max_packet_mult * (opts->streaming_maxburst + 1)); /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { INFO(cdev, "Unable to allocate control EP\n"); goto error; } uvc->control_ep = ep; if (gadget_is_superspeed(c->cdev->gadget)) ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, &uvc_ss_streaming_comp); else if (gadget_is_dualspeed(cdev->gadget)) ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); else ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); if (!ep) { INFO(cdev, "Unable to allocate streaming EP\n"); goto error; } uvc->video.ep = ep; uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; us = usb_gstrings_attach(cdev, uvc_function_strings, ARRAY_SIZE(uvc_en_us_strings)); if (IS_ERR(us)) { ret = PTR_ERR(us); goto error; } uvc_iad.iFunction = us[UVC_STRING_CONTROL_IDX].id; uvc_control_intf.iInterface = us[UVC_STRING_CONTROL_IDX].id; ret = us[UVC_STRING_STREAMING_IDX].id; uvc_streaming_intf_alt0.iInterface = ret; uvc_streaming_intf_alt1.iInterface = ret; /* Allocate interface IDs. */ if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_iad.bFirstInterface = ret; uvc_control_intf.bInterfaceNumber = ret; uvc->control_intf = ret; if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_streaming_intf_alt0.bInterfaceNumber = ret; uvc_streaming_intf_alt1.bInterfaceNumber = ret; uvc->streaming_intf = ret; /* Copy descriptors */ f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); if (IS_ERR(f->fs_descriptors)) { ret = PTR_ERR(f->fs_descriptors); f->fs_descriptors = NULL; goto error; } if (gadget_is_dualspeed(cdev->gadget)) { f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); if (IS_ERR(f->hs_descriptors)) { ret = PTR_ERR(f->hs_descriptors); f->hs_descriptors = NULL; goto error; } } if (gadget_is_superspeed(c->cdev->gadget)) { f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); if (IS_ERR(f->ss_descriptors)) { ret = PTR_ERR(f->ss_descriptors); f->ss_descriptors = NULL; goto error; } } /* Preallocate control endpoint request. */ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); if (uvc->control_req == NULL || uvc->control_buf == NULL) { ret = -ENOMEM; goto error; } uvc->control_req->buf = uvc->control_buf; uvc->control_req->complete = uvc_function_ep0_complete; uvc->control_req->context = uvc; if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { printk(KERN_INFO "v4l2_device_register failed\n"); goto error; } /* Initialise video. */ ret = uvcg_video_init(&uvc->video); if (ret < 0) goto error; /* Register a V4L2 device. */ ret = uvc_register_video(uvc); if (ret < 0) { printk(KERN_INFO "Unable to register video device\n"); goto error; } return 0; error: v4l2_device_unregister(&uvc->v4l2_dev); if (uvc->control_req) usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); kfree(uvc->control_buf); usb_free_all_descriptors(f); return ret; }
static int ecm_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_ecm *ecm = func_to_ecm(f); int status; struct usb_ep *ep; /* allocate instance-specific interface IDs */ status = usb_interface_id(c, f); if (status < 0) goto fail; ecm->ctrl_id = status; ecm_control_intf.bInterfaceNumber = status; #ifdef CONFIG_LGE_USB_GADGET_DRIVER ecm_iad.bFirstInterface = status; #endif ecm_union_desc.bMasterInterface0 = status; status = usb_interface_id(c, f); printk(KERN_DEBUG "[MSG]>>f_ecm > ecm_bind : interface = %d !! \n", status ); if (status < 0) goto fail; ecm->data_id = status; ecm_data_nop_intf.bInterfaceNumber = status; ecm_data_intf.bInterfaceNumber = status; ecm_union_desc.bSlaveInterface0 = status; status = -ENODEV; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc); if (!ep) goto fail; ecm->port.in_ep = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc); if (!ep) goto fail; ecm->port.out_ep = ep; ep->driver_data = cdev; /* claim */ /* NOTE: a status/notification endpoint is *OPTIONAL* but we * don't treat it that way. It's simpler, and some newer CDC * profiles (wireless handsets) no longer treat it as optional. */ ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc); if (!ep) goto fail; ecm->notify = ep; ep->driver_data = cdev; /* claim */ status = -ENOMEM; /* allocate notification request and buffer */ ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); if (!ecm->notify_req) goto fail; ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL); if (!ecm->notify_req->buf) goto fail; ecm->notify_req->context = ecm; ecm->notify_req->complete = ecm_notify_complete; /* copy descriptors, and track endpoint copies */ f->descriptors = usb_copy_descriptors(ecm_fs_function); if (!f->descriptors) goto fail; ecm->fs.in = usb_find_endpoint(ecm_fs_function, f->descriptors, &fs_ecm_in_desc); ecm->fs.out = usb_find_endpoint(ecm_fs_function, f->descriptors, &fs_ecm_out_desc); ecm->fs.notify = usb_find_endpoint(ecm_fs_function, f->descriptors, &fs_ecm_notify_desc); /* 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)) { hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress; hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress; hs_ecm_notify_desc.bEndpointAddress = fs_ecm_notify_desc.bEndpointAddress; printk(KERN_ERR "[MSG]>> f_ecm > ecm_bind : IN EP = %d !! \n", hs_ecm_in_desc.bEndpointAddress ); printk(KERN_ERR "[MSG]>> f_ecm > ecm_bind : OUT EP= %d !! \n", hs_ecm_out_desc.bEndpointAddress); printk(KERN_ERR "[MSG]>> f_ecm > ecm_bind : NOT EP= %d !! \n", hs_ecm_notify_desc.bEndpointAddress); /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(ecm_hs_function); if (!f->hs_descriptors) goto fail; ecm->hs.in = usb_find_endpoint(ecm_hs_function, f->hs_descriptors, &hs_ecm_in_desc); ecm->hs.out = usb_find_endpoint(ecm_hs_function, f->hs_descriptors, &hs_ecm_out_desc); ecm->hs.notify = usb_find_endpoint(ecm_hs_function, f->hs_descriptors, &hs_ecm_notify_desc); } /* NOTE: all that is done without knowing or caring about * the network link ... which is unavailable to this code * until we're activated via set_alt(). */ ecm->port.open = ecm_open; ecm->port.close = ecm_close; DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n", gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", ecm->port.in_ep->name, ecm->port.out_ep->name, ecm->notify->name); return 0; fail: if (f->descriptors) usb_free_descriptors(f->descriptors); if (ecm->notify_req) { kfree(ecm->notify_req->buf); usb_ep_free_request(ecm->notify, ecm->notify_req); } /* we might as well release our claims on endpoints */ if (ecm->notify) ecm->notify->driver_data = NULL; if (ecm->port.out) ecm->port.out_ep->driver_data = NULL; if (ecm->port.in) ecm->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); return status; }
static int __init uvc_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct uvc_device *uvc = to_uvc(f); struct usb_ep *ep; int ret = -EINVAL; INFO(cdev, "uvc_function_bind\n"); /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { INFO(cdev, "Unable to allocate control EP\n"); goto error; } uvc->control_ep = ep; ep->driver_data = uvc; ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep); if (!ep) { INFO(cdev, "Unable to allocate streaming EP\n"); goto error; } uvc->video.ep = ep; ep->driver_data = uvc; /* Allocate interface IDs. */ if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_iad.bFirstInterface = ret; uvc_control_intf.bInterfaceNumber = ret; uvc->control_intf = ret; if ((ret = usb_interface_id(c, f)) < 0) goto error; uvc_streaming_intf_alt0.bInterfaceNumber = ret; uvc_streaming_intf_alt1.bInterfaceNumber = ret; uvc->streaming_intf = ret; /* Copy descriptors. */ f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); /* Preallocate control endpoint request. */ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); if (uvc->control_req == NULL || uvc->control_buf == NULL) { ret = -ENOMEM; goto error; } uvc->control_req->buf = uvc->control_buf; uvc->control_req->complete = uvc_function_ep0_complete; uvc->control_req->context = uvc; /* Avoid letting this gadget enumerate until the userspace server is * active. */ if ((ret = usb_function_deactivate(f)) < 0) goto error; /* Initialise video. */ ret = uvc_video_init(&uvc->video); if (ret < 0) goto error; /* Register a V4L2 device. */ ret = uvc_register_video(uvc); if (ret < 0) { printk(KERN_INFO "Unable to register video device\n"); goto error; } return 0; error: uvc_function_unbind(c, f); return ret; }
static int rndis_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_rndis *rndis = func_to_rndis(f); int status; struct usb_ep *ep; /* allocate instance-specific interface IDs */ status = usb_interface_id(c, f); if (status < 0) goto fail; rndis->ctrl_id = status; rndis_iad_descriptor.bFirstInterface = status; rndis_control_intf.bInterfaceNumber = status; rndis_union_desc.bMasterInterface0 = status; status = usb_interface_id(c, f); if (status < 0) goto fail; rndis->data_id = status; rndis_data_intf.bInterfaceNumber = status; rndis_union_desc.bSlaveInterface0 = status; status = -ENODEV; /* allocate instance-specific endpoints */ ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); if (!ep) goto fail; rndis->port.in_ep = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); if (!ep) goto fail; rndis->port.out_ep = ep; ep->driver_data = cdev; /* claim */ /* NOTE: a status/notification endpoint is, strictly speaking, * optional. We don't treat it that way though! It's simpler, * and some newer profiles don't treat it as optional. */ ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc); if (!ep) goto fail; rndis->notify = ep; ep->driver_data = cdev; /* claim */ status = -ENOMEM; /* allocate notification request and buffer */ rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); if (!rndis->notify_req) goto fail; rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL); if (!rndis->notify_req->buf) goto fail; rndis->notify_req->length = STATUS_BYTECOUNT; rndis->notify_req->context = rndis; rndis->notify_req->complete = rndis_response_complete; /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress; hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress; hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress; ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress; ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress; ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function, eth_ss_function); if (status) goto fail; rndis->port.open = rndis_open; rndis->port.close = rndis_close; status = rndis_register(rndis_response_available, rndis); if (status < 0) goto fail; rndis->config = status; rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); rndis_set_host_mac(rndis->config, rndis->ethaddr); rndis_set_max_pkt_xfer(rndis->config, rndis_ul_max_pkt_per_xfer); if (rndis->manufacturer && rndis->vendorID && rndis_set_param_vendor(rndis->config, rndis->vendorID, rndis->manufacturer)) goto fail; /* NOTE: all that is done without knowing or caring about * the network link ... which is unavailable to this code * until we're activated via set_alt(). */ DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n", gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", rndis->port.in_ep->name, rndis->port.out_ep->name, rndis->notify->name); return 0; fail: usb_free_all_descriptors(f); if (rndis->notify_req) { kfree(rndis->notify_req->buf); usb_ep_free_request(rndis->notify, rndis->notify_req); } /* we might as well release our claims on endpoints */ if (rndis->notify) rndis->notify->driver_data = NULL; if (rndis->port.out_ep) rndis->port.out_ep->driver_data = NULL; if (rndis->port.in_ep) rndis->port.in_ep->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; 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; }
/* ACM function driver setup/binding */ static int acm_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_acm *acm = func_to_acm(f); struct usb_string *us; int status; struct usb_ep *ep; D("+\n"); /* REVISIT might want instance-specific strings to help * distinguish instances ... */ /* maybe allocate device-global string IDs, and patch descriptors */ us = usb_gstrings_attach(cdev, acm_strings, ARRAY_SIZE(acm_string_defs)); if (IS_ERR(us)) return PTR_ERR(us); acm_control_interface_desc.iInterface = us[ACM_CTRL_IDX].id; acm_data_interface_desc.iInterface = us[ACM_DATA_IDX].id; acm_iad_descriptor.iFunction = us[ACM_IAD_IDX].id; /* allocate instance-specific interface IDs, and patch descriptors */ status = usb_interface_id(c, f); if (status < 0) goto fail; D("interface id: %d\n", status); if (g_acm_is_single_interface) { D("single interface\n"); acm->ctrl_id = acm->data_id = status; acm_single_interface_desc.bInterfaceNumber = status; acm_call_mgmt_descriptor.bDataInterface = status; } else { acm->ctrl_id = (u8)status; acm_iad_descriptor.bFirstInterface = status; acm_control_interface_desc.bInterfaceNumber = status; acm_union_desc .bMasterInterface0 = status; status = usb_interface_id(c, f); if (status < 0) goto fail; acm->data_id = status; acm_data_interface_desc.bInterfaceNumber = status; acm_union_desc.bSlaveInterface0 = status; acm_call_mgmt_descriptor.bDataInterface = status; } bsp_usb_add_setup_dev((unsigned)acm->data_id); status = -ENODEV; /* allocate instance-specific endpoints */ D("to ep autoconfig\n"); ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); if (!ep) goto fail; acm->port.in = ep; ep->driver_data = cdev; /* claim */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); if (!ep) goto fail; acm->port.out = ep; ep->driver_data = cdev; /* claim */ if (acm->support_notify) { ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); if (!ep) goto fail; acm->notify = ep; ep->driver_data = cdev; /* claim */ /* allocate notification */ acm->notify_req = gs_acm_cdev_alloc_req(ep, sizeof(struct usb_cdc_notification) + 2, GFP_KERNEL); if (!acm->notify_req) goto fail; acm->notify_req->complete = acm_cdc_notify_complete; acm->notify_req->context = acm; } else { acm->notify = NULL; acm->notify_req = NULL; } /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds */ D("do desc\n"); acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; if (acm->support_notify) acm_hs_notify_desc.bEndpointAddress = acm_fs_notify_desc.bEndpointAddress; acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; D("to assign desc\n"); acm_set_config_vendor(acm); status = usb_assign_descriptors(f, acm_fs_cur_function, acm_hs_cur_function, acm_ss_cur_function); if (status) goto fail; DBG(cdev, "acm_cdev%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", acm->port_num, gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", acm->port.in->name, acm->port.out->name, acm->notify ? acm->notify->name : "null"); printk(KERN_INFO "acm_cdev%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", acm->port_num, gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", acm->port.in->name, acm->port.out->name, acm->notify ? acm->notify->name : "null"); return 0; fail: if (acm->notify_req) gs_acm_cdev_free_req(acm->notify, acm->notify_req); /* we might as well release our claims on endpoints */ if (acm->notify) acm->notify->driver_data = NULL; if (acm->port.out) acm->port.out->driver_data = NULL; if (acm->port.in) acm->port.in->driver_data = NULL; ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); D("-\n"); return status; }