Skip to content

Commit

Permalink
Merge pull request #23 from mndza/auto-adv
Browse files Browse the repository at this point in the history
gateware.platform: add `ApolloAdvertiser` hook in boards with USB switch
  • Loading branch information
mossmann authored Mar 7, 2024
2 parents 4435e2b + 2c30ce9 commit f3b0453
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 26 deletions.
98 changes: 98 additions & 0 deletions cynthion/python/src/gateware/platform/adv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#
# This file is part of Cynthion.
#
# Copyright (c) 2020-2023 Great Scott Gadgets <info@greatscottgadgets.com>
# SPDX-License-Identifier: BSD-3-Clause

from collections import defaultdict

from apollo_fpga.gateware import ApolloAdvertiser
from luna.gateware.usb.usb2.control import USBControlEndpoint
from luna.gateware.usb.request.standard import StandardRequestHandler

from usb_protocol.types.descriptors.standard import StandardDescriptorNumbers, ConfigurationDescriptor, InterfaceDescriptor
from usb_protocol.emitters import DeviceDescriptorCollection


def control_phy_hook(usb_device, m):

# Add ApolloAdvertiser submodule
m.submodules.apollo_adv = adv = ApolloAdvertiser()

# Find control endpoint or create one
for endpoint in usb_device._endpoints:
if isinstance(endpoint, USBControlEndpoint):
control_ep = endpoint
break
else:
control_ep = usb_device.add_control_endpoint()

# Find standard request handler and modify the device descriptors
for handler in control_ep._request_handlers:
if isinstance(handler, StandardRequestHandler):
# Inject additional Apollo interface
intf_number = add_apollo_interface(handler.descriptors)
break
else:
descriptors = DeviceDescriptorCollection()
intf_number = add_apollo_interface(descriptors)
control_ep.add_standard_request_handlers(descriptors)

# Add request handler
control_ep.add_request_handler(adv.default_request_handler(intf_number))


def add_apollo_interface(descriptors):
''' Inject an Apollo interface in the provided device descriptor '''
#
# Extract information from the previous configuration descriptor, if it exists
#
intf_descriptors = []
intf_assigned = defaultdict(bool)
try:
raw_bytes = descriptors.get_descriptor_bytes(StandardDescriptorNumbers.CONFIGURATION)
except KeyError:
conf_values = None
else:
# Parse configuration descriptor
conf_values = ConfigurationDescriptor.parse(raw_bytes)
raw_bytes = raw_bytes[conf_values.bLength:]

# Store subordinate interface descriptors
for i in range(conf_values.bNumInterfaces):

# Parse descriptor information
intf_values = InterfaceDescriptor.parse(raw_bytes)

# Store the slice of bytes, including endpoints
descr_len = raw_bytes[0]
for i in range(intf_values.bNumEndpoints):
descr_len += raw_bytes[descr_len]
intf_descriptors.append(raw_bytes[:descr_len])
raw_bytes = raw_bytes[descr_len:]

# Flag interface number as assigned / occupied
intf_assigned[intf_values.bInterfaceNumber] = True

# Choose the lower, unassigned interface number
intf_number = min(n for n in range(256) if not intf_assigned[n])

#
# Rebuild configuration descriptor with the new interface
#
with descriptors.ConfigurationDescriptor() as c:

# Only set fields that won't be modified later
if conf_values is not None:
for field in ('bConfigurationValue', 'iConfiguration', 'bmAttributes', 'bMaxPower'):
setattr(c, field, conf_values[field])

# Add the previous interface descriptors along with our new Apollo interface
for interface in intf_descriptors:
c.add_subordinate_descriptor(interface)
with c.InterfaceDescriptor() as i:
i.bInterfaceNumber = intf_number
i.bInterfaceClass = 0xff
i.bInterfaceSubclass = 0x00 # Apollo interface

return intf_number
2 changes: 1 addition & 1 deletion cynthion/python/src/gateware/platform/cynthion_r0_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from amaranth.build import Resource, Subsignal, Pins, PinsN, Attrs, Clock, DiffPairs, Connector

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform

__all__ = ["CynthionPlatformRev0D1"]

Expand Down
2 changes: 1 addition & 1 deletion cynthion/python/src/gateware/platform/cynthion_r0_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform

__all__ = ["CynthionPlatformRev0D2"]

Expand Down
2 changes: 1 addition & 1 deletion cynthion/python/src/gateware/platform/cynthion_r0_3.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform

__all__ = ["CynthionPlatformRev0D3"]

Expand Down
2 changes: 1 addition & 1 deletion cynthion/python/src/gateware/platform/cynthion_r0_4.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform

__all__ = ["CynthionPlatformRev0D4"]

Expand Down
2 changes: 1 addition & 1 deletion cynthion/python/src/gateware/platform/cynthion_r0_5.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform

__all__ = ["CynthionPlatformRev0D5"]

Expand Down
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r0_6.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev0D6"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev0D6(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -169,3 +170,7 @@ class CynthionPlatformRev0D6(CynthionPlatform):
Connector("mezzanine", 0,
"- - B9 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r0_7.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev0D7"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev0D7(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -169,3 +170,7 @@ class CynthionPlatformRev0D7(CynthionPlatform):
Connector("mezzanine", 0,
"- - B8 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r1_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev1D0"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev1D0(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -169,3 +170,7 @@ class CynthionPlatformRev1D0(CynthionPlatform):
Connector("mezzanine", 0,
"- - B8 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r1_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev1D1"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev1D1(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -169,3 +170,7 @@ class CynthionPlatformRev1D1(CynthionPlatform):
Connector("mezzanine", 0,
"- - B8 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r1_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev1D2"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev1D2(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -181,3 +182,7 @@ class CynthionPlatformRev1D2(CynthionPlatform):
Connector("mezzanine", 0,
"- - B8 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r1_3.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev1D3"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev1D3(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -181,3 +182,7 @@ class CynthionPlatformRev1D3(CynthionPlatform):
Connector("mezzanine", 0,
"- - B8 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}
11 changes: 8 additions & 3 deletions cynthion/python/src/gateware/platform/cynthion_r1_4.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from amaranth.build import *
from amaranth_boards.resources import *

from cynthion.gateware.platform.core import CynthionPlatform
from .core import CynthionPlatform
from .adv import control_phy_hook

__all__ = ["CynthionPlatformRev1D4"]

Expand All @@ -22,8 +23,8 @@ class CynthionPlatformRev1D4(CynthionPlatform):
package = "BG256"
speed = os.getenv("ECP5_SPEED_GRADE", "8")

# By default, assume we'll be connecting via our target PHY.
default_usb_connection = "target_phy"
# By default, assume we'll be connecting via our control PHY.
default_usb_connection = "control_phy"

#
# Preferred DRAM bus I/O (de)-skewing constants.
Expand Down Expand Up @@ -178,3 +179,7 @@ class CynthionPlatformRev1D4(CynthionPlatform):
Connector("mezzanine", 0,
"- - B8 A9 B10 A10 B11 D14 C14 F14 E14 G13 G12 - - - - C16 C15 B16 B15 A14 B13 A13 D13 A12 B12 A11 - -"),
]

usb_device_hooks = {
"control_phy_0": control_phy_hook
}

0 comments on commit f3b0453

Please sign in to comment.