[DEV] Getting Headphone Vol+/Vol- working on Android

Search This thread

loliman

Senior Member
Oct 28, 2010
76
10
Hi there,

as I mentioned in different threads, I noticed, that it is not possible to change the volume of your device via headphones (in my case Beats Tour with ControlTalk). I did some research about it and found, that Apple has got a patent on this procedure, so it is not possible to implement this in Android devices.
As is did some further research I found the basics, how it is working. As far as I understood the volume control is possible because of different resistors (three) in the cable. Each of this resistor is bound to one button (vol+/play-pause/vol-). If you press one button, the amperage is reduced because of the resistor. Now the only thing that has to be done is to interpret this amperage and decide which button was pressed. I was wondering why exactly the Android devices are not able to recognize the clicks on vol+/-. I did some research and testing again and found out, that "Headset Droid" does not even recognize, that the button were pressed, "Headset monitor" does not show any event. The funny thing is, that, if I press vol+ and vol- together, the click IS recognized, but the device interprets it as a click on the play-pause button. With this I would say, it is not a
hardware issue, it should be software, kernel, related.
I looked into the latest XE kernel (pyramidLE-crc-2.6.35) and searched for different keywords, but can’t find the exact files, where the headset control is configured (there must be any files, cause htc headphones are working like a charm with previous/play-pause/next). I've got two ideas how this could work.
  1. Add some code to recognize the button-presses and interpret them correctly. That would be the elegant, clean way.
  2. Another idea is, that we could get every headphone treated like htc headphones (vol+ would be next track, vol- last track). There is an app to change the htc previous/next buttons to work like vol+/- so that would be enough. That would be the "easy" way, but more dirty.
Some more information: I did not change anything in the kernel and never compiled the kernel, so I can’t say, if I'm on the right track.

Here is what I found in the kernelfiles so far:

\arch\arm\mach-msm //it seems, that there are some amperages are configured here, but it does not seem to be the right ones...
Code:
/* HTC OTHC Driver - BEGIN */
[...]
static struct hsed_bias_config htc_headset_othc_bias_config = {
	.othc_headset = OTHC_HEADSET_NO,
	.othc_lowcurr_thresh_uA = 100,
	.othc_highcurr_thresh_uA = 500,
	.othc_hyst_prediv_us = 3000,
	.othc_period_clkdiv_us = 3000,
	.othc_hyst_clk_us = 45000,
	.othc_period_clk_us = 6000,
	.othc_wakeup = 1,
};
[...]

\arch\arm\mach-msm\htc_headset_mgr.c //here’s the headsetmanager, the type of headphone seems to be set here
Code:
[...]
	switch (hi->hs_35mm_type) {
	case HEADSET_UNPLUG:
		state = "headset_unplug";
		break;
	case HEADSET_NO_MIC:
		state = "headset_no_mic";
		break;
	case HEADSET_MIC:
		state = "headset_mic";
		break;
	case HEADSET_METRICO:
		state = "headset_metrico";
		break;
	case HEADSET_UNKNOWN_MIC:
		state = "headset_unknown_mic";
		break;
	case HEADSET_TV_OUT:
		state = "headset_tv_out";
		break;
	case HEADSET_UNSTABLE:
		state = "headset_unstable";
		break;
	case HEADSET_BEATS:
		state = "headset_beats";
		break;
	case HEADSET_BEATS_SOLO:
		state = "headset_beats_solo";
		break;
	case HEADSET_INDICATOR:
		state = "headset_indicator";
		break;
	default:
		state = "error_state";
	}
[...]

As I never worked in kernel before (I am experienced in C) I don’t know whether I'm doing it wrong or not. Some help and any suggestions would be helpful, perhaps we can get this working.

I hope you understand my thoughts and problems, it's hard to express them in german and it's even harder in englisch :D

Kind regards,
 
Last edited:

tvkanters

Member
Mar 5, 2011
9
11
tvkdevelopment.com
Dev of Headset Droid here.
I'd say it's a cool initiative to try to make the volume buttons work. The last time I researched the issue, it seemed to be a hardware problem at the 3.5mm plug. My guess for why clicking both vol+ and vol- generates a play/pause, is that by pressing them both, the play/pause button might actually be pressed. Of course, I could be wrong about this.

Either way, to give you an idea of what to aim for: Catching the volume button clicks globally is a lot harder than to catch the next and previous buttons in Android. Headset Droid doesn't support vol+ or vol- presses, but will only show play/pause, next and previous in the headset monitor.
If you somehow manage to get the volume buttons working as they should, the volume level should change as if you pressed the volume buttons on your device.
 

exxpired

Senior Member
Aug 15, 2010
654
186
Watford
Headset button controller app works fine with beats. My set up is long press to change track on either button and short press to increase/decrease volume :)

Sent from my HTC Sensation XE with Beats Audio
 
Last edited:

loliman

Senior Member
Oct 28, 2010
76
10
Dev of Headset Droid here.
I'd say it's a cool initiative to try to make the volume buttons work. The last time I researched the issue, it seemed to be a hardware problem at the 3.5mm plug. My guess for why clicking both vol+ and vol- generates a play/pause, is that by pressing them both, the play/pause button might actually be pressed. Of course, I could be wrong about this.

Either way, to give you an idea of what to aim for: Catching the volume button clicks globally is a lot harder than to catch the next and previous buttons in Android. Headset Droid doesn't support vol+ or vol- presses, but will only show play/pause, next and previous in the headset monitor.
If you somehow manage to get the volume buttons working as they should, the volume level should change as if you pressed the volume buttons on your device.

nice to have you here! ;)
i thought the same about pressing vol+ and - at the same time, bit i took a close look, the button itself (i mean the part of the button that you are actually seeing) is not moving while pressing both.
whats the difference between the htc buttons (next/previous) and, lets call them, "apple" ones (vol+/-). I read about how 3.5mm plugs are technically working and I cant imagine, that htc headphones are working THAT different from "apples" version. I had a nice article about that, I will search for it and post it here.

//EDIT: Can't find it anywhere... read the first post, I tried to explain it, hope you understand how it works. :p
 
Last edited:

loliman

Senior Member
Oct 28, 2010
76
10
Just some small information (sorry for double-post): Found this - reverse engineering apple headphones - and this today - reverese engineering htc headphones. It seems that it is indeed a voltage drop, that lets the system recognize the button-presses in BOTH headphones. I'll have a closer look in the evening when I'm home from work and will compare the results, if it’s similar, we might get it working by a software patch. :)
 
Last edited:
  • Like
Reactions: blaspheme000

tvkanters

Member
Mar 5, 2011
9
11
tvkdevelopment.com
The second link is broken for me, but if the plug plays no role in it as you suggest, it does sound a lot more promising. : )

I'm still not convinced about pressing the two volume buttons not trigging the play/pause button, though. I've got some earphones with 'Apple' volume buttons as well (a-JAYS Four) and I can't reproduce what you're describing on my Nexus One running CM7.1.

I'll be looking forward to hearing what you find out later on. : )
 

loliman

Senior Member
Oct 28, 2010
76
10
Again some news and could be, that I need some help... :rolleyes:
As far as I can see, the current cycle in both headphones (apple and htc) are exactly the same, except for the different resistors, which would explain the different voltages.
Regarding code I'm stuck at this function in \arch\arm\mach-msm\htc_headset_mgr.c
Code:
static void button_35mm_work_func(struct work_struct *work)
{
	int key;
	struct button_work *works;

	wake_lock_timeout(&hi->hs_wake_lock, HS_WAKE_LOCK_TIMEOUT);

	HS_DBG();
[B]
	works = container_of(work, struct button_work, key_work.work);
	hi->key_level_flag = works->key_code;[/B]

	if (hi->key_level_flag) {
		switch (hi->key_level_flag) {
		case 1:
			key = HS_MGR_KEYCODE_MEDIA;
			break;
		case 2:
			key = HS_MGR_KEYCODE_BACKWARD;
			break;
		case 3:
			key = HS_MGR_KEYCODE_FORWARD;
			break;
		default:
			HS_LOG("3.5mm RC: WRONG Button Pressed");
			kfree(works);
			return;
		}
		headset_button_event(1, key);
	} else { /* key release */
		if (atomic_read(&hi->btn_state))
			headset_button_event(0, atomic_read(&hi->btn_state));
		else
			HS_LOG("3.5mm RC: WRONG Button Release");
	}

	kfree(works);
}
I tried to roll back the events that are triggered by a keypress and the different functions are (from the first to the last):
??-->button_35mm_work_func-->headset_button_event-->button_pressed-->??
But I does not understand how button_35mm_work_func "does know" which button has been pressed... I'm stuck there for the moment :x
I do not want to know whats coming after button_pressed, cause I think its enough to get the button working as next/previous for the moment. Then we can look into volume control.
If any kernel-dev would be helping it should be easier, as I said, I never worked with kernels before, still learning. :D
So far.
 

jeebsion

