Beispiel #1
0
int fastboot_usb_ep_init()
{
	if (!l_fbdev.in_ep) {
		debugf("ep in is not alloc\r\n");
		return -1;
	}
	in = l_fbdev.in_ep;

	if (!l_fbdev.out_ep) {
		debugf("ep out is not alloc\r\n");
		return -1;
	}
	out = l_fbdev.out_ep;

	tx_req = usb_ep_alloc_request(in, 0);
	if (!tx_req) {
		debugf("ep tx request is not alloc\r\n");
		return -1;
	}
	rx_req = usb_ep_alloc_request(out, 0);
	if (!rx_req) {
		debugf("ep rx request is not alloc\r\n");
		usb_ep_free_request(in, tx_req);
		return -1;
	}

	return 0;
}
Beispiel #2
0
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;
}
Beispiel #3
0
int sysfs_endpoint_enable(sysfs_endpoint* sys_ep, struct usb_endpoint_descriptor* enable_desc)
{
  struct usb_request* request = 0;
  if (!sys_ep) {
    return -EINVAL;
  }
  DBG(sys_ep, "%s\n", __func__);
  if (sys_ep->enabled_desc) {
    return 0;
  }
  if (usb_ep_enable(sys_ep->ep, enable_desc)) {
    return -ENODEV;
  }
  request = usb_ep_alloc_request(sys_ep->ep, GFP_KERNEL);
  if (!request) {
    usb_ep_disable(sys_ep->ep);
    return -ENOMEM;
  }
  request->complete = sysfs_complete;
  request->context = sys_ep;
  sys_ep->request = request;
  sys_ep->enabled_desc = enable_desc;
  wake_up_interruptible(&sys_ep->waitq);
  return 0;
}
void pantech_usb_test_bind_loopback(void *endpoint)
{
	struct usb_ep *ep	= (struct usb_ep *)endpoint;
	if(!ep) return;

	if(!loopback_usb_request) {
		loopback_usb_request = usb_ep_alloc_request(ep, GFP_ATOMIC);
		if(!loopback_usb_request) {
			printk("error bind loopback\n");
		}
	}
	
	if(!loopback_buffer) {
		loopback_buffer = kmalloc(LOOPBACK_BUF_SIZE, GFP_ATOMIC);
		if(!loopback_buffer) {
			printk("error allocation loopback buffer\n");
		} else {
			printk("success allocation loopback buffer\n");
		}
	}	

	loopback_usb_test_cmd.run = 0;
	loopback_usb_test_cmd.open = 0;
	loopback_usb_test_cmd.type = 0xff;
}
/*
 * gs_alloc_req
 *
 * Allocate a usb_request and its buffer.  Returns a pointer to the
 * usb_request or NULL if there is an error.
 */
