73 iReply.Close(); |
77 iReply.Close(); |
74 iUssdMessaging.Close(); |
78 iUssdMessaging.Close(); |
75 TRACE_FUNC_EXIT |
79 TRACE_FUNC_EXIT |
76 } |
80 } |
77 |
81 |
78 void CCUSDCommandHandler::DoCancel() |
82 void CCUSDCommandHandler::HandleCommand( const TDesC8& /*aCmd*/, |
79 { |
|
80 TRACE_FUNC_ENTRY |
|
81 // This would never get called as the AO is never activated |
|
82 TRACE_FUNC_EXIT |
|
83 } |
|
84 |
|
85 void CCUSDCommandHandler::HandleCommand( const TDesC8& aCmd, |
|
86 RBuf8& /*aReply*/, |
83 RBuf8& /*aReply*/, |
87 TBool /*aReplyNeeded*/ ) |
84 TBool /*aReplyNeeded*/ ) |
88 { |
85 { |
89 TRACE_FUNC_ENTRY |
86 TRACE_FUNC_ENTRY |
90 TAtCommandParser::TCommandHandlerType cmdHandlerType = iATCmdParser.CommandHandlerType(); |
87 TAtCommandParser::TCommandHandlerType cmdHandlerType = iATCmdParser.CommandHandlerType(); |
91 |
88 iReply.Zero(); |
|
89 |
92 switch (cmdHandlerType) |
90 switch (cmdHandlerType) |
93 { |
91 { |
94 case (TAtCommandParser::ECmdHandlerTypeTest): |
92 case (TAtCommandParser::ECmdHandlerTypeTest): |
95 { |
93 { |
96 iReply.Create(KDefaultCmdBufLength); |
|
97 iReply.Append(KCRLF); |
94 iReply.Append(KCRLF); |
98 iReply.Append(KCUSDSupportedCmdsList); |
95 iReply.Append(KCUSDSupportedCmdsList); |
99 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
96 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
100 break; |
97 break; |
101 } |
98 } |
102 case (TAtCommandParser::ECmdHandlerTypeRead): |
99 case (TAtCommandParser::ECmdHandlerTypeRead): |
103 { |
100 { |
104 iReply.Create(KDefaultCmdBufLength); |
|
105 iReply.Append(KCRLF); |
101 iReply.Append(KCRLF); |
106 iReply.Append(KAtCUSD); |
102 iReply.Append(KAtCUSD); |
107 iReply.AppendNum(iDisplayRetMessage); |
103 iReply.AppendNum(iDisplayRetMessage); |
108 iReply.Append(KCRLF); |
104 iReply.Append(KCRLF); |
109 |
105 |
110 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
106 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
111 break; |
107 break; |
112 } |
108 } |
113 case (TAtCommandParser::ECmdHandlerTypeSet): |
109 case (TAtCommandParser::ECmdHandlerTypeSet): |
114 { |
110 { |
115 if(ParseCUSDCmd(aCmd) == KErrNone) |
111 if(ParseCUSDCmd() == KErrNone) |
116 { |
112 { |
117 if(iUSSDCommand.Length() == 0) |
113 if(iUSSDCommand.Length() == 0) |
118 { |
114 { |
119 Trace(KDebugPrintD, "No USSD command: ", iUSSDCommand.Length()); |
115 Trace(KDebugPrintD, "No USSD command: ", iUSSDCommand.Length()); |
120 |
116 |
121 // the USSD command is not set then this is a set |
117 // the USSD command is not set then this is a set |
122 iReply.Create(KDefaultCmdBufLength); |
118 iReply.Append( KOKCRLF ); |
123 iReply.Append(KCRLF); |
119 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply); |
124 iReply.Append(KAtCUSD); |
|
125 iReply.AppendNum(iDisplayRetMessage); |
|
126 iReply.Append(KCRLF); |
|
127 |
|
128 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
|
129 } |
120 } |
130 else |
121 else |
131 { |
122 { |
132 if(iUSSDSender->HandleSendUSSDCmd(iUSSDCommand, iSendAttributes) == KErrNone) |
123 if(iUSSDSender->SendUSSDCmd(iUSSDCommand, iSendAttributes) == KErrNone) |
133 { |
124 { |
134 iSendCommandSent = ETrue; |
125 iSendCommandSent = ETrue; |
135 } |
126 } |
136 else |
127 else |
137 { |
128 { |
138 iCallback->CreateReplyAndComplete(EReplyTypeError); |
129 iCallback->CreateReplyAndComplete(EReplyTypeError); |
139 } |
130 } |
140 } |
131 } |
141 } |
132 } |
153 } |
144 } |
154 } |
145 } |
155 TRACE_FUNC_EXIT |
146 TRACE_FUNC_EXIT |
156 } |
147 } |
157 |
148 |
158 void CCUSDCommandHandler::RunL() |
|
159 { |
|
160 TRACE_FUNC_ENTRY |
|
161 // This would never get called as the AO is never activated |
|
162 TRACE_FUNC_EXIT |
|
163 } |
|
164 |
|
165 |
|
166 void CCUSDCommandHandler::HandleCommandCancel() |
149 void CCUSDCommandHandler::HandleCommandCancel() |
167 { |
150 { |
168 TRACE_FUNC_ENTRY |
151 TRACE_FUNC_ENTRY |
169 iUSSDSender->Cancel(); |
152 iUSSDSender->Cancel(); |
170 TRACE_FUNC_EXIT |
153 iSendCommandSent = EFalse; |
171 } |
154 TRACE_FUNC_EXIT |
172 |
155 } |
173 TInt CCUSDCommandHandler::ParseCUSDCmd(const TDesC8& aCmd) |
156 |
174 { |
157 TInt CCUSDCommandHandler::ParseCUSDCmd() |
175 TRACE_FUNC_ENTRY |
158 { |
176 |
159 TRACE_FUNC_ENTRY |
177 iReply.Create(KDefaultCmdBufLength); |
160 |
178 TBool tempRetMessage = EFalse; |
161 TInt tempDispValue; |
179 TInt ret = iATCmdParser.NextIntParam(tempRetMessage); |
162 TInt ret = iATCmdParser.NextIntParam(tempDispValue); |
180 |
163 |
181 if(ret == KErrNone) |
164 |
182 { |
165 if (ret == KErrNone && tempDispValue >= 0 && tempDispValue < 3) |
183 if(tempRetMessage < 0 || tempRetMessage > 2) |
166 { |
184 { |
167 Trace(KDebugPrintD, "tempDispValue: ", tempDispValue); |
185 Trace(KDebugPrintD, "Display mode invalid: ", tempRetMessage); |
168 iDisplayRetMessage = tempDispValue; |
186 TRACE_FUNC_EXIT |
169 } |
187 return KErrGeneral; |
170 else if (ret != KErrNotFound) |
188 } |
171 { |
189 else |
172 Trace(KDebugPrintD, "First NextIntParam failed: ", ret); |
190 { |
173 TRACE_FUNC_EXIT |
191 iDisplayRetMessage = tempRetMessage; |
174 return KErrGeneral; |
192 } |
|
193 } |
175 } |
194 |
176 |
195 // now parse the USSD command |
177 // now parse the USSD command |
196 TPtrC8 command = iATCmdParser.NextTextParam(ret); |
178 TPtrC8 command; |
197 |
179 ret = iATCmdParser.NextTextParam(command); |
198 if (ret == KErrNone) |
180 if (ret == KErrNone ) |
199 { |
181 { |
200 if(iUSSDCommand.Create(command.Length()) != KErrNone) |
182 if(iUSSDCommand.Create(command.Length()) != KErrNone) |
201 { |
183 { |
|
184 Trace(KDebugPrintD, "iUSSDCommand.Create() failed ", ret); |
202 TRACE_FUNC_EXIT |
185 TRACE_FUNC_EXIT |
203 return KErrGeneral; |
186 return KErrGeneral; |
204 } |
187 } |
205 |
188 |
|
189 Trace(KDebugPrintS, "command: ", &command); |
206 if(Pack(command, iUSSDCommand) < 0) |
190 if(Pack(command, iUSSDCommand) < 0) |
207 { |
191 { |
208 Trace(KDebugPrintS, "Pack() returned error, command: ", &command); |
192 Trace(KDebugPrintS, "Pack() returned error, command: ", &command); |
209 TRACE_FUNC_EXIT |
|
210 return KErrGeneral; |
|
211 } |
|
212 } |
|
213 |
|
214 TInt tempDcs = -1; |
|
215 ret = iATCmdParser.NextIntParam(tempDcs); |
|
216 |
|
217 if(ret == KErrNone) |
|
218 { |
|
219 if(!IsDcsValid(tempDcs)) |
|
220 { |
|
221 Trace(KDebugPrintD, "Invalid coding standard: ", tempDcs); |
|
222 TRACE_FUNC_EXIT |
193 TRACE_FUNC_EXIT |
223 return KErrGeneral; |
194 return KErrGeneral; |
224 } |
195 } |
225 else |
196 } |
226 { |
197 else if (ret != KErrNotFound) |
227 iSendAttributes.iDcs = tempDcs; |
198 { |
228 } |
199 TRACE_FUNC_EXIT |
229 } |
200 return KErrGeneral; |
|
201 } |
|
202 TInt dcs = 0; // 3GPP TS 23.038 [25] Cell Broadcast Data Coding Scheme in integer format (default 0) |
|
203 ret = iATCmdParser.NextIntParam(dcs); |
|
204 |
|
205 Trace(KDebugPrintD, "ret: ", ret); |
|
206 Trace(KDebugPrintD, "IsDcsValid(dcs): ", IsDcsValid(dcs)); |
|
207 Trace(KDebugPrintD, "iATCmdParser.NextParam().Length(): ", iATCmdParser.NextParam().Length()); |
|
208 if(ret != KErrNone && ret != KErrNotFound || !IsDcsValid(dcs) || |
|
209 iATCmdParser.NextParam().Length() != 0) |
|
210 { |
|
211 Trace(KDebugPrintD, "Second NextIntParam failed: ", ret); |
|
212 TRACE_FUNC_EXIT |
|
213 return KErrGeneral; |
|
214 } |
|
215 else |
|
216 { |
|
217 // dcs will have the default value if no parameter is given in the command line |
|
218 Trace(KDebugPrintD, "dcs ", dcs); |
|
219 iSendAttributes.iDcs = dcs; |
|
220 } |
|
221 |
230 TRACE_FUNC_EXIT |
222 TRACE_FUNC_EXIT |
231 return KErrNone; |
223 return KErrNone; |
232 } |
224 } |
233 |
225 |
234 void CCUSDCommandHandler::HandleSendMessageComplete(TInt aResult) |
226 void CCUSDCommandHandler::HandleSendMessageComplete(TInt aError) |
235 { |
227 { |
236 TRACE_FUNC_ENTRY |
228 TRACE_FUNC_ENTRY |
237 if(aResult == KErrNone) |
229 if (aError != KErrNone) |
238 { |
230 { |
239 iReply.Create(KDefaultCmdBufLength); |
231 // Only respond from a Send USSD request if there has been an error |
240 iReply.Append(KCRLF); |
232 iCallback->CreateReplyAndComplete(EReplyTypeError); |
241 iReply.Append(KAtCUSD); |
233 } |
242 iReply.Append(KCRLF); |
234 else if (iDisplayRetMessage == 0) |
243 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
235 { |
|
236 // if display mode is 0 then no response apart from OK should be displayed |
|
237 iCallback->CreateReplyAndComplete( EReplyTypeOther, KOKCRLF ); |
|
238 } |
|
239 |
|
240 iUSSDCommand.Close(); |
|
241 TRACE_FUNC_EXIT |
|
242 } |
|
243 |
|
244 void CCUSDCommandHandler::HandleReadMessageComplete(TInt aError) |
|
245 { |
|
246 TRACE_FUNC_ENTRY |
|
247 if(aError == KErrNone) |
|
248 { |
|
249 if(iDisplayRetMessage) |
|
250 { |
|
251 FormatUSSDReceivedData(); |
|
252 |
|
253 if(iSendCommandSent) |
|
254 { |
|
255 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
|
256 } |
|
257 else |
|
258 { |
|
259 iCallback->HandleUnsolicitedRequest(iReply); |
|
260 } |
|
261 } |
|
262 |
|
263 // as we have received the data initiated by the send USSD request we set |
|
264 // this parameter to EFalse |
|
265 iSendCommandSent = EFalse; |
|
266 |
|
267 // re-issue the read request |
|
268 iUSSDReader->ReadUSSDMessage(iReceivedData, iReceiveAttributes); |
244 } |
269 } |
245 else |
270 else |
246 { |
271 { |
247 iCallback->CreateReplyAndComplete(EReplyTypeError); |
272 iCallback->CreateReplyAndComplete(EReplyTypeError); |
248 } |
273 } |
249 |
|
250 iSendCommandSent = EFalse; |
|
251 iUSSDCommand.Close(); |
|
252 TRACE_FUNC_EXIT |
|
253 } |
|
254 |
|
255 void CCUSDCommandHandler::HandleReadMessageComplete(TInt aResult) |
|
256 { |
|
257 TRACE_FUNC_ENTRY |
|
258 if(iDisplayRetMessage) |
|
259 { |
|
260 FormatUSSDReceivedData(); |
|
261 |
|
262 if(iSendCommandSent) |
|
263 { |
|
264 iCallback->CreateReplyAndComplete( EReplyTypeOther, iReply ); |
|
265 } |
|
266 else |
|
267 { |
|
268 iCallback->HandleUnsolicitedRequest(iReply); |
|
269 } |
|
270 } |
|
271 // re-issue the read request |
|
272 iUSSDReader->ReadUSSDMessage(iReceivedData, iReceiveAttributes); |
|
273 TRACE_FUNC_EXIT |
274 TRACE_FUNC_EXIT |
274 } |
275 } |
275 |
276 |
276 TInt CCUSDCommandHandler::Pack(const TDesC8& aIn, TDes8& aOut) |
277 TInt CCUSDCommandHandler::Pack(const TDesC8& aIn, TDes8& aOut) |
277 { |
278 { |
278 TRACE_FUNC_ENTRY |
279 TRACE_FUNC_ENTRY |
279 TInt startBit = 0; |
280 TInt startBit = 0; |
280 |
281 |
281 // Ensure we've got the right length |
282 // Ensure we've got the right length |
282 TInt packedOctetsRequired = PackedOctetsRequired( aIn.Length() ); |
283 TInt packedOctetsRequired = PackedOctetsRequired( aIn.Length() ); |
283 if ( packedOctetsRequired > ( aOut.MaxLength() - aOut.Length() ) ) |
284 if (packedOctetsRequired > ( aOut.MaxLength() - aOut.Length() ) ) |
284 { |
285 { |
285 Trace(KDebugPrintD, "packedOctetsRequired: ", packedOctetsRequired); |
286 Trace(KDebugPrintD, "packedOctetsRequired: ", packedOctetsRequired); |
286 TRACE_FUNC_EXIT |
287 TRACE_FUNC_EXIT |
287 return KErrOverflow; |
288 return KErrOverflow; |
288 } |
289 } |
289 |
290 |
290 // Do the conversion |
291 // Do the conversion |
291 TInt elementSizeInBits = ElementSizeInBits(TSmsDataCodingScheme::ESmsAlphabet7Bit); |
292 TInt elementSizeInBits = ElementSizeInBits(TSmsDataCodingScheme::ESmsAlphabet7Bit); |
292 if ( elementSizeInBits == 8 ) // 8 bit data |
293 |
|
294 Trace(KDebugPrintD, "elementSizeInBits = : ", elementSizeInBits); |
|
295 if (elementSizeInBits == 8) // 8 bit data |
293 { |
296 { |
294 // Straight copy here |
297 // Straight copy here |
295 aOut.Append( aIn ); |
298 aOut.Append( aIn ); |
296 } |
299 } |
297 else if ( elementSizeInBits == 7 ) // Need packing to 7-bit |
300 else if (elementSizeInBits == 7) // Need packing to 7-bit |
298 { |
301 { |
299 // Get raw pointers and do packing |
302 Trace(KDebugPrintS, "aOut: ", &aOut); |
300 TUint8* outPtr = ( TUint8* )aOut.Ptr() + aOut.Length(); |
303 Trace(KDebugPrintS, "aIn: ", &aIn); |
301 const TUint8* inPtr = aIn.Ptr(); |
304 |
302 |
305 // Get raw pointers and do packing |
303 outPtr[0] = 0; |
306 TUint8* outPtr = ( TUint8* )aOut.Ptr() + aOut.Length(); |
304 for ( TInt i = 0; i < aIn.Length() ; ++i ) |
307 const TUint8* inPtr = aIn.Ptr(); |
305 { |
308 |
306 TUint8 to = inPtr[i]; |
309 TInt inLength = aIn.Length(); |
307 *outPtr |= ( to << startBit ); |
310 outPtr[0] = 0; |
308 if ( startBit ) |
311 |
|
312 Trace(KDebugPrintD, "inLength = : ", inLength); |
|
313 for (TInt i = 0; i < inLength; ++i) |
|
314 { |
|
315 TUint8 to = inPtr[i]; |
|
316 *outPtr |= ( to << startBit ); |
|
317 |
|
318 if (startBit) |
|
319 { |
|
320 ++outPtr; |
|
321 *outPtr = ( TUint8 ) ( to >> ( 8 - startBit ) ); |
|
322 } |
|
323 |
|
324 startBit = (startBit + 7) % 8; // roll 0,1,2,3,4,5,6,7,0,1,2,... |
|
325 } |
|
326 |
|
327 Trace(KDebugPrintD, "startBit = : ", startBit); |
|
328 |
|
329 if ((inPtr[inLength - 1] == KPhCltUssdCarriageReturn && startBit == 0) || startBit == 1 ) |
|
330 { |
|
331 //We have to add one CR more |
|
332 *outPtr |= ( KPhCltUssdCarriageReturn << startBit ); |
|
333 |
|
334 if (startBit) |
309 { |
335 { |
310 ++outPtr; |
336 ++outPtr; |
311 *outPtr = ( TUint8 ) ( to >> ( 8 - startBit ) ); |
337 *outPtr = (TUint8) (KPhCltUssdCarriageReturn >> (8 - startBit)); |
312 } |
338 } |
313 startBit = ( startBit + 7 )%8; // roll 0,1,2,3,4,5,6,7,0,1,2,... |
339 else |
314 |
340 { |
315 if ( i == aIn.Length() - 1 ) // if this is the last time |
341 ++packedOctetsRequired; |
316 { |
342 } |
317 if ( ( to == KPhCltUssdCarriageReturn && startBit == 0 ) || |
343 startBit = (startBit + 7)%8; |
318 startBit == 1 ) |
344 } |
319 { |
345 |
320 //We have to add one CR more |
346 // Increment the length for the packed data |
321 *outPtr |= ( KPhCltUssdCarriageReturn << startBit ); |
347 aOut.SetLength(aOut.Length() + packedOctetsRequired); |
322 if ( startBit ) |
348 |
323 { |
349 Trace(KDebugPrintD, "aOut.Length() = : ", aOut.Length()); |
324 ++outPtr; |
350 } |
325 *outPtr = ( TUint8 ) ( KPhCltUssdCarriageReturn >> ( 8 - startBit ) ); |
|
326 } |
|
327 else |
|
328 { |
|
329 ++packedOctetsRequired; |
|
330 } |
|
331 startBit = ( startBit + 7 )%8; |
|
332 } |
|
333 } |
|
334 } |
|
335 // Increment the length for the packed data |
|
336 aOut.SetLength( aOut.Length() + packedOctetsRequired ); |
|
337 } |
|
338 |
351 |
339 // Return number of bytes used |
352 // Return number of bytes used |
340 TRACE_FUNC_EXIT |
353 TRACE_FUNC_EXIT |
341 return packedOctetsRequired; |
354 return packedOctetsRequired; |
342 } |
355 } |
343 |
356 |
344 TInt CCUSDCommandHandler::PackedOctetsRequired( TInt aNumUDUnits ) const |
357 TInt CCUSDCommandHandler::PackedOctetsRequired(TInt aNumUDUnits) const |
345 { |
358 { |
346 TRACE_FUNC_ENTRY |
359 TRACE_FUNC_ENTRY |
347 TInt startBit = 0; |
360 TInt startBit = 0; |
348 |
361 |
349 TInt octetsRequired = 0; |
362 TInt octetsRequired = 0; |
350 TInt elementSizeInBits = ElementSizeInBits(TSmsDataCodingScheme::ESmsAlphabet7Bit); |
363 TInt elementSizeInBits = ElementSizeInBits(TSmsDataCodingScheme::ESmsAlphabet7Bit); |
351 if ( elementSizeInBits == 8 ) |
364 if (elementSizeInBits == 8) |
352 { |
365 { |
353 octetsRequired=aNumUDUnits; |
366 octetsRequired=aNumUDUnits; |
354 } |
367 } |
355 else |
368 else |
356 { |
369 { |
357 octetsRequired = ( startBit + aNumUDUnits*elementSizeInBits + 7 )/8; // Rounds up |
370 octetsRequired = (startBit + aNumUDUnits*elementSizeInBits + 7 )/8; // Rounds up |
358 } |
371 } |
359 TRACE_FUNC_EXIT |
372 TRACE_FUNC_EXIT |
360 return octetsRequired; |
373 return octetsRequired; |
361 } |
374 } |
362 |
375 |
363 TBool CCUSDCommandHandler::IsDcsValid( const TUint8 aDcs ) const |
376 TBool CCUSDCommandHandler::IsDcsValid( const TUint8 aDcs ) const |
364 { |
377 { |
365 TRACE_FUNC_ENTRY |
378 TRACE_FUNC_ENTRY |
366 TBool isDcsValid( EFalse ); |
379 TBool isDcsValid(EFalse); |
367 // 76543210 |
380 // 76543210 |
368 TUint8 codingGroup = ( aDcs & 0xF0 ) >> KHighNibbleShift; // bits XXXX____ |
381 TUint8 codingGroup = ( aDcs & 0xF0 ) >> KHighNibbleShift; // bits XXXX____ |
369 TUint8 characterSet = ( aDcs & 0x0C ) >> KQuarterShift; // bits ____XX__ |
382 TUint8 characterSet = ( aDcs & 0x0C ) >> KQuarterShift; // bits ____XX__ |
370 TUint8 lowQuartet = ( aDcs & 0x0F ); // bits ____XXXX |
383 TUint8 lowQuartet = ( aDcs & 0x0F ); // bits ____XXXX |
371 |
384 |
372 switch ( codingGroup ) |
385 switch (codingGroup) |
373 { |
386 { |
374 case 0x00: |
387 case 0x00: |
375 case 0x02: |
388 case 0x02: |
376 case 0x03: |
389 case 0x03: |
377 case 0x0F: |
390 case 0x0F: |