Skip to content

Commit 905ab83

Browse files
committed
fix: separate host expected bytes from device intended bytes
1 parent 9118e91 commit 905ab83

File tree

5 files changed

+34
-29
lines changed

5 files changed

+34
-29
lines changed

src/machine/usb/msc/msc.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ type msc struct {
3535
respStatus csw.Status // Response status for the last command
3636
sendZLP bool // Flag to indicate if a zero-length packet should be sent before sending CSW
3737

38-
cbw *CBW // Last received Command Block Wrapper
39-
queuedBytes uint32 // Number of bytes queued for sending
40-
sentBytes uint32 // Number of bytes sent
41-
totalBytes uint32 // Total bytes to send
42-
cswBuf []byte // CSW response buffer
43-
state mscState
38+
cbw *CBW // Last received Command Block Wrapper
39+
queuedBytes uint32 // Number of bytes queued for sending
40+
sentBytes uint32 // Number of bytes sent
41+
transferBytes uint32 // Total bytes to send
42+
cswBuf []byte // CSW response buffer
43+
state mscState
4444

4545
maxLUN uint8 // Maximum Logical Unit Number (n-1 for n LUNs)
4646
dev machine.BlockDevice
@@ -160,8 +160,9 @@ func (m *msc) sendUSBPacket(b []byte) {
160160
func (m *msc) sendCSW(status csw.Status) {
161161
// Generate CSW packet into m.cswBuf and send it
162162
residue := uint32(0)
163-
if m.totalBytes >= m.sentBytes {
164-
residue = m.totalBytes - m.sentBytes
163+
expected := m.cbw.transferLength()
164+
if expected >= m.sentBytes {
165+
residue = expected - m.sentBytes
165166
}
166167
m.cbw.CSW(status, residue, m.cswBuf)
167168
m.state = mscStateStatusSent
@@ -245,7 +246,7 @@ func (m *msc) run(b []byte, isEpOut bool) bool {
245246

246247
// Move on to the data transfer phase next go around (after sending the first message)
247248
m.state = mscStateData
248-
m.totalBytes = cbw.transferLength()
249+
m.transferBytes = cbw.transferLength()
249250
m.queuedBytes = 0
250251
m.sentBytes = 0
251252
m.respStatus = csw.StatusPassed
@@ -281,7 +282,7 @@ func (m *msc) run(b []byte, isEpOut bool) bool {
281282
// to cycle back through this block, e.g. with TEST UNIT READY which sends only a CSW after
282283
// setting the sense key/add'l code/qualifier internally
283284
if m.state == mscStateStatus && !m.txStalled {
284-
if m.totalBytes > m.sentBytes && m.cbw.isIn() {
285+
if m.cbw.transferLength() > m.sentBytes && m.cbw.isIn() {
285286
// 6.7.2 The Thirteen Cases - Case 5 (Hi > Di): STALL before status
286287
m.stallEndpoint(usb.MSC_ENDPOINT_IN)
287288
} else if m.sendZLP {

src/machine/usb/msc/scsi.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ func (m *msc) scsiCmdBegin() {
2121
return
2222
}
2323

24-
if m.totalBytes > 0 && m.cbw.isOut() {
24+
if m.transferBytes > 0 && m.cbw.isOut() {
2525
// Reject any other multi-packet commands
26-
if m.totalBytes > m.maxPacketSize {
26+
if m.transferBytes > m.maxPacketSize {
2727
m.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidCmdOpCode)
2828
return
2929
} else {
@@ -53,7 +53,7 @@ func (m *msc) scsiCmdBegin() {
5353
}
5454

5555
if len(m.buf) == 0 {
56-
if m.totalBytes > 0 {
56+
if m.transferBytes > 0 {
5757
// 6.7.2 The Thirteen Cases - Case 4 (Hi > Dn)
5858
// https://usb.org/sites/default/files/usbmassbulk_10.pdf
5959
m.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, 0)
@@ -63,7 +63,7 @@ func (m *msc) scsiCmdBegin() {
6363
m.state = mscStateStatus
6464
}
6565
} else {
66-
if m.totalBytes == 0 {
66+
if m.transferBytes == 0 {
6767
// 6.7.1 The Thirteen Cases - Case 2 (Hn < Di)
6868
// https://usb.org/sites/default/files/usbmassbulk_10.pdf
6969
m.sendScsiError(csw.StatusFailed, scsi.SenseIllegalRequest, 0)
@@ -93,7 +93,7 @@ func (m *msc) scsiDataTransfer(b []byte) bool {
9393
// Update our sent bytes count to include the just-confirmed bytes
9494
m.sentBytes += m.queuedBytes
9595

96-
if m.sentBytes >= m.totalBytes {
96+
if m.sentBytes >= m.transferBytes {
9797
// Transfer complete, send CSW after transfer confirmed
9898
m.state = mscStateStatus
9999
} else if cmdType == scsi.CmdRead {
@@ -158,8 +158,8 @@ func (m *msc) scsiCmdModeSense(cmd scsi.Cmd) {
158158

159159
// The host allows a good amount of leeway in response size
160160
// Reset total bytes to what we'll actually send
161-
if m.totalBytes > respLen {
162-
m.totalBytes = respLen
161+
if m.transferBytes > respLen {
162+
m.transferBytes = respLen
163163
m.sendZLP = true
164164
}
165165

@@ -210,7 +210,7 @@ func (m *msc) scsiCmdRequestSense() {
210210
// Set the buffer size to the SCSI sense message size and clear
211211
m.resetBuffer(scsi.RequestSenseRespLen)
212212
m.queuedBytes = scsi.RequestSenseRespLen
213-
m.totalBytes = scsi.RequestSenseRespLen
213+
m.transferBytes = scsi.RequestSenseRespLen
214214

215215
// 0x70 - current error, 0x71 - deferred error (not used)
216216
m.buf[0] = 0xF0 // 0x70 for current error plus 0x80 for valid flag bit
@@ -266,7 +266,7 @@ func (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool {
266266
switch cmdType {
267267
case scsi.CmdWrite:
268268
// If we're writing data wait until we have a full write block of data that can be processed.
269-
if m.queuedBytes == uint32(cap(m.blockCache)) {
269+
if m.queuedBytes == uint32(cap(m.blockCache)) || (m.sentBytes+m.queuedBytes >= m.transferBytes) {
270270
m.taskQueued = true
271271
}
272272
case scsi.CmdUnmap:
@@ -279,7 +279,11 @@ func (m *msc) scsiQueueTask(cmdType scsi.CmdType, b []byte) bool {
279279

280280
func (m *msc) sendScsiError(status csw.Status, key scsi.Sense, code scsi.SenseCode) {
281281
// Generate CSW into m.cswBuf
282-
residue := m.totalBytes - m.sentBytes
282+
expected := m.cbw.transferLength()
283+
residue := uint32(0)
284+
if expected > m.sentBytes {
285+
residue = expected - m.sentBytes
286+
}
283287

284288
// Prepare to send CSW
285289
m.sendZLP = true // Ensure the transaction is signaled as ended before a CSW is sent
@@ -291,7 +295,7 @@ func (m *msc) sendScsiError(status csw.Status, key scsi.Sense, code scsi.SenseCo
291295
m.addlSenseCode = code
292296
m.addlSenseQualifier = 0x00 // Not used
293297

294-
if m.totalBytes > 0 && residue > 0 {
298+
if expected > 0 && residue > 0 {
295299
if m.cbw.isIn() {
296300
m.stallEndpoint(usb.MSC_ENDPOINT_IN)
297301
} else {

src/machine/usb/msc/scsi_inquiry.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ func (m *msc) scsiEvpdInquiry(cmd scsi.Cmd, pageCode uint8) {
136136

137137
// Set total bytes to the length of our response
138138
m.queuedBytes = uint32(len(m.buf))
139-
m.totalBytes = uint32(len(m.buf))
139+
m.transferBytes = uint32(len(m.buf))
140140
}
141141

142142
func (m *msc) scsiStdInquiry(cmd scsi.Cmd) {
143143
m.resetBuffer(scsi.InquiryRespLen)
144144
m.queuedBytes = scsi.InquiryRespLen
145-
m.totalBytes = scsi.InquiryRespLen
145+
m.transferBytes = scsi.InquiryRespLen
146146

147147
// byte 0 - Device Type (0x00 for direct access block device)
148148
// byte 1 - Removable media bit

src/machine/usb/msc/scsi_readwrite.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func (m *msc) scsiCmdReadWrite(cmd scsi.Cmd) {
1212
status := m.validateScsiReadWrite(cmd)
1313
if status != csw.StatusPassed {
1414
m.sendScsiError(status, scsi.SenseIllegalRequest, scsi.SenseCodeInvalidCmdOpCode)
15-
} else if m.totalBytes > 0 {
15+
} else if m.transferBytes > 0 {
1616
if cmd.CmdType() == scsi.CmdRead {
1717
m.scsiRead(cmd)
1818
} else {
@@ -28,7 +28,7 @@ func (m *msc) scsiCmdReadWrite(cmd scsi.Cmd) {
2828
func (m *msc) validateScsiReadWrite(cmd scsi.Cmd) csw.Status {
2929
blockCount := cmd.BlockCount()
3030
// CBW wrapper transfer length
31-
if m.totalBytes == 0 {
31+
if m.transferBytes == 0 {
3232
// If the SCSI command's block count doesn't loosely match the wrapper's transfer length something's wrong
3333
if blockCount > 0 {
3434
return csw.StatusPhaseError
@@ -50,7 +50,7 @@ func (m *msc) validateScsiReadWrite(cmd scsi.Cmd) csw.Status {
5050
// https://usb.org/sites/default/files/usbmassbulk_10.pdf
5151
return csw.StatusFailed
5252
}
53-
if m.totalBytes/blockCount == 0 {
53+
if m.transferBytes/blockCount == 0 {
5454
// Block size shouldn't be small enough to round to zero
5555
// 6.7.2 The Thirteen Cases - Case 7 (Hi < Di) READ(10) or
5656
// 6.7.3 The Thirteen Cases - Case 13 (Ho < Do) WRITE(10)
@@ -103,7 +103,7 @@ func (m *msc) writeBlock(b []byte, lba, offset uint32) (n int, err error) {
103103

104104
func (m *msc) scsiRead(cmd scsi.Cmd) {
105105
// Make sure we don't exceed the buffer size
106-
readEnd := m.totalBytes - m.sentBytes
106+
readEnd := m.transferBytes - m.sentBytes
107107
if readEnd > m.maxPacketSize {
108108
readEnd = m.maxPacketSize
109109
}
@@ -136,7 +136,7 @@ func (m *msc) scsiWrite(cmd scsi.Cmd, b []byte) {
136136
m.sentBytes += uint32(len(b))
137137
}
138138

139-
if m.sentBytes >= m.totalBytes {
139+
if m.sentBytes >= m.transferBytes {
140140
// Data transfer is complete, send CSW
141141
m.state = mscStateStatus
142142
m.run([]byte{}, true)

src/machine/usb/msc/scsi_unmap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (m *msc) scsiUnmap(b []byte) {
6060
// FIXME: We need to handle erase block alignment
6161

6262
m.sentBytes += uint32(len(b))
63-
if m.sentBytes >= m.totalBytes {
63+
if m.sentBytes >= m.transferBytes {
6464
// Order 66 complete, send CSW to establish galactic empire
6565
m.state = mscStateStatus
6666
m.run([]byte{}, true)

0 commit comments

Comments
 (0)