Fix Darwin USB/IP availability and doorbell handling

This commit is contained in:
世界
2026-04-24 05:07:15 +08:00
parent 3cfe767ae4
commit 9ea04956fa
3 changed files with 56 additions and 10 deletions
+9 -2
View File
@@ -882,15 +882,22 @@ func (c *darwinVirtualController) handleDoorbell(doorbell uint32) {
c.logger.Debug("process doorbell: ", err)
return
}
var previousNoResponse unsafe.Pointer
for {
transfer := endpoint.currentTransfer()
if transfer.ptr == nil || !transfer.message.valid() {
return
}
status, length := c.handleTransfer(key, transfer.message)
if transfer.message.noResponse() {
return
if transfer.ptr == previousNoResponse {
return
}
previousNoResponse = transfer.ptr
c.handleTransfer(key, transfer.message)
continue
}
previousNoResponse = nil
status, length := c.handleTransfer(key, transfer.message)
if err := endpoint.complete(transfer, darwinUSBIPStatusToCIStatus(status), length); err != nil {
c.logger.Debug("complete transfer: ", err)
c.Close()
+39 -7
View File
@@ -205,8 +205,8 @@ func TestWaitDarwinControllerClosesOnContextCancel(t *testing.T) {
}
type fakeDarwinEndpointStateMachine struct {
transfer darwinCITransfer
currentRead bool
transfers []darwinCITransfer
currentRead int
completeCalled int
}
@@ -221,11 +221,12 @@ func (f *fakeDarwinEndpointStateMachine) processDoorbell(uint32) error {
}
func (f *fakeDarwinEndpointStateMachine) currentTransfer() darwinCITransfer {
if f.currentRead {
if f.currentRead >= len(f.transfers) {
return darwinCITransfer{}
}
f.currentRead = true
return f.transfer
transfer := f.transfers[f.currentRead]
f.currentRead++
return transfer
}
func (f *fakeDarwinEndpointStateMachine) complete(darwinCITransfer, int, int) error {
@@ -242,10 +243,10 @@ func TestDarwinHandleDoorbellSkipsNoResponseCompletion(t *testing.T) {
data0: (uint32(2) << 8) | 1,
}
endpoint := &fakeDarwinEndpointStateMachine{
transfer: darwinCITransfer{
transfers: []darwinCITransfer{{
ptr: unsafe.Pointer(&message),
message: message,
},
}},
}
controller.endpoints[darwinEndpointKey{device: 1, endpoint: 2}] = endpoint
@@ -253,6 +254,37 @@ func TestDarwinHandleDoorbellSkipsNoResponseCompletion(t *testing.T) {
require.Zero(t, endpoint.completeCalled)
}
func TestDarwinHandleDoorbellContinuesAfterNoResponseTransfer(t *testing.T) {
t.Parallel()
controller := newDarwinVirtualController(context.Background(), newTestLogger(), nil, DeviceInfoTruncated{})
noResponseMessage := darwinCIMessage{
control: (1 << 15) | (1 << 14) | 0x3c,
data0: (uint32(2) << 8) | 1,
}
responseMessage := darwinCIMessage{
control: (1 << 15) | 0x3c,
data0: (uint32(2) << 8) | 1,
}
endpoint := &fakeDarwinEndpointStateMachine{
transfers: []darwinCITransfer{
{
ptr: unsafe.Pointer(&noResponseMessage),
message: noResponseMessage,
},
{
ptr: unsafe.Pointer(&responseMessage),
message: responseMessage,
},
},
}
controller.endpoints[darwinEndpointKey{device: 1, endpoint: 2}] = endpoint
controller.handleDoorbell((uint32(2) << 8) | 1)
require.Equal(t, 1, endpoint.completeCalled)
require.Equal(t, 2, endpoint.currentRead)
}
func startDarwinFakeUSBIPServer(t *testing.T) *darwinFakeUSBIPServer {
t.Helper()
+8 -1
View File
@@ -384,7 +384,12 @@ func (s *ServerService) handleImport(conn net.Conn) {
_ = WriteOpRepImport(conn, OpStatusError, nil)
return
}
defer s.releaseClaim(busid)
releaseClaim := true
defer func() {
if releaseClaim {
s.releaseClaim(busid)
}
}()
info := export.entry.Info
if err := WriteOpRepImport(conn, OpStatusOK, &info); err != nil {
s.logger.Warn("reply import ", busid, ": ", err)
@@ -395,6 +400,8 @@ func (s *ServerService) handleImport(conn net.Conn) {
if err := session.serve(); err != nil && s.ctx.Err() == nil {
s.logger.Debug("data session ", busid, ": ", err)
}
s.releaseClaim(busid)
releaseClaim = false
s.broadcastChanged()
}