[V2 PATCH 03/10] added media agnostic (MA) data structures and handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is where we create, store and handle endpoint and device structures
that are specific to the MA USB drivers. Each MA USB structure maps 1:1
with it's corresponding USB structure (e.g. there is one MA USB endpoint
per USB endpoint).

Signed-off-by: Sean O. Stalley <sean.stalley@xxxxxxxxx>
Signed-off-by: Stephanie Wallick <stephanie.s.wallick@xxxxxxxxx>
---
 drivers/staging/mausb/drivers/mausb_const.h    | 109 ++++
 drivers/staging/mausb/drivers/mausb_mem-host.c | 402 ++++++++++++
 drivers/staging/mausb/drivers/mausb_mem-host.h |  74 +++
 drivers/staging/mausb/drivers/mausb_mem.c      | 842 +++++++++++++++++++++++++
 drivers/staging/mausb/drivers/mausb_mem.h      | 509 +++++++++++++++
 drivers/staging/mausb/drivers/mausb_state.h    | 184 ++++++
 6 files changed, 2120 insertions(+)
 create mode 100755 drivers/staging/mausb/drivers/mausb_const.h
 create mode 100644 drivers/staging/mausb/drivers/mausb_mem-host.c
 create mode 100644 drivers/staging/mausb/drivers/mausb_mem-host.h
 create mode 100644 drivers/staging/mausb/drivers/mausb_mem.c
 create mode 100644 drivers/staging/mausb/drivers/mausb_mem.h
 create mode 100644 drivers/staging/mausb/drivers/mausb_state.h

