usb_midi_device_android.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/midi/usb_midi_device_android.h"
  5. #include <stddef.h>
  6. #include "base/android/jni_array.h"
  7. #include "base/i18n/icu_string_conversions.h"
  8. #include "base/strings/stringprintf.h"
  9. #include "base/time/time.h"
  10. #include "media/midi/midi_jni_headers/UsbMidiDeviceAndroid_jni.h"
  11. #include "media/midi/usb_midi_descriptor_parser.h"
  12. using base::android::JavaParamRef;
  13. using base::android::ScopedJavaLocalRef;
  14. namespace midi {
  15. UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(
  16. const base::android::JavaRef<jobject>& raw_device,
  17. UsbMidiDeviceDelegate* delegate)
  18. : raw_device_(raw_device), delegate_(delegate) {
  19. JNIEnv* env = base::android::AttachCurrentThread();
  20. Java_UsbMidiDeviceAndroid_registerSelf(env, raw_device_,
  21. reinterpret_cast<jlong>(this));
  22. GetDescriptorsInternal();
  23. InitDeviceInfo();
  24. }
  25. UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() {
  26. JNIEnv* env = base::android::AttachCurrentThread();
  27. Java_UsbMidiDeviceAndroid_close(env, raw_device_);
  28. }
  29. std::vector<uint8_t> UsbMidiDeviceAndroid::GetDescriptors() {
  30. return descriptors_;
  31. }
  32. std::string UsbMidiDeviceAndroid::GetManufacturer() {
  33. return manufacturer_;
  34. }
  35. std::string UsbMidiDeviceAndroid::GetProductName() {
  36. return product_;
  37. }
  38. std::string UsbMidiDeviceAndroid::GetDeviceVersion() {
  39. return device_version_;
  40. }
  41. void UsbMidiDeviceAndroid::Send(int endpoint_number,
  42. const std::vector<uint8_t>& data) {
  43. JNIEnv* env = base::android::AttachCurrentThread();
  44. const uint8_t* head = data.size() ? &data[0] : NULL;
  45. ScopedJavaLocalRef<jbyteArray> data_to_pass =
  46. base::android::ToJavaByteArray(env, head, data.size());
  47. Java_UsbMidiDeviceAndroid_send(env, raw_device_, endpoint_number,
  48. data_to_pass);
  49. }
  50. void UsbMidiDeviceAndroid::OnData(JNIEnv* env,
  51. jint endpoint_number,
  52. const JavaParamRef<jbyteArray>& data) {
  53. std::vector<uint8_t> bytes;
  54. base::android::JavaByteArrayToByteVector(env, data, &bytes);
  55. const uint8_t* head = bytes.size() ? &bytes[0] : NULL;
  56. delegate_->ReceiveUsbMidiData(this, endpoint_number, head, bytes.size(),
  57. base::TimeTicks::Now());
  58. }
  59. void UsbMidiDeviceAndroid::GetDescriptorsInternal() {
  60. JNIEnv* env = base::android::AttachCurrentThread();
  61. base::android::ScopedJavaLocalRef<jbyteArray> descriptors =
  62. Java_UsbMidiDeviceAndroid_getDescriptors(env, raw_device_);
  63. base::android::JavaByteArrayToByteVector(env, descriptors, &descriptors_);
  64. }
  65. void UsbMidiDeviceAndroid::InitDeviceInfo() {
  66. UsbMidiDescriptorParser parser;
  67. UsbMidiDescriptorParser::DeviceInfo info;
  68. const uint8_t* data = descriptors_.size() > 0 ? &descriptors_[0] : nullptr;
  69. if (!parser.ParseDeviceInfo(data, descriptors_.size(), &info)) {
  70. // We don't report the error here. If it is critical, we will realize it
  71. // when we parse the descriptors again for ports.
  72. manufacturer_ = "invalid descriptor";
  73. product_ = "invalid descriptor";
  74. device_version_ = "invalid descriptor";
  75. return;
  76. }
  77. manufacturer_ =
  78. GetString(info.manufacturer_index,
  79. base::StringPrintf("(vendor id = 0x%04x)", info.vendor_id));
  80. product_ =
  81. GetString(info.product_index,
  82. base::StringPrintf("(product id = 0x%04x)", info.product_id));
  83. device_version_ = info.BcdVersionToString(info.bcd_device_version);
  84. }
  85. std::vector<uint8_t> UsbMidiDeviceAndroid::GetStringDescriptor(int index) {
  86. JNIEnv* env = base::android::AttachCurrentThread();
  87. base::android::ScopedJavaLocalRef<jbyteArray> descriptors =
  88. Java_UsbMidiDeviceAndroid_getStringDescriptor(env, raw_device_, index);
  89. std::vector<uint8_t> ret;
  90. base::android::JavaByteArrayToByteVector(env, descriptors, &ret);
  91. return ret;
  92. }
  93. std::string UsbMidiDeviceAndroid::GetString(int index,
  94. const std::string& backup) {
  95. const uint8_t DESCRIPTOR_TYPE_STRING = 3;
  96. if (!index) {
  97. // index 0 means there is no such descriptor.
  98. return backup;
  99. }
  100. std::vector<uint8_t> descriptor = GetStringDescriptor(index);
  101. if (descriptor.size() < 2 || descriptor.size() < descriptor[0] ||
  102. descriptor[1] != DESCRIPTOR_TYPE_STRING) {
  103. // |descriptor| is not a valid string descriptor.
  104. return backup;
  105. }
  106. size_t size = descriptor[0];
  107. std::string encoded(reinterpret_cast<char*>(&descriptor[0]) + 2, size - 2);
  108. std::string result;
  109. // Unicode ECN specifies that the string is encoded in UTF-16LE.
  110. if (!base::ConvertToUtf8AndNormalize(encoded, "utf-16le", &result))
  111. return backup;
  112. return result;
  113. }
  114. } // namespace midi