下面列出了android.hardware.usb.UsbDeviceConnection#controlTransfer ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Request the active configuration descriptor through the USB device connection.
*/
public static ConfigurationDescriptor fromDeviceConnection(UsbDeviceConnection connection)
throws IllegalArgumentException, ParseException {
//Create a sufficiently large buffer for incoming data
byte[] buffer = new byte[LENGTH];
connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX,
buffer, LENGTH, TIMEOUT);
//Do a short read to determine descriptor length
int totalLength = headerLengthCheck(buffer);
//Obtain the full descriptor
buffer = new byte[totalLength];
connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX,
buffer, totalLength, TIMEOUT);
return parseResponse(buffer);
}
/**
* 指定したIDのStringディスクリプタから文字列を取得する。取得できなければnull
* @param connection
* @param id
* @param languageCount
* @param languages
* @return
*/
private static String getString(final UsbDeviceConnection connection, final int id, final int languageCount, final byte[] languages) {
final byte[] work = new byte[256];
String result = null;
for (int i = 1; i <= languageCount; i++) {
int ret = connection.controlTransfer(
USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) | id, languages[i], work, 256, 0);
if ((ret > 2) && (work[0] == ret) && (work[1] == USB_DT_STRING)) {
// skip first two bytes(bLength & bDescriptorType), and copy the rest to the string
try {
result = new String(work, 2, ret - 2, "UTF-16LE");
if (!"Љ".equals(result)) { // 変なゴミが返ってくる時がある
break;
} else {
result = null;
}
} catch (final UnsupportedEncodingException e) {
// ignore
}
}
}
return result;
}
/**
* 指定したIDのStringディスクリプタから文字列を取得する。取得できなければnull
* @param connection
* @param id
* @param languageCount
* @param languages
* @return
*/
public static String getString(@NonNull final UsbDeviceConnection connection,
final int id, final int languageCount, final byte[] languages) {
final byte[] work = new byte[256];
String result = null;
for (int i = 1; i <= languageCount; i++) {
int ret = connection.controlTransfer(
USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) | id, languages[i], work, 256, 0);
if ((ret > 2) && (work[0] == ret) && (work[1] == USB_DT_STRING)) {
// skip first two bytes(bLength & bDescriptorType), and copy the rest to the string
result = new String(work, 2, ret - 2, CharsetsUtils.UTF16LE/*"UTF-16LE"*/);
if (!"Љ".equals(result)) { // 変なゴミが返ってくる時がある
break;
} else {
result = null;
}
}
}
return result;
}
/**
* 指定したIDのStringディスクリプタから文字列を取得する。取得できなければnull
* @param connection
* @param id
* @param languageCount
* @param languages
* @return
*/
private static String getString(final UsbDeviceConnection connection, final int id, final int languageCount, final byte[] languages) {
final byte[] work = new byte[256];
String result = null;
for (int i = 1; i <= languageCount; i++) {
int ret = connection.controlTransfer(
USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) | id, languages[i], work, 256, 0);
if ((ret > 2) && (work[0] == ret) && (work[1] == USB_DT_STRING)) {
// skip first two bytes(bLength & bDescriptorType), and copy the rest to the string
try {
result = new String(work, 2, ret - 2, "UTF-16LE");
if (!"Љ".equals(result)) { // 変なゴミが返ってくる時がある
break;
} else {
result = null;
}
} catch (final UnsupportedEncodingException e) {
// ignore
}
}
}
return result;
}
public static int doControlTransfer(UsbDeviceConnection devConn, int requestType,
int request, int value, int index, byte[] buff, int length, int interval) {
// Mask out possible sign expansions
requestType &= 0xFF;
request &= 0xFF;
value &= 0xFFFF;
index &= 0xFFFF;
length &= 0xFFFF;
System.out.printf("SETUP: %x %x %x %x %x\n",
requestType, request, value, index, length);
int res = devConn.controlTransfer(requestType, request, value,
index, buff, length, interval);
if (res < 0) {
res = -Errno.getErrno();
if (res != -110) {
// Don't print for ETIMEDOUT
System.err.println("Control Xfer failed: "+res);
}
}
return res;
}
/**
* Request the device descriptor through the USB device connection.
*/
public static DeviceDescriptor fromDeviceConnection(UsbDeviceConnection connection)
throws IllegalArgumentException {
byte[] buffer = new byte[LENGTH];
connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX,
buffer, LENGTH, TIMEOUT);
return parseResponse(buffer);
}
/**
* ベンダー名・製品名・バージョン・シリアルを取得する
* @param manager
* @param device
* @param _info
* @return
*/
@TargetApi(Build.VERSION_CODES.M)
public static UsbDeviceInfo updateDeviceInfo(final UsbManager manager, final UsbDevice device, final UsbDeviceInfo _info) {
final UsbDeviceInfo info = _info != null ? _info : new UsbDeviceInfo();
info.clear();
if (device != null) {
if (BuildCheck.isLollipop()) {
info.manufacturer = device.getManufacturerName();
info.product = device.getProductName();
info.serial = device.getSerialNumber();
}
if (BuildCheck.isMarshmallow()) {
info.usb_version = device.getVersion();
}
if ((manager != null) && manager.hasPermission(device)) {
final UsbDeviceConnection connection = manager.openDevice(device);
if(connection == null) {
return null;
}
final byte[] desc = connection.getRawDescriptors();
if (TextUtils.isEmpty(info.usb_version)) {
info.usb_version = String.format("%x.%02x", ((int)desc[3] & 0xff), ((int)desc[2] & 0xff));
}
if (TextUtils.isEmpty(info.version)) {
info.version = String.format("%x.%02x", ((int)desc[13] & 0xff), ((int)desc[12] & 0xff));
}
if (TextUtils.isEmpty(info.serial)) {
info.serial = connection.getSerial();
}
final byte[] languages = new byte[256];
int languageCount = 0;
// controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
try {
int result = connection.controlTransfer(
USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) | 0, 0, languages, 256, 0);
if (result > 0) {
languageCount = (result - 2) / 2;
}
if (languageCount > 0) {
if (TextUtils.isEmpty(info.manufacturer)) {
info.manufacturer = getString(connection, desc[14], languageCount, languages);
}
if (TextUtils.isEmpty(info.product)) {
info.product = getString(connection, desc[15], languageCount, languages);
}
if (TextUtils.isEmpty(info.serial)) {
info.serial = getString(connection, desc[16], languageCount, languages);
}
}
} finally {
connection.close();
}
}
if (TextUtils.isEmpty(info.manufacturer)) {
info.manufacturer = USBVendorId.vendorName(device.getVendorId());
}
if (TextUtils.isEmpty(info.manufacturer)) {
info.manufacturer = String.format("%04x", device.getVendorId());
}
if (TextUtils.isEmpty(info.product)) {
info.product = String.format("%04x", device.getProductId());
}
}
return info;
}
/**
* USB機器情報(ベンダー名・製品名・バージョン・シリアル等)を取得する
* @param connection
* @param device
* @param out
* @return
*/
@SuppressLint("NewApi")
public static UsbDeviceInfo getDeviceInfo(
@Nullable final UsbDeviceConnection connection,
@Nullable final UsbDevice device, @Nullable final UsbDeviceInfo out) {
final UsbDeviceInfo result = out != null ? out : new UsbDeviceInfo();
result.clear();
result.device = device;
if (device != null) {
if (BuildCheck.isAPI29() && (connection != null)) {
// API>=29でターゲットAPI>=29ならパーミッションがないとシリアル番号を読み込めない
// connectionがnullでないならopenできているのでパーミッションがある
result.manufacturer = device.getManufacturerName();
result.product = device.getProductName();
result.configCounts = device.getConfigurationCount();
} else if (BuildCheck.isLollipop()) { // API >= 21
result.manufacturer = device.getManufacturerName();
result.product = device.getProductName();
result.serial = device.getSerialNumber();
result.configCounts = device.getConfigurationCount();
}
if (BuildCheck.isMarshmallow()) { // API >= 23
result.version = device.getVersion();
}
if (connection != null) {
final byte[] desc = connection.getRawDescriptors();
if (desc != null) {
if (TextUtils.isEmpty(result.usb_version)) {
result.usb_version = String.format("%x.%02x", ((int)desc[3] & 0xff), ((int)desc[2] & 0xff));
}
if (TextUtils.isEmpty(result.version)) {
result.version = String.format("%x.%02x", ((int)desc[13] & 0xff), ((int)desc[12] & 0xff));
}
if (BuildCheck.isAPI29()) { // API >= 29
// API>=29でターゲットAPI>=29ならパーミッションがないとシリアル番号を読み込めない
result.serial = device.getSerialNumber();
}
if (TextUtils.isEmpty(result.serial)) {
result.serial = connection.getSerial();
}
if (result.configCounts < 0) {
// FIXME 未実装 デバイスディスクリプタをパースせんとなりゃん
result.configCounts = 1;
}
final byte[] languages = new byte[256];
int languageCount = 0;
// controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
int res = connection.controlTransfer(
USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8)/* | 0*/, 0, languages, 256, 0);
if (res > 0) {
languageCount = (res - 2) / 2;
}
if (languageCount > 0) {
if (TextUtils.isEmpty(result.manufacturer)) {
result.manufacturer = UsbUtils.getString(connection, desc[14], languageCount, languages);
}
if (TextUtils.isEmpty(result.product)) {
result.product = UsbUtils.getString(connection, desc[15], languageCount, languages);
}
if (TextUtils.isEmpty(result.serial)) {
result.serial = UsbUtils.getString(connection, desc[16], languageCount, languages);
}
}
}
}
if (TextUtils.isEmpty(result.manufacturer)) {
result.manufacturer = USBVendorId.vendorName(device.getVendorId());
}
if (TextUtils.isEmpty(result.manufacturer)) {
result.manufacturer = String.format("%04x", device.getVendorId());
}
if (TextUtils.isEmpty(result.product)) {
result.product = String.format("%04x", device.getProductId());
}
}
return result;
}
/**
* ベンダー名・製品名・バージョン・シリアルを取得する
* @param manager
* @param device
* @param _info
* @return
*/
public static UsbDeviceInfo updateDeviceInfo(final UsbManager manager, final UsbDevice device, final UsbDeviceInfo _info) {
final UsbDeviceInfo info = _info != null ? _info : new UsbDeviceInfo();
info.clear();
if (device != null) {
if (BuildCheck.isLollipop()) {
info.manufacturer = device.getManufacturerName();
info.product = device.getProductName();
info.serial = device.getSerialNumber();
}
if (BuildCheck.isMarshmallow()) {
info.usb_version = device.getVersion();
}
if ((manager != null) && manager.hasPermission(device)) {
final UsbDeviceConnection connection = manager.openDevice(device);
final byte[] desc = connection.getRawDescriptors();
if (TextUtils.isEmpty(info.usb_version)) {
info.usb_version = String.format("%x.%02x", ((int)desc[3] & 0xff), ((int)desc[2] & 0xff));
}
if (TextUtils.isEmpty(info.version)) {
info.version = String.format("%x.%02x", ((int)desc[13] & 0xff), ((int)desc[12] & 0xff));
}
if (TextUtils.isEmpty(info.serial)) {
info.serial = connection.getSerial();
}
final byte[] languages = new byte[256];
int languageCount = 0;
// controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
try {
int result = connection.controlTransfer(
USB_REQ_STANDARD_DEVICE_GET, // USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) | 0, 0, languages, 256, 0);
if (result > 0) {
languageCount = (result - 2) / 2;
}
if (languageCount > 0) {
if (TextUtils.isEmpty(info.manufacturer)) {
info.manufacturer = getString(connection, desc[14], languageCount, languages);
}
if (TextUtils.isEmpty(info.product)) {
info.product = getString(connection, desc[15], languageCount, languages);
}
if (TextUtils.isEmpty(info.serial)) {
info.serial = getString(connection, desc[16], languageCount, languages);
}
}
} finally {
connection.close();
}
}
if (TextUtils.isEmpty(info.manufacturer)) {
info.manufacturer = USBVendorId.vendorName(device.getVendorId());
}
if (TextUtils.isEmpty(info.manufacturer)) {
info.manufacturer = String.format("%04x", device.getVendorId());
}
if (TextUtils.isEmpty(info.product)) {
info.product = String.format("%04x", device.getProductId());
}
}
return info;
}