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"
8 #include "base/android/jni_array.h"
9 #include "base/i18n/icu_string_conversions.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "jni/UsbMidiDeviceAndroid_jni.h"
13 #include "media/midi/usb_midi_descriptor_parser.h"
18 UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(ObjectRef raw_device
,
19 UsbMidiDeviceDelegate
* delegate
)
20 : raw_device_(raw_device
), delegate_(delegate
) {
21 JNIEnv
* env
= base::android::AttachCurrentThread();
22 Java_UsbMidiDeviceAndroid_registerSelf(env
, raw_device_
.obj(),
23 reinterpret_cast<jlong
>(this));
25 GetDescriptorsInternal();
29 UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() {
30 JNIEnv
* env
= base::android::AttachCurrentThread();
31 Java_UsbMidiDeviceAndroid_close(env
, raw_device_
.obj());
34 std::vector
<uint8
> UsbMidiDeviceAndroid::GetDescriptors() {
38 std::string
UsbMidiDeviceAndroid::GetManufacturer() {
42 std::string
UsbMidiDeviceAndroid::GetProductName() {
46 std::string
UsbMidiDeviceAndroid::GetDeviceVersion() {
47 return device_version_
;
50 void UsbMidiDeviceAndroid::Send(int endpoint_number
,
51 const std::vector
<uint8
>& data
) {
52 JNIEnv
* env
= base::android::AttachCurrentThread();
53 const uint8
* head
= data
.size() ? &data
[0] : NULL
;
54 ScopedJavaLocalRef
<jbyteArray
> data_to_pass
=
55 base::android::ToJavaByteArray(env
, head
, data
.size());
57 Java_UsbMidiDeviceAndroid_send(env
, raw_device_
.obj(), endpoint_number
,
61 void UsbMidiDeviceAndroid::OnData(JNIEnv
* env
,
65 std::vector
<uint8
> bytes
;
66 base::android::JavaByteArrayToByteVector(env
, data
, &bytes
);
68 const uint8
* head
= bytes
.size() ? &bytes
[0] : NULL
;
69 delegate_
->ReceiveUsbMidiData(this, endpoint_number
, head
, bytes
.size(),
70 base::TimeTicks::Now());
73 bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv
* env
) {
74 return RegisterNativesImpl(env
);
77 void UsbMidiDeviceAndroid::GetDescriptorsInternal() {
78 JNIEnv
* env
= base::android::AttachCurrentThread();
79 base::android::ScopedJavaLocalRef
<jbyteArray
> descriptors
=
80 Java_UsbMidiDeviceAndroid_getDescriptors(env
, raw_device_
.obj());
82 base::android::JavaByteArrayToByteVector(env
, descriptors
.obj(),
86 void UsbMidiDeviceAndroid::InitDeviceInfo() {
87 UsbMidiDescriptorParser parser
;
88 UsbMidiDescriptorParser::DeviceInfo info
;
90 const uint8
* data
= descriptors_
.size() > 0 ? &descriptors_
[0] : nullptr;
92 if (!parser
.ParseDeviceInfo(data
, descriptors_
.size(), &info
)) {
93 // We don't report the error here. If it is critical, we will realize it
94 // when we parse the descriptors again for ports.
95 manufacturer_
= "invalid descriptor";
96 product_
= "invalid descriptor";
97 device_version_
= "invalid descriptor";
102 GetString(info
.manufacturer_index
,
103 base::StringPrintf("(vendor id = 0x%04x)", info
.vendor_id
));
105 GetString(info
.product_index
,
106 base::StringPrintf("(product id = 0x%04x)", info
.product_id
));
107 device_version_
= info
.BcdVersionToString(info
.bcd_device_version
);
110 std::vector
<uint8
> UsbMidiDeviceAndroid::GetStringDescriptor(int index
) {
111 JNIEnv
* env
= base::android::AttachCurrentThread();
112 base::android::ScopedJavaLocalRef
<jbyteArray
> descriptors
=
113 Java_UsbMidiDeviceAndroid_getStringDescriptor(env
, raw_device_
.obj(),
116 std::vector
<uint8
> ret
;
117 base::android::JavaByteArrayToByteVector(env
, descriptors
.obj(), &ret
);
121 std::string
UsbMidiDeviceAndroid::GetString(int index
,
122 const std::string
& backup
) {
123 const uint8 DESCRIPTOR_TYPE_STRING
= 3;
126 // index 0 means there is no such descriptor.
129 std::vector
<uint8
> descriptor
= GetStringDescriptor(index
);
130 if (descriptor
.size() < 2 || descriptor
.size() < descriptor
[0] ||
131 descriptor
[1] != DESCRIPTOR_TYPE_STRING
) {
132 // |descriptor| is not a valid string descriptor.
135 size_t size
= descriptor
[0];
136 std::string
encoded(reinterpret_cast<char*>(&descriptor
[0]) + 2, size
- 2);
138 // Unicode ECN specifies that the string is encoded in UTF-16LE.
139 if (!base::ConvertToUtf8AndNormalize(encoded
, "utf-16le", &result
))