这是indexloc提供的服务,不要输入任何密码
Skip to content
Closed

Usb #606

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 99 additions & 26 deletions app/src/main/java/com/termux/api/apis/UsbAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Looper;
import android.util.JsonWriter;
import android.util.Log;
import android.util.SparseArray;

import com.termux.api.TermuxApiReceiver;
Expand Down Expand Up @@ -47,58 +49,130 @@ public void writeJson(JsonWriter out) throws Exception {
}
});
break;
case "open":
device = getDevice(apiReceiver, context, intent);
if (device == null) return;
ResultReturner.returnData(apiReceiver, intent, new ResultReturner.WithAncillaryFd() {
@Override
public void writeResult(PrintWriter out) {
if (getPermission(device, context, intent)) {
int result = open(device, context);
if (result < 0) {
out.append("Failed to open device\n");
} else {
this.setFd(result);
out.append("@"); // has to be non-empty
}
} else out.append("No permission\n");
}
});
break;
case "permission":
device = getDevice(apiReceiver, context, intent);
if (device == null) return;
ResultReturner.returnData(apiReceiver, intent, out -> {
boolean result = getPermission(device, context, intent);
out.append(result ? "yes\n" : "no\n");
});
break;
case "open":
device = getDevice(apiReceiver, context, intent);
if (device == null) return;
ResultReturner.returnData(apiReceiver, intent, new ResultReturner.WithAncillaryFd() {
@Override
public void writeResult(PrintWriter out) {
if (getPermission(device, context, intent)) {
int result = open(device, context);
if (result < 0) {
out.append("Failed to open device\n");
} else {
this.setFd(result);
out.append("@"); // has to be non-empty
}
} else out.append("No permission\n");
}
});

break;
default:
ResultReturner.returnData(apiReceiver, intent, out -> out.append("Invalid action\n"));
}
}

}

