Commit 90ff96f2 authored by Inaky Perez-Gonzalez's avatar Inaky Perez-Gonzalez Committed by David Vrabel

wusb: add the Wireless USB core

Add support for Ceritified Wireless USB 1.0 to the USB stack.

This has been split into several patches for easier review.

core (this patch):
  - host controller infrastructure
  - cluster reservation
  - UWB PAL registration
  - fake root hub

protocol:
  - MMC management (start/stop, managing IEs)
  - device connection

security:
  - device authentication and authorization

build-system:
  - Kconfig and Kbuild files
Signed-off-by: default avatarDavid Vrabel <david.vrabel@csr.com>
parent c7f73648
/*
* WUSB devices
* sysfs bindings
*
* Copyright (C) 2007 Intel Corporation
* Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*
* Get them out of the way...
*/
#include <linux/jiffies.h>
#include <linux/ctype.h>
#include <linux/workqueue.h>
#include "wusbhc.h"
#undef D_LOCAL
#define D_LOCAL 4
#include <linux/uwb/debug.h>
static ssize_t wusb_disconnect_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct usb_device *usb_dev;
struct wusbhc *wusbhc;
unsigned command;
u8 port_idx;
if (sscanf(buf, "%u", &command) != 1)
return -EINVAL;
if (command == 0)
return size;
usb_dev = to_usb_device(dev);
wusbhc = wusbhc_get_by_usb_dev(usb_dev);
if (wusbhc == NULL)
return -ENODEV;
mutex_lock(&wusbhc->mutex);
port_idx = wusb_port_no_to_idx(usb_dev->portnum);
__wusbhc_dev_disable(wusbhc, port_idx);
mutex_unlock(&wusbhc->mutex);
wusbhc_put(wusbhc);
return size;
}
static DEVICE_ATTR(wusb_disconnect, 0200, NULL, wusb_disconnect_store);
static ssize_t wusb_cdid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t result;
struct wusb_dev *wusb_dev;
wusb_dev = wusb_dev_get_by_usb_dev(to_usb_device(dev));
if (wusb_dev == NULL)
return -ENODEV;
result = ckhdid_printf(buf, PAGE_SIZE, &wusb_dev->cdid);
strcat(buf, "\n");
wusb_dev_put(wusb_dev);
return result + 1;
}
static DEVICE_ATTR(wusb_cdid, 0444, wusb_cdid_show, NULL);
static ssize_t wusb_ck_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
int result;
struct usb_device *usb_dev;
struct wusbhc *wusbhc;
struct wusb_ckhdid ck;
result = sscanf(buf,
"%02hhx %02hhx %02hhx %02hhx "
"%02hhx %02hhx %02hhx %02hhx "
"%02hhx %02hhx %02hhx %02hhx "
"%02hhx %02hhx %02hhx %02hhx\n",
&ck.data[0] , &ck.data[1],
&ck.data[2] , &ck.data[3],
&ck.data[4] , &ck.data[5],
&ck.data[6] , &ck.data[7],
&ck.data[8] , &ck.data[9],
&ck.data[10], &ck.data[11],
&ck.data[12], &ck.data[13],
&ck.data[14], &ck.data[15]);
if (result != 16)
return -EINVAL;
usb_dev = to_usb_device(dev);
wusbhc = wusbhc_get_by_usb_dev(usb_dev);
if (wusbhc == NULL)
return -ENODEV;
result = wusb_dev_4way_handshake(wusbhc, usb_dev->wusb_dev, &ck);
memset(&ck, 0, sizeof(ck));
wusbhc_put(wusbhc);
return result < 0 ? result : size;
}
static DEVICE_ATTR(wusb_ck, 0200, NULL, wusb_ck_store);
static struct attribute *wusb_dev_attrs[] = {
&dev_attr_wusb_disconnect.attr,
&dev_attr_wusb_cdid.attr,
&dev_attr_wusb_ck.attr,
NULL,
};
static struct attribute_group wusb_dev_attr_group = {
.name = NULL, /* we want them in the same directory */
.attrs = wusb_dev_attrs,
};
int wusb_dev_sysfs_add(struct wusbhc *wusbhc, struct usb_device *usb_dev,
struct wusb_dev *wusb_dev)
{
int result = sysfs_create_group(&usb_dev->dev.kobj,
&wusb_dev_attr_group);
struct device *dev = &usb_dev->dev;
if (result < 0)
dev_err(dev, "Cannot register WUSB-dev attributes: %d\n",
result);
return result;
}
void wusb_dev_sysfs_rm(struct wusb_dev *wusb_dev)
{
struct usb_device *usb_dev = wusb_dev->usb_dev;
if (usb_dev)
sysfs_remove_group(&usb_dev->dev.kobj, &wusb_dev_attr_group);
}
/*
* Wireless USB Host Controller
* UWB Protocol Adaptation Layer (PAL) glue.
*
* Copyright (C) 2008 Cambridge Silicon Radio Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wusbhc.h"
/**
* wusbhc_pal_register - register the WUSB HC as a UWB PAL
* @wusbhc: the WUSB HC
*/
int wusbhc_pal_register(struct wusbhc *wusbhc)
{
uwb_pal_init(&wusbhc->pal);
return uwb_pal_register(wusbhc->uwb_rc, &wusbhc->pal);
}
/**
* wusbhc_pal_register - unregister the WUSB HC as a UWB PAL
* @wusbhc: the WUSB HC
*/
void wusbhc_pal_unregister(struct wusbhc *wusbhc)
{
uwb_pal_unregister(wusbhc->uwb_rc, &wusbhc->pal);
}
/*
* WUSB cluster reservation management
*
* Copyright (C) 2007 Cambridge Silicon Radio Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/uwb.h>
#include "wusbhc.h"
/*
* WUSB cluster reservations are multicast reservations with the
* broadcast cluster ID (BCID) as the target DevAddr.
*
* FIXME: consider adjusting the reservation depending on what devices
* are attached.
*/
static int wusbhc_bwa_set(struct wusbhc *wusbhc, u8 stream,
const struct uwb_mas_bm *mas)
{
if (mas == NULL)
mas = &uwb_mas_bm_zero;
return wusbhc->bwa_set(wusbhc, stream, mas);
}
/**
* wusbhc_rsv_complete_cb - WUSB HC reservation complete callback
* @rsv: the reservation
*
* Either set or clear the HC's view of the reservation.
*
* FIXME: when a reservation is denied the HC should be stopped.
*/
static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv)
{
struct wusbhc *wusbhc = rsv->pal_priv;
struct device *dev = wusbhc->dev;
char buf[72];
switch (rsv->state) {
case UWB_RSV_STATE_O_ESTABLISHED:
bitmap_scnprintf(buf, sizeof(buf), rsv->mas.bm, UWB_NUM_MAS);
dev_dbg(dev, "established reservation: %s\n", buf);
wusbhc_bwa_set(wusbhc, rsv->stream, &rsv->mas);
break;
case UWB_RSV_STATE_NONE:
dev_dbg(dev, "removed reservation\n");
wusbhc_bwa_set(wusbhc, 0, NULL);
wusbhc->rsv = NULL;
break;
default:
dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state);
break;
}
}
/**
* wusbhc_rsv_establish - establish a reservation for the cluster
* @wusbhc: the WUSB HC requesting a bandwith reservation
*/
int wusbhc_rsv_establish(struct wusbhc *wusbhc)
{
struct uwb_rc *rc = wusbhc->uwb_rc;
struct uwb_rsv *rsv;
struct uwb_dev_addr bcid;
int ret;
rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc);
if (rsv == NULL)
return -ENOMEM;
bcid.data[0] = wusbhc->cluster_id;
bcid.data[1] = 0;
rsv->owner = &rc->uwb_dev;
rsv->target.type = UWB_RSV_TARGET_DEVADDR;
rsv->target.devaddr = bcid;
rsv->type = UWB_DRP_TYPE_PRIVATE;
rsv->max_mas = 256;
rsv->min_mas = 16; /* one MAS per zone? */
rsv->sparsity = 16; /* at least one MAS in each zone? */
rsv->is_multicast = true;
ret = uwb_rsv_establish(rsv);
if (ret == 0)
wusbhc->rsv = rsv;
else
uwb_rsv_destroy(rsv);
return ret;
}
/**
* wusbhc_rsv_terminate - terminate any cluster reservation
* @wusbhc: the WUSB host whose reservation is to be terminated
*/
void wusbhc_rsv_terminate(struct wusbhc *wusbhc)
{
if (wusbhc->rsv)
uwb_rsv_terminate(wusbhc->rsv);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment