Dear Lukasz Majewski, > USB Composite gadget implementation for u-boot. It builds on top > of USB UDC drivers. > > This commit is based on following files from Linux Kernel v2.6.36: > > ./include/linux/usb/composite.h > ./drivers/usb/gadget/composite.c > > SHA1: d187abb9a83e6c6b6e9f2ca17962bdeafb4bc903 > > Signed-off-by: Lukasz Majewski <l.majew...@samsung.com> > Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com> > Cc: Marek Vasut <ma...@denx.de> > > --- > Changes for v2: > - Squash the kernel files with u-boot compatibility layer. > - Removal of dead/kernel specific code > - Comments corrected according to u-boot coding style > --- > drivers/usb/gadget/composite.c | 1091 > +++++++++++++++++++++++++++++++++++++++ include/linux/usb/composite.h | > 350 +++++++++++++ > include/usb/lin_gadget_compat.h | 25 +- > 3 files changed, 1464 insertions(+), 2 deletions(-) > create mode 100644 drivers/usb/gadget/composite.c > create mode 100644 include/linux/usb/composite.h
[...] > +int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) > +{ > + unsigned next = c->next_string_id; > + if (unlikely(n > 254 || (unsigned)next + n > 254)) This unlikely() call is unlikely part of uboot :) > + return -ENODEV; > + c->next_string_id += n; > + return next + 1; > +} > + > +static void composite_setup_complete(struct usb_ep *ep, struct usb_request > *req) +{ > + if (req->status || req->actual != req->length) > + debug("%s: setup complete --> %d, %d/%d\n", __func__, > + req->status, req->actual, req->length); > +} > + > +/* [...] > + > +static void composite_unbind(struct usb_gadget *gadget) > +{ > + struct usb_composite_dev *cdev = get_gadget_data(gadget); > + > + /* > + * composite_disconnect() must already have been called > + * by the underlying peripheral controller driver! > + * so there's no i/o concurrency that could affect the > + * state protected by cdev->lock. > + */ > + BUG_ON(cdev->config); Do we have BUG_ON() defined in uboot ? > + > + while (!list_empty(&cdev->configs)) { > + struct usb_configuration *c; > + > + c = list_first_entry(&cdev->configs, > + struct usb_configuration, list); > + while (!list_empty(&c->functions)) { > + struct usb_function *f; > + > + f = list_first_entry(&c->functions, > + struct usb_function, list); > + list_del(&f->list); > + if (f->unbind) { > + debug("unbind function '%s'/%p\n", > + f->name, f); > + f->unbind(c, f); > + } > + } > + list_del(&c->list); > + if (c->unbind) { > + debug("unbind config '%s'/%p\n", c->label, c); > + c->unbind(c); > + } > + } > + if (composite->unbind) > + composite->unbind(cdev); > + > + if (cdev->req) { > + kfree(cdev->req->buf); > + usb_ep_free_request(gadget->ep0, cdev->req); > + } > + kfree(cdev); > + set_gadget_data(gadget, NULL); > + > + composite = NULL; > +} > + > +static int composite_bind(struct usb_gadget *gadget) > +{ > + struct usb_composite_dev *cdev; > + int status = -ENOMEM; > + > + cdev = calloc(sizeof *cdev, 1); > + if (!cdev) > + return status; > + > + cdev->gadget = gadget; > + set_gadget_data(gadget, cdev); > + INIT_LIST_HEAD(&cdev->configs); > + > + /* preallocate control response and buffer */ > + cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); > + if (!cdev->req) > + goto fail; > + cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); > + if (!cdev->req->buf) > + goto fail; > + cdev->req->complete = composite_setup_complete; > + gadget->ep0->driver_data = cdev; > + > + cdev->bufsiz = USB_BUFSIZ; > + cdev->driver = composite; > + > + usb_gadget_set_selfpowered(gadget); > + usb_ep_autoconfig_reset(cdev->gadget); > + > + status = composite->bind(cdev); > + if (status < 0) > + goto fail; > + > + cdev->desc = *composite->dev; > + cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; > + > + debug("%s: ready\n", composite->name); > + return 0; > + > +fail: > + composite_unbind(gadget); > + return status; > +} > + > +static void > +composite_suspend(struct usb_gadget *gadget) > +{ > + struct usb_composite_dev *cdev = get_gadget_data(gadget); > + struct usb_function *f; > + > + debug("%s: suspend\n", __func__); > + if (cdev->config) { > + list_for_each_entry(f, &cdev->config->functions, list) { > + if (f->suspend) > + f->suspend(f); > + } > + } > + if (composite->suspend) > + composite->suspend(cdev); > + > + cdev->suspended = 1; > +} > + > +static void > +composite_resume(struct usb_gadget *gadget) > +{ > + struct usb_composite_dev *cdev = get_gadget_data(gadget); > + struct usb_function *f; > + > + debug("%s: resume\n", __func__); > + if (composite->resume) > + composite->resume(cdev); > + if (cdev->config) { > + list_for_each_entry(f, &cdev->config->functions, list) { > + if (f->resume) > + f->resume(f); > + } > + } > + > + cdev->suspended = 0; > +} > + > +static struct usb_gadget_driver composite_driver = { > + .speed = USB_SPEED_HIGH, > + > + .bind = composite_bind, > + .unbind = composite_unbind, You have some weird indent in here? > + > + .setup = composite_setup, > + .disconnect = composite_disconnect, > + > + .suspend = composite_suspend, > + .resume = composite_resume, > +}; > + I think this patch is getting much better ;-) _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot