Skip to content

Commit d172198

Browse files
committed
Improve USB device detection
1 parent 0d630fe commit d172198

File tree

6 files changed

+68
-23
lines changed

6 files changed

+68
-23
lines changed

DEBUGGING.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Debugging tips
2+
3+
## usb
4+
5+
- https://github.com/qemu/qemu/blob/master/docs/usb2.txt
6+
```
7+
device_add usb-mouse,id=usbmouse_hotplug,port=4
8+
device_del usbmouse_hotplug
9+
```

qemu.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ PORT_VNC=5
99
QEMU_ARGS_COMMON_HW_CONFIG=\
1010
-machine q35,nvdimm=on -cpu qemu64 -smp 4 \
1111
-bios $(OVMF) \
12-
-device qemu-xhci -device usb-mouse \
12+
-device qemu-xhci -device usb-mouse,id=usbmouse1 \
1313
-netdev user,id=usbnet0 -device usb-net,netdev=usbnet0 \
1414
-object filter-dump,id=f2,netdev=usbnet0,file=dump_usb_nic.dat \
1515
-m 2G,slots=2,maxmem=4G \

src/hpet.cc

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ void HPET::BusyWaitMicroSecond(uint64_t microsec) {
8484
uint64_t HPET::GetFemtosecondPerCount() {
8585
return femtosecond_per_count_;
8686
}
87+
uint64_t HPET::GetCountPerSecond() {
88+
return 1e15 / femtosecond_per_count_;
89+
}
8790

8891
void HPET::Print() {
8992
PutStringAndHex("HPET at", registers_);

src/hpet.h

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class HPET {
2020
HPET::TimerConfig flags);
2121
uint64_t ReadMainCounterValue();
2222
uint64_t GetFemtosecondPerCount();
23+
uint64_t GetCountPerSecond();
2324
void BusyWait(uint64_t ms);
2425
void BusyWaitMicroSecond(uint64_t);
2526
void Print(void);

src/xhci.cc

+49-21
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,14 @@ void Controller::ResetPort(int port) {
153153
while ((ReadPORTSC(port) & kPortSCBitPortReset)) {
154154
// wait
155155
}
156-
port_state_[port] = kNeedsSlotAssignment;
157-
port_is_initializing_[port] = true;
156+
port_state_[port] = kDisabled;
157+
port_is_initializing_[port] = false;
158158
}
159159

160160
void Controller::DisablePort(int port) {
161161
PutStringAndHex("Disable port", port);
162162
WritePORTSC(port, 2);
163-
port_state_[port] = kDisabled;
164-
port_is_initializing_[port] = false;
163+
ResetPort(port);
165164
}
166165

167166
class Controller::EndpointContext {
@@ -712,6 +711,7 @@ void Controller::HandleAddressDeviceCompleted(int slot) {
712711
uint8_t* buf = AllocMemoryForMappedIO<uint8_t*>(kSizeOfDescriptorBuffer);
713712
descriptor_buffers_[slot] = buf;
714713
port_is_initializing_[slot_info_[slot].port] = false;
714+
kprintf("AddressDevice for port %d completed\n", slot_info_[slot].port);
715715
RequestDeviceDescriptor(slot, SlotInfo::kWaitingForDeviceDescriptor);
716716
}
717717

@@ -858,24 +858,25 @@ void Controller::HandleTransferEvent(BasicTRB& e) {
858858
}
859859
}
860860

861+
static void PrintPortSCValue(uint32_t portsc) {
862+
PutStringAndHex("PORTSC", portsc);
863+
PutString("PortSC: ");
864+
PutHex64ZeroFilled(portsc);
865+
PutString(" (");
866+
PutString((portsc & (1 << 9)) ? "1" : "0");
867+
PutString((portsc & (1 << 0)) ? "1" : "0");
868+
PutString((portsc & (1 << 1)) ? "1" : "0");
869+
PutString((portsc & (1 << 4)) ? "1" : "0");
870+
PutString(") ");
871+
// 7.2.2.1.1 Default USB Speed ID Mapping
872+
PutString("Speed=0x");
873+
PutHex64(GetBits<13, 10>(portsc));
874+
PutString("\n");
875+
}
861876
void Controller::PrintPortSC() {
862877
for (int slot = 1; slot <= num_of_slots_enabled_; slot++) {
863-
uint32_t portsc = ReadPORTSC(slot);
864878
PutStringAndHex("Port", slot);
865-
PutStringAndHex("PORTSC", portsc);
866-
PutString("PortSC: ");
867-
PutHex64ZeroFilled(portsc);
868-
PutString(" (");
869-
PutString((portsc & (1 << 9)) ? "1" : "0");
870-
PutString((portsc & (1 << 0)) ? "1" : "0");
871-
PutString((portsc & (1 << 1)) ? "1" : "0");
872-
PutString((portsc & (1 << 4)) ? "1" : "0");
873-
PutString(") ");
874-
// 7.2.2.1.1 Default USB Speed ID Mapping
875-
PutString("Speed=0x");
876-
PutHex64(GetBits<13, 10>(portsc));
877-
878-
PutString("\n");
879+
PrintPortSCValue(ReadPORTSC(slot));
879880
}
880881
}
881882
void Controller::PrintUSBSTS() {
@@ -891,6 +892,7 @@ void Controller::PrintUSBSTS() {
891892
}
892893

893894
void Controller::CheckPortAndInitiateProcess() {
895+
HPET& hpet = HPET::GetInstance();
894896
for (int i = 0; i < kMaxNumOfPorts; i++) {
895897
if (port_state_[i] == kNeedsSlotAssignment) {
896898
port_state_[i] = kWaitingForSlotAssignment;
@@ -903,16 +905,28 @@ void Controller::CheckPortAndInitiateProcess() {
903905
enable_slot_trb.control = (BasicTRB::kTRBTypeEnableSlotCommand << 10);
904906
cmd_ring_->Push();
905907
NotifyHostControllerDoorbell();
908+
kprintf("Sent slot assignment request for port%d\n", i);
906909
return;
907910
}
908911
}
909912
for (int i = 0; i < kMaxNumOfPorts; i++) {
910-
if (port_is_initializing_[i])
911-
return;
913+
if (!port_is_initializing_[i]) {
914+
continue;
915+
}
916+
if (port_init_deadline_ < hpet.ReadMainCounterValue()) {
917+
kprintf("Port init deadline exceeded for port %d\n", i);
918+
DisablePort(i);
919+
}
920+
return;
912921
}
913922
for (int i = 0; i < kMaxNumOfPorts; i++) {
914923
if (port_state_[i] == kAttachedUSB2) {
915924
ResetPort(i);
925+
port_state_[i] = kNeedsSlotAssignment;
926+
port_is_initializing_[i] = true;
927+
kprintf("Port init deadline for port %d is set.\n", i);
928+
port_init_deadline_ =
929+
hpet.ReadMainCounterValue() + hpet.GetCountPerSecond();
916930
return;
917931
}
918932
}
@@ -990,13 +1004,27 @@ void Controller::PollEvents() {
9901004
}
9911005
for (int port = 1; port <= max_ports_; port++) {
9921006
uint32_t portsc = ReadPORTSC(port);
1007+
if (!(portsc & kPortSCBitCurrentConnectStatus)) {
1008+
// Device is disconnected
1009+
if (port_state_[port] == kDisconnected) {
1010+
continue;
1011+
}
1012+
DisablePort(port);
1013+
port_state_[port] = kDisconnected;
1014+
kprintf("port %d disconnected\n", port);
1015+
PrintPortSCValue(ReadPORTSC(port));
1016+
continue;
1017+
}
9931018
if (port_state_[port] == kDisconnected &&
9941019
(portsc & kPortSCBitCurrentConnectStatus)) {
1020+
kprintf("port %d connected\n", port);
1021+
PrintPortSCValue(ReadPORTSC(port));
9951022
port_state_[port] = kAttached;
9961023
}
9971024
if (port_state_[port] == kAttached &&
9981025
!(portsc & kPortSCBitPortEnableDisable) &&
9991026
!(portsc & kPortSCBitPortReset) && ReadPORTSCLinkState(port) == 7) {
1027+
kprintf("port %d: kAttachedUSB2\n", port);
10001028
port_state_[port] = kAttachedUSB2;
10011029
}
10021030
}

src/xhci.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,11 @@ class Controller {
274274
static constexpr uint32_t kUSBCMDMaskRunStop = 0b01;
275275
static constexpr uint32_t kUSBCMDMaskHCReset = 0b10;
276276

277+
/*
278+
* PORTSC values
279+
*/
277280
static constexpr uint32_t kPortSCBitCurrentConnectStatus = 1 << 0;
278-
static constexpr uint32_t kPortSCBitPortEnableDisable = 1 << 1;
281+
static constexpr uint32_t kPortSCBitPortEnableDisable = 1 << 1; // RW1CS
279282
static constexpr uint32_t kPortSCBitPortReset = 1 << 4;
280283
static constexpr uint32_t kPortSCBitPortLinkState = 0b111100000;
281284
static constexpr uint32_t kPortSCPortLinkStateShift = 5;
@@ -404,6 +407,7 @@ class Controller {
404407
bool controller_reset_requested_ = false;
405408
int max_num_of_scratch_pad_buf_entries_;
406409
volatile uint64_t* scratchpad_buffer_array_;
410+
uint64_t port_init_deadline_;
407411
};
408412

409413
} // namespace XHCI

0 commit comments

Comments
 (0)