diff --git a/src/userland/usb/include/usb.h b/src/userland/usb/include/usb.h index 5662180..6d43ea2 100644 --- a/src/userland/usb/include/usb.h +++ b/src/userland/usb/include/usb.h @@ -61,6 +61,7 @@ void *(*initialize)(uint32_t, uint32_t, uint32_t); void (*getDeviceDescriptor)(void *, uint32_t, uint32_t, void *); void (*setupEndpoints)(void *, ListElement *, uint32_t); + void (*setupHID)(void *, uint32_t, void *); } UsbHostControllerInterface; typedef struct { diff --git a/src/userland/usb/include/usb.h b/src/userland/usb/include/usb.h index 5662180..6d43ea2 100644 --- a/src/userland/usb/include/usb.h +++ b/src/userland/usb/include/usb.h @@ -61,6 +61,7 @@ void *(*initialize)(uint32_t, uint32_t, uint32_t); void (*getDeviceDescriptor)(void *, uint32_t, uint32_t, void *); void (*setupEndpoints)(void *, ListElement *, uint32_t); + void (*setupHID)(void *, uint32_t, void *); } UsbHostControllerInterface; typedef struct { diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 30b43fb..8bbf51a 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -29,22 +29,42 @@ // only doing blank interface descriptors for now, there are // also interface assosciations... ListElement *endpointConfigurations = NULL; + ListElement *hidInterfaces = NULL; while (interface->descriptorType == 4) { printf("interface %i: %i endpoint(s), class %i, subclass %i\n", interface->interfaceNumber, interface->endpointCount, interface->interfaceClass, interface->subClass); void *nextInterface = (void *)interface + interface->size; - for (uint32_t i = 0; i < interface->endpointCount; i++) { + for (uint32_t i = 0; i < interface->endpointCount;) { UsbEndpointDescriptor *endpoint = nextInterface; - listAdd(&endpointConfigurations, endpoint); + if (endpoint->descriptorType == 5) { + listAdd(&endpointConfigurations, endpoint); + printf("endpoint %i (%i): address: %x, attributes: %x\n", i, + endpoint->descriptorType, endpoint->address, + endpoint->attributes); + i++; + } nextInterface += endpoint->size; - printf("endpoint %i: address: %x, attributes: %x\n", i, - endpoint->address, endpoint->attributes); + } + if (interface->interfaceClass == 3) { + listAdd(&hidInterfaces, interface); } interface = nextInterface; } slot->interface->setupEndpoints(slot->data, endpointConfigurations, configurationValue); + foreach (hidInterfaces, UsbInterfaceDescriptor *, interface, { + UsbEndpointDescriptor *endpoint = (void *)interface + interface->size; + while (endpoint->descriptorType != 5) { + endpoint = (void *)endpoint + endpoint->size; + } + uint8_t endpointNumber = endpoint->address & 0xF; // never 0 + uint8_t direction = endpoint->address >> 7; + uint8_t endpointIndex = (endpointNumber)*2 - 1 + direction; + void *buffer = requestMemory(1, 0, 0); + void *bufferPhysical = getPhysicalAddress(buffer); + slot->interface->setupHID(slot->data, endpointIndex, buffer); + }) // clear list } diff --git a/src/userland/usb/include/usb.h b/src/userland/usb/include/usb.h index 5662180..6d43ea2 100644 --- a/src/userland/usb/include/usb.h +++ b/src/userland/usb/include/usb.h @@ -61,6 +61,7 @@ void *(*initialize)(uint32_t, uint32_t, uint32_t); void (*getDeviceDescriptor)(void *, uint32_t, uint32_t, void *); void (*setupEndpoints)(void *, ListElement *, uint32_t); + void (*setupHID)(void *, uint32_t, void *); } UsbHostControllerInterface; typedef struct { diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 30b43fb..8bbf51a 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -29,22 +29,42 @@ // only doing blank interface descriptors for now, there are // also interface assosciations... ListElement *endpointConfigurations = NULL; + ListElement *hidInterfaces = NULL; while (interface->descriptorType == 4) { printf("interface %i: %i endpoint(s), class %i, subclass %i\n", interface->interfaceNumber, interface->endpointCount, interface->interfaceClass, interface->subClass); void *nextInterface = (void *)interface + interface->size; - for (uint32_t i = 0; i < interface->endpointCount; i++) { + for (uint32_t i = 0; i < interface->endpointCount;) { UsbEndpointDescriptor *endpoint = nextInterface; - listAdd(&endpointConfigurations, endpoint); + if (endpoint->descriptorType == 5) { + listAdd(&endpointConfigurations, endpoint); + printf("endpoint %i (%i): address: %x, attributes: %x\n", i, + endpoint->descriptorType, endpoint->address, + endpoint->attributes); + i++; + } nextInterface += endpoint->size; - printf("endpoint %i: address: %x, attributes: %x\n", i, - endpoint->address, endpoint->attributes); + } + if (interface->interfaceClass == 3) { + listAdd(&hidInterfaces, interface); } interface = nextInterface; } slot->interface->setupEndpoints(slot->data, endpointConfigurations, configurationValue); + foreach (hidInterfaces, UsbInterfaceDescriptor *, interface, { + UsbEndpointDescriptor *endpoint = (void *)interface + interface->size; + while (endpoint->descriptorType != 5) { + endpoint = (void *)endpoint + endpoint->size; + } + uint8_t endpointNumber = endpoint->address & 0xF; // never 0 + uint8_t direction = endpoint->address >> 7; + uint8_t endpointIndex = (endpointNumber)*2 - 1 + direction; + void *buffer = requestMemory(1, 0, 0); + void *bufferPhysical = getPhysicalAddress(buffer); + slot->interface->setupHID(slot->data, endpointIndex, buffer); + }) // clear list } diff --git a/src/userland/usb/xhci/xhci.c b/src/userland/usb/xhci/xhci.c index b8fcae1..f315025 100644 --- a/src/userland/usb/xhci/xhci.c +++ b/src/userland/usb/xhci/xhci.c @@ -83,20 +83,19 @@ foreach (endpoints, UsbEndpointDescriptor *, endpoint, { uint8_t endpointNumber = endpoint->address & 0xF; // never 0 uint8_t direction = endpoint->address >> 7; - uint8_t endpointIndex = (endpointNumber + direction) * 2 - 1; + uint8_t endpointIndex = (endpointNumber)*2 - 1 + direction; XHCIEndpointContext *endpointContext = &inputContext->deviceContext.endpoints[endpointIndex]; - endpointContext->endpointState = 0; endpointContext->maxPrimaryStreams = 0; endpointContext->interval = endpoint->interval; endpointContext->errorCount = 3; endpointContext->endpointType = - 4 * direction + endpoint->attributes & 3; + direction << 2 | endpoint->attributes & 3; endpointContext->maxPacketSize = endpoint->maxPacketSize; slot->endpointRings[endpointIndex] = malloc(sizeof(TrbRing)); setupTrbRing(slot->endpointRings[endpointIndex], 256); endpointContext->transferDequeuePointerLow = - U32(slot->endpointRings[endpointIndex]->physical) | 0; + U32(slot->endpointRings[endpointIndex]->physical) | 1; endpointContext->transferDequeuePointerHigh = 0; endpointContext->averageTRBLength = 2048; inputContext->inputControl.addContextFlags |= 1 << (endpointIndex + 1); @@ -135,9 +134,104 @@ await(serviceId, eventId); } +void setProtocol(SlotXHCI *slot) { + XHCISetupStageTRB setup = {0}; + setup.requestType = 0x21; + setup.request = 0x0B; + setup.value = 0; + setup.index = 0; + setup.length = 0; + setup.transferLength = 8; + setup.interruptOnCompletion = 0; + setup.interrupterTarget = 0; + setup.type = 2; + setup.transferType = 3; + setup.immediateData = 1; + XHCIStatusStageTRB status = {0}; + status.inDirection = 1; + status.evaluateNext = 0; + status.interruptOnCompletion = 1; + status.type = 4; + + enqueueCommand(slot->controlRing, (void *)&setup); + uint32_t commandAddress = + U32(enqueueCommand(slot->controlRing, (void *)&status)); + uint32_t eventId = createDirectEventSave(commandAddress); + slot->controller->doorbells[slot->slotIndex] = 1; + await(serviceId, eventId); +} + +void setIdle(SlotXHCI *slot) { + XHCISetupStageTRB setup = {0}; + setup.requestType = 0x21; + setup.request = 0x0A; + setup.value = 0; + setup.index = 0; + setup.length = 0; + setup.transferLength = 8; + setup.interruptOnCompletion = 0; + setup.interrupterTarget = 0; + setup.type = 2; + setup.transferType = 3; + setup.immediateData = 1; + XHCIStatusStageTRB status = {0}; + status.inDirection = 1; + status.evaluateNext = 0; + status.interruptOnCompletion = 1; + status.type = 4; + + enqueueCommand(slot->controlRing, (void *)&setup); + uint32_t commandAddress = + U32(enqueueCommand(slot->controlRing, (void *)&status)); + uint32_t eventId = createDirectEventSave(commandAddress); + slot->controller->doorbells[slot->slotIndex] = 1; + await(serviceId, eventId); +} + +void setupHID(SlotXHCI *slot, uint32_t endpointIndex, void *buffer) { + setProtocol(slot); + setIdle(slot); + // XHCIDataStageTRB data = {0}; + // data.dataBuffer[0] = U32(getPhysicalAddress(buffer)); + // data.inDirection = 1; + // data.transferSize = 8; + // data.type = 3; + // data.interrupterTarget = 0; + // data.interruptOnShortPacket = 1; + // data.interruptOnCompletion = 1; + + // XHCIStatusStageTRB status = {0}; + // status.inDirection = 1; + // status.evaluateNext = 0; + // status.interruptOnCompletion = 1; + // status.inDirection = 0; + // status.type = 4; + + XHCINormalTRB normal = {0}; + normal.type = 1; + normal.inDirection = 1; + normal.interrupterTarget = 0; + normal.interruptOnCompletion = 1; + normal.interruptOnShortPacket = 1; + normal.dataBuffer[0] = U32(getPhysicalAddress(buffer)); + normal.transferSize = 4; + + void *trb = (void *)enqueueCommand(slot->endpointRings[endpointIndex], + (void *)&normal); + // enqueueCommand(slot->controlRing, (void *)&status); + printf("enqueueing normal stage: %x on endpoint %i\n", trb, endpointIndex); + slot->controller->doorbells[slot->slotIndex] = endpointIndex + 1; + sleep(1000); + for (uint32_t i = 0; i < 10; i++) { + printf("%x ", ((uint32_t *)buffer)[i]); + } + printf("\n"); +} + UsbHostControllerInterface xhci = { .initialize = init, .getDeviceDescriptor = (void *)usbGetDeviceDescriptor, .setupEndpoints = (void *)xhciSetupEndpoints, + .setupHID = (void *)setupHID, .pciClass = 0x0C0330, }; diff --git a/src/userland/usb/include/usb.h b/src/userland/usb/include/usb.h index 5662180..6d43ea2 100644 --- a/src/userland/usb/include/usb.h +++ b/src/userland/usb/include/usb.h @@ -61,6 +61,7 @@ void *(*initialize)(uint32_t, uint32_t, uint32_t); void (*getDeviceDescriptor)(void *, uint32_t, uint32_t, void *); void (*setupEndpoints)(void *, ListElement *, uint32_t); + void (*setupHID)(void *, uint32_t, void *); } UsbHostControllerInterface; typedef struct { diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 30b43fb..8bbf51a 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -29,22 +29,42 @@ // only doing blank interface descriptors for now, there are // also interface assosciations... ListElement *endpointConfigurations = NULL; + ListElement *hidInterfaces = NULL; while (interface->descriptorType == 4) { printf("interface %i: %i endpoint(s), class %i, subclass %i\n", interface->interfaceNumber, interface->endpointCount, interface->interfaceClass, interface->subClass); void *nextInterface = (void *)interface + interface->size; - for (uint32_t i = 0; i < interface->endpointCount; i++) { + for (uint32_t i = 0; i < interface->endpointCount;) { UsbEndpointDescriptor *endpoint = nextInterface; - listAdd(&endpointConfigurations, endpoint); + if (endpoint->descriptorType == 5) { + listAdd(&endpointConfigurations, endpoint); + printf("endpoint %i (%i): address: %x, attributes: %x\n", i, + endpoint->descriptorType, endpoint->address, + endpoint->attributes); + i++; + } nextInterface += endpoint->size; - printf("endpoint %i: address: %x, attributes: %x\n", i, - endpoint->address, endpoint->attributes); + } + if (interface->interfaceClass == 3) { + listAdd(&hidInterfaces, interface); } interface = nextInterface; } slot->interface->setupEndpoints(slot->data, endpointConfigurations, configurationValue); + foreach (hidInterfaces, UsbInterfaceDescriptor *, interface, { + UsbEndpointDescriptor *endpoint = (void *)interface + interface->size; + while (endpoint->descriptorType != 5) { + endpoint = (void *)endpoint + endpoint->size; + } + uint8_t endpointNumber = endpoint->address & 0xF; // never 0 + uint8_t direction = endpoint->address >> 7; + uint8_t endpointIndex = (endpointNumber)*2 - 1 + direction; + void *buffer = requestMemory(1, 0, 0); + void *bufferPhysical = getPhysicalAddress(buffer); + slot->interface->setupHID(slot->data, endpointIndex, buffer); + }) // clear list } diff --git a/src/userland/usb/xhci/xhci.c b/src/userland/usb/xhci/xhci.c index b8fcae1..f315025 100644 --- a/src/userland/usb/xhci/xhci.c +++ b/src/userland/usb/xhci/xhci.c @@ -83,20 +83,19 @@ foreach (endpoints, UsbEndpointDescriptor *, endpoint, { uint8_t endpointNumber = endpoint->address & 0xF; // never 0 uint8_t direction = endpoint->address >> 7; - uint8_t endpointIndex = (endpointNumber + direction) * 2 - 1; + uint8_t endpointIndex = (endpointNumber)*2 - 1 + direction; XHCIEndpointContext *endpointContext = &inputContext->deviceContext.endpoints[endpointIndex]; - endpointContext->endpointState = 0; endpointContext->maxPrimaryStreams = 0; endpointContext->interval = endpoint->interval; endpointContext->errorCount = 3; endpointContext->endpointType = - 4 * direction + endpoint->attributes & 3; + direction << 2 | endpoint->attributes & 3; endpointContext->maxPacketSize = endpoint->maxPacketSize; slot->endpointRings[endpointIndex] = malloc(sizeof(TrbRing)); setupTrbRing(slot->endpointRings[endpointIndex], 256); endpointContext->transferDequeuePointerLow = - U32(slot->endpointRings[endpointIndex]->physical) | 0; + U32(slot->endpointRings[endpointIndex]->physical) | 1; endpointContext->transferDequeuePointerHigh = 0; endpointContext->averageTRBLength = 2048; inputContext->inputControl.addContextFlags |= 1 << (endpointIndex + 1); @@ -135,9 +134,104 @@ await(serviceId, eventId); } +void setProtocol(SlotXHCI *slot) { + XHCISetupStageTRB setup = {0}; + setup.requestType = 0x21; + setup.request = 0x0B; + setup.value = 0; + setup.index = 0; + setup.length = 0; + setup.transferLength = 8; + setup.interruptOnCompletion = 0; + setup.interrupterTarget = 0; + setup.type = 2; + setup.transferType = 3; + setup.immediateData = 1; + XHCIStatusStageTRB status = {0}; + status.inDirection = 1; + status.evaluateNext = 0; + status.interruptOnCompletion = 1; + status.type = 4; + + enqueueCommand(slot->controlRing, (void *)&setup); + uint32_t commandAddress = + U32(enqueueCommand(slot->controlRing, (void *)&status)); + uint32_t eventId = createDirectEventSave(commandAddress); + slot->controller->doorbells[slot->slotIndex] = 1; + await(serviceId, eventId); +} + +void setIdle(SlotXHCI *slot) { + XHCISetupStageTRB setup = {0}; + setup.requestType = 0x21; + setup.request = 0x0A; + setup.value = 0; + setup.index = 0; + setup.length = 0; + setup.transferLength = 8; + setup.interruptOnCompletion = 0; + setup.interrupterTarget = 0; + setup.type = 2; + setup.transferType = 3; + setup.immediateData = 1; + XHCIStatusStageTRB status = {0}; + status.inDirection = 1; + status.evaluateNext = 0; + status.interruptOnCompletion = 1; + status.type = 4; + + enqueueCommand(slot->controlRing, (void *)&setup); + uint32_t commandAddress = + U32(enqueueCommand(slot->controlRing, (void *)&status)); + uint32_t eventId = createDirectEventSave(commandAddress); + slot->controller->doorbells[slot->slotIndex] = 1; + await(serviceId, eventId); +} + +void setupHID(SlotXHCI *slot, uint32_t endpointIndex, void *buffer) { + setProtocol(slot); + setIdle(slot); + // XHCIDataStageTRB data = {0}; + // data.dataBuffer[0] = U32(getPhysicalAddress(buffer)); + // data.inDirection = 1; + // data.transferSize = 8; + // data.type = 3; + // data.interrupterTarget = 0; + // data.interruptOnShortPacket = 1; + // data.interruptOnCompletion = 1; + + // XHCIStatusStageTRB status = {0}; + // status.inDirection = 1; + // status.evaluateNext = 0; + // status.interruptOnCompletion = 1; + // status.inDirection = 0; + // status.type = 4; + + XHCINormalTRB normal = {0}; + normal.type = 1; + normal.inDirection = 1; + normal.interrupterTarget = 0; + normal.interruptOnCompletion = 1; + normal.interruptOnShortPacket = 1; + normal.dataBuffer[0] = U32(getPhysicalAddress(buffer)); + normal.transferSize = 4; + + void *trb = (void *)enqueueCommand(slot->endpointRings[endpointIndex], + (void *)&normal); + // enqueueCommand(slot->controlRing, (void *)&status); + printf("enqueueing normal stage: %x on endpoint %i\n", trb, endpointIndex); + slot->controller->doorbells[slot->slotIndex] = endpointIndex + 1; + sleep(1000); + for (uint32_t i = 0; i < 10; i++) { + printf("%x ", ((uint32_t *)buffer)[i]); + } + printf("\n"); +} + UsbHostControllerInterface xhci = { .initialize = init, .getDeviceDescriptor = (void *)usbGetDeviceDescriptor, .setupEndpoints = (void *)xhciSetupEndpoints, + .setupHID = (void *)setupHID, .pciClass = 0x0C0330, }; diff --git a/src/userland/usb/xhci/xhci.h b/src/userland/usb/xhci/xhci.h index 8a21958..5693e36 100644 --- a/src/userland/usb/xhci/xhci.h +++ b/src/userland/usb/xhci/xhci.h @@ -108,6 +108,16 @@ } __attribute__((packed)) XHCIDataStageTRB; typedef volatile struct { + uint32_t dataBuffer[2]; + + uint32_t transferSize : 17, tdSize : 5, interrupterTarget : 10; + + uint32_t cycle : 1, evaluateNext : 1, interruptOnShortPacket : 1, + noSnoop : 1, chain : 1, interruptOnCompletion : 1, immediateData : 1, + reserved : 3, type : 6, inDirection : 1; +} __attribute__((packed)) XHCINormalTRB; + +typedef volatile struct { uint32_t routeString : 20, speed : 4, reserved : 1, multiTT : 1, isHub : 1, contextEntryCount : 5; uint32_t maxLatency : 16, rootHubPort : 8, portCount : 8;