blob: b1fa47779122c5d396cac163806eafc086e7458e [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package eth
import (
"encoding/binary"
"fmt"
"syscall/zx"
"syscall/zx/fdio"
)
type EthInfo struct {
Features uint32
MTU uint32
MAC [6]byte
_ [2]byte
_ [12]uint32
} // eth_info_t
const FeatureWlan = 0x01
const FeatureSynth = 0x02
type ethfifos struct {
// fifo handles
tx zx.Handle
rx zx.Handle
// maximum number of items in fifos
txDepth uint32
rxDepth uint32
} // eth_fifos_t
const ioctlFamilyETH = 0x20 // IOCTL_FAMILY_ETH
const (
ioctlOpGetInfo = 0 // IOCTL_ETHERNET_GET_INFO, IOCTL_KIND_DEFAULT
ioctlOpGetFifos = 1 // IOCTL_ETHERNET_GET_FIFOS, IOCTL_KIND_GET_TWO_HANDLES
ioctlOpSetIobuf = 2 // IOCTL_ETHERNET_SET_IOBUF, IOCTL_KIND_SET_HANDLE
ioctlOpStart = 3 // IOCTL_ETHERNET_START, IOCTL_KIND_DEFAULT
ioctlOpStop = 4 // IOCTL_ETHERNET_STOP, IOCTL_KIND_DEFAULT
ioctlOpTXListenStart = 5 // IOCTL_ETHERNET_TX_LISTEN_START, IOCTL_KIND_DEFAULT
ioctlOpTXListenStop = 6 // IOCTL_ETHERNET_TX_LISTEN_STOP, IOCTL_KIND_DEFAULT
ioctlOpSetClientName = 7 // IOCTL_ETHERNET_SET_CLIENT_NAME, IOCTL_KIND_DEFAULT
ioctlOpGetStatus = 8 // IOCTL_ETHERNET_GET_STATUS, IOCTL_KIND_DEFAULT
)
func IoctlGetInfo(m fdio.FDIO) (info EthInfo, err error) {
num := fdio.IoctlNum(fdio.IoctlKindDefault, ioctlFamilyETH, ioctlOpGetInfo)
res := make([]byte, 64)
if _, err := m.Ioctl(num, nil, res); err != nil {
return info, fmt.Errorf("IOCTL_ETHERNET_GET_INFO: %v", err)
}
info.Features = binary.LittleEndian.Uint32(res)
info.MTU = binary.LittleEndian.Uint32(res[4:])
copy(info.MAC[:], res[8:])
return info, nil
}
func IoctlGetFifos(m fdio.FDIO) (fifos ethfifos, err error) {
num := fdio.IoctlNum(fdio.IoctlKindGetTwoHandles, ioctlFamilyETH, ioctlOpGetFifos)
res := make([]byte, 8)
h, err := m.Ioctl(num, nil, res)
if err != nil {
return fifos, fmt.Errorf("IOCTL_ETHERNET_GET_FIFOS: %v", err)
}
if len(res) != 8 {
return fifos, fmt.Errorf("IOCTL_ETHERNET_GET_FIFOS: bad length: %d", len(res))
}
fifos.tx = h[0]
fifos.rx = h[1]
fifos.txDepth = binary.LittleEndian.Uint32(res)
fifos.rxDepth = binary.LittleEndian.Uint32(res[4:])
return fifos, nil
}
func IoctlSetIobuf(m fdio.FDIO, h zx.Handle) error {
num := fdio.IoctlNum(fdio.IoctlKindSetHandle, ioctlFamilyETH, ioctlOpSetIobuf)
err := m.IoctlSetHandle(num, h)
if err != nil {
return fmt.Errorf("IOCTL_ETHERNET_SET_IOBUF: %v", err)
}
return nil
}
func IoctlSetClientName(m fdio.FDIO, name []byte) error {
num := fdio.IoctlNum(fdio.IoctlKindDefault, ioctlFamilyETH, ioctlOpSetClientName)
_, err := m.Ioctl(num, name, nil)
if err != nil {
return fmt.Errorf("IOCTL_ETHERNET_SET_CLIENT_NAME: %v", err)
}
return nil
}
func IoctlStart(m fdio.FDIO) error {
num := fdio.IoctlNum(fdio.IoctlKindDefault, ioctlFamilyETH, ioctlOpStart)
_, err := m.Ioctl(num, nil, nil)
if err != nil {
return fmt.Errorf("IOCTL_ETHERNET_START: %v", err)
}
return nil
}
func IoctlStop(m fdio.FDIO) error {
num := fdio.IoctlNum(fdio.IoctlKindDefault, ioctlFamilyETH, ioctlOpStop)
_, err := m.Ioctl(num, nil, nil)
if err != nil {
return fmt.Errorf("IOCTL_ETHERNET_STOP: %v", err)
}
return nil
}
func IoctlTXListenStart(m fdio.FDIO) error {
num := fdio.IoctlNum(fdio.IoctlKindDefault, ioctlFamilyETH, ioctlOpTXListenStart)
_, err := m.Ioctl(num, nil, nil)
if err != nil {
return fmt.Errorf("IOCTL_ETHERNET_TX_LISTEN_START: %v", err)
}
return nil
}
func IoctlGetStatus(m fdio.FDIO) (status uint32, err error) {
num := fdio.IoctlNum(fdio.IoctlKindDefault, ioctlFamilyETH, ioctlOpGetStatus)
res := make([]byte, 4)
_, err = m.Ioctl(num, nil, res)
if err != nil {
return 0, fmt.Errorf("IOCTL_ETHERNET_GET_STATUS: %v", err)
}
if len(res) != 4 {
return 0, fmt.Errorf("IOCTL_ETHERNET_GET_STATUS: bad length: %d", len(res))
}
status = binary.LittleEndian.Uint32(res)
return status, nil
}