diff --git a/drivers/staging/mausb/drivers/mausb_const.h b/drivers/staging/mausb/drivers/mausb_const.h
new file mode 100755
index 0000000..1089f81
--- /dev/null
+++ b/drivers/staging/mausb/drivers/mausb_const.h
@@ -0,0 +1,109 @@
+/* Name:	mausb_const.h
+ * Description: This header describes the Media Agnostic USB constants
+ *              that must be known by the both the host and device side drivers.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Contact Information:
+ * Sean Stalley, sean.stalley@xxxxxxxxx
+ * Stephanie Wallick, stephanie.s.wallick@xxxxxxxxx
+ * 2111 NE 25th Avenue
+ * Hillsboro, Oregon 97124
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MAUSB_CONST_H
+#define __MAUSB_CONST_H
+
+/* MA USB protocol constants per Table 68 of the MA USB Spec */
+#define MAUSB_DATA_CHANNEL_DELAY	400	/* temp value */
+#define MAUSB_MGMT_CHANNEL_DELAY	((100 * HZ)/1000 + 1)
+#define MAUSB_MGMT_RESPONSE_DELAY	((5 * HZ)/1000 + 1) /* 5 msec */
+#define MAUSB_MGMT_RT_DELAY \
+	((MAUSB_MGMT_RESPONSE_DELAY + (2 * MAUSB_MGMT_CHANNEL_DELAY)))
+#define MAUSB_TRANSFER_RESPONSE_TIME	10	/* 10 msec */
+#define MAUSB_TRANSFER_TIMEOUT \
+	(MAUSB_TRANSFER_RESPONSE_TIME + (2 * MAUSB_DATA_CHANNEL_DELAY))
+#define MAUSB_TRANSFER_KEEP_ALIVE \
+	(MAUSB_TRANSFER_RESPONSE_TIME + MAUSB_DATA_CHANNEL_DELAY)
+#define MAUSB_DEFAULT_KEEP_ALIVE	 0
+#define MAUSB_MAX_TRANSFER_LIFETIME	 1000	/* 1 sec */
+#define MAUSB_TRANSFER_REPEAT_TIME	 10	/* 10 msec */
+
+#define MAUSB_MAX_REQ_ID		 ((1 << 8) - 1)
+#define MAUSB_MAX_SEQ_NUM		 ((1 << 24) - 1)
+#define MAUSB_MAX_DIALOG_TOKEN		 ((1 << 10) - 1)
+#define MAUSB_MIN_CONTROL_BUF_SIZE	 4104	/* Bytes */
+
+
+/* MA USB protocol variables per Table 69 of the MA USB Spec */
+#define MAUSB_BULK_TRANSFER_RETRIES	 10	/* min value is 5 */
+#define MAUSB_CONTROL_TRANSFER_RETRIES	 10	/* min value is 5 */
+#define MAUSB_INTERRUPT_TRANSFER_RETRIES 10	/* min value is 3 */
+#define MAUSB_MGMT_TRANSFER_RETRIES	 4      /* min value is 4 */
+#define MAUSB_TRANSFER_SETUP_RETRIES	 4	/* min value is 4 */
+
+
+/* MA USB constants not explicitly defined in MA USB Spec */
+#define MAUSB_HALF_REQ_ID		 ((MAUSB_MAX_REQ_ID + 1) >> 2)
+#define MAUSB_HALF_SEQ_NUM		 ((MAUSB_MAX_SEQ_NUM + 1) >> 2)
+#define MAUSB_MAX_OUTSTANDING_SEQ_NUM	 (1 << 23)
+
+/* Largest packet size (in bytes) that the medium can handle */
+#define MAUSB_MAX_PACKET_SIZE	300
+
+/* Used to parse get_status control requests */
+#define EP_REQ (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+#define EP_IN_REQ (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+#define DEV_IN_REQ (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define INTF_IN_REQ (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Used for generating the mass_id for the device */
+#define MASS_ID_MIN	1
+#define MASS_ID_MAX	254
+
+
+#endif
diff --git a/drivers/staging/mausb/drivers/mausb_mem-host.c b/drivers/staging/mausb/drivers/mausb_mem-host.c
new file mode 100644
index 0000000..7ba0ec5
--- /dev/null
+++ b/drivers/staging/mausb/drivers/mausb_mem-host.c
@@ -0,0 +1,402 @@
+/* Name:	mausb_mem-host.c
+ * Description: Contains hostside-specific memory functions, as well as
+ *              wrappers for functions in mausb_mem.c.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Contact Information:
+ * Sean Stalley, sean.stalley@xxxxxxxxx
+ * Stephanie Wallick, stephanie.s.wallick@xxxxxxxxx
+ * 2111 NE 25th Avenue
+ * Hillsboro, Oregon 97124
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include <linux/kthread.h>
+
+#include "mausb_hcd.h"
+#include "mausb_mem-host.h"
+#include "mausb_mem.h"
+#include "mausb_tx.h"
+#include "mausb_mgmt.h"
+
+/**
+ * Returns a pointer to the media agnostic data for a given endpoint.
+ */
+struct mausb_host_ep *usb_to_ma_endpoint(struct usb_host_endpoint *ep)
+{
+	return (struct mausb_host_ep *) ep->hcpriv;
+}
+
+/**
+ * Returns the number of urbs currently in the MA USB HCD. Will return 0 if the
+ * MA USB HCD is empty or a negative errno if an error occurs.
+ */
+int mausb_hcd_urb_count(struct mausb_hcd *mhcd)
+{
+	int			count = 0;
+	struct mausb_host_ep	*ma_ep;
+	struct mausb_dev	*mausb_dev;
+	struct mausb_urb	*maurb;
+	unsigned long		irq_flags;
+
+	/* for every device */
+	spin_lock_irqsave(&mhcd->hcd_lock, irq_flags);
+	list_for_each_entry(mausb_dev, &mhcd->ma_dev.dev_list, dev_list) {
+		spin_unlock_irqrestore(&mhcd->hcd_lock, irq_flags);
+
+		/* for every endpoint */
+		spin_lock_irqsave(&mausb_dev->dev_lock, irq_flags);
+		list_for_each_entry(ma_ep, &mausb_dev->ep_list, ep_list) {
+			spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+
+			/* for every urb */
+			spin_lock_irqsave(&ma_ep->ep_lock, irq_flags);
+			list_for_each_entry(maurb, &ma_ep->urb_list, urb_list) {
+				++count;
+			}
+
+			spin_unlock_irqrestore(&ma_ep->ep_lock, irq_flags);
+			spin_lock_irqsave(&mausb_dev->dev_lock, irq_flags);
+		}
+
+		spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+		spin_lock_irqsave(&mhcd->hcd_lock, irq_flags);
+	}
+
+	spin_unlock_irqrestore(&mhcd->hcd_lock, irq_flags);
+
+	return count;
+}
+
+/**
+ * This function removes a device data from the hcd. All endpoints belonging
+ * to this device are also removed from the hcd and released (including EP0).
+ */
+void mausb_free_dev(struct usb_hcd *hcd, struct usb_device *dev)
+{
+	struct mausb_hcd	*mhcd = usb_hcd_to_mausb_hcd(hcd);
+	struct ma_dev		*ma_dev = &mhcd->ma_dev;
+	struct mausb_dev	*mausb_dev = mausb_find_dev_host(ma_dev, dev);
+	struct mausb_host_ep	*ep0 = list_first_entry(&mausb_dev->ep_list,
+					struct mausb_host_ep, ep_list);
+
+	if (NULL == mausb_dev) {
+		mausb_err(mhcd, "%s: USB device #%i not found\n",
+			__func__, dev->devnum);
+		return;
+	}
+
+	ep0->ep_handle_state = MAUSB_EP_HANDLE_INACTIVE;
+
+	/* inactivate EP0 handle */
+	mausb_tx_dev_mgmt_req_ep(EPInactivateReq, &mhcd->ma_dev.mgmt,
+		mausb_dev, true, ep0);
+
+	/* delete remaining EP Handles */
+	mausb_tx_dev_mgmt_req(EPHandleDeleteReq, &mhcd->ma_dev.mgmt,
+		mausb_dev, MAUSB_HOST);
+
+	mausb_tx_dev_mgmt_req(USBDevDisconnectReq, &ma_dev->mgmt,
+		mausb_dev, MAUSB_HOST);
+
+	mausb_internal_free_dev(ma_dev, mausb_dev);
+
+	return;
+}
+
+/*
+ * Adds an endpoint to the specified device.
+ *
+ * This function allocates private endpoint data and adds the given endpoint
+ * to the given device. In the mausb_hcd, devices hold their endpoints in a
+ * linked list.
+ */
+int mausb_add_endpoint(struct usb_hcd *hcd, struct usb_device *dev,
+		struct usb_host_endpoint *ep)
+{
+	int			status;
+	char			*ep_type;
+	struct mausb_hcd	*mhcd = usb_hcd_to_mausb_hcd(hcd);
+	struct ma_dev		*ma_dev = &mhcd->ma_dev;
+	struct mausb_dev	*mausb_dev;
+	struct mausb_ms_drv	*ms_driver = ma_dev->ms_driver;
+	struct mausb_host_ep	*ma_ep;
+
+	/* don't need to do anything for root hub */
+	if ((NULL == dev->parent) && (&dev->ep0 != ep))
+		return 0;
+
+	mausb_dev = mausb_find_dev_host(ma_dev, dev);
+	if (NULL == mausb_dev) {
+		mausb_err(mhcd, "unable to add endpoint: USB device #%i not"
+			" found\n", dev->devnum);
+		return -ENODEV;
+	}
+
+	status = mausb_internal_add_ep(mausb_dev, ep, NULL, &ma_ep,
+		&host_transfer_timeout, GFP_KERNEL);
+
+	if (status < 0) {
+		mausb_err(mhcd, "could not add endpoint: error %i\n", status);
+		return status;
+	}
+
+	/* need ms driver before adding endpoint */
+	if (NULL == ms_driver)
+		return -ENODEV;
+
+	/* for debug messages */
+	switch (usb_endpoint_type(&ep->desc)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		ep_type = "control";
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		ep_type = "bulk";
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		ep_type = "interrupt";
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		ep_type = "isochronous";
+		break;
+	default:
+		ep_type = "unknown";
+	}
+
+	/* set up control endpoint data channel */
+	if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_CONTROL) {
+		status = mausb_add_data_channel(ms_driver, ma_ep,
+			&complete_control_transferRequest);
+	}
+	/* set up bulk IN endpoint data channel */
+	else if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK
+		&& usb_endpoint_dir_in(&ep->desc)) {
+		status = mausb_add_data_channel(ms_driver, ma_ep,
+			&complete_IN_transferRequest);
+	}
+	/* set up bulk OUT endpoint data channel */
+	else if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK
+		&& usb_endpoint_dir_out(&ep->desc)) {
+		status = mausb_add_data_channel(ms_driver, ma_ep,
+			&complete_OUT_transferRequest);
+	}
+	/* set up an interrupt IN endpoint data channel */
+	else if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_INT
+		&& usb_endpoint_dir_in(&ep->desc)) {
+		status = mausb_add_data_channel(ms_driver, ma_ep,
+			&complete_IN_transferRequest);
+	}
+	/* set up an interrupt OUT endpoint data channel */
+	else if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_INT
+		&& usb_endpoint_dir_out(&ep->desc)) {
+		status = mausb_add_data_channel(ms_driver, ma_ep,
+			&complete_OUT_transferRequest);
+	} else {
+		mausb_err(mhcd,
+			"%s: attempted to add channel for ep %i of unsupported"
+			" type\n", __func__, usb_endpoint_num(&ep->desc));
+		return -EOPNOTSUPP;
+	}
+
+	if (status < 0) {
+		mausb_err(mhcd, "cannot add %s channel for ep %i: error %i\n",
+			ep_type, usb_endpoint_num(&ep->desc), status);
+		/* cleanup endpoint */
+		mausb_internal_drop_ep(ma_ep);
+	} else {
+		mausb_dbg(mhcd, "%s: added %s channel for ep %i\n", __func__,
+			ep_type, usb_endpoint_num(&ep->desc));
+	}
+
+	return status;
+}
+
+/*
+ * Removes an endpoint from the specified device.
+ *
+ * This function removes the given endpoint from the given device and releases
+ * private endpoint data. In the mausb_hcd, devices hold their endpoints in
+ * a linked list.
+ *
+ * TODO: determine & implement proper behavior when endpoint is not
+ *       associated with given device (or is associated with a different
+ *       device)
+ */
+int mausb_drop_endpoint(struct usb_hcd *hcd, struct usb_device *dev,
+		struct usb_host_endpoint *ep)
+{
+	int			ret = 0;
+	struct mausb_hcd	*mhcd = usb_hcd_to_mausb_hcd(hcd);
+	struct mausb_host_ep	*ma_ep = usb_to_ma_endpoint(ep);
+	struct mausb_dev	*ma_dev;
+	struct mausb_urb	*ma_urb, *next_urb;
+	unsigned long		irq_flags;
+
+	if (NULL == ma_ep) {
+		mausb_err(mhcd, "%s: cannot find data for endpoint at %p\n",
+			__func__, ep);
+		return -ENODEV;
+	}
+
+	ma_dev = ma_ep->mausb_dev;
+
+	mausb_dbg(mhcd, "dropping endpoint at %p to USB device #%i\n", ep,
+		dev->devnum);
+
+	ret = mausb_tx_dev_mgmt_req_ep(CancelTransferReq, &mhcd->ma_dev.mgmt,
+		ma_dev, true, ma_ep);
+
+	ma_ep->ep_handle_state = MAUSB_EP_HANDLE_INACTIVE;
+
+	ret = mausb_tx_dev_mgmt_req_ep(EPInactivateReq, &mhcd->ma_dev.mgmt,
+		ma_dev, true, ma_ep);
+
+	spin_lock_irqsave(&ma_ep->ep_lock, irq_flags);
+	list_for_each_entry_safe(ma_urb, next_urb, &ma_ep->urb_list, urb_list) {
+
+		mausb_unlink_giveback_urb(ma_urb, -ECONNRESET);
+	}
+
+	if (!list_empty(&ma_ep->urb_list)) {
+		mausb_err(mhcd, "%s: could not drop all urbs for ma_ep at %p\n",
+			__func__, ma_ep->ep);
+	}
+
+	spin_unlock_irqrestore(&ma_ep->ep_lock, irq_flags);
+
+	return 0;
+}
+
+/**
+ * This function allocates a new device and adds it onto the MA device's linked
+ * list of usb devices. It also allocates endpoint data for the control
+ * endpoint (EP0).
+ *
+ * Returns 1 on success or 0 on failure.
+ */
+int mausb_alloc_dev(struct usb_hcd *hcd, struct usb_device *dev)
+{
+	int			status = 0;
+	struct mausb_hcd	*mhcd = usb_hcd_to_mausb_hcd(hcd);
+	struct ma_dev		*ma_dev = &mhcd->ma_dev;
+	struct mausb_dev	*mausb_dev;
+
+	mausb_dev = mausb_internal_alloc_dev(ma_dev, dev, NULL);
+	if (NULL == mausb_dev)
+		return 0;
+
+	/* add EP0 */
+	mausb_dbg(mhcd, "%s: adding EP0 . . .\n", __func__);
+	status = mausb_add_endpoint(hcd, dev, &dev->ep0);
+
+	/*
+	 * Don't add send the EP Request yet, usbcore hasn't set
+	 * the ep0 descriptor. Wait until a datapacket is sent.
+	 */
+
+	if (status >= 0)
+		return 1;
+
+	/* TODO: drop endpoint here if failure */
+	mausb_free_dev(hcd, dev);
+	mausb_err(mhcd, "%s: could not add EP0 %i\n", __func__, status);
+	return 0;
+}
+
+/**
+ * USB core calls the HCD's check_bandwidth function immediately after adding
+ * or deleting endpoints.
+ */
+int mausb_check_bandwidth(struct usb_hcd *hcd, struct usb_device *dev)
+{
+	int			status;
+	struct mausb_hcd	*mhcd = usb_hcd_to_mausb_hcd(hcd);
+	struct ma_dev		*ma_dev = &mhcd->ma_dev;
+	struct mausb_dev	*mausb_dev = mausb_find_dev_host(ma_dev, dev);
+
+	/* don't do anything if roothub */
+	if (NULL == dev->parent)
+		return 0;
+
+	if (NULL == mausb_dev) {
+		mausb_err(mhcd, "%s: could not find data for USB device #%i\n",
+			__func__, dev->devnum);
+		return -ENODEV;
+	}
+
+	/* delete the old endpoints (if applicable) */
+	status = mausb_tx_dev_mgmt_req(EPHandleDeleteReq, &ma_dev->mgmt,
+					mausb_dev, MAUSB_HOST);
+
+	/* TODO: error checking (suppose the EPHandleDelete fails...) */
+
+	/* add the new endpoints (if applicable) */
+	status = mausb_tx_dev_mgmt_req(EPHandleReq, &ma_dev->mgmt, mausb_dev,
+		MAUSB_HOST);
+
+	if (-ENODEV == status) /* no endpoints were applicable */
+		status = 0;
+
+	return status;
+}
+
+/**
+ * This function will be called if mausb_add_endpoint(), mausb_drop_ep(),
+ * or mausb_check_bandwidth returns with an error. It is supposed to revert
+ * a device to a previously good schedule. We assume any schedule will work,
+ * so we should, in theory, never have to revert to a previous schedule.
+ */
+void mausb_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *dev)
+{
+	mausb_dbg(usb_hcd_to_mausb_hcd(hcd),
+		"resetting bandwidth for USB edvice #%i\n", dev->devnum);
+	return;
+}
+
diff --git a/drivers/staging/mausb/drivers/mausb_mem-host.h b/drivers/staging/mausb/drivers/mausb_mem-host.h
new file mode 100644
index 0000000..9df6c1f
--- /dev/null
+++ b/drivers/staging/mausb/drivers/mausb_mem-host.h
@@ -0,0 +1,74 @@
+/* Name:	mausb_mem-host.h
+ * Description: header for mausb_mem-host.c
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Contact Information:
+ * Sean Stalley, sean.stalley@xxxxxxxxx
+ * Stephanie Wallick, stephanie.s.wallick@xxxxxxxxx
+ * 2111 NE 25th Avenue
+ * Hillsboro, Oregon 97124
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MAUSB_MEM_HOST_H
+#define __MAUSB_MEM_HOST_H
+
+/* endpoint/device helper functions */
+struct mausb_host_ep *usb_to_ma_endpoint(struct usb_host_endpoint *ep);
+int mausb_hcd_urb_count(struct mausb_hcd *mhcd);
+
+/* USB core interfaces */
+int mausb_alloc_dev(struct usb_hcd *hcd, struct usb_device *dev);
+void mausb_free_dev(struct usb_hcd *hcd, struct usb_device *dev);
+int mausb_add_endpoint(struct usb_hcd *hcd, struct usb_device *dev,
+		struct usb_host_endpoint *ep);
+int mausb_drop_endpoint(struct usb_hcd *hcd, struct usb_device *dev,
+		struct usb_host_endpoint *ep);
+int mausb_check_bandwidth(struct usb_hcd *hcd, struct usb_device *dev);
+void mausb_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *dev);
+
+#endif
diff --git a/drivers/staging/mausb/drivers/mausb_mem.c b/drivers/staging/mausb/drivers/mausb_mem.c
new file mode 100644
index 0000000..e378e2d
--- /dev/null
+++ b/drivers/staging/mausb/drivers/mausb_mem.c
@@ -0,0 +1,842 @@
+/* Name:	mausb_mem.c
+ * Description: Handles all of the dynamic data structures for the host
+ *              controller, including any data that needs to exist
+ *              on a per-device, per-endpoint, or per-transfer basis.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Contact Information:
+ * Sean Stalley, sean.stalley@xxxxxxxxx
+ * Stephanie Wallick, stephanie.s.wallick@xxxxxxxxx
+ * 2111 NE 25th Avenue
+ * Hillsboro, Oregon 97124
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/kthread.h>
+
+#include "mausb_mem.h"
+#include "mausb_mgmt.h"
+#include "mausb_tx.h"
+#include "mausb_pkt.h"
+#include "mausb_const.h"
+#include "mausb_hcd.h"
+
+struct mausb_host_ep *mausb_state_to_ep(struct mausb_ep_state *state)
+{
+	return container_of(state, struct mausb_host_ep, state);
+}
+EXPORT_SYMBOL(mausb_state_to_ep);
+
+struct mausb_hcd *mausb_host_ep_to_mahcd(struct mausb_host_ep *ep)
+{
+	return ep->mausb_dev->ma_dev->mhcd;
+}
+EXPORT_SYMBOL(mausb_host_ep_to_mahcd);
+
+struct mausb_udc *mausb_host_ep_to_maudc(struct mausb_host_ep *ep)
+{
+	return ep->mausb_dev->ma_dev->maudc;
+}
+EXPORT_SYMBOL(mausb_host_ep_to_maudc);
+
+struct ma_dev *context_to_ma_dev(void *context)
+{
+	return (struct ma_dev *) context;
+}
+
+/*
+ * Finds the media-agnostic data for a given device.
+ *
+ * @ma_dev:	The MA USB device the USB device is located behind.
+ * @dev:	The USB device to find.
+ * @handle:	The MA USB device handle of USB device to find.
+ * @gadget:	The USB gadget device to find.
+ *
+ * Returns a pointer to the media agnostic data for a USB device given one or
+ * more parameters. Returns NULL if the device cannot be found.
+ */
+struct mausb_dev *mausb_find_dev(struct ma_dev *ma_dev,
+		struct usb_device *dev, unsigned long *handle,
+		struct usb_gadget *gadget)
+{
+	struct mausb_dev *mausb_dev;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags);
+	list_for_each_entry(mausb_dev, &ma_dev->dev_list, dev_list) {
+
+		/* if found */
+		if ((NULL != dev && mausb_dev->dev == dev) ||
+			(NULL != gadget && mausb_dev->gadget == gadget) ||
+			(NULL != handle && mausb_dev->dev_handle == *handle)) {
+			spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+			return mausb_dev;
+		}
+	}
+	spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+
+	/* device not found */
+	return NULL;
+}
+
+struct mausb_dev *mausb_find_dev_host(struct ma_dev *ma_dev,
+		struct usb_device *dev)
+{
+	return mausb_find_dev(ma_dev, dev, NULL, NULL);
+}
+EXPORT_SYMBOL(mausb_find_dev_host);
+
+/**
+ * Returns true if usb_endpoint descriptors are the same.
+ */
+static bool mausb_ep_desc_eq(const struct usb_endpoint_descriptor *desc1,
+		const struct usb_endpoint_descriptor *desc2)
+{
+	return ((desc1->bLength == desc2->bLength)
+		&& (desc1->bDescriptorType  == desc2->bDescriptorType)
+		&& (desc1->bEndpointAddress == desc2->bEndpointAddress)
+		&& (desc1->bmAttributes     == desc2->bmAttributes)
+		&& (desc1->wMaxPacketSize   == desc2->wMaxPacketSize));
+}
+
+/**
+ * Finds the media agnostic data for an endpoint given one or more parameters.
+ *
+ * @ep:			USB host endpoint to find MA USB endpoint for.
+ * @dev_ep:		USB device endpoint to find MA USB endpoint for.
+ * @handle:		Endpoint handle of MA USB endpoint.
+ * @mausb_dev:		The MA USB device the endpoint belongs to.
+ * @ep_desc:		endpoint descriptor for USB endpoint.
+ * @address:		MA USB endpoint address.
+ *
+ * Returns a pointer to the media agnostic data for the endpoint or NULL if
+ * the device cannot be found.
+ */
+static struct mausb_host_ep *mausb_find_ep(struct usb_host_endpoint *ep,
+		struct usb_ep *dev_ep, struct mausb_ep_handle *handle,
+		struct mausb_dev *mausb_dev,
+		const struct usb_endpoint_descriptor *ep_desc,
+		u8 address)
+{
+	struct mausb_host_ep *ma_ep;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&mausb_dev->dev_lock, irq_flags);
+	list_for_each_entry(ma_ep, &mausb_dev->ep_list, ep_list) {
+
+		/* if found */
+		if ((NULL != dev_ep && ma_ep->dev_ep == dev_ep) ||
+			(NULL != ep && ma_ep->ep == ep) ||
+			(NULL != handle
+			 && ma_ep->ep_handle_state != MAUSB_EP_HANDLE_UNASSIGNED
+			 && ma_ep->ep_handle.handle == handle->handle) ||
+			(NULL != ep_desc && NULL != ma_ep->ep
+			 && mausb_ep_desc_eq(ep_desc, &ma_ep->ep->desc)) ||
+			(NULL != ep_desc && NULL != ma_ep->dev_ep &&
+			 NULL != ma_ep->dev_ep->desc
+			 && mausb_ep_desc_eq(ep_desc, ma_ep->dev_ep->desc)) ||
+			(address != 0 && NULL != ma_ep->dev_ep &&
+			 address == ma_ep->dev_ep->address)) {
+
+			spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+			return ma_ep;
+		}
+	}
+
+	spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+
+	/* endpoint not found */
+	return NULL;
+}
+
+struct mausb_host_ep *mausb_find_ep_dev(struct usb_ep *dev_ep,
+			struct mausb_dev *mausb_dev)
+{
+	return mausb_find_ep(NULL, dev_ep, NULL, mausb_dev, NULL, 0);
+}
+EXPORT_SYMBOL(mausb_find_ep_dev);
+
+struct mausb_host_ep *mausb_find_ep_host(struct usb_host_endpoint *ep,
+	struct mausb_dev *mausb_dev)
+{
+	return mausb_find_ep(ep, NULL, NULL, mausb_dev, NULL, 0);
+}
+EXPORT_SYMBOL(mausb_find_ep_host);
+
+struct mausb_host_ep *mausb_find_ep_by_desc(
+	const struct usb_endpoint_descriptor *ep_desc,
+	struct mausb_dev *mausb_dev)
+
+{
+	return mausb_find_ep(NULL, NULL, NULL, mausb_dev, ep_desc, 0);
+}
+EXPORT_SYMBOL(mausb_find_ep_by_desc);
+
+struct mausb_host_ep *mausb_find_ep_by_handle(struct mausb_ep_handle *handle,
+	struct mausb_dev *mausb_dev)
+{
+	return mausb_find_ep(NULL, NULL, handle, mausb_dev, NULL, 0);
+}
+EXPORT_SYMBOL(mausb_find_ep_by_handle);
+
+struct mausb_host_ep *mausb_find_ep_by_address(u8 address,
+	struct mausb_dev *mausb_dev)
+
+{
+	return mausb_find_ep(NULL, NULL, NULL, mausb_dev, NULL, address);
+}
+EXPORT_SYMBOL(mausb_find_ep_by_address);
+
+struct mausb_host_ep *mausb_find_ep_from_handle(struct mausb_ep_handle handle,
+	struct ma_dev *ma_dev)
+{
+	struct mausb_host_ep *ma_ep;
+	struct mausb_dev *mausb_dev;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags);
+	list_for_each_entry(mausb_dev, &ma_dev->dev_list, dev_list) {
+		spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+
+		ma_ep = mausb_find_ep_by_handle(&handle, mausb_dev);
+		if (ma_ep != NULL)
+			return ma_ep;
+
+		spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags);
+	}
+	spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+
+	return NULL;
+}
+
+/**
+ * Wrapper function to be used by devices when they want to generate an
+ * ma packet.
+ */
+struct mausb_pkt *mausb_pkt_from_ms_pkt_ma_dev(struct ms_pkt *ms_pkt,
+	struct ma_dev *ma_dev, gfp_t mem_flags)
+{
+	return mausb_pkt_from_ms_pkt(ms_pkt,
+			ma_dev->ms_driver->ops->pkt_destructor, mem_flags);
+}
+EXPORT_SYMBOL(mausb_pkt_from_ms_pkt_ma_dev);
+
+/**
+ * Wrapper to be used by endpoints when they want to generate an ma packet.
+ */
+struct mausb_pkt *mausb_pkt_from_ms_pkt_ep(struct ms_pkt *ms_pkt,
+	struct mausb_host_ep *ep, gfp_t mem_flags)
+{
+	return mausb_pkt_from_ms_pkt_ma_dev(ms_pkt, ep->mausb_dev->ma_dev,
+		mem_flags);
+}
+EXPORT_SYMBOL(mausb_pkt_from_ms_pkt_ep);
+
+const struct usb_endpoint_descriptor *mausb_get_ep_des(
+		struct mausb_host_ep *ma_ep)
+{
+	if ((NULL != ma_ep->ep && NULL != ma_ep->dev_ep) ||
+	    (NULL == ma_ep->ep && NULL == ma_ep->dev_ep)) {
+
+		mamem_err("%s: ERROR: ep = 0x%p, dev_ep = 0x%p "
+			"(only one should be set)\n", __func__,
+			ma_ep->ep, ma_ep->dev_ep);
+
+		return NULL;
+	}
+
+	if (NULL != ma_ep->ep)
+		return &ma_ep->ep->desc;
+
+	if (NULL != ma_ep->dev_ep)
+		return ma_ep->dev_ep->desc;
+
+	/* We should never get here */
+	BUG();
+	return NULL;
+}
+EXPORT_SYMBOL(mausb_get_ep_des);
+
+/**
+ * Fills an MA USB packet header for the given maurb
+ */
+static int fill_mausb_dph(struct mausb_dph *ma_pkt, struct mausb_urb *maurb,
+		  bool in, bool host)
+{
+	const struct usb_endpoint_descriptor *ep_des;
+	unsigned long irq_flags;
+
+	/* set the version number */
+	ma_pkt->common.ver_flags =  MAUSB_VERSION_1_0 & MAUSB_VERSION_MASK;
+
+	/* set the host flag if from the host */
+	ma_pkt->common.ver_flags |= host ? MAUSB_PKT_FLAG_HOST : 0;
+
+	/* set the device handle field */
+	spin_lock_irqsave(&maurb->ep->ep_lock, irq_flags);
+	ma_pkt->common.ep_handle = maurb->ep->ep_handle;
+	spin_unlock_irqrestore(&maurb->ep->ep_lock, irq_flags);
+
+	ma_pkt->common.pkt_status = SUCCESS;
+
+	ep_des = mausb_get_ep_des(maurb->ep);
+
+	/* set transfer type in tflags field */
+	switch (usb_endpoint_type(ep_des)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		ma_pkt->eps_tflags |= MAUSB_PKT_TFLAG_TYPE_CTRL;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		ma_pkt->eps_tflags |= MAUSB_PKT_TFLAG_TYPE_ISOC;
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		ma_pkt->eps_tflags |= MAUSB_PKT_TFLAG_TYPE_BULK;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		ma_pkt->eps_tflags |= MAUSB_PKT_TFLAG_TYPE_INT;
+		break;
+	default:
+		mamem_err("%s: invalid transfer type\n", __func__);
+	}
+
+	return 0;
+}
+
+/**
+ * Create a datapacket from a given URB.
+ */
+struct mausb_pkt *mausb_create_dp(int *status, struct mausb_urb *maurb,
+	bool in, bool host, gfp_t memflags)
+{
+	struct mausb_pkt	*pkt;
+	int			ret = 0;
+
+	pkt = mausb_alloc_pkt(MAUSB_PKT_TYPE_DATA, status, memflags);
+	if (NULL == pkt) {
+		mamem_err("%s:failed to allocate memory for mausb packet\n",
+			__func__);
+
+		if (NULL != status)
+			*status = -ENOMEM;
+
+		return NULL;
+	}
+
+	ret = fill_mausb_dph(pkt->data, maurb, in, host);
+	INIT_LIST_HEAD(&pkt->pkt_list);
+	if (NULL != status)
+		*status = ret;
+
+	return pkt;
+}
+EXPORT_SYMBOL(mausb_create_dp);
+
+struct mausb_urb *mausb_alloc_maurb(struct mausb_host_ep *ma_ep, gfp_t memflags)
+{
+	struct mausb_urb     *maurb;
+
+	maurb = kzalloc(sizeof(struct mausb_urb), memflags);
+	if (!maurb)
+		return NULL;
+
+	INIT_LIST_HEAD(&maurb->urb_list);
+	maurb->ep = ma_ep;
+	maurb->dev = ma_ep->mausb_dev;
+
+	return maurb;
+}
+EXPORT_SYMBOL(mausb_alloc_maurb);
+
+/**
+ * Deletes the given maurb and removes all pointers to it from memory.
+ */
+int mausb_internal_drop_maurb(struct mausb_urb *maurb, struct mausb_hcd *mhcd)
+{
+	struct mausb_host_ep *ep = maurb->ep;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&ep->ep_lock, irq_flags);
+
+	list_del(&maurb->urb_list);
+	if (maurb == ep->active_transfer)
+		ep->active_transfer = NULL;
+
+	spin_unlock_irqrestore(&ep->ep_lock, irq_flags);
+
+	spin_lock_irqsave(&mhcd->urb_list_lock, irq_flags);
+	list_del(&maurb->ma_hcd_urb_list);
+	spin_unlock_irqrestore(&mhcd->urb_list_lock, irq_flags);
+
+	/*
+	 * Nobody else should know this maurb exists, so it should be
+	 * safe to free
+	 */
+	kfree(maurb);
+
+	return 0;
+}
+EXPORT_SYMBOL(mausb_internal_drop_maurb);
+
+/**
+ * Sets endpoint state to default.
+ *
+ * @state:	State of endpoint to be configured.
+ * @buf_size:	The maximum number of Bytes the device-side buffer
+ *              can receive from the host.
+ *
+ * Called whenever an MA USB endpoint is configured and needs to be set
+ * or reset to its initial state.
+ */
+void init_ep_state(struct mausb_ep_state *state, u32 buf_size)
+{
+	state->request_id = 0;
+	state->active_request_id = 0;
+	state->seq_number = 0;
+	state->tx_pending = 0;
+	state->earliest_request_id = 0;
+	state->earliest_unacked = 0;
+	state->occupancy = 0;
+	state->rx_buf_size = buf_size;
+	state->keep_alive_timer = MAUSB_TRANSFER_KEEP_ALIVE;
+	state->retry_counter = MAUSB_BULK_TRANSFER_RETRIES;
+	/* TODO: number of retries depends on transfer type, include
+	 * other transfer types (control and interrupt) */
+}
+
+struct mausb_gadget_ep *usb_ep_to_mausb_gadget_ep(struct usb_ep *ep)
+{
+	return container_of(ep, struct mausb_gadget_ep, dev_ep);
+}
+EXPORT_SYMBOL(usb_ep_to_mausb_gadget_ep);
+
+/**
+ * Links a Device-side endpoint to an MA USB endpoint
+ */
+void mausb_link_ma_ep_to_usb_ep(struct mausb_host_ep *ma_ep,
+		struct usb_ep *dev_ep)
+{
+	struct mausb_gadget_ep *gadget_ep = usb_ep_to_mausb_gadget_ep(dev_ep);
+
+	ma_ep->dev_ep = dev_ep;
+	ma_ep->halted = 0;
+	ma_ep->wedged = 0;
+
+	ma_ep->usb_req_list = &gadget_ep->usb_req_list;
+}
+EXPORT_SYMBOL(mausb_link_ma_ep_to_usb_ep);
+
+/*
+ * Adds an endpoint to the specified device.
+ *
+ * @ma_dev:		The usb device to add the endpoint to.
+ * @ep/dev_ep:		The usb struct for the endpoint being added.
+ *			Note: give only one of the endpoint pointers and
+ *                      set the other to NULL.
+ * @mausb_ep:		The mausb_ep struct created by this function.
+ * @transfer_timeout:	The transfer timeout function. A thread will be
+ *                      spawned with this function for handling timeouts.
+ *
+ * Adds the given endpoint to the given device. The difference between this
+ * function and mausb_add_endpoint (which can be called from the usb core)
+ * is that this uses the private ma-structs. Calling this function is
+ * cheaper, and therefore preferred when possible, since mausb_add_endpoint
+ * will have to find the internal structures.
+ */
+int mausb_internal_add_ep(struct mausb_dev *ma_dev,
+		struct usb_host_endpoint *ep, struct usb_ep *dev_ep,
+		struct mausb_host_ep **mausb_ep,
+		int (*transfer_timeout)(void *data), gfp_t memflags)
+{
+	struct mausb_host_ep *ma_ep;
+	unsigned long irq_flags;
+
+	ma_ep = kzalloc(sizeof(struct mausb_host_ep), memflags);
+	if (!ma_ep)
+		return -ENOMEM;
+
+	/* host operations */
+	if (ep != NULL) {
+		ep->hcpriv = ma_ep;
+		ma_ep->ep = ep;
+
+	/* device operations */
+	} else if (dev_ep != NULL)
+		mausb_link_ma_ep_to_usb_ep(ma_ep, dev_ep);
+
+	ma_ep->mausb_dev = ma_dev;
+
+	/* set initial EP State */
+	init_ep_state(&ma_ep->state, DEVICE_RX_BUF_SIZE);
+
+	/*
+	 * only used by full speed devices to determine if the max packet
+	 * size has changed for EP0
+	 */
+	ma_ep->max_pkt = 8;
+
+	/* initialize mausb_ep_handle */
+	ma_ep->ep_handle_state = MAUSB_EP_HANDLE_UNASSIGNED;
+
+	INIT_LIST_HEAD(&ma_ep->urb_list);
+	INIT_LIST_HEAD(&ma_ep->ep_list);
+	INIT_LIST_HEAD(&ma_ep->req_list);
+	INIT_LIST_HEAD(&ma_ep->resp_list);
+
+	spin_lock_init(&ma_ep->ep_lock);
+	ma_ep->tx_timed_out = false;
+
+	/* initialize endpoint work queue */
+	init_waitqueue_head(&ma_ep->host_ep_wq);
+
+	/* initialize endpoint timer */
+	setup_timer(&ma_ep->timer, wake_timeout_thread, (unsigned long) ma_ep);
+
+	/* add the endpoint to the device */
+	spin_lock_irqsave(&ma_dev->dev_lock, irq_flags);
+	list_add_tail(&ma_ep->ep_list, &ma_dev->ep_list);
+	spin_unlock_irqrestore(&ma_dev->dev_lock, irq_flags);
+
+	/* give a pointer to the ma_ep back to the caller */
+	if (NULL != mausb_ep)
+		*mausb_ep = ma_ep;
+
+	return 0;
+}
+EXPORT_SYMBOL(mausb_internal_add_ep);
+
+/**
+ * Drops the given endpoint from the given device. The difference between this
+ * function and mausb_drop_endpoint (which can be called from the usb core)
+ * is that this uses the private ma-structs. Calling this function is
+ * cheaper, and therefore preferred when possible, since mausb_drop_endpoint
+ * will have to find the internal endpoint structure.
+ */
+int mausb_internal_drop_ep(struct mausb_host_ep *ma_ep)
+{
+	struct mausb_dev *ma_dev;
+	struct mausb_request  *ma_request, *next_request;
+	struct mausb_pkt *ma_pkt, *next_pkt;
+	unsigned long     irq_flags;
+	unsigned long     irq_flags2;
+
+	if (NULL == ma_ep)
+		return -EINVAL;
+
+	/* drop all pending transfers */
+	spin_lock_irqsave(&ma_ep->ep_lock, irq_flags);
+	ma_dev = ma_ep->mausb_dev;
+
+	/* stop transfer timeout thread */
+	if (NULL != ma_ep->timeout_task)
+		kthread_stop(ma_ep->timeout_task);
+
+	/* drop all pending usb_requests (if there are any) */
+	if (NULL != ma_ep->usb_req_list) {
+		list_for_each_entry_safe(ma_request, next_request,
+					ma_ep->usb_req_list, usb_req_list) {
+			list_del(&ma_request->usb_req_list);
+			ma_request->req.status = -ESHUTDOWN;
+			ma_request->req.complete(ma_ep->dev_ep,
+							&ma_request->req);
+		}
+	}
+
+	/* flush out all of the stored request/response packets */
+	list_for_each_entry_safe(ma_pkt, next_pkt, &ma_ep->req_list, pkt_list) {
+		list_del(&ma_pkt->pkt_list);
+		mausb_free_pkt(ma_pkt);
+	}
+	list_for_each_entry_safe(ma_pkt, next_pkt,
+					&ma_ep->resp_list, pkt_list) {
+		list_del(&ma_pkt->pkt_list);
+		mausb_free_pkt(ma_pkt);
+	}
+
+	/* remove the endpoint from the list */
+	spin_lock_irqsave(&ma_dev->dev_lock, irq_flags2);
+	list_del(&ma_ep->ep_list);
+	spin_unlock_irqrestore(&ma_dev->dev_lock, irq_flags2);
+
+	spin_unlock_irqrestore(&ma_ep->ep_lock, irq_flags);
+
+	kfree(ma_ep);
+
+	return 0;
+}
+EXPORT_SYMBOL(mausb_internal_drop_ep);
+
+/**
+ * Updates the state of an endpoint based on the mausb_ep_des.
+ */
+int mausb_update_ep(struct mausb_host_ep *ma_ep,
+			struct mausb_ep_des *ma_ep_des)
+{
+	unsigned long     irq_flags;
+
+	spin_lock_irqsave(&ma_ep->ep_lock, irq_flags);
+
+	if (!ma_ep_des->valid) { /* Valid bit: 0 means valid */
+		ma_ep->ep_handle.handle = ma_ep_des->ep_handle.handle;
+		ma_ep->ep_handle_state = MAUSB_EP_HANDLE_ACTIVE;
+	}
+
+	if (ma_ep_des->dir == 0) {
+		ma_ep->state.rx_buf_size = ma_ep_des->buffer_size;
+
+
+		if (ma_ep_des->l_man)
+			ma_ep->lman_support = true;
+		else
+			ma_ep->lman_support = false;
+	}
+
+	/*TODO: parse and use the remainder of the values in the packet */
+
+	spin_unlock_irqrestore(&ma_ep->ep_lock, irq_flags);
+
+	return 0;
+}
+
+/**
+ * Allocates private per-usb-device data.
+ *
+ * @ma_dev:	The MA USB device to which the USB device belongs
+ * @usb_dev:	The host-side USB device struct to add.
+ * @gadget:	The device-side USB device struct to add.
+ *
+ * This function allocates a new device and adds it onto the MA USB device's
+ * linked list of usb devices. It also allocates endpoint data for the control
+ * endpoint (EP0).
+ */
+struct mausb_dev *mausb_internal_alloc_dev(struct ma_dev *ma_dev,
+		struct usb_device *dev, struct usb_gadget *gadget)
+{
+	unsigned long     irq_flags;
+	struct mausb_dev *mausb_dev;
+
+	mausb_dev = kzalloc(sizeof(struct mausb_dev), GFP_KERNEL);
+
+	if (!mausb_dev)
+		return NULL;
+
+	if (NULL != dev)
+		mausb_dev->dev = dev;
+	if (NULL != gadget)
+		mausb_dev->gadget = gadget;
+	mausb_dev->ma_dev = ma_dev;
+	INIT_LIST_HEAD(&mausb_dev->ep_list);
+	INIT_LIST_HEAD(&mausb_dev->dev_list);
+	spin_lock_init(&mausb_dev->dev_lock);
+
+	spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags);
+
+	/*
+	 * If this is the first device to be allocated, then it should be the
+	 * most upstream.
+	 */
+	if (NULL == ma_dev->top_dev)
+		ma_dev->top_dev = mausb_dev;
+
+	list_add_tail(&mausb_dev->dev_list, &ma_dev->dev_list);
+	spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+
+	return mausb_dev;
+}
+EXPORT_SYMBOL(mausb_internal_alloc_dev);
+
+/**
+ * Frees private per-device data.
+ *
+ * @ma_dev:	The MA USB device that the USB device beingfreed belongs to.
+ * @mausb_dev:	The MA USB data associated with the USB device being freed.
+ *
+ * This function removes a USB device from the MA USB hcd's linked list
+ * and releases the device's media agnostic data structure. All endpoints
+ * belonging to this device are also removed from the MA USB hcd and released
+ * (including EP0).
+ */
+int mausb_internal_free_dev(struct ma_dev *ma_dev, struct mausb_dev *mausb_dev)
+{
+	int			ret = 0;
+	unsigned long		irq_flags, irq_flags2;
+	struct mausb_host_ep	*ma_ep, *next;
+
+	/* remove all the endpoints from the device */
+	spin_lock_irqsave(&mausb_dev->dev_lock, irq_flags);
+	list_for_each_entry_safe(ma_ep, next, &mausb_dev->ep_list, ep_list) {
+		spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+		ret = mausb_internal_drop_ep(ma_ep);
+
+		spin_lock_irqsave(&mausb_dev->dev_lock, irq_flags);
+	}
+
+	if (!list_empty(&mausb_dev->ep_list)) {
+		spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+		return ret;
+	}
+
+	/* remove the mausb device from the ma device */
+	spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags2);
+	list_del(&mausb_dev->dev_list);
+
+	/* if the top device is being removed */
+	if (ma_dev->top_dev == mausb_dev)
+		ma_dev->top_dev = NULL;
+
+	spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags2);
+
+	spin_unlock_irqrestore(&mausb_dev->dev_lock, irq_flags);
+
+	kfree(mausb_dev);
+
+	return ret;
+
+}
+EXPORT_SYMBOL(mausb_internal_free_dev);
+
+/**
+ * Resets all the data in a ma_dev struct. This includes freeing all the MA
+ * data for the usb devices and endpoints connected to this device.
+ */
+int mausb_internal_reset_ma_dev(struct ma_dev *ma_dev, __u8 ma_dev_addr,
+	__u8 mass_id, struct mausb_hcd *mhcd, struct mausb_udc *maudc)
+{
+	int			ret = -EINVAL;
+	struct mausb_dev	*mausb_dev, *mausb_next;
+	int (*req_switch)(struct mausb_mgmt_pkt *req,
+			  struct mausb_mgmt_pkt *resp,
+			  struct mausb_mgmt *mgmt)
+		= ma_dev->mgmt.req_switch;
+	int (*device_connect)(int) = ma_dev->ma_drv.device_connect;
+	unsigned long irq_flags;
+
+	if (NULL != mhcd)
+		ma_dev->mhcd = mhcd;
+
+	if (NULL != maudc)
+		ma_dev->maudc = maudc;
+
+	spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags);
+	list_for_each_entry_safe(mausb_dev, mausb_next, &ma_dev->dev_list,
+				dev_list) {
+		spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+
+		ret = mausb_internal_free_dev(ma_dev, mausb_dev);
+
+		spin_lock_irqsave(&ma_dev->ma_dev_lock, irq_flags);
+	}
+
+	if (!list_empty(&ma_dev->dev_list)) {
+		/* could not clear all the devices */
+		ret = -EAGAIN;
+	}
+
+	spin_unlock_irqrestore(&ma_dev->ma_dev_lock, irq_flags);
+
+	/* TODO: make sure this doesn't break any locking rules */
+	mausb_init_ma_device(ma_dev, ma_dev_addr, mass_id, mhcd,
+			     maudc, req_switch, device_connect);
+
+	return ret;
+}
+
+/**
+ * Initializes the media agnostic management structure.
+ */
+int mausb_init_mgmt(struct mausb_mgmt *mgmt, spinlock_t *ma_dev_lock,
+		int (*req_switch)(struct mausb_mgmt_pkt *req,
+		struct mausb_mgmt_pkt *resp, struct mausb_mgmt *mgmt))
+{
+	INIT_LIST_HEAD(&mgmt->req_list);
+	mgmt->token = 0;
+	mgmt->tx_pair.to_ms.context = NULL;
+	mgmt->tx_pair.to_ms.transfer_packet = NULL;
+	mgmt->tx_pair.to_ma.context = NULL;
+	mgmt->tx_pair.to_ma.transfer_packet = NULL;
+	mgmt->hub_dev_handle = 0;
+	mgmt->ma_dev_lock = ma_dev_lock;
+	mgmt->req_switch = req_switch;
+
+	return 0;
+}
+
+static void mausb_init_pkt_dmux(struct mausb_pkt_transfer *pkt_dmux,
+		void *context)
+{
+	pkt_dmux->transfer_packet = &mausb_pkt_dmux;
+	pkt_dmux->context = context;
+}
+
+/*
+ * Initializes the data structure for an MA USB device.
+ */
+int mausb_init_ma_device(struct ma_dev *ma_dev, __u8 ma_dev_addr, __u8 mass_id,
+		struct mausb_hcd *mhcd, struct mausb_udc *maudc,
+		int (*req_switch)(struct mausb_mgmt_pkt *req,
+		struct mausb_mgmt_pkt *resp, struct mausb_mgmt *mgmt),
+		int (*device_connect)(int))
+{
+	INIT_LIST_HEAD(&ma_dev->dev_list);
+	ma_dev->top_dev = NULL;
+	ma_dev->ma_dev_addr = ma_dev_addr;
+	ma_dev->mass_id = mass_id;
+	if (mhcd != NULL)
+		ma_dev->mhcd = mhcd;
+	if (maudc != NULL)
+		ma_dev->maudc = maudc;
+	spin_lock_init(&ma_dev->ma_dev_lock);
+	ma_dev->ma_drv.device_connect = device_connect;
+	mausb_init_pkt_dmux(&ma_dev->ma_drv.pkt_dmux, ma_dev);
+
+	mausb_init_mgmt(&ma_dev->mgmt, &ma_dev->ma_dev_lock, req_switch);
+
+	return 0;
+}
+EXPORT_SYMBOL(mausb_init_ma_device);
+
diff --git a/drivers/staging/mausb/drivers/mausb_mem.h b/drivers/staging/mausb/drivers/mausb_mem.h
new file mode 100644
index 0000000..870591f
--- /dev/null
+++ b/drivers/staging/mausb/drivers/mausb_mem.h
@@ -0,0 +1,509 @@
+/* Name:	mausb_mem.h
+ * Description: Header for mausb_mem.c. Needed do make calls to
+ *              functions defined in mausb_mem.c.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Contact Information:
+ * Sean Stalley, sean.stalley@xxxxxxxxx
+ * Stephanie Wallick, stephanie.s.wallick@xxxxxxxxx
+ * 2111 NE 25th Avenue
+ * Hillsboro, Oregon 97124
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MAUSB_MEM_H
+#define __MAUSB_MEM_H
+
+#include "mausb_state.h"
+#include "mausb_pkt.h"
+#include "mausb_msapi.h"
+
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/gadget.h>
+#include <linux/timer.h>
+
+#ifdef DEBUG
+#define mamem_dbg(format, arg...) \
+	printk(KERN_DEBUG format, ##arg)
+#else
+#define mamem_dbg(format, arg...)
+#endif
+
+#define mamem_warn(format, arg...) \
+	printk(KERN_WARNING format, ##arg)
+
+#define mamem_err(format, arg...) \
+	printk(KERN_ERR format, ##arg)
+
+/* forward declarations */
+struct mausb_urb;
+struct mausb_pkt;
+struct mausb_host_ep;
+
+/**
+ * mausb_mgmt - MAUSB management datastrucure
+ *
+ * Contains all the data necessary to handle management packets.
+ *
+ * @req_list:		List of all currently pending management requests for
+ *			this device.
+ * @token:		The value of the token field in the most recently sent
+ *			management request.
+ * @tx_pair:		Indicates where management packets should be sent.
+ *
+ * The following variables are to store common management packet fields:
+ *
+ * @hub_dev_handle:	Device Handle of the MAUSB Dock hub. used for
+ *                  	USBDevHandleReq packets.
+ * @ma_dev_lock:	The spinlock which protects the management data in this
+ *			struct.
+ * @req_switch:		The host or devices request switch. It accepts an
+ * 			incoming request, makes the necessary calls, and
+ *			returns a partially completed response (it fills the
+ *			response type, status & any data fields specific to
+ *			that response). the remainder of the fields are
+ *			completed by mausb_rx_mgmt_req.
+ */
+struct mausb_mgmt {
+	struct list_head		req_list;
+	__u16				token:10;
+	struct mausb_transfer_pair	tx_pair;
+	__u16				hub_dev_handle;
+	spinlock_t			*ma_dev_lock;
+	int (*req_switch)(struct mausb_mgmt_pkt *req,
+			struct mausb_mgmt_pkt *resp, struct mausb_mgmt *mgmt);
+};
+
+/**
+ * mausb_mgmt_req_list - MAUSB management request list entry
+ *
+ * An entry in the mausb_mgmt request linked list.
+ *
+ * @req_list:	Pointers to other entries in the list.
+ * @mgmt_req:	The request management packet.
+ * @mgmt_resp:	The response management packet, set to NULL until a response
+ *		is received.
+ * @resp_rcvd:	An event triggered when the response is received.
+ */
+struct mausb_mgmt_req_list {
+	struct list_head	req_list;
+
+	struct mausb_pkt	*mgmt_req;
+	struct mausb_pkt	*mgmt_resp;
+
+	struct completion	resp_rcvd;
+};
+
+/**
+ * Media Agnostic Session State
+ *
+ * Defines the current state of the session between the host & device.
+ * Per MAUSB spec, sections 7.1 & 8.1.1.
+ */
+enum mausb_session_state {
+	MAUSB_SESSION_DOWN,
+	MAUSB_SESSION_CONNECTING,
+	MAUSB_SESSION_ACITVE,
+	MAUSB_SESSION_INACTIVE
+};
+
+/**
+ * stores information returned in a CapResp packet
+ */
+struct ma_capability {
+	__u16		num_ep;
+	__u8		num_dev;
+	__u8		num_stream:5;
+	__u8		dev_type:3;
+	__u16		max_tx_reqs;
+	__u16		max_mgmt_reqs:12;
+};
+
+/**
+ * MA device data
+ *
+ * This structure is used to hold MA device-specific data
+ * (i.e. one instance of this structure exists per MA device).
+ *
+ * @mgmt:		Contains the data needed to keep track of the device's
+ *			management packets.
+ * @dev_list:		Stores a list of the devices connected to this HCD.
+ *			This includes any internal mausb data that exists on
+ *			a per-device, per-endpoint, or per-transfer basis.
+ * @top_dev:		The most upstream mausb device. Used to determine
+ *			where to send MA USB device management packets (such as
+ *			MAUSBDevSleepReq and MAUSBDevWakeReq).
+ * @session_state:	Defines the current state of the session between the
+ *			host and device. Per MAUSB spec, sections 7.1 & 8.1.1.
+ * @ma_dev_addr: 	MA Device Address. Assigned by the host via a
+ *               	MAUSBDevResetReq.
+ * @mass_id:		Media-Agnostic Service Set Identifier. Assigned by the
+ *			host via a MAUSBDevResetReq.
+ * @ma_dev_lock:	Spinlock for this device. This lock should be held
+ *			before accessing any data in this structure.
+ * @ma_drv:		Media agnostic driver interfaces.
+ * @ms_drv:		Media specific driver interfaces.
+ * @ma_cap:		Stores MA device info from CapResp packet fields.
+ * @speed:		Stores MA device info from speed capability descriptor.
+ * @pout:		Stores MA device info from P-managed OUT capability
+ *			descriptor.
+ * @iso:		Stores MA device info from isochronous capabilities
+ *			descriptor.
+ * @synch:		Stores MA device info from synchronization capabilities
+ *			descriptor.
+ * @cont_id:		Stores MA device info from container ID capability
+ *			descriptor.
+ * @link_sleep:		Stores MA device info from link sleep capability
+ *			descriptor.
+ */
+struct ma_dev {
+	struct mausb_mgmt		mgmt;
+	struct list_head		dev_list;
+	struct mausb_dev		*top_dev;
+	enum mausb_session_state	session_state;
+	__u8				ma_dev_addr:7;
+	__u8				mass_id;
+	spinlock_t			ma_dev_lock;
+
+	union {
+		struct mausb_hcd *mhcd;
+		struct mausb_udc *maudc;
+	};
+
+	struct mausb_ma_drv		ma_drv;
+	struct mausb_ms_drv		*ms_driver;
+
+	struct ma_capability		ma_cap;
+	struct mausb_dev_cap_speed	*speed;
+	struct mausb_dev_cap_pout	*pout;
+	struct mausb_dev_cap_iso	*iso;
+	struct mausb_dev_cap_sync	*sync;
+	struct mausb_dev_cap_cont_id	*cont_id;
+	struct mausb_dev_cap_link_sleep *link_sleep;
+};
+
+/**
+ * MA USB device data
+ *
+ * This structure is used to hold device-pecific data
+ * (i.e. one instance of this structure exists per usb device).
+ *
+ * @dev:		A pointer to the kernel's usb device structure. Can be
+ *			used to uniquely identify a device.
+ * @gadget:		A pointer to the kernel's usb gadget structure.
+ * @ma_dev:		Pointer to parent ma_dev structure.
+ * @ep_list:		A linked list of all the endpoints for this device.
+ *              	MAUSBDevHandleResp packet.
+ * @dev_handle:		MA USB device handle for this device
+ * @dev_address:	The usb device address. set by the ma_dev.
+ *               	NOTE: this is not the same as the address given by
+ *			the kernel.
+ * @dev_list:		A linked list of all the devices in the HCD.
+ * @dev_lock:		Spinlock for this device. This lock should be held
+ * 			before accessing any data in this structure.
+ */
+struct mausb_dev {
+	union {
+		struct usb_device *dev;	   /* Host only */
+		struct usb_gadget *gadget; /* Device only */
+	};
+	struct ma_dev     *ma_dev;
+	struct list_head   ep_list;
+	__u16              dev_handle;
+	__u8               dev_address;
+	struct list_head   dev_list;
+	spinlock_t         dev_lock;
+};
+
+/**
+ * MAUSB Endpoint Handle State Variables
+ *
+ * Defines the states for an MA USB Endpoint Handle.
+ *
+ * Per MAUSB spec, seciton 7.2
+ *
+ * Note: MAUSB_EP_HANDLE_DELETED is used to flag an endpoint for deletion
+ *       it is not per spec; endpoints in this state should not be used and
+ *       will be deleted in the next EPHandleDeleteReq.
+ */
+enum mausb_ep_handle_state {
+	MAUSB_EP_HANDLE_UNASSIGNED = 0,
+	MAUSB_EP_HANDLE_ACTIVE,
+	MAUSB_EP_HANDLE_INACTIVE,
+	MAUSB_EP_HANDLE_HALTED,
+	MAUSB_EP_HANDLE_DELETED
+};
+
+/**
+ * MA USB host-side endpoint data
+ *
+ * This structure is used to hold endpoint-specific data
+ * (i.e. one instance of this structure exists per endpoint).
+ *
+ * The following data is protected by the devices's dev_lock:
+ *
+ * @ep: 	Used only by the host side. A pointer to the kernel's host-side
+ *      	endpoint structure. Can be used to uniquely identify an
+ *		endpoint. Note: the HCD probably shouldn't read or write
+ *		anything from the usb_host_endpoint structure, since it belongs
+ *		to the kernel.
+ * @dev_ep:	Used only by the device side. A pointer to the kernel's
+ *          	device-side endpoint structure.
+ * @ep_list:	A linked list of all the endpoints connected to the same
+ *           	device.
+ *
+ * The following data is protected by the endpoint's ep_lock:
+ *
+ * @state:		The MA USB state variables for this endpoint. Per
+ *			MA USB Spec, sections 5.4.1 and 5.5.2.
+ * @active_transfer:	Urb that maps to the transfer in progress.
+ * @ep_handle:		The endpoint handle to be used by packets for this
+ *			endpoint per MA USB Spec, section 6.2.1.5.
+ * @ep_handle_state:	Defines the states an Endpoint Handle can be in.
+ *                   	Per MA USB Spec, section 7.2.
+ * @buffer:		Buffer that holds data going to/from a host during
+ *			transfer.
+ * @actual_length:	Length of buffer.
+ * @lman_support:	For control or non-iso OUT endpoints. Indicates if
+ *                	link-managed tranfers are supported. Not valid until
+ *                	an EPHandleResp is received for this endpoint.
+ * @control_dir:	Control endpoints only; used to determine the direction
+ *               	of the current transfer.
+ * @ccu:		The credit conumption unit, in bytes. Per MA USB Spec,
+ *			table 27.
+ * @mausb_dev:		The device the endpoint belongs to.
+ * @urb_list:		A linked list of all URBs pending for this endpoint.
+ *            		URBs map one-to-one with MAUSB Transfers, so each entry
+ *            		also represents an MA USB Transfer.
+ * @usb_req_list:	Only used on the device side. A linked list of all
+ *                	usb_requests submitted to this endpoint.
+ * @req_list:		Head of list of created transferRequests and
+ *	      		transferAck packets.
+ * @resp_list:		Head of list of received transferResponses packets.
+ * @ep_lock:		Spinlock for this endpoint. This lock should be held
+ *			before accessing any data in this structure.
+ * @timer:		Endpoint timer structure, used to monitor transfer
+ *			timeouts.
+ * @timeout_task:	Thread used to perform packet resends after transfer
+ *			timeout.
+ * @host_ep_wq:		Work queue for timeout thread to wait on while sleeping.
+ * @tx_timed_out:	Used to flag when a timeout event has occured during
+ *			a transfer.
+ * @tx_pair:		Transfer pair for this endpoint.
+ * @gadget:		USB gadget associated with this endpoint.
+ * @busy:		True if this endpoint is busy, otherwise false.
+ * @halted:		1 if endpoint is halted, otherwise 0.
+ * @wedged:		1 if endpoint is wedged, otherwise 0.
+ * @stream_en:		1 if streams are enabled for this endpoint, otherwise 0.
+ * @max_pkt:		Max packet size for this endpoint.
+ */
+struct mausb_host_ep {
+
+	struct usb_host_endpoint	*ep; 	 /* Host only */
+	struct usb_ep			*dev_ep; /* Device only */
+	struct list_head		ep_list;
+	struct mausb_ep_state		state;
+	struct mausb_urb		*active_transfer;
+	struct mausb_ep_handle		ep_handle;
+	enum mausb_ep_handle_state	ep_handle_state;
+	void				*buffer;
+	u32				actual_length;
+	bool				lman_support;
+	bool				control_dir;
+	u16				ccu;
+	struct mausb_dev		*mausb_dev;
+	struct list_head		urb_list;
+	struct list_head		*usb_req_list;
+	struct list_head		req_list;
+	struct list_head		resp_list;
+	spinlock_t			ep_lock;
+	struct timer_list		timer;
+	struct task_struct		*timeout_task;
+	wait_queue_head_t		host_ep_wq;
+	bool				tx_timed_out;
+	struct mausb_transfer_pair	tx_pair;
+	struct usb_gadget		*gadget; /* Device only */
+	bool				busy;
+	unsigned			halted:1;
+	unsigned			wedged:1;
+	unsigned			stream_en:1;
+	u16                             max_pkt;
+};
+
+/**
+ * endpoint request structure - describes one I/O request
+ *
+ * @usb_ep:	A device-side endpoint structure.
+ * @queue:	The list of all requests currently enqueued to this endpoint.
+ */
+struct mausb_gadget_ep {
+	struct usb_ep dev_ep;
+	struct list_head usb_req_list;
+};
+
+/**
+ * MA USB urb structure
+ *
+ * Stores MAUSB-specific urb data. In our implementation, one urb from usb
+ * core maps to exactly one MA USB transfer. When an urb is submitted, it
+ * queues a new transfer. When a transfer is complete (or fails), the urb
+ * is given back to the core.
+ *
+ * All data listed in this structure is protected by the ep_lock.
+ * If you want to use any of this data, you need to be in posession
+ * of this lock.
+ *
+ * @urb:		Used only on the host side. The urb submitted to the
+ *			HCD by usbcore.
+ * @usb_request_list:	Used only on the device side. A pointer to the list of
+ *                    	msusb_requests for this endpoint.
+ * @urb_list:		Connects this mausb_urb with other mausb_urbs
+ *			queued to the same endpoint.
+ * @ma_hcd_urb_list:	Connects this urb to urbs queued to the same ma hcd.
+ * @state:		Current state of the transfer as defined in the
+ *			MA USB Spec.
+ * @ep:			The endpoint that the transfer belongs to.
+ * @dev:		The device that the transfer belongs to.
+ * @transfer_size:	Total number of bytes for transfer associated with urb.
+ */
+struct mausb_urb {
+	struct urb			*urb;		   /* Host Only */
+	struct list_head		*usb_request_list; /* Device Only */
+	struct list_head		urb_list;
+	struct list_head		ma_hcd_urb_list;
+	struct mausb_transfer_state	state;
+	struct mausb_host_ep		*ep;
+	struct mausb_dev		*dev;
+	unsigned int			transfer_size;
+};
+
+/**
+ * endpoint request structure - describes one I/O request
+ *
+ * @req:		The usb_request struct. Enqueuing a usb_request is
+ *			what triggers the creation of this struct.
+ * @usb_req_list:	List of all requests enqueued at this endpoint.
+ */
+struct mausb_request {
+	struct usb_request req;
+	struct list_head   usb_req_list;
+};
+
+/* endpoint/device helper functions */
+struct mausb_host_ep *usb_to_ma_endpoint(struct usb_host_endpoint *ep);
+int mausb_hcd_urb_count(struct mausb_hcd *mhcd);
+
+#define MAUSB_ADD  true
+#define MAUSB_DEL  false
+#define MAUSB_DEV  false
+#define MAUSB_HOST true
+#define MAUSB_OUT  false
+#define MAUSB_IN   true
+struct mausb_pkt *mausb_create_dp(int *status, struct mausb_urb *maurb,
+		bool in, bool host, gfp_t memflags);
+
+/* endpoint/device memory management functions */
+struct mausb_host_ep *mausb_state_to_ep(struct mausb_ep_state *state);
+struct ma_dev *context_to_ma_dev(void *context);
+struct mausb_hcd *mausb_host_ep_to_mahcd(struct mausb_host_ep *ep);
+struct mausb_udc *mausb_host_ep_to_maudc(struct mausb_host_ep *ep);
+struct mausb_dev *usb_dev_to_mausb_dev(struct usb_device *udev);
+struct mausb_host_ep *mausb_find_ep_dev(struct usb_ep *dev_ep,
+		struct mausb_dev *mausb_dev);
+struct mausb_host_ep *mausb_find_ep_host(struct usb_host_endpoint *ep,
+		struct mausb_dev *mausb_dev);
+struct mausb_host_ep *mausb_find_ep_by_handle(struct mausb_ep_handle *handle,
+		struct mausb_dev *mausb_dev);
+struct mausb_host_ep *mausb_find_ep_from_handle(struct mausb_ep_handle handle,
+		struct ma_dev *ma_dev);
+struct mausb_pkt *mausb_pkt_from_ms_pkt_ma_dev(struct ms_pkt *ms_pkt,
+		struct ma_dev *ma_dev, gfp_t mem_flags);
+struct mausb_pkt *mausb_pkt_from_ms_pkt_ep(struct ms_pkt *ms_pkt,
+		struct mausb_host_ep *ep, gfp_t mem_flags);
+struct mausb_dev *mausb_find_dev(struct ma_dev *ma_dev, struct usb_device *dev,
+		unsigned long *handle, struct usb_gadget *gadget);
+struct mausb_dev *mausb_find_dev_host(struct ma_dev *ma_dev,
+		struct usb_device *dev);
+struct mausb_host_ep *mausb_find_ep_by_desc(
+		const struct usb_endpoint_descriptor *ep_desc,
+		struct mausb_dev *mausb_dev);
+struct mausb_host_ep *mausb_find_ep_by_address(u8 address,
+		struct mausb_dev *mausb_dev);
+struct mausb_urb *mausb_alloc_maurb(struct mausb_host_ep *ma_ep,
+		gfp_t memflags);
+int mausb_internal_drop_maurb(struct mausb_urb *maurb, struct mausb_hcd *mhcd);
+void init_ep_state(struct mausb_ep_state *state, u32 buf_size);
+int mausb_activate_endpoints(struct mausb_dev *mausb_dev);
+void mausb_link_ma_ep_to_usb_ep(struct mausb_host_ep *ma_ep,
+		struct usb_ep *dev_ep);
+struct mausb_gadget_ep *usb_ep_to_mausb_gadget_ep(struct usb_ep *ep);
+int mausb_internal_add_ep(struct mausb_dev *ma_dev,
+		struct usb_host_endpoint *ep, struct usb_ep *dev_ep,
+		struct mausb_host_ep **mausb_ep,
+		int (*transfer_timeout)(void *data), gfp_t memflags);
+int mausb_internal_drop_ep(struct mausb_host_ep *ma_ep);
+int mausb_update_ep(struct mausb_host_ep *ma_ep,
+		struct mausb_ep_des *ma_ep_des);
+struct mausb_dev *mausb_internal_alloc_dev(struct ma_dev *ma_dev,
+		struct usb_device *dev, struct usb_gadget *gadget);
+int mausb_internal_free_dev(struct ma_dev *ma_dev,
+		struct mausb_dev *mausb_dev);
+int mausb_internal_reset_ma_dev(struct ma_dev *ma_dev, __u8 ma_dev_addr,
+		__u8 mass_id, struct mausb_hcd *mhcd, struct mausb_udc *maudc);
+int mausb_init_ma_device(struct ma_dev *ma_dev, __u8 ma_dev_addr, __u8 mass_id,
+		struct mausb_hcd *mhcd, struct mausb_udc *maudc,
+		int (*req_switch)(struct mausb_mgmt_pkt *req,
+		struct mausb_mgmt_pkt *resp, struct mausb_mgmt *mgmt),
+		int (*device_connect)(int));
+int mausb_init_mgmt(struct mausb_mgmt *mgmt, spinlock_t *ma_dev_lock,
+		int (*req_switch)(struct mausb_mgmt_pkt *req,
+		struct mausb_mgmt_pkt *resp, struct mausb_mgmt *mgmt));
+const struct usb_endpoint_descriptor *mausb_get_ep_des(
+		struct mausb_host_ep *ma_ep);
+
+#endif
diff --git a/drivers/staging/mausb/drivers/mausb_state.h b/drivers/staging/mausb/drivers/mausb_state.h
new file mode 100644
index 0000000..01f0171
--- /dev/null
+++ b/drivers/staging/mausb/drivers/mausb_state.h
@@ -0,0 +1,184 @@
+/* Name:	mausb_state.h
+ * Description: Contains all of the state variables for hosts and devices as
+ *              defined by the MAUSB spec.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Contact Information:
+ * Sean Stalley, sean.stalley@xxxxxxxxx
+ * Stephanie Wallick, stephanie.s.wallick@xxxxxxxxx
+ * 2111 NE 25th Avenue
+ * Hillsboro, Oregon 97124
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MAUSB_STATE_H
+#define __MAUSB_STATE_H
+
+/**
+ * MAUSB endpoint state variables, per MA USB Spec sections 5.4.1 & 5.5.2.
+ *
+ * Note: this struct contains the fields necessary to store the state on both
+ * the host and device side.
+ *
+ * @seq_number:		For a sender, this field contains the sequence number
+ *			that should be placed in the next outgoing packet.
+ *              	For a receiver, this field contains the sequence number
+ *              	expected in the next incoming packet.
+ * @keep_alive_timer:	Timeout counter. Set to aMausbTransferKeepAlive
+ *                    	upon a new transfer initialization. To be decremented
+ *                    	every aMAUSBTransferTimeTick interval. If the timer
+ *                    	reaches 0, A retry is triggered.
+ * @retry_counter: 	Indicates how many more times the
+ *                 	transfer will be attempted. Decremented upon a timeout
+ *                 	(see keep_alive_timer for details). If this counter
+ *                 	reaches 0, the transfer fails due to a timeout.
+ * @request_id: 	Request ID number. for IN transfers,  all
+ *			transfer_request packets currently being sent or
+ *			received should have this request ID number. for OUT
+ *			transfers, All transfer_request and transfer_ack
+ *			packets currently being sent or received should have
+ *			this request ID number.
+ * @active_request_id: 	Active Request ID number. used by IN transfers only.
+ *                     	All transfer_ack packets being sent/received should
+ *                     	contain this number.
+ * @earliest_unacked: 	Stores the sequence number of the most recent packet
+ *                    	that has been sent out but has not been acknowledged
+ *                    	by the receiver.
+ * @rx_buf_size: 	Receiver Buffer Size. Used for OUT transfers only.
+ *			Indicates the available buffer space for packets in the
+ *			device (in bytes).
+ *			Note: this value is signed for the host and
+ *			unsigned for the receiver. A negative number
+ *			indicates a buffer overflow.
+ *			Note: defined in spec as a 25-bit signed int
+ *			for a host and a 32-bit unsigned for a device.
+ * @occupancy: 		Size (in bytes) of the payload accepted into the receive
+ *             		buffer. Used only on the device side for OUT transfers.
+ * @earliest_request_id:Request ID of earliest transferReq whose state
+ *			needs to be tracked (host IN).
+ * @transfer_retries:	Reload value for retry_counter. Should be set to
+ *		      	a ControlTransferRetries, aBulkTransferRetries,
+ *		      	or aInterruptTransferRetries depending on transfer
+ *		      	type.
+ * @delayed:		Set to true if the interval between two sucessive
+ *			transferResp packets exceeds aTransferRepeatTime.
+ * @tx_pending: 	Set to 1 when a transfer is in progress, otherwise it
+ *			should be zero. A new transfer cannot be started until
+ *			this flag is cleared.
+ */
+struct mausb_ep_state {                      /* HOST     | DEVICE       */
+
+	unsigned int seq_number:24;          /* IN | OUT | IN | OUT     */
+	int 	     keep_alive_timer;       /* IN | OUT | IN | OUT     */
+	unsigned int retry_counter;          /* IN | OUT | IN | OUT     */
+	__u8         request_id;             /* IN | OUT | IN | OUT     */
+	__u8         active_request_id;      /* IN | OUT | IN |         */
+	unsigned int earliest_unacked:24;    /*    | OUT | IN | OUT     */
+	__u32        rx_buf_size;            /*    | OUT |    | OUT     */
+	unsigned int occupancy;              /*    |     |    | OUT     */
+	u8	     earliest_request_id;    /* IN | OUT | IN | OUT     */
+	unsigned int transfer_retries;       /* IN | OUT | IN | OUT     */
+	bool	     delayed;                /*    |     | IN |         */
+
+	/* TODO: add response_timer (device IN and OUT/host OUT) */
+
+	unsigned int tx_pending:1;       /* beyond spec */
+};
+
+/**
+ * MA USB transfer state variables, per section 5.4.1 & 5.5.2.
+ *
+ * In our implementation, URBs and MAUSB transfers map one-to-one,
+ * so the transfer state and the urb state are one in the same.
+ *
+ * @rem_size:		The remaining transfer size (in bytes). This value is
+ *			set at the beginning of a transfer and is decremented
+ *			as data is received.
+ * @payload_size:	Payload size for out transfer (in bytes). For MA USB
+ *			host, it indicates the overall transfered OUT payload
+ *			size for the current urb. For MA USB device, It
+ *			indicates the received OUT payload size for the
+ *			current MA USB OUT request.
+ * @transfer_error:	A boolean which is only set to TRUE when a
+ *			non-recoverable error is detected in the transfer.
+ * @transfer_complete: 	A boolean which is only set to TRUE when a transfer
+ *                     	is evaluated to be complete. (ie. the final ACK has
+ *                     	has been sent/received).
+ * @eot_detected: 	A boolean which is only set to TRUE when a transfer
+ *                	is complete (ie: all the data has been transferred).
+ *                	Note: eot_detected & transfer_complete differ in when
+ *                	they are set. eot_detected is sent after the last data
+ *                	packet received, transfer_complete is set after the
+ *			final ACK.
+ * @last_transfer_sn: 	Last Transfer Sequence Number. Stores the sequence
+ *                    	number of the final packet of this transfer.
+ * @transfer_acked:	Set to true when a transferReq or transferAck packet is
+ *                  	released to the data channel acknowledging the last
+ *		    	transferResp belonging to a transfer.
+ * @k:			A  transfer-dependent multiplicative factor used to
+ *			reload keep_alive_timer when a transfer has a status
+ *			of TRANSFER_PENDING.
+ * @ack_transfer_sn:	The value of the sequence number in the last
+ *                   	transferReq packet that belongs to the transfer and
+ *                   	has the ARQ field set to 1.
+ */
+struct mausb_transfer_state {             /* HOST     | DEVICE       */
+
+	__u32        rem_size;            /* IN | OUT | IN | OUT     */
+	__u32        payload_size;        /* IN | OUT | IN | OUT     */
+	bool         transfer_error;      /* IN | OUT | IN | OUT     */
+	bool         transfer_complete;   /* IN | OUT | IN | OUT     */
+	bool         eot_detected;        /* IN |     | IN | OUT     */
+	unsigned int last_transfer_sn:24; /* IN |     | IN |         */
+	bool         transfer_acked;      /* IN | OUT |    |         */
+	unsigned int k;                   /* IN |     |    |         */
+	unsigned int ack_transfer_sn:24;  /*    | OUT |    |         */
+
+	/*TODO: add transfer_completion_timer (host IN) */
+};
+
+#endif
-- 
1.9.1

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux