github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/board/f-secure/usbarmory/mark-two/usb.go (about)

     1  // USB armory Mk II support for tamago/arm
     2  // https://github.com/f-secure-foundry/tamago
     3  //
     4  // Copyright (c) F-Secure Corporation
     5  // https://foundry.f-secure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  package usbarmory
    11  
    12  import (
    13  	"time"
    14  
    15  	"github.com/f-secure-foundry/tamago/soc/imx6"
    16  )
    17  
    18  // Receptacle USB port controller constants
    19  const (
    20  	FUSB303_CONTROL1 = 0x05
    21  	CONTROL1_ENABLE  = 3
    22  
    23  	FUSB303_TYPE = 0x13
    24  )
    25  
    26  // Receptacle USB port controller modes
    27  const (
    28  	TYPE_DEBUGSRC    = 1 << 6
    29  	TYPE_DEBUGSNK    = 1 << 5
    30  	TYPE_SINK        = 1 << 4
    31  	TYPE_SOURCE      = 1 << 3
    32  	TYPE_ACTIVECABLE = 1 << 2
    33  	TYPE_AUDIOVBUS   = 1
    34  	TYPE_AUDIO       = 0
    35  )
    36  
    37  // EnableReceptacleController activates the receptacle USB port controller.
    38  func EnableReceptacleController() (err error) {
    39  	a, err := imx6.I2C1.Read(FUSB303_ADDR, FUSB303_CONTROL1, 1, 1)
    40  
    41  	if err != nil {
    42  		return
    43  	}
    44  
    45  	a[0] |= 1 << CONTROL1_ENABLE
    46  	return imx6.I2C1.Write(a, FUSB303_ADDR, FUSB303_CONTROL1, 1)
    47  }
    48  
    49  // ReceptacleMode returns the type of device or accessory detected by the
    50  // receptacle USB port controller.
    51  func ReceptacleMode() (mode int, err error) {
    52  	t, err := imx6.I2C1.Read(FUSB303_ADDR, FUSB303_TYPE, 1, 1)
    53  	return int(t[0]), err
    54  }
    55  
    56  // EnableDebugAccessory enables debug accessory detection on the receptacle USB
    57  // port controller.
    58  //
    59  // A debug accessory allows access, among all other debug signals, to the UART2
    60  // serial console.
    61  //
    62  // Note that there is a delay (typically up to 200ms) between the return of
    63  // this call and the actual enabling of the debug accessory, for this reason
    64  // the serial console is not immediately available.
    65  //
    66  // To wait detection of a debug accessory use DetectDebugAccessory() instead.
    67  func EnableDebugAccessory() (err error) {
    68  	return EnableReceptacleController()
    69  }
    70  
    71  func waitDebugAccessory(timeout time.Duration, ch chan<- bool) {
    72  	start := time.Now()
    73  
    74  	for time.Since(start) < timeout {
    75  		mode, err := ReceptacleMode()
    76  
    77  		if err != nil {
    78  			break
    79  		}
    80  
    81  		if mode == TYPE_DEBUGSRC || mode == TYPE_DEBUGSNK {
    82  			ch <- true
    83  			return
    84  		}
    85  
    86  		time.Sleep(10 * time.Millisecond)
    87  	}
    88  
    89  	ch <- false
    90  }
    91  
    92  // DetectDebugAccessory enables debug accessory detection on the receptacle USB
    93  // port controller and polls successful detection (typically done in up to
    94  // 200ms).
    95  //
    96  // An error is returned if no debug accessory is detected within the timeout.
    97  //
    98  // On the returned boolean channel are sent successful detection (true) or
    99  // timeout (false).
   100  func DetectDebugAccessory(timeout time.Duration) (<-chan bool, error) {
   101  	ch := make(chan bool)
   102  
   103  	err := EnableReceptacleController()
   104  
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	go waitDebugAccessory(timeout, ch)
   110  
   111  	return ch, nil
   112  }