Tuesday, March 10, 2009

Bluetooth Handsfree Profile Support for Windows Mobile 5 - The Series

http://thefiles.macadamian.com/2007/01/bluetooth-handsfree-profil_116786630484523617.html

Bluetooth Handsfree Profile Support for Windows Mobile 5 - The Series (Part 1)

Bluetooth Handsfree Profile Support for Windows Mobile 5 - Part 1

Have you ever run into the question of what mechanisms are there for supporting Bluetooth on your WM5 device? What has Microsoft provided to extend the Handsfree profile functionality? How can I use the Audio Gateway?

Very good questions. In this series of articles about Bluetooth support, I'm going to try to fill in the holes. This series is geared towards developers who have experimented with the Audio Gateway and are scratching their heads as to how to get into this "black box".

Microsoft supports Bluetooth with an architecture known as the "Audio Gateway." It consists of the core itself, the Services interface, AT Command Extension Module, Phone Extension Module, and Network Component. All of these components interact with the Core that signals the Bluetooth stack of commands and state changes. To read up on the Audio Gateway architecture, trickle into the MSDN website and search for "Bluetooth Audio Gateway."

Now, as a developer, you're wondering, "How do I get into this darn thing and make it do what I want it to do?"

There are a few ways to interact with the Audio Gateway (which I'll refer to as the "AG").

Firstly, from a services standpoint, Services.exe and the underlying layer of IOCTL calls the core support call enumerations to control the AG. I've listed the constants below. They are also in the .h file. The constants are pretty self-explanatory, so I won't go into much detail about them. Basically, there is the AG service, which we can start, stop and refresh. If the service has started and a Bluetooth device has been paired with the WM5 device, a service level connection must be established with the device as to signal different commands via AT Commands (to be discussed later), which we can start and stop as well. On top of that, the AG can route audio to the Bluetooth headset.

// You can find these within service.h
// IOCTL_SERVICE_START
// IOCTL_SERVICE_REFRESH
// IOCTL_SERVICE_STOP
// IOCTL_SERVICE_STATUS

#define IOCTL_AG_OPEN_AUDIO 0x01
#define IOCTL_AG_CLOSE_AUDIO 0x02
#define IOCTL_AG_CLOSE_CONTROL 0x03
#define IOCTL_AG_SET_SPEAKER_VOL 0x04
#define IOCTL_AG_SET_MIC_VOL 0x05
#define IOCTL_AG_GET_SPEAKER_VOL 0x06
#define IOCTL_AG_GET_MIC_VOL 0x07
#define IOCTL_AG_GET_POWER_MODE 0x08
#define IOCTL_AG_SET_POWER_MODE 0x09
#define IOCTL_AG_OPEN_CONTROL 0x0A


So, by simply calling these defines within a IOCTL call, you'll be able to achieve basic services support. Note that some defines require you to pass in values. I don't want to go into too much detail about this, since we're just scratching the surface, and I'm hoping as the reader you're asking yourself, "When does the fun really start?"

HANDLE msAGHandle = ::CreateFile( L"BAG0:", 0, 0, 0, OPEN_EXISTING, 0, 0 );
if ( INVALID_HANDLE_VALUE == msAGHandle )
{
// log something with GetLastError();
return;
}

BOOL result = ::DeviceIoControl( msAGHandle, IOCTL_SERVICE_STOP, 0, 0, 0, 0, 0, 0 );
if ( FALSE == result )
{
// log something
}

::CloseHandle( msAGHandle );


Aside from the services layer, it has been hypothesized (however not actually confirmed by me) that we can replace the AT Command Extension Module to override the AG core of AT command reception and AT command processing. What happens in the AG core, once paired and a service level connection has been established, is if an AT command is received, the core will first "ask" the AT Command Extension Module if it would like to handle this command. If the AT Command Extension Module wishes to handle the command, it returns, from the interface call, "true", otherwise "false" to signal that the core does its own processing.

So how do you replace the AT Command Extension Module?

Easy. There are two ways to replace this module. In the Windows directory of your WM5 device, a file called "btagext.dll" exposes an interface (interface description to come) which the core dynamically links to. You can replace this file with your own file to override the AT command processing. Replacing the file can get a little messy if one doesn't have the proper access rights to overwrite Windows dlls.

Another way is to edit the registry so that the AT Command Extension Module path points to your dll. First, copy your AT Command Extension DLL onto the device, edit the registry path "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Bluetooth\\AudioGateway\\BTAGExtModule" with your DLL path, restart the device or restart the AG service and... Voila!

So what does your custom AT Command Extension Module have to override?

The "btagext.dll" exposes these commands:
typedef DWORD (*PFN_SendATCommand) (LPSTR szCommand, DWORD cbCommand);
BOOL BthAGATHandler(LPSTR szCommand, DWORD cbCommand);
void BthAGATSetCallback(PFN_SendATCommand pfn);
DWORD BthAGOnVoiceTag(BOOL fOn);


I leave it up to you to explore how you can replace the AT Command Extension Module. Take a look at the MSDN Website for further details about these methods. Since we are supporting the Handsfree profile, search the Bluetooth website for the .pdf file for a list of AT commands to support... Or stay tuned for a description of these AT commands.

OK, now for the really fun stuff.

I know some of you are in the same boat as I was, saying to yourself, "I've paired and authenticated with the device, so how do I use the AG to route audio? I can route audio via the IOCTL calls but I can't do any other in-call processing. Some libraries offered in WinCE are not exposed to me, e.g. the Network component (for network signalling), so I can't signal different in-call states."

Personally, I've never gotten around to using the AG service, since specific libraries in the WM5 PPC and Smartphone SDK weren't included in my version and, simply put, I had no mechanism to control the AG service besides the service component via IOCTL calls.

What to do, what to do?! Hey lets build our own Audio Gateway! Yeah! That'll be fun!

Bluetooth Handsfree Profile Support for Windows Mobile 5 - The Series (Part 2)

Bluetooth HandsFree Profile Support for Windows Mobile 5 - part 2

In our last article, we explored some of the interfaces offered by the Audio Gateway (AG) for developers.
The problem was that some of the mechanisms offered in WinCE to signal the AG core of specific network events are not present in the PPC and Smartphone SDK. In this article, I'll show you how to create a lightweight replacement for the AG without spending two weeks (or more) figuring out what's inside that little "black box" they call the Audio Gateway. Please be aware I've never worked for Microsoft and everything within this article should be considered "as is".

To start, I'll give you some background information on how the AG core is constructed and then I'll share specific details on creating a connection with the Bluetooth device, processing AT commands, and routing audio to the Bluetooth chip.

The AG core consists of 3 modules:

Parser: Once the AG core has established a socket connection with the Bluetooth Headset device, the interactions between the WM5 device and the Bluetooth Headset are signed via the socket connection with AT Commands. The parser' responsibility is to retrieve these messages from the socket, parse them and return them to the Handler module for processing.

Interface: Exposes methods to signal the network states and initiate commands from the services layer. It also listens for incoming Bluetooth device requests that are trying to create a baseband connection, whether synchronously or asynchronously.

Handler: The core module that receives input from both the Interface module and the Parser module and, based on those stimuli and the internal state of the AG core, will respond accordingly, i.e. send AT command responses, create a service level socket connection, an IOCTL call to the audio driver to route voice...etc.

The Meat and Bones of the Parser
The parser is quite simple. After the Handler creates a socket connection with the Bluetooth Headset (I'll talk more about that in the third installment) it passes the connected socket to the Parser module to listen for and receive incoming AT commands. Listed below are the AT commands that are supported by the Bluetooth HandsFree profile and their corresponding general definitions.

"AT+CKPD=200" - Indicates a Bluetooth button press
"AT+VGM=" - Indicates a microphone volume change
"AT+VGS=" - Indicates a speakerphone volume change
"AT+BRSF=" - The Headset is asking what features are supported
"AT+CIND?" - The Headset is asking about the indicators that are signaled
"AT+CIND=?" - The Headset is asking about the test indicators
"AT+CMER=" - The Headset is asking which indicates are registered for updates
"ATA" - When an incoming call has been answered, usually a Bluetooth button press
"AT+CHUP" - When a call has been hung up, usually a Bluetooth button press
"ATD>" - The Headset is requesting the local device to perform a memory dial
"ATD" - The Headset is requesting to dial the number
"AT+BLDN" - The Headset is requesting to perform last number dialed
"AT+CCWA=" - The Headset has enabled call waiting
"AT+CLIP=" - The Headset has enabled CLI (Calling Line Identification)
"AT+VTS=" - The Headset is asking to send DTMF digits
"AT+CHLD=" - The Headset is asking to put the call on Hold
"AT+BVRA=" - The Headset is requesting voice recognition
"ATH" - Call hang-up

Once the parser receives one of these commands, it parses the received buffer for these character sequences and passes the parsed command back to the Handler (discussed later) as an enumeration that the Handler will be able to identify and process.

The Meat and Bones of the Interface Module
The Interface module exposes methods for signaling the Handler of network connections, listens for incoming connections and calls Handler methods of services requests.

Firstly, the Interface layer must ensure that the Bluetooth stack has been started, otherwise there's no point in processing any other commands for the network layer or the services layer. The mechanism in which the underlying layer signals that the Bluetooth stack is fully functional is via waiting on an Event Handle. Here's some code to support this:
#define BTH_NAMEDEVENT_STACK_INITED L"system/events/bluetooth/StackInitialized"
HANDLE btStack = ::OpenEvent( EVENT_ALL_ACCESS, FALSE,BTH_NAMEDEVENT_STACK_INITED );

// m_closeEvent is a previously Created Event to signal other
// waiting threads to stop waiting (created by the developer)

if( btStack && m_closeEvent )
{
HANDLE waitObjects[] = {btStack, m_closeEvent};
DWORD result = ::WaitForMultipleObjects( 2, &waitObjects[0], FALSE, INFINITE );
::CloseHandle( btStack );
if( result - WAIT_OBJECT_0 == 0 )
{
//The Bluetooth stack is up, signal core module to finish initialization
}
else if( 1 == result - WAIT_OBJECT_0 WAIT_FAILED == result )
{
// We've been signaled to close, Bluetooth stack is down!
// Or our application has signaled us to stop waiting
}
}

Here we wait on the Open Bluetooth Stack Initialized Event or our own pre-created event to indicate either the Bluetooth stack is operational or to exit, since our application is closing too.

This same scheme also works for waiting for a synchronous or asynchronous baseband connection (Which I'll discuss further in the third installment), but instead of waiting on the BTH_NAMEDEVENT_STACK_INITED wstring, we wait on the Opened Event BTH_NAMEDEVENT_CONNECTIONS_CHANGED, as defined below:
#define BTH_NAMEDEVENT_CONNECTIONS_CHANGED L"system/events/bluetooth/ConnectionsChange"

If the Interface module receives a signal of this event, it notifies the Handler module to check its baseband connections for changes.

Aside from the listening for baseband connections, or if the Bluetooth Stack is up, the Interface module also want to process service commands and network layer notifications. So, following the services interface, as mentioned in the previous article, the module needs to support:

Opening audio
Closing audio
Opening a control channel
Closing a control channel
Getting/setting the microphone volume
Getting/setting the speaker volume
Getting/setting the power mode

And these methods simply call the Handler methods for processing (Which I'll talk about more in the third installment).
For reliability, however, a developer can't create a control channel if no Bluetooth device has been paired with the WM5 device (obviously). Also, a developer can't open up a control channel without a fully initialized Interface Module (Bluetooth Stack is operational).
Secondly, you can't open an audio channel if there is no control channel open.

On the Network signaling side, the Interface Module exposes a method call to the network layer, which passes a number to identify the type of network call being signaled. The supported signaling calls are:
#define NETWORK_EVENT_CALL_IN 0x00
#define NETWORK_EVENT_CALL_OUT 0x01
#define NETWORK_EVENT_CALL_CONNECT 0x02
#define NETWORK_EVENT_CALL_DISCONNECT 0x03
#define NETWORK_EVENT_CALL_REJECT 0x04
#define NETWORK_EVENT_CALL_INFO 0x05
#define NETWORK_EVENT_CALL_BUSY 0x06
#define NETWORK_EVENT_RING 0x07

void BthAGOnNetworkEvent( DWORD dwEvent, LPSTR pszParam );

If you're designing the Interface module and the appliction accesses the network layer, you'll have to support these defines and signal your Handler class to handle these events. For more detail on these libraries, visit the MSDN website.

Important Note:
If you're developing the Interface Module alongside Microsoft's Audio Gateway, be sure that you turn off the MS AG in your Interface Module initialization code before doing anything else. If you don't, the Microsoft's AG will interfere with *your* Gateway application. The first article in this series lists code that turn offs the service. Please refer to it for the IOCTL call that corresponds to the service shutdown.

Ok, now we're getting to the really juicy part, The Handler Module. What's ticking underneath that hood, you might ask. In this article, we've explored a system level overview of the AG core and gone into details about the different responsibilities associated with the Parser Module and the Interface Module. But what ties them all together? The Handler module!

Stay tuned for a detailed description of the Handler Module...
Comments:
Internet Explorer may not respond when you click Print or Print Preview in the File menu.When you try to connect to Web folders, you may receive the following error message:The current operation could not be completed because an unexpected error has occurred.
What version were you using?
This is very useful artical, I have developed tiny AG for bluetooth Hands Free (HF) device but I am facing issue to connect with HF when HF is made ON/OFF means connection from HF side.

I am able to make socket connection with BT_ADDRESS from registry to HF but how can I make it possible that HF make connection with me when it made start.
There are a few options you can use to detect that the Headset has either turned on or is trying to communicate with your device.
You can listen to the event "system/events/bluetooth/ConnectionsChange" just call OpenEvent with this string. Otherwise you can build a notification framework around RequestBluetoothNotifications(...). Look on msdn for more information about this. If your bluetooth device is paired and has turned on it will notify with an event
Another problem that you might run into is that MS AG might be interferring with your tiny AG. If that is the case simple do a IOControl call to the "BAG" to stop the control channel
#define IOCTL_AG_CLOSE_CONTROL 0x03
#define IOCTL_AG_OPEN_CONTROL 0x0A
Thanks for your prompt response.I tried both the methods to get event on connection change but I am facing issue like I get disconnect event immediately as I get connect event. I figure out the event type by second method Request......
I have already stoped MS AG (BAG ) service.
How can my AG accept the initiated connection request and get socket handle or should my AG try to connect with the BT_Address what my AG currently doing??
Try this out, don't stop the MS AG service entirely, keep it running. If you receive the disconnection from the headset (e.g. the headset has powered off or gone out of range) close the connection and start the MS AG control channel. When you receive a notification that there is a baseband connection again, stop MS AG control channel and then try to connect to the headset with your tiny AG. And yes connect with the BT_Address from the registry. Does this answer your question? - I'm a little unclear as to your second post.
Hello Quan Nguyen,

I tried your suggested way to connect with HF by stopping MS AG control channel on baseband connection event but the issue is my AG fails to connect with HF if my AG try to connect with HF on base band connection event, means MS AG start to make connection with HF earlier than my AG start on the event.

My AG is able to make connection with HF after few second (around 1)of the event by closing already opened MS AG connection by IOCTL_AG_CLOSE_CONTROL.

How can I stop MS AG to make connection on this connection event? or any other event that I can use for knowing about MS AG made connection with HF after base band connection event.

One thing I also want to know is if I stop entire MS AG service is there any functinality that may be affected like pairing or file transfer or other???

Any help will be very helpful to me.
Yes the MS AG when it receives the baseband notification will connect faster than your AG. And from my experience this is unavoidable unless you turn the MS AG off entirely. If MS AG service is running I do not know of any "clean" way of stopping the MS AG service from trying to connect.
You will be able to see that the headset makes a connection with the system through the RequestBluetoothNotifications notifications and you can equate that if you're not connect to it, it must be the MS AG.

If you turn off MS AG entirely, pairing and file transfer will not be affected (to my knowledge). However functionality related to BT audio while *your* AG has control of the control channel will be affected if you don't support it properly.
Hello Quan Nguyen,

Thanks for your response.
I did it by stopping MS AG entirely.
Again I have one issue related to connect() API with blocking mode. When HF is already OFF and I am trying to make connection by connect() it blocks for ever and it hangs my application. and also normally when HF is ON connect() takes 7-10 seconds to return. Can you please give me some guide line or how to tackle with such situation.
Well there a few things you can do to get around this. You can always run a multi-threaded application. One thread would call the connect() and on another thread you can set a timer which will closesocket() and stop the connect() from blocking. You can also use the select() method with a timeout. Drop by MSDN and take a look at the methods for socket programming. When the Headset is ON and it takes 7-10 seconds to connect, I think this is unavoidable. This is the latency it takes for the bluetooth connection to negotiate properly. From my experience it shouldn't take that long. If you analyse your code and it's not because of something you're doing in your application then from your perspective there is really nothing you can do (I believe - from an application level implementation).
Hello Quan Nguyen,

One time more I need your help.
I already created complete service for bluetooth AG and it works fine.

Issue I am facing in DOPOD 810 and HTC TyTN is Createfile("PFX0",0,0,NULL,OPEN_EXISTING,0,NULL);

But it fails every time I try to call createfile() and return invalid handle (0xFFFFFFFFF).

It is called in multithreaded application.
Hi,
A few things here,
1# For your CreateFile(...) make sure that it is L"PFX0" and not "PFX0". I would imagine this is important. The compiler should catch this
2# Make sure that the index is correct, possibly it could be PFX1..etc
3# Make sure that you can find this within the active drivers list [HKEY_LOCAL_MACHINE\Drivers\Active] within the registry of the device
4# If createFile(...) returns an error what does GetLastError() return, this could reveal some possible hints.
Hello Quan Nguyen,

One hint I want, is service I made for tiny bluetooth gateway is working correctly with HTC Touch. I am facing issue with TyTN device is event socket gets connected with Hands Free it doesn't start to send AT commands to my service. Also some time I start to connect and it doesn't gets connected forever. Is there any thing missing to say bluetooth stack after socket gets closed??

Socket connection is not smooth as HTC Touch device I am getting.

I try to connect with hands free when STACK_UP, connect event from stack.
Hello Quan Nguyen,

I want to close connection on removing pairing from settings on PDA.

Can you please suggest me the way how can I get notification of removing perticular pairing??

One thing I found with my AG is once my AG gets connected with HF and I remove pairing from PDA, still registry entry for the same HF is there and not removed while in case of not connected with HF via my AG it removes the registry on removing pairing.

Any thing left to inform stack to take that action after closing socket??
Hello Quan Nguyen,

I really want help from you,

My service for BTAG works fine but I am facing issue for making pairing.
Pairing logic I am using from default , When device gets paired my service will try to make connection.

I handled BTE_KEY_REVOKED event to remove connection on removing pairing. Problem I am facing with Jabra BT135 is after removing pairing if I try to make pairing again then Jabra device continuously asking for passkey and give incorrect passkey msg.

On removing pairing my service just close the socket and tear down the connection. I think any thing is missed out during closing connection hence again pairing create issue.

Can you please tell me for closing connection with BTHF just close socket in any condition like active voice or active call? or anything need to take care with BTHF or stack.

After removing pairing if I try it again, device found successfully and asking for passkey again and again.

How can I tell BTHF or stack to remove previous connection completely sp I can make fresh pairing and new connection again??


Please respond atleast.

Thanks in advance.
Hello Quan Nguyen,

I didn't receive any reply for earlier post.

Can you please reply for this one atlest?

Proble I am facing is receiving AT commands.

After making BT radio ON when my AG try to connect with BTHF and gets connected and negotiated with proper At commends and responses successfully but after that my AG didn't receive any AT commands for call operating like ATA,CHUP or BLDN and none. When my AG sends AT commands like RING it operates correctly and play ring but my AG didn't receive any At commands from HF.


This problem happens only when I break active connection by making BT radio OFF. It doesn't create any problem if I break active connection by making BTHF OFF. Why my AG didn't get any AT commands from BTHF?????

Is there anything to say to BT stack or BTHF???

Any registry to cahnge?
When I make BTHF off and try to make connection after makinf ON, it works fine but not working when BT radio is made OFF and then ON, it gets negotiated correctly but after that not responding well and At commands are not received.

Please respond at lest, even have no answer.
Hi Paresh,
My apologies for not responding, I'm not a part of the Macadamian Files any longer and hence have not checked this blog site for quite some time.

My apologies again

Regards,

Quan Nguyen
How can I control the AG to connect HF by my application?
I tried to use the bluetooth api, suck as: BthCreateACLConnection, BthCreateScoConnection, or via socket directly. But all did work.
Because the AG didn't know the connection status. Maybe i have to use the AG to connect HF in the application.

Bluetooth HandsFree Profile Support for Windows Mobile 5 - The Series (part 3)

In the last two articles, we talked about the different ways to interact with Microsoft's Audio Gateway (AG). We then focused on how to start writing your own light-weight Audio Gateway, since some versions of the PPC and Smartphone SDK do not include mechanisms to support control of the AG. In the second article, we took a system level view of the AG core and gave enough detail to create a Parser and Interface Module.

Today, we'll get to the real guts, and this is what heroes are made of: the Handler Module. However, be warned that this is not for the timid, nor the faint of heart. We'll dive into the deep end right away!

This third and last installment will discuss how to create the Handler Module, which includes processing the services and network commands from the Interface module; processing the AT Commands from the Parser Module, starting the service/control level socket connection with the Bluetooth Device; and routing audio to the Bluetooth chip.

Yeah, that's right--what you've been waiting for! With this information, you can do loads of cool things like streaming mp3 music from your mobile device to your bluetooth headset. Wow! Imagine what else you can do with a little imagination!

The Guts of the Handler Module


The guts of the Handler Module contains four small sub-modules, the connection processing, the AT command processing, network notification processing and the services processing. We'll break down these four sub-modules in this article.

Creating a Socket Connection with the Bluetooth HandsFree device:


First, we assume that the Bluetooth device has already been paired with WM5 device, if not then do so right now! Start->Settings->Connections->Bluetooth... you know the rest, if not consult your WM5 Device User's Manual on how to pair with a Bluetooth device.

Once the pair has been completed and Microsoft's AG has been turned off (See the previous article), we're ready to create a service level connection with the Bluetooth device.

The pairing of the Bluetooth device will create an entry in the registry, under [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Bluetooth\\AudioGateway\\Devices]. In this registry folder will be numbered folders for the different Bluetooth devices that have been paired with the WM5 device. These folders consist of a socket address and the associated service value which the connection offers, in our case, the Handsfree profile service. To create a service/control-level socket connection, first iterate through the numbered folders to get the right address and service that corresponds to the device that you want to create a connection with. Then, simply connect with the Bluetooth device by using the standard winsock socket connection scheme as shown in the code below:

// make sure to include these
#include
#include

// in a function to create the connection, do this
// create a Socket
m_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (INVALID_SOCKET == m_socket)
{
// Failed to create socket: Log something here with GetLastError();
return;
}

// Fill the socket addr structure with the bluetooth device information
SOCKADDR_BTH socketAddr = {0};
socketAddr.serviceClassId = /*Service value from the registry goes here*/;
socketAddr.addressFamily = AF_BTH;
socketAddr.btAddr = /*Address from the registry goes here*/;

// connect to the device
if( SOCKET_ERROR == connect(m_socket, (SOCKADDR *)&m_addr, sizeof(m_addr)) )
{
// Failed to connect: Log something here with GetLastError();
return;
}
Simply put, get the registry value, create the socket, fill the SOCKADDR_BTH structure with the registry value and try to connect to the Bluetooth device.

Parse AT Command Processing and Initialization Hand-shaking


So, we've created a service/control level connection with the Bluetooth device, now what? Well, once the Bluetooth device has detected a connection, it will send initialization codes as AT Commands. It's the Parser's job to parse these initialization codes and send them to us to send to the Handler Module for processing.

To receive these commands, we'll need to receive, from the socket, i.e.
// create an array of char with a size of RECEIVE_BUFFER_SIZE (that's your define)
// with s(the socket that was just connected)
int result = recv(s, buffer, RECEIVE_BUFFER_SIZE, 0);

And subsequently send out responses through the same socket the AT Command responses, i.e.
// "command" is a std::string and "s" is the socket
// that has the connection to the Bluetooth device
::send(s, command.c_str(), command.size(), 0);


The initialization hand-shaking is outlined below. However, for a detailed overview of this call flow go to the Bluetooth website .
        Headset                 AG
| |
| AT+BRSF= |
|--------------------->| 1.
| |
| +BRSF: |
|<---------------------|
| OK |
|<---------------------|
| |
| AT+CIND=? |
|--------------------->| 2.
| |
| +CIND:... |
|<---------------------|
| OK |
|<---------------------|
| |
| AT+CIND |
|--------------------->| 3.
| |
| +CIND:... |
|<---------------------|
| OK |
|<---------------------|
| |
| AT+CMER= |
|--------------------->| 4.
| OK |
|<---------------------|
| |
| |

Note that the OK command send string as follows: "\r\nOK\r\n"

1. The Headset first sends the AG the features that it supports and in turn the AG sends back features that are supported.

Listed below are constants to define the end of the AT command (after the "=" sign)

#define HF_FEATURE_EC_ANDOR_NR                   0x01
#define HF_FEATURE_CALL_WAITING_THREEWAY_CALLING 0x02
#define HF_FEATURE_CLI_PRESENTATION 0x04
#define HF_FEATURE_VOICE_RECOGNITION_ACTIVATION 0x08
#define HF_FEATURE_REMOTE_VOLUME_CONTROL 0x10

#define AG_FEATURE_THREE_WAY_CALLING 0x01
#define AG_FEATURE_EC_ANDOR_NR 0x02
#define AG_FEATURE_VOICE_RECOGNITION 0x04
#define AG_FEATURE_INBAND_RINGTONE 0x08
#define AG_FEATURE_ATTACH_NUMBER_TO_VOICETAG 0x10
#define AG_FEATURE_REJECT_A_CALL 0x20

These values can be OR'ed together to create the support value, e.g. if we only want to support three-way calling and reject a call features the value would be 0x21. Subsequently, if the headset only supports voice recognition activation and remote volume control, it would send to the AG 0x18. Hence, the string which would be sent out from the AG to the headset would be "\r\n+BRSF:%d\r\n", where %d is equal to the features supported.

Note the new line and carriage return before and after the command. These are classic AT Command delimiters. See the Bluetooth Spec for details.

2. The next message sent from the Headset to the AG is a request by the Headset to the AG to indicate which indicators are supported by the AG. An example of the response string is as follows: "\r\n+CIND:

(\"service\",(0,1)),(\"call\",(0,1)),(\"callsetup\",(0-3))\r\n"

3. The headset then requests the status of those indicators. In our example we respond with the string "\r\n+CIND: %d,%d,%d\r\n", where the %d are defined:

first %d indicates that we have cellular service (from the listed values this could be 0-1)
second %d indicates that we're in a call: 0 for false (from the listed values this could be 0-1)
third %d indicates the current call set-up: 0 for idle (from the listed values this could be 0-3)

4. Finally, the headset sends a request to enable the indicator status update in the AG.

NOTE: From time to time, in my experience, what follows with some devices that the microphone volume information is sent after step 4.

ALSO NOTE: In the last article, we discussed the different AT commands which can be expected to be received by the AG, the additional commands not mentioned in this article are out of scope, i.e. "AT+BLDN" - last number dialed, which requires the developer to have some grasp of the RIL layer. However, from a purely simple view, sending back an "\r\nOK\r\n" to the headset for these commands will be sufficient. But, I've given enough information that if the developer does understand the RIL and has implemented telephony functionality, they will be able to piece together how processing of these AT commands can be done. Keep a look out for additional articles about RIL if interested.

OK, we're done with the initialization! WOW! that was a lot of information. Let's move on to network signaling.

Network Signaling of In-call States:


As mentioned in the second article from the Interface layer, there are a few messages which will be signaled by the Interface Module to the Handler module that need to be supported: Incoming Call, Outgoing Call, Call Connected, Call Disconnected, Call Rejected, Call Busy, Call Waiting and Call Ringing. Listed below are the AT Commands sent to the headset for the corresponding Network event to signal the Headset into a different state

Incoming Call
"\r\n+BSIR:0\r\n"
"\r\n+CIEV:3,1\r\n"

Outgoing Call
"\r\n+CIEV:3,3\r\n"

Call Connected
"\r\n+CIEV:2,1\r\n"
"\r\n+CIEV:3,0\r\n"

Call Disconnected and Call Rejected
"\r\n+CIEV:2,0\r\n"

Call Waiting
"\r\n+CCWA:\"0\",0,1\r\n"

Call Ringing
"\r\nRING\r\n"

Almost done! Let’s move to the final section--voice routing.

Services Processing:


In the last article, we talked about the Interface Module and how the Handler Module needs to support method calls from the Interface Layer. In this section, we'll go deeper into these calls to see how we can accurately process them. The commands are listed as:

Opening Audio
Closing audio
Opening a control channel
Closing a control channel
Getting/setting the mic volume
Getting/setting the speaker volume
Getting/setting the power mode

I leave it up to the reader to be able to handle the start and stop of your own AG service and also the mic/speaker and power getting and setting methods, since they are trivial.

Open/Close Control Channel: from the previous section, we learned how to connect to the Bluetooth socket to create a service level connection with the remote Bluetooth device. Hence, to handle the Open Control Channel command, we'll need to create some reliability and error checking around this socket connection. To close the control channel, all that is needed is to close the connected socket with a Winsock call. I leave it up to the reader to choose an appropriate method to shut down the socket connection.

Finally, the last piece is to open and close the audio, and this is not a trivial task.

First, we need to create a synchronous connection with the Bluetooth device. If you're lucky enough, you'll already have the libraries for creating this connection. Unfortunately, this is an article that describes a work-around if you don't have this library.

In the Windows directory, you'll find the DLL "btdrt.dll." You'll need to dynamically link to a few methods to get the audio connection. Listed below is example code to call the create synchronous connection and shut down the synchronous connection (which we'll need to route audio):

//******Note that the developer needs to call
//before these calls call ::LoadLibrary(...)
//once finished with these calls call ::FreeLibrary(...)

// Code for creating a SCO connection
typedef int (*BthCreateSCOConnectionWrapper)( BT_ADDR*, unsigned short* );
BthCreateSCOConnectionWrapper proc;
HMODULE hMod;
if(NULL == (hMod = ::GetModuleHandle(L"\\Windows\\btdrt.dll")))
{
// Log something since we can't find the module
return;
}

if(NULL == (proc = (BthCreateSCOConnectionWrapper)::GetProcAddress(hMod,
L"BthCreateSCOConnection")))
{
// Log something since we can't find the method
return;
}
//ptrBTAddr is a pointer to the Bluetooth Address--the same address we created the service level connection with
//ptrHandle is a pointer to an unsigned short which will be filled with the handle to the SCO connection
proc(ptrBTAddr, ptrHandle);


// Code for closing the SCO connection
typedef int (*BthCloseConnectionWrapper)( unsigned short );
BthCloseConnectionWrapper proc;
HMODULE hMod;
if(NULL == (hMod = ::GetModuleHandle(L"\\Windows\\btdrt.dll")))
{
// Log something since we can't find the module
return;
}

if(NULL == (proc = (BthCloseConnectionWrapper)::GetProcAddress(hMod,
L"BthCloseConnection")))
{
// Log something since we can't find the method
return;
}
// handle is the pointer to the unsigned short value that was passed in to create the SCO connection
return proc( handle );


Once we have a service level connection, a SCO connection with the Bluetooth device,
we can call the audio driver to route to the Bluetooth chip.

#define WODM_BT_SCO_AUDIO_CONTROL 500
waveOutMessage(0, WODM_BT_SCO_AUDIO_CONTROL, 0, TRUE);

To close the audio channel, first signal the audio driver to stop routing to the Bluetooth chip and close the SCO connection.
waveOutMessage(0, WODM_BT_SCO_AUDIO_CONTROL, 0, FALSE);

And that's it!

I hope that this has been an adventure. Play around with what has been shown; contact me if there is anything missing. I've omitted the getting and setting of the registry values with regards to different call states, volume settings and feature supports. However, if you're interested, take a look on the MSDN websites for registry settings related to the Audio Gateway and apply them into your architecture (and AT Command processing).

Best of luck in your Bluetooth Handsfree Adventures!

If you've read this series in its entirety drop me a line, I would love to hear what you've thought about the article.

Look for more articles related to Bluetooth and Telephony in the near feature by me!

Labels: , ,


Comments:
Hello Quan,

great article :dumpup:
I've enjoyed reading a lot :)

Could you give a hint how to redirect a2dp to wiress stereo headset?
Hi,
Thanks for the comments. A2DP is quite involved and possibly would require an additional article(s) ;-) to describe. I would like to note that A2DP streaming audio is not done through the narrow band voice on the SCO channel. In any case it's not a trivial task to undertake. What exactly are you having trouble with? Have you referred to the bluetooth spec for A2DP profile? A2DP Profile Link
Hi Quan,

thanks for the link. Great info.
I tried to set up a a2dp connection and wasn't successful so far.

I would love to read an a2dp article by you :)
Hi Quan,

It is very useful to understand , how to switch audio between device and bluetooth hands free. I am facing issue here in DOPOD 810 is I am able to route audio from device to bluetooth hands free as your suggested way, but routing from hands free to device is something funny. I just close SCO connection and send 500 (FALSE) to driver and I loose audio from either side, what it require is stop/start audio after starting it again I am able to route. Same thing is done in default phone hands free usage, it can route audio anywhere without stop/start. Only difference I am getting here is I am able to route audio from hands free to device for cell call only but If I try same for music or audio played with WaveOut API then above problem occurs. Any idea will help me lot I stuck with it.
This post has been removed by the author.
Hi Paresh,
So after closing the SCO conneciton calling
waveOutMessage(0, 500, 0, FALSE); gives you no audio?
Does the call fail or is it successful, waveOutMessage(...) usually comes with a return code. If it is successful quite possibly you need to call the RIL audio set audio method, i.e. call RIL_SetAudioDevices(HRIL, RILAUDIODEVICEINFO* ); which is from the ril.dll within the Windows system folder.
If you're having a hard time finding the definition of this method try finding the ril.h file on google.

Basically this translates to a IOControl call to the WAV driver to route audio
Hello Quan,

I am trying to switch audio from HF to device with DeviceIOControl() with IOCTL IOCTL_WAV_MESSAGE and
suggested msg value 500 with dwParam2 -> TRUE/FALSE in MMDRV_MESSAGE_PARAMS structure. I am able to route cell call audio only without STOP/START but not other audio.
hi this is good article but it would have been better for me if i could have it for linux. such as handfree profile implememntation on linuc system..

thanks but..
good one
thanks a lot
please give me some guidance for the same for linux
Hello QUAN,

It is really very good article.
I am quite n ew to this Bluetooth technology. However I am in need of Bluetooth API's for Application level on Linux so that with those API's I should be able to call driver level functions.Can you suggest me something.

Regards
Nisha

How to be a program manager

How to be a program manager
by Joel Spolsky
Monday, March 09, 2009

Having a good program manager is one of the secret formulas to making really great software. And you probably don’t have one on your team, because most teams don’t.

Charles Simonyi, the brilliant programmer who co-invented WYSIWYG word processing, dated Martha Stewart, made a billion dollars off of Microsoft stock and went into space, first tried to solve the Mythical Man Month problem of organizing really big software teams by creating one super duper überprogrammer writing the top-level functions, while handing off the implementation of the lower-level functions to a team of grunt junior-programmers as needed. They called this position program manager. Simonyi is brilliant, but this idea, not so much. Nobody wanted to be a grunt junior programmer, I guess.

For more on the history, read William Poundstone’s How Would You Move Mount Fuji?

Jabe Blumenthal, a programmer on the Mac Excel team in the late 80s, recycled the title for a different job. He had noticed that software development was getting so complicated that none of the programmers had the time to figure out how to make software that was either usable or useful. The marketing team was ranting and raving about customer needs and nobody had time to talk to them or translate their MBA-speak into actual features. There was a lot of product design stuff that took a lot of work: talking to users, running usability tests, reviewing competitive products, and thinking hard about how to make things easier, and most programmers just didn’t have the time (nor were they particularly good at it). Blumenthal took the title “Program Manager,” but reinvented the job completely.

What does a program manager do?

Henceforth, a program manager would:

  1. Design UIs
  2. Write functional specs
  3. Coordinate teams
  4. Serve as the customer advocate, and
  5. Wear Banana Republic chinos

On small products, you might just have one program manager, but on larger products, you would probably have more than one. Each can be responsible for some subset of the features. A good rule of thumb is that it takes about one program manager for every four programmers. If you’re having trouble dividing up the work, one approach I learned from Mike Conte is to divide up the product according to user activities. For example, Twitter could be divided into four user activities:

  1. Registering and getting started
  2. Posting messages and reading replies
  3. Configuring your account
  4. Searching for news


Tyler Griffin Hicks-Wright
My first program management assignment at Microsoft was on Excel, working on the user activity called “customization,” i.e., scripting and macros. The first thing I had to do was figure out what customers needed, which I did by talking to as many customers as I could until I started to get kind of bored because I kept hearing the same thing. I spent a lot of time talking to the development team to figure out what would be possible and reasonable to implement in a single 18 month release, and I spent a lot of time talking to the Visual Basic team to see if they could supply a compiler, code editor, and dialog box editor that could be used in Excel for our macro language. I also had to talk to Apple, which was developing their own universal macro language called AppleScript, and the other application teams at Microsoft, mainly Word, Access, Project, and Mail, who generally did whatever Excel did. Most of this process consisted of talking. Meetings, email, phone calls. I am scarred for life from this, and now cower in my office in fear that the phone will ring.

The second step was writing a vision statement: sort of a broad document that said, this is how Visual Basic would work in Excel, this is what some sample macros would look like, these are the major pieces we would need to build, and this is how it would solve customers’ problems. When that didn’t generate too many objections, I started working on a much more detailed spec, which explained, down to the smallest detail, how everything looked to the user.

This was a functional spec, not a technical spec, which means, all it talked about was what the user saw, not how it was implemented. (Read all about functional specs here.) A program manager doesn’t care how the development team implements things internally. As I sent chapters of the spec to Ben Waldman, the development lead, he and his team sat down and figured out what they had to do internally to make it work. They came up with a rather brilliant and very compact table that mapped the object-oriented interface I was defining onto internal Excel functions, but that really wasn’t my business. I didn’t know too much about Excel internals and didn’t really know how things should be implemented.

Truth be told, I didn’t know anything about anything. Fresh out of college, I didn’t have enough experience to develop the code, test the code, write the documentation, market the product, or do the usability tests. Luckily, Microsoft had seriously experienced gurus in each of those positions, who taught me everything I know today, and who did the real work of producing an awesome product. For example, I knew that users would want to copy the value of a spreadsheet cell into a variable:

x = [A1]

had to work. The trouble was that a cell could hold a number or a string, but Basic was early bound… you had to DIM x as an Integer, Float or String before you could use it.

Basic had to get some kind of dynamic types, but I wasn’t smart enough to figure out how to do that. Didn’t matter. Tom Corbett, a programmer on the Visual Basic team, figured out how. And thus Variants and IDispatch were born, and Basic became a dynamic language with what you kids now call “duck typing”. The point being, my job wasn’t necessarily to solve problems, it was to figure out what customers needed and make sure that programmers figured out how to solve them.

Once the spec was finished and the development team got down to work, I had two responsibilities: resolving any questions that came up about the design, and talking to all the other teams so that the developers didn’t have to. I met with the testers explaining how things were supposed to work and helping them plan how to test everything. I met with the documentation team, making sure they understood how to write a good tutorial and reference for Excel Basic. I met with localization experts to figure out a localization strategy. I sat down with marketing to explain the marketing benefits of VBA. I worked with usability experts to set up usability tests.

A program manager does go to a lot of meetings, but doesn’t produce much other than that written spec, which is why as a twerp fresh out of school I was still able to do the job. You don’t have to be a 14-year veteran programmer to work as a program manager (in fact, with 14 years of programming experience, you might know too much to be a good user advocate.)

Conflict


Tom Chi and Kevin Cheng
Lacking a program manager, your garden-variety super-smart programmer is going to come up with a completely baffling user interface that makes perfect sense IF YOU’RE A VULCAN (cf. git). The best programmers are notoriously brilliant, and have some trouble imagining what it must be like not to be able to memorize 16 one-letter command line arguments. These programmers then have a tendency to get attached to their first ideas, especially when they’ve already written the code.

One of the best things a program manager can add to the software design process is a second opinion as to how things should be designed, hopefully one that is more empathetic to those RETARDED USERS with their pesky mental feebleness requiring that an application be usable without reading the man page, writing a custom emacs-lisp function, or translating numbers into octal in your head.

A good program manager will come with her own ideas for how the UI should work, which might be better, or worse, than the developer’s idea. And then there’s a long debate. Typically, the program manager wants something simple and easy to understand for the users, featuring a telepathic user interface and a 30" screen that nonetheless fits in your pocket, while the developer wants something that is trivial to implement in code, with a command-line interface (“what’s so unusable about that?”) and Python bindings.

One of the most monumental debates I remember from the Excel 5 project was between a developer who wanted pivot tables to float on the drawing layer above the spreadsheet, and the program manager, who insisted that pivot tables live right in the cells on the spreadsheet. This debate went on for a really, really long time, and eventually, the program manager prevailed, but the final design came out much much better than any one individual’s design would have been.

To make sure that the debate happens respectfully and on a rational basis of facts, it’s absolutely critical that the program managers and developers be peers. If developers report to the program manager, at some point during the debate the program manager is going to get sick of the whole thing and just say, “OK, enough talking, now we do it my way.” When they’re peers, this can never happen. It’s a little bit like courts of law: we don’t allow a lawyer for one side to be the judge, and we work on the theory that the truth is most likely to be uncovered through a process of debate between equals. The debate can only be a fair one if neither side has an unfair advantage.

This is an important point, so if you were daydreaming about Sally in 11th grade, wondering where she is now, snap out of it. She’s a biotherapist in Scottsdale, and a Republican. Now pay attention. Programmers can’t report to program managers which means, among other things, that the development lead, or the CTO, or the CEO, can’t be the person who writes the specs.

The number one mistake most companies make is having the manager of the programmers writing the specs and designing the product. This is a mistake because the design does not get a fair trial, and is not born out of conflict and debate, so it’s not as good as it could be.

I learned this the hard way. At Fog Creek Software, I did a lot of the program management myself, and it was a constant battle to remind people that they were supposed to argue with me when I said wrong things. We’re not a big company but we are finally big enough to have real program managers now, Dan and Jason, and the programmers love arguing with them.

Of course, when programmers are peers of the program managers, the programmers tend to have the upper hand. Here’s something that has happened several times: a programmer asks me to intervene in some debate he is having with a program manager.

“Who is going to write the code?” I asked.

“I am…”

“OK, who checks things into source control?”

“Me, I guess, …”

“So what’s the problem, exactly?” I asked. “You have absolute control over the state of each and every bit in the final product. What else do you need? A tiara?”

You see, it turns out that this system puts the burden on the program manager to persuade the programmer, because at some point, the program manager runs the risk that the programmer will give up and just do whatever the heck the programmer feels like. Thus, being effective as a program manager means you have to (a) be right, and (b) earn the respect of the programmers so that they concede that you’re right.

How do you earn this respect?

It helps, as a program manager, to be pretty good at coding yourself. This is unfair. Program managers aren’t supposed to write code. But programmers tend to respect programmers a lot more than non-programmers, no matter how smart they are. It is possible to be an effective program manager without being a coder, but the burden of earning the respect of the programming team will be higher.

flip the bozo bit v. Decide that someone is a clown, and stop listening to them.

The other way to earn the programming team’s respect is to demonstrate intelligence, open-mindedness, and fairness in any debates that come up. If a program manager says dumb things, the programmer might flip the bozo bit on them. If a program manager becomes personally or emotionally attached to a certain way of doing things, to the point at which they’re being unreasonable, they’re going to lose a lot of credibility… both sides, but especially the program manager, need to be emotionally detached from the debate and willing to consider new evidence and change their opinions when the facts merit it. Finally, if a program manager is seen as playing politics, having private meetings with the boss or trying to divide-and-conquer to win a debate instead of debating on the merits, they’re going to lose a lot of trust of the programmers.

And when a program manager loses the programming team’s trust, it’s over. They’re not going to be effective. The programmers are going to tune them out and do whatever they want anyway. This leads to worse code and wasted time, since not only are you paying an ineffective program manager a salary, but that ineffective program manager is calling meetings and soaking up everybody else’s time even though they’re not really making the code any better.

Specs? Really? That’s so unagile

There are so many development organizations where specs are a monument to mindless bureaucratic paperwork that entire movements sprung up organized around the idea of not writing specs. These people are misguided. Writing a functional specification is at the very heart of agile development, because it lets you iterate rapidly over many possible designs before you write code. Compared to code, a written spec is trivial to change. The very act of writing a specification forces you to think through the design you thought you had in your head, and helps you see the flaws in it quickly so that you can iterate and try more designs. Teams that use functional specifications have better designed products, because they had the opportunity to explore more possible solutions quickly. They also write code faster, because they have a clearer picture when they start of what’s going to be needed. Functional specifications are so important one of the few hard and fast rules at Fog Creek is “No Code Without Spec.”

The exact form the functional specification takes may vary. All a functional specification has to do is explain how the program will behave. It doesn’t say anything about how the code will work internally. You start at the highest level: a vision statement, no more than one page explaining the gist of the new feature. Once that’s nailed down, you can develop storyboards… mockups of the screens showing the user’s progression through the application, with detailed notes showing how they work. For many types of functionality, especially UI-heavy functionality, once you have these storyboards, you’re done. That’s your spec. Jason Fried, you can go now.

To learn how to write good functional specifications, read my four part series. If you want to see a typical spec I wrote, you can download the full Fog Creek Copilot spec.

For more complex functionality with hidden behavior that’s not expressed in the UI storyboards, you’re going to want more details written down. In any case, the very act of writing down a spec helps you discover problems, conflicts, and design issues long before the first line of code is written, so when you do write the code, you have far fewer unexpected issues popping up which might force a rewrite or, worse, a suboptimal design.

How do you learn to be a Program Manager?

Mostly, becoming a program manager is about learning: learning about technology, learning about people, and learning how to be effective in a political organization. A good program manager combines an engineer’s approach to designing technology with a politician’s ability to build consensus and bring people together. While you’re working on that, though, there are a few books you should read:

As far as I can tell, Scott Berkun’s book Making Things Happen is the only book that’s been written that pretty much covers exactly what a program manager has to do, so start with that. Scott was a program manager on the Internet Explorer team for many years.

Another big part of the program manager’s job is user interface design. Read Steve Krug’s Don’t Make Me Think, then my own book User Interface Design for Programmers.

Finally, and I know it sounds cheesy, but Dale Carnegie’s 1937 book How to Win Friends & Influence People is actually a fantastic introduction to interpersonal skills. It’s the first book I make all the management trainees at Fog Creek read, before anything else, and they always snicker when I tell them to read it, and love it when they’re done.


Work with me, here! Fog Creek Software has great paid internships in software development for qualified college students. They’re in New York City. Free housing, lunch, and more. And you get to work on real, shipping software with the smartest developers in the business.


Want to know more?

You’re reading Joel on Software, stuffed with years and years of completely raving mad articles about software development, managing software teams, designing user interfaces, running successful software companies, and rubber duckies.



About the author.

I’m Joel Spolsky, founder of Fog Creek Software, a New York company that proves that you can treat programmers well and still be highly profitable. Programmers get private offices, free lunch, and work 40 hours a week. Customers only pay for software if they’re delighted. We make FogBugz, an enlightened project management system designed to help great teams develop brilliant software, and Fog Creek Copilot, which makes remote desktop access easy.

Install project has error "An error occurred while validating. HRESULT = '80040155'"

http://social.msdn.microsoft.com/Forums/en-US/winformssetup/thread/a0fb1a0d-ecb8-47ba-8a69-e2af82f08516/


Hi, Eric

Have you installed the software "InstallShield" on your PC and uninstalled it?

You can check the link http://support.installshield.com/kb/view.asp?articleid=q106194 provided above and do as the instruction shows.

For me, I just download the .REG file from http://support.installshield.com/kb/files/Q106194/Hotfix.zip and runs it to modify the registry file. Then the above problem is fixed.

If you did not install the software, there may be some other causes. You can first make a backup of your registry and runs the modification. If the error still exists, it means your problem is different from mine, first restore your registry and see whether there is more information about your problem.

Hope it useful!

polymorphism in C#

Maxotek Blog » C# Tutorial


The term polymorphism means multiple forms. In the world of programming, it refers to the ability of an object to exist in multiple forms. Polymorphism is one one of the key concepts of Object Oriented Programming.

Why do we need polymorphism?

Polymorphism is there to increase the complexity of the already complex world of programming. Just kidding! By using functions, we break down the program into smaller logical parts that are easier to understand, implement and thereby maintain. In this sense, the function is the smallest self sufficient (ideally) logical block of a program. As you get to know more about the real world programming, you’ll find that even these small logical blocks are often very big and rather complex. Consider the following function which is used to calculate the area of a circle from the radius entered as integer.

1

2
3
4
5
double CalcArea(int Radius)


{
double Area = Math.PI * Radius * Radius;

return Area;
}

This function can only handle integers as input. What if the Radius was in double? The function would fail in such a case. We can create another function named CalcAreaDouble to handle the input in double.

1

2
3
4
5
double CalcAreaDouble(double Radius)


{
double Area = Math.PI * Radius * Radius;

return Area;
}

While, this works, there’s something wrong about this method. The name of a function should describe(in brief) what it does and not the type of values it returns or takes as input. Both these functions do the same job, Calculate Area. Hence, they should have the same name. Thanks to Polymorphism, we can declare two functions with the same name, inside the same class.

1

2
3
4
5
6
7
8
9
10
11
double CalcArea(int Radius)


{
double Area = Math.PI * Radius * Radius;

return Area;
}

double CalcArea(double Radius)

{
double Area = Math.PI * Radius * Radius;

return Area;
}

This is called function overloading. For two functions with the same name to co-exist, they must follow certain rules:-

  • The functions must differ in either the type, the sequence or the number of input parameters i.e they must have different function signatures. The CalcArea functions have different types of parameters.

    These two functions differ in the number of parameters:-

    1
    
    2
    3
    4
    5
    6
    7
    8
    9
    int SumOfNum(int Num1, int Num2)
    

    {
    return Num1 + Num2;
    }


    int SumOfNum(int Num1, int Num2, int Num3)

    {
    return Num1 + Num2 + Num3;

    }

    While, these have different sequence:-

    1
    
    2
    3
    4
    5
    6
    7
    8
    9
    float SumOfNum(int Num1, float Num2)
    

    {
    return Num1 + Num2;
    }


    float SumOfNum(float Num1, int Num2)

    {
    return Num1 + Num2;
    }
  • Return type has no influence on function overloading. Hence, these two functions cannot co-exist:-
    1
    
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    double CalcArea(int Radius)
    

    {
    double Area = Math.PI * Radius * Radius;

    return Area;
    }

    int CalcArea(int Radius)

    {
    double Area = Math.PI * Radius * Radius;

    return Area;
    }
Static Polymorphism

Function overloading along with operator overloading which we shall look at in the next tutorial are ways of implementing static polymorphism. Static polymorphism inturn, is one of the two types of Polymorphism, the other being Dynamic polymorphism. Also called as early binding, this concept refers to an entity existing in different forms. Just like a teacher who carries on the role of a father, a husband, a comrade besides being a teacher, the functions exist in different forms, each specializing in handling one type of role. In static polymorphism, the response to a function is decided at compile time and hence it is also called early binding.

Overloading Constructors

Since constructors are also functions and can be parameterized(takes parameters as input), they can be overloaded. This allows flexibility while creating an object. Consider the Rectangle class declared in the System.Drawing namespace. It can be instantiated by either of the two methods.

Method 1: Using default constructor

In this method, the bounds of the rectangle object Rect are individually set.

1

2
3
4
5
Rectangle Rect = new Rectangle();


Rect.X = 10;
Rect.Y = 20;

Rect.Width = 30;
Rect.Height = 40;

Method 2: Using the Parametrized Constructor

Rectangle Rect = new Rectangle(10, 20, 30, 40);

Notice, how much easier this method is. The initialization in this case is handled by the constructor of the Rectangle class.

The rectangle class would have an implementation similar to this one:-

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Rectangle

{
public int X;

public int Y;
public int Width;

public int Height;

Rectangle()

{
this.X = 0;

this.Y = 0;

this.Width = 0;

this.Height = 0;

}
Rectangle(int x, int y, int width, int height)

{
this.X = x;

this.Y = y;
this.Width = width;

this.Height = height;
}

}

As you can see, the class has two overloaded constructors, one being the default constructor which takes no parameter and initializes the values of X, Y, Width and Height to 0. The other one initializes these values based on the inputs to it.

Note: This code is just to give you an idea of how the constructors are implemented. In actual fact, the rectangle class would be a lot more complex than this and would require further codes inside the constructors.


Operator Overloading

By default, out of the various C# operators, only the dot operator can be applied to user-defined types. Consider the following code snippet:-

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Program


{
static void Main(string[] args)

{
Car Car1 = new Car();

Car Car2 = new Car();


Car Car3 = Car1 + Car2;
}

}

class Car
{
public int Speed;

public string Name;
}

The compiler generates an error at line 8 saying that the operator + cannot be applied to objects of the Car class. How is the compiler supposed to know whether we want to add the speeds of two cars or concatenate their names. This is where the concept of Operator Overloading jumps in. Before we see how the + operator is prepared to work with the objects of the Car class, we need to understand how the concept works. Given below is a code snippet which accomplishes the addition in objects using a specialized method - Add().

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
using System;


class Program

{
static void Main(string[] args)

{
Car Car1 = new Car();

Car Car2 = new Car();

Car1.Speed = 30;
Car2.Speed = 70;


Car Car3 = Car.Add(Car1, Car2);

Console.WriteLine("Car3's Speed = {0}", Car3.Speed);

Console.Read();
}

}

class Car
{
public int Speed;

public string Name;

public static Car Add(Car Car1, Car Car2)

{
Car NewCar = new Car();

NewCar.Speed = Car1.Speed + Car2.Speed;

return NewCar;
}
}

The Add method is declared as static so it can be invoked at the class level as Car.Add(). It takes two parameters of the type Car as inputs. It then creates a new object of the Car class, with a speed equal to the sum of the speeds of the input objects - Car1 and Car2. Finally, the new object is returned. In this way, the addition of two objects can be accomplished. The same concept is used in Operator Overloading, except for the fact that the specialized function in their case are of the format operator .

Note: The logic inside the Add function is totally up to the the programmer.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
using System;


class Program

{
static void Main(string[] args)

{
Car Car1 = new Car();

Car Car2 = new Car();

Car1.Speed = 30;
Car2.Speed = 70;


Car Car3 = Car1 + Car2;
Console.WriteLine("Car3's Speed = {0}", Car3.Speed);

Console.Read();
}

}

class Car
{
public int Speed;

public string Name;

public static Car operator +(Car Car1, Car Car2)

{
Car NewCar = new Car();

NewCar.Speed = Car1.Speed + Car2.Speed;

return NewCar;
}
}

As you can see, the + operator utilizes a function in the background to do its neat work. Although the concept in both the cases is same, using operators allows much greater ease. The code Car Car3 = Car1 + Car2; is much closer to the real world and its easier to type, isn’t it?

Here’s a table showing which operators can/cannot be overloaded in C#.

Operators Description
+ - ! ~ ++ – These being unary operators take one operand and can be overloaded.
+ - * / % Binary arithmetic operators take two operands and can be overloaded.
== != < > <= >= Comparison operators take two parameters and can also be overloaded.
&& || These need to be overloaded indirectly using the & and |
+= -= *= /= %= Arithmetic assignment operators cannot be overloaded.
= . ?: -> new is sizeof typeof These special operators cannot be overloaded.

Note: The overloading methods must be declared as public and static.

Overloading Prefix Unary Operators

Below is the logic to accomplish unary - operator overloading. This operator changes the sign of the relative speed and is used as: -

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;


class Program

{
static void Main(string[] args)

{
Car Car1 = new Car();

Car1.RelativeSpeed = 30;
Car Car2 = -Car1;

}
}

class Car
{
public int RelativeSpeed;

public string Name;

public static Car operator -(Car CarObj)

{
Car NewCar = new Car();

NewCar.RelativeSpeed = -CarObj.RelativeSpeed;

return NewCar;
}
}

Notice, that the overloaded function takes only a single parameter. If another parameter was specified, this function would overload the binary - operator. Structures being user-defined data types can also be overloaded in this fashion. The only difference is that structures being value types, can be implemented in an easier way.

1

2
3
4
5
6
7
8
9
10
11
struct Car


{
public int RelativeSpeed;
public string Name;


public static Car operator -(Car CarObj)

{
CarObj.RelativeSpeed = -CarObj.RelativeSpeed;

return CarObj;
}
}

If the same implementation of the Operator - function was used in a class, both Car1 and Car2 would have the same RelativeSpeed of -30 after line 9. So, in the class implementation we have created a new object of the Car class.

Overloading Pre & Post Increment Operators

Unlike, C++, C# handles the Pre & Post Increment Operators by itself. Hence, we don’t need to overload them separately. Below is the implementation of the ++ operator in the Car structure.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

using System;


class Program

{
static void Main(string[] args)

{
Car Car1 = new Car();

Car1.RelativeSpeed = 30;
Car Car2 = Car1++;

Car Car3 = ++Car1;
Console.WriteLine("Relative speed of Car1 = {0}, Car2 = {1} and Car3 = {2}"

, Car1.RelativeSpeed, Car2.RelativeSpeed, Car3.RelativeSpeed);

Console.Read();
}

}

struct Car
{
public int RelativeSpeed;

public string Name;

public static Car operator ++(Car CarObj)

{
CarObj.RelativeSpeed++;;
return CarObj;

}
}

At line 9, the overloaded function for the object Car1 is invoked. The operation being post increment, Car2 gets assigned the current value of Car1 which has a relative speed of 30. After this the RelativeSpeed is incremented by 1. So, Car1 has a relative speed of 31 now. In the next line, pre increment results in the value of Car1 to be incremented by 1 before the value is assigned to Car3. Car1’s RelativeSpeed is now equal to 32. This value gets copied in Car3. So, the output of the code is: Relative speed of Car1 = 32, Car2 = 30 and Car3 = 32.

If the same logic was used in the Car Class’s overloaded function, the output would be: Relative speed of Car1 = 32, Car2 = 32 and Car3 = 32. Why does this happen? As mentioned before, the class is a reference type. Hence, when we say Car1 = Car2, it implies that Car1 now points to the same object in the memory as does Car2. In structures, the same statement would be equivalent to Copy the value of Car2 in Car1.

Arithmetic Assignment Operators

Recall that, the Arithmetic Assignment operators ( += -= *= /= %= ) cannot be overloaded. This is because A += B is equivalent to A = A + B, A -= B is equivalent to A = A - B and so on. Once, you overload the binary + operator, you can perform the += operation on the objects of the class. Same is true for the rest of the Arithmetic operators.

Logical Operators

Overloading Logical Operators is a bit tricky. Firstly, to overload the && operator the function name should be operator & and for || operator it should be operator |. Secondly, before performing these boolean short-circuit operations, the true and false operators need to be defined.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
using System;



class Program
{
static void Main(string[] args)

{
Car Car1 = new Car();

Car Car2 = new Car();

Car1.Running = true;
Car2.Running = false;


Car Car3 = Car1 && Car2;
Console.WriteLine(Car3.Running);

Console.Read();
}

}

class Car
{
public bool Running;


public static Car operator &(Car Car1, Car Car2)

{
Car NewCar = new Car();

NewCar.Running = Car1.Running && Car2.Running;

return NewCar;
}

public static bool operator true(Car CarObj)

{
return true;
}

public static bool operator false(Car CarObj)

{
return false;
}
}