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 }