diff --git a/dom/bluetooth/BluetoothCommon.h b/dom/bluetooth/BluetoothCommon.h index 84eeba2f0ee..424b9909cd0 100644 --- a/dom/bluetooth/BluetoothCommon.h +++ b/dom/bluetooth/BluetoothCommon.h @@ -214,6 +214,49 @@ enum ControlPlayStatus { PLAYSTATUS_ERROR = 0xFF, }; +enum BluetoothAvrcpPlayerAttribute { + AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, + AVRCP_PLAYER_ATTRIBUTE_REPEAT, + AVRCP_PLAYER_ATTRIBUTE_SHUFFLE, + AVRCP_PLAYER_ATTRIBUTE_SCAN +}; + +enum BluetoothAvrcpStatus { + AVRCP_STATUS_BAD_COMMAND, + AVRCP_STATUS_BAD_PARAMETER, + AVRCP_STATUS_NOT_FOUND, + AVRCP_STATUS_INTERNAL_ERROR, + AVRCP_STATUS_SUCCESS +}; + +enum BluetoothAvrcpEvent { + AVRCP_EVENT_PLAY_STATUS_CHANGED, + AVRCP_EVENT_TRACK_CHANGE, + AVRCP_EVENT_TRACK_REACHED_END, + AVRCP_EVENT_TRACK_REACHED_START, + AVRCP_EVENT_PLAY_POS_CHANGED, + AVRCP_EVENT_APP_SETTINGS_CHANGED +}; + +enum BluetoothAvrcpNotification { + AVRCP_NTF_INTERIM, + AVRCP_NTF_CHANGED +}; + +struct BluetoothAvrcpElementAttribute { + uint32_t mId; + nsString mValue; +}; + +struct BluetoothAvrcpNotificationParam { + ControlPlayStatus mPlayStatus; + uint8_t mTrack[8]; + uint32_t mSongPos; + uint8_t mNumAttr; + uint8_t mIds[256]; + uint8_t mValues[256]; +}; + END_BLUETOOTH_NAMESPACE #endif // mozilla_dom_bluetooth_bluetoothcommon_h__ diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp index 48ae4010b00..5809fb66b29 100644 --- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp +++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp @@ -89,8 +89,8 @@ public: class UpdateRegisterNotificationTask : public nsRunnable { public: - UpdateRegisterNotificationTask(btrc_event_id_t aEventId, uint32_t aParam) - : mEventId(aEventId) + UpdateRegisterNotificationTask(BluetoothAvrcpEvent aEvent, uint32_t aParam) + : mEvent(aEvent) , mParam(aParam) { MOZ_ASSERT(!NS_IsMainThread()); @@ -102,11 +102,11 @@ public: BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get(); NS_ENSURE_TRUE(a2dp, NS_OK); - a2dp->UpdateRegisterNotification(mEventId, mParam); + a2dp->UpdateRegisterNotification(mEvent, mParam); return NS_OK; } private: - btrc_event_id_t mEventId; + BluetoothAvrcpEvent mEvent; uint32_t mParam; }; @@ -149,33 +149,35 @@ ConvertAttributeString(int aAttrId, nsAString& aAttrStr) class UpdateElementAttrsTask : public nsRunnable { public: - UpdateElementAttrsTask(uint8_t aNumAttr, btrc_media_attr_t* aPlayerAttrs) - : mNumAttr(aNumAttr) - , mPlayerAttrs(aPlayerAttrs) + UpdateElementAttrsTask(uint8_t aNumAttr, const btrc_media_attr_t* aPlayerAttrs) + : mNumAttr(aNumAttr) { MOZ_ASSERT(!NS_IsMainThread()); + + mAttrs = new BluetoothAvrcpElementAttribute[mNumAttr]; + + for (uint8_t i = 0; i < mNumAttr; ++i) { + mAttrs[i].mId = aPlayerAttrs[i]; + } } nsresult Run() { MOZ_ASSERT(NS_IsMainThread()); - btrc_element_attr_val_t* attrs = new btrc_element_attr_val_t[mNumAttr]; - for (int i = 0; i < mNumAttr; i++) { - nsAutoString attrText; - attrs[i].attr_id = mPlayerAttrs[i]; - ConvertAttributeString(mPlayerAttrs[i], attrText); - strcpy((char *)attrs[i].text, NS_ConvertUTF16toUTF8(attrText).get()); + for (uint8_t i = 0; i < mNumAttr; ++i) { + ConvertAttributeString(mAttrs[i].mId, mAttrs[i].mValue); } NS_ENSURE_TRUE(sBtAvrcpInterface, NS_OK); - sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs, nullptr); + sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, mAttrs, nullptr); return NS_OK; } + private: uint8_t mNumAttr; - btrc_media_attr_t* mPlayerAttrs; + nsAutoArrayPtr mAttrs; }; class UpdatePassthroughCmdTask : public nsRunnable @@ -342,9 +344,30 @@ AvrcpGetElementAttrCallback(uint8_t aNumAttr, btrc_media_attr_t* aPlayerAttrs) static void AvrcpRegisterNotificationCallback(btrc_event_id_t aEventId, uint32_t aParam) { + BluetoothAvrcpEvent event; + MOZ_ASSERT(!NS_IsMainThread()); - NS_DispatchToMainThread(new UpdateRegisterNotificationTask(aEventId, aParam)); + switch (aEventId) { + case BTRC_EVT_PLAY_STATUS_CHANGED: + event = AVRCP_EVENT_PLAY_STATUS_CHANGED; + case BTRC_EVT_TRACK_CHANGE: + event = AVRCP_EVENT_TRACK_CHANGE; + case BTRC_EVT_TRACK_REACHED_END: + event = AVRCP_EVENT_TRACK_REACHED_END; + case BTRC_EVT_TRACK_REACHED_START: + event = AVRCP_EVENT_TRACK_REACHED_START; + case BTRC_EVT_PLAY_POS_CHANGED: + event = AVRCP_EVENT_PLAY_POS_CHANGED; + case BTRC_EVT_APP_SETTINGS_CHANGED: + event = AVRCP_EVENT_APP_SETTINGS_CHANGED; + break; + default: + BT_LOGR("Unknown event 0x%x", aEventId); + return; + } + + NS_DispatchToMainThread(new UpdateRegisterNotificationTask(event, aParam)); } /* @@ -1097,26 +1120,25 @@ BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle, // Send track changed and position changed if track num is not the same. // See also AVRCP 1.3 Spec 5.4.2 if (mMediaNumber != aMediaNumber && - mTrackChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) { - btrc_register_notification_t param; + mTrackChangedNotifyType == AVRCP_NTF_INTERIM) { + BluetoothAvrcpNotificationParam param; // convert to network big endian format // since track stores as uint8[8] // 56 = 8 * (BTRC_UID_SIZE -1) for (int i = 0; i < BTRC_UID_SIZE; ++i) { - param.track[i] = (aMediaNumber >> (56 - 8 * i)); + param.mTrack[i] = (aMediaNumber >> (56 - 8 * i)); } - mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED; - sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_TRACK_CHANGE, - BTRC_NOTIFICATION_TYPE_CHANGED, - ¶m, nullptr); - if (mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) { - param.song_pos = mPosition; + mTrackChangedNotifyType = AVRCP_NTF_CHANGED; + sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_TRACK_CHANGE, + AVRCP_NTF_CHANGED, + param, nullptr); + if (mPlayPosChangedNotifyType == AVRCP_NTF_INTERIM) { + param.mSongPos = mPosition; // EVENT_PLAYBACK_POS_CHANGED shall be notified if changed current track - mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED; - sBtAvrcpInterface->RegisterNotificationRsp( - BTRC_EVT_PLAY_POS_CHANGED, - BTRC_NOTIFICATION_TYPE_CHANGED, - ¶m, nullptr); + mPlayPosChangedNotifyType = AVRCP_NTF_CHANGED; + sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_PLAY_POS_CHANGED, + AVRCP_NTF_CHANGED, + param, nullptr); } } @@ -1143,27 +1165,27 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration, #if ANDROID_VERSION > 17 NS_ENSURE_TRUE_VOID(sBtAvrcpInterface); // always update playstatus first - sBtAvrcpInterface->GetPlayStatusRsp((btrc_play_status_t)aPlayStatus, - aDuration, aPosition, nullptr); + sBtAvrcpInterface->GetPlayStatusRsp(aPlayStatus, aDuration, + aPosition, nullptr); // when play status changed, send both play status and position if (mPlayStatus != aPlayStatus && - mPlayStatusChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) { - btrc_register_notification_t param; - param.play_status = (btrc_play_status_t)aPlayStatus; - mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED; - sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_STATUS_CHANGED, - BTRC_NOTIFICATION_TYPE_CHANGED, - ¶m, nullptr); + mPlayStatusChangedNotifyType == AVRCP_NTF_INTERIM) { + BluetoothAvrcpNotificationParam param; + param.mPlayStatus = aPlayStatus; + mPlayStatusChangedNotifyType = AVRCP_NTF_CHANGED; + sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_PLAY_STATUS_CHANGED, + AVRCP_NTF_CHANGED, + param, nullptr); } if (mPosition != aPosition && - mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) { - btrc_register_notification_t param; - param.song_pos = aPosition; - mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED; - sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_POS_CHANGED, - BTRC_NOTIFICATION_TYPE_CHANGED, - ¶m, nullptr); + mPlayPosChangedNotifyType == AVRCP_NTF_INTERIM) { + BluetoothAvrcpNotificationParam param; + param.mSongPos = aPosition; + mPlayPosChangedNotifyType = AVRCP_NTF_CHANGED; + sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_PLAY_POS_CHANGED, + AVRCP_NTF_CHANGED, + param, nullptr); } mDuration = aDuration; @@ -1180,21 +1202,22 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration, * aParam is only valid when position changed */ void -BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam) +BluetoothA2dpManager::UpdateRegisterNotification(BluetoothAvrcpEvent aEvent, + uint32_t aParam) { MOZ_ASSERT(NS_IsMainThread()); #if ANDROID_VERSION > 17 NS_ENSURE_TRUE_VOID(sBtAvrcpInterface); - btrc_register_notification_t param; + BluetoothAvrcpNotificationParam param; - switch (aEventId) { - case BTRC_EVT_PLAY_STATUS_CHANGED: - mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM; - param.play_status = (btrc_play_status_t)mPlayStatus; + switch (aEvent) { + case AVRCP_EVENT_PLAY_STATUS_CHANGED: + mPlayStatusChangedNotifyType = AVRCP_NTF_INTERIM; + param.mPlayStatus = mPlayStatus; break; - case BTRC_EVT_TRACK_CHANGE: + case AVRCP_EVENT_TRACK_CHANGE: // In AVRCP 1.3 and 1.4, the identifier parameter of EVENT_TRACK_CHANGED // is different. // AVRCP 1.4: If no track is selected, we shall return 0xFFFFFFFFFFFFFFFF, @@ -1202,26 +1225,26 @@ BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam) // version 1.4 is to allow for new UID feature. As for AVRCP 1.3, we shall // return 0xFFFFFFFF. Since PTS enforces to check this part to comply with // the most updated spec. - mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM; + mTrackChangedNotifyType = AVRCP_NTF_INTERIM; // needs to convert to network big endian format since track stores // as uint8[8]. 56 = 8 * (BTRC_UID_SIZE -1). for (int index = 0; index < BTRC_UID_SIZE; ++index) { // We cannot easily check if a track is selected, so whenever A2DP is // streaming, we assume a track is selected. if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) { - param.track[index] = 0x0; + param.mTrack[index] = 0x0; } else { - param.track[index] = 0xFF; + param.mTrack[index] = 0xFF; } } break; - case BTRC_EVT_PLAY_POS_CHANGED: + case AVRCP_EVENT_PLAY_POS_CHANGED: // If no track is selected, return 0xFFFFFFFF in the INTERIM response - mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM; + mPlayPosChangedNotifyType = AVRCP_NTF_INTERIM; if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) { - param.song_pos = mPosition; + param.mSongPos = mPosition; } else { - param.song_pos = 0xFFFFFFFF; + param.mSongPos = 0xFFFFFFFF; } mPlaybackInterval = aParam; break; @@ -1229,9 +1252,8 @@ BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam) break; } - sBtAvrcpInterface->RegisterNotificationRsp((btrc_event_id_t)aEventId, - BTRC_NOTIFICATION_TYPE_INTERIM, - ¶m, nullptr); + sBtAvrcpInterface->RegisterNotificationRsp(aEvent, AVRCP_NTF_INTERIM, + param, nullptr); #endif } diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h index 52490e3f418..b37decab42a 100644 --- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h +++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h @@ -52,7 +52,7 @@ public: void UpdatePlayStatus(uint32_t aDuration, uint32_t aPosition, ControlPlayStatus aPlayStatus); - void UpdateRegisterNotification(int aEventId, int aParam); + void UpdateRegisterNotification(BluetoothAvrcpEvent aEvent, uint32_t aParam); void GetAlbum(nsAString& aAlbum); uint32_t GetDuration(); ControlPlayStatus GetPlayStatus(); @@ -105,9 +105,9 @@ private: * mPlayPosChangedNotifType represents current RegisterNotification * notification type. */ - int mPlayStatusChangedNotifyType; - int mTrackChangedNotifyType; - int mPlayPosChangedNotifyType; + BluetoothAvrcpNotification mPlayStatusChangedNotifyType; + BluetoothAvrcpNotification mTrackChangedNotifyType; + BluetoothAvrcpNotification mPlayPosChangedNotifyType; }; END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.cpp b/dom/bluetooth/bluedroid/BluetoothInterface.cpp index 5778265a1f9..a9356bd0887 100644 --- a/dom/bluetooth/bluedroid/BluetoothInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothInterface.cpp @@ -355,6 +355,153 @@ Convert(BluetoothHandsfreeVolumeType aIn, bthf_volume_type_t& aOut) return NS_OK; } +#if ANDROID_VERSION >= 18 +static nsresult +Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut) +{ + static const btrc_play_status_t sPlayStatus[] = { + [PLAYSTATUS_STOPPED] = BTRC_PLAYSTATE_STOPPED, + [PLAYSTATUS_PLAYING] = BTRC_PLAYSTATE_PLAYING, + [PLAYSTATUS_PAUSED] = BTRC_PLAYSTATE_PAUSED, + [PLAYSTATUS_FWD_SEEK] = BTRC_PLAYSTATE_FWD_SEEK, + [PLAYSTATUS_REV_SEEK] = BTRC_PLAYSTATE_REV_SEEK + }; + if (aIn >= MOZ_ARRAY_LENGTH(sPlayStatus)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPlayStatus[aIn]; + return NS_OK; +} + +static nsresult +Convert(enum BluetoothAvrcpPlayerAttribute aIn, btrc_player_attr_t& aOut) +{ + static const btrc_player_attr_t sPlayerAttr[] = { + [AVRCP_PLAYER_ATTRIBUTE_EQUALIZER] = BTRC_PLAYER_ATTR_EQUALIZER, + [AVRCP_PLAYER_ATTRIBUTE_REPEAT] = BTRC_PLAYER_ATTR_REPEAT, + [AVRCP_PLAYER_ATTRIBUTE_SHUFFLE] = BTRC_PLAYER_ATTR_SHUFFLE, + [AVRCP_PLAYER_ATTRIBUTE_SCAN] = BTRC_PLAYER_ATTR_SCAN + }; + if (aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPlayerAttr[aIn]; + return NS_OK; +} + +static nsresult +Convert(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut) +{ + static const btrc_status_t sStatus[] = { + [AVRCP_STATUS_BAD_COMMAND] = BTRC_STS_BAD_CMD, + [AVRCP_STATUS_BAD_PARAMETER] = BTRC_STS_BAD_PARAM, + [AVRCP_STATUS_NOT_FOUND] = BTRC_STS_NOT_FOUND, + [AVRCP_STATUS_INTERNAL_ERROR] = BTRC_STS_INTERNAL_ERR, + [AVRCP_STATUS_SUCCESS] = BTRC_STS_NO_ERROR + }; + if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sStatus[aIn]; + return NS_OK; +} + +static nsresult +Convert(enum BluetoothAvrcpEvent aIn, btrc_event_id_t& aOut) +{ + static const btrc_event_id_t sEventId[] = { + [AVRCP_EVENT_PLAY_STATUS_CHANGED] = BTRC_EVT_PLAY_STATUS_CHANGED, + [AVRCP_EVENT_TRACK_CHANGE] = BTRC_EVT_TRACK_CHANGE, + [AVRCP_EVENT_TRACK_REACHED_END] = BTRC_EVT_TRACK_REACHED_END, + [AVRCP_EVENT_TRACK_REACHED_START] = BTRC_EVT_TRACK_REACHED_START, + [AVRCP_EVENT_PLAY_POS_CHANGED] = BTRC_EVT_PLAY_POS_CHANGED, + [AVRCP_EVENT_APP_SETTINGS_CHANGED] = BTRC_EVT_APP_SETTINGS_CHANGED + }; + if (aIn >= MOZ_ARRAY_LENGTH(sEventId)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sEventId[aIn]; + return NS_OK; +} + +static nsresult +Convert(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut) +{ + static const btrc_notification_type_t sNotificationType[] = { + [AVRCP_NTF_INTERIM] = BTRC_NOTIFICATION_TYPE_INTERIM, + [AVRCP_NTF_CHANGED] = BTRC_NOTIFICATION_TYPE_CHANGED + }; + if (aIn >= MOZ_ARRAY_LENGTH(sNotificationType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNotificationType[aIn]; + return NS_OK; +} + +static nsresult +Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut) +{ + const NS_ConvertUTF16toUTF8 value(aIn.mValue); + size_t len = std::min(strlen(value.get()), sizeof(aOut.text) - 1); + + memcpy(aOut.text, value.get(), len); + aOut.text[len] = '\0'; + aOut.attr_id = aIn.mId; + + return NS_OK; +} + +#endif + +/* |ConvertArray| is a helper for converting arrays. Pass an + * instance of this structure as the first argument to |Convert| + * to convert an array. The output type has to support the array + * subscript operator. + */ +template +struct ConvertArray +{ + ConvertArray(const T* aData, unsigned long aLength) + : mData(aData) + , mLength(aLength) + { } + + const T* mData; + unsigned long mLength; +}; + +/* This implementation of |Convert| converts the elements of an + * array one-by-one. The result data structures must have enough + * memory allocated. + */ +template +static nsresult +Convert(const ConvertArray& aIn, Tout& aOut) +{ + for (unsigned long i = 0; i < aIn.mLength; ++i) { + nsresult rv = Convert(aIn.mData[i], aOut[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +/* This implementation of |Convert| is a helper that automatically + * allocates enough memory to hold the conversion results. The + * actual conversion is performed by the array-conversion helper + * above. + */ +template +static nsresult +Convert(const ConvertArray& aIn, nsAutoArrayPtr& aOut) +{ + aOut = new Tout[aIn.mLength]; + Tout* out = aOut.get(); + + return Convert(aIn, out); +} + // // Result handling // @@ -1490,12 +1637,19 @@ BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes) } void -BluetoothAvrcpInterface::GetPlayStatusRsp(btrc_play_status_t aPlayStatus, +BluetoothAvrcpInterface::GetPlayStatusRsp(ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->get_play_status_rsp(aPlayStatus, aSongLen, - aSongPos); + bt_status_t status; + btrc_play_status_t playStatus = BTRC_PLAYSTATE_STOPPED; + + if (!(NS_FAILED(Convert(aPlayStatus, playStatus)))) { + status = mInterface->get_play_status_rsp(playStatus, aSongLen, aSongPos); + } else { + status = BT_STATUS_PARM_INVALID; + } + if (aRes) { DispatchBluetoothAvrcpResult( aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, status); @@ -1504,10 +1658,18 @@ BluetoothAvrcpInterface::GetPlayStatusRsp(btrc_play_status_t aPlayStatus, void BluetoothAvrcpInterface::ListPlayerAppAttrRsp( - int aNumAttr, btrc_player_attr_t* aPAttrs, + int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs, BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs); + bt_status_t status; + ConvertArray pAttrsArray(aPAttrs, aNumAttr); + nsAutoArrayPtr pAttrs; + + if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) { + status = mInterface->list_player_app_attr_rsp(aNumAttr, pAttrs); + } else { + status = BT_STATUS_PARM_INVALID; + } if (aRes) { DispatchBluetoothAvrcpResult( @@ -1529,9 +1691,20 @@ BluetoothAvrcpInterface::ListPlayerAppValueRsp( void BluetoothAvrcpInterface::GetPlayerAppValueRsp( - btrc_player_settings_t* aPVals, BluetoothAvrcpResultHandler* aRes) + uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->get_player_app_value_rsp(aPVals); + bt_status_t status; + btrc_player_settings_t pVals; + + /* FIXME: you need to implement the missing conversion functions */ + NS_NOTREACHED("Conversion function missing"); + + if (false /* TODO: we don't support any player app values currently */) { + status = mInterface->get_player_app_value_rsp(&pVals); + } else { + status = BT_STATUS_PARM_INVALID; + } if (aRes) { DispatchBluetoothAvrcpResult( @@ -1541,11 +1714,21 @@ BluetoothAvrcpInterface::GetPlayerAppValueRsp( void BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp( - int aNumAttr, btrc_player_setting_text_t* aPAttrs, + int aNumAttr, const uint8_t* aIds, const char** aTexts, BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->get_player_app_attr_text_rsp(aNumAttr, - aPAttrs); + bt_status_t status; + btrc_player_setting_text_t* aPAttrs; + + /* FIXME: you need to implement the missing conversion functions */ + NS_NOTREACHED("Conversion function missing"); + + if (false /* TODO: we don't support any attributes currently */) { + status = mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs); + } else { + status = BT_STATUS_PARM_INVALID; + } + if (aRes) { DispatchBluetoothAvrcpResult( aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, status); @@ -1554,11 +1737,21 @@ BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp( void BluetoothAvrcpInterface::GetPlayerAppValueTextRsp( - int aNumVal, btrc_player_setting_text_t* aPVals, + int aNumVal, const uint8_t* aIds, const char** aTexts, BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->get_player_app_value_text_rsp(aNumVal, - aPVals); + bt_status_t status; + btrc_player_setting_text_t* pVals; + + /* FIXME: you need to implement the missing conversion functions */ + NS_NOTREACHED("Conversion function missing"); + + if (false /* TODO: we don't support any values currently */) { + status = mInterface->get_player_app_value_text_rsp(aNumVal, pVals); + } else { + status = BT_STATUS_PARM_INVALID; + } + if (aRes) { DispatchBluetoothAvrcpResult( aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, status); @@ -1567,10 +1760,18 @@ BluetoothAvrcpInterface::GetPlayerAppValueTextRsp( void BluetoothAvrcpInterface::GetElementAttrRsp( - uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs, + uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs, BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->get_element_attr_rsp(aNumAttr, aPAttrs); + bt_status_t status; + ConvertArray pAttrsArray(aAttrs, aNumAttr); + nsAutoArrayPtr pAttrs; + + if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) { + status = mInterface->get_element_attr_rsp(aNumAttr, pAttrs); + } else { + status = BT_STATUS_PARM_INVALID; + } if (aRes) { DispatchBluetoothAvrcpResult( @@ -1580,9 +1781,16 @@ BluetoothAvrcpInterface::GetElementAttrRsp( void BluetoothAvrcpInterface::SetPlayerAppValueRsp( - btrc_status_t aRspStatus, BluetoothAvrcpResultHandler* aRes) + BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->set_player_app_value_rsp(aRspStatus); + bt_status_t status; + btrc_status_t rspStatus = BTRC_STS_BAD_CMD; // silences compiler warning + + if (NS_SUCCEEDED(Convert(aRspStatus, rspStatus))) { + status = mInterface->set_player_app_value_rsp(rspStatus); + } else { + status = BT_STATUS_PARM_INVALID; + } if (aRes) { DispatchBluetoothAvrcpResult( @@ -1592,11 +1800,55 @@ BluetoothAvrcpInterface::SetPlayerAppValueRsp( void BluetoothAvrcpInterface::RegisterNotificationRsp( - btrc_event_id_t aEventId, btrc_notification_type_t aType, - btrc_register_notification_t* aPParam, BluetoothAvrcpResultHandler* aRes) + BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes) { - bt_status_t status = mInterface->register_notification_rsp(aEventId, aType, - aPParam); + nsresult rv; + bt_status_t status; + btrc_event_id_t event = { }; + btrc_notification_type_t type = BTRC_NOTIFICATION_TYPE_INTERIM; + btrc_register_notification_t param; + + switch (aEvent) { + case AVRCP_EVENT_PLAY_STATUS_CHANGED: + rv = Convert(aParam.mPlayStatus, param.play_status); + break; + case AVRCP_EVENT_TRACK_CHANGE: + MOZ_ASSERT(sizeof(aParam.mTrack) == sizeof(param.track)); + memcpy(param.track, aParam.mTrack, sizeof(param.track)); + rv = NS_OK; + break; + case AVRCP_EVENT_TRACK_REACHED_END: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + case AVRCP_EVENT_TRACK_REACHED_START: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + case AVRCP_EVENT_PLAY_POS_CHANGED: + param.song_pos = aParam.mSongPos; + rv = NS_OK; + break; + case AVRCP_EVENT_APP_SETTINGS_CHANGED: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + default: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + } + + if (NS_SUCCEEDED(rv) && + NS_SUCCEEDED(Convert(aEvent, event)) && + NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->register_notification_rsp(event, type, ¶m); + } else { + status = BT_STATUS_PARM_INVALID; + } + if (aRes) { DispatchBluetoothAvrcpResult( aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, status); diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.h b/dom/bluetooth/bluedroid/BluetoothInterface.h index f052b5a1dea..58f5e3c862a 100644 --- a/dom/bluetooth/bluedroid/BluetoothInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothInterface.h @@ -276,33 +276,39 @@ public: BluetoothAvrcpResultHandler* aRes); void Cleanup(BluetoothAvrcpResultHandler* aRes); - void GetPlayStatusRsp(btrc_play_status_t aPlayStatus, + void GetPlayStatusRsp(ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, BluetoothAvrcpResultHandler* aRes); - void ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs, + void ListPlayerAppAttrRsp(int aNumAttr, + const BluetoothAvrcpPlayerAttribute* aPAttrs, BluetoothAvrcpResultHandler* aRes); void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes); - void GetPlayerAppValueRsp(btrc_player_settings_t* aPVals, + /* TODO: redesign this interface once we actually use it */ + void GetPlayerAppValueRsp(uint8_t aNumAttrs, + const uint8_t* aIds, const uint8_t* aValues, BluetoothAvrcpResultHandler* aRes); + /* TODO: redesign this interface once we actually use it */ void GetPlayerAppAttrTextRsp(int aNumAttr, - btrc_player_setting_text_t* aPAttrs, + const uint8_t* aIds, const char** aTexts, BluetoothAvrcpResultHandler* aRes); + /* TODO: redesign this interface once we actually use it */ void GetPlayerAppValueTextRsp(int aNumVal, - btrc_player_setting_text_t* aPVals, + const uint8_t* aIds, const char** aTexts, BluetoothAvrcpResultHandler* aRes); - void GetElementAttrRsp(uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs, + void GetElementAttrRsp(uint8_t aNumAttr, + const BluetoothAvrcpElementAttribute* aAttr, BluetoothAvrcpResultHandler* aRes); - void SetPlayerAppValueRsp(btrc_status_t aRspStatus, + void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes); - void RegisterNotificationRsp(btrc_event_id_t aEventId, - btrc_notification_type_t aType, - btrc_register_notification_t* aPParam, + void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent, + BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, BluetoothAvrcpResultHandler* aRes); void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);