Member
Apr 13, 2010
6
1
loliman,

I just found this thread .. how is it coming? Any slightest light here? like at least a punch in volt signal and all?
 

loliman

Senior Member
Oct 28, 2010
76
10
Forget to tell you... I'm at vacation till tomorrow (friday). I found some more things and compiled a Kernel with some changes. I'll tell you when I'm back home. ;)

Sent from my HTC Sensation XE with Beats Audio using XDA App
 
  • Like
Reactions: jeebsion

loliman

Senior Member
Oct 28, 2010
76
10
Some bad news... I tried some things yesterday wich didnt worked and now I accidently deleted my virtual machine (linux...) :D I'll creat a new one and try some more things (I've got some more ideas) tomorrow, I'll post more recently in the next days, sorry, had been busy ;)
 

cbarrick

Member
Jan 15, 2010
6
7
Athens, GA
Any news? I'd love to help, though I've got no experience with C or kernel level code. How are you reading the headphone amperage? What about just writing a headphone button driver from scratch? I was just thinking simply detect an amperage change and pass that info up to handle everything else in the Android framework, but I'm not sure exactly how to do that :p. How have you gone about this, and if I were to experiment, where should I start?
 

bharath23

New member
Oct 9, 2012
2
0
Its been a while but I am wondering if any things changed with regards to this. I got a Klipsch S4i as a gift and I know it wont work on my Droid X2, hate to give away these headphones they sound so sweet.
 

Shano56

Senior Member
Oct 21, 2011
1,439
557
I was hoping for a fix so I can use the volume control on my Sennheisers, but then my gf's cat chewed through them so now I can be patient :)

Sent from my Nexus 4 using Tapatalk 2
 
Jan 23, 2014
7
2
Beats volume boton

Some bad news... I tried some things yesterday wich didnt worked and now I accidently deleted my virtual machine (linux...) :D I'll creat a new one and try some more things (I've got some more ideas) tomorrow, I'll post more recently in the next days, sorry, had been busy ;)

loliman, what happen with this research? did you finf something more? or did you just quit ? im asking because im trying to do the same....
 

Adam013s

Member
Aug 24, 2014
5
0
tilburg
I have ludacris

Hey anything new found i found this problem with my sould by ludacris sl49 i bought them for 80 euro and they didn't even post a sticker on the goddamn box or somewhere visible they ts all should just make universal drivers for earbuds and headphones this anoyes me only the middle button works for play and pause stupid bull****
 

Mofo Jones

New member
Dec 6, 2014
1
0
From what I've seen it appears to be a patent issue with apple being the bad guys. I may be wrong though.
 

