When trying to communicate with the USB device using SCSI commands like INQUIRY and Test Unit Ready, I'm either not receiving any response or encountering errors. For instance, I've been receiving -1 from the bulkTransfer method, indicating a failure in communication. Notably, I haven't observed any explicit permission errors or other system logs that provide clear direction.
the code:
package com.example.myapplication
import android.app.PendingIntent
import android.content.BroadcastReceiver
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.UsbEndpoint
import android.hardware.usb.UsbManager
import android.os.Build
import android.os.Bundle
import android.widget.LinearLayout
import android.widget.ScrollView
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.core.view.setPadding
class MainActivity : ComponentActivity() {
private lateinit var usbManager: UsbManager
private val actionUsbPermission = "com.example.USB_PERMISSION"
private lateinit var logTextView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initializeUI()
usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
val permissionFilter = IntentFilter(actionUsbPermission)
registerReceiver(usbPermissionReceiver, permissionFilter)
discoverDevices()
}
private fun initializeUI() {
val layout = LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
setPadding(16)
}
val scrollView = ScrollView(this).apply {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT)
}
logTextView = TextView(this).apply {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
}
scrollView.addView(logTextView)
layout.addView(scrollView)
setContentView(layout)
}
private fun discoverDevices() {
val deviceList: HashMap<String, UsbDevice> = usbManager.deviceList
if (deviceList.isEmpty()) {
logMessage("No USB devices found.")
return
}
deviceList.values.forEach { device ->
logMessage("Device: ${device.deviceName}")
requestPermission(device)
}
}
private fun requestPermission(device: UsbDevice) {
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_MUTABLE
} else {
0
}
val permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(actionUsbPermission), flags)
usbManager.requestPermission(device, permissionIntent)
}
private val usbPermissionReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == actionUsbPermission) {
synchronized(this) {
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
device?.apply {
logMessage("Permission granted for device $deviceName")
performSimpleUmsCommunication(this)
}
} else {
logMessage("Permission denied for device ")
}
}
}
}
}
private fun performSimpleUmsCommunication(device: UsbDevice) {
try {
val connection: UsbDeviceConnection = usbManager.openDevice(device) ?: run {
logMessage("Unable to open connection to device.")
return
}
for (index in 0 until device.interfaceCount) {
val usbInterface = device.getInterface(index)
if (!connection.claimInterface(usbInterface, true)) {
logMessage("Unable to claim interface $index.")
continue
}
var epOut: UsbEndpoint? = null
var epIn: UsbEndpoint? = null
for (i in 0 until usbInterface.endpointCount) {
val ep = usbInterface.getEndpoint(i)
if (ep.direction == UsbConstants.USB_DIR_OUT && ep.type == UsbConstants.USB_ENDPOINT_XFER_BULK) {
epOut = ep
} else if (ep.direction == UsbConstants.USB_DIR_IN && ep.type == UsbConstants.USB_ENDPOINT_XFER_BULK) {
epIn = ep
}
}
if (epOut == null || epIn == null) {
logMessage("Cannot find IN/OUT endpoints for interface $index.")
continue
}
// Send SCSI Read Capacity (10) command
val readCapacityCommand = byteArrayOf(
0x1A, // MODE SENSE (6)
0x00, // Reserved
0x3F, // Page Code (0x3F for return all mode pages)
0x00, // Reserved
0x1C, // Allocation Length (set to 28 bytes)
0x00 // Control
)
val response = ByteArray(8) // Typical response size for Read Capacity
logMessage("Sending Read Capacity (10) command: ${bytesToHex(readCapacityCommand)}")
val commandResult = connection.bulkTransfer(epOut, readCapacityCommand, readCapacityCommand.size, 5000)
if (commandResult < 0) {
logMessage("Error sending Read Capacity (10) command: $commandResult")
continue
}
val received = connection.bulkTransfer(epIn, response, response.size, 5000)
if (received >= 0) {
logMessage("Received response: ${bytesToHex(response.copyOf(received))}")
} else {
logMessage("Error receiving response for Read Capacity (10) command: $received")
}
connection.releaseInterface(usbInterface)
}
connection.close()
} catch (e: Exception) {
logMessage("Exception during USB communication: ${e.message}")
}
}
// Helper function to convert byte array to a hexadecimal string
private fun bytesToHex(bytes: ByteArray): String {
val hexChars = "0123456789ABCDEF"
val result = StringBuilder(bytes.size * 2)
for (byte in bytes) {
val intVal = byte.toInt() and 0xff
result.append(hexChars[intVal ushr 4])
result.append(hexChars[intVal and 0x0f])
}
return result.toString()
}
private fun logMessage(message: String) {
runOnUiThread { logTextView.append(message + "\n") }
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(usbPermissionReceiver)
}
}
And the adb error:
2023-12-23 22:29:03.316 1517-2592 StorageManagerService system_server E
android.os.ServiceSpecificException: (code -5)
at android.os.Parcel.createExceptionOrNull(Parcel.java:3037)
at android.os.Parcel.createException(Parcel.java:3007)
at android.os.Parcel.readException(Parcel.java:2990)
at android.os.Parcel.readException(Parcel.java:2932)
at android.os.IVold$Stub$Proxy.mount(IVold.java:2205)
at com.android.server.StorageManagerService.mount(StorageManagerService.java:2819)
at com.android.server.StorageManagerService.-$$Nest$mmount(Unknown Source:0)
at com.android.server.StorageManagerService$StorageManagerServiceHandler.handleMessage(StorageManagerService.java:972)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.os.HandlerThread.run(HandlerThread.java:67)
usbui
2023-12-23 22:29:04.655 1517-2528 UsbUI system_server D onUEvent(Host Interface): {SUBSYSTEM=usb, SEQNUM=909705, ACTION=unbind, INTERFACE=8/6/80, DEVTYPE=usb_interface, PRODUCT=3337/301/f000, DEVPATH=/devices/platform/soc/a600000.ssusb/a600000.dwc3/xhci-hcd.8.auto/usb2/2-1/2-1:1.0, TYPE=0/0/0}
2023-12-23 22:29:04.656 1517-2528 UsbUI system_server D onUEvent(Host Interface): {SUBSYSTEM=usb, SEQNUM=909706, ACTION=bind, INTERFACE=8/6/80, DEVTYPE=usb_interface, PRODUCT=3337/301/f000, DRIVER=usbfs, MODALIAS=usb:v3337p0301dF000dc00dsc00dp00ic08isc06ip50in00, DEVPATH=/devices/platform/soc/a600000.ssusb/a600000.dwc3/xhci-hcd.8.auto/usb2/2-1/2-1:1.0, TYPE=0/0/0}
2023-12-23 22:29:04.656 1517-2528 UsbUI system_server D onUEvent(Host Interface): {SUBSYSTEM=usb, SEQNUM=909707, ACTION=unbind, INTERFACE=8/6/80, DEVTYPE=usb_interface, PRODUCT=3337/301/f000, DEVPATH=/devices/platform/soc/a600000.ssusb/a600000.dwc3/xhci-hcd.8.auto/usb2/2-1/2-1:1.0, TYPE=0/0/0}
I want the device to mount on Android (with Windows currently running), or to send SCSI commands, but I can't do either.
Many thanks for sharing your knowledge.
QAQ