Implemented LED RPC + started USB

This commit is contained in:
mame82 2018-05-02 20:43:22 +00:00
parent 86021e193a
commit 3a9ec59b18
6 changed files with 361 additions and 311 deletions

View File

@ -3,19 +3,27 @@ package main
import (
"log"
"time"
"reflect"
// "reflect"
"flag" //will be replaced with cobra
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "../proto"
)
const (
address = "localhost:50051"
)
func main() {
//Parse cli flags, should be replaced with cobra
blinkCountPtr := flag.Int("blink", -1, "LED blink count (0 = LED off, 255 = LED solid, 1..254 blink n times)")
var rpcHostPtr string
var rpcPortPtr string
flag.StringVar(&rpcHostPtr, "host", "localhost", "The remote RPC host running P4wnP1 service")
flag.StringVar(&rpcPortPtr, "port", "50051", "The remote RPC port of P4wnP1 service")
flag.Parse()
// Set up a connection to the server.
address := rpcHostPtr + ":" + rpcPortPtr
log.Printf("Connecting %s ...", address)
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
@ -23,12 +31,23 @@ func main() {
defer conn.Close()
c := pb.NewP4WNP1Client(conn)
// Contact the server and print out its response.
// Contact the server
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if *blinkCountPtr >= 0 {
c.SetLEDSettings(ctx, &pb.LEDSettings{ BlinkCount: uint32(*blinkCountPtr) })
}
/*
r, err := c.GetGadgetSettings(ctx, &pb.Empty{})
if err != nil {
log.Fatalf("could not get GadgetSettings: %v", err)
}
log.Printf("USB Settings %s: %+v", reflect.TypeOf(*r), *r)
log.Printf("Set LED to blink count 3")
c.SetLEDSettings(ctx, &pb.LEDSettings{ BlinkCount: 3})
*/
}

View File

@ -1,11 +1,11 @@
//package led
package main
package core
import(
"os"
"log"
"io/ioutil"
"time"
"sync/atomic"
pb "../proto"
)
@ -21,7 +21,11 @@ const (
LED_DELAY_PAUSE = 500 * time.Millisecond
)
func initLed(led_on bool) (error) {
var (
blink_count uint32 = 0
)
func InitLed(led_on bool) (error) {
//set trigger of LED to manual
log.Println("Setting LED to manual trigger ...")
ioutil.WriteFile(LED_TRIGGER_PATH, []byte(LED_TRIGGER_MANUAL), os.ModePerm)
@ -32,35 +36,34 @@ func initLed(led_on bool) (error) {
log.Println("Setting LED to OFF ...")
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_OFF), os.ModePerm)
}
atomic.StoreUint32(&blink_count, 0)
go led_loop()
return nil
}
func led_loop() {
blink_count := 10
for {
for i := 0; i <= blink_count; i++ {
for i := uint32(0); i < atomic.LoadUint32(&blink_count); i++ {
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_ON), os.ModePerm)
time.Sleep(LED_DELAY_ON)
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_OFF), os.ModePerm)
time.Sleep(LED_DELAY_OFF)
//Don't turn off led if blink_count >= 255 (solid)
if 255 > atomic.LoadUint32(&blink_count) {
ioutil.WriteFile(LED_BRIGHTNESS_PATH, []byte(LED_OFF), os.ModePerm)
time.Sleep(LED_DELAY_OFF)
}
}
time.Sleep(LED_DELAY_PAUSE)
}
}
func setLed(s pb.LEDSettings) (error) {
log.Printf("setLED called with %+v", s)
atomic.StoreUint32(&blink_count, s.BlinkCount)
return nil
}
func main() {
initLed(false)
log.Println("testing led")
settings := pb.LEDSettings{}
setLed(settings)
go led_loop()
time.Sleep(10 * time.Second)
}

View File

