Skip to content

Commit 58b16f9

Browse files
committed
Integrate T-BC on Perla2 platform
Assisted by Cursor AI Add Perla2 vendor definitions Integrate on the target Signed-off-by: Vitaly Grinberg <[email protected]>
1 parent fa94c4c commit 58b16f9

36 files changed

+3085
-272
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ RUN make clean && make
55

66
FROM quay.io/centos/centos:stream9
77

8-
RUN yum -y update && yum -y update glibc && yum --setopt=skip_missing_names_on_install=False -y install linuxptp ethtool hwdata synce4l && yum clean all
8+
RUN yum -y update && yum -y update glibc && yum --setopt=skip_missing_names_on_install=False -y install pciutils linuxptp ethtool hwdata synce4l && yum clean all
99

1010

1111
RUN yum install -y procps-ng

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/golang/glog v1.2.4
1212
github.com/google/goexpect v0.0.0-20210430020637-ab937bf7fd6f
1313
github.com/jaypipes/ghw v0.12.0
14-
github.com/k8snetworkplumbingwg/ptp-operator v0.0.0-20251105200506-7495c02a5a34
14+
github.com/k8snetworkplumbingwg/ptp-operator v0.0.0-20251204124210-1fe2e26893f5
1515
github.com/mdlayher/genetlink v1.3.2
1616
github.com/mdlayher/netlink v1.7.2
1717
github.com/prometheus/client_golang v1.16.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
9494
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
9595
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
9696
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
97-
github.com/k8snetworkplumbingwg/ptp-operator v0.0.0-20251105200506-7495c02a5a34 h1:wgQR7ZC6EcPjUNGkmAwoT89Hff1PbitpPe8KDjl+lVM=
98-
github.com/k8snetworkplumbingwg/ptp-operator v0.0.0-20251105200506-7495c02a5a34/go.mod h1:sZdvVrCIjLF8TF7D1Jd1C+Awv+qZ8oY1W9/lliM1p78=
97+
github.com/k8snetworkplumbingwg/ptp-operator v0.0.0-20251204124210-1fe2e26893f5 h1:nE9BDzM+55YROTu6tYGwroNJ3yPTNmUKg1ABxZdBIdM=
98+
github.com/k8snetworkplumbingwg/ptp-operator v0.0.0-20251204124210-1fe2e26893f5/go.mod h1:sZdvVrCIjLF8TF7D1Jd1C+Awv+qZ8oY1W9/lliM1p78=
9999
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
100100
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
101101
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=

pkg/controller/hardwareconfig_controller.go

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import (
1717
ptpv2alpha1 "github.com/k8snetworkplumbingwg/ptp-operator/api/v2alpha1"
1818
)
1919

20+
const (
21+
backoffTime = 15 * time.Second
22+
)
23+
2024
// HardwareConfigUpdateHandler defines the interface implemented by the daemon (or a test double)
2125
// to receive effective hardware configuration updates computed by this controller.
2226
//
@@ -90,8 +94,7 @@ func (r *HardwareConfigReconciler) Reconcile(ctx context.Context, req ctrl.Reque
9094
glog.Infof("HardwareConfig deleted, recalculating hardware configurations name=%s", req.Name)
9195
return r.reconcileAllConfigs(ctx)
9296
}
93-
glog.Errorf("Failed to get HardwareConfig: %v", err)
94-
return ctrl.Result{}, err
97+
return ctrl.Result{}, fmt.Errorf("failed to get HardwareConfig: %w", err)
9598
}
9699