Top Liked Posts

  • There are no posts matching your filters.
  • 5
    Hi there,

    as I mentioned in different threads, I noticed, that it is not possible to change the volume of your device via headphones (in my case Beats Tour with ControlTalk). I did some research about it and found, that Apple has got a patent on this procedure, so it is not possible to implement this in Android devices.
    As is did some further research I found the basics, how it is working. As far as I understood the volume control is possible because of different resistors (three) in the cable. Each of this resistor is bound to one button (vol+/play-pause/vol-). If you press one button, the amperage is reduced because of the resistor. Now the only thing that has to be done is to interpret this amperage and decide which button was pressed. I was wondering why exactly the Android devices are not able to recognize the clicks on vol+/-. I did some research and testing again and found out, that "Headset Droid" does not even recognize, that the button were pressed, "Headset monitor" does not show any event. The funny thing is, that, if I press vol+ and vol- together, the click IS recognized, but the device interprets it as a click on the play-pause button. With this I would say, it is not a
    hardware issue, it should be software, kernel, related.
    I looked into the latest XE kernel (pyramidLE-crc-2.6.35) and searched for different keywords, but can’t find the exact files, where the headset control is configured (there must be any files, cause htc headphones are working like a charm with previous/play-pause/next). I've got two ideas how this could work.
    1. Add some code to recognize the button-presses and interpret them correctly. That would be the elegant, clean way.
    2. Another idea is, that we could get every headphone treated like htc headphones (vol+ would be next track, vol- last track). There is an app to change the htc previous/next buttons to work like vol+/- so that would be enough. That would be the "easy" way, but more dirty.
    Some more information: I did not change anything in the kernel and never compiled the kernel, so I can’t say, if I'm on the right track.

    Here is what I found in the kernelfiles so far:

    \arch\arm\mach-msm //it seems, that there are some amperages are configured here, but it does not seem to be the right ones...
    Code:
    /* HTC OTHC Driver - BEGIN */
    [...]
    static struct hsed_bias_config htc_headset_othc_bias_config = {
    	.othc_headset = OTHC_HEADSET_NO,
    	.othc_lowcurr_thresh_uA = 100,
    	.othc_highcurr_thresh_uA = 500,
    	.othc_hyst_prediv_us = 3000,
    	.othc_period_clkdiv_us = 3000,
    	.othc_hyst_clk_us = 45000,
    	.othc_period_clk_us = 6000,
    	.othc_wakeup = 1,
    };
    [...]

    \arch\arm\mach-msm\htc_headset_mgr.c //here’s the headsetmanager, the type of headphone seems to be set here
    Code:
    [...]
    	switch (hi->hs_35mm_type) {
    	case HEADSET_UNPLUG:
    		state = "headset_unplug";
    		break;
    	case HEADSET_NO_MIC:
    		state = "headset_no_mic";
    		break;
    	case HEADSET_MIC:
    		state = "headset_mic";
    		break;
    	case HEADSET_METRICO:
    		state = "headset_metrico";
    		break;
    	case HEADSET_UNKNOWN_MIC:
    		state = "headset_unknown_mic";
    		break;
    	case HEADSET_TV_OUT:
    		state = "headset_tv_out";
    		break;
    	case HEADSET_UNSTABLE:
    		state = "headset_unstable";
    		break;
    	case HEADSET_BEATS:
    		state = "headset_beats";
    		break;
    	case HEADSET_BEATS_SOLO:
    		state = "headset_beats_solo";
    		break;
    	case HEADSET_INDICATOR:
    		state = "headset_indicator";
    		break;
    	default:
    		state = "error_state";
    	}
    [...]

    As I never worked in kernel before (I am experienced in C) I don’t know whether I'm doing it wrong or not. Some help and any suggestions would be helpful, perhaps we can get this working.

    I hope you understand my thoughts and problems, it's hard to express them in german and it's even harder in englisch :D

    Kind regards,
    3
    Again some news and could be, that I need some help... :rolleyes:
    As far as I can see, the current cycle in both headphones (apple and htc) are exactly the same, except for the different resistors, which would explain the different voltages.
    Regarding code I'm stuck at this function in \arch\arm\mach-msm\htc_headset_mgr.c
    Code:
    static void button_35mm_work_func(struct work_struct *work)
    {
    	int key;
    	struct button_work *works;
    
    	wake_lock_timeout(&hi->hs_wake_lock, HS_WAKE_LOCK_TIMEOUT);
    
    	HS_DBG();
    [B]
    	works = container_of(work, struct button_work, key_work.work);
    	hi->key_level_flag = works->key_code;[/B]
    
    	if (hi->key_level_flag) {
    		switch (hi->key_level_flag) {
    		case 1:
    			key = HS_MGR_KEYCODE_MEDIA;
    			break;
    		case 2:
    			key = HS_MGR_KEYCODE_BACKWARD;
    			break;
    		case 3:
    			key = HS_MGR_KEYCODE_FORWARD;
    			break;
    		default:
    			HS_LOG("3.5mm RC: WRONG Button Pressed");
    			kfree(works);
    			return;
    		}
    		headset_button_event(1, key);
    	} else { /* key release */
    		if (atomic_read(&hi->btn_state))
    			headset_button_event(0, atomic_read(&hi->btn_state));
    		else
    			HS_LOG("3.5mm RC: WRONG Button Release");
    	}
    
    	kfree(works);
    }
    I tried to roll back the events that are triggered by a keypress and the different functions are (from the first to the last):
    ??-->button_35mm_work_func-->headset_button_event-->button_pressed-->??
    But I does not understand how button_35mm_work_func "does know" which button has been pressed... I'm stuck there for the moment :x
    I do not want to know whats coming after button_pressed, cause I think its enough to get the button working as next/previous for the moment. Then we can look into volume control.
    If any kernel-dev would be helping it should be easier, as I said, I never worked with kernels before, still learning. :D
    So far.
    1
    Just some small information (sorry for double-post): Found this - reverse engineering apple headphones - and this today - reverese engineering htc headphones. It seems that it is indeed a voltage drop, that lets the system recognize the button-presses in BOTH headphones. I'll have a closer look in the evening when I'm home from work and will compare the results, if it’s similar, we might get it working by a software patch. :)
    1
    Forget to tell you... I'm at vacation till tomorrow (friday). I found some more things and compiled a Kernel with some changes. I'll tell you when I'm back home. ;)

    Sent from my HTC Sensation XE with Beats Audio using XDA App