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  }