@ -1,41 +1,41 @@
package main
//package rpcserv
package core
import (
"encoding/json"
"log"
"net"
"encoding/json"
pb "../proto"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "../proto"
"google.golang.org/grpc/reflection"
)
type server struct{}
//Attach handler function implementing the "GetGadgetSettings" interface to server
func (s *server) GetGadgetSettings(context.Context, *pb.Empty) (*pb.GadgetSettings, error) {
usbset := &pb.GadgetSettings {
Pid: "0x1337",
Vid: "0x1222",
Manufacturer: "MaMe82",
Serial: "deadbeef13371337",
Product: "P4wnP1 by MaMe82",
Use_RNDIS: false,
Use_CDC_ECM: true,
usbset := &pb.GadgetSettings{
Pid: "0x1337",
Vid: "0x1222",
Manufacturer: "MaMe82",
Serial: "deadbeef13371337",
Product: "P4wnP1 by MaMe82",
Use_RNDIS: false,
Use_CDC_ECM: true,
Use_HID_KEYBOARD: false,
Use_HID_MOUSE: false,
Use_HID_RAW: false,
Use_UMS: false,
Use_SERIAL: false,
RndisSettings: &pb.GadgetSettingsEthernet { HostAddr: "11:22:33:44:55:66", DevAddr: "66:55:44:33:22:11", },
CdcEcmSettings: &pb.GadgetSettingsEthernet { HostAddr: "11:22:33:54:76:98", DevAddr: "66:55:44:98:76:54", },
Use_HID_MOUSE: false,
Use_HID_RAW: false,
Use_UMS: false,
Use_SERIAL: false,
RndisSettings: &pb.GadgetSettingsEthernet{HostAddr: "11:22:33:44:55:66", DevAddr: "66:55:44:33:22:11"},
CdcEcmSettings: &pb.GadgetSettingsEthernet{HostAddr: "11:22:33:54:76:98", DevAddr: "66:55:44:98:76:54"},
}
j_usbset, _ := json.Marshal(usbset)
log.Printf("Gadget settings requested %v", string(j_usbset))
return usbset, nil
}
@ -59,29 +59,27 @@ func (s *server) GetLEDSettings(context.Context, *pb.Empty) (*pb.LEDSettings, er
return led_settings, nil
}
func (s *server) SetLEDSettings(context.Context, *pb.LEDSettings) (*pb.Error, error) {
func (s *server) SetLEDSettings(ctx context.Context, ledSettings *pb.LEDSettings) (rpcerr *pb.Error, err error) {
log.Printf("SetLEDSettings %+v", ledSettings)
setLed(*ledSettings)
return &pb.Error{Err: 0}, nil
}
func start_rpc_server(host string, port string) {
listen_address := host+":"+port
func StartRpcServer(host string, port string) {
listen_address := host + ":" + port
//Open TCP listener
log.Printf("P4wnP1 RPC server lsitening on " + listen_address)
lis, err := net.Listen("tcp", listen_address)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
//Create gRPC Server
s := grpc.NewServer()
pb.RegisterP4WNP1Server(s, &server{})
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
log.Fatalf("Failed to serve: %v", err)
}
}
func main() {
start_rpc_server("127.0.0.1", "50051")
}

View File

@ -1,210 +1,160 @@
package usb
package core
import(
import (
"errors"
"os"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
pb "../proto"
)
const (
USB_GADGET_DIR_BASE = "/sys/kernel/config/usb_gadget"
USB_GADGET_DIR = USB_GADGET_DIR_BASE + "/mame82_gadget"
USB_DEFAULT_SERIAL = "deadbeefdeadbeef"
USB_GADGET_DIR_BASE = "/sys/kernel/config/usb_gadget"
USB_GADGET_DIR = USB_GADGET_DIR_BASE + "/mame82_gadget"
USB_DEFAULT_SERIAL = "deadbeefdeadbeef"
USB_DEFAULT_MANUFACTURER = "MaMe82"
USB_DEFAULT_PRODUCT = "P4wnP1 by MaMe82"
USB_DEFAULT_PRODUCT = "P4wnP1 by MaMe82"
USB_bcdDevice = "0x0100" //Version 1.00
USB_bcdUSB = "0x0200" //mode: USB 2.0
USB_bcdUSB = "0x0200" //mode: USB 2.0
// composite class / subclass / proto (needs single configuration)
USB_bDeviceClass = "0xEF"
USB_bDeviceClass = "0xEF"
USB_bDeviceSubClass = "0x02"
USB_bDeviceProtocol = "0x01"
USB_CONFIGURATION_MaxPower = "250"
USB_CONFIGURATION_MaxPower = "250"
USB_CONFIGURATION_bmAttributes = "0x80" //should be 0x03 for USB_OTG_SRP | USB_OTG_HNP
//RNDIS function constants
USB_FUNCTION_RNDIS_DEFAULT_host_addr = "42:63:65:12:34:56"
USB_FUNCTION_RNDIS_DEFAULT_dev_addr = "42:63:65:56:34:12"
/*
//RNDIS function constants
USB_FUNCTION_RNDIS_DEFAULT_host_addr = "42:63:65:12:34:56"
USB_FUNCTION_RNDIS_DEFAULT_dev_addr = "42:63:65:56:34:12"
*/
//OS descriptors for RNDIS composite function on Windows
USB_FUNCTION_RNDIS_os_desc_use = "1"
USB_FUNCTION_RNDIS_os_desc_b_vendor_code = "0xbc"
USB_FUNCTION_RNDIS_os_desc_qw_sign = "MSFT100"
USB_FUNCTION_RNDIS_os_desc_interface_compatible_id = "RNDIS"
USB_FUNCTION_RNDIS_os_desc_use = "1"
USB_FUNCTION_RNDIS_os_desc_b_vendor_code = "0xbc"
USB_FUNCTION_RNDIS_os_desc_qw_sign = "MSFT100"
USB_FUNCTION_RNDIS_os_desc_interface_compatible_id = "RNDIS"
USB_FUNCTION_RNDIS_os_desc_interface_sub_compatible_id = "5162001"
//CDC ECM function constants
USB_FUNCTION_CDC_ECM_DEFAULT_host_addr = "42:63:66:12:34:56"
USB_FUNCTION_CDC_ECM_DEFAULT_dev_addr = "42:63:66:56:34:12"
/*
//CDC ECM function constants
USB_FUNCTION_CDC_ECM_DEFAULT_host_addr = "42:63:66:12:34:56"
USB_FUNCTION_CDC_ECM_DEFAULT_dev_addr = "42:63:66:56:34:12"
*/
//HID function, keyboard constants
USB_FUNCTION_HID_KEYBOARD_protocol = "1"
USB_FUNCTION_HID_KEYBOARD_subclass = "1"
USB_FUNCTION_HID_KEYBOARD_protocol = "1"
USB_FUNCTION_HID_KEYBOARD_subclass = "1"
USB_FUNCTION_HID_KEYBOARD_report_length = "8"
USB_FUNCTION_HID_KEYBOARD_report_desc = "\x05\x01\t\x06\xa1\x01\x05\x07\x19\xe0)\xe7\x15\x00%\x01u\x01\x95\x08\x81\x02\x95\x01u\x08\x81\x03\x95\x05u\x01\x05\x08\x19\x01)\x05\x91\x02\x95\x01u\x03\x91\x03\x95\x06u\x08\x15\x00%e\x05\x07\x19\x00)e\x81\x00\xc0"
USB_FUNCTION_HID_KEYBOARD_name = "hid.keyboard"
USB_FUNCTION_HID_KEYBOARD_report_desc = "\x05\x01\t\x06\xa1\x01\x05\x07\x19\xe0)\xe7\x15\x00%\x01u\x01\x95\x08\x81\x02\x95\x01u\x08\x81\x03\x95\x05u\x01\x05\x08\x19\x01)\x05\x91\x02\x95\x01u\x03\x91\x03\x95\x06u\x08\x15\x00%e\x05\x07\x19\x00)e\x81\x00\xc0"
USB_FUNCTION_HID_KEYBOARD_name = "hid.keyboard"
//HID function, mouse constants
USB_FUNCTION_HID_MOUSE_protocol = "2"
USB_FUNCTION_HID_MOUSE_subclass = "1"
USB_FUNCTION_HID_MOUSE_protocol = "2"
USB_FUNCTION_HID_MOUSE_subclass = "1"
USB_FUNCTION_HID_MOUSE_report_length = "6"
USB_FUNCTION_HID_MOUSE_report_desc = "\x05\x01\t\x02\xa1\x01\t\x01\xa1\x00\x85\x01\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x03\x05\x01\t0\t1\x15\x81%\x7fu\x08\x95\x02\x81\x06\x95\x02u\x08\x81\x01\xc0\xc0\x05\x01\t\x02\xa1\x01\t\x01\xa1\x00\x85\x02\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x01\x05\x01\t0\t1\x15\x00&\xff\x7f\x95\x02u\x10\x81\x02\xc0\xc0"
USB_FUNCTION_HID_MOUSE_name = "hid.mouse"
USB_FUNCTION_HID_MOUSE_report_desc = "\x05\x01\t\x02\xa1\x01\t\x01\xa1\x00\x85\x01\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x03\x05\x01\t0\t1\x15\x81%\x7fu\x08\x95\x02\x81\x06\x95\x02u\x08\x81\x01\xc0\xc0\x05\x01\t\x02\xa1\x01\t\x01\xa1\x00\x85\x02\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x01\x05\x01\t0\t1\x15\x00&\xff\x7f\x95\x02u\x10\x81\x02\xc0\xc0"
USB_FUNCTION_HID_MOUSE_name = "hid.mouse"
//HID function, custom vendor device constants
USB_FUNCTION_HID_RAW_protocol = "1"
USB_FUNCTION_HID_RAW_subclass = "1"
USB_FUNCTION_HID_RAW_protocol = "1"
USB_FUNCTION_HID_RAW_subclass = "1"
USB_FUNCTION_HID_RAW_report_length = "64"
USB_FUNCTION_HID_RAW_report_desc = "\x06\x00\xff\t\x01\xa1\x01\t\x01\x15\x00&\xff\x00u\x08\x95@\x81\x02\t\x02\x15\x00&\xff\x00u\x08\x95@\x91\x02\xc0"
USB_FUNCTION_HID_RAW_name = "hid.raw"
USB_FUNCTION_HID_RAW_report_desc = "\x06\x00\xff\t\x01\xa1\x01\t\x01\x15\x00&\xff\x00u\x08\x95@\x81\x02\t\x02\x15\x00&\xff\x00u\x08\x95@\x91\x02\xc0"
USB_FUNCTION_HID_RAW_name = "hid.raw"
)
type USB struct {
Vid string
Pid string
Manufacturer string
Product string
Serial string
Use_CDC_ECM bool
Use_RNDIS bool
Use_HID_KEYBOARD bool
Use_HID_MOUSE bool
Use_HID_RAW bool
Use_UMS bool
Use_SERIAL bool
func InitDefaultGadgetSettings() error {
return InitGadget(CreateDefaultGadgetSettings())
}
func DestroyAllGadgets() error {
//gadget_root := "./test"
gadget_root := USB_GADGET_DIR_BASE
//check if root exists, return error otherwise
if _, err := os.Stat(gadget_root); os.IsNotExist(err) {
return errors.New("Configfs path for gadget doesn't exist")
func CreateDefaultGadgetSettings() (res pb.GadgetSettings) {
res = pb.GadgetSettings{
Vid: "0x1d6b",
Pid: "0x1337",
Manufacturer: "MaMe82",
Product: "P4wnP1 by MaMe82",
Serial: "deadbeef1337",
Use_CDC_ECM: true,
Use_RNDIS: true,
Use_HID_KEYBOARD: false,
Use_HID_MOUSE: false,
Use_HID_RAW: false,
Use_UMS: false,
Use_SERIAL: false,
RndisSettings: &pb.GadgetSettingsEthernet{
HostAddr: "42:63:65:12:34:56",
DevAddr: "42:63:65:56:34:12",
},
CdcEcmSettings: &pb.GadgetSettingsEthernet{
HostAddr: "42:63:66:12:34:56",
DevAddr: "42:63:66:56:34:12",
},
}
gadget_dirs, err := ioutil.ReadDir(gadget_root)
return res
}
//depends on `bash`, `grep` and `lsmod` binary
func CheckLibComposite() error {
log.Printf("Checking for libcomposite...")
out, err := exec.Command("lsmod").Output()
if err != nil {
return errors.New("No gadgets")
log.Fatal(err)
}
for _, gadget_dir_obj := range gadget_dirs {
gadget_name := gadget_dir_obj.Name()
fmt.Println("Found gadget: "+gadget_name)
err = DestroyGadget(gadget_name)
if err != nil {
fmt.Println(err) //don't return, continue with next
}
if strings.Contains(string(out), "libcomposite") {
log.Printf("... libcomposite loaded")
return nil
}
return nil
//if here, libcomposite isn't loaded ... try to load
log.Printf("Libcomposite not loaded, trying to fix ...")
err = exec.Command("modprobe", "libcomposite").Run()
if err == nil {
log.Printf("... libcomposite loaded")
}
return err
}
func DestroyGadget(Gadget_name string) error {
//gadget_root := "./test"
gadget_dir := USB_GADGET_DIR_BASE + "/" + Gadget_name
//check if root exists, return error otherwise
if _, err := os.Stat(USB_GADGET_DIR_BASE); os.IsNotExist(err) {
return errors.New("Gadget " + Gadget_name + " doesn't exist")
}
fmt.Println("Deconstructing gadget " + Gadget_name + "...")
//Assure gadget gets unbound from UDC
ioutil.WriteFile(gadget_dir+"/UDC", []byte("\x00"), os.ModePerm)
//Iterate over configurations
config_dirs, _ := ioutil.ReadDir(gadget_dir + "/configs")
for _, conf_dir_obj := range config_dirs {
conf_name := conf_dir_obj.Name()
conf_dir := gadget_dir + "/configs/" + conf_name
fmt.Println("Found config: " + conf_name)
//find linked functions
conf_content, _ := ioutil.ReadDir(conf_dir)
for _, function := range conf_content {
//Remove link from function to config
if function.Mode() & os.ModeSymlink > 0 {
fmt.Println("\tRemoving function " + function.Name() + " from config " + conf_name)
os.Remove(conf_dir + "/" + function.Name())
}
}
//find string directories in config
strings_content, _ := ioutil.ReadDir(conf_dir + "/strings")
for _, str := range strings_content {
string_dir := str.Name()
//Remove string from config
fmt.Println("\tRemoving string dir '" + string_dir + "' from configuration")
os.Remove(conf_dir + "/strings/" + string_dir)
}
//Check if there's an OS descriptor refering this config
if _, err := os.Stat(gadget_dir + "/os_desc/" + conf_name); !os.IsNotExist(err) {
fmt.Println("\tDeleting link to '" + conf_name + "' from gadgets OS descriptor")
os.Remove(gadget_dir + "/os_desc/" + conf_name)
}
// remove config folder, finally
fmt.Println("\tDeleting configuration '" + conf_name + "'")
os.Remove(conf_dir)
}
// remove functions
fmt.Println("Removing functions from '" + Gadget_name + "'")
os.RemoveAll(gadget_dir + "/functions/")
//find string directories in gadget
strings_content, _ := ioutil.ReadDir(gadget_dir + "/strings")
for _, str := range strings_content {
string_dir := str.Name()
//Remove string from config
fmt.Println("Removing string dir '" + string_dir + "' from " + Gadget_name)
os.Remove(gadget_dir + "/strings/" + string_dir)
}
//And now remove the gadget itself
fmt.Println("Removing gadget " + Gadget_name)
os.Remove(gadget_dir)
return nil
}
func (self USB) CreateGadget() error {
func InitGadget(settings pb.GadgetSettings) error {
//gadget_root := "./test"
gadget_root := USB_GADGET_DIR_BASE
//check if root exists, return error otherwise
if _, err := os.Stat(gadget_root); os.IsNotExist(err) {
return errors.New("Configfs path for gadget doesn't exist")
return errors.New("Configfs path for gadget doesn't exist")
}
//ToDo: check if UDC is present and usable
//create gadget folder
os.Mkdir(USB_GADGET_DIR, os.ModePerm)
//set vendor ID, product ID
ioutil.WriteFile(USB_GADGET_DIR+"/idVendor", []byte(self.Vid), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/idProduct", []byte(self.Pid), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/idVendor", []byte(settings.Vid), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/idProduct", []byte(settings.Pid), os.ModePerm)
//set USB mode to 2.0 and device version to 1.0
ioutil.WriteFile(USB_GADGET_DIR+"/bcdUSB", []byte(USB_bcdUSB), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/bcdDevice", []byte(USB_bcdDevice), os.ModePerm)
//composite class / subclass / proto (needs single configuration)
ioutil.WriteFile(USB_GADGET_DIR+"/bDeviceClass", []byte(USB_bDeviceClass), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/bDeviceSubClass", []byte(USB_bDeviceSubClass), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/bDeviceProtocol", []byte(USB_bDeviceProtocol), os.ModePerm)
// set device descriptions
os.Mkdir(USB_GADGET_DIR+"/strings/0x409", os.ModePerm) // English language strings
ioutil.WriteFile(USB_GADGET_DIR+"/strings/0x409/serialnumber", []byte(self.Serial), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/strings/0x409/manufacturer", []byte(self.Manufacturer), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/strings/0x409/product", []byte(self.Product), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/strings/0x409/serialnumber", []byte(settings.Serial), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/strings/0x409/manufacturer", []byte(settings.Manufacturer), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/strings/0x409/product", []byte(settings.Product), os.ModePerm)
// create configuration instance (only one, as multiple configs aren't valid for Windows composite devices)
os.MkdirAll(USB_GADGET_DIR+"/configs/c.1/strings/0x409", os.ModePerm) // English language strings
ioutil.WriteFile(USB_GADGET_DIR+"/configs/c.1/strings/0x409/configuration", []byte("Config 1: Composite"), os.ModePerm)
@ -212,26 +162,26 @@ func (self USB) CreateGadget() error {
ioutil.WriteFile(USB_GADGET_DIR+"/configs/c.1/bmAttributes", []byte(USB_CONFIGURATION_bmAttributes), os.ModePerm)
// RNDIS has to be the first interface on Composite device for Windows (first function initialized)
if self.Use_RNDIS {
if settings.Use_RNDIS {
os.Mkdir(USB_GADGET_DIR+"/functions/rndis.usb0", os.ModePerm) //create RNDIS function
ioutil.WriteFile(USB_GADGET_DIR+"/functions/rndis.usb0/host_addr", []byte(USB_FUNCTION_RNDIS_DEFAULT_host_addr), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/functions/rndis.usb0/dev_addr", []byte(USB_FUNCTION_RNDIS_DEFAULT_dev_addr), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/functions/rndis.usb0/host_addr", []byte(settings.RndisSettings.HostAddr), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/functions/rndis.usb0/dev_addr", []byte(settings.RndisSettings.DevAddr), os.ModePerm)
/*
add OS specific device descriptors to force Windows to load RNDIS drivers
=============================================================================
Witout this additional descriptors, most Windows system detect the RNDIS interface as "Serial COM port"
To prevent this, the Microsoft specific OS descriptors are added in here
!! Important:
If the device already has been connected to the Windows System without providing the
OS descriptor, Windows never asks again for them and thus never installs the RNDIS driver
This behavior is driven by creation of an registry hive, the first time a device without
OS descriptors is attached. The key is build like this:
HKLM\SYSTEM\CurrentControlSet\Control\usbflags\[USB_VID+USB_PID+bcdRelease\osvc
add OS specific device descriptors to force Windows to load RNDIS drivers
=============================================================================
Witout this additional descriptors, most Windows system detect the RNDIS interface as "Serial COM port"
To prevent this, the Microsoft specific OS descriptors are added in here
!! Important:
If the device already has been connected to the Windows System without providing the
OS descriptor, Windows never asks again for them and thus never installs the RNDIS driver
This behavior is driven by creation of an registry hive, the first time a device without
OS descriptors is attached. The key is build like this:
To allow Windows to read the OS descriptors again, the according registry hive has to be
deleted manually or USB descriptor values have to be cahnged (f.e. USB_PID).
HKLM\SYSTEM\CurrentControlSet\Control\usbflags\[USB_VID+USB_PID+bcdRelease\osvc
To allow Windows to read the OS descriptors again, the according registry hive has to be
deleted manually or USB descriptor values have to be cahnged (f.e. USB_PID).
*/
//set OS descriptors for Windows
@ -244,110 +194,190 @@ func (self USB) CreateGadget() error {
//activate function by symlinking to config 1
err := os.Symlink(USB_GADGET_DIR+"/functions/rndis.usb0", USB_GADGET_DIR+"/configs/c.1/rndis.usb0")
if err != nil {
fmt.Println(err)
log.Println(err)
}
// add config 1 to OS descriptors
err = os.Symlink(USB_GADGET_DIR+"/configs/c.1", USB_GADGET_DIR+"/os_desc/c.1")
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
if self.Use_CDC_ECM {
if settings.Use_CDC_ECM {
os.Mkdir(USB_GADGET_DIR+"/functions/ecm.usb1", os.ModePerm) //create CDC ECM function
ioutil.WriteFile(USB_GADGET_DIR+"/functions/ecm.usb1/host_addr", []byte(USB_FUNCTION_CDC_ECM_DEFAULT_host_addr), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/functions/ecm.usb1/dev_addr", []byte(USB_FUNCTION_CDC_ECM_DEFAULT_dev_addr), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/functions/ecm.usb1/host_addr", []byte(settings.CdcEcmSettings.HostAddr), os.ModePerm)
ioutil.WriteFile(USB_GADGET_DIR+"/functions/ecm.usb1/dev_addr", []byte(settings.CdcEcmSettings.DevAddr), os.ModePerm)
//activate function by symlinking to config 1
err := os.Symlink(USB_GADGET_DIR+"/functions/ecm.usb1", USB_GADGET_DIR+"/configs/c.1/ecm.usb1")
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
if self.Use_SERIAL {
if settings.Use_SERIAL {
os.Mkdir(USB_GADGET_DIR+"/functions/acm.GS0", os.ModePerm) //create ACM function
//activate function by symlinking to config 1
err := os.Symlink(USB_GADGET_DIR+"/functions/acm.GS0", USB_GADGET_DIR+"/configs/c.1/acm.GS0")
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
if self.Use_HID_KEYBOARD {
funcdir := USB_GADGET_DIR+"/functions/"+USB_FUNCTION_HID_KEYBOARD_name
if settings.Use_HID_KEYBOARD {
funcdir := USB_GADGET_DIR + "/functions/" + USB_FUNCTION_HID_KEYBOARD_name
os.Mkdir(funcdir, os.ModePerm) //create HID function for keyboard
ioutil.WriteFile(funcdir + "/protocol", []byte(USB_FUNCTION_HID_KEYBOARD_protocol), os.ModePerm)
ioutil.WriteFile(funcdir + "/subclass", []byte(USB_FUNCTION_HID_KEYBOARD_subclass), os.ModePerm)
ioutil.WriteFile(funcdir + "/report_length", []byte(USB_FUNCTION_HID_KEYBOARD_report_length), os.ModePerm)
ioutil.WriteFile(funcdir + "/report_desc", []byte(USB_FUNCTION_HID_KEYBOARD_report_desc), os.ModePerm)
ioutil.WriteFile(funcdir+"/protocol", []byte(USB_FUNCTION_HID_KEYBOARD_protocol), os.ModePerm)
ioutil.WriteFile(funcdir+"/subclass", []byte(USB_FUNCTION_HID_KEYBOARD_subclass), os.ModePerm)
ioutil.WriteFile(funcdir+"/report_length", []byte(USB_FUNCTION_HID_KEYBOARD_report_length), os.ModePerm)
ioutil.WriteFile(funcdir+"/report_desc", []byte(USB_FUNCTION_HID_KEYBOARD_report_desc), os.ModePerm)
err := os.Symlink(funcdir, USB_GADGET_DIR+"/configs/c.1/"+USB_FUNCTION_HID_KEYBOARD_name)
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
if self.Use_HID_MOUSE {
funcdir := USB_GADGET_DIR+"/functions/"+USB_FUNCTION_HID_MOUSE_name
if settings.Use_HID_MOUSE {
funcdir := USB_GADGET_DIR + "/functions/" + USB_FUNCTION_HID_MOUSE_name
os.Mkdir(funcdir, os.ModePerm) //create HID function for mouse
ioutil.WriteFile(funcdir + "/protocol", []byte(USB_FUNCTION_HID_MOUSE_protocol), os.ModePerm)
ioutil.WriteFile(funcdir + "/subclass", []byte(USB_FUNCTION_HID_MOUSE_subclass), os.ModePerm)
ioutil.WriteFile(funcdir + "/report_length", []byte(USB_FUNCTION_HID_MOUSE_report_length), os.ModePerm)
ioutil.WriteFile(funcdir + "/report_desc", []byte(USB_FUNCTION_HID_MOUSE_report_desc), os.ModePerm)
ioutil.WriteFile(funcdir+"/protocol", []byte(USB_FUNCTION_HID_MOUSE_protocol), os.ModePerm)
ioutil.WriteFile(funcdir+"/subclass", []byte(USB_FUNCTION_HID_MOUSE_subclass), os.ModePerm)
ioutil.WriteFile(funcdir+"/report_length", []byte(USB_FUNCTION_HID_MOUSE_report_length), os.ModePerm)
ioutil.WriteFile(funcdir+"/report_desc", []byte(USB_FUNCTION_HID_MOUSE_report_desc), os.ModePerm)
err := os.Symlink(funcdir, USB_GADGET_DIR+"/configs/c.1/"+USB_FUNCTION_HID_MOUSE_name)
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
if self.Use_HID_RAW {
funcdir := USB_GADGET_DIR+"/functions/"+USB_FUNCTION_HID_RAW_name
if settings.Use_HID_RAW {
funcdir := USB_GADGET_DIR + "/functions/" + USB_FUNCTION_HID_RAW_name
os.Mkdir(funcdir, os.ModePerm) //create HID function for mouse
ioutil.WriteFile(funcdir + "/protocol", []byte(USB_FUNCTION_HID_RAW_protocol), os.ModePerm)
ioutil.WriteFile(funcdir + "/subclass", []byte(USB_FUNCTION_HID_RAW_subclass), os.ModePerm)
ioutil.WriteFile(funcdir + "/report_length", []byte(USB_FUNCTION_HID_RAW_report_length), os.ModePerm)
ioutil.WriteFile(funcdir + "/report_desc", []byte(USB_FUNCTION_HID_RAW_report_desc), os.ModePerm)
ioutil.WriteFile(funcdir+"/protocol", []byte(USB_FUNCTION_HID_RAW_protocol), os.ModePerm)
ioutil.WriteFile(funcdir+"/subclass", []byte(USB_FUNCTION_HID_RAW_subclass), os.ModePerm)
ioutil.WriteFile(funcdir+"/report_length", []byte(USB_FUNCTION_HID_RAW_report_length), os.ModePerm)
ioutil.WriteFile(funcdir+"/report_desc", []byte(USB_FUNCTION_HID_RAW_report_desc), os.ModePerm)
err := os.Symlink(funcdir, USB_GADGET_DIR+"/configs/c.1/"+USB_FUNCTION_HID_RAW_name)
if err != nil {
fmt.Println(err)
log.Println(err)
}
}
//get UDC driver name and bind to gadget
files, err := ioutil.ReadDir("/sys/class/udc")
if err != nil {
return errors.New("Couldn't find working UDC driver")
return errors.New("Couldn't find working UDC driver")
}
if len(files) < 1 {
return errors.New("Couldn't find working UDC driver")
return errors.New("Couldn't find working UDC driver")
}
udc_name := files[0].Name()
ioutil.WriteFile(USB_GADGET_DIR+"/UDC", []byte(udc_name), os.ModePerm)
return nil
}
func New() USB {
ust := USB{
Vid: "0x1d6b",
Pid: "0x1338",
Manufacturer: USB_DEFAULT_MANUFACTURER,
Product: USB_DEFAULT_PRODUCT,
Serial: USB_DEFAULT_SERIAL,
func DestroyAllGadgets() error {
//gadget_root := "./test"
gadget_root := USB_GADGET_DIR_BASE
//check if root exists, return error otherwise
if _, err := os.Stat(gadget_root); os.IsNotExist(err) {
return errors.New("Configfs path for gadget doesn't exist")
}
return ust
gadget_dirs, err := ioutil.ReadDir(gadget_root)
if err != nil {
return errors.New("No gadgets")
}
for _, gadget_dir_obj := range gadget_dirs {
gadget_name := gadget_dir_obj.Name()
log.Println("Found gadget: " + gadget_name)
err = DestroyGadget(gadget_name)
if err != nil {
log.Println(err) //don't return, continue with next
}
}
return nil
}
func DestroyGadget(Gadget_name string) error {
//gadget_root := "./test"
gadget_dir := USB_GADGET_DIR_BASE + "/" + Gadget_name
//check if root exists, return error otherwise
if _, err := os.Stat(USB_GADGET_DIR_BASE); os.IsNotExist(err) {
return errors.New("Gadget " + Gadget_name + " doesn't exist")
}
log.Println("Deconstructing gadget " + Gadget_name + "...")
//Assure gadget gets unbound from UDC
ioutil.WriteFile(gadget_dir+"/UDC", []byte("\x00"), os.ModePerm)
//Iterate over configurations
config_dirs, _ := ioutil.ReadDir(gadget_dir + "/configs")
for _, conf_dir_obj := range config_dirs {
conf_name := conf_dir_obj.Name()
conf_dir := gadget_dir + "/configs/" + conf_name
log.Println("Found config: " + conf_name)
//find linked functions
conf_content, _ := ioutil.ReadDir(conf_dir)
for _, function := range conf_content {
//Remove link from function to config
if function.Mode()&os.ModeSymlink > 0 {
log.Println("\tRemoving function " + function.Name() + " from config " + conf_name)
os.Remove(conf_dir + "/" + function.Name())
}
}
//find string directories in config
strings_content, _ := ioutil.ReadDir(conf_dir + "/strings")
for _, str := range strings_content {
string_dir := str.Name()
//Remove string from config
log.Println("\tRemoving string dir '" + string_dir + "' from configuration")
os.Remove(conf_dir + "/strings/" + string_dir)
}
//Check if there's an OS descriptor refering this config
if _, err := os.Stat(gadget_dir + "/os_desc/" + conf_name); !os.IsNotExist(err) {
log.Println("\tDeleting link to '" + conf_name + "' from gadgets OS descriptor")
os.Remove(gadget_dir + "/os_desc/" + conf_name)
}
// remove config folder, finally
log.Println("\tDeleting configuration '" + conf_name + "'")
os.Remove(conf_dir)
}
// remove functions
log.Println("Removing functions from '" + Gadget_name + "'")
os.RemoveAll(gadget_dir + "/functions/")
//find string directories in gadget
strings_content, _ := ioutil.ReadDir(gadget_dir + "/strings")
for _, str := range strings_content {
string_dir := str.Name()
//Remove string from config
log.Println("Removing string dir '" + string_dir + "' from " + Gadget_name)
os.Remove(gadget_dir + "/strings/" + string_dir)
}
//And now remove the gadget itself
log.Println("Removing gadget " + Gadget_name)
os.Remove(gadget_dir)
return nil
}

29
main.go
View File

@ -1,29 +0,0 @@
package main
import (
"fmt"
"./core"
)
func main() {
usb.DestroyAllGadgets()
usb_gadget := usb.New()
usb_gadget.Pid = "0x1234"
// usb_gadget.Use_RNDIS = true //2 EP
// usb_gadget.Use_CDC_ECM = true // 2 EP
// usb_gadget.Use_HID_KEYBOARD = true //1 EP
// usb_gadget.Use_HID_MOUSE = true // 1 EP
// usb_gadget.Use_HID_RAW = true //1 EP
usb_gadget.Use_SERIAL = true //2 EP
fmt.Printf("%+v\n", usb_gadget)
err := usb_gadget.CreateGadget()
if err != nil {
fmt.Print(err)
}
}

29
service.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"log"
"./core"
)
func main() {
var err error
err = core.CheckLibComposite()
if err != nil {
log.Fatalf("Couldn't load libcomposite: %v", err)
}
err = core.DestroyAllGadgets()
if err != nil {
log.Fatalf("Error while rolling back existing USB gadgets: %v", err)
}
err = core.InitDefaultGadgetSettings()
if err != nil {
log.Fatalf("Error while setting up the default gadget: %v", err)
}
core.InitLed(false) //Set LED to manual triger
//core.StartRpcServer("127.0.0.1", "50051") //start gRPC service
core.StartRpcServer("", "50051") //start gRPC service
}