Skip to content

Commit

Permalink
add test to identify device
Browse files Browse the repository at this point in the history
  • Loading branch information
adelolmo committed Oct 29, 2023
1 parent 892aca2 commit 8f720ad
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 26 deletions.
2 changes: 1 addition & 1 deletion debian/changelog
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ hd-idle (1.21) unstable; urgency=medium
* Use GivenName instead of Name in the log

[ Andoni del Olmo ]
* Support Jmicron USB Bridge Controller
* Support Jmicron USB Bridge Controller for ATA command

-- Andoni del Olmo <andoni.delolmo@gmail.com> Sun, 22 Oct 2023 09:55:29 +0200

Expand Down
11 changes: 1 addition & 10 deletions sgio/ata.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,13 @@ const (
ataOpStandbyNow2 = 0x94 // Retired in ATA4. Did not coexist with ATAPI.
)

type ataDevice struct {
device string
debug bool
}

func StopAtaDevice(device string, debug bool) error {
ad := ataDevice{
device: device,
debug: debug,
}
f, err := openDevice(device)
if err != nil {
return err
}

switch ad.deviceType() {
switch NewAtaDevice(device, debug).deviceType() {
case Jmicron:
if err = sendSgio(f, jmicronGetRegisters(), debug); err != nil {
return err
Expand Down
45 changes: 30 additions & 15 deletions sgio/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)

Expand All @@ -30,27 +29,44 @@ const (

sysblock = "/sys/block"

jmicron = 0x152d
jmicron = "152d"
)

type AtaDevice struct {
device string
debug bool
fsRoot string
}

func NewAtaDevice(device string, debug bool) AtaDevice {
return AtaDevice{
device: device,
debug: debug,
fsRoot: sysblock,
}
}

type apt struct {
idVendor, idProduct, bcdDevice int
idVendor, idProduct, bcdDevice string
}

func (a apt) isJmicron() bool {
if a.idVendor != jmicron {
return false
}
switch a.idProduct {
case 0x2329, 0x2336, 0x2338, 0x2339:
case "2329", "2336", "2338", "2339":
return true
}
return false
}

func (ad ataDevice) deviceType() int {
func (ad AtaDevice) deviceType() int {
a, err := ad.identifyDevice(ad.device)
if err != nil {
if ad.debug {
fmt.Println("APT: Unsupported device")
}
return Unknown
}
if a.isJmicron() {
Expand All @@ -60,12 +76,15 @@ func (ad ataDevice) deviceType() int {
return Jmicron
}

if ad.debug {
fmt.Println("APT: Unsupported device")
}
return Unknown
}

func (ad ataDevice) identifyDevice(device string) (apt, error) {
func (ad AtaDevice) identifyDevice(device string) (apt, error) {
diskname := strings.Split(device, "/")[2]
sysblockdisk := filepath.Join(sysblock, diskname)
sysblockdisk := filepath.Join(ad.fsRoot, diskname)
idVendor, err := findSystemFile(sysblockdisk, "idVendor")
if err != nil {
return apt{}, err
Expand All @@ -79,7 +98,7 @@ func (ad ataDevice) identifyDevice(device string) (apt, error) {
return apt{}, err
}
if ad.debug {
fmt.Printf("APT: USB ID = 0x%d:0x%d (0x%3d)\n", idVendor, idProduct, bcdDevice)
fmt.Printf("APT: USB ID = 0x%s:0x%s (0x%3s)\n", idVendor, idProduct, bcdDevice)
}
return apt{
idVendor: idVendor,
Expand All @@ -89,24 +108,20 @@ func (ad ataDevice) identifyDevice(device string) (apt, error) {
nil
}

func findSystemFile(systemRoot, filename string) (int, error) {
func findSystemFile(systemRoot, filename string) (string, error) {
_, err := os.ReadFile(filepath.Join(systemRoot, filename))
relativeDir := ""
var content []byte

depth := 0
for depth < 20 {
if err == nil {
id, err := strconv.Atoi(strings.TrimSpace(string(content)))
if err != nil {
return -1, err
}
return id, nil
return strings.TrimSpace(string(content)), nil
}
relativeDir += "/.."
content, err = os.ReadFile(systemRoot + relativeDir + "/" + filename)
depth++
}

return -1, fmt.Errorf("device not found")
return "", fmt.Errorf("device not found")
}
80 changes: 80 additions & 0 deletions sgio/type_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package sgio

import (
"log"
"os"
"path/filepath"
"strings"
"testing"
)

const (
tmpDir = "/tmp/hd-idle/ata"
)

func TestAtaDevice_deviceType(t *testing.T) {
type fields struct {
device string
debug bool
fsRoot string
idVendor, idProduct, bcdDevice string
}
tests := []struct {
name string
fields fields
want int
}{
{
name: "find jmicron controller",
fields: fields{
device: "/dev/sde",
debug: true,
fsRoot: filepath.Join(tmpDir, "sys", "block"),
idVendor: "152d",
idProduct: "2339",
bcdDevice: "100",
},
want: Jmicron,
},
{
name: "unknown device",
fields: fields{
device: "/dev/sde",
debug: true,
fsRoot: filepath.Join(tmpDir, "sys", "block"),
idVendor: "1058",
idProduct: "25a3",
bcdDevice: "1021",
},
want: Unknown,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ad := AtaDevice{
device: tt.fields.device,
debug: tt.fields.debug,
fsRoot: tt.fields.fsRoot,
}

err := os.RemoveAll(tmpDir)
if err != nil {
log.Fatal(err)
}
infoDir := filepath.Join(tmpDir, "/sys/devices/pci0000:00/0000:00:15.0/usb2/2-2/2-2.3/2-2.3.2")
diskname := strings.Split(tt.fields.device, "/")[2]
deviceRoot := infoDir + "/2-2.3.2:1.0/host5/target5:0:0/5:0:0:0/block/" + diskname
_ = os.MkdirAll(deviceRoot, 0755)
_ = os.WriteFile(filepath.Join(infoDir, "idVendor"), []byte(tt.fields.idVendor), 0666)
_ = os.WriteFile(filepath.Join(infoDir, "idProduct"), []byte(tt.fields.idProduct), 0666)
_ = os.WriteFile(filepath.Join(infoDir, "bcdDevice"), []byte(tt.fields.bcdDevice), 0666)
_ = os.MkdirAll(filepath.Join(tmpDir, "/sys/block"), 0755)
if err = os.Symlink(deviceRoot, filepath.Join(tmpDir, "/sys/block", diskname)); err != nil {
log.Fatal(err)
}
if got := ad.deviceType(); got != tt.want {
t.Errorf("deviceType() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 8f720ad

Please sign in to comment.