Files
ipsw/pkg/usb/pongo/pongo.go

100 lines
2.0 KiB
Go

//go:build libusb
package pongo
import (
"encoding/binary"
"fmt"
"math/bits"
"github.com/apex/log"
"github.com/google/gousb"
)
const (
PONGO_USB_VENDOR = 0x05ac
PONGO_USB_PRODUCT = 0x4141
)
type Client struct {
dev *gousb.Device
}
func NewClient() (*Client, error) {
ctx := gousb.NewContext()
defer ctx.Close()
devs, err := ctx.OpenDevices(func(desc *gousb.DeviceDesc) bool {
if desc.Vendor == PONGO_USB_VENDOR && desc.Product == PONGO_USB_PRODUCT {
dev, err := ctx.OpenDeviceWithVIDPID(desc.Vendor, desc.Product)
if err != nil {
log.Fatalf("Could not open a device: %v", err)
}
vendor, _ := dev.Manufacturer()
product, _ := dev.Product()
log.WithFields(log.Fields{
"vendor": fmt.Sprintf("'%s'", vendor),
"product": fmt.Sprintf("'%s'", product),
}).Debug("Found USB Device")
return true
}
return false
})
if err != nil {
return nil, err
}
if len(devs) == 0 {
return nil, fmt.Errorf("no 'pongoOS' devices found")
}
return &Client{
dev: devs[0],
}, nil
}
func (c *Client) Close() error {
return c.dev.Close()
}
func (c *Client) SendCommand(cmd string) error {
if n, err := c.dev.Control(0x21, 3, 0, 0, []byte(cmd+"\n")); err != nil {
return fmt.Errorf("%s.Control(%s): %v", c.dev, cmd, err)
} else if n != len(cmd)+1 {
return fmt.Errorf("%s.Control(%s): %d bytes written, want %d", c.dev, cmd, n, len(cmd)+1)
}
return nil
}
func encodeUint32(x uint32) []byte {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, x)
return buf[bits.LeadingZeros32(x)>>3:]
}
func (c *Client) GetStdOut() (string, error) {
var out string
progress := []byte{1}
bbuf := make([]byte, 0x1000)
for progress[0] == 1 {
if _, err := c.dev.Control(0xa1, 2, 0, 0, progress); err != nil {
return "", fmt.Errorf("%s.Control(%s): %v", c.dev, "get stdout", err)
}
n, err := c.dev.Control(0xa1, 1, 0, 0, bbuf)
if err != nil {
return "", fmt.Errorf("%s.Control(%s): %v", c.dev, "get stdout", err)
}
if n == 0 {
break
}
out += string(bbuf[:n])
}
return out, nil
}