@@ -30,52 +30,46 @@ public Parameters(String manufacturer, String serial,
3030 }
3131 }
3232
33- public static final String CONFIG_DIR = "c.1" ;
33+ private static final String CONFIG_DIR = "c.1" ;
34+ // https://android.googlesource.com/platform/system/core/+/master/rootdir/init.usb.configfs.rc
35+ private static final String SYSTEM_GADGET = "g1" ;
3436
35- private final Parameters params_ ;
36- private final String name_ ;
37+ private final String gadget_name_ ;
3738 private final String configFsPath_ ;
3839
3940 private final ArrayList <UsbGadgetFunction > functions_ ;
4041
41- private String oldGadgetUsingUDC_ = null ;
42- private String oldGadgetUDCDriver_ = null ;
43-
44- public UsbGadget (Parameters parameters , String name , String configFsPath ) {
45- this .params_ = parameters ;
46- this .name_ = name ;
42+ public UsbGadget (String name , String configFsPath ) {
43+ this .gadget_name_ = name ;
4744 this .configFsPath_ = configFsPath ;
4845
4946 this .functions_ = new ArrayList <>();
5047 }
5148
52- public void addFunction (UsbGadgetFunction function ) {
53- functions_ .add (function );
54- }
55-
56- public void create (Shell .Threaded su ) throws Shell .ShellDiedException {
57- String gadgetPath = getGadgetPath ();
58- if (Command .pathExists (su , gadgetPath )) {
49+ public void create (Shell .Threaded su , Parameters params ) throws Shell .ShellDiedException {
50+ String gadgetPath = getGadgetPath (gadget_name_ );
51+ if (!Command .getSystemProp (su , "sys.usb.configfs" ).equals ("1" ))
52+ throw new IllegalStateException ("Device does not support ConfigFS" );
53+ if (isCreated (su ))
5954 throw new IllegalStateException ("USB gadget already exists" );
60- }
6155
6256 su .run (new String []{
6357 "mkdir " + gadgetPath ,
6458 "cd " + gadgetPath ,
65- Command .echoToFile (params_ .idProduct , "idProduct" ),
66- Command .echoToFile (params_ .idVendor , "idVendor" ),
59+ Command .echoToFile (params .idProduct , "idProduct" ),
60+ Command .echoToFile (params .idVendor , "idVendor" ),
6761 Command .echoToFile ("239" , "bDeviceClass" ),
6862 Command .echoToFile ("0x02" , "bDeviceSubClass" ),
6963 Command .echoToFile ("0x01" , "bDeviceProtocol" ),
7064
7165 "mkdir strings/0x409" ,
72- Command .echoToFile (params_ .serial , "strings/0x409/serialnumber" ),
73- Command .echoToFile (params_ .manufacturer , "strings/0x409/manufacturer" ),
74- Command .echoToFile (params_ .product , "strings/0x409/product" ),
66+ Command .echoToFile (params .serial , "strings/0x409/serialnumber" ),
67+ Command .echoToFile (params .manufacturer , "strings/0x409/manufacturer" ),
68+ Command .echoToFile (params .product , "strings/0x409/product" ),
7569
7670 String .format ("mkdir \" configs/%s\" " , CONFIG_DIR ),
7771 String .format ("mkdir \" configs/%s/strings/0x409\" " , CONFIG_DIR ),
78- Command .echoToFile (params_ .configName , String .format ("configs/%s/strings/0x409/configuration" , CONFIG_DIR )),
72+ Command .echoToFile (params .configName , String .format ("configs/%s/strings/0x409/configuration" , CONFIG_DIR )),
7973 });
8074
8175 for (UsbGadgetFunction function : this .functions_ ) {
@@ -84,62 +78,42 @@ public void create(Shell.Threaded su) throws Shell.ShellDiedException {
8478 }
8579
8680 public void bind (Shell .Threaded su ) throws Shell .ShellDiedException {
87- String gadgetPath = getGadgetPath ();
88- if (isBound (su )) {
81+ String gadgetPath = getGadgetPath (gadget_name_ );
82+ if (!isCreated (su ))
83+ throw new IllegalStateException ("USB gadget does not exist" );
84+ if (isBound (su ))
8985 throw new IllegalStateException ("USB gadget is already bound to UDC" );
90- }
9186
9287 for (UsbGadgetFunction function : this .functions_ ) {
9388 function .bind (su , gadgetPath , CONFIG_DIR );
9489 }
9590
96- ArrayList <String > drivers = Command .ls (su , "/sys/class/udc" );
97- if (drivers .size () != 1 ) {
98- // TODO allow multiple USB drivers
99- throw new IllegalStateException ("There must be exactly one USB driver" );
100- }
101- String udc = drivers .get (0 );
102- this .oldGadgetUDCDriver_ = udc ;
103-
104- // Look for other gadgets using the same usb driver
105- ArrayList <String > otherUsbGadgets = Command .ls (su , Paths .get (gadgetPath , ".." ).toString ());
106- for (String otherUsbGadgetPath : otherUsbGadgets ) {
107- String udcPath = Paths .get (gadgetPath , ".." , otherUsbGadgetPath , "UDC" ).toString ();
108- String driver = Command .readFile (su , udcPath );
109- if (driver .equals (udc )) {
110- // Backup the driver so we can restore it later
111- this .oldGadgetUsingUDC_ = udcPath ;
112- su .run (Command .echoToFile ("" , udcPath ));
113- break ;
114- }
115- }
91+ String udc = getSystemUDC (su );
92+ if (udc .isEmpty ()) throw new IllegalStateException ("Could not determine system UDC" );
11693
117- su .run (Command .echoToFile (udc , Paths .get (gadgetPath , "UDC" ).toString ()));
94+ su .run (Command .echoToFile ("" , getUDCPath (SYSTEM_GADGET )));
95+ su .run (Command .echoToFile (udc , getUDCPath (gadget_name_ )));
11896 }
11997
12098 public void unbind (Shell .Threaded su ) throws Shell .ShellDiedException {
121- if (!isBound (su )) {
99+ if (!isCreated (su ))
100+ throw new IllegalStateException ("USB gadget does not exist" );
101+ if (!isBound (su ))
122102 throw new IllegalStateException ("USB gadget is not bound to UDC" );
123- }
124103
125- // Disable gadget
126- su .run (Command .echoToFile ("" , getUDCPath ()));
127- // Restore old driver if we need to
128- if (oldGadgetUsingUDC_ != null ) {
129- su .run (Command .echoToFile (oldGadgetUDCDriver_ , oldGadgetUsingUDC_ ));
130- }
104+ su .run (Command .echoToFile ("" , getUDCPath (gadget_name_ )));
105+ su .run (Command .echoToFile (getSystemUDC (su ), SYSTEM_GADGET ));
131106
132- String gadgetPath = getGadgetPath ();
107+ String gadgetPath = getGadgetPath (gadget_name_ );
133108 for (UsbGadgetFunction function : this .functions_ ) {
134109 function .unbind (su , gadgetPath , CONFIG_DIR );
135110 }
136111 }
137112
138113 public void remove (Shell .Threaded su ) throws Shell .ShellDiedException {
139- String gadgetPath = getGadgetPath ();
140- if (!Command . pathExists (su , gadgetPath )) {
114+ String gadgetPath = getGadgetPath (gadget_name_ );
115+ if (!isCreated (su ))
141116 throw new IllegalStateException ("USB gadget does not exist" );
142- }
143117
144118 for (UsbGadgetFunction function : this .functions_ ) {
145119 function .remove (su , gadgetPath );
@@ -150,28 +124,52 @@ public void remove(Shell.Threaded su) throws Shell.ShellDiedException {
150124 String .format ("rmdir \" configs/%s\" " , CONFIG_DIR ),
151125 "rmdir strings/0x409" ,
152126 "cd .." ,
153- String .format ("rmdir \" %s\" " , this .name_ )
127+ String .format ("rmdir \" %s\" " , this .gadget_name_ )
154128 });
155129 }
156130
157- public String getGadgetPath () {
158- return String .format ("%s/usb_gadget/%s" , configFsPath_ , name_ );
131+ public String getGadgetPath (String gadgetName ) {
132+ return String .format ("%s/usb_gadget/%s" , configFsPath_ , gadgetName );
159133 }
160134
161- public String getUDCPath () {
162- return Paths .get (getGadgetPath (), "UDC" ).toString ();
135+ public String getUDCPath (String gadgetName ) {
136+ return Paths .get (getGadgetPath (gadgetName ), "UDC" ).toString ();
163137 }
164138
165- public String getUDC (Shell .Threaded su ) {
166- return Command .readFile (su , getUDCPath ());
139+ public String getActiveUDC (Shell .Threaded su , String gadgetName ) throws Shell . ShellDiedException {
140+ return Command .readFile (su , getUDCPath (gadgetName ));
167141 }
168142
169- public String getUDCState (Shell .Threaded su , String udc ) {
170- return Command .readFile (su , String . format ( "/sys/class/udc/%s/state" , udc ));
143+ public boolean isCreated (Shell .Threaded su ) throws Shell . ShellDiedException {
144+ return Command .pathExists (su , getGadgetPath ( gadget_name_ ));
171145 }
172146
173- public boolean isBound (Shell .Threaded su ) {
174- return !getUDC (su ).isEmpty ();
147+ public boolean isBound (Shell .Threaded su ) throws Shell .ShellDiedException {
148+ return !getActiveUDC (su , gadget_name_ ).isEmpty ();
149+ }
150+
151+ public void addFunction (UsbGadgetFunction function ) {
152+ functions_ .add (function );
153+ }
154+
155+ public ArrayList <UsbGadgetFunction > getFunctions () {
156+ return functions_ ;
157+ }
158+
159+ public String serial () {
160+ ArrayList <String > functionDir = new ArrayList <>();
161+ for (UsbGadgetFunction function : getFunctions ()) {
162+ functionDir .add (function .getFunctionDir ());
163+ }
164+ return String .format ("%x" , functionDir .hashCode ());
165+ }
166+
167+ public static String getSystemUDC (Shell .Threaded su ) throws Shell .ShellDiedException {
168+ return Command .getSystemProp (su , "sys.usb.controller" );
169+ }
170+
171+ public static String getUDCState (Shell .Threaded su , String udc ) throws Shell .ShellDiedException {
172+ return Command .readFile (su , String .format ("/sys/class/udc/%s/state" , udc ));
175173 }
176174
177175}
0 commit comments