src/devices/usb/drivers/xhci/xhci-root-hub.cc
// handles control requests for virtual root hub devices
handles control requests for virtual root hub devices
handles control requests for virtual root hub devices
static zx_status_t xhci_rh_control(xhci_t* xhci, xhci_root_hub_t* rh, usb_setup_t* setup,
                                   usb_request_t* req) {
  uint8_t request_type = setup->bmRequestType;
  uint8_t request = setup->bRequest;
  uint16_t value = le16toh(setup->wValue);
  uint16_t index = le16toh(setup->wIndex);
  xhci_usb_request_internal_t* req_int = USB_REQ_TO_XHCI_INTERNAL(req);
  zxlogf(TRACE, "xhci_rh_control type: 0x%02X req: %d value: %d index: %d length: %d", request_type,
         request, value, index, le16toh(setup->wLength));
  if ((request_type & USB_DIR_MASK) == USB_DIR_IN && request == USB_REQ_GET_DESCRIPTOR) {
    return xhci_rh_get_descriptor(xhci, request_type, rh, value, index, le16toh(setup->wLength),
                                  req);
  } else if ((request_type & ~USB_DIR_MASK) == (USB_TYPE_CLASS | USB_RECIP_PORT)) {
    if (index < 1 || index > rh->num_ports) {
      usb_request_complete(req, ZX_ERR_INVALID_ARGS, 0, &req_int->complete_cb);
      return ZX_OK;
    }
    auto rh_port_index = rh->port_map[index - 1];
    auto port_index = static_cast<uint8_t>(index - 1);
    if (request == USB_REQ_SET_FEATURE) {
      if (value == USB_FEATURE_PORT_POWER) {
        usb_request_complete(req, ZX_OK, 0, &req_int->complete_cb);
        return ZX_OK;
      } else if (value == USB_FEATURE_PORT_RESET) {
        xhci_reset_port(xhci, rh, rh_port_index);
        usb_request_complete(req, ZX_OK, 0, &req_int->complete_cb);
        return ZX_OK;
      }
    } else if (request == USB_REQ_CLEAR_FEATURE) {
      auto* change_bits = &rh->port_status[port_index].wPortChange;
      switch (value) {
        case USB_FEATURE_C_PORT_CONNECTION:
          *change_bits &= static_cast<uint16_t>(~USB_C_PORT_CONNECTION);
          break;
        case USB_FEATURE_C_PORT_ENABLE:
          *change_bits &= static_cast<uint16_t>(~USB_C_PORT_ENABLE);
          break;
        case USB_FEATURE_C_PORT_SUSPEND:
          *change_bits &= static_cast<uint16_t>(~USB_C_PORT_SUSPEND);
          break;
        case USB_FEATURE_C_PORT_OVER_CURRENT:
          *change_bits &= static_cast<uint16_t>(~USB_C_PORT_OVER_CURRENT);
          break;
        case USB_FEATURE_C_PORT_RESET:
          *change_bits &= static_cast<uint16_t>(~USB_C_PORT_RESET);
          break;
      }
      usb_request_complete(req, ZX_OK, 0, &req_int->complete_cb);
      return ZX_OK;
    } else if ((request_type & USB_DIR_MASK) == USB_DIR_IN && request == USB_REQ_GET_STATUS &&
               value == 0) {
      usb_port_status_t* status = &rh->port_status[port_index];
      size_t length = req->header.length;
      if (length > sizeof(*status))
        length = sizeof(*status);
      usb_request_copy_to(req, status, length, 0);
      usb_request_complete(req, ZX_OK, length, &req_int->complete_cb);
      return ZX_OK;
    }
  } else if (request_type == (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) &&
             request == USB_REQ_SET_CONFIGURATION && req->header.length == 0) {
    usb_request_complete(req, ZX_OK, 0, &req_int->complete_cb);
    return ZX_OK;
  }
  zxlogf(ERROR, "unsupported root hub control request type: 0x%02X req: %d value: %d index: %d",
         request_type, request, value, index);
  usb_request_complete(req, ZX_ERR_NOT_SUPPORTED, 0, &req_int->complete_cb);
  return ZX_ERR_NOT_SUPPORTED;
}
static zx_status_t xhci_rh_control ( xhci_t * xhci , xhci_root_hub_t * rh , usb_setup_t * setup , usb_request_t * req ) { uint8_t request_type = setup -> bmRequestType ; uint8_t request = setup -> bRequest ; uint16_t value = le16toh ( setup -> wValue ) ; uint16_t index = le16toh ( setup -> wIndex ) ; xhci_usb_request_internal_t * req_int = USB_REQ_TO_XHCI_INTERNAL ( req ) ; zxlogf ( TRACE , " " , request_type , request , value , index , le16toh ( setup -> wLength ) ) ; if ( ( request_type & USB_DIR_MASK ) == USB_DIR_IN && request == USB_REQ_GET_DESCRIPTOR ) { return xhci_rh_get_descriptor ( xhci , request_type , rh , value , index , le16toh ( setup -> wLength ) , req ) ; } else if ( ( request_type & ~ USB_DIR_MASK ) == ( USB_TYPE_CLASS | USB_RECIP_PORT ) ) { if ( index < 1 || index > rh -> num_ports ) { usb_request_complete ( req , ZX_ERR_INVALID_ARGS , 0 , & req_int -> complete_cb ) ; return ZX_OK ; } auto rh_port_index = rh -> port_map [ index - 1 ] ; auto port_index = static_cast < uint8_t > ( index - 1 ) ; if ( request == USB_REQ_SET_FEATURE ) { if ( value == USB_FEATURE_PORT_POWER ) { usb_request_complete ( req , ZX_OK , 0 , & req_int -> complete_cb ) ; return ZX_OK ; } else if ( value == USB_FEATURE_PORT_RESET ) { xhci_reset_port ( xhci , rh , rh_port_index ) ; usb_request_complete ( req , ZX_OK , 0 , & req_int -> complete_cb ) ; return ZX_OK ; } } else if ( request == USB_REQ_CLEAR_FEATURE ) { auto * change_bits = & rh -> port_status [ port_index ] . wPortChange ; switch ( value ) { case USB_FEATURE_C_PORT_CONNECTION : * change_bits &= static_cast < uint16_t > ( ~ USB_C_PORT_CONNECTION ) ; break ; case USB_FEATURE_C_PORT_ENABLE : * change_bits &= static_cast < uint16_t > ( ~ USB_C_PORT_ENABLE ) ; break ; case USB_FEATURE_C_PORT_SUSPEND : * change_bits &= static_cast < uint16_t > ( ~ USB_C_PORT_SUSPEND ) ; break ; case USB_FEATURE_C_PORT_OVER_CURRENT : * change_bits &= static_cast < uint16_t > ( ~ USB_C_PORT_OVER_CURRENT ) ; break ; case USB_FEATURE_C_PORT_RESET : * change_bits &= static_cast < uint16_t > ( ~ USB_C_PORT_RESET ) ; break ; } usb_request_complete ( req , ZX_OK , 0 , & req_int -> complete_cb ) ; return ZX_OK ; } else if ( ( request_type & USB_DIR_MASK ) == USB_DIR_IN && request == USB_REQ_GET_STATUS && value == 0 ) { usb_port_status_t * status = & rh -> port_status [ port_index ] ; size_t length = req -> header . length ; if ( length > sizeof ( * status ) ) length = sizeof ( * status ) ; usb_request_copy_to ( req , status , length , 0 ) ; usb_request_complete ( req , ZX_OK , length , & req_int -> complete_cb ) ; return ZX_OK ; } } else if ( request_type == ( USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE ) && request == USB_REQ_SET_CONFIGURATION && req -> header . length == 0 ) { usb_request_complete ( req , ZX_OK , 0 , & req_int -> complete_cb ) ; return ZX_OK ; } zxlogf ( ERROR , " " , request_type , request , value , index ) ; usb_request_complete ( req , ZX_ERR_NOT_SUPPORTED , 0 , & req_int -> complete_cb ) ; return ZX_ERR_NOT_SUPPORTED ; }
handles control requests for virtual root hub devices
handles control requests for virtual root hub devices
// index is 1-based port number // nothing to do - root hub ports are already powered // nothing to do here