1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // This file contains the capabilites part of playerinformation. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 @publishedAll |
|
21 @released |
|
22 */ |
|
23 |
|
24 #include <bluetooth/logger.h> |
|
25 #include <remconinterfaceselector.h> |
|
26 #include <remcon/avrcpspec.h> |
|
27 #include <playerinformationtarget.h> |
|
28 |
|
29 #include "eventsmask.h" |
|
30 #include "playerinformation.h" |
|
31 |
|
32 #ifdef __FLOG_ACTIVE |
|
33 _LIT8(KLogComponent, LOG_COMPONENT_AVRCP_PLAYER_INFO); |
|
34 #endif |
|
35 |
|
36 class TRemConMetadataTransferGetCapabilities |
|
37 { |
|
38 public: |
|
39 TUint8 iCapabilityID; |
|
40 }; |
|
41 |
|
42 EXPORT_C void MPlayerCapabilitiesObserver::ClearEvents() |
|
43 { |
|
44 DoClearEvents(); |
|
45 } |
|
46 |
|
47 EXPORT_C TInt MPlayerCapabilitiesObserver::AddEvent(TRegisterNotificationEvent aEvent) |
|
48 { |
|
49 return DoAddEvent(aEvent); |
|
50 } |
|
51 |
|
52 EXPORT_C TInt MPlayerCapabilitiesObserver::RemoveEvent(TRegisterNotificationEvent aEvent) |
|
53 { |
|
54 return DoRemoveEvent(aEvent); |
|
55 } |
|
56 |
|
57 EXPORT_C void MPlayerCapabilitiesObserver::ClearCompanyIds() |
|
58 { |
|
59 DoClearCompanyIds(); |
|
60 } |
|
61 |
|
62 EXPORT_C TInt MPlayerCapabilitiesObserver::AddCompanyId(TInt aID) |
|
63 { |
|
64 return DoAddCompanyId( aID ); |
|
65 } |
|
66 |
|
67 EXPORT_C TInt MPlayerCapabilitiesObserver::RemoveCompanyID(TInt aID) |
|
68 { |
|
69 return DoRemoveCompanyID( aID ); |
|
70 } |
|
71 |
|
72 |
|
73 // from MPlayerCapabilitiesObserver |
|
74 void CPlayerInfoTarget::DoClearEvents() |
|
75 { |
|
76 // AVRCP 1.3 specification, Appendix H says that PlaybackStatusChanged |
|
77 // and TrackChanged event notification support is mandatory, so add these |
|
78 |
|
79 iSupportedNotificationEventList->Reset(); |
|
80 iSupportedNotificationEventList->Append(ERegisterNotificationPlaybackStatusChanged); |
|
81 iSupportedNotificationEventList->Append(ERegisterNotificationTrackChanged); |
|
82 } |
|
83 |
|
84 |
|
85 TInt CPlayerInfoTarget::DoAddEvent( TRegisterNotificationEvent aEvent ) |
|
86 { |
|
87 // check the event is supported (note system status is NOT supported) |
|
88 if ( aEvent >= ERegisterNotificationReservedLast |
|
89 || aEvent == ERegisterNotificationSystemStatusChanged_NotSupported) |
|
90 { |
|
91 return KErrNotSupported; |
|
92 } |
|
93 |
|
94 // check if aEvent is already in the list of supported events |
|
95 if (!iSupportedNotificationEventList->Find(aEvent)) |
|
96 { |
|
97 // not found so add it to the list |
|
98 iSupportedNotificationEventList->Append(aEvent); |
|
99 return KErrNone; |
|
100 } |
|
101 |
|
102 // else return already in the list |
|
103 return KErrAlreadyExists; |
|
104 } |
|
105 |
|
106 |
|
107 TInt CPlayerInfoTarget::DoRemoveEvent( TRegisterNotificationEvent aEvent ) |
|
108 { |
|
109 // AVRCP 1.3 specification, Appendix H says that PlaybackStatusChanged |
|
110 // and TrackChanged event notification support is mandatory, so add these |
|
111 TInt err = KErrNone; |
|
112 if ( aEvent == ERegisterNotificationPlaybackStatusChanged |
|
113 || aEvent == ERegisterNotificationTrackChanged) |
|
114 { |
|
115 return KErrNotSupported; |
|
116 } |
|
117 |
|
118 // Find aEvent in the list of supported events |
|
119 if (iSupportedNotificationEventList->Find(aEvent)) |
|
120 { |
|
121 // and then remove it |
|
122 iSupportedNotificationEventList->Remove(aEvent); |
|
123 TInt pendingPos = iPendingNotificationEventList.Find(aEvent); |
|
124 if (pendingPos != KErrNotFound) |
|
125 { |
|
126 iPendingNotificationEventList.Remove( pendingPos ); |
|
127 |
|
128 // Tell anyone waiting for a notification that an event has been |
|
129 // removed. Alas, we can't specify _WHICH_ event has been removed |
|
130 // since there's no way to indicate this in an INTERNAL_ERROR response |
|
131 SendError(KErrAvrcpMetadataInternalError, |
|
132 RAvrcpIPC::SetIPCOperationIdFromEventId(aEvent), |
|
133 ERemConNotifyResponseChanged); |
|
134 } |
|
135 } |
|
136 else |
|
137 { |
|
138 err = KErrNotFound; |
|
139 } |
|
140 return err; |
|
141 } |
|
142 |
|
143 |
|
144 void CPlayerInfoTarget::DoClearCompanyIds() |
|
145 { |
|
146 // The Bluetooth SIG vendor id must always be present |
|
147 // See AVRCP 1.3 Specification, section 5.5.1, table 5.4 |
|
148 iCompanyIdList.Reset(); |
|
149 iCompanyIdList.Append(KBluetoothSIGVendorId); |
|
150 } |
|
151 |
|
152 |
|
153 TInt CPlayerInfoTarget::DoAddCompanyId( TInt aID ) |
|
154 { |
|
155 if ( aID > KMaxCompanyID ) |
|
156 { |
|
157 return KErrNotSupported; |
|
158 } |
|
159 |
|
160 // check if the ID is already in the list |
|
161 TInt pos = iCompanyIdList.Find( aID ); |
|
162 |
|
163 // add only if not present in list to avoid duplicates |
|
164 if (pos != KErrNotFound) |
|
165 { |
|
166 return KErrAlreadyExists; |
|
167 } |
|
168 |
|
169 // make sure the list cannot contain more than 255 items |
|
170 if (iCompanyIdList.Count() >= KMaxNrOfCompanyIDs) |
|
171 { |
|
172 return KErrOverflow; |
|
173 } |
|
174 |
|
175 return iCompanyIdList.Append( aID ); |
|
176 } |
|
177 |
|
178 |
|
179 TInt CPlayerInfoTarget::DoRemoveCompanyID( TInt aID ) |
|
180 { |
|
181 // The Bluetooth SIG vendor id must always be present |
|
182 // See AVRCP 1.3 Specification, section 5.5.1, table 5.4 |
|
183 if ( aID == KBluetoothSIGVendorId ) |
|
184 { |
|
185 return KErrNotSupported; |
|
186 } |
|
187 |
|
188 // check if the ID is in the list |
|
189 TInt pos = iCompanyIdList.Find( aID ); |
|
190 |
|
191 // if found remove else do nothing |
|
192 if (pos != KErrNotFound) |
|
193 { |
|
194 iCompanyIdList.Remove( pos ); |
|
195 return KErrNone; |
|
196 } |
|
197 return pos; |
|
198 } |
|
199 |
|
200 |
|
201 void CPlayerInfoTarget::ProcessGetCapabilities(const TDesC8& aData) |
|
202 { |
|
203 LOG_STATIC_FUNC |
|
204 |
|
205 /* Decode the get capability message */ |
|
206 TRemConMetadataTransferGetCapabilities getCapability; |
|
207 |
|
208 // check there is at least 1 byte of data |
|
209 if (!aData.Length()) |
|
210 { |
|
211 // Invalid packet |
|
212 return SendError(KErrAvrcpMetadataInvalidParameter, EGetCapabilities); |
|
213 } |
|
214 |
|
215 TPckgC<TRemConMetadataTransferGetCapabilities> data(*reinterpret_cast<const TRemConMetadataTransferGetCapabilities*>(aData.Ptr())); |
|
216 getCapability = data(); |
|
217 TGetCapabilityValues id = (TGetCapabilityValues) getCapability.iCapabilityID; |
|
218 |
|
219 // format the response in a TRemConGetCapabilitiesResponse |
|
220 RRemConGetCapabilitiesResponse response; |
|
221 |
|
222 switch ( id ) |
|
223 { |
|
224 case ECapabilityIdCompanyID: |
|
225 // respond with ECapabilityIdCompanyID |
|
226 response.iCapabilityId = ECapabilityIdCompanyID; |
|
227 |
|
228 // followed by number of IDs |
|
229 response.iCapabilityCount = iCompanyIdList.Count(); |
|
230 |
|
231 // and then list of company ids, |
|
232 for (TInt i=0; i< iCompanyIdList.Count(); i++ ) |
|
233 { |
|
234 TInt x = iCompanyIdList[i]; |
|
235 if (response.iCapabilities.Append(x) != KErrNone) |
|
236 { |
|
237 response.Close(); |
|
238 return SendError(KErrAvrcpMetadataInternalError, EGetCapabilities); // Try to send internal error if OOM |
|
239 } |
|
240 } |
|
241 break; |
|
242 |
|
243 case ECapabilityIdEventsSupported: |
|
244 // respond with ECapabilityIdEventsSupported |
|
245 response.iCapabilityId = ECapabilityIdEventsSupported; |
|
246 |
|
247 // followed by number of supported events, and then list of events |
|
248 response.iCapabilityCount = 0; |
|
249 iSupportedNotificationEventList->Begin(); |
|
250 while(iSupportedNotificationEventList->Next()) |
|
251 { |
|
252 if (KErrNone != response.iCapabilities.Append(iSupportedNotificationEventList->Get())) |
|
253 { |
|
254 response.Close(); |
|
255 return SendError(KErrAvrcpMetadataInternalError, EGetCapabilities); // Try to send internal error if OOM |
|
256 } |
|
257 response.iCapabilityCount++; |
|
258 } |
|
259 break; |
|
260 |
|
261 default: |
|
262 /* other IDs are reserved */ |
|
263 return SendError(KErrAvrcpMetadataInvalidParameter, EGetCapabilities); // Invalid packet |
|
264 } |
|
265 |
|
266 TInt error = 0; |
|
267 TRAP(error, response.WriteL(iOutBuf)); // Don't send error if OOM |
|
268 response.Close(); |
|
269 if (error == KErrNone) |
|
270 // send the result back to the CT |
|
271 InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid), |
|
272 EGetCapabilities, ERemConResponse, iOutBuf ); |
|
273 } |
|
274 |
|