97100
// Recalculate and apply hardware configuration for this node
@@ -147,51 +150,51 @@ func (r *HardwareConfigReconciler) reconcileAllConfigs(ctx context.Context) (ctr
147150
// List all HardwareConfigs in the cluster
148151
hwConfigList := &ptpv2alpha1.HardwareConfigList{}
149152
if err := r.List(ctx, hwConfigList); err != nil {
150-
glog.Errorf("Failed to list HardwareConfigs: %v", err)
151-
return ctrl.Result{}, err
153+
return ctrl.Result{}, fmt.Errorf("failed to list HardwareConfigs: %w", err)
152154
}
153155

154156
// Validate hardware config separation before proceeding
155157
if err := r.validateHardwareConfigSeparation(hwConfigList.Items); err != nil {
156158
glog.Errorf("Hardware config validation failed: %v", err)
157159
// Don't return error to avoid controller crash, but log the issue
158-
// In production, you might want to set a status condition instead
160+
// TODO: Set a status condition instead
161+
// add a status condition to the HardwareConfig CRD to enable that
162+
// type HardwareConfigStatus struct {
163+
// MatchedNodes []MatchedNode `json:"matchedNodes,omitempty" yaml:"matchedNodes,omitempty"`
164+
// Conditions []metav1.Condition `json:"conditions,omitempty"
159165
}
160166

161167
// Check if any hardware configs are associated with currently active PTP profiles
162168
// If so, trigger a PTP restart to ensure hardware and PTP configurations are synchronized
163169
needsPTPRestart := r.checkIfActiveProfilesAffected(ctx, hwConfigList.Items)
164170

165171
// Calculate the applicable hardware configurations for this node
166-
applicableConfigs, err := r.calculateNodeHardwareConfigs(ctx, hwConfigList.Items)
167-
if err != nil {
168-
glog.Errorf("Failed to calculate node hardware configurations: %v", err)
169-
return ctrl.Result{}, err
170-
}
172+
applicableConfigs := r.calculateNodeHardwareConfigs(ctx, hwConfigList.Items)
171173

172174
// Apply hardware configurations via the handler (the daemon instance in production)
173175
if len(applicableConfigs) > 0 {
174176
glog.Infof("Updating daemon hardware configuration with %d hardware configs for node %s", len(applicableConfigs), r.NodeName)
175177

176178
// Send hardware configuration update to daemon (HardwareConfigHandler)
177179
if r.HardwareConfigHandler != nil {
178-
err = r.HardwareConfigHandler.UpdateHardwareConfig(applicableConfigs)
180+
err := r.HardwareConfigHandler.UpdateHardwareConfig(applicableConfigs)
179181
if err != nil {
180-
glog.Errorf("Failed to update daemon hardware configuration: %v", err)
181-
return ctrl.Result{}, err
182+
glog.Infof("could not update daemon hardware configuration: %v (will retry after backoff)", err)
183+
// Requeue after a short delay to avoid immediate retry storms
184+
return ctrl.Result{RequeueAfter: backoffTime}, nil
182185
}
183186
}
184-
185187
glog.Infof("Successfully updated daemon hardware configuration configs=%d", len(applicableConfigs))
186188
} else {
187189
glog.Infof("No applicable hardware configurations found for node %s", r.NodeName)
188190

189191
// Clear hardware configurations if needed
190192
if r.HardwareConfigHandler != nil {
191-
err = r.HardwareConfigHandler.UpdateHardwareConfig([]ptpv2alpha1.HardwareConfig{})
193+
err := r.HardwareConfigHandler.UpdateHardwareConfig([]ptpv2alpha1.HardwareConfig{})
192194
if err != nil {
193-
glog.Errorf("Failed to clear daemon hardware configuration: %v", err)
194-
return ctrl.Result{}, err
195+
glog.Errorf("Failed to clear daemon hardware configuration: %v (will retry after backoff)", err)
196+
// Requeue after a short delay to avoid immediate retry storms
197+
return ctrl.Result{RequeueAfter: backoffTime}, nil
195198
}
196199
}
197200
}
@@ -243,24 +246,21 @@ func (r *HardwareConfigReconciler) scheduleDeferredRestart(_ context.Context) {
243246
}
244247

245248
// calculateNodeHardwareConfigs determines which hardware configurations should be applied to this node
246-
//
247-
//nolint:unparam // error return is kept for future node matching logic
248-
func (r *HardwareConfigReconciler) calculateNodeHardwareConfigs(_ context.Context, hwConfigs []ptpv2alpha1.HardwareConfig) ([]ptpv2alpha1.HardwareConfig, error) {
249+
func (r *HardwareConfigReconciler) calculateNodeHardwareConfigs(_ context.Context, hwConfigs []ptpv2alpha1.HardwareConfig) []ptpv2alpha1.HardwareConfig {
249250
var applicableConfigs []ptpv2alpha1.HardwareConfig
250251

251252
// For now, we apply all hardware configurations to all nodes
252253
// This can be enhanced later with node matching logic similar to PtpConfig
253254
for _, hwConfig := range hwConfigs {
254-
glog.Infof("Processing HardwareConfig name=%s profile=%s", hwConfig.Name, getProfileName(hwConfig.Spec.Profile))
255+
glog.Infof("Processing HardwareConfig name=%s profile=%s", hwConfig.Name, hwConfig.Spec.Profile.Name)
255256

256257
// TODO: Add node-specific filtering logic here
257258
// For now, we include all hardware configs
258259
applicableConfigs = append(applicableConfigs, hwConfig)
259-
glog.Infof("Added hardware config profileName=%s relatedPtpProfile=%s", getProfileName(hwConfig.Spec.Profile), hwConfig.Spec.RelatedPtpProfileName)
260+
glog.Infof("Added hardware config profileName=%s relatedPtpProfile=%s", hwConfig.Spec.Profile.Name, hwConfig.Spec.RelatedPtpProfileName)
260261
}
261-
262262
glog.Infof("Calculated hardware configurations for node node=%s totalConfigs=%d", r.NodeName, len(applicableConfigs))
263-
return applicableConfigs, nil
263+
return applicableConfigs
264264
}
265265

266266
// checkIfActiveProfilesAffected determines if hardware config changes should trigger PTP restart
@@ -304,14 +304,6 @@ func (r *HardwareConfigReconciler) checkIfActiveProfilesAffected(_ context.Conte
304304
return false
305305
}
306306

307-
// getProfileName safely extracts the profile name from a HardwareProfile
308-
func getProfileName(profile ptpv2alpha1.HardwareProfile) string {
309-
if profile.Name != nil {
310-
return *profile.Name
311-
}
312-
return "unnamed"
313-
}
314-
315307
// SetupWithManager sets up the controller with the Manager
316308
func (r *HardwareConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
317309
// Watch HardwareConfig resources

pkg/controller/hardwareconfig_controller_test.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,7 @@ func TestCalculateNodeHardwareConfigs(t *testing.T) {
149149
}
150150

151151
// Call the method under test
152-
result, err := reconciler.calculateNodeHardwareConfigs(context.TODO(), tc.hwConfigs)
153-
154-
// Verify no error occurred
155-
assert.NoError(t, err)
152+
result := reconciler.calculateNodeHardwareConfigs(context.TODO(), tc.hwConfigs)
156153

157154
// Verify the number of hardware configs
158155
assert.Len(t, result, tc.expectedConfigsCount,
@@ -161,11 +158,7 @@ func TestCalculateNodeHardwareConfigs(t *testing.T) {
161158
// Verify config names match expected (based on profile names within configs)
162159
var actualConfigNames []string
163160
for _, hwConfig := range result {
164-
if hwConfig.Spec.Profile.Name != nil {
165-
actualConfigNames = append(actualConfigNames, *hwConfig.Spec.Profile.Name)
166-
} else {
167-
actualConfigNames = append(actualConfigNames, "unnamed")
168-
}
161+
actualConfigNames = append(actualConfigNames, *hwConfig.Spec.Profile.Name)
169162
}
170163
assert.ElementsMatch(t, tc.expectedConfigNames, actualConfigNames,
171164
"Expected config names %v, got %v", tc.expectedConfigNames, actualConfigNames)

pkg/controller/ptpconfig_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ func anyRuleMatchesNode(matchRules []ptpv1.MatchRule, nodeName string, nodeLabel
200200
// TODO: Add support for "key=value" format matching
201201
}
202202
}
203+
203204
return false
204205
}
205206

pkg/daemon/config.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ func NewLinuxPTPConfUpdate() (*LinuxPTPConfUpdate, error) {
159159
if err != nil {
160160
return nil, fmt.Errorf("failed to read %s: %v", PTP4L_CONF_FILE_PATH, err)
161161
}
162-
163-
return &LinuxPTPConfUpdate{UpdateCh: make(chan bool), defaultPTP4lConfig: defaultPTP4lConfig}, nil
162+
return &LinuxPTPConfUpdate{UpdateCh: make(chan bool, 10), defaultPTP4lConfig: defaultPTP4lConfig}, nil
164163
}
165164

166165
func (l *LinuxPTPConfUpdate) UpdateConfig(nodeProfilesJson []byte) error {

pkg/daemon/daemon.go

Lines changed: 112 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/config"
2626

2727
"github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/dpll"
28+
dpllnl "github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/dpll-netlink"
2829
"github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/leap"
2930

3031
"github.com/k8snetworkplumbingwg/linuxptp-daemon/pkg/event"
@@ -336,6 +337,57 @@ func (dn *Daemon) getHoldoverParameters(profileName string, clockID uint64) *ptp
336337
return dn.hardwareConfigManager.GetHoldoverParameters(profileName, clockID)
337338
}
338339

340+
// getInterfacesFromHardwareConfig derives interfaces from hardwareconfig structure for T-BC mode.
341+
// It extracts the first interface from structure[*]->dpll->networkInterface.
342+
// Returns an empty slice if no hardwareconfig is available or no interfaces are found.
343+
func (dn *Daemon) getInterfacesFromHardwareConfig(nodeProfile *ptpv1.PtpProfile) config.IFaces {
344+
if dn.hardwareConfigManager == nil || nodeProfile == nil || nodeProfile.Name == nil {
345+
return config.IFaces{}
346+
}
347+
348+
// Get hardware configs for this profile
349+
hwProfiles := dn.hardwareConfigManager.GetHardwareConfigsForProfile(nodeProfile)
350+
if len(hwProfiles) == 0 {
351+
glog.V(2).Infof("No hardware configs found for profile %s", *nodeProfile.Name)
352+
return config.IFaces{}
353+
}
354+
355+
var interfaces config.IFaces
356+
357+
// Iterate through hardware profiles and extract interfaces from structure
358+
for _, hwProfile := range hwProfiles {
359+
if hwProfile.ClockChain == nil || len(hwProfile.ClockChain.Structure) == 0 {
360+
continue
361+
}
362+
363+
// Get the first subsystem from structure and use GetSubsystemNetworkInterface
364+
firstSubsystem := hwProfile.ClockChain.Structure[0]
365+
networkInterface, err := hardwareconfig.GetSubsystemNetworkInterface(hwProfile.ClockChain, firstSubsystem.Name)
366+
if err != nil {
367+
glog.V(2).Infof("Failed to get network interface for first subsystem %s: %v", firstSubsystem.Name, err)
368+
continue
369+
}
370+
371+
if networkInterface != "" {
372+
// Determine event source based on T-BC configuration
373+
// For T-BC, the interface typically depends on PTP4l
374+
eventSource := event.PTP4l
375+
376+
// Get PHC ID for the interface
377+
phcID := ptpnetwork.GetPhcId(networkInterface)
378+
379+
interfaces = append(interfaces, config.Iface{
380+
Name: networkInterface,
381+
Source: eventSource,
382+
PhcId: phcID,
383+
IsMaster: false,
384+
})
385+
}
386+
}
387+
388+
return interfaces
389+
}
390+
339391
// New LinuxPTP is called by daemon to generate new linuxptp instance
340392
func New(
341393
nodeName string,
@@ -450,6 +502,7 @@ func (dn *Daemon) applyNodePTPProfiles() error {
450502
dn.readyTracker.setConfig(false)
451503

452504
glog.Infof("in applyNodePTPProfiles - starting to apply %d node profiles", len(dn.ptpUpdate.NodeProfiles))
505+
453506
dn.stopAllProcesses()
454507
// All process should have been stopped,
455508
// clear process in process manager.
@@ -485,6 +538,20 @@ func (dn *Daemon) applyNodePTPProfiles() error {
485538
})
486539

487540
relations := reconcileRelatedProfiles(dn.ptpUpdate.NodeProfiles)
541+
542+
// Update PtpConfig in hardware config manager for clock chain resolution
543+
// This is done after sorting and reconciliation to ensure we use the same
544+
// processed profiles that will actually be applied. The NodeProfiles are already
545+
// filtered to be relevant for this node by calculateNodeProfiles in the controller.
546+
if dn.hardwareConfigManager != nil && len(dn.ptpUpdate.NodeProfiles) > 0 {
547+
ptpConfig := &ptpv1.PtpConfig{
548+
Spec: ptpv1.PtpConfigSpec{
549+
Profile: dn.ptpUpdate.NodeProfiles,
550+
},
551+
}
552+
dn.hardwareConfigManager.SetPtpConfig(ptpConfig)
553+
glog.Infof("Updated PtpConfig in hardware config manager with %d profiles (after sorting and reconciliation)", len(dn.ptpUpdate.NodeProfiles))
554+
}
488555
// TODO: resolve clock IDs, clockType, leadingInterface and upstreamPort from hardware config
489556
// (needed to keep code compatibility elsewhere and allow it to work both with hardware config and plugins)
490557
for _, profile := range dn.ptpUpdate.NodeProfiles {
@@ -920,7 +987,24 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
920987
}
921988
var clockId uint64
922989
phaseOffsetPinFilter := map[string]string{}
923-
for _, iface := range dprocess.ifaces {
990+
991+
// For T-BC mode with hardwareconfig, derive interfaces from hardwareconfig structure
992+
// instead of analyzing ts2phc configuration file
993+
var interfacesToUse config.IFaces
994+
if profileClockType == TBC && dn.hardwareConfigManager != nil &&
995+
dn.hardwareConfigManager.ReadyHardwareConfigForProfile(*nodeProfile.Name) {
996+
interfacesToUse = dn.getInterfacesFromHardwareConfig(nodeProfile)
997+
if len(interfacesToUse) > 0 {
998+
glog.Infof("Using interfaces from hardwareconfig for T-BC profile %s: %v", *nodeProfile.Name, interfacesToUse)
999+
} else {
1000+
glog.Warningf("Failed to derive interfaces from hardwareconfig for T-BC profile %s, falling back to ts2phc config", *nodeProfile.Name)
1001+
interfacesToUse = dprocess.ifaces
1002+
}
1003+
} else {
1004+
interfacesToUse = dprocess.ifaces
1005+
}
1006+
1007+
for _, iface := range interfacesToUse {
9241008
var eventSource []event.EventSource
9251009
if iface.Source == event.GNSS || iface.Source == event.PPS ||
9261010
(iface.Source == event.PTP4l && profileClockType == TBC) {
@@ -986,6 +1070,12 @@ func (dn *Daemon) applyNodePtpProfile(runID int, nodeProfile *ptpv1.PtpProfile)
9861070
// Used only in T-BC in-sync condition:
9871071
inSyncConditionTh, inSyncConditionTimes)
9881072
glog.Infof("depending on %s", dpllDaemon.DependsOn())
1073+
// Set hardwareconfig handler if hardwareconfig manager is available
1074+
if dn.hardwareConfigManager != nil {
1075+
dpllDaemon.SetHardwareConfigHandler(func(devices []*dpllnl.DoDeviceGetReply) error {
1076+
return dn.hardwareConfigManager.ProcessDPLLDeviceNotifications(devices)
1077+
})
1078+
}
9891079
dpllDaemon.CmdInit()
9901080
dprocess.depProcess = append(dprocess.depProcess, dpllDaemon)
9911081
}
@@ -1097,14 +1187,29 @@ func (p *ptpProcess) tBCTransitionCheck(output string, pm *plugin.PluginManager)
10971187
}
10981188

10991189
// applyConditionOrFallback applies hardware config for a condition or falls back to plugin
1100-
func (p *ptpProcess) applyConditionOrFallback(conditionType, pluginAction string, pm *plugin.PluginManager) {
1190+
func (p *ptpProcess) applyConditionOrFallback(conditionType, pluginAction string, pm *plugin.PluginManager, logLine string) {
11011191
if p.dn != nil && p.dn.hardwareConfigManager != nil {
1102-
if err := p.dn.hardwareConfigManager.ApplyConditionForProfile(&p.nodeProfile, conditionType); err != nil {
1103-
glog.Errorf("Failed to apply hardware config for '%s' condition: %v", conditionType, err)
1192+
// Extract source name from log line if available
1193+
sourceName := ""
1194+
if p.tbcStateDetector != nil && logLine != "" {
1195+
portName := p.tbcStateDetector.ExtractPortName(logLine)
1196+
if portName != "" {
1197+
// Look up source name(s) for this port
1198+
sources := p.tbcStateDetector.GetSourcesForPort(portName)
1199+
if len(sources) > 0 {
1200+
// Use the first matching source (typically there's only one)
1201+
sourceName = sources[0]
1202+
glog.Infof("Found source '%s' for port '%s'", sourceName, portName)
1203+
}
1204+
}
1205+
}
1206+
1207+
if err := p.dn.hardwareConfigManager.ApplyConditionForProfile(&p.nodeProfile, conditionType, sourceName); err != nil {
1208+
glog.Errorf("Failed to apply hardware config for '%s' condition (source=%s): %v", conditionType, sourceName, err)
11041209
// Fallback to plugin if hardware config fails
11051210
pm.AfterRunPTPCommand(&p.nodeProfile, pluginAction)
11061211
} else {
1107-
glog.Infof("Successfully applied hardware config for '%s' condition", conditionType)
1212+
glog.Infof("Successfully applied hardware config for '%s' condition (source=%s)", conditionType, sourceName)
11081213
}
11091214
} else {
11101215
// Fallback to plugin if no hardware config manager
@@ -1119,11 +1224,11 @@ func (p *ptpProcess) processTBCTransitionHardwareConfig(output string, pm *plugi
11191224

11201225
switch conditionType {
11211226
case hardwareconfig.ConditionTypeLocked:
1122-
p.applyConditionOrFallback(hardwareconfig.ConditionTypeLocked, "tbc-ho-exit", pm)
1227+
p.applyConditionOrFallback(hardwareconfig.ConditionTypeLocked, "tbc-ho-exit", pm, output)
11231228
p.lastTransitionResult = event.PTP_LOCKED
11241229
p.sendPtp4lEvent()
11251230
case hardwareconfig.ConditionTypeLost:
1126-
p.applyConditionOrFallback(hardwareconfig.ConditionTypeLost, "tbc-ho-entry", pm)
1231+
p.applyConditionOrFallback(hardwareconfig.ConditionTypeLost, "tbc-ho-entry", pm, output)
11271232
p.lastTransitionResult = event.PTP_FREERUN
11281233
p.sendPtp4lEvent()
11291234
}

0 commit comments

Comments
 (0)