/*
 * Check an aimed rpipe to make sure it points to where we want
 *
 * We use bit 19 of the Linux USB pipe bitmap for unauth vs auth
 * space; when it is like that, we or 0x80 to make an unauth address.
 */
static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa,
			   const struct usb_host_endpoint *ep,
			   const struct urb *urb, gfp_t gfp)
{
	int result = 0;		/* better code for lack of companion? */
	struct device *dev = &wa->usb_iface->dev;
	struct usb_device *usb_dev = urb->dev;
	u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0;
	u8 portnum = wusb_port_no_to_idx(urb->dev->portnum);

#define AIM_CHECK(rdf, val, text)					\
	do {								\
		if (rpipe->descr.rdf != (val)) {			\
			dev_err(dev,					\
				"rpipe aim discrepancy: " #rdf " " text "\n", \
				rpipe->descr.rdf, (val));		\
			result = -EINVAL;				\
			WARN_ON(1);					\
		}							\
	} while (0)
	AIM_CHECK(wMaxPacketSize, cpu_to_le16(ep->desc.wMaxPacketSize),
		  "(%u vs %u)");
	AIM_CHECK(bHSHubPort, portnum, "(%u vs %u)");
	AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ?
			UWB_PHY_RATE_53 : UWB_PHY_RATE_200,
		  "(%u vs %u)");
	AIM_CHECK(bDeviceAddress, urb->dev->devnum | unauth, "(%u vs %u)");
	AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)");
	AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)");
	AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)");
#undef AIM_CHECK
	return result;
}
Пример #2
0
/*
 * Check an aimed rpipe to make sure it points to where we want
 *
 * We use bit 19 of the Linux USB pipe bitmap for unauth vs auth
 * space; when it is like that, we or 0x80 to make an unauth address.
 */
static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa,
			   const struct usb_host_endpoint *ep,
			   const struct urb *urb, gfp_t gfp)
{
	int result = 0;
	struct device *dev = &wa->usb_iface->dev;
	u8 portnum = wusb_port_no_to_idx(urb->dev->portnum);

#define AIM_CHECK(rdf, val, text)					\
	do {								\
		if (rpipe->descr.rdf != (val)) {			\
			dev_err(dev,					\
				"rpipe aim discrepancy: " #rdf " " text "\n", \
				rpipe->descr.rdf, (val));		\
			result = -EINVAL;				\
			WARN_ON(1);					\
		}							\
	} while (0)
	AIM_CHECK(hwa_bDeviceInfoIndex, portnum, "(%u vs %u)");
	AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ?
			UWB_PHY_RATE_53 : UWB_PHY_RATE_200,
		  "(%u vs %u)");
	AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)");
	AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)");
	AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)");
#undef AIM_CHECK
	return result;
}
Пример #3
0
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;
}
/*
 * Aim an rpipe to its device & endpoint destination
 *
 * Make sure we change the address to unauthenticathed if the device
 * is WUSB and it is not authenticated.
 */
static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa,
		     struct usb_host_endpoint *ep, struct urb *urb, gfp_t gfp)
{
	int result = -ENOMSG;	/* better code for lack of companion? */
	struct device *dev = &wa->usb_iface->dev;
	struct usb_device *usb_dev = urb->dev;
	struct usb_wireless_ep_comp_descriptor *epcd;
	u8 unauth;

	epcd = rpipe_epc_find(dev, ep);
	if (epcd == NULL) {
		dev_err(dev, "ep 0x%02x: can't find companion descriptor\n",
			ep->desc.bEndpointAddress);
		goto error;
	}
	unauth = usb_dev->wusb && !usb_dev->authenticated ? 0x80 : 0;
	__rpipe_reset(wa, le16_to_cpu(rpipe->descr.wRPipeIndex));
	atomic_set(&rpipe->segs_available, le16_to_cpu(rpipe->descr.wRequests));
	/* FIXME: block allocation system; request with queuing and timeout */
	/* FIXME: compute so seg_size > ep->maxpktsize */
	rpipe->descr.wBlocks = cpu_to_le16(16);		/* given */
	/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
	if (usb_endpoint_xfer_isoc(&ep->desc))
		rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize;
	else
		rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize;
	rpipe->descr.bHSHubAddress = 0;			/* reserved: zero */
	rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum);
	/* FIXME: use maximum speed as supported or recommended by device */
	rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ?
		UWB_PHY_RATE_53 : UWB_PHY_RATE_200;

	dev_dbg(dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n",
		urb->dev->devnum, urb->dev->devnum | unauth,
		le16_to_cpu(rpipe->descr.wRPipeIndex),
		usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed);

	/* see security.c:wusb_update_address() */
	if (unlikely(urb->dev->devnum == 0x80))
		rpipe->descr.bDeviceAddress = 0;
	else
		rpipe->descr.bDeviceAddress = urb->dev->devnum | unauth;
	rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress;
	/* FIXME: bDataSequence */
	rpipe->descr.bDataSequence = 0;
	/* FIXME: dwCurrentWindow */
	rpipe->descr.dwCurrentWindow = cpu_to_le32(1);
	/* FIXME: bMaxDataSequence */
	rpipe->descr.bMaxDataSequence = epcd->bMaxSequence - 1;
	rpipe->descr.bInterval = ep->desc.bInterval;
	/* FIXME: bOverTheAirInterval */
	rpipe->descr.bOverTheAirInterval = 0;	/* 0 if not isoc */
	/* FIXME: xmit power & preamble blah blah */
	rpipe->descr.bmAttribute = ep->desc.bmAttributes & 0x03;
	/* rpipe->descr.bmCharacteristics RO */
	/* FIXME: bmRetryOptions */
	rpipe->descr.bmRetryOptions = 15;
	/* FIXME: use for assessing link quality? */
	rpipe->descr.wNumTransactionErrors = 0;
	result = __rpipe_set_descr(wa, &rpipe->descr,
				   le16_to_cpu(rpipe->descr.wRPipeIndex));
	if (result < 0) {
		dev_err(dev, "Cannot aim rpipe: %d\n", result);
		goto error;
	}
	result = 0;
