melef wrote:
No I'm not sending a DATA stage.
Without seeing the code it's difficult to say.
This is what I have for the procedure:
Code:
static usb_status_t ConfigureDevice(UsbDeviceInfo* device, int CONFIG, uint8_t HubPorts)
{
usb_status_t status = USB_FAIL;
REQUEST_PACKET device_packet;
device_packet.request_type = USB_BM_REQUEST_INPUT | USB_BM_REQUEST_STANDARD | USB_BM_REQUEST_DEVICE;
device_packet.request = USB_BREQUEST_GET_DESCRIPTOR;
device_packet.value = USB_DESCRIPTOR_WVALUE(USB_DESCRIPTOR_CONFIGURATION, CONFIG-1);
device_packet.index = 0;
auto confdesc = GetCompleteDescriptor<usb_configuration_descriptor>(device, device_packet, &GetConfigLength);
if (!confdesc)
return USB_FAIL;
usb_interface_descriptor* defiface = raw_offset<usb_interface_descriptor*>(confdesc, confdesc->bLength);
usb_descriptor* descep = raw_offset<usb_descriptor*>(defiface, defiface->bLength);
usb_endpoint_descriptor** endpointdata = new usb_endpoint_descriptor * [defiface->bNumEndpoints + 1];
int i = 0;
while (raw_diff(descep, confdesc) < confdesc->wTotalLength)
{
if (descep->bDescriptorType == USB_DESCRIPTOR_ENDPOINT)
{
endpointdata[i++] = (usb_endpoint_descriptor*)descep;
if (i == defiface->bNumEndpoints) break;
}
descep = raw_offset<usb_descriptor*>(descep, descep->bLength);
}
endpointdata[defiface->bNumEndpoints] = nullptr;
if (USB_FAILED(status = device->ConfigureEndpoint(endpointdata, 1, 0, 0, HubPorts)))
return status;
//Send set configuration
device_packet.request_type = USB_BM_REQUEST_OUTPUT | USB_BM_REQUEST_STANDARD | USB_BM_REQUEST_DEVICE;
device_packet.request = USB_BREQUEST_SET_CONFIGURATION;
device_packet.value = USB_DESCRIPTOR_WVALUE(0, CONFIG);
device_packet.index = 0;
device_packet.length = 0;
void* devdesc;
if (USB_FAILED(status = device->RequestData(device_packet, (void**)&devdesc)))
return status;
kputs(u"Device Configured\n");
return USB_SUCCESS;
}
Set_Configuration is USB_BM_REQUEST_OUTPUT, something very simple that might potentially get overlooked.
The one that caught me out for a while was that for retrieving the descriptor, the index is zero-based, (CONFIG-1), but it's one-base (CONFIG) for SET_CONFIGURATION.
And then it could even be an issue with the endpoint configuration.
Code:
virtual usb_status_t ConfigureEndpoint(usb_endpoint_descriptor** pEndpoints, uint8_t config, uint8_t iface, uint8_t alternate, uint8_t downstreamports)
{
paddr_t incontxt;
size_t epAdd = 1;
size_t highbit = 0;
auto parseep = [](usb_endpoint_descriptor* ep, uint8_t& addr, uint8_t& dirIn)
{
addr = ep->bEndpointAddress & 0xF;
dirIn = ep->bEndpointAddress >> 7;
};
auto BitToSet = [&](usb_endpoint_descriptor* ep)
{
uint8_t addr, dirIn;
parseep(ep, addr, dirIn);
return 2 * addr + dirIn;
};
for (int n = 0; pEndpoints[n]; ++n)
{
auto bitset = BitToSet(pEndpoints[n]);
epAdd |= (1 << bitset);
highbit = bitset > highbit ? bitset : highbit;
}
auto mapin = controller->CreateInputContext(incontxt, epAdd, 0, config, iface, alternate);
mapin->slot.ContextEntries = highbit;
if (downstreamports > 0)
{
mapin->slot.Hub = 1;
mapin->slot.NumberPorts = downstreamports;
}
for (int n = 0; pEndpoints[n]; ++n)
{
auto ep = pEndpoints[n];
uint8_t addr, dirIn;
parseep(ep, addr, dirIn);
auto epct = controller->GetEndpointContext(mapin, addr, dirIn);
epct->MaxPacketSize = ep->wMaxPacketSize & 0x7FF;
auto usbtyp = ep->bmAttributes & USB_EP_ATTR_TYPE_MASK;
epct->EpType = usbtyp | (dirIn << 2);
if (dirIn)
{
auto ring = controller->MakeEventRing(1);
epct->TRDequeuePtr = (uint64_t)get_physical_address(ring->dequeueptr) | 1;
}
auto MaxEsit = epct->MaxPacketSize * (epct->MaxBurstSize + 1);
epct->HID = 1;
switch (usbtyp)
{
case USB_EP_ATTR_TYPE_CONTROL:
break;
case USB_EP_ATTR_TYPE_BULK:
break;
case USB_EP_ATTR_TYPE_INTERRUPT:
epct->CErr = 3;
epct->MaxEsitLow = MaxEsit & 0xFFFF;
epct->MaxEsitHigh = MaxEsit >> 16;
epct->Interval = 11;
epct->AverageTrbLength = 0x400;
break;
case USB_EP_ATTR_TYPE_ISOCHRONOUS:
break;
default:
break;
}
}
//while (1);
//Issue address device command
void* last_command = controller->cmdring.enqueue(create_configureendpoint_command(incontxt, slotid, false));
uint64_t* curevt = (uint64_t*)controller->waitComplete(last_command, 1000);
if (get_trb_completion_code(curevt) != XHCI_COMPLETION_SUCCESS)
{
kprintf(u"Error configuring endpoint: %x\n", get_trb_completion_code(curevt));
return USB_FAIL;
}
return USB_SUCCESS;
}