Skip to content

Fix DPLL pin API #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 52 additions & 37 deletions pkg/dpll-netlink/dpll-uapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,22 +145,22 @@ func GetDpllStatusHR(reply *DoDeviceGetReply) DpllStatusHR {

// DoPinGetReply is used with the DoPinGet method.
type DoPinGetReplyHR struct {
Id uint32 `json:"id"`
ClockId uint64 `json:"clockId"`
BoardLabel string `json:"boardLabel"`
PanelLabel string `json:"panelLabel"`
PackageLabel string `json:"packageLabel"`
Type string `json:"type"`
Frequency uint64 `json:"frequency"`
FrequencySupported FrequencyRange `json:"frequencySupported"`
Capabilities string `json:"capabilities"`
ParentDevice PinParentDeviceHR `json:"pinParentDevice"`
ParentPin PinParentPinHR `json:"pinParentPin"`
PhaseAdjustMin int32 `json:"phaseAdjustMin"`
PhaseAdjustMax int32 `json:"phaseAdjustMax"`
PhaseAdjust int32 `json:"phaseAdjust"`
FractionalFrequencyOffset int `json:"fractionalFrequencyOffset"`
ModuleName string `json:"moduleName"`
Id uint32 `json:"id"`
ClockId uint64 `json:"clockId"`
BoardLabel string `json:"boardLabel"`
PanelLabel string `json:"panelLabel"`
PackageLabel string `json:"packageLabel"`
Type string `json:"type"`
Frequency uint64 `json:"frequency"`
FrequencySupported []FrequencyRange `json:"frequencySupported"`
Capabilities string `json:"capabilities"`
ParentDevice []PinParentDeviceHR `json:"pinParentDevice"`
ParentPin []PinParentPinHR `json:"pinParentPin"`
PhaseAdjustMin int32 `json:"phaseAdjustMin"`
PhaseAdjustMax int32 `json:"phaseAdjustMax"`
PhaseAdjust int32 `json:"phaseAdjust"`
FractionalFrequencyOffset int `json:"fractionalFrequencyOffset"`
ModuleName string `json:"moduleName"`
}

// PinParentDevice contains nested netlink attributes.
Expand Down Expand Up @@ -241,33 +241,48 @@ func GetPinCapabilities(c uint32) string {
}

// GetPinInfoHR returns human-readable pin status
func GetPinInfoHR(reply *DoPinGetReply) ([]byte, error) {
func GetPinInfoHR(reply *PinInfo) ([]byte, error) {
hr := DoPinGetReplyHR{
Id: reply.Id,
ClockId: reply.ClockId,
BoardLabel: reply.BoardLabel,
PanelLabel: reply.PanelLabel,
PackageLabel: reply.PackageLabel,
Type: GetPinType(reply.Type),
Frequency: reply.Frequency,
FrequencySupported: reply.FrequencySupported,
Capabilities: GetPinCapabilities(reply.Capabilities),
ParentDevice: PinParentDeviceHR{
ParentId: reply.ParentDevice.ParentId,
Direction: GetPinDirection(reply.ParentDevice.Direction),
Prio: reply.ParentDevice.Prio,
State: GetPinState(reply.ParentDevice.State),
PhaseOffset: reply.ParentDevice.PhaseOffset,
},
ParentPin: PinParentPinHR{
ParentId: reply.ParentPin.ParentId,
State: GetPinState(reply.ParentPin.State),
},
Id: reply.Id,
ClockId: reply.ClockId,
BoardLabel: reply.BoardLabel,
PanelLabel: reply.PanelLabel,
PackageLabel: reply.PackageLabel,
Type: GetPinType(reply.Type),
Frequency: reply.Frequency,
FrequencySupported: make([]FrequencyRange, 0),
Capabilities: GetPinCapabilities(reply.Capabilities),
ParentDevice: make([]PinParentDeviceHR, 0),
ParentPin: make([]PinParentPinHR, 0),
PhaseAdjustMin: reply.PhaseAdjustMin,
PhaseAdjustMax: reply.PhaseAdjustMax,
PhaseAdjust: reply.PhaseAdjust,
FractionalFrequencyOffset: reply.FractionalFrequencyOffset,
ModuleName: reply.ModuleName,
}
for i := 0; i < len(reply.ParentDevice); i++ {
hr.ParentDevice = append(
hr.ParentDevice, PinParentDeviceHR{
ParentId: reply.ParentDevice[i].ParentId,
Direction: GetPinDirection(reply.ParentDevice[i].Direction),
Prio: reply.ParentDevice[i].Prio,
State: GetPinState(reply.ParentDevice[i].State),
PhaseOffset: reply.ParentDevice[i].PhaseOffset,
})

}
for i := 0; i < len(reply.ParentPin); i++ {
hr.ParentPin = append(hr.ParentPin, PinParentPinHR{
ParentId: reply.ParentPin[i].ParentId,
State: GetPinState(reply.ParentPin[i].State),
})
}
for i := 0; i < len(reply.FrequencySupported); i++ {
hr.FrequencySupported = append(hr.FrequencySupported, FrequencyRange{
FrequencyMin: reply.FrequencySupported[i].FrequencyMin,
FrequencyMax: reply.FrequencySupported[i].FrequencyMax,
})
}

return json.Marshal(hr)
}
133 changes: 91 additions & 42 deletions pkg/dpll-netlink/dpll.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ func ParseDeviceReplies(msgs []genetlink.Message) ([]*DoDeviceGetReply, error) {
case DPLL_A_MODULE_NAME:
reply.ModuleName = ad.String()
case DPLL_A_MODE:
//reply.Mode = ad.Uint32()
reply.Mode = ad.Uint32()
case DPLL_A_MODE_SUPPORTED:
// reply.ModeSupported = append(reply.ModeSupported, ad.Uint32())
reply.ModeSupported = append(reply.ModeSupported, ad.Uint32())
case DPLL_A_LOCK_STATUS:
reply.LockStatus = ad.Uint32()
case DPLL_A_PAD:
Expand All @@ -158,11 +158,9 @@ func ParseDeviceReplies(msgs []genetlink.Message) ([]*DoDeviceGetReply, error) {
log.Println("default", ad.Type(), len(ad.Bytes()), ad.Bytes())
}
}

if err := ad.Err(); err != nil {
return nil, err
}

replies = append(replies, &reply)
}
return replies, nil
Expand Down Expand Up @@ -245,27 +243,23 @@ type DoDeviceGetReply struct {
Id uint32
ModuleName string
Mode uint32
ModeSupported uint32
ModeSupported []uint32
LockStatus uint32
Temp int32
ClockId uint64
Type uint32
}

