mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 19:17:47 +00:00
Compare commits
1 Commits
release
...
usb-msc-erase
| Author | SHA1 | Date | |
|---|---|---|---|
| 465bde5df6 |
@@ -1,11 +1,13 @@
|
|||||||
package msc
|
package msc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"machine"
|
"machine"
|
||||||
"machine/usb"
|
"machine/usb"
|
||||||
"machine/usb/descriptor"
|
"machine/usb/descriptor"
|
||||||
"machine/usb/msc/csw"
|
"machine/usb/msc/csw"
|
||||||
"machine/usb/msc/scsi"
|
"machine/usb/msc/scsi"
|
||||||
|
"math/bits"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,6 +25,8 @@ const (
|
|||||||
mscInterface = 2
|
mscInterface = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errInvalidBlockSize = errors.New("usb/msc: invalid block size")
|
||||||
|
|
||||||
var MSC *msc
|
var MSC *msc
|
||||||
|
|
||||||
type msc struct {
|
type msc struct {
|
||||||
@@ -60,20 +64,41 @@ type msc struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Port returns the USB Mass Storage port
|
// Port returns the USB Mass Storage port
|
||||||
func Port(dev machine.BlockDevice) *msc {
|
func Port(dev machine.BlockDevice) (*msc, error) {
|
||||||
if MSC == nil {
|
if MSC == nil {
|
||||||
MSC = newMSC(dev)
|
msc, err := newMSC(dev)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
MSC = msc
|
||||||
}
|
}
|
||||||
return MSC
|
return MSC, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMSC(dev machine.BlockDevice) *msc {
|
func newMSC(dev machine.BlockDevice) (*msc, error) {
|
||||||
// Size our buffer to match the maximum packet size of the IN endpoint
|
// Size our buffer to match the maximum packet size of the IN endpoint
|
||||||
maxPacketSize := descriptor.EndpointMSCIN.GetMaxPacketSize()
|
maxPacketSize := descriptor.EndpointMSCIN.GetMaxPacketSize()
|
||||||
|
|
||||||
|
// Windows only supports block sizes of 512 or 4096 bytes, other systems are
|
||||||
|
// probably similar.
|
||||||
|
blockSize := max(dev.EraseBlockSize(), dev.WriteBlockSize())
|
||||||
|
if bits.OnesCount32(uint32(blockSize)) != 1 {
|
||||||
|
return nil, errInvalidBlockSize // not a power of two
|
||||||
|
}
|
||||||
|
var blockSizeUSB uint32
|
||||||
|
switch {
|
||||||
|
case blockSize <= 512:
|
||||||
|
blockSizeUSB = 512
|
||||||
|
case blockSize <= 4096:
|
||||||
|
blockSizeUSB = 4096
|
||||||
|
default:
|
||||||
|
return nil, errInvalidBlockSize
|
||||||
|
}
|
||||||
|
|
||||||
m := &msc{
|
m := &msc{
|
||||||
// Some platforms require reads/writes to be aligned to the full underlying hardware block
|
// Some platforms require reads/writes to be aligned to the full underlying hardware block
|
||||||
blockCache: make([]byte, dev.WriteBlockSize()),
|
blockCache: make([]byte, dev.WriteBlockSize()),
|
||||||
blockSizeUSB: 512,
|
blockSizeUSB: blockSizeUSB,
|
||||||
buf: make([]byte, dev.WriteBlockSize()),
|
buf: make([]byte, dev.WriteBlockSize()),
|
||||||
cswBuf: make([]byte, csw.MsgLen),
|
cswBuf: make([]byte, csw.MsgLen),
|
||||||
cbw: &CBW{Data: make([]byte, 31)},
|
cbw: &CBW{Data: make([]byte, 31)},
|
||||||
@@ -114,7 +139,7 @@ func newMSC(dev machine.BlockDevice) *msc {
|
|||||||
|
|
||||||
go m.processTasks()
|
go m.processTasks()
|
||||||
|
|
||||||
return m
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *msc) processTasks() {
|
func (m *msc) processTasks() {
|
||||||
|
|||||||
@@ -91,6 +91,16 @@ func (m *msc) writeBlock(b []byte, lba, offset uint32) (n int, err error) {
|
|||||||
return 0, invalidWriteError
|
return 0, invalidWriteError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erase the block first if needed.
|
||||||
|
// Data packets arrive in order, so if we want to write to the start of a
|
||||||
|
// block, that means it's the first write to this erase block and it needs
|
||||||
|
// to be erased first.
|
||||||
|
if uint32(blockStart)%m.blockSizeUSB == 0 {
|
||||||
|
firstBlock := uint32(blockStart) / uint32(m.dev.EraseBlockSize())
|
||||||
|
numBlocks := (m.blockSizeUSB + uint32(m.dev.EraseBlockSize()) - 1) / uint32(m.dev.EraseBlockSize())
|
||||||
|
m.dev.EraseBlocks(int64(firstBlock), int64(numBlocks))
|
||||||
|
}
|
||||||
|
|
||||||
// Write the full block to the underlying device
|
// Write the full block to the underlying device
|
||||||
n, err = m.dev.WriteAt(b, blockStart)
|
n, err = m.dev.WriteAt(b, blockStart)
|
||||||
n -= int(blockOffset)
|
n -= int(blockOffset)
|
||||||
|
|||||||
Reference in New Issue
Block a user