|
1 // Copyright (c) 2005-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 // Class of Device (CoD) Service Manager. |
|
15 // Manages the Service bit settings in the composite CoD word. |
|
16 // The CoD is a 24 bit word, of which the upper eleven bits describe the Service class |
|
17 // profiles a Bluetooth device supports. Since these Services can be offered by transitory |
|
18 // applications, we need to provide mechanisms that allow applications to set the Service |
|
19 // bits accordingly. Bits 2 to 12 are the Service class and these are sub-divided into major |
|
20 // and minor classifications. Bits 0 and 1 are currently always zero. |
|
21 // 23 13 12 8 7 2 1 0 |
|
22 // |<--- Service class -->|<--- Device class ---> |
|
23 // [ . . . . . . . ][ . . . . . . . ][ . . . . . .0.0] |
|
24 // The Services are identified by the following table. |
|
25 // 23 13 |
|
26 // v v |
|
27 // Service LimitedDiscoverableMode 00000000001 ......this is not used |
|
28 // reserved 00000000010 |
|
29 // reserved 00000000100 |
|
30 // Service Positioning 00000001000 |
|
31 // Service Networking 00000010000 |
|
32 // Service Rendering 00000100000 |
|
33 // Service Capturing 00001000000 |
|
34 // Service ObjectTransfer 00010000000 |
|
35 // Service Audio 00100000000 |
|
36 // Service Telephony 01000000000 |
|
37 // Service Information 10000000000 |
|
38 // Because the Symbian OS handles data in 32bit and 16bit sizes, the CoD word is always |
|
39 // transported using an unsigned 32bit type. The MS byte is ignored. |
|
40 // In order to correctly process the Service bits, they are right-shifted 13 bit positions |
|
41 // and then they are managed in a 16 bit type. |
|
42 // Its feasible that multiple applications will offer the same service, therefore the |
|
43 // CoD Service Manager must keep a separate count (iServRefCount[]) of each Service bit set |
|
44 // and the bit is only removed from the CoD when the counter is decremented to zero. |
|
45 // The practical implementation is that the CSM privately owns an array of eleven counters. |
|
46 // Each SAP has an iCodServiceBits (16bit type), inherited from the base class which is a |
|
47 // record of the Service bits set by that SAP. So the SAPs are know their individual Service |
|
48 // bit settings and the CSM knows the totals. |
|
49 // As a further precaution against mis-use, each SAP will be allowed one shot at setting |
|
50 // the bits. This is controlled by assigning the msb (of iCodServiceBits) as a flag which |
|
51 // will be TRUE when the Service bit(s) have been set. This is defined as KBTCodBitsRegdFlag. |
|
52 // The action of the Publish and Suscribe interface (P&S) for writing the CoD remains, but is |
|
53 // now sub-ordinate to the SAP managed Service bits. The P&S execution path has been diverted |
|
54 // from Linkmgr to the CSM. The P&S sets the CoD Device class bits as before, but its |
|
55 // Service bit(s) are ORed with the SAP settings before writing the CoD. |
|
56 // |
|
57 // |
|
58 |
|
59 |
|
60 #include <bluetooth/logger.h> |
|
61 #include "codman.h" |
|
62 #include "linkmgr.h" |
|
63 |
|
64 #ifdef __FLOG_ACTIVE |
|
65 _LIT8(KLogComponent, LOG_COMPONENT_IN_CONN_LISTENER); |
|
66 #endif |
|
67 |
|
68 //------------------------------------------------------------------------// |
|
69 //class CBTCodServiceMan |
|
70 //------------------------------------------------------------------------// |
|
71 |
|
72 void Panic(TBTCodPanic aPanic) |
|
73 { |
|
74 LOG_STATIC_FUNC |
|
75 User::Panic(KBTCodPanic, aPanic); |
|
76 } |
|
77 |
|
78 CBTCodServiceMan* CBTCodServiceMan::NewL() |
|
79 { |
|
80 #ifdef __FLOG_ACTIVE |
|
81 CONNECT_LOGGER |
|
82 #endif |
|
83 LOG_STATIC_FUNC |
|
84 CBTCodServiceMan* self = new(ELeave) CBTCodServiceMan(); |
|
85 CleanupStack::PushL(self); |
|
86 self->ConstructL(); |
|
87 CleanupStack::Pop(); |
|
88 return self; |
|
89 } |
|
90 |
|
91 CBTCodServiceMan::CBTCodServiceMan() |
|
92 { |
|
93 LOG_FUNC |
|
94 iServRefCount.Reset(); |
|
95 } |
|
96 |
|
97 void CBTCodServiceMan::ConstructL() |
|
98 { |
|
99 LOG_FUNC |
|
100 } |
|
101 |
|
102 CBTCodServiceMan::~CBTCodServiceMan() |
|
103 { |
|
104 LOG_FUNC |
|
105 __ASSERT_DEBUG(ResolveServiceBits()==NULL, Panic(EBTCodServiceBits)); |
|
106 #ifdef __FLOG_ACTIVE |
|
107 CLOSE_LOGGER |
|
108 #endif |
|
109 } |
|
110 |
|
111 void CBTCodServiceMan::Initialise() |
|
112 { |
|
113 LOG_FUNC |
|
114 iPandSCod = iLinkMgr->iLocalDeviceSettings.DeviceClass(); // iPandSCod now has valid CoD |
|
115 } |
|
116 |
|
117 TInt CBTCodServiceMan::RegisterCodService(TUint16 aCodService) |
|
118 /* |
|
119 This method is called via the base class (CBluetoothSAP), when an L2CAPSAP |
|
120 or RFCommSAP becomes active. It keeps a count of the Service bits being set. |
|
121 */ |
|
122 { |
|
123 LOG_FUNC |
|
124 TInt err = KErrNone; |
|
125 TUint index = 0; |
|
126 |
|
127 while (aCodService != 0) |
|
128 { |
|
129 if (aCodService & KBTCodServiceLSB) |
|
130 { |
|
131 iServRefCount[index]++; |
|
132 } |
|
133 index++; |
|
134 aCodService >>= 1; |
|
135 } |
|
136 |
|
137 TRAP(err, WriteCoDL()); |
|
138 return err; |
|
139 } |
|
140 |
|
141 |
|
142 TInt CBTCodServiceMan::RemoveCodService(TUint16 aCodService) |
|
143 { |
|
144 /* |
|
145 This method is called via the base class (CBluetoothSAP), when an L2CAPSAP |
|
146 or RFCommSAP closes. It decrements the service bit counters and if any reach |
|
147 zero, the CoD will be written and delete the bit(s). |
|
148 */ |
|
149 LOG_FUNC |
|
150 TInt err = KErrNone; |
|
151 TUint index = 0; |
|
152 TBool removeService = EFalse; |
|
153 |
|
154 while (aCodService != 0) |
|
155 { |
|
156 if (aCodService & KBTCodServiceLSB) |
|
157 { |
|
158 __ASSERT_DEBUG(iServRefCount[index] > 0, Panic(EBTCodBadCount)); |
|
159 if(iServRefCount[index]) |
|
160 { |
|
161 if (--iServRefCount[index] == 0) |
|
162 { |
|
163 removeService = ETrue; |
|
164 } |
|
165 } |
|
166 } |
|
167 aCodService >>= 1; |
|
168 index++; |
|
169 } |
|
170 |
|
171 if (removeService) |
|
172 { |
|
173 TRAP(err, WriteCoDL()); |
|
174 } |
|
175 return err; |
|
176 } |
|
177 |
|
178 |
|
179 TUint16 CBTCodServiceMan::ResolveServiceBits() |
|
180 { |
|
181 /* |
|
182 This private method will sweep through the iServRefCounts and return |
|
183 a tally of the Service bit positions currently set. |
|
184 */ |
|
185 LOG_FUNC |
|
186 TUint16 serviceBits = 0; |
|
187 |
|
188 for (TUint i=0; i<KBTMaxCodServices; i++) |
|
189 { |
|
190 if (iServRefCount[i]) |
|
191 { |
|
192 serviceBits |= 1<<i; |
|
193 } |
|
194 } |
|
195 return serviceBits; |
|
196 } |
|
197 |
|
198 |
|
199 TInt CBTCodServiceMan::PandSCodHandler(TUint32 aCod) |
|
200 { |
|
201 LOG_FUNC |
|
202 // The P&S interface wants to write the CoD value |
|
203 TInt err = KErrNone; |
|
204 |
|
205 aCod &= KBTCodMask; // ensure upper unused byte is clear |
|
206 iPandSCod = aCod; // save new P&S CoD word |
|
207 TRAP(err, WriteCoDL()); |
|
208 return err; |
|
209 } |
|
210 |
|
211 |
|
212 void CBTCodServiceMan::WriteCoDL() |
|
213 { |
|
214 /* |
|
215 This private method is called whenever SAP services bits require updating. |
|
216 These bits are obtained from the iServRefCounts and ORed with P&S service |
|
217 settings before being written to the CoD. |
|
218 */ |
|
219 LOG_FUNC |
|
220 TUint32 sapServiceBits; |
|
221 |
|
222 sapServiceBits = ResolveServiceBits(); // sweep through the iServRefCounts |
|
223 sapServiceBits <<= KBTCodServiceOffset; // re-position the service bits |
|
224 |
|
225 __ASSERT_ALWAYS(iLinkMgr, Panic(EBTCodBadLinkmgr)); |
|
226 iLinkMgr->WriteClassOfDeviceL(sapServiceBits | iPandSCod); // write Cod with managed Service bits |
|
227 } |
|
228 |