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.
5 #include "media/midi/usb_midi_device_android.h"
10 #include "base/android/jni_array.h"
11 #include "base/i18n/icu_string_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
14 #include "jni/UsbMidiDeviceAndroid_jni.h"
15 #include "media/midi/usb_midi_descriptor_parser.h"
19 UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(ObjectRef raw_device
,
20 UsbMidiDeviceDelegate
* delegate
)
21 : raw_device_(raw_device
), delegate_(delegate
) {
22 JNIEnv
* env
= base::android::AttachCurrentThread();
23 Java_UsbMidiDeviceAndroid_registerSelf(
24 env
, raw_device_
.obj(), reinterpret_cast<jlong
>(this));
26 GetDescriptorsInternal();
30 UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() {
31 JNIEnv
* env
= base::android::AttachCurrentThread();
32 Java_UsbMidiDeviceAndroid_close(env
, raw_device_
.obj());
35 std::vector
<uint8
> UsbMidiDeviceAndroid::GetDescriptors() {
39 std::string
UsbMidiDeviceAndroid::GetManufacturer() {
43 std::string
UsbMidiDeviceAndroid::GetProductName() {
47 std::string
UsbMidiDeviceAndroid::GetDeviceVersion() {
48 return device_version_
;
51 void UsbMidiDeviceAndroid::Send(int endpoint_number
,
52 const std::vector
<uint8
>& data
) {
53 JNIEnv
* env
= base::android::AttachCurrentThread();
54 const uint8
* head
= data
.size() ? &data
[0] : NULL
;
55 ScopedJavaLocalRef
<jbyteArray
> data_to_pass
=
56 base::android::ToJavaByteArray(env
, head
, data
.size());
58 Java_UsbMidiDeviceAndroid_send(
59 env
, raw_device_
.obj(), endpoint_number
, data_to_pass
.obj());
62 void UsbMidiDeviceAndroid::OnData(JNIEnv
* env
,
66 std::vector
<uint8
> bytes
;
67 base::android::JavaByteArrayToByteVector(env
, data
, &bytes
);
69 const uint8
* head
= bytes
.size() ? &bytes
[0] : NULL
;
70 delegate_
->ReceiveUsbMidiData(this, endpoint_number
, head
, bytes
.size(),
71 base::TimeTicks::Now());
74 bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv
* env
) {
75 return RegisterNativesImpl(env
);
78 void UsbMidiDeviceAndroid::GetDescriptorsInternal() {
79 JNIEnv
* env
= base::android::AttachCurrentThread();
80 base::android::ScopedJavaLocalRef
<jbyteArray
> descriptors
=
81 Java_UsbMidiDeviceAndroid_getDescriptors(env
, raw_device_
.obj());
83 base::android::JavaByteArrayToByteVector(env
, descriptors
.obj(),
87 void UsbMidiDeviceAndroid::InitDeviceInfo() {
88 UsbMidiDescriptorParser parser
;
89 UsbMidiDescriptorParser::DeviceInfo info
;
91 const uint8
* data
= descriptors_
.size() > 0 ? &descriptors_
[0] : nullptr;
93 if (!parser
.ParseDeviceInfo(data
, descriptors_
.size(), &info
)) {
94 // We don't report the error here. If it is critical, we will realize it
95 // when we parse the descriptors again for ports.
96 manufacturer_
= "invalid descriptor";
97 product_
= "invalid descriptor";
98 device_version_
= "invalid descriptor";
103 GetString(info
.manufacturer_index
,
104 base::StringPrintf("(vendor id = 0x%04x)", info
.vendor_id
));
106 GetString(info
.product_index
,
107 base::StringPrintf("(product id = 0x%04x)", info
.product_id
));
108 device_version_
= info
.BcdVersionToString(info
.bcd_device_version
);
111 std::vector
<uint8
> UsbMidiDeviceAndroid::GetStringDescriptor(int index
) {
112 JNIEnv
* env
= base::android::AttachCurrentThread();
113 base::android::ScopedJavaLocalRef
<jbyteArray
> descriptors
=
114 Java_UsbMidiDeviceAndroid_getStringDescriptor(env
, raw_device_
.obj(),
117 std::vector
<uint8
> ret
;
118 base::android::JavaByteArrayToByteVector(env
, descriptors
.obj(), &ret
);
122 std::string
UsbMidiDeviceAndroid::GetString(int index
,
123 const std::string
& backup
) {
124 const uint8 DESCRIPTOR_TYPE_STRING
= 3;
127 // index 0 means there is no such descriptor.
130 std::vector
<uint8
> descriptor
= GetStringDescriptor(index
);
131 if (descriptor
.size() < 2 || descriptor
.size() < descriptor
[0] ||
132 descriptor
[1] != DESCRIPTOR_TYPE_STRING
) {
133 // |descriptor| is not a valid string descriptor.
136 size_t size
= descriptor
[0];
137 std::string
encoded(reinterpret_cast<char*>(&descriptor
[0]) + 2, size
- 2);
139 // Unicode ECN specifies that the string is encoded in UTF-16LE.
140 if (!base::ConvertToUtf8AndNormalize(encoded
, "utf-16le", &result
))