func ParsePinReplies(msgs []genetlink.Message) ([]*DoPinGetReply, error) {
replies := make([]*DoPinGetReply, 0, len(msgs))
func ParsePinReplies(msgs []genetlink.Message) ([]*PinInfo, error) {
replies := make([]*PinInfo, 0, len(msgs))

for _, m := range msgs {
ad, err := netlink.NewAttributeDecoder(m.Data)
if err != nil {
return nil, err
}
// Initialize phase offset to a max value, so later we can detect it has been updated
reply := DoPinGetReply{
ParentDevice: PinParentDevice{
PhaseOffset: math.MaxInt64,
},
}
var reply PinInfo

for ad.Next() {
switch ad.Type() {
case DPLL_A_PIN_CLOCK_ID:
Expand All @@ -284,47 +278,58 @@ func ParsePinReplies(msgs []genetlink.Message) ([]*DoPinGetReply, error) {
reply.Frequency = ad.Uint64()
case DPLL_A_PIN_FREQUENCY_SUPPORTED:
ad.Nested(func(ad *netlink.AttributeDecoder) error {
var temp FrequencyRange
for ad.Next() {
switch ad.Type() {
case DPLL_A_PIN_FREQUENCY_MIN:
reply.FrequencySupported.FrequencyMin = ad.Uint64()
temp.FrequencyMin = ad.Uint64()
case DPLL_A_PIN_FREQUENCY_MAX:
reply.FrequencySupported.FrequencyMax = ad.Uint64()
temp.FrequencyMax = ad.Uint64()
}
}
reply.FrequencySupported = append(reply.FrequencySupported, temp)
return nil
})
case DPLL_A_PIN_CAPABILITIES:
reply.Capabilities = ad.Uint32()
case DPLL_A_PIN_PARENT_DEVICE:
ad.Nested(func(ad *netlink.AttributeDecoder) error {
temp := PinParentDevice{
// Initialize phase offset to a max value, so later we can detect it has been updated
PhaseOffset: math.MaxInt64,
}
for ad.Next() {
switch ad.Type() {
case DPLL_A_PIN_PARENT_ID:
reply.ParentDevice.ParentId = ad.Uint32()
temp.ParentId = ad.Uint32()
case DPLL_A_PIN_DIRECTION:
reply.ParentDevice.Direction = ad.Uint32()
temp.Direction = ad.Uint32()
case DPLL_A_PIN_PRIO:
reply.ParentDevice.Prio = ad.Uint32()
temp.Prio = ad.Uint32()
case DPLL_A_PIN_STATE:
reply.ParentDevice.State = ad.Uint32()
temp.State = ad.Uint32()
case DPLL_A_PIN_PHASE_OFFSET:
reply.ParentDevice.PhaseOffset = ad.Int64()
temp.PhaseOffset = ad.Int64()
}

}
reply.ParentDevice = append(reply.ParentDevice, temp)
return nil
})
case DPLL_A_PIN_PARENT_PIN:
ad.Nested(func(ad *netlink.AttributeDecoder) error {
var temp PinParentPin
for ad.Next() {

switch ad.Type() {
case DPLL_A_PIN_PARENT_ID:
reply.ParentPin.ParentId = ad.Uint32()
temp.ParentId = ad.Uint32()
case DPLL_A_PIN_STATE:
reply.ParentPin.State = ad.Uint32()
temp.State = ad.Uint32()
}
}

}
reply.ParentPin = append(reply.ParentPin, temp)
return nil
})
case DPLL_A_PIN_PHASE_ADJUST_MIN:
Expand All @@ -350,11 +355,9 @@ func ParsePinReplies(msgs []genetlink.Message) ([]*DoPinGetReply, error) {
}

// DoPinGet wraps the "pin-get" operation:
func (c *Conn) DoPinGet(req DoPinGetRequest) (*DoPinGetReply, error) {
func (c *Conn) DoPinGet(req DoPinGetRequest) (*PinInfo, error) {
ae := netlink.NewAttributeEncoder()
if req.Id != 0 {
ae.Uint32(DPLL_A_PIN_ID, req.Id)
}
ae.Uint32(DPLL_A_PIN_ID, req.Id)

b, err := ae.Encode()
if err != nil {
Expand All @@ -378,26 +381,18 @@ func (c *Conn) DoPinGet(req DoPinGetRequest) (*DoPinGetReply, error) {
return nil, err
}
if len(replies) != 1 {
return nil, errors.New("dpll: expected exactly one DoPinGetReply")
return nil, errors.New("dpll: expected exactly one PinInfo")
}

return replies[0], nil
}

func (c *Conn) DumpPinGet() ([]*DoPinGetReply, error) {
ae := netlink.NewAttributeEncoder()

b, err := ae.Encode()
if err != nil {
return nil, err
}

func (c *Conn) DumpPinGet() ([]*PinInfo, error) {
msg := genetlink.Message{
Header: genetlink.Header{
Command: DPLL_CMD_PIN_GET,
Version: c.f.Version,
},
Data: b,
}

msgs, err := c.c.Execute(msg, c.f.ID, netlink.Request|netlink.Dump)
Expand All @@ -418,19 +413,19 @@ type DoPinGetRequest struct {
Id uint32
}

// DoPinGetReply is used with the DoPinGet method.
type DoPinGetReply struct {
// PinInfo is used with the DoPinGet method.
type PinInfo struct {
Id uint32
ClockId uint64
BoardLabel string
PanelLabel string
PackageLabel string
Type uint32
Frequency uint64
FrequencySupported FrequencyRange
FrequencySupported []FrequencyRange
Capabilities uint32
ParentDevice PinParentDevice
ParentPin PinParentPin
ParentDevice []PinParentDevice
ParentPin []PinParentPin
PhaseAdjustMin int32
PhaseAdjustMax int32
PhaseAdjust int32
Expand Down Expand Up @@ -489,3 +484,57 @@ func (c *Conn) PinPhaseAdjust(req PinPhaseAdjustRequest) error {
_, err = c.c.Send(msg, c.f.ID, netlink.Request)
return err
}

type PinParentDeviceCtl struct {
Id uint32
PhaseAdjust *int32
PinParentCtl []PinControl
}
type PinControl struct {
PinParentId uint32
Direction *uint32
Prio *uint32
State *uint32
}

func EncodePinControl(req PinParentDeviceCtl) ([]byte, error) {
ae := netlink.NewAttributeEncoder()
ae.Uint32(DPLL_A_PIN_ID, req.Id)
if req.PhaseAdjust != nil {
ae.Int32(DPLL_A_PIN_PHASE_ADJUST, *req.PhaseAdjust)
}
for _, pp := range req.PinParentCtl {
ae.Nested(DPLL_A_PIN_PARENT_DEVICE, func(ae *netlink.AttributeEncoder) error {
ae.Uint32(DPLL_A_PIN_PARENT_ID, pp.PinParentId)
if pp.State != nil {
ae.Uint32(DPLL_A_PIN_STATE, *pp.State)
}
if pp.Prio != nil {
ae.Uint32(DPLL_A_PIN_PRIO, *pp.Prio)
}
if pp.Direction != nil {
ae.Uint32(DPLL_A_PIN_DIRECTION, *pp.Direction)
}
return nil
})
}
b, err := ae.Encode()
if err != nil {
return []byte{}, err
}
return b, nil
}

// SendCommand sends DPLL commands that don't require waiting for a reply
func (c *Conn) SendCommand(command uint8, data []byte) error {
msg := genetlink.Message{
Header: genetlink.Header{
Command: command,
Version: c.f.Version,
},
Data: data,
}
// No replies.
_, err := c.c.Send(msg, c.f.ID, netlink.Request)
return err
}
Loading