github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/usb/device.go (about) 1 // USB device mode support 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.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 usb 11 12 import ( 13 "sync" 14 "time" 15 16 "github.com/usbarmory/tamago/internal/reg" 17 ) 18 19 // DeviceMode sets the USB controller in device mode. 20 func (hw *USB) DeviceMode() { 21 hw.Lock() 22 defer hw.Unlock() 23 24 reg.Set(hw.cmd, USBCMD_RST) 25 reg.Wait(hw.cmd, USBCMD_RST, 1, 0) 26 27 // p3872, 56.6.33 USB Device Mode (USB_nUSBMODE), IMX6ULLRM) 28 m := reg.Read(hw.mode) 29 30 // set device only controller 31 m = (m & ^uint32(0b11<<USBMODE_CM)) | (USBMODE_CM_DEVICE << USBMODE_CM) 32 // disable setup lockout 33 m |= (1 << USBMODE_SLOM) 34 // disable stream mode 35 m &^= (1 << USBMODE_SDIS) 36 37 reg.Write(hw.mode, m) 38 reg.Wait(hw.mode, USBMODE_CM, 0b11, USBMODE_CM_DEVICE) 39 40 // initialize endpoint queue head list 41 hw.initQH() 42 // set control endpoint 43 hw.set(0, IN, 64, true, 0) 44 hw.set(0, OUT, 64, true, 0) 45 46 // set OTG termination 47 reg.Set(hw.otg, OTGSC_OT) 48 49 // clear pending interrupts 50 reg.WriteBack(hw.sts) 51 52 // run 53 reg.Set(hw.cmd, USBCMD_RS) 54 } 55 56 // Start waits and handles configured USB endpoints in device mode, it should 57 // never return. Note that isochronous endpoints are not supported. 58 func (hw *USB) Start(dev *Device) { 59 if dev == nil { 60 return 61 } 62 63 hw.Device = dev 64 65 for { 66 // check for bus reset 67 if reg.Get(hw.sts, USBSTS_URI, 1) == 1 { 68 // set inactive configuration 69 hw.Device.ConfigurationValue = 0 70 71 // perform controller reset procedure 72 hw.Reset() 73 } 74 75 // wait for a setup packet 76 if !reg.WaitFor(10*time.Millisecond, hw.setup, 0, 1, 1) { 77 continue 78 } 79 80 if conf, _ := hw.handleSetup(); conf == 0 { 81 continue 82 } 83 84 // stop configuration endpoints 85 if hw.exit != nil { 86 close(hw.exit) 87 hw.wg.Wait() 88 } 89 90 // start configuration endpoints 91 hw.startEndpoints() 92 } 93 } 94 95 // ServiceInterrupts services pending endpoint transfer and bus reset events. 96 func (hw *USB) ServiceInterrupts() { 97 defer reg.WriteBack(hw.sts) 98 99 if hw.Device == nil { 100 return 101 } 102 103 // check for bus reset 104 if reg.Get(hw.sts, USBSTS_URI, 1) == 1 { 105 // set inactive configuration 106 hw.Device.ConfigurationValue = 0 107 108 // perform controller reset procedure 109 hw.Reset() 110 } 111 112 // process setup packets 113 for reg.Read(hw.setup) != 0 { 114 if conf, _ := hw.handleSetup(); conf != 0 { 115 // stop configuration endpoints 116 if hw.exit != nil { 117 close(hw.exit) 118 hw.wg.Wait() 119 } 120 121 // set interrupt event announcement 122 hw.event = sync.NewCond(hw) 123 124 // start configuration endpoints 125 hw.startEndpoints() 126 } 127 } 128 129 if hw.event != nil { 130 // announce interrupt event to endpoints waiting transfer 131 hw.event.Broadcast() 132 } 133 }