('Android蓝牙AVRCP功能的实现作者:MacroLiuAVRCP的按键定义:\\sdk\\emulator\\keymaps\\AVRCP.klkey200MEDIA_PLAY_PAUSEWAKEkey201MEDIA_PLAY_PAUSEWAKEkey166MEDIA_STOPWAKEkey163MEDIA_NEXTWAKEkey165MEDIA_PREVIOUSWAKEkey168MEDIA_REWINDWAKEkey208MEDIA_FAST_FORWARDWAKEBCM(broadcom)宏定义需要打开:BOARD_HAVE_BLUETOOTH_BCM:=trueBT音频控制的代码external\\bluetooth\\bluez\\audio\\control.c(1)按键的MAPstaticstruct{constcharname;uint8_tavrcp;uint16_tuinput;}key_map[]={{"PLAY",PLAY_OP,KEY_PLAYCD},{"STOP",STOP_OP,KEY_STOPCD},{"PAUSE",PAUSE_OP,KEY_PAUSECD},{"FORWARD",FORWARD_OP,KEY_NEXTSONG},{"BACKWARD",BACKWARD_OP,KEY_PREVIOUSSONG},{"REWIND",REWIND_OP,KEY_REWIND},{"FASTFORWARD",FAST_FORWARD_OP,KEY_FASTFORWARD},{NULL}};(2)按键处理staticvoidhandle_panel_passthrough(structcontrolcontrol,{…for(i=0;key_map[i].name!=NULL;i++){uint8_tkey_quirks;if((operands[0]&0x7F)!=key_map[i].avrcp)continue;DBG("AVRCP:%s%s",key_map[i].name,status);key_quirks=control->key_quirks[key_map[i].avrcp];if(key_quirks&QUIRK_NO_RELEASE){if(!pressed){DBG("AVRCP:Ignoringrelease");break;}DBG("AVRCP:treatingkeypressaspress+release");send_key(control->uinput,key_map[i].uinput,1);send_key(control->uinput,key_map[i].uinput,0);break;}send_key(control->uinput,key_map[i].uinput,pressed);break;}…}HCIDUMP数据分析以Sony耳机DRC-BT15为例#adbshell#hcidump–X左键:>ACLdata:handle12flags0x02dlen12L2CAP(d):cid0x0042len8[psm0]0000:30110e00487c4c000...HL.HCIEvent:MaxSlotsChange(0x1b)plen30000:0c0005...>HCIEvent:ModeChange(0x14)plen60000:000c00000000......>HCIEvent:CommandStatus(0x0f)plen40000:0c010408....>ACLdata:handle12flags0x02dlen12L2CAP(d):cid0x0042len8[psm0]0000:40110e00487ccc00@...H?HCIEvent:NumberofCompletedPackets(0x13)plen50000:010c000200.....播放/暂停:>ACLdata:handle12flags0x02dlen12L2CAP(d):cid0x0042len8[psm0]0000:50110e00487c4b00P...HK.ACLdata:handle12flags0x02dlen12L2CAP(d):cid0x0042len8[psm0]0000:60110e00487ccb00`...H?HCIEvent:NumberofCompletedPackets(0x13)plen50000:010c000200.....右键:>ACLdata:handle12flags0x02dlen12L2CAP(d):cid0x0042len8[psm0]0000:70110e00487c4600p...HF.ACLdata:handle12flags0x02dlen12L2CAP(d):cid0x0042len8[psm0]0000:80110e00487cc600....H?HCIEvent:NumberofCompletedPackets(0x13)plen50000:010c000200.....>HCIEvent:MaxSlotsChange(0x1b)plen30000:0c0001...>HCIEvent:ModeChange(0x14)plen60000:000c0002c800....?然后将control.c的日志打印出来:按一次”“播放/暂停键”:D/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=46对应PAUSE_OPD/ACRVP(237):key_quirks=0,pressed=1按键按下D/ACRVP(237):control->uinput=fffffffe,send_key=201对应MEDIA_PLAY_PAUSED/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=c6(=0x46|0x80表示按键释放了)D/ACRVP(237):key_quirks=0,pressed=0按键释放D/ACRVP(237):control->uinput=fffffffe,send_key=201对应MEDIA_PLAY_PAUSE再按一次”“播放/暂停键”:D/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=44对应PLAY_OPD/ACRVP(237):key_quirks=0,pressed=1按键按下D/ACRVP(237):control->uinput=fffffffe,send_key=200对应MEDIA_PLAY_PAUSED/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=c4D/ACRVP(237):key_quirks=0,pressed=0按键释放D/ACRVP(237):control->uinput=fffffffe,send_key=200对应MEDIA_PLAY_PAUSEnextkey:D/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=4b对应FORWARD_OPD/ACRVP(237):key_quirks=0,pressed=1D/ACRVP(237):control->uinput=fffffffe,send_key=163对应MEDIA_NEXTD/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=cbD/ACRVP(237):key_quirks=0,pressed=0D/ACRVP(237):control->uinput=fffffffe,send_key=163prevkey:D/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=4c对应BACKWARD_OPD/ACRVP(237):key_quirks=0,pressed=1D/ACRVP(237):control->uinput=fffffffe,send_key=165对应D/ACRVP(237):---handle_panel_passthrough----D/ACRVP(237):operands[0]=ccD/ACRVP(237):key_quirks=0,pressed=0D/ACRVP(237):control->uinput=fffffffe,send_key=165MEDIA_PREVIOUS从上面可以看到bluetooth的协议栈blueZ是没有问题的将frameworks\\base\\libs\\ui\\EventHub.cpp的LOG打开,只能看到了control.c的日志,EventHub的getEvent完全不响应观察所有log日志发现,openDevice里也没有装载AVRCP.kl初步判断event有问题event分析:$adbshell#cd/proc/bus/input#catdevicescatdevices#catdevicescatdevicesI:Bus=0019Vendor=0001Product=0001Version=0001参考s3c-keypad.cN:Name="s3c-keypad"input_dev->name=DEVICE_NAME;P:Phys=s3c-keypad/input0input_dev->phys="s3c-keypad/input0";S:Sysfs=/devices/virtual/input/input0virtual的?U:Uniq=H:Handlers=event0B:EV=3B:KEY=40004000I:Bus=0019Vendor=0001Product=0001Version=0100参考vpad_buttons.cN:Name="s3c-eintkey"input->name=pdev->name,gpio_keys_device_driver.name="s3c-eintkey",P:Phys=gpio-keys/input0input->phys="gpio-keys/input0"S:Sysfs=/devices/platform/s3c-eintkey/input/input1为什么这里是platform目录?U:Uniq=H:Handlers=event1B:EV=3B:KEY=100000000I:Bus=0018Vendor=0000Product=0000Version=0000参考amri_ts.cN:Name="amri_ts"amri_ts_driver.name="amri_ts"P:Phys=没有定义S:Sysfs=/devices/platform/s3c2440-i2c.0/i2c-0/0-0033/input/input2为什么这里是platform目录?U:Uniq=H:Handlers=event2B:EV=bB:KEY=4000000040000800400010000B:ABS=26500000I:Bus=0000Vendor=0000Product=0000Version=0000N:Name="ecompass_data"P:Phys=S:Sysfs=/devices/virtual/input/input3U:Uniq=H:Handlers=event3B:EV=9B:ABS=307bf从上面可以看到,完全没有AVRCP的event。解决办法:Kernel$makemenuconfigCONFIG_INPUT_UINPUT解决后的状况:$adbshell#cd/proc/bus/input#catdevices显示增加了一个eventI:Bus=0005Vendor=0000Product=0000Version=0000N:Name="AVRCP"P:Phys=S:Sysfs=/devices/virtual/input/input4U:Uniq=H:Handlers=event4B:EV=100007B:KEY=1030016800000B:REL=0看openDevice的信息:D/EventHub(84):EventHub::readNotifynfd:87D/EventHub(84):Openingdevice:/dev/input/event4D/EventHub(84):Gettingkeys...D/EventHub(84):Gettingabsolutecontrollers...D/EventHub(84):keylayoutFilename=/system/usr/keylayout/AVRCP.klI/EventHub(84):Newkeyboard:device->id=0x10003devname=\'AVRCP\'propName=\'hw.keyboards.65539.devname\'keylayout=\'/system/usr/keylayout/AVRCP.kl\'I/EventHub(84):Newdevice:path=/dev/input/event4name=AVRCPid=0x10003(of0x4)index=4fd=196classes=0x1D/EventHub(84):Addingdevice/dev/input/event40x361800at4,id=3,classes=0x1D/EventHub(84):Reportingdeviceopened:id=0x10003,name=/dev/input/event4按键时也可以看到EventHub的信息了:Log如下:D/ACRVP(236):---handle_panel_passthrough----D/ACRVP(236):operands[0]=46D/ACRVP(236):key_quirks=0,pressed=1D/ACRVP(236):control->uinput=14,send_key=201control.c发出201号键,按键按下了D/EventHub(84):/dev/input/event4got:t0=937,t1=582930,type=1,code=201,v=1表示从event4得到201号键MEDIA_PLAY_PAUSED/EventHub(84):iev.code=201keyCode=85flags=0x00000001err=0D/EventHub(84):/dev/input/event4got:t0=937,t1=600241,type=0,code=0,v=0D/AudioHardware(61):AudioStreamOutALSA::setParameters()routing=0D/ACRVP(236):---handle_panel_passthrough----D/ACRVP(236):operands[0]=c6D/ACRVP(236):key_quirks=0,pressed=0D/ACRVP(236):control->uinput=14,send_key=c9D/EventHub(84):/dev/input/event4got:t0=937,t1=664391,type=1,code=201,v=0control.c发出201号键,按键释放了D/EventHub(84):iev.code=201keyCode=85flags=0x00000001err=0D/EventHub(84):/dev/input/event4got:t0=937,t1=664406,type=0,code=0,v=0D/A2DP(61):a2dp_stopD/A2DP(61):bluetooth_stopE/BluetoothEventLoop.cpp(84):event_filter:Receivedsignalorg.bluez.AudioSink:Stoppedfrom/org/bluez/236/hci0/dev_00_1D_BA_A5_D8_1CE/BluetoothEventLoop.cpp(84):event_filter:Receivedsignalorg.bluez.AudioSink:PropertyChangedfrom/org/bluez/236/hci0/dev_00_1D_BA_A5_D8_1CE/BluetoothEventLoop.cpp(84):event_filter:Receivedsignalorg.bluez.AudioSink:PropertyChangedfrom/org/bluez/236/hci0/dev_00_1D_BA_A5_D8_1CV/BluetoothEventRedirector(244):Receivedandroid.bluetooth.a2dp.action.SINK_STATE_CHANGEDD/CachedBluetoothDevice(244):onProfileStateChanged:profileA2DPnewProfileState2D/BluetoothA2dpService(84):A2DPstate:device:00:1D:BA:A5:D8:1CState:4->2D/A2DP(61):ReceivedBT_RESPONSE-BT_STOP_STREAMD/dalvikvm(285):GC_EXPLICITfreed87K,56%free2640K/5895K,external1625K/2137K,paused75msMacroLiu2011-08-01',)