github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/contrib/spidev/spidev.go (about)

     1  // Copyright 2021 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // spidev communicates with the Linux spidev driver.
     6  //
     7  // Synopsis:
     8  //
     9  //	spidev [OPTIONS] raw < tx.bin > rx.bin
    10  //	spidev [OPTIONS] sfdp
    11  //
    12  // Options:
    13  //
    14  //	-D DEV: spidev device (default /dev/spidev0.0)
    15  //	-s SPEED: max speed in Hz (default 500000)
    16  //
    17  // Description:
    18  //
    19  //	raw: The binary data from stdin is transmitted over the SPI bus.
    20  //	     Received data is printed to stdout.
    21  //	sfdp: Parse and print the parameters in the SFDP.
    22  package main
    23  
    24  import (
    25  	"errors"
    26  	"io"
    27  	"log"
    28  	"os"
    29  
    30  	flag "github.com/spf13/pflag"
    31  	"github.com/mvdan/u-root-coreutils/pkg/flash"
    32  	"github.com/mvdan/u-root-coreutils/pkg/flash/sfdp"
    33  	"github.com/mvdan/u-root-coreutils/pkg/spidev"
    34  )
    35  
    36  type spi interface {
    37  	Transfer([]spidev.Transfer) error
    38  	SetSpeedHz(uint32) error
    39  	Close() error
    40  }
    41  
    42  type spiOpenFunc func(dev string) (spi, error)
    43  
    44  func openSPIDev(dev string) (spi, error) {
    45  	return spidev.Open(dev)
    46  }
    47  
    48  func run(args []string, spiOpen spiOpenFunc, input io.Reader, output io.Writer) error {
    49  	// Parse args.
    50  	fs := flag.NewFlagSet("spidev", flag.ContinueOnError)
    51  	dev := fs.StringP("device", "D", "/dev/spidev0.0", "spidev device")
    52  	speed := fs.Uint32P("speed", "s", 500000, "max speed in Hz")
    53  	if err := fs.Parse(args); err != nil {
    54  		return err
    55  	}
    56  
    57  	if fs.NArg() != 1 {
    58  		flag.Usage()
    59  		return errors.New("expected one subcommand")
    60  	}
    61  
    62  	// Open the spi device.
    63  	s, err := spiOpen(*dev)
    64  	if err != nil {
    65  		return err
    66  	}
    67  	defer s.Close()
    68  	if err := s.SetSpeedHz(*speed); err != nil {
    69  		return err
    70  	}
    71  
    72  	// Currently, only the raw subcommand is supported.
    73  	switch fs.Args()[0] {
    74  	case "raw":
    75  		// Create transfer from stdin.
    76  		tx, err := io.ReadAll(input)
    77  		if err != nil {
    78  			return err
    79  		}
    80  		if len(tx) == 0 {
    81  			return nil
    82  		}
    83  		transfers := []spidev.Transfer{
    84  			{
    85  				Tx: tx,
    86  				Rx: make([]byte, len(tx)),
    87  			},
    88  		}
    89  
    90  		// Perform transfers.
    91  		if err := s.Transfer(transfers); err != nil {
    92  			return err
    93  		}
    94  
    95  		_, err = output.Write(transfers[0].Rx)
    96  		return err
    97  
    98  	case "sfdp":
    99  		// Create flash device and read SFDP.
   100  		f, err := flash.New(s)
   101  		if err != nil {
   102  			return err
   103  		}
   104  
   105  		// Print sfdp.
   106  		return f.SFDP().PrettyPrint(output, sfdp.BasicTableLookup)
   107  
   108  	default:
   109  		flag.Usage()
   110  		return errors.New("unknown subcommand")
   111  	}
   112  }
   113  
   114  func main() {
   115  	if err := run(os.Args[1:], openSPIDev, os.Stdin, os.Stdout); err != nil {
   116  		log.Fatalf("Error: %v", err)
   117  	}
   118  }