예제 #1
0
int usb_assign_descriptors(struct usb_function *f,
		struct usb_descriptor_header **fs,
		struct usb_descriptor_header **hs,
		struct usb_descriptor_header **ss)
{
	struct usb_gadget *g = f->config->cdev->gadget;

	if (fs) {
		f->fs_descriptors = usb_copy_descriptors(fs);
		if (!f->fs_descriptors)
			goto err;
	}
	if (hs && gadget_is_dualspeed(g)) {
		f->hs_descriptors = usb_copy_descriptors(hs);
		if (!f->hs_descriptors)
			goto err;
	}
	if (ss && gadget_is_superspeed(g)) {
		f->ss_descriptors = usb_copy_descriptors(ss);
		if (!f->ss_descriptors)
			goto err;
	}
	return 0;
err:
	usb_free_all_descriptors(f);
	return -ENOMEM;
}
예제 #2
0
static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
{
    struct f_hidg *hidg = func_to_hidg(f);

    pr_info("%s: destroying device %p\n", __func__, hidg);
    /* This does not cover all race conditions, only most common one */
    mutex_lock(&hidg->lock);
    hacky_device_list_remove(hidg);
    mutex_unlock(&hidg->lock);

    device_destroy(hidg_class, MKDEV(major, hidg->minor));
    cdev_del(&hidg->cdev);

    /* disable/free request and end point */
    usb_ep_disable(hidg->in_ep);
    /* TODO: calling this function crash kernel,
       not calling this funct ion crash kernel inside f_hidg_write */
    /* usb_ep_dequeue(hidg->in_ep, hidg->req); */

    kfree(hidg->req->buf);
    usb_ep_free_request(hidg->in_ep, hidg->req);

    usb_free_all_descriptors(f);

    kfree(hidg->report_desc);
    kfree(hidg->set_report_buff);
    kfree(hidg);
}
예제 #3
0
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 void acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct f_acm        *acm = func_to_acm(f);
	D("+\n");
	acm_string_defs[0].id = 0;
	usb_free_all_descriptors(f);
	if (acm->notify_req)
		gs_acm_cdev_free_req(acm->notify, acm->notify_req);
	D("-\n");
}
예제 #5
0
파일: f_uvc.c 프로젝트: asmalldev/linux
static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct usb_composite_dev *cdev = c->cdev;
	struct uvc_device *uvc = to_uvc(f);

	INFO(cdev, "%s\n", __func__);

	video_unregister_device(&uvc->vdev);
	v4l2_device_unregister(&uvc->v4l2_dev);

	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
	kfree(uvc->control_buf);

	usb_free_all_descriptors(f);
}
예제 #6
0
static void
rndis_unbind(struct usb_configuration *c, struct usb_function *f)
{
    struct f_rndis		*rndis = func_to_rndis(f);

    rndis_deregister(rndis->config);
    rndis_exit();

    usb_free_all_descriptors(f);

    kfree(rndis->notify_req->buf);
    usb_ep_free_request(rndis->notify, rndis->notify_req);

    kfree(rndis);
    __rndis = NULL;
}
예제 #7
0
파일: f_uvc.c 프로젝트: AiWinters/linux
static void
uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct usb_composite_dev *cdev = c->cdev;
	struct uvc_device *uvc = to_uvc(f);

	INFO(cdev, "uvc_function_unbind\n");

	video_unregister_device(uvc->vdev);
	uvc->control_ep->driver_data = NULL;
	uvc->video.ep->driver_data = NULL;

	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
	kfree(uvc->control_buf);

	usb_free_all_descriptors(f);

	kfree(uvc);
}
예제 #8
0
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;
}
예제 #9
0
파일: f_uvc.c 프로젝트: 7799/linux
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;
}
예제 #10
0
파일: f_uvc.c 프로젝트: asmalldev/linux
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;
}
예제 #11
0
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;
}
예제 #12
0
파일: f_uvc.c 프로젝트: AiWinters/linux
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;
	/*
	 * 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;

	/*
	 * 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->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;

	/* 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:
	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;
}