/* * 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; }
/* * 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; }
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; }
/* * 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; }