diff --git a/P4wnP1_client_cli/cli_client.go b/P4wnP1_client_cli/cli_client.go index b12d93b..9f2258b 100644 --- a/P4wnP1_client_cli/cli_client.go +++ b/P4wnP1_client_cli/cli_client.go @@ -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}) + */ } diff --git a/core/led.go b/core/led.go index c22430e..006cfab 100644 --- a/core/led.go +++ b/core/led.go @@ -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) -} diff --git a/P4wnP1_service/service.go b/core/rpcsrv.go similarity index 64% rename from P4wnP1_service/service.go rename to core/rpcsrv.go index 91f0923..caf2897 100644 --- a/P4wnP1_service/service.go +++ b/core/rpcsrv.go @@ -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") -} diff --git a/core/usb.go b/core/usb.go index e1879aa..c540e43 100644 --- a/core/usb.go +++ b/core/usb.go @@ -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 +} diff --git a/main.go b/main.go deleted file mode 100644 index aadbbf8..0000000 --- a/main.go +++ /dev/null @@ -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) - } - -} diff --git a/service.go b/service.go new file mode 100644 index 0000000..5f54fc1 --- /dev/null +++ b/service.go @@ -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 +}