move usb to drivers for quilt patches
[kernel-power] / usbhost / usb / gadget / f_raw.c
diff --git a/usbhost/usb/gadget/f_raw.c b/usbhost/usb/gadget/f_raw.c
deleted file mode 100644 (file)
index 5c128a4..0000000
+++ /dev/null
@@ -1,779 +0,0 @@
-/*
- * f_raw.c -- USB Raw Access Function Driver
- *
- * Copyright (C) 2009 Nokia Corporation
- * Contact: Felipe Balbi <felipe.balbi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* #define VERBOSE_DEBUG */
-
-#include <linux/kernel.h>
-#include <linux/utsname.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/cdev.h>
-#include <linux/poll.h>
-#include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/raw.h>
-
-#include "gadget_chips.h"
-
-struct graw {
-       struct cdev                     chdev;
-
-       struct usb_gadget               *gadget;
-       struct usb_function             func;
-
-       unsigned                        major;
-       dev_t                           dev;
-};
-
-static struct graw *the_graw;
-static struct f_raw *the_raw;
-
-struct raw_request {
-       struct usb_request              *req;
-       struct list_head                list;
-       wait_queue_head_t               wait;
-       unsigned long                   len;
-
-       unsigned                        queued:1, completed:1;
-       int                             nr;
-};
-
-struct raw_ep_descs {
-       struct usb_endpoint_descriptor  *raw_out;
-};
-
-struct f_raw {
-       /* pool of read requests */
-       struct list_head                read_pool;
-       int                             nr_reqs;
-
-       /* synchronize with userland access */
-       struct mutex                    mutex;
-
-       struct usb_ep                   *out;
-       struct raw_request              *allocated_req;
-       struct class                    *class;
-
-       struct raw_ep_descs             fs;
-       struct raw_ep_descs             hs;
-
-       struct graw                     graw;
-
-       unsigned                        vmas;
-       unsigned                        connected:1;
-       unsigned                        can_activate:1;
-
-       u8                              intf_id;
-};
-
-static inline struct f_raw *func_to_raw(struct usb_function *f)
-{
-       return container_of(f, struct f_raw, graw.func);
-}
-
-static u64 raw_dmamask = DMA_BIT_MASK(64);
-
-/*-------------------------------------------------------------------------*/
-
-#define RAW_INTF_IDX   1
-
-static struct usb_string raw_string_defs[] = {
-       [RAW_INTF_IDX].s        = "Device Upgrade Interface",
-       {  },   /* end of list */
-};
-
-static struct usb_gadget_strings raw_string_table = {
-       .language               = 0x0409,       /* en-US */
-       .strings                = raw_string_defs,
-};
-
-static struct usb_gadget_strings *raw_strings[] = {
-       &raw_string_table,
-       NULL,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_interface_descriptor raw_intf __initdata = {
-       .bLength                = sizeof(raw_intf),
-       .bDescriptorType        = USB_DT_INTERFACE,
-       .bInterfaceNumber       = 0,
-
-       .bAlternateSetting      = 0,
-       .bNumEndpoints          = 1,
-       .bInterfaceClass        = USB_CLASS_VENDOR_SPEC,
-};
-
-/* High-Speed Support */
-
-static struct usb_endpoint_descriptor raw_hs_ep_out_desc = {
-       .bLength                = USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType        = USB_DT_ENDPOINT,
-
-       .bEndpointAddress       = USB_DIR_OUT,
-       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize         = __constant_cpu_to_le16(512),
-};
-
-static struct usb_descriptor_header *hs_function[] __initdata = {
-       (struct usb_descriptor_header *) &raw_intf,
-       (struct usb_descriptor_header *) &raw_hs_ep_out_desc,
-       NULL,
-};
-
-/* Full-Speed Support */
-
-static struct usb_endpoint_descriptor raw_fs_ep_out_desc = {
-       .bLength                = USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType        = USB_DT_ENDPOINT,
-
-       .bEndpointAddress       = USB_DIR_OUT,
-       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_descriptor_header *fs_function[] __initdata = {
-       (struct usb_descriptor_header *) &raw_intf,
-       (struct usb_descriptor_header *) &raw_fs_ep_out_desc,
-       NULL,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static void raw_complete(struct usb_ep *ep, struct usb_request *req);
-
-static struct raw_request *raw_alloc_request(struct f_raw *raw, unsigned buflen)
-{
-       struct list_head        *pool = &raw->read_pool;
-       struct usb_request      *req;
-       struct raw_request      *raw_req;
-       void                    *buf;
-
-       raw_req = kzalloc(sizeof(*raw_req), GFP_KERNEL);
-       if (raw_req == NULL)
-               goto fail1;
-
-       INIT_LIST_HEAD(&raw_req->list);
-
-       req = usb_ep_alloc_request(raw->out, GFP_KERNEL);
-       if (req == NULL)
-               goto fail2;
-
-       req->length = buflen;
-       req->complete = raw_complete;
-       req->context = raw_req;
-
-       buf = dma_alloc_coherent(&raw->graw.gadget->dev, buflen,
-                                &req->dma, GFP_KERNEL);
-       if (IS_ERR(buf))
-               goto fail3;
-       req->buf = buf;
-
-       raw_req->req = req;
-       raw_req->len = buflen;
-
-       if (raw->nr_reqs == MAX_NR_REQUESTS)
-               goto fail4;
-
-       raw_req->nr = raw->nr_reqs;
-       raw->nr_reqs++;
-       list_add_tail(&raw_req->list, pool);
-
-       return raw_req;
-
-fail4:
-       dma_free_coherent(&raw->graw.gadget->dev, buflen,
-                         buf, req->dma);
-
-fail3:
-       usb_ep_free_request(raw->out, req);
-
-fail2:
-       kfree(raw_req);
-
-fail1:
-       return NULL;
-}
-
-static void raw_complete(struct usb_ep *ep, struct usb_request *req)
-{
-       struct f_raw                    *raw = ep->driver_data;
-       struct raw_request              *raw_req = req->context;
-       struct usb_composite_dev        *cdev = raw->graw.func.config->cdev;
-       int                             status = req->status;
-
-       switch (status) {
-       case 0:                         /* normal completion */
-               break;
-       case -ECONNABORTED:             /* hardware forced ep reset */
-       case -ECONNRESET:               /* request dequeued */
-       case -ESHUTDOWN:                /* disconnected from host */
-               VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status,
-                               req->actual, req->length);
-               return;
-       case -EOVERFLOW:                /* not big enough buffer */
-       default:
-               DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
-                               status, req->actual, req->length);
-       case -EREMOTEIO:                /* short read */
-               break;
-       }
-
-       raw_req->queued = 0;
-       raw_req->completed = 1;
-       wake_up_interruptible(&raw_req->wait);
-}
-
-static struct raw_request *find_request(struct f_raw *raw, int value)
-{
-       struct raw_request *req;
-
-       list_for_each_entry(req, &raw->read_pool, list)
-               if (req->nr == value)
-                       return req;
-
-       return NULL;
-}
-
-static inline int enable_raw(struct usb_composite_dev *cdev, struct f_raw *raw)
-{
-       const struct usb_endpoint_descriptor    *out_desc;
-       struct usb_ep                           *ep;
-
-       int                                     status = 0;
-
-       /* choose endpoint */
-       out_desc = ep_choose(cdev->gadget, &raw_hs_ep_out_desc,
-                       &raw_fs_ep_out_desc);
-
-       /* enable it */
-       ep = raw->out;
-       status = usb_ep_enable(ep, out_desc);
-       if (status < 0)
-               return status;
-       ep->driver_data = raw;
-
-       DBG(cdev, "%s enabled\n", raw->graw.func.name);
-
-       return 0;
-}
-
-static inline void disable_raw(struct f_raw *raw)
-{
-       struct usb_composite_dev        *cdev;
-       struct usb_ep                   *ep;
-
-       int                             status;
-
-       cdev = raw->graw.func.config->cdev;
-
-       ep = raw->out;
-       if (ep->driver_data) {
-               status = usb_ep_disable(ep);
-               if (status < 0)
-                       DBG(cdev, "disable %s --> %d\n",
-                                       ep->name, status);
-               ep->driver_data = NULL;
-       }
-
-       VDBG(cdev, "%s disabled\n", raw->graw.func.name);
-}
-
-static int raw_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
-{
-       struct usb_composite_dev        *cdev = f->config->cdev;
-       struct f_raw                    *raw = func_to_raw(f);
-
-       /* we konw alt is zero */
-       if (raw->out->driver_data)
-               disable_raw(raw);
-
-       return enable_raw(cdev, raw);
-}
-
-static void raw_disable(struct usb_function *f)
-{
-       struct f_raw    *raw = func_to_raw(f);
-
-       disable_raw(raw);
-}
-
-static int raw_queue_request(struct f_raw *raw, struct raw_queue_request *qr)
-{
-       struct usb_ep           *ep = raw->out;
-       struct raw_request      *raw_req;
-       int                     status = 0;
-
-       raw_req = find_request(raw, qr->nr);
-       if (raw_req == NULL)
-               return -ENOENT;
-
-       if (qr->nr_bytes > raw_req->len)
-               return -EINVAL;
-
-       /* FIXME: lock with irqsave and check if transfer already in progress,
-        * bail out if so. */
-
-       raw_req->req->length = qr->nr_bytes;
-
-       init_waitqueue_head(&raw_req->wait);
-       raw_req->completed = 0;
-       raw_req->queued = 1;
-       status = usb_ep_queue(ep, raw_req->req, GFP_KERNEL);
-       if (status) {
-               struct usb_composite_dev        *cdev;
-
-               cdev = raw->graw.func.config->cdev;
-               ERROR(cdev, "start %s %s --> %d\n", "OUT", ep->name, status);
-               raw_req->queued = 0;
-       }
-
-       return status;
-}
-
-static int raw_free_request(struct f_raw *raw, int nr)
-{
-       struct raw_request *raw_req;
-       struct usb_request *req;
-
-       raw_req = find_request(raw, nr);
-       if (raw_req == NULL)
-               return -ENOENT;
-
-       if (raw->allocated_req == raw_req)
-               raw->allocated_req = NULL;
-       /* FIXME: munmap? */
-
-       req = raw_req->req;
-       /* FIXME: spinlocking? */
-       if (raw_req->queued)
-               usb_ep_dequeue(raw->out, req);
-       raw_req->queued = 0;
-       dma_free_coherent(&raw->graw.gadget->dev, raw_req->len, req->buf,
-                       req->dma);
-       usb_ep_free_request(raw->out, req);
-       list_del(&raw_req->list);
-       kfree(raw_req);
-
-       return 0;
-}
-
-static int raw_get_request_status(struct f_raw *raw,
-                                 struct raw_request_status *st)
-{
-       struct raw_request      *raw_req;
-
-       raw_req = find_request(raw, st->nr);
-       if (raw_req == NULL)
-               return -ENOENT;
-
-       if (!raw_req->queued) {
-               st->status = raw_req->req->status;
-               st->nr_bytes = raw_req->req->actual;
-               raw_req->completed = 0;
-       } else {
-               st->status = -EBUSY;
-               st->nr_bytes = 0;
-       }
-
-       return 0;
-}
-
-static void get_completion_map(struct f_raw *raw, unsigned int *mask_out)
-{
-       struct raw_request *req;
-       unsigned int mask = 0;
-
-       list_for_each_entry(req, &raw->read_pool, list)
-               if (req->completed)
-                       mask |= (1 << req->nr);
-
-       *mask_out = mask;
-}
-
-static long fraw_ioctl(struct file *filp, unsigned code, unsigned long value)
-{
-       struct f_raw                    *raw = filp->private_data;
-       struct usb_ep                   *ep = raw->out;
-       unsigned int                    map;
-       int                             status = 0;
-       struct raw_request_status       req_st;
-       struct raw_queue_request        que_req;
-
-       if (unlikely(!ep))
-               return -EINVAL;
-
-       mutex_lock(&raw->mutex);
-
-       switch (code) {
-       case RAW_FIFO_STATUS:
-               status = usb_ep_fifo_status(ep);
-               break;
-       case RAW_FIFO_FLUSH:
-               usb_ep_fifo_flush(ep);
-               break;
-       case RAW_CLEAR_HALT:
-               status = usb_ep_clear_halt(ep);
-               break;
-       case RAW_ALLOC_REQUEST:
-               if (raw->allocated_req != NULL) {
-                       status = -EBUSY;
-                       break;
-               }
-               if (value > MAX_REQUEST_LEN || (value % PAGE_SIZE) != 0) {
-                       status = -EINVAL;
-                       break;
-               }
-               raw->allocated_req = raw_alloc_request(raw, value);
-               if (raw->allocated_req == NULL) {
-                       status = -ENOMEM;
-                       break;
-               }
-               status = raw->allocated_req->nr;
-               break;
-       case RAW_QUEUE_REQUEST:
-               status = copy_from_user(&que_req, (void __user *) value,
-                                       sizeof(que_req));
-               if (status)
-                       break;
-               status = raw_queue_request(raw, &que_req);
-               break;
-       case RAW_FREE_REQUEST:
-               status = raw_free_request(raw, value);
-               break;
-       case RAW_GET_COMPLETION_MAP:
-               get_completion_map(raw, &map);
-               status = put_user(map, (unsigned int __user *) value);
-               break;
-       case RAW_GET_REQUEST_STATUS:
-               status = copy_from_user(&req_st, (void __user *) value,
-                                       sizeof(req_st));
-               if (status)
-                       break;
-               status = raw_get_request_status(raw, &req_st);
-               if (status)
-                       break;
-               status = copy_to_user((void __user *) value, &req_st,
-                                     sizeof(req_st));
-       }
-
-       mutex_unlock(&raw->mutex);
-
-       return status;
-}
-
-static int fraw_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       size_t                  size = vma->vm_end - vma->vm_start;
-       struct f_raw            *raw = filp->private_data;
-       struct raw_request      *raw_req;
-       struct usb_request      *req;
-       int                     ret;
-
-       mutex_lock(&raw->mutex);
-       raw_req = raw->allocated_req;
-       if (raw_req == NULL) {
-               ret = -ENXIO;
-               goto out;
-       }
-       req = raw_req->req;
-
-       if (size != raw_req->len) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       vma->vm_private_data = raw;
-
-       ret = dma_mmap_coherent(&raw->graw.gadget->dev, vma, req->buf,
-                               req->dma, raw_req->len);
-       if (ret < 0)
-               goto out;
-
-       raw->allocated_req = NULL;
-
-out:
-       mutex_unlock(&raw->mutex);
-
-       return 0;
-}
-
-static int fraw_open(struct inode *inode, struct file *filp)
-{
-       struct f_raw                    *raw;
-
-       raw = the_raw;
-       filp->private_data = the_raw;
-
-       return 0;
-}
-
-static int fraw_release(struct inode *inode, struct file *filp)
-{
-       struct f_raw                    *raw = filp->private_data;
-
-       while (!list_empty(&raw->read_pool)) {
-               struct raw_request *req;
-
-               req = list_first_entry(&raw->read_pool, struct raw_request,
-                                      list);
-               raw_free_request(raw, req->nr);
-       }
-       raw->nr_reqs = 0;
-       filp->private_data = NULL;
-
-       return 0;
-}
-
-static unsigned int fraw_poll(struct file *filp, struct poll_table_struct *pt)
-{
-       struct f_raw                    *raw = filp->private_data;
-       struct raw_request              *req;
-       int                             ret = 0;
-
-       mutex_lock(&raw->mutex);
-       list_for_each_entry(req, &raw->read_pool, list) {
-               poll_wait(filp, &req->wait, pt);
-
-               if (req->completed) {
-                       ret = POLLIN | POLLRDNORM;
-                       break;
-               }
-       }
-       mutex_unlock(&raw->mutex);
-
-       return ret;
-}
-
-static struct file_operations fraw_fops = {
-       .owner          = THIS_MODULE,
-       .open           = fraw_open,
-       .release        = fraw_release,
-       .unlocked_ioctl = fraw_ioctl,
-       .mmap           = fraw_mmap,
-       .poll           = fraw_poll,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init raw_bind(struct usb_configuration *c, struct usb_function *f)
-{
-       struct usb_composite_dev        *cdev = c->cdev;
-       struct f_raw                    *raw = func_to_raw(f);
-       struct usb_ep                   *ep;
-
-       int                             status;
-
-       /* allocate instance-specific interface IDs and patch descriptors */
-
-       status = usb_interface_id(c, f);
-       if (status < 0)
-               goto fail;
-       raw->intf_id = status;
-
-       raw_intf.bInterfaceNumber = status;
-
-       /* allocate instance-specific endpoints */
-
-       ep = usb_ep_autoconfig(cdev->gadget, &raw_fs_ep_out_desc);
-       if (!ep)
-               goto fail;
-       raw->out = ep;
-       ep->driver_data = cdev; /* claim */
-
-       /* copy descriptors and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(fs_function);
-
-       raw->fs.raw_out = usb_find_endpoint(fs_function,
-                       f->descriptors, &raw_fs_ep_out_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)) {
-               raw_hs_ep_out_desc.bEndpointAddress =
-                       raw_fs_ep_out_desc.bEndpointAddress;
-
-               /* copy descriptors and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(hs_function);
-
-               raw->hs.raw_out = usb_find_endpoint(hs_function,
-                               f->hs_descriptors, &raw_hs_ep_out_desc);
-       }
-
-       INIT_LIST_HEAD(&raw->read_pool);
-       mutex_init(&raw->mutex);
-
-       /* create device nodes */
-       raw->class = class_create(THIS_MODULE, "fraw");
-       device_create(raw->class, &cdev->gadget->dev,
-                       MKDEV(raw->graw.major, 0), raw, "%s", f->name);
-
-       cdev->gadget->dev.dma_mask = &raw_dmamask;
-       cdev->gadget->dev.coherent_dma_mask = DMA_64BIT_MASK;
-       raw->graw.gadget = cdev->gadget;
-       the_raw = raw;
-
-       DBG(cdev, "raw: %s speed OUT/%s\n",
-                       gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
-                       raw->out->name);
-
-       return 0;
-
-fail:
-       if (raw->class)
-               class_destroy(raw->class);
-
-       if (raw->out)
-               raw->out->driver_data = NULL;
-
-       ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
-
-       return status;
-}
-
-static void raw_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-       struct f_raw *raw = func_to_raw(f);
-
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
-       device_destroy(raw->class, MKDEV(raw->graw.major, 0));
-       class_destroy(raw->class);
-       kfree(raw);
-}
-
-/**
- * raw_bind_config - add a RAW function to a configuration
- * @c: the configuration to support the RAW instance
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- */
-static int __init raw_bind_config(struct usb_configuration *c)
-{
-       struct f_raw    *raw;
-       int             status;
-
-       if (raw_string_defs[RAW_INTF_IDX].id == 0) {
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-
-               raw_string_defs[RAW_INTF_IDX].id = status;
-               raw_intf.iInterface = status;
-       }
-
-       /* allocate and initialize one new instance */
-       raw = kzalloc(sizeof(*raw), GFP_KERNEL);
-       if (!raw)
-               return -ENOMEM;
-
-       raw->graw.func.name     = "raw";
-       raw->graw.func.strings  = raw_strings;
-       /* descriptors are per-instance copies */
-       raw->graw.func.bind     = raw_bind;
-       raw->graw.func.unbind   = raw_unbind;
-       raw->graw.func.set_alt  = raw_set_alt;
-       raw->graw.func.disable  = raw_disable;
-
-       status = usb_add_function(c, &raw->graw.func);
-       if (status)
-               kfree(raw);
-
-       return status;
-}
-
-/**
- * graw_setup - initialize character driver for one rx
- * @g: gadget to associate with
- * Contex: may sleep
- *
- * Returns negative errno or zero.
- */
-static int __init graw_setup(struct usb_gadget *g)
-{
-       struct graw     *graw;
-
-       int             status;
-       int             major;
-
-       dev_t           dev;
-
-       if (the_graw)
-               return -EBUSY;
-
-       graw = kzalloc(sizeof(*graw), GFP_KERNEL);
-       if (!graw) {
-               status = -ENOMEM;
-               goto fail1;
-       }
-
-       status = alloc_chrdev_region(&dev, 0, 1, "fraw");
-       if (status)
-               goto fail2;
-
-       major = MAJOR(dev);
-
-       cdev_init(&graw->chdev, &fraw_fops);
-       graw->chdev.owner       = THIS_MODULE;
-       graw->dev               = dev;
-       graw->major             = major;
-
-       status = cdev_add(&graw->chdev, dev, 1);
-       if (status)
-               goto fail3;
-
-       the_graw = graw;
-
-       return 0;
-
-fail3:
-       /* cdev_put(&graw->cdev); */
-       unregister_chrdev_region(graw->dev, 1);
-
-fail2:
-       kfree(graw);
-
-fail1:
-       return status;
-}
-
-static void __exit graw_cleanup(void)
-{
-       struct graw     *graw = the_graw;
-
-       if (!graw)
-               return;
-
-       cdev_del(&graw->chdev);
-       /* cdev_put(&graw->chdev); */
-       unregister_chrdev_region(graw->dev, 1);
-       kfree(graw);
-}
-