mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 80c89809a9 |
@@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) {
|
|||||||
// microcontrollers
|
// microcontrollers
|
||||||
{"hifive1b", "examples/echo", 3668, 280, 0, 2244},
|
{"hifive1b", "examples/echo", 3668, 280, 0, 2244},
|
||||||
{"microbit", "examples/serial", 2694, 342, 8, 2248},
|
{"microbit", "examples/serial", 2694, 342, 8, 2248},
|
||||||
{"wioterminal", "examples/pininterrupt", 7187, 1489, 116, 6888},
|
{"wioterminal", "examples/pininterrupt", 6833, 1491, 120, 6888},
|
||||||
|
|
||||||
// TODO: also check wasm. Right now this is difficult, because
|
// TODO: also check wasm. Right now this is difficult, because
|
||||||
// wasm binaries are run through wasm-opt and therefore the
|
// wasm binaries are run through wasm-opt and therefore the
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ func handleUSBSetAddress(setup usb.Setup) bool {
|
|||||||
|
|
||||||
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
|
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
|
||||||
func SendUSBInPacket(ep uint32, data []byte) bool {
|
func SendUSBInPacket(ep uint32, data []byte) bool {
|
||||||
sendUSBPacket(ep, data, 0)
|
sendUSBPacket(ep, data)
|
||||||
|
|
||||||
// clear transfer complete flag
|
// clear transfer complete flag
|
||||||
setEPINTFLAG(ep, sam.USB_DEVICE_EPINTFLAG_TRCPT1)
|
setEPINTFLAG(ep, sam.USB_DEVICE_EPINTFLAG_TRCPT1)
|
||||||
@@ -351,27 +351,28 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
|
|||||||
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
||||||
//
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
|
func sendUSBPacket(ep uint32, data []byte) {
|
||||||
l := uint16(len(data))
|
// Select the corresponding buffer.
|
||||||
if 0 < maxsize && maxsize < l {
|
buffer := udd_ep_control_cache_buffer[:]
|
||||||
l = maxsize
|
if ep != 0 {
|
||||||
|
buffer = udd_ep_in_cache_buffer[ep][:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set endpoint address for sending data
|
// Copy the packet to the buffer.
|
||||||
if ep == 0 {
|
copy(buffer[:len(data)], data)
|
||||||
copy(udd_ep_control_cache_buffer[:], data[:l])
|
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_control_cache_buffer))))
|
// Select the corresponding endpoint descriptor.
|
||||||
} else {
|
endpoint := &usbEndpointDescriptors[ep].DeviceDescBank[1]
|
||||||
copy(udd_ep_in_cache_buffer[ep][:], data[:l])
|
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))
|
// Set the endpoint address.
|
||||||
}
|
endpoint.ADDR.Set(uint32(uintptr(unsafe.Pointer(unsafe.SliceData(buffer)))))
|
||||||
|
|
||||||
// clear multi-packet size which is total bytes already sent
|
// clear multi-packet size which is total bytes already sent
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)
|
endpoint.PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)
|
||||||
|
|
||||||
// set byte count, which is total number of bytes to be sent
|
// set byte count, which is total number of bytes to be sent
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
endpoint.PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits((uint32(l) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
endpoint.PCKSIZE.SetBits((uint32(len(data)) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
|
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ func handleUSBSetAddress(setup usb.Setup) bool {
|
|||||||
|
|
||||||
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
|
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
|
||||||
func SendUSBInPacket(ep uint32, data []byte) bool {
|
func SendUSBInPacket(ep uint32, data []byte) bool {
|
||||||
sendUSBPacket(ep, data, 0)
|
sendUSBPacket(ep, data)
|
||||||
|
|
||||||
// clear transfer complete flag
|
// clear transfer complete flag
|
||||||
setEPINTFLAG(ep, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)
|
setEPINTFLAG(ep, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)
|
||||||
@@ -354,27 +354,28 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
|
|||||||
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
||||||
//
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
|
func sendUSBPacket(ep uint32, data []byte) {
|
||||||
l := uint16(len(data))
|
// Select the corresponding buffer.
|
||||||
if 0 < maxsize && maxsize < l {
|
buffer := udd_ep_control_cache_buffer[:]
|
||||||
l = maxsize
|
if ep != 0 {
|
||||||
|
buffer = udd_ep_in_cache_buffer[ep][:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set endpoint address for sending data
|
// Copy the packet to the buffer.
|
||||||
if ep == 0 {
|
copy(buffer[:len(data)], data)
|
||||||
copy(udd_ep_control_cache_buffer[:], data[:l])
|
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_control_cache_buffer))))
|
// Select the corresponding endpoint descriptor.
|
||||||
} else {
|
endpoint := &usbEndpointDescriptors[ep].DeviceDescBank[1]
|
||||||
copy(udd_ep_in_cache_buffer[ep][:], data[:l])
|
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))
|
// Set the endpoint address.
|
||||||
}
|
endpoint.ADDR.Set(uint32(uintptr(unsafe.Pointer(unsafe.SliceData(buffer)))))
|
||||||
|
|
||||||
// clear multi-packet size which is total bytes already sent
|
// clear multi-packet size which is total bytes already sent
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)
|
endpoint.PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask << usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos)
|
||||||
|
|
||||||
// set byte count, which is total number of bytes to be sent
|
// set byte count, which is total number of bytes to be sent
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
endpoint.PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits((uint32(l) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
endpoint.PCKSIZE.SetBits((uint32(len(data)) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
|
func ReceiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ func initEndpoint(ep, config uint32) {
|
|||||||
|
|
||||||
// SendUSBInPacket sends a packet for USBHID (interrupt in / bulk in).
|
// SendUSBInPacket sends a packet for USBHID (interrupt in / bulk in).
|
||||||
func SendUSBInPacket(ep uint32, data []byte) bool {
|
func SendUSBInPacket(ep uint32, data []byte) bool {
|
||||||
sendUSBPacket(ep, data, 0)
|
sendUSBPacket(ep, data)
|
||||||
|
|
||||||
// clear transfer complete flag
|
// clear transfer complete flag
|
||||||
nrf.USBD.INTENCLR.Set(nrf.USBD_INTENCLR_ENDEPOUT0 << 4)
|
nrf.USBD.INTENCLR.Set(nrf.USBD_INTENCLR_ENDEPOUT0 << 4)
|
||||||
@@ -267,33 +267,32 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
|
|||||||
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
||||||
//
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
|
func sendUSBPacket(ep uint32, data []byte) {
|
||||||
|
// Select the corresponding buffer.
|
||||||
count := len(data)
|
count := len(data)
|
||||||
if 0 < int(maxsize) && int(maxsize) < count {
|
var buffer []byte
|
||||||
count = int(maxsize)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ep == 0 {
|
if ep == 0 {
|
||||||
copy(udd_ep_control_cache_buffer[:], data[:count])
|
buffer = udd_ep_control_cache_buffer[:]
|
||||||
if count > usb.EndpointPacketSize {
|
if count > usb.EndpointPacketSize {
|
||||||
|
// The packet must be sent in chunks.
|
||||||
sendOnEP0DATADONE.offset = usb.EndpointPacketSize
|
sendOnEP0DATADONE.offset = usb.EndpointPacketSize
|
||||||
sendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset]
|
sendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[usb.EndpointPacketSize]
|
||||||
sendOnEP0DATADONE.count = count - usb.EndpointPacketSize
|
sendOnEP0DATADONE.count = count - usb.EndpointPacketSize
|
||||||
count = usb.EndpointPacketSize
|
count = usb.EndpointPacketSize
|
||||||
}
|
}
|
||||||
sendViaEPIn(
|
|
||||||
ep,
|
|
||||||
&udd_ep_control_cache_buffer[0],
|
|
||||||
count,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
copy(udd_ep_in_cache_buffer[ep][:], data[:count])
|
buffer = udd_ep_in_cache_buffer[ep][:]
|
||||||
sendViaEPIn(
|
|
||||||
ep,
|
|
||||||
&udd_ep_in_cache_buffer[ep][0],
|
|
||||||
count,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy the packet to the buffer.
|
||||||
|
copy(buffer[:len(data)], data)
|
||||||
|
|
||||||
|
// Send the first chunk of the packet.
|
||||||
|
sendViaEPIn(
|
||||||
|
ep,
|
||||||
|
&buffer[0],
|
||||||
|
count,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleEndpointRx(ep uint32) []byte {
|
func handleEndpointRx(ep uint32) []byte {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func handleUSBSetAddress(setup usb.Setup) bool {
|
|||||||
const ackTimeout = 570
|
const ackTimeout = 570
|
||||||
|
|
||||||
rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_ACK_REC)
|
rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_ACK_REC)
|
||||||
sendUSBPacket(0, []byte{}, 0)
|
sendUSBPacket(0, []byte{})
|
||||||
|
|
||||||
// Wait for transfer to complete with a timeout.
|
// Wait for transfer to complete with a timeout.
|
||||||
t := timer.timeElapsed()
|
t := timer.timeElapsed()
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ func handleUSBSetAddress(setup usb.Setup) bool {
|
|||||||
const ackTimeout = 570
|
const ackTimeout = 570
|
||||||
|
|
||||||
rp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_ACK_REC)
|
rp.USB.SIE_STATUS.Set(rp.USB_SIE_STATUS_ACK_REC)
|
||||||
sendUSBPacket(0, []byte{}, 0)
|
sendUSBPacket(0, []byte{})
|
||||||
|
|
||||||
// Wait for transfer to complete with a timeout.
|
// Wait for transfer to complete with a timeout.
|
||||||
t := timer.timeElapsed()
|
t := timer.timeElapsed()
|
||||||
|
|||||||
@@ -72,19 +72,15 @@ func initEndpoint(ep, config uint32) {
|
|||||||
|
|
||||||
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
|
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
|
||||||
func SendUSBInPacket(ep uint32, data []byte) bool {
|
func SendUSBInPacket(ep uint32, data []byte) bool {
|
||||||
sendUSBPacket(ep, data, 0)
|
sendUSBPacket(ep, data)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
|
||||||
//
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
|
func sendUSBPacket(ep uint32, data []byte) {
|
||||||
count := len(data)
|
count := len(data)
|
||||||
if 0 < int(maxsize) && int(maxsize) < count {
|
|
||||||
count = int(maxsize)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ep == 0 {
|
if ep == 0 {
|
||||||
if count > usb.EndpointPacketSize {
|
if count > usb.EndpointPacketSize {
|
||||||
count = usb.EndpointPacketSize
|
count = usb.EndpointPacketSize
|
||||||
@@ -145,7 +141,7 @@ func setEPDataPID(ep uint32, dataOne bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendZlp() {
|
func SendZlp() {
|
||||||
sendUSBPacket(0, []byte{}, 0)
|
sendUSBPacket(0, []byte{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendViaEPIn(ep uint32, data []byte, count int) {
|
func sendViaEPIn(ep uint32, data []byte, count int) {
|
||||||
|
|||||||
+72
-37
@@ -81,21 +81,6 @@ func usbSerial() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// strToUTF16LEDescriptor converts a utf8 string into a string descriptor
|
|
||||||
// note: the following code only converts ascii characters to UTF16LE. In order
|
|
||||||
// to do a "proper" conversion, we would need to pull in the 'unicode/utf16'
|
|
||||||
// package, which at the time this was written added 512 bytes to the compiled
|
|
||||||
// binary.
|
|
||||||
func strToUTF16LEDescriptor(in string, out []byte) {
|
|
||||||
out[0] = byte(len(out))
|
|
||||||
out[1] = descriptor.TypeString
|
|
||||||
for i, rune := range in {
|
|
||||||
out[(i<<1)+2] = byte(rune)
|
|
||||||
out[(i<<1)+3] = 0
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const cdcLineInfoSize = 7
|
const cdcLineInfoSize = 7
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -137,51 +122,53 @@ var (
|
|||||||
usbStallHandler [NumberOfUSBEndpoints]func(usb.Setup) bool
|
usbStallHandler [NumberOfUSBEndpoints]func(usb.Setup) bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var usbLangInfo = [4]byte{
|
||||||
|
// length = 4 bytes
|
||||||
|
0x04,
|
||||||
|
// descriptor type = string
|
||||||
|
0x03,
|
||||||
|
// language codes
|
||||||
|
// 0x0409 = English (United States)
|
||||||
|
0x09, 0x04,
|
||||||
|
}
|
||||||
|
|
||||||
// sendDescriptor creates and sends the various USB descriptor types that
|
// sendDescriptor creates and sends the various USB descriptor types that
|
||||||
// can be requested by the host.
|
// can be requested by the host.
|
||||||
func sendDescriptor(setup usb.Setup) {
|
func sendDescriptor(setup usb.Setup) {
|
||||||
switch setup.WValueH {
|
switch setup.WValueH {
|
||||||
case descriptor.TypeConfiguration:
|
case descriptor.TypeConfiguration:
|
||||||
sendUSBPacket(0, usbDescriptor.Configuration, setup.WLength)
|
sendDescriptorData(usbDescriptor.Configuration, setup.WLength)
|
||||||
return
|
return
|
||||||
|
|
||||||
case descriptor.TypeDevice:
|
case descriptor.TypeDevice:
|
||||||
usbDescriptor.Configure(usbVendorID(), usbProductID())
|
usbDescriptor.Configure(usbVendorID(), usbProductID())
|
||||||
sendUSBPacket(0, usbDescriptor.Device, setup.WLength)
|
sendDescriptorData(usbDescriptor.Device, setup.WLength)
|
||||||
return
|
return
|
||||||
|
|
||||||
case descriptor.TypeString:
|
case descriptor.TypeString:
|
||||||
switch setup.WValueL {
|
switch setup.WValueL {
|
||||||
case 0:
|
case 0:
|
||||||
usb_trans_buffer[0] = 0x04
|
sendDescriptorData(usbLangInfo[:], setup.WLength)
|
||||||
usb_trans_buffer[1] = 0x03
|
|
||||||
usb_trans_buffer[2] = 0x09
|
|
||||||
usb_trans_buffer[3] = 0x04
|
|
||||||
sendUSBPacket(0, usb_trans_buffer[:4], setup.WLength)
|
|
||||||
|
|
||||||
case usb.IPRODUCT:
|
case usb.IPRODUCT:
|
||||||
b := usb_trans_buffer[:(len(usbProduct())<<1)+2]
|
sendDescriptorString(usbProduct(), setup.WLength)
|
||||||
strToUTF16LEDescriptor(usbProduct(), b)
|
|
||||||
sendUSBPacket(0, b, setup.WLength)
|
|
||||||
|
|
||||||
case usb.IMANUFACTURER:
|
case usb.IMANUFACTURER:
|
||||||
b := usb_trans_buffer[:(len(usbManufacturer())<<1)+2]
|
sendDescriptorString(usbManufacturer(), setup.WLength)
|
||||||
strToUTF16LEDescriptor(usbManufacturer(), b)
|
|
||||||
sendUSBPacket(0, b, setup.WLength)
|
|
||||||
|
|
||||||
case usb.ISERIAL:
|
case usb.ISERIAL:
|
||||||
sz := len(usbSerial())
|
serial := usbSerial()
|
||||||
if sz == 0 {
|
if len(serial) == 0 {
|
||||||
SendZlp()
|
SendZlp()
|
||||||
} else {
|
} else {
|
||||||
b := usb_trans_buffer[:(sz<<1)+2]
|
sendDescriptorString(serial, setup.WLength)
|
||||||
strToUTF16LEDescriptor(usbSerial(), b)
|
|
||||||
sendUSBPacket(0, b, setup.WLength)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: why do we do this when WValueL is unknown?
|
||||||
return
|
return
|
||||||
case descriptor.TypeHIDReport:
|
case descriptor.TypeHIDReport:
|
||||||
if h, ok := usbDescriptor.HID[setup.WIndex]; ok {
|
if h, ok := usbDescriptor.HID[setup.WIndex]; ok {
|
||||||
sendUSBPacket(0, h, setup.WLength)
|
sendDescriptorData(h, setup.WLength)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case descriptor.TypeDeviceQualifier:
|
case descriptor.TypeDeviceQualifier:
|
||||||
@@ -194,6 +181,39 @@ func sendDescriptor(setup usb.Setup) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendDescriptorString sends a string descriptor, truncating it to fit maxLen or the buffer size.
|
||||||
|
// note: the following code only converts ascii characters to UTF16LE. In order
|
||||||
|
// to do a "proper" conversion, we would need to pull in the 'unicode/utf16'
|
||||||
|
// package, which at the time this was written added 512 bytes to the compiled
|
||||||
|
// binary.
|
||||||
|
// TODO: old comment, re-evaluate
|
||||||
|
func sendDescriptorString(data string, maxLen uint16) {
|
||||||
|
if maxLen < 2 {
|
||||||
|
// Something has gone horribly wrong.
|
||||||
|
SendZlp()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp the length.
|
||||||
|
maxEncBytes := min(len(usb_trans_buffer), len(udd_ep_control_cache_buffer), int(maxLen))
|
||||||
|
data = data[:min(len(data), (maxEncBytes-2)/2)]
|
||||||
|
|
||||||
|
// Write the header.
|
||||||
|
buf := usb_trans_buffer[:2*len(data)+2]
|
||||||
|
hdr, body := buf[:2], buf[2:]
|
||||||
|
hdr[0] = byte(len(buf))
|
||||||
|
hdr[1] = descriptor.TypeString
|
||||||
|
|
||||||
|
// Convert the string to UTF16.
|
||||||
|
// NOTE: Using range here would cause the length to disagree when multibyte codepoints are present.
|
||||||
|
for i := 0; i < len(data); i++ {
|
||||||
|
body[2*i] = byte(data[i])
|
||||||
|
body[2*i+1] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sendUSBPacket(0, buf)
|
||||||
|
}
|
||||||
|
|
||||||
func handleStandardSetup(setup usb.Setup) bool {
|
func handleStandardSetup(setup usb.Setup) bool {
|
||||||
switch setup.BRequest {
|
switch setup.BRequest {
|
||||||
case usb.GET_STATUS:
|
case usb.GET_STATUS:
|
||||||
@@ -206,7 +226,7 @@ func handleStandardSetup(setup usb.Setup) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendUSBPacket(0, usb_trans_buffer[:2], setup.WLength)
|
sendDescriptorData(usb_trans_buffer[:2], setup.WLength)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb.CLEAR_FEATURE:
|
case usb.CLEAR_FEATURE:
|
||||||
@@ -251,7 +271,7 @@ func handleStandardSetup(setup usb.Setup) bool {
|
|||||||
|
|
||||||
case usb.GET_CONFIGURATION:
|
case usb.GET_CONFIGURATION:
|
||||||
usb_trans_buffer[0] = usbConfiguration
|
usb_trans_buffer[0] = usbConfiguration
|
||||||
sendUSBPacket(0, usb_trans_buffer[:1], setup.WLength)
|
sendDescriptorData(usb_trans_buffer[:1], setup.WLength)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb.SET_CONFIGURATION:
|
case usb.SET_CONFIGURATION:
|
||||||
@@ -271,7 +291,7 @@ func handleStandardSetup(setup usb.Setup) bool {
|
|||||||
|
|
||||||
case usb.GET_INTERFACE:
|
case usb.GET_INTERFACE:
|
||||||
usb_trans_buffer[0] = usbSetInterface
|
usb_trans_buffer[0] = usbSetInterface
|
||||||
sendUSBPacket(0, usb_trans_buffer[:1], setup.WLength)
|
sendDescriptorData(usb_trans_buffer[:1], setup.WLength)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb.SET_INTERFACE:
|
case usb.SET_INTERFACE:
|
||||||
@@ -285,6 +305,21 @@ func handleStandardSetup(setup usb.Setup) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendDescriptorData sends a descriptor, truncating it to fit maxLen or the buffer size.
|
||||||
|
func sendDescriptorData(data []byte, maxLen uint16) {
|
||||||
|
data = lenToCap(data)
|
||||||
|
data = data[:min(len(data), len(udd_ep_control_cache_buffer), int(maxLen))]
|
||||||
|
sendUSBPacket(0, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the cap of the slice to the length.
|
||||||
|
// This is safe, but cannot be proven by the compiler.
|
||||||
|
//
|
||||||
|
//go:nobounds
|
||||||
|
func lenToCap(b []byte) []byte {
|
||||||
|
return b[:len(b):len(b)]
|
||||||
|
}
|
||||||
|
|
||||||
func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) {
|
func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) {
|
||||||
if len(usbDescriptor.Device) == 0 {
|
if len(usbDescriptor.Device) == 0 {
|
||||||
usbDescriptor = descriptor.CDC
|
usbDescriptor = descriptor.CDC
|
||||||
|
|||||||
Reference in New Issue
Block a user