error:
	return result;
}
Пример #5
0
/*
 * Aim an rpipe to its device & endpoint destination
 *
 * Make sure we change the address to unauthenticated if the device
 * is WUSB and it is not authenticated.
 */
static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa,
		     struct usb_host_endpoint *ep, struct urb *urb, gfp_t gfp)
{
	int result = -ENOMSG;	/* better code for lack of companion? */
	struct device *dev = &wa->usb_iface->dev;
	struct usb_device *usb_dev = urb->dev;
	struct usb_wireless_ep_comp_descriptor *epcd;
	u32 ack_window, epcd_max_sequence;
	u8 unauth;

	epcd = rpipe_epc_find(dev, ep);
	if (epcd == NULL) {
		dev_err(dev, "ep 0x%02x: can't find companion descriptor\n",
			ep->desc.bEndpointAddress);
		goto error;
	}
	unauth = usb_dev->wusb && !usb_dev->authenticated ? 0x80 : 0;
	__rpipe_reset(wa, le16_to_cpu(rpipe->descr.wRPipeIndex));
	atomic_set(&rpipe->segs_available,
		le16_to_cpu(rpipe->descr.wRequests));
	/* FIXME: block allocation system; request with queuing and timeout */
	/* FIXME: compute so seg_size > ep->maxpktsize */
	rpipe->descr.wBlocks = cpu_to_le16(16);		/* given */
	/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
	if (usb_endpoint_xfer_isoc(&ep->desc))
		rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize;
	else
		rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize;

	rpipe->descr.hwa_bMaxBurst = max(min_t(unsigned int,
				epcd->bMaxBurst, 16U), 1U);
	rpipe->descr.hwa_bDeviceInfoIndex =
			wusb_port_no_to_idx(urb->dev->portnum);
	/* FIXME: use maximum speed as supported or recommended by device */
	rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ?
		UWB_PHY_RATE_53 : UWB_PHY_RATE_200;

	dev_dbg(dev, "addr %u (0x%02x) rpipe #%u ep# %u speed %d\n",
		urb->dev->devnum, urb->dev->devnum | unauth,
		le16_to_cpu(rpipe->descr.wRPipeIndex),
		usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed);

	rpipe->descr.hwa_reserved = 0;

	rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress;
	/* FIXME: bDataSequence */
	rpipe->descr.bDataSequence = 0;

	/* start with base window of hwa_bMaxBurst bits starting at 0. */
	ack_window = 0xFFFFFFFF >> (32 - rpipe->descr.hwa_bMaxBurst);
	rpipe->descr.dwCurrentWindow = cpu_to_le32(ack_window);
	epcd_max_sequence = max(min_t(unsigned int,
			epcd->bMaxSequence, 32U), 2U);
	rpipe->descr.bMaxDataSequence = epcd_max_sequence - 1;
	rpipe->descr.bInterval = ep->desc.bInterval;
	if (usb_endpoint_xfer_isoc(&ep->desc))
		rpipe->descr.bOverTheAirInterval = epcd->bOverTheAirInterval;
	else
		rpipe->descr.bOverTheAirInterval = 0;	/* 0 if not isoc */
	/* FIXME: xmit power & preamble blah blah */
	rpipe->descr.bmAttribute = (ep->desc.bmAttributes &
					USB_ENDPOINT_XFERTYPE_MASK);
	/* rpipe->descr.bmCharacteristics RO */
	rpipe->descr.bmRetryOptions = (wa->wusb->retry_count & 0xF);
	/* FIXME: use for assessing link quality? */
	rpipe->descr.wNumTransactionErrors = 0;
	result = __rpipe_set_descr(wa, &rpipe->descr,
				   le16_to_cpu(rpipe->descr.wRPipeIndex));
	if (result < 0) {
		dev_err(dev, "Cannot aim rpipe: %d\n", result);
		goto error;
	}
	result = 0;
error:
	return result;
}