private static void listDevices(final Context context, JsonWriter out) throws IOException {
final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
Iterator<String> deviceIterator = deviceList.keySet().iterator();
out.beginArray();
while (deviceIterator.hasNext()) {
out.value(deviceIterator.next());
for (UsbDevice device : deviceList.values()) {
out.beginObject();
out.name("device_name").value(device.getDeviceName());
out.name("device_id").value(device.getDeviceId());
out.name("vendor_id").value(String.format("0x%04x", device.getVendorId()));
out.name("product_id").value(String.format("0x%04x", device.getProductId()));
out.name("device_class").value(device.getDeviceClass()+" - "+translateDeviceClass(device.getDeviceClass()));
out.name("device_sub_class").value(device.getDeviceSubclass());
out.name("manufacturer_name").value(device.getManufacturerName().replace("\u0000", ""));
out.name("device_protocol").value(device.getDeviceProtocol());
out.name("product_name").value(device.getProductName().replace("\u0000", ""));
out.name("serial_number").value(device.getSerialNumber());
out.name("configurations").value(device.getConfigurationCount());
out.name("descriptor_type").value(device.describeContents());
out.name("access_granted").value(usbManager.hasPermission(device));
out.endObject();
}
out.endArray();
}
private static String translateDeviceClass(int usbClass){
switch(usbClass){
case UsbConstants.USB_CLASS_APP_SPEC:
return "App specific USB class";
case UsbConstants.USB_CLASS_AUDIO:
return "Audio device";
case UsbConstants.USB_CLASS_CDC_DATA:
return "CDC device (communications device class)";
case UsbConstants.USB_CLASS_COMM:
return "Communication device";
case UsbConstants.USB_CLASS_CONTENT_SEC:
return "Content security device";
case UsbConstants.USB_CLASS_CSCID:
return "Content smart card device";
case UsbConstants.USB_CLASS_HID:
return "Human interface device (for example a keyboard)";
case UsbConstants.USB_CLASS_HUB:
return "USB hub";
case UsbConstants.USB_CLASS_MASS_STORAGE:
return "Mass storage device";
case UsbConstants.USB_CLASS_MISC:
return "Wireless miscellaneous devices";
case UsbConstants.USB_CLASS_PER_INTERFACE:
return "Usb class is determined on a per-interface basis";
case UsbConstants.USB_CLASS_PHYSICA:
return "Physical device";
case UsbConstants.USB_CLASS_PRINTER:
return "Printer";
case UsbConstants.USB_CLASS_STILL_IMAGE:
return "Still image devices (digital cameras)";
case UsbConstants.USB_CLASS_VENDOR_SPEC:
return "Vendor specific USB class";
case UsbConstants.USB_CLASS_VIDEO:
return "Video device";
case UsbConstants.USB_CLASS_WIRELESS_CONTROLLER:
return "Wireless controller device";
default: return "Unknown USB class!";
}
}

private static UsbDevice getDevice(final TermuxApiReceiver apiReceiver, final Context context, final Intent intent) {
String deviceName = intent.getStringExtra("device");
String vendorId = intent.getStringExtra("vendorId");
String productId = intent.getStringExtra("productId");
if (deviceName == null && (vendorId == null || productId == null)) {
Log.e(LOG_TAG, "Missing usb device info in open()");
ResultReturner.returnData(apiReceiver, intent, out -> out.append("Need either usbfs path or vendorId+productId\n"));
return null;
}

final UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
UsbDevice device = deviceList.get(deviceName);
UsbDevice device = null;
if (deviceName != null) {
device = deviceList.get(deviceName);
} else {
for (UsbDevice dev : deviceList.values()) {
Log.d(LOG_TAG, "Comparing "+dev.getDeviceName()+" with given vendorId and productId");
if (String.format("0x%04x", dev.getVendorId()).equalsIgnoreCase(vendorId) &&
String.format("0x%04x", dev.getProductId()).equalsIgnoreCase(productId)) {
device = dev;
break;
}
}
}
if (device == null) {
ResultReturner.returnData(apiReceiver, intent, out -> out.append("No such device\n"));
} else {
Log.i(LOG_TAG, "Found matching device at "+device.getDeviceName());
}
return device;
}
Expand Down Expand Up @@ -131,7 +205,6 @@ public void onReceive(final Context usbContext, final Intent usbIntent) {
if (looper != null) looper.quit();
}
}

}
}
};
Expand All @@ -148,7 +221,7 @@ public void onReceive(final Context usbContext, final Intent usbIntent) {

private static boolean getPermission(final @NonNull UsbDevice device, final Context context, final Intent intent) {
boolean request = intent.getBooleanExtra("request", false);
if(request) {
if (request) {
return requestPermission(device, context);
} else {
return hasPermission(device, context);
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/com/termux/api/util/ResultReturner.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ public void setInput(InputStream inputStream) throws Exception {
this.in = inputStream;
}
}

/**
* Possible subclass of {@link ResultWriter} when the output is binary data instead of text.
*/
public static abstract class BinaryOutput implements ResultWriter {
private OutputStream out;

public void setOutput(OutputStream outputStream) {
this.out = outputStream;
}

public abstract void writeResult(OutputStream out) throws Exception;

/**
* writeResult with a PrintWriter is marked as final and overwritten, so you don't accidentally use it
*/
Expand Down Expand Up @@ -178,7 +178,7 @@ public static void returnData(Object context, final Intent intent, final ResultW
} else {
resultWriter.writeResult(writer);
}
if(resultWriter instanceof WithAncillaryFd) {
if (resultWriter instanceof WithAncillaryFd) {
int fd = ((WithAncillaryFd) resultWriter).getFd();
if (fd >= 0) {
pfds[0] = ParcelFileDescriptor.adoptFd(fd);
Expand All @@ -188,7 +188,7 @@ public static void returnData(Object context, final Intent intent, final ResultW
}
}

if(pfds[0] != null) {
if (pfds[0] != null) {
pfds[0].close();
}

Expand Down