struct usb_request *
gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
{
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, kmalloc_flags);

	if (req != NULL) {
		req->length = len;
        /* if len is 0, alloc the empty req */
        if (0 == len) {
            req->buf = NULL;
            req->dma = (dma_addr_t)NULL;
        }
        else {
    		req->buf = kmalloc(len, kmalloc_flags);
    		if (req->buf == NULL) {
    			usb_ep_free_request(ep, req);
    			return NULL;
    	    }
        }
	}

	return req;
}
Beispiel #6
0
int send_sps_req(struct usb_ep *data_ep)
{
	struct usb_request *req = NULL;
	struct f_qdss *qdss = data_ep->driver_data;
	struct usb_gadget *gadget = qdss->cdev->gadget;
	u32 sps_params = 0;

	pr_debug("send_sps_req\n");

	req = usb_ep_alloc_request(data_ep, GFP_ATOMIC);
	if (!req) {
		pr_err("usb_ep_alloc_request failed\n");
		return -ENOMEM;
	}

	if (gadget_is_dwc3(gadget)) {
		req->length = 32*1024;
		sps_params = MSM_SPS_MODE | MSM_DISABLE_WB | MSM_INTERNAL_MEM |
			bam_info.usb_bam_pipe_idx;
	} else {
		/* non DWC3 BAM requires req->length to be 0 */
		req->length = 0;
		sps_params = (MSM_SPS_MODE | bam_info.usb_bam_pipe_idx |
				MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
	}
	req->udc_priv = sps_params;
	qdss->endless_req = req;
	if (usb_ep_queue(data_ep, req, GFP_ATOMIC)) {
		pr_err("send_sps_req: usb_ep_queue error\n");
		return -EIO;
	}
	return 0;
}
static int
uvc_video_alloc_requests(struct uvc_video *video)
{
	unsigned int i;
	int ret = -ENOMEM;

	BUG_ON(video->req_size);

	for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
		video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
		if (video->req_buffer[i] == NULL)
			goto error;

		video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
		if (video->req[i] == NULL)
			goto error;

		video->req[i]->buf = video->req_buffer[i];
		video->req[i]->length = 0;
		video->req[i]->dma = DMA_ADDR_INVALID;
		video->req[i]->complete = uvc_video_complete;
		video->req[i]->context = video;

		list_add_tail(&video->req[i]->list, &video->req_free);
	}

	video->req_size = video->ep->maxpacket;
	return 0;

error:
	uvc_video_free_requests(video);
	return ret;
}
Beispiel #8
0
static struct usb_request * __rkusb_init_ep_req(struct rkusb_dev *dev, struct usb_ep* ep) 
{
                struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if (!req)
		return NULL;
                req->buf = dev->req_in_buf;
	return req;
}
Beispiel #9
0
static struct usb_request *dtf_request_new(struct usb_ep *ep, int buffer_size)
{
	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);

	_dbgmsg_gadget( "_dbgmsg_gadget\n" );
	req = usb_ep_alloc_request(ep, GFP_KERNEL);
	if (!req) {
		_dbgmsg_gadget( "usb_ep_alloc_request error\n" );
		return NULL;
	}

	/* now allocate buffers for the requests */
	req->buf = kmalloc(buffer_size, GFP_KERNEL);
	if (!req->buf) {
		_dbgmsg_gadget( "usb_ep_free_request\n" );
		usb_ep_free_request(ep, req);
		return NULL;
	}

	return req;
}
static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
{
	unsigned		i;
	struct usb_request	*req;
	bool			usb_in;

	if (!n)
		return -ENOMEM;

	/* queue/recycle up to N requests */
	i = n;
	list_for_each_entry(req, list, list) {
		if (i-- == 0)
			goto extra;
	}

	if (ep->desc->bEndpointAddress & USB_DIR_IN)
		usb_in = true;
	else
		usb_in = false;

	while (i--) {
		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
		if (!req)
			return list_empty(list) ? -ENOMEM : 0;
		/* update completion handler */
		if (usb_in)
			req->complete = tx_complete;
		else
			req->complete = rx_complete;

		list_add(&req->list, list);
	}
	return 0;

extra:
	/* free extras */
	for (;;) {
		struct list_head	*next;

		next = req->list.next;
		list_del(&req->list);
		usb_ep_free_request(ep, req);

		if (next == list)
			break;

		req = container_of(next, struct usb_request, list);
	}
	return 0;
}
Beispiel #11
0
static struct usb_request *gs_request_new(struct usb_ep *ep)
{
	struct usb_request *req = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if (!req)
		return NULL;

	req->buf = kmalloc(ep->maxpacket, GFP_ATOMIC);
	if (!req->buf) {
		usb_ep_free_request(ep, req);
		return NULL;
	}

	return req;
}
Beispiel #12
0
static struct usb_request *acc_request_new(struct usb_ep *ep, int buffer_size)
{
	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
	if (!req)
		return NULL;

	/* now allocate buffers for the requests */
	req->buf = kmalloc(buffer_size, GFP_KERNEL);
	if (!req->buf) {
		usb_ep_free_request(ep, req);
		return NULL;
	}

	return req;
}
Beispiel #13
0
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len)
{
	struct usb_request      *req;

	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if (req) {
		req->length = len ?: default_len;
		req->buf = kmalloc(req->length, GFP_ATOMIC);
		if (!req->buf) {
			usb_ep_free_request(ep, req);
			req = NULL;
		}
	}
	return req;
}
Beispiel #14
0
struct usb_request *alloc_ep_req(struct usb_ep *ep)
{
	struct usb_request	*req;

	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if (req) {
		req->length = buflen;
		req->buf = kmalloc(buflen, GFP_ATOMIC);
		if (!req->buf) {
			usb_ep_free_request(ep, req);
			req = NULL;
		}
	}
	return req;
}
Beispiel #15
0
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
{
    struct usb_request	*req;

    req = usb_ep_alloc_request(ep, GFP_ATOMIC);
    if (req) {
        req->length = length;
        req->buf = kmalloc(length, GFP_ATOMIC);
        if (!req->buf) {
            usb_ep_free_request(ep, req);
            req = NULL;
        }
    }
    return req;
}
Beispiel #16
0
static int alloc_requests(struct fastboot_dev *dev, unsigned n, gfp_t gfp_flags)
{

#if 0
	dev->tx_req = usb_ep_alloc_request(dev->in_ep, 0);

	if (!dev->tx_req)
		goto fail1;

	dev->rx_req = usb_ep_alloc_request(dev->out_ep, 0);

	if (!dev->rx_req)
		goto fail2;

	return 0;

fail2:
	usb_ep_free_request(dev->in_ep, dev->tx_req);
fail1:
	error("can't alloc requests");
	return -1;
#endif
	return 0;
}
Beispiel #17
0
struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len)
{
	struct usb_request      *req;

	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if (req) {
		req->length = usb_endpoint_dir_out(ep->desc) ?
			usb_ep_align(ep, len) : len;
		req->buf = kmalloc(req->length, GFP_ATOMIC);
		if (!req->buf) {
			usb_ep_free_request(ep, req);
			req = NULL;
		}
	}
	return req;
}
static int npk_prepare_usb_requests(void)
{
    if (!_npk_dev || !_npk_dev->ep_in) {
        pr_err("Invalid npk device or enpoint");
        return -ENODEV;
    }

    _npk_dev->req_data = usb_ep_alloc_request(_npk_dev->ep_in, GFP_KERNEL);
    if (!_npk_dev->req_data) {
        npk_usb_request_free(_npk_dev->ep_in, _npk_dev->req_data);
        _npk_dev->req_data = NULL;
        pr_err("Cannot allocate usb request");
        return -ENOMEM;
    }
    return 0;
}
Beispiel #19
0
/*-------------------------------------------------------------------------*/
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
{
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, 0);
	if (!req)
		return req;

	req->length = length;
	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
	if (!req->buf) {
		usb_ep_free_request(ep, req);
		req = NULL;
	}

	return req;
}
static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
{
	unsigned		i;
	struct usb_request	*req;

	if (!n)
		return -ENOMEM;

	/* queue/recycle up to N requests */
	i = n;
	list_for_each_entry(req, list, list) {
		if (i-- == 0)
			goto extra;
	}
	while (i--) {
		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
		if (!req)
			return list_empty(list) ? -ENOMEM : 0;
		/* use req buffer for 4-byte align */
		req->buf = kmalloc(MAX_BUFFER_SIZE, GFP_ATOMIC);
		if (!req->buf) {
			usb_ep_free_request(ep, req);
			return list_empty(list) ? -ENOMEM : 0;
		}

		list_add(&req->list, list);
	}
	return 0;

extra:
	/* free extras */
	for (;;) {
		struct list_head	*next;

		next = req->list.next;
		list_del(&req->list);
		kfree(req->buf);
		usb_ep_free_request(ep, req);

		if (next == list)
			break;

		req = container_of(next, struct usb_request, list);
	}
	return 0;
}
Beispiel #21
0
static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
{
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, 0);
	if (!req)
		return NULL;

	req->length = EP_BUFFER_SIZE;
	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
	if (!req->buf) {
		usb_ep_free_request(ep, req);
		return NULL;
	}
	memset(req->buf, 0, req->length);

	return req;
}
/*
 * gs_alloc_req
 *
 * Allocate a usb_request and its buffer.  Returns a pointer to the
 * usb_request or NULL if there is an error.
 */
struct usb_request *
gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
{
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, kmalloc_flags);

	if (req != NULL) {
		req->length = len;
		req->buf = kmalloc(len, kmalloc_flags);
		if (req->buf == NULL) {
			usb_ep_free_request(ep, req);
			return NULL;
		}
	}

	return req;
}
Beispiel #23
0
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
{
	struct usb_request	*req;

	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
	if (req) {
		if (len)
			req->length = len;
		else
			req->length = buflen;
		req->buf = kmalloc(req->length, GFP_ATOMIC);
		if (!req->buf) {
			usb_ep_free_request(ep, req);
			req = NULL;
		}
	}
	return req;
}
Beispiel #24
0
struct usb_request *
gsdio_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags)
{
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, flags);
	if (!req) {
		pr_err("%s: usb alloc request failed\n", __func__);
		return NULL;
	}

	req->length = len;
	req->buf = kmalloc(len, flags);
	if (!req->buf) {
		pr_err("%s: request buf allocation failed\n", __func__);
		usb_ep_free_request(ep, req);
		return NULL;
	}

	return req;
}
Beispiel #25
0
static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
{
	unsigned		i;
	struct usb_request	*req;

	if (!n)
		return -ENOMEM;

	/* queue/recycle up to N requests */
	i = n;
	list_for_each_entry(req, list, list) {
		if (i-- == 0)
			goto extra;
	}
	while (i--) {
		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
		if (!req){
			printk(KERN_ERR "%s@%d: usb_ep_alloc_request fail: %d\n", __func__, __LINE__, i);
			return list_empty(list) ? -ENOMEM : 0;
		}
		list_add(&req->list, list);
	}
	return 0;

extra:
	/* free extras */
	for (;;) {
		struct list_head	*next;

		next = req->list.next;
		list_del(&req->list);
		usb_ep_free_request(ep, req);

		if (next == list)
			break;

		req = container_of(next, struct usb_request, list);
	}
	return 0;
}
/*
 * gs_alloc_req
 *
 * Allocate a usb_request and its buffer.  Returns a pointer to the
 * usb_request or NULL if there is an error.
 */
struct usb_request *
pxa910_gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
{
	struct usb_request *req;

	req = usb_ep_alloc_request(ep, kmalloc_flags);

	if (req != NULL) {
		req->length = len;
#ifdef CONFIG_PXA910_1G_DDR_WORKAROUND
		req->buf = kmalloc(len, kmalloc_flags | GFP_DMA);
#else
		req->buf = kmalloc(len, kmalloc_flags);
#endif
		if (req->buf == NULL) {
			usb_ep_free_request(ep, req);
			return NULL;
		}
	}

	return req;
}
Beispiel #27
0
static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
{
    unsigned		i;
    struct usb_request	*req;

    if (!n)
        return -ENOMEM;


    i = n;
    list_for_each_entry(req, list, list) {
        if (i-- == 0)
            goto extra;
    }
    while (i--) {
        req = usb_ep_alloc_request(ep, GFP_ATOMIC);
        if (!req)
            return list_empty(list) ? -ENOMEM : 0;
        list_add(&req->list, list);
    }
    return 0;

extra:

    for (;;) {
        struct list_head	*next;

        next = req->list.next;
        list_del(&req->list);
        usb_ep_free_request(ep, req);

        if (next == list)
            break;

        req = container_of(next, struct usb_request, list);
    }
    return 0;
}
static int bam_data_alloc_requests(struct usb_ep *ep, struct list_head *head,
		int num,
		void (*cb)(struct usb_ep *ep, struct usb_request *),
		gfp_t flags)
{
	int i;
	struct usb_request *req;

	pr_debug("%s: ep:%p head:%p num:%d cb:%p", __func__,
			ep, head, num, cb);

	for (i = 0; i < num; i++) {
		req = usb_ep_alloc_request(ep, flags);
		if (!req) {
			pr_err("%s: req allocated:%d\n", __func__, i);
			return list_empty(head) ? -ENOMEM : 0;
		}
		req->complete = cb;
		list_add(&req->list, head);
	}

	return 0;
}
Beispiel #29
0
static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv,
				       unsigned short status)
{
	struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usb_request *req;
	unsigned short *buf;

	/* alloc new usb_request for recip */
	req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC);
	if (!req) {
		dev_err(dev, "recip request allocation fail\n");
		return;
	}

	/* alloc recip data buffer */
	buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
	if (!buf) {
		usb_ep_free_request(&dcp->ep, req);
		dev_err(dev, "recip data allocation fail\n");
		return;
	}

	/* recip data is status */
	*buf = cpu_to_le16(status);

	/* allocated usb_request/buffer will be freed */
	req->complete	= __usbhsg_recip_send_complete;
	req->buf	= buf;
	req->length	= sizeof(*buf);
	req->zero	= 0;

	/* push packet */
	pipe->handler = &usbhs_fifo_pio_push_handler;
	usbhsg_queue_push(dcp, usbhsg_req_to_ureq(req));
}
Beispiel #30
0
static int __init zero_bind(struct usb_gadget *gadget)
{
    struct zero_dev		*dev;
    struct usb_ep		*ep;
    int			gcnum;

    /* FIXME this can't yet work right with SH ... it has only
     * one configuration, numbered one.
     */
    if (gadget_is_sh(gadget))
        return -ENODEV;

    /* Bulk-only drivers like this one SHOULD be able to
     * autoconfigure on any sane usb controller driver,
     * but there may also be important quirks to address.
     */
    usb_ep_autoconfig_reset(gadget);
    ep = usb_ep_autoconfig(gadget, &fs_source_desc);
    if (!ep) {
autoconf_fail:
        pr_err("%s: can't autoconfigure on %s\n",
               shortname, gadget->name);
        return -ENODEV;
    }
    EP_IN_NAME = ep->name;
    ep->driver_data = ep;	/* claim */

    ep = usb_ep_autoconfig(gadget, &fs_sink_desc);
    if (!ep)
        goto autoconf_fail;
    EP_OUT_NAME = ep->name;
    ep->driver_data = ep;	/* claim */

    gcnum = usb_gadget_controller_number(gadget);
    if (gcnum >= 0)
        device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
    else {
        /* gadget zero is so simple (for now, no altsettings) that
         * it SHOULD NOT have problems with bulk-capable hardware.
         * so warn about unrcognized controllers, don't panic.
         *
         * things like configuration and altsetting numbering
         * can need hardware-specific attention though.
         */
        pr_warning("%s: controller '%s' not recognized\n",
                   shortname, gadget->name);
        device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
    }


    /* ok, we made sense of the hardware ... */
    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;
    spin_lock_init(&dev->lock);
    dev->gadget = gadget;
    set_gadget_data(gadget, dev);

    init_timer(&dev->resume);
    dev->resume.function = zero_autoresume;
    dev->resume.data = (unsigned long) dev;

    /* preallocate control response and buffer */
    dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
    if (!dev->req)
        goto enomem;
    dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
    if (!dev->req->buf)
        goto enomem;

    dev->req->complete = zero_setup_complete;

    device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

    if (gadget_is_dualspeed(gadget)) {
        /* assume ep0 uses the same value for both speeds ... */
        dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;

        /* and that all endpoints are dual-speed */
        hs_source_desc.bEndpointAddress =
            fs_source_desc.bEndpointAddress;
        hs_sink_desc.bEndpointAddress =
            fs_sink_desc.bEndpointAddress;
    }

    if (gadget_is_otg(gadget)) {
        otg_descriptor.bmAttributes |= USB_OTG_HNP,
                                       source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
    }

    usb_gadget_set_selfpowered(gadget);

    if (autoresume) {
        source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
    }

    gadget->ep0->driver_data = dev;

    INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
    INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
         EP_OUT_NAME, EP_IN_NAME);

    snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
             init_utsname()->sysname, init_utsname()->release,
             gadget->name);

    return 0;

enomem:
    zero_unbind(gadget);
    return -ENOMEM;
}