avrcp.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2011 Intel Corporation.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <inttypes.h>
  21. #include "parser.h"
  22. /* ctype entries */
  23. #define AVC_CTYPE_CONTROL 0x0
  24. #define AVC_CTYPE_STATUS 0x1
  25. #define AVC_CTYPE_SPECIFIC_INQUIRY 0x2
  26. #define AVC_CTYPE_NOTIFY 0x3
  27. #define AVC_CTYPE_GENERAL_INQUIRY 0x4
  28. #define AVC_CTYPE_NOT_IMPLEMENTED 0x8
  29. #define AVC_CTYPE_ACCEPTED 0x9
  30. #define AVC_CTYPE_REJECTED 0xA
  31. #define AVC_CTYPE_IN_TRANSITION 0xB
  32. #define AVC_CTYPE_STABLE 0xC
  33. #define AVC_CTYPE_CHANGED 0xD
  34. #define AVC_CTYPE_INTERIM 0xF
  35. /* subunit type */
  36. #define AVC_SUBUNIT_MONITOR 0x00
  37. #define AVC_SUBUNIT_AUDIO 0x01
  38. #define AVC_SUBUNIT_PRINTER 0x02
  39. #define AVC_SUBUNIT_DISC 0x03
  40. #define AVC_SUBUNIT_TAPE 0x04
  41. #define AVC_SUBUNIT_TURNER 0x05
  42. #define AVC_SUBUNIT_CA 0x06
  43. #define AVC_SUBUNIT_CAMERA 0x07
  44. #define AVC_SUBUNIT_PANEL 0x09
  45. #define AVC_SUBUNIT_BULLETIN_BOARD 0x0a
  46. #define AVC_SUBUNIT_CAMERA_STORAGE 0x0b
  47. #define AVC_SUBUNIT_VENDOR_UNIQUE 0x0c
  48. #define AVC_SUBUNIT_EXTENDED 0x1e
  49. #define AVC_SUBUNIT_UNIT 0x1f
  50. /* opcodes */
  51. #define AVC_OP_VENDORDEP 0x00
  52. #define AVC_OP_UNITINFO 0x30
  53. #define AVC_OP_SUBUNITINFO 0x31
  54. #define AVC_OP_PASSTHROUGH 0x7c
  55. /* operands in passthrough commands */
  56. #define AVC_PANEL_VOLUME_UP 0x41
  57. #define AVC_PANEL_VOLUME_DOWN 0x42
  58. #define AVC_PANEL_MUTE 0x43
  59. #define AVC_PANEL_PLAY 0x44
  60. #define AVC_PANEL_STOP 0x45
  61. #define AVC_PANEL_PAUSE 0x46
  62. #define AVC_PANEL_RECORD 0x47
  63. #define AVC_PANEL_REWIND 0x48
  64. #define AVC_PANEL_FAST_FORWARD 0x49
  65. #define AVC_PANEL_EJECT 0x4a
  66. #define AVC_PANEL_FORWARD 0x4b
  67. #define AVC_PANEL_BACKWARD 0x4c
  68. /* Packet types */
  69. #define AVRCP_PACKET_TYPE_SINGLE 0x00
  70. #define AVRCP_PACKET_TYPE_START 0x01
  71. #define AVRCP_PACKET_TYPE_CONTINUING 0x02
  72. #define AVRCP_PACKET_TYPE_END 0x03
  73. /* pdu ids */
  74. #define AVRCP_GET_CAPABILITIES 0x10
  75. #define AVRCP_LIST_PLAYER_ATTRIBUTES 0x11
  76. #define AVRCP_LIST_PLAYER_VALUES 0x12
  77. #define AVRCP_GET_CURRENT_PLAYER_VALUE 0x13
  78. #define AVRCP_SET_PLAYER_VALUE 0x14
  79. #define AVRCP_GET_PLAYER_ATTRIBUTE_TEXT 0x15
  80. #define AVRCP_GET_PLAYER_VALUE_TEXT 0x16
  81. #define AVRCP_DISPLAYABLE_CHARSET 0x17
  82. #define AVRCP_CT_BATTERY_STATUS 0x18
  83. #define AVRCP_GET_ELEMENT_ATTRIBUTES 0x20
  84. #define AVRCP_GET_PLAY_STATUS 0x30
  85. #define AVRCP_REGISTER_NOTIFICATION 0x31
  86. #define AVRCP_REQUEST_CONTINUING 0x40
  87. #define AVRCP_ABORT_CONTINUING 0x41
  88. #define AVRCP_SET_ABSOLUTE_VOLUME 0x50
  89. #define AVRCP_SET_ADDRESSED_PLAYER 0x60
  90. #define AVRCP_SET_BROWSED_PLAYER 0x70
  91. #define AVRCP_GET_FOLDER_ITEMS 0x71
  92. #define AVRCP_CHANGE_PATH 0x72
  93. #define AVRCP_GET_ITEM_ATTRIBUTES 0x73
  94. #define AVRCP_PLAY_ITEM 0x74
  95. #define AVRCP_SEARCH 0x80
  96. #define AVRCP_ADD_TO_NOW_PLAYING 0x90
  97. #define AVRCP_GENERAL_REJECT 0xA0
  98. /* notification events */
  99. #define AVRCP_EVENT_PLAYBACK_STATUS_CHANGED 0x01
  100. #define AVRCP_EVENT_TRACK_CHANGED 0x02
  101. #define AVRCP_EVENT_TRACK_REACHED_END 0x03
  102. #define AVRCP_EVENT_TRACK_REACHED_START 0x04
  103. #define AVRCP_EVENT_PLAYBACK_POS_CHANGED 0x05
  104. #define AVRCP_EVENT_BATT_STATUS_CHANGED 0x06
  105. #define AVRCP_EVENT_SYSTEM_STATUS_CHANGED 0x07
  106. #define AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED 0x08
  107. #define AVRCP_EVENT_NOW_PLAYING_CONTENT_CHANGED 0x09
  108. #define AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED 0x0a
  109. #define AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED 0x0b
  110. #define AVRCP_EVENT_UIDS_CHANGED 0x0c
  111. #define AVRCP_EVENT_VOLUME_CHANGED 0x0d
  112. /* error statuses */
  113. #define AVRCP_STATUS_INVALID_COMMAND 0x00
  114. #define AVRCP_STATUS_INVALID_PARAMETER 0x01
  115. #define AVRCP_STATUS_NOT_FOUND 0x02
  116. #define AVRCP_STATUS_INTERNAL_ERROR 0x03
  117. #define AVRCP_STATUS_SUCCESS 0x04
  118. #define AVRCP_STATUS_UID_CHANGED 0x05
  119. #define AVRCP_STATUS_INVALID_DIRECTION 0x07
  120. #define AVRCP_STATUS_NOT_DIRECTORY 0x08
  121. #define AVRCP_STATUS_DOES_NOT_EXIST 0x09
  122. #define AVRCP_STATUS_INVALID_SCOPE 0x0a
  123. #define AVRCP_STATUS_OUT_OF_BOUNDS 0x0b
  124. #define AVRCP_STATUS_IS_DIRECTORY 0x0c
  125. #define AVRCP_STATUS_MEDIA_IN_USE 0x0d
  126. #define AVRCP_STATUS_NOW_PLAYING_LIST_FULL 0x0e
  127. #define AVRCP_STATUS_SEARCH_NOT_SUPPORTED 0x0f
  128. #define AVRCP_STATUS_SEARCH_IN_PROGRESS 0x10
  129. #define AVRCP_STATUS_INVALID_PLAYER_ID 0x11
  130. #define AVRCP_STATUS_PLAYER_NOT_BROWSABLE 0x12
  131. #define AVRCP_STATUS_PLAYER_NOT_ADDRESSED 0x13
  132. #define AVRCP_STATUS_NO_VALID_SEARCH_RESULTS 0x14
  133. #define AVRCP_STATUS_NO_AVAILABLE_PLAYERS 0x15
  134. #define AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED 0x16
  135. /* player attributes */
  136. #define AVRCP_ATTRIBUTE_ILEGAL 0x00
  137. #define AVRCP_ATTRIBUTE_EQUALIZER 0x01
  138. #define AVRCP_ATTRIBUTE_REPEAT_MODE 0x02
  139. #define AVRCP_ATTRIBUTE_SHUFFLE 0x03
  140. #define AVRCP_ATTRIBUTE_SCAN 0x04
  141. /* media attributes */
  142. #define AVRCP_MEDIA_ATTRIBUTE_ILLEGAL 0x0
  143. #define AVRCP_MEDIA_ATTRIBUTE_TITLE 0x1
  144. #define AVRCP_MEDIA_ATTRIBUTE_ARTIST 0x2
  145. #define AVRCP_MEDIA_ATTRIBUTE_ALBUM 0x3
  146. #define AVRCP_MEDIA_ATTRIBUTE_TRACK 0x4
  147. #define AVRCP_MEDIA_ATTRIBUTE_TOTAL 0x5
  148. #define AVRCP_MEDIA_ATTRIBUTE_GENRE 0x6
  149. #define AVRCP_MEDIA_ATTRIBUTE_DURATION 0x7
  150. /* play status */
  151. #define AVRCP_PLAY_STATUS_STOPPED 0x00
  152. #define AVRCP_PLAY_STATUS_PLAYING 0x01
  153. #define AVRCP_PLAY_STATUS_PAUSED 0x02
  154. #define AVRCP_PLAY_STATUS_FWD_SEEK 0x03
  155. #define AVRCP_PLAY_STATUS_REV_SEEK 0x04
  156. #define AVRCP_PLAY_STATUS_ERROR 0xFF
  157. /* media scope */
  158. #define AVRCP_MEDIA_PLAYER_LIST 0x00
  159. #define AVRCP_MEDIA_PLAYER_VFS 0x01
  160. #define AVRCP_MEDIA_SEARCH 0x02
  161. #define AVRCP_MEDIA_NOW_PLAYING 0x03
  162. static struct avrcp_continuing {
  163. uint16_t num;
  164. uint16_t size;
  165. } avrcp_continuing;
  166. static const char *ctype2str(uint8_t ctype)
  167. {
  168. switch (ctype & 0x0f) {
  169. case AVC_CTYPE_CONTROL:
  170. return "Control";
  171. case AVC_CTYPE_STATUS:
  172. return "Status";
  173. case AVC_CTYPE_SPECIFIC_INQUIRY:
  174. return "Specific Inquiry";
  175. case AVC_CTYPE_NOTIFY:
  176. return "Notify";
  177. case AVC_CTYPE_GENERAL_INQUIRY:
  178. return "General Inquiry";
  179. case AVC_CTYPE_NOT_IMPLEMENTED:
  180. return "Not Implemented";
  181. case AVC_CTYPE_ACCEPTED:
  182. return "Accepted";
  183. case AVC_CTYPE_REJECTED:
  184. return "Rejected";
  185. case AVC_CTYPE_IN_TRANSITION:
  186. return "In Transition";
  187. case AVC_CTYPE_STABLE:
  188. return "Stable";
  189. case AVC_CTYPE_CHANGED:
  190. return "Changed";
  191. case AVC_CTYPE_INTERIM:
  192. return "Interim";
  193. default:
  194. return "Unknown";
  195. }
  196. }
  197. static const char *opcode2str(uint8_t opcode)
  198. {
  199. switch (opcode) {
  200. case AVC_OP_VENDORDEP:
  201. return "Vendor Dependent";
  202. case AVC_OP_UNITINFO:
  203. return "Unit Info";
  204. case AVC_OP_SUBUNITINFO:
  205. return "Subunit Info";
  206. case AVC_OP_PASSTHROUGH:
  207. return "Passthrough";
  208. default:
  209. return "Unknown";
  210. }
  211. }
  212. static const char *pt2str(uint8_t pt)
  213. {
  214. switch (pt) {
  215. case AVRCP_PACKET_TYPE_SINGLE:
  216. return "Single";
  217. case AVRCP_PACKET_TYPE_START:
  218. return "Start";
  219. case AVRCP_PACKET_TYPE_CONTINUING:
  220. return "Continuing";
  221. case AVRCP_PACKET_TYPE_END:
  222. return "End";
  223. default:
  224. return "Unknown";
  225. }
  226. }
  227. static const char *pdu2str(uint8_t pduid)
  228. {
  229. switch (pduid) {
  230. case AVRCP_GET_CAPABILITIES:
  231. return "GetCapabilities";
  232. case AVRCP_LIST_PLAYER_ATTRIBUTES:
  233. return "ListPlayerApplicationSettingAttributes";
  234. case AVRCP_LIST_PLAYER_VALUES:
  235. return "ListPlayerApplicationSettingValues";
  236. case AVRCP_GET_CURRENT_PLAYER_VALUE:
  237. return "GetCurrentPlayerApplicationSettingValue";
  238. case AVRCP_SET_PLAYER_VALUE:
  239. return "SetPlayerApplicationSettingValue";
  240. case AVRCP_GET_PLAYER_ATTRIBUTE_TEXT:
  241. return "GetPlayerApplicationSettingAttributeText";
  242. case AVRCP_GET_PLAYER_VALUE_TEXT:
  243. return "GetPlayerApplicationSettingValueText";
  244. case AVRCP_DISPLAYABLE_CHARSET:
  245. return "InformDisplayableCharacterSet";
  246. case AVRCP_CT_BATTERY_STATUS:
  247. return "InformBatteryStatusOfCT";
  248. case AVRCP_GET_ELEMENT_ATTRIBUTES:
  249. return "GetElementAttributes";
  250. case AVRCP_GET_PLAY_STATUS:
  251. return "GetPlayStatus";
  252. case AVRCP_REGISTER_NOTIFICATION:
  253. return "RegisterNotification";
  254. case AVRCP_REQUEST_CONTINUING:
  255. return "RequestContinuingResponse";
  256. case AVRCP_ABORT_CONTINUING:
  257. return "AbortContinuingResponse";
  258. case AVRCP_SET_ABSOLUTE_VOLUME:
  259. return "SetAbsoluteVolume";
  260. case AVRCP_SET_ADDRESSED_PLAYER:
  261. return "SetAddressedPlayer";
  262. case AVRCP_SET_BROWSED_PLAYER:
  263. return "SetBrowsedPlayer";
  264. case AVRCP_GET_FOLDER_ITEMS:
  265. return "GetFolderItems";
  266. case AVRCP_CHANGE_PATH:
  267. return "ChangePath";
  268. case AVRCP_GET_ITEM_ATTRIBUTES:
  269. return "GetItemAttributes";
  270. case AVRCP_PLAY_ITEM:
  271. return "PlayItem";
  272. case AVRCP_SEARCH:
  273. return "Search";
  274. case AVRCP_ADD_TO_NOW_PLAYING:
  275. return "AddToNowPlaying";
  276. case AVRCP_GENERAL_REJECT:
  277. return "GeneralReject";
  278. default:
  279. return "Unknown";
  280. }
  281. }
  282. static char *cap2str(uint8_t cap)
  283. {
  284. switch (cap) {
  285. case 0x2:
  286. return "CompanyID";
  287. case 0x3:
  288. return "EventsID";
  289. default:
  290. return "Unknown";
  291. }
  292. }
  293. static char *event2str(uint8_t event)
  294. {
  295. switch (event) {
  296. case AVRCP_EVENT_PLAYBACK_STATUS_CHANGED:
  297. return "EVENT_PLAYBACK_STATUS_CHANGED";
  298. case AVRCP_EVENT_TRACK_CHANGED:
  299. return "EVENT_TRACK_CHANGED";
  300. case AVRCP_EVENT_TRACK_REACHED_END:
  301. return "EVENT_TRACK_REACHED_END";
  302. case AVRCP_EVENT_TRACK_REACHED_START:
  303. return "EVENT_TRACK_REACHED_START";
  304. case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
  305. return "EVENT_PLAYBACK_POS_CHANGED";
  306. case AVRCP_EVENT_BATT_STATUS_CHANGED:
  307. return "EVENT_BATT_STATUS_CHANGED";
  308. case AVRCP_EVENT_SYSTEM_STATUS_CHANGED:
  309. return "EVENT_SYSTEM_STATUS_CHANGED";
  310. case AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
  311. return "EVENT_PLAYER_APPLICATION_SETTING_CHANGED";
  312. case AVRCP_EVENT_NOW_PLAYING_CONTENT_CHANGED:
  313. return "EVENT_NOW_PLAYING_CONTENT_CHANGED";
  314. case AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED:
  315. return "EVENT_AVAILABLE_PLAYERS_CHANGED";
  316. case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
  317. return "EVENT_ADDRESSED_PLAYER_CHANGED";
  318. case AVRCP_EVENT_UIDS_CHANGED:
  319. return "EVENT_UIDS_CHANGED";
  320. case AVRCP_EVENT_VOLUME_CHANGED:
  321. return "EVENT_VOLUME_CHANGED";
  322. default:
  323. return "Reserved";
  324. }
  325. }
  326. static const char *error2str(uint8_t status)
  327. {
  328. switch (status) {
  329. case AVRCP_STATUS_INVALID_COMMAND:
  330. return "Invalid Command";
  331. case AVRCP_STATUS_INVALID_PARAMETER:
  332. return "Invalid Parameter";
  333. case AVRCP_STATUS_NOT_FOUND:
  334. return "Not Found";
  335. case AVRCP_STATUS_INTERNAL_ERROR:
  336. return "Internal Error";
  337. case AVRCP_STATUS_SUCCESS:
  338. return "Success";
  339. case AVRCP_STATUS_UID_CHANGED:
  340. return "UID Changed";
  341. case AVRCP_STATUS_INVALID_DIRECTION:
  342. return "Invalid Direction";
  343. case AVRCP_STATUS_NOT_DIRECTORY:
  344. return "Not a Directory";
  345. case AVRCP_STATUS_DOES_NOT_EXIST:
  346. return "Does Not Exist";
  347. case AVRCP_STATUS_INVALID_SCOPE:
  348. return "Invalid Scope";
  349. case AVRCP_STATUS_OUT_OF_BOUNDS:
  350. return "Range Out of Bonds";
  351. case AVRCP_STATUS_MEDIA_IN_USE:
  352. return "Media in Use";
  353. case AVRCP_STATUS_IS_DIRECTORY:
  354. return "UID is a Directory";
  355. case AVRCP_STATUS_NOW_PLAYING_LIST_FULL:
  356. return "Now Playing List Full";
  357. case AVRCP_STATUS_SEARCH_NOT_SUPPORTED:
  358. return "Seach Not Supported";
  359. case AVRCP_STATUS_SEARCH_IN_PROGRESS:
  360. return "Search in Progress";
  361. case AVRCP_STATUS_INVALID_PLAYER_ID:
  362. return "Invalid Player ID";
  363. case AVRCP_STATUS_PLAYER_NOT_BROWSABLE:
  364. return "Player Not Browsable";
  365. case AVRCP_STATUS_PLAYER_NOT_ADDRESSED:
  366. return "Player Not Addressed";
  367. case AVRCP_STATUS_NO_VALID_SEARCH_RESULTS:
  368. return "No Valid Search Result";
  369. case AVRCP_STATUS_NO_AVAILABLE_PLAYERS:
  370. return "No Available Players";
  371. case AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED:
  372. return "Addressed Player Changed";
  373. default:
  374. return "Unknown";
  375. }
  376. }
  377. static void avrcp_rejected_dump(int level, struct frame *frm, uint16_t len)
  378. {
  379. uint8_t status;
  380. p_indent(level, frm);
  381. if (len < 1) {
  382. printf("PDU Malformed\n");
  383. raw_dump(level, frm);
  384. return;
  385. }
  386. status = p_get_u8(frm);
  387. printf("Error: 0x%02x (%s)\n", status, error2str(status));
  388. }
  389. static void avrcp_get_capabilities_dump(int level, struct frame *frm, uint16_t len)
  390. {
  391. uint8_t cap;
  392. uint8_t count;
  393. p_indent(level, frm);
  394. if (len < 1) {
  395. printf("PDU Malformed\n");
  396. raw_dump(level, frm);
  397. return;
  398. }
  399. cap = p_get_u8(frm);
  400. printf("CapabilityID: 0x%02x (%s)\n", cap, cap2str(cap));
  401. if (len == 1)
  402. return;
  403. p_indent(level, frm);
  404. count = p_get_u8(frm);
  405. printf("CapabilityCount: 0x%02x\n", count);
  406. switch (cap) {
  407. case 0x2:
  408. for (; count > 0; count--) {
  409. int i;
  410. p_indent(level, frm);
  411. printf("%s: 0x", cap2str(cap));
  412. for (i = 0; i < 3; i++)
  413. printf("%02x", p_get_u8(frm));
  414. printf("\n");
  415. }
  416. break;
  417. case 0x3:
  418. for (; count > 0; count--) {
  419. uint8_t event;
  420. p_indent(level, frm);
  421. event = p_get_u8(frm);
  422. printf("%s: 0x%02x (%s)\n", cap2str(cap), event,
  423. event2str(event));
  424. }
  425. break;
  426. default:
  427. raw_dump(level, frm);
  428. }
  429. }
  430. static const char *attr2str(uint8_t attr)
  431. {
  432. switch (attr) {
  433. case AVRCP_ATTRIBUTE_ILEGAL:
  434. return "Illegal";
  435. case AVRCP_ATTRIBUTE_EQUALIZER:
  436. return "Equalizer ON/OFF Status";
  437. case AVRCP_ATTRIBUTE_REPEAT_MODE:
  438. return "Repeat Mode Status";
  439. case AVRCP_ATTRIBUTE_SHUFFLE:
  440. return "Shuffle ON/OFF Status";
  441. case AVRCP_ATTRIBUTE_SCAN:
  442. return "Scan ON/OFF Status";
  443. default:
  444. return "Unknown";
  445. }
  446. }
  447. static void avrcp_list_player_attributes_dump(int level, struct frame *frm,
  448. uint16_t len)
  449. {
  450. uint8_t num;
  451. if (len == 0)
  452. return;
  453. p_indent(level, frm);
  454. num = p_get_u8(frm);
  455. printf("AttributeCount: 0x%02x\n", num);
  456. for (; num > 0; num--) {
  457. uint8_t attr;
  458. p_indent(level, frm);
  459. attr = p_get_u8(frm);
  460. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  461. }
  462. }
  463. static const char *value2str(uint8_t attr, uint8_t value)
  464. {
  465. switch (attr) {
  466. case AVRCP_ATTRIBUTE_ILEGAL:
  467. return "Illegal";
  468. case AVRCP_ATTRIBUTE_EQUALIZER:
  469. switch (value) {
  470. case 0x01:
  471. return "OFF";
  472. case 0x02:
  473. return "ON";
  474. default:
  475. return "Reserved";
  476. }
  477. case AVRCP_ATTRIBUTE_REPEAT_MODE:
  478. switch (value) {
  479. case 0x01:
  480. return "OFF";
  481. case 0x02:
  482. return "Single Track Repeat";
  483. case 0x03:
  484. return "All Track Repeat";
  485. case 0x04:
  486. return "Group Repeat";
  487. default:
  488. return "Reserved";
  489. }
  490. case AVRCP_ATTRIBUTE_SHUFFLE:
  491. switch (value) {
  492. case 0x01:
  493. return "OFF";
  494. case 0x02:
  495. return "All Track Suffle";
  496. case 0x03:
  497. return "Group Suffle";
  498. default:
  499. return "Reserved";
  500. }
  501. case AVRCP_ATTRIBUTE_SCAN:
  502. switch (value) {
  503. case 0x01:
  504. return "OFF";
  505. case 0x02:
  506. return "All Track Scan";
  507. case 0x03:
  508. return "Group Scan";
  509. default:
  510. return "Reserved";
  511. }
  512. default:
  513. return "Unknown";
  514. }
  515. }
  516. static void avrcp_list_player_values_dump(int level, struct frame *frm,
  517. uint8_t ctype, uint16_t len)
  518. {
  519. static uint8_t attr = 0; /* Remember attribute */
  520. uint8_t num;
  521. p_indent(level, frm);
  522. if (len < 1) {
  523. printf("PDU Malformed\n");
  524. raw_dump(level, frm);
  525. return;
  526. }
  527. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  528. goto response;
  529. attr = p_get_u8(frm);
  530. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  531. return;
  532. response:
  533. num = p_get_u8(frm);
  534. printf("ValueCount: 0x%02x\n", num);
  535. for (; num > 0; num--) {
  536. uint8_t value;
  537. p_indent(level, frm);
  538. value = p_get_u8(frm);
  539. printf("ValueID: 0x%02x (%s)\n", value,
  540. value2str(attr, value));
  541. }
  542. }
  543. static void avrcp_get_current_player_value_dump(int level, struct frame *frm,
  544. uint8_t ctype, uint16_t len)
  545. {
  546. uint8_t num;
  547. p_indent(level, frm);
  548. if (len < 1) {
  549. printf("PDU Malformed\n");
  550. raw_dump(level, frm);
  551. return;
  552. }
  553. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  554. goto response;
  555. num = p_get_u8(frm);
  556. printf("AttributeCount: 0x%02x\n", num);
  557. for (; num > 0; num--) {
  558. uint8_t attr;
  559. p_indent(level, frm);
  560. attr = p_get_u8(frm);
  561. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  562. }
  563. return;
  564. response:
  565. num = p_get_u8(frm);
  566. printf("ValueCount: 0x%02x\n", num);
  567. for (; num > 0; num--) {
  568. uint8_t attr, value;
  569. p_indent(level, frm);
  570. attr = p_get_u8(frm);
  571. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  572. p_indent(level, frm);
  573. value = p_get_u8(frm);
  574. printf("ValueID: 0x%02x (%s)\n", value,
  575. value2str(attr, value));
  576. }
  577. }
  578. static void avrcp_set_player_value_dump(int level, struct frame *frm,
  579. uint8_t ctype, uint16_t len)
  580. {
  581. uint8_t num;
  582. p_indent(level, frm);
  583. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  584. return;
  585. if (len < 1) {
  586. printf("PDU Malformed\n");
  587. raw_dump(level, frm);
  588. return;
  589. }
  590. num = p_get_u8(frm);
  591. printf("AttributeCount: 0x%02x\n", num);
  592. for (; num > 0; num--) {
  593. uint8_t attr, value;
  594. p_indent(level, frm);
  595. attr = p_get_u8(frm);
  596. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  597. p_indent(level, frm);
  598. value = p_get_u8(frm);
  599. printf("ValueID: 0x%02x (%s)\n", value,
  600. value2str(attr, value));
  601. }
  602. }
  603. static const char *charset2str(uint16_t charset)
  604. {
  605. switch (charset) {
  606. case 1:
  607. case 2:
  608. return "Reserved";
  609. case 3:
  610. return "ASCII";
  611. case 4:
  612. return "ISO_8859-1";
  613. case 5:
  614. return "ISO_8859-2";
  615. case 6:
  616. return "ISO_8859-3";
  617. case 7:
  618. return "ISO_8859-4";
  619. case 8:
  620. return "ISO_8859-5";
  621. case 9:
  622. return "ISO_8859-6";
  623. case 10:
  624. return "ISO_8859-7";
  625. case 11:
  626. return "ISO_8859-8";
  627. case 12:
  628. return "ISO_8859-9";
  629. case 106:
  630. return "UTF-8";
  631. default:
  632. return "Unknown";
  633. }
  634. }
  635. static void avrcp_get_player_attribute_text_dump(int level, struct frame *frm,
  636. uint8_t ctype, uint16_t len)
  637. {
  638. uint8_t num;
  639. p_indent(level, frm);
  640. if (len < 1) {
  641. printf("PDU Malformed\n");
  642. raw_dump(level, frm);
  643. return;
  644. }
  645. num = p_get_u8(frm);
  646. printf("AttributeCount: 0x%02x\n", num);
  647. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  648. goto response;
  649. for (; num > 0; num--) {
  650. uint8_t attr;
  651. p_indent(level, frm);
  652. attr = p_get_u8(frm);
  653. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  654. }
  655. return;
  656. response:
  657. for (; num > 0; num--) {
  658. uint8_t attr, len;
  659. uint16_t charset;
  660. p_indent(level, frm);
  661. attr = p_get_u8(frm);
  662. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  663. p_indent(level, frm);
  664. charset = p_get_u16(frm);
  665. printf("CharsetID: 0x%04x (%s)\n", charset,
  666. charset2str(charset));
  667. p_indent(level, frm);
  668. len = p_get_u8(frm);
  669. printf("StringLength: 0x%02x\n", len);
  670. p_indent(level, frm);
  671. printf("String: ");
  672. for (; len > 0; len--) {
  673. uint8_t c = p_get_u8(frm);
  674. printf("%1c", isprint(c) ? c : '.');
  675. }
  676. printf("\n");
  677. }
  678. }
  679. static void avrcp_get_player_value_text_dump(int level, struct frame *frm,
  680. uint8_t ctype, uint16_t len)
  681. {
  682. static uint8_t attr = 0; /* Remember attribute */
  683. uint8_t num;
  684. p_indent(level, frm);
  685. if (len < 1) {
  686. printf("PDU Malformed\n");
  687. raw_dump(level, frm);
  688. return;
  689. }
  690. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  691. goto response;
  692. attr = p_get_u8(frm);
  693. printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
  694. p_indent(level, frm);
  695. num = p_get_u8(frm);
  696. printf("ValueCount: 0x%02x\n", num);
  697. for (; num > 0; num--) {
  698. uint8_t value;
  699. p_indent(level, frm);
  700. value = p_get_u8(frm);
  701. printf("ValueID: 0x%02x (%s)\n", value,
  702. value2str(attr, value));
  703. }
  704. return;
  705. response:
  706. num = p_get_u8(frm);
  707. printf("ValueCount: 0x%02x\n", num);
  708. for (; num > 0; num--) {
  709. uint8_t value, len;
  710. uint16_t charset;
  711. p_indent(level, frm);
  712. value = p_get_u8(frm);
  713. printf("ValueID: 0x%02x (%s)\n", value,
  714. value2str(attr, value));
  715. p_indent(level, frm);
  716. charset = p_get_u16(frm);
  717. printf("CharsetID: 0x%04x (%s)\n", charset,
  718. charset2str(charset));
  719. p_indent(level, frm);
  720. len = p_get_u8(frm);
  721. printf("StringLength: 0x%02x\n", len);
  722. p_indent(level, frm);
  723. printf("String: ");
  724. for (; len > 0; len--) {
  725. uint8_t c = p_get_u8(frm);
  726. printf("%1c", isprint(c) ? c : '.');
  727. }
  728. printf("\n");
  729. }
  730. }
  731. static void avrcp_displayable_charset(int level, struct frame *frm,
  732. uint8_t ctype, uint16_t len)
  733. {
  734. uint8_t num;
  735. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  736. return;
  737. p_indent(level, frm);
  738. if (len < 2) {
  739. printf("PDU Malformed\n");
  740. raw_dump(level, frm);
  741. return;
  742. }
  743. num = p_get_u8(frm);
  744. printf("CharsetCount: 0x%02x\n", num);
  745. for (; num > 0; num--) {
  746. uint16_t charset;
  747. p_indent(level, frm);
  748. charset = p_get_u16(frm);
  749. printf("CharsetID: 0x%04x (%s)\n", charset,
  750. charset2str(charset));
  751. }
  752. }
  753. static const char *status2str(uint8_t status)
  754. {
  755. switch (status) {
  756. case 0x0:
  757. return "NORMAL";
  758. case 0x1:
  759. return "WARNING";
  760. case 0x2:
  761. return "CRITICAL";
  762. case 0x3:
  763. return "EXTERNAL";
  764. case 0x4:
  765. return "FULL_CHARGE";
  766. default:
  767. return "Reserved";
  768. }
  769. }
  770. static void avrcp_ct_battery_status_dump(int level, struct frame *frm,
  771. uint8_t ctype, uint16_t len)
  772. {
  773. uint8_t status;
  774. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  775. return;
  776. p_indent(level, frm);
  777. status = p_get_u8(frm);
  778. printf("BatteryStatus: 0x%02x (%s)\n", status, status2str(status));
  779. }
  780. static const char *mediattr2str(uint32_t attr)
  781. {
  782. switch (attr) {
  783. case AVRCP_MEDIA_ATTRIBUTE_ILLEGAL:
  784. return "Illegal";
  785. case AVRCP_MEDIA_ATTRIBUTE_TITLE:
  786. return "Title";
  787. case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
  788. return "Artist";
  789. case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
  790. return "Album";
  791. case AVRCP_MEDIA_ATTRIBUTE_TRACK:
  792. return "Track";
  793. case AVRCP_MEDIA_ATTRIBUTE_TOTAL:
  794. return "Track Total";
  795. case AVRCP_MEDIA_ATTRIBUTE_GENRE:
  796. return "Genre";
  797. case AVRCP_MEDIA_ATTRIBUTE_DURATION:
  798. return "Track duration";
  799. default:
  800. return "Reserved";
  801. }
  802. }
  803. static void avrcp_get_element_attributes_dump(int level, struct frame *frm,
  804. uint8_t ctype, uint16_t len,
  805. uint8_t pt)
  806. {
  807. uint64_t id;
  808. uint8_t num;
  809. p_indent(level, frm);
  810. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  811. goto response;
  812. if (len < 9) {
  813. printf("PDU Malformed\n");
  814. raw_dump(level, frm);
  815. return;
  816. }
  817. id = p_get_u64(frm);
  818. printf("Identifier: 0x%jx (%s)\n", id, id ? "Reserved" : "PLAYING");
  819. p_indent(level, frm);
  820. num = p_get_u8(frm);
  821. printf("AttributeCount: 0x%02x\n", num);
  822. for (; num > 0; num--) {
  823. uint32_t attr;
  824. p_indent(level, frm);
  825. attr = p_get_u32(frm);
  826. printf("Attribute: 0x%08x (%s)\n", attr, mediattr2str(attr));
  827. }
  828. return;
  829. response:
  830. if (pt == AVRCP_PACKET_TYPE_SINGLE || pt == AVRCP_PACKET_TYPE_START) {
  831. if (len < 1) {
  832. printf("PDU Malformed\n");
  833. raw_dump(level, frm);
  834. return;
  835. }
  836. num = p_get_u8(frm);
  837. avrcp_continuing.num = num;
  838. printf("AttributeCount: 0x%02x\n", num);
  839. len--;
  840. } else {
  841. num = avrcp_continuing.num;
  842. if (avrcp_continuing.size > 0) {
  843. uint16_t size;
  844. if (avrcp_continuing.size > len) {
  845. size = len;
  846. avrcp_continuing.size -= len;
  847. } else {
  848. size = avrcp_continuing.size;
  849. avrcp_continuing.size = 0;
  850. }
  851. printf("ContinuingAttributeValue: ");
  852. for (; size > 0; size--) {
  853. uint8_t c = p_get_u8(frm);
  854. printf("%1c", isprint(c) ? c : '.');
  855. }
  856. printf("\n");
  857. len -= size;
  858. }
  859. }
  860. while (num > 0 && len > 0) {
  861. uint32_t attr;
  862. uint16_t charset, attrlen;
  863. p_indent(level, frm);
  864. attr = p_get_u32(frm);
  865. printf("Attribute: 0x%08x (%s)\n", attr, mediattr2str(attr));
  866. p_indent(level, frm);
  867. charset = p_get_u16(frm);
  868. printf("CharsetID: 0x%04x (%s)\n", charset,
  869. charset2str(charset));
  870. p_indent(level, frm);
  871. attrlen = p_get_u16(frm);
  872. printf("AttributeValueLength: 0x%04x\n", attrlen);
  873. len -= sizeof(attr) + sizeof(charset) + sizeof(attrlen);
  874. num--;
  875. p_indent(level, frm);
  876. printf("AttributeValue: ");
  877. for (; attrlen > 0 && len > 0; attrlen--, len--) {
  878. uint8_t c = p_get_u8(frm);
  879. printf("%1c", isprint(c) ? c : '.');
  880. }
  881. printf("\n");
  882. if (attrlen > 0)
  883. avrcp_continuing.size = attrlen;
  884. }
  885. avrcp_continuing.num = num;
  886. }
  887. static const char *playstatus2str(uint8_t status)
  888. {
  889. switch (status) {
  890. case AVRCP_PLAY_STATUS_STOPPED:
  891. return "STOPPED";
  892. case AVRCP_PLAY_STATUS_PLAYING:
  893. return "PLAYING";
  894. case AVRCP_PLAY_STATUS_PAUSED:
  895. return "PAUSED";
  896. case AVRCP_PLAY_STATUS_FWD_SEEK:
  897. return "FWD_SEEK";
  898. case AVRCP_PLAY_STATUS_REV_SEEK:
  899. return "REV_SEEK";
  900. case AVRCP_PLAY_STATUS_ERROR:
  901. return "ERROR";
  902. default:
  903. return "Unknown";
  904. }
  905. }
  906. static void avrcp_get_play_status_dump(int level, struct frame *frm,
  907. uint8_t ctype, uint16_t len)
  908. {
  909. uint32_t interval;
  910. uint8_t status;
  911. if (ctype <= AVC_CTYPE_GENERAL_INQUIRY)
  912. return;
  913. p_indent(level, frm);
  914. if (len < 9) {
  915. printf("PDU Malformed\n");
  916. raw_dump(level, frm);
  917. return;
  918. }
  919. interval = p_get_u32(frm);
  920. printf("SongLength: 0x%08x (%u miliseconds)\n", interval, interval);
  921. p_indent(level, frm);
  922. interval = p_get_u32(frm);
  923. printf("SongPosition: 0x%08x (%u miliconds)\n", interval, interval);
  924. p_indent(level, frm);
  925. status = p_get_u8(frm);
  926. printf("PlayStatus: 0x%02x (%s)\n", status, playstatus2str(status));
  927. }
  928. static void avrcp_register_notification_dump(int level, struct frame *frm,
  929. uint8_t ctype, uint16_t len)
  930. {
  931. uint8_t event, status;
  932. uint16_t uid;
  933. uint32_t interval;
  934. uint64_t id;
  935. p_indent(level, frm);
  936. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  937. goto response;
  938. if (len < 5) {
  939. printf("PDU Malformed\n");
  940. raw_dump(level, frm);
  941. return;
  942. }
  943. event = p_get_u8(frm);
  944. printf("EventID: 0x%02x (%s)\n", event, event2str(event));
  945. p_indent(level, frm);
  946. interval = p_get_u32(frm);
  947. printf("Interval: 0x%08x (%u seconds)\n", interval, interval);
  948. return;
  949. response:
  950. if (len < 1) {
  951. printf("PDU Malformed\n");
  952. raw_dump(level, frm);
  953. return;
  954. }
  955. event = p_get_u8(frm);
  956. printf("EventID: 0x%02x (%s)\n", event, event2str(event));
  957. p_indent(level, frm);
  958. switch (event) {
  959. case AVRCP_EVENT_PLAYBACK_STATUS_CHANGED:
  960. status = p_get_u8(frm);
  961. printf("PlayStatus: 0x%02x (%s)\n", status,
  962. playstatus2str(status));
  963. break;
  964. case AVRCP_EVENT_TRACK_CHANGED:
  965. id = p_get_u64(frm);
  966. printf("Identifier: 0x%16" PRIx64 " (%" PRIu64 ")\n", id, id);
  967. break;
  968. case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
  969. interval = p_get_u32(frm);
  970. printf("Position: 0x%08x (%u miliseconds)\n", interval,
  971. interval);
  972. break;
  973. case AVRCP_EVENT_BATT_STATUS_CHANGED:
  974. status = p_get_u8(frm);
  975. printf("BatteryStatus: 0x%02x (%s)\n", status,
  976. status2str(status));
  977. break;
  978. case AVRCP_EVENT_SYSTEM_STATUS_CHANGED:
  979. status = p_get_u8(frm);
  980. printf("SystemStatus: 0x%02x ", status);
  981. switch (status) {
  982. case 0x00:
  983. printf("(POWER_ON)\n");
  984. break;
  985. case 0x01:
  986. printf("(POWER_OFF)\n");
  987. break;
  988. case 0x02:
  989. printf("(UNPLUGGED)\n");
  990. break;
  991. default:
  992. printf("(UNKOWN)\n");
  993. break;
  994. }
  995. break;
  996. case AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
  997. status = p_get_u8(frm);
  998. printf("AttributeCount: 0x%02x\n", status);
  999. for (; status > 0; status--) {
  1000. uint8_t attr, value;
  1001. p_indent(level, frm);
  1002. attr = p_get_u8(frm);
  1003. printf("AttributeID: 0x%02x (%s)\n", attr,
  1004. attr2str(attr));
  1005. p_indent(level, frm);
  1006. value = p_get_u8(frm);
  1007. printf("ValueID: 0x%02x (%s)\n", value,
  1008. value2str(attr, value));
  1009. }
  1010. break;
  1011. case AVRCP_EVENT_VOLUME_CHANGED:
  1012. status = p_get_u8(frm) & 0x7F;
  1013. printf("Volume: %.2f%% (%d/127)\n", status/1.27, status);
  1014. break;
  1015. case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
  1016. uid = p_get_u16(frm);
  1017. printf("PlayerID: 0x%04x (%u)\n", uid, uid);
  1018. p_indent(level, frm);
  1019. uid = p_get_u16(frm);
  1020. printf("UIDCounter: 0x%04x (%u)\n", uid, uid);
  1021. break;
  1022. case AVRCP_EVENT_UIDS_CHANGED:
  1023. uid = p_get_u16(frm);
  1024. printf("UIDCounter: 0x%04x (%u)\n", uid, uid);
  1025. break;
  1026. }
  1027. }
  1028. static void avrcp_set_absolute_volume_dump(int level, struct frame *frm,
  1029. uint8_t ctype, uint16_t len)
  1030. {
  1031. uint8_t value;
  1032. p_indent(level, frm);
  1033. if (len < 1) {
  1034. printf("PDU Malformed\n");
  1035. raw_dump(level, frm);
  1036. return;
  1037. }
  1038. value = p_get_u8(frm) & 0x7F;
  1039. printf("Volume: %.2f%% (%d/127)\n", value/1.27, value);
  1040. }
  1041. static void avrcp_set_addressed_player(int level, struct frame *frm,
  1042. uint8_t ctype, uint16_t len)
  1043. {
  1044. uint16_t id;
  1045. uint8_t status;
  1046. p_indent(level, frm);
  1047. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  1048. goto response;
  1049. if (len < 2) {
  1050. printf("PDU Malformed\n");
  1051. raw_dump(level, frm);
  1052. return;
  1053. }
  1054. id = p_get_u16(frm);
  1055. printf("PlayerID: 0x%04x (%u)\n", id, id);
  1056. return;
  1057. response:
  1058. if (len < 1) {
  1059. printf("PDU Malformed\n");
  1060. raw_dump(level, frm);
  1061. return;
  1062. }
  1063. status = p_get_u8(frm);
  1064. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1065. }
  1066. static void avrcp_set_browsed_player_dump(int level, struct frame *frm,
  1067. uint8_t hdr, uint16_t len)
  1068. {
  1069. uint32_t items;
  1070. uint16_t id, uids, charset;
  1071. uint8_t status, folders;
  1072. p_indent(level, frm);
  1073. if (hdr & 0x02)
  1074. goto response;
  1075. if (len < 2) {
  1076. printf("PDU Malformed\n");
  1077. raw_dump(level, frm);
  1078. return;
  1079. }
  1080. id = p_get_u16(frm);
  1081. printf("PlayerID: 0x%04x (%u)\n", id, id);
  1082. return;
  1083. response:
  1084. if (len != 1 && len < 10) {
  1085. printf("PDU Malformed\n");
  1086. raw_dump(level, frm);
  1087. return;
  1088. }
  1089. status = p_get_u8(frm);
  1090. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1091. if (len == 1)
  1092. return;
  1093. p_indent(level, frm);
  1094. uids = p_get_u16(frm);
  1095. printf("UIDCounter: 0x%04x (%u)\n", uids, uids);
  1096. p_indent(level, frm);
  1097. items = p_get_u32(frm);
  1098. printf("Number of Items: 0x%08x (%u)\n", items, items);
  1099. p_indent(level, frm);
  1100. charset = p_get_u16(frm);
  1101. printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
  1102. p_indent(level, frm);
  1103. folders = p_get_u8(frm);
  1104. printf("Folder Depth: 0x%02x (%u)\n", folders, folders);
  1105. for (; folders > 0; folders--) {
  1106. uint16_t len;
  1107. p_indent(level, frm);
  1108. len = p_get_u8(frm);
  1109. printf("Folder: ");
  1110. for (; len > 0; len--) {
  1111. uint8_t c = p_get_u8(frm);
  1112. printf("%1c", isprint(c) ? c : '.');
  1113. }
  1114. printf("\n");
  1115. }
  1116. }
  1117. static const char *scope2str(uint8_t scope)
  1118. {
  1119. switch (scope) {
  1120. case AVRCP_MEDIA_PLAYER_LIST:
  1121. return "Media Player List";
  1122. case AVRCP_MEDIA_PLAYER_VFS:
  1123. return "Media Player Virtual Filesystem";
  1124. case AVRCP_MEDIA_SEARCH:
  1125. return "Search";
  1126. case AVRCP_MEDIA_NOW_PLAYING:
  1127. return "Now Playing";
  1128. default:
  1129. return "Unknown";
  1130. }
  1131. }
  1132. static void avrcp_play_item_dump(int level, struct frame *frm,
  1133. uint8_t ctype, uint16_t len)
  1134. {
  1135. uint64_t uid;
  1136. uint32_t uidcounter;
  1137. uint8_t scope, status;
  1138. p_indent(level, frm);
  1139. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  1140. goto response;
  1141. if (len < 11) {
  1142. printf("PDU Malformed\n");
  1143. raw_dump(level, frm);
  1144. return;
  1145. }
  1146. scope = p_get_u8(frm);
  1147. printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
  1148. p_indent(level, frm);
  1149. uid = p_get_u64(frm);
  1150. printf("UID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
  1151. p_indent(level, frm);
  1152. uidcounter = p_get_u16(frm);
  1153. printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
  1154. return;
  1155. response:
  1156. status = p_get_u8(frm);
  1157. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1158. }
  1159. static void avrcp_add_to_now_playing_dump(int level, struct frame *frm,
  1160. uint8_t ctype, uint16_t len)
  1161. {
  1162. uint64_t uid;
  1163. uint32_t uidcounter;
  1164. uint8_t scope, status;
  1165. p_indent(level, frm);
  1166. if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
  1167. goto response;
  1168. if (len < 11) {
  1169. printf("PDU Malformed\n");
  1170. raw_dump(level, frm);
  1171. return;
  1172. }
  1173. scope = p_get_u8(frm);
  1174. printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
  1175. p_indent(level, frm);
  1176. uid = p_get_u64(frm);
  1177. printf("UID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
  1178. p_indent(level, frm);
  1179. uidcounter = p_get_u16(frm);
  1180. printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
  1181. return;
  1182. response:
  1183. status = p_get_u8(frm);
  1184. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1185. }
  1186. static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
  1187. {
  1188. uint8_t pduid, pt;
  1189. uint16_t len;
  1190. p_indent(level, frm);
  1191. pduid = p_get_u8(frm);
  1192. pt = p_get_u8(frm);
  1193. len = p_get_u16(frm);
  1194. printf("AVRCP: %s: pt %s len 0x%04x\n", pdu2str(pduid),
  1195. pt2str(pt), len);
  1196. if (len != frm->len) {
  1197. p_indent(level, frm);
  1198. printf("PDU Malformed\n");
  1199. raw_dump(level, frm);
  1200. return;
  1201. }
  1202. if (ctype == AVC_CTYPE_REJECTED) {
  1203. avrcp_rejected_dump(level + 1, frm, len);
  1204. return;
  1205. }
  1206. switch (pduid) {
  1207. case AVRCP_GET_CAPABILITIES:
  1208. avrcp_get_capabilities_dump(level + 1, frm, len);
  1209. break;
  1210. case AVRCP_LIST_PLAYER_ATTRIBUTES:
  1211. avrcp_list_player_attributes_dump(level + 1, frm, len);
  1212. break;
  1213. case AVRCP_LIST_PLAYER_VALUES:
  1214. avrcp_list_player_values_dump(level + 1, frm, ctype, len);
  1215. break;
  1216. case AVRCP_GET_CURRENT_PLAYER_VALUE:
  1217. avrcp_get_current_player_value_dump(level + 1, frm, ctype,
  1218. len);
  1219. break;
  1220. case AVRCP_SET_PLAYER_VALUE:
  1221. avrcp_set_player_value_dump(level + 1, frm, ctype, len);
  1222. break;
  1223. case AVRCP_GET_PLAYER_ATTRIBUTE_TEXT:
  1224. avrcp_get_player_attribute_text_dump(level + 1, frm, ctype,
  1225. len);
  1226. break;
  1227. case AVRCP_GET_PLAYER_VALUE_TEXT:
  1228. avrcp_get_player_value_text_dump(level + 1, frm, ctype, len);
  1229. break;
  1230. case AVRCP_DISPLAYABLE_CHARSET:
  1231. avrcp_displayable_charset(level + 1, frm, ctype, len);
  1232. break;
  1233. case AVRCP_CT_BATTERY_STATUS:
  1234. avrcp_ct_battery_status_dump(level + 1, frm, ctype, len);
  1235. break;
  1236. case AVRCP_GET_ELEMENT_ATTRIBUTES:
  1237. avrcp_get_element_attributes_dump(level + 1, frm, ctype, len,
  1238. pt);
  1239. break;
  1240. case AVRCP_GET_PLAY_STATUS:
  1241. avrcp_get_play_status_dump(level + 1, frm, ctype, len);
  1242. break;
  1243. case AVRCP_REGISTER_NOTIFICATION:
  1244. avrcp_register_notification_dump(level + 1, frm, ctype, len);
  1245. break;
  1246. case AVRCP_SET_ABSOLUTE_VOLUME:
  1247. avrcp_set_absolute_volume_dump(level + 1, frm, ctype, len);
  1248. break;
  1249. case AVRCP_SET_ADDRESSED_PLAYER:
  1250. avrcp_set_addressed_player(level + 1, frm, ctype, len);
  1251. break;
  1252. case AVRCP_PLAY_ITEM:
  1253. avrcp_play_item_dump(level + 1, frm, ctype, len);
  1254. break;
  1255. case AVRCP_ADD_TO_NOW_PLAYING:
  1256. avrcp_add_to_now_playing_dump(level + 1, frm, ctype, len);
  1257. break;
  1258. default:
  1259. raw_dump(level, frm);
  1260. }
  1261. }
  1262. static char *op2str(uint8_t op)
  1263. {
  1264. switch (op & 0x7f) {
  1265. case AVC_PANEL_VOLUME_UP:
  1266. return "VOLUME UP";
  1267. case AVC_PANEL_VOLUME_DOWN:
  1268. return "VOLUME DOWN";
  1269. case AVC_PANEL_MUTE:
  1270. return "MUTE";
  1271. case AVC_PANEL_PLAY:
  1272. return "PLAY";
  1273. case AVC_PANEL_STOP:
  1274. return "STOP";
  1275. case AVC_PANEL_PAUSE:
  1276. return "PAUSE";
  1277. case AVC_PANEL_RECORD:
  1278. return "RECORD";
  1279. case AVC_PANEL_REWIND:
  1280. return "REWIND";
  1281. case AVC_PANEL_FAST_FORWARD:
  1282. return "FAST FORWARD";
  1283. case AVC_PANEL_EJECT:
  1284. return "EJECT";
  1285. case AVC_PANEL_FORWARD:
  1286. return "FORWARD";
  1287. case AVC_PANEL_BACKWARD:
  1288. return "BACKWARD";
  1289. default:
  1290. return "UNKNOWN";
  1291. }
  1292. }
  1293. static void avrcp_passthrough_dump(int level, struct frame *frm)
  1294. {
  1295. uint8_t op, len;
  1296. p_indent(level, frm);
  1297. op = p_get_u8(frm);
  1298. printf("Operation: 0x%02x (%s %s)\n", op, op2str(op),
  1299. op & 0x80 ? "Released" : "Pressed");
  1300. p_indent(level, frm);
  1301. len = p_get_u8(frm);
  1302. printf("Lenght: 0x%02x\n", len);
  1303. raw_dump(level, frm);
  1304. }
  1305. static const char *subunit2str(uint8_t subunit)
  1306. {
  1307. switch (subunit) {
  1308. case AVC_SUBUNIT_MONITOR:
  1309. return "Monitor";
  1310. case AVC_SUBUNIT_AUDIO:
  1311. return "Audio";
  1312. case AVC_SUBUNIT_PRINTER:
  1313. return "Printer";
  1314. case AVC_SUBUNIT_DISC:
  1315. return "Disc";
  1316. case AVC_SUBUNIT_TAPE:
  1317. return "Tape";
  1318. case AVC_SUBUNIT_TURNER:
  1319. return "Turner";
  1320. case AVC_SUBUNIT_CA:
  1321. return "CA";
  1322. case AVC_SUBUNIT_CAMERA:
  1323. return "Camera";
  1324. case AVC_SUBUNIT_PANEL:
  1325. return "Panel";
  1326. case AVC_SUBUNIT_BULLETIN_BOARD:
  1327. return "Bulleting Board";
  1328. case AVC_SUBUNIT_CAMERA_STORAGE:
  1329. return "Camera Storage";
  1330. case AVC_SUBUNIT_VENDOR_UNIQUE:
  1331. return "Vendor Unique";
  1332. case AVC_SUBUNIT_EXTENDED:
  1333. return "Extended to next byte";
  1334. case AVC_SUBUNIT_UNIT:
  1335. return "Unit";
  1336. default:
  1337. return "Reserved";
  1338. }
  1339. }
  1340. static const char *playertype2str(uint8_t type)
  1341. {
  1342. switch (type & 0x0F) {
  1343. case 0x01:
  1344. return "Audio";
  1345. case 0x02:
  1346. return "Video";
  1347. case 0x03:
  1348. return "Audio, Video";
  1349. case 0x04:
  1350. return "Audio Broadcasting";
  1351. case 0x05:
  1352. return "Audio, Audio Broadcasting";
  1353. case 0x06:
  1354. return "Video, Audio Broadcasting";
  1355. case 0x07:
  1356. return "Audio, Video, Audio Broadcasting";
  1357. case 0x08:
  1358. return "Video Broadcasting";
  1359. case 0x09:
  1360. return "Audio, Video Broadcasting";
  1361. case 0x0A:
  1362. return "Video, Video Broadcasting";
  1363. case 0x0B:
  1364. return "Audio, Video, Video Broadcasting";
  1365. case 0x0C:
  1366. return "Audio Broadcasting, Video Broadcasting";
  1367. case 0x0D:
  1368. return "Audio, Audio Broadcasting, Video Broadcasting";
  1369. case 0x0E:
  1370. return "Video, Audio Broadcasting, Video Broadcasting";
  1371. case 0x0F:
  1372. return "Audio, Video, Audio Broadcasting, Video Broadcasting";
  1373. }
  1374. return "None";
  1375. }
  1376. static const char *playersubtype2str(uint32_t subtype)
  1377. {
  1378. switch (subtype & 0x03) {
  1379. case 0x01:
  1380. return "Audio Book";
  1381. case 0x02:
  1382. return "Podcast";
  1383. case 0x03:
  1384. return "Audio Book, Podcast";
  1385. }
  1386. return "None";
  1387. }
  1388. static void avrcp_media_player_item_dump(int level, struct frame *frm,
  1389. uint16_t len)
  1390. {
  1391. uint16_t id, charset, namelen;
  1392. uint8_t type, status;
  1393. uint32_t subtype;
  1394. uint64_t features[2];
  1395. p_indent(level, frm);
  1396. if (len < 28) {
  1397. printf("PDU Malformed\n");
  1398. raw_dump(level, frm);
  1399. return;
  1400. }
  1401. id = p_get_u16(frm);
  1402. printf("PlayerID: 0x%04x (%u)\n", id, id);
  1403. p_indent(level, frm);
  1404. type = p_get_u8(frm);
  1405. printf("PlayerType: 0x%04x (%s)\n", type, playertype2str(type));
  1406. p_indent(level, frm);
  1407. subtype = p_get_u32(frm);
  1408. printf("PlayerSubtype: 0x%08x (%s)\n", subtype,
  1409. playersubtype2str(subtype));
  1410. p_indent(level, frm);
  1411. status = p_get_u8(frm);
  1412. printf("PlayStatus: 0x%02x (%s)\n", status, playstatus2str(status));
  1413. p_indent(level, frm);
  1414. p_get_u128(frm, &features[0], &features[1]);
  1415. printf("Features: 0x%16" PRIx64 "%16" PRIx64 "\n", features[1],
  1416. features[0]);
  1417. p_indent(level, frm);
  1418. charset = p_get_u16(frm);
  1419. printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
  1420. p_indent(level, frm);
  1421. namelen = p_get_u16(frm);
  1422. printf("NameLength: 0x%04x (%u)\n", namelen, namelen);
  1423. p_indent(level, frm);
  1424. printf("Name: ");
  1425. for (; namelen > 0; namelen--) {
  1426. uint8_t c = p_get_u8(frm);
  1427. printf("%1c", isprint(c) ? c : '.');
  1428. }
  1429. printf("\n");
  1430. }
  1431. static const char *foldertype2str(uint8_t type)
  1432. {
  1433. switch (type) {
  1434. case 0x00:
  1435. return "Mixed";
  1436. case 0x01:
  1437. return "Titles";
  1438. case 0x02:
  1439. return "Albuns";
  1440. case 0x03:
  1441. return "Artists";
  1442. case 0x04:
  1443. return "Genres";
  1444. case 0x05:
  1445. return "Playlists";
  1446. case 0x06:
  1447. return "Years";
  1448. }
  1449. return "Reserved";
  1450. }
  1451. static void avrcp_folder_item_dump(int level, struct frame *frm, uint16_t len)
  1452. {
  1453. uint8_t type, playable;
  1454. uint16_t charset, namelen;
  1455. uint64_t uid;
  1456. p_indent(level, frm);
  1457. if (len < 14) {
  1458. printf("PDU Malformed\n");
  1459. raw_dump(level, frm);
  1460. return;
  1461. }
  1462. uid = p_get_u64(frm);
  1463. printf("FolderUID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
  1464. p_indent(level, frm);
  1465. type = p_get_u8(frm);
  1466. printf("FolderType: 0x%02x (%s)\n", type, foldertype2str(type));
  1467. p_indent(level, frm);
  1468. playable = p_get_u8(frm);
  1469. printf("IsPlayable: 0x%02x (%s)\n", playable,
  1470. playable & 0x01 ? "True" : "False");
  1471. p_indent(level, frm);
  1472. charset = p_get_u16(frm);
  1473. printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
  1474. p_indent(level, frm);
  1475. namelen = p_get_u16(frm);
  1476. printf("NameLength: 0x%04x (%u)\n", namelen, namelen);
  1477. p_indent(level, frm);
  1478. printf("Name: ");
  1479. for (; namelen > 0; namelen--) {
  1480. uint8_t c = p_get_u8(frm);
  1481. printf("%1c", isprint(c) ? c : '.');
  1482. }
  1483. printf("\n");
  1484. }
  1485. static const char *elementtype2str(uint8_t type)
  1486. {
  1487. switch (type) {
  1488. case 0x00:
  1489. return "Audio";
  1490. case 0x01:
  1491. return "Video";
  1492. }
  1493. return "Reserved";
  1494. }
  1495. static void avrcp_attribute_entry_list_dump(int level, struct frame *frm,
  1496. uint8_t count)
  1497. {
  1498. for (; count > 0; count--) {
  1499. uint32_t attr;
  1500. uint16_t charset;
  1501. uint8_t len;
  1502. p_indent(level, frm);
  1503. attr = p_get_u32(frm);
  1504. printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
  1505. p_indent(level, frm);
  1506. charset = p_get_u16(frm);
  1507. printf("CharsetID: 0x%04x (%s)\n", charset,
  1508. charset2str(charset));
  1509. p_indent(level, frm);
  1510. len = p_get_u16(frm);
  1511. printf("AttributeLength: 0x%04x (%u)\n", len, len);
  1512. p_indent(level, frm);
  1513. printf("AttributeValue: ");
  1514. for (; len > 0; len--) {
  1515. uint8_t c = p_get_u8(frm);
  1516. printf("%1c", isprint(c) ? c : '.');
  1517. }
  1518. printf("\n");
  1519. }
  1520. }
  1521. static void avrcp_media_element_item_dump(int level, struct frame *frm,
  1522. uint16_t len)
  1523. {
  1524. uint64_t uid;
  1525. uint16_t charset, namelen;
  1526. uint8_t type, count;
  1527. p_indent(level, frm);
  1528. if (len < 14) {
  1529. printf("PDU Malformed\n");
  1530. raw_dump(level, frm);
  1531. return;
  1532. }
  1533. uid = p_get_u64(frm);
  1534. printf("ElementUID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
  1535. p_indent(level, frm);
  1536. type = p_get_u8(frm);
  1537. printf("ElementType: 0x%02x (%s)\n", type, elementtype2str(type));
  1538. p_indent(level, frm);
  1539. charset = p_get_u16(frm);
  1540. printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
  1541. p_indent(level, frm);
  1542. namelen = p_get_u16(frm);
  1543. printf("NameLength: 0x%04x (%u)\n", namelen, namelen);
  1544. p_indent(level, frm);
  1545. printf("Name: ");
  1546. for (; namelen > 0; namelen--) {
  1547. uint8_t c = p_get_u8(frm);
  1548. printf("%1c", isprint(c) ? c : '.');
  1549. }
  1550. printf("\n");
  1551. p_indent(level, frm);
  1552. count = p_get_u8(frm);
  1553. printf("AttributeCount: 0x%02x (%u)\n", count, count);
  1554. avrcp_attribute_entry_list_dump(level, frm, count);
  1555. }
  1556. static void avrcp_get_folder_items_dump(int level, struct frame *frm,
  1557. uint8_t hdr, uint16_t len)
  1558. {
  1559. uint8_t scope, count, status;
  1560. uint32_t start, end;
  1561. uint16_t uid, num;
  1562. p_indent(level, frm);
  1563. if (hdr & 0x02)
  1564. goto response;
  1565. if (len < 10) {
  1566. printf("PDU Malformed\n");
  1567. raw_dump(level, frm);
  1568. return;
  1569. }
  1570. scope = p_get_u8(frm);
  1571. printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
  1572. p_indent(level, frm);
  1573. start = p_get_u32(frm);
  1574. printf("StartItem: 0x%08x (%u)\n", start, start);
  1575. p_indent(level, frm);
  1576. end = p_get_u32(frm);
  1577. printf("EndItem: 0x%08x (%u)\n", end, end);
  1578. p_indent(level, frm);
  1579. count = p_get_u8(frm);
  1580. printf("AttributeCount: 0x%02x (%u)\n", count, count);
  1581. for (; count > 0; count--) {
  1582. uint32_t attr;
  1583. p_indent(level, frm);
  1584. attr = p_get_u32(frm);
  1585. printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
  1586. }
  1587. return;
  1588. response:
  1589. status = p_get_u8(frm);
  1590. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1591. if (len == 1)
  1592. return;
  1593. p_indent(level, frm);
  1594. uid = p_get_u16(frm);
  1595. printf("UIDCounter: 0x%04x (%u)\n", uid, uid);
  1596. p_indent(level, frm);
  1597. num = p_get_u16(frm);
  1598. printf("Number of Items: 0x%04x (%u)\n", num, num);
  1599. for (; num > 0; num--) {
  1600. uint8_t type;
  1601. uint16_t len;
  1602. p_indent(level, frm);
  1603. type = p_get_u8(frm);
  1604. len = p_get_u16(frm);
  1605. switch (type) {
  1606. case 0x01:
  1607. printf("Item: 0x01 (Media Player)) ");
  1608. printf("Length: 0x%04x (%u)\n", len, len);
  1609. avrcp_media_player_item_dump(level, frm, len);
  1610. break;
  1611. case 0x02:
  1612. printf("Item: 0x02 (Folder) ");
  1613. printf("Length: 0x%04x (%u)\n", len, len);
  1614. avrcp_folder_item_dump(level, frm, len);
  1615. break;
  1616. case 0x03:
  1617. printf("Item: 0x03 (Media Element) ");
  1618. printf("Length: 0x%04x (%u)\n", len, len);
  1619. avrcp_media_element_item_dump(level, frm, len);
  1620. break;
  1621. }
  1622. }
  1623. }
  1624. static const char *dir2str(uint8_t dir)
  1625. {
  1626. switch (dir) {
  1627. case 0x00:
  1628. return "Folder Up";
  1629. case 0x01:
  1630. return "Folder Down";
  1631. }
  1632. return "Reserved";
  1633. }
  1634. static void avrcp_change_path_dump(int level, struct frame *frm, uint8_t hdr,
  1635. uint16_t len)
  1636. {
  1637. uint64_t uid;
  1638. uint32_t items;
  1639. uint16_t uidcounter;
  1640. uint8_t dir, status;
  1641. p_indent(level, frm);
  1642. if (hdr & 0x02)
  1643. goto response;
  1644. if (len < 11) {
  1645. printf("PDU Malformed\n");
  1646. raw_dump(level, frm);
  1647. return;
  1648. }
  1649. uidcounter = p_get_u16(frm);
  1650. printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
  1651. p_indent(level, frm);
  1652. dir = p_get_u8(frm);
  1653. printf("Direction: 0x%02x (%s)\n", dir, dir2str(dir));
  1654. p_indent(level, frm);
  1655. uid = p_get_u64(frm);
  1656. printf("FolderUID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
  1657. return;
  1658. response:
  1659. status = p_get_u8(frm);
  1660. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1661. if (len == 1)
  1662. return;
  1663. p_indent(level, frm);
  1664. items = p_get_u32(frm);
  1665. printf("Number of Items: 0x%04x (%u)", items, items);
  1666. }
  1667. static void avrcp_get_item_attributes_dump(int level, struct frame *frm,
  1668. uint8_t hdr, uint16_t len)
  1669. {
  1670. uint64_t uid;
  1671. uint32_t uidcounter;
  1672. uint8_t scope, count, status;
  1673. p_indent(level, frm);
  1674. if (hdr & 0x02)
  1675. goto response;
  1676. if (len < 12) {
  1677. printf("PDU Malformed\n");
  1678. raw_dump(level, frm);
  1679. return;
  1680. }
  1681. scope = p_get_u8(frm);
  1682. printf("Scope: 0x%02x (%s)\n", scope, scope2str(scope));
  1683. p_indent(level, frm);
  1684. uid = p_get_u64(frm);
  1685. printf("UID: 0x%16" PRIx64 " (%" PRIu64 ")\n", uid, uid);
  1686. p_indent(level, frm);
  1687. uidcounter = p_get_u16(frm);
  1688. printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
  1689. p_indent(level, frm);
  1690. count = p_get_u8(frm);
  1691. printf("AttributeCount: 0x%02x (%u)\n", count, count);
  1692. for (; count > 0; count--) {
  1693. uint32_t attr;
  1694. p_indent(level, frm);
  1695. attr = p_get_u32(frm);
  1696. printf("AttributeID: 0x%08x (%s)\n", attr, mediattr2str(attr));
  1697. }
  1698. return;
  1699. response:
  1700. status = p_get_u8(frm);
  1701. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1702. if (len == 1)
  1703. return;
  1704. p_indent(level, frm);
  1705. count = p_get_u8(frm);
  1706. printf("AttributeCount: 0x%02x (%u)\n", count, count);
  1707. avrcp_attribute_entry_list_dump(level, frm, count);
  1708. }
  1709. static void avrcp_search_dump(int level, struct frame *frm, uint8_t hdr,
  1710. uint16_t len)
  1711. {
  1712. uint32_t uidcounter, items;
  1713. uint16_t charset, namelen;
  1714. uint8_t status;
  1715. p_indent(level, frm);
  1716. if (hdr & 0x02)
  1717. goto response;
  1718. if (len < 4) {
  1719. printf("PDU Malformed\n");
  1720. raw_dump(level, frm);
  1721. return;
  1722. }
  1723. charset = p_get_u16(frm);
  1724. printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset));
  1725. p_indent(level, frm);
  1726. namelen = p_get_u16(frm);
  1727. printf("Length: 0x%04x (%u)\n", namelen, namelen);
  1728. p_indent(level, frm);
  1729. printf("String: ");
  1730. for (; namelen > 0; namelen--) {
  1731. uint8_t c = p_get_u8(frm);
  1732. printf("%1c", isprint(c) ? c : '.');
  1733. }
  1734. printf("\n");
  1735. return;
  1736. response:
  1737. status = p_get_u8(frm);
  1738. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1739. if (len == 1)
  1740. return;
  1741. p_indent(level, frm);
  1742. uidcounter = p_get_u16(frm);
  1743. printf("UIDCounter: 0x%04x (%u)\n", uidcounter, uidcounter);
  1744. p_indent(level, frm);
  1745. items = p_get_u32(frm);
  1746. printf("Number of Items: 0x%04x (%u)", items, items);
  1747. }
  1748. static void avrcp_general_reject_dump(int level, struct frame *frm,
  1749. uint8_t hdr, uint16_t len)
  1750. {
  1751. uint8_t status;
  1752. p_indent(level, frm);
  1753. if (hdr & 0x02)
  1754. goto response;
  1755. printf("PDU Malformed\n");
  1756. raw_dump(level, frm);
  1757. return;
  1758. response:
  1759. status = p_get_u8(frm);
  1760. printf("Status: 0x%02x (%s)\n", status, error2str(status));
  1761. }
  1762. static void avrcp_browsing_dump(int level, struct frame *frm, uint8_t hdr)
  1763. {
  1764. uint8_t pduid;
  1765. uint16_t len;
  1766. pduid = p_get_u8(frm);
  1767. len = p_get_u16(frm);
  1768. printf("AVRCP: %s: len 0x%04x\n", pdu2str(pduid), len);
  1769. if (len != frm->len) {
  1770. p_indent(level, frm);
  1771. printf("PDU Malformed\n");
  1772. raw_dump(level, frm);
  1773. return;
  1774. }
  1775. switch (pduid) {
  1776. case AVRCP_SET_BROWSED_PLAYER:
  1777. avrcp_set_browsed_player_dump(level + 1, frm, hdr, len);
  1778. break;
  1779. case AVRCP_GET_FOLDER_ITEMS:
  1780. avrcp_get_folder_items_dump(level + 1, frm, hdr, len);
  1781. break;
  1782. case AVRCP_CHANGE_PATH:
  1783. avrcp_change_path_dump(level + 1, frm, hdr, len);
  1784. break;
  1785. case AVRCP_GET_ITEM_ATTRIBUTES:
  1786. avrcp_get_item_attributes_dump(level + 1, frm, hdr, len);
  1787. break;
  1788. case AVRCP_SEARCH:
  1789. avrcp_search_dump(level + 1, frm, hdr, len);
  1790. break;
  1791. case AVRCP_GENERAL_REJECT:
  1792. avrcp_general_reject_dump(level + 1, frm, hdr, len);
  1793. break;
  1794. default:
  1795. raw_dump(level, frm);
  1796. }
  1797. }
  1798. static void avrcp_control_dump(int level, struct frame *frm)
  1799. {
  1800. uint8_t ctype, address, subunit, opcode, company[3];
  1801. int i;
  1802. ctype = p_get_u8(frm);
  1803. address = p_get_u8(frm);
  1804. opcode = p_get_u8(frm);
  1805. printf("AV/C: %s: address 0x%02x opcode 0x%02x\n", ctype2str(ctype),
  1806. address, opcode);
  1807. p_indent(level + 1, frm);
  1808. subunit = address >> 3;
  1809. printf("Subunit: %s\n", subunit2str(subunit));
  1810. p_indent(level + 1, frm);
  1811. printf("Opcode: %s\n", opcode2str(opcode));
  1812. /* Skip non-panel subunit packets */
  1813. if (subunit != AVC_SUBUNIT_PANEL) {
  1814. raw_dump(level, frm);
  1815. return;
  1816. }
  1817. /* Not implemented should not contain any operand */
  1818. if (ctype == AVC_CTYPE_NOT_IMPLEMENTED) {
  1819. raw_dump(level, frm);
  1820. return;
  1821. }
  1822. switch (opcode) {
  1823. case AVC_OP_PASSTHROUGH:
  1824. avrcp_passthrough_dump(level + 1, frm);
  1825. break;
  1826. case AVC_OP_VENDORDEP:
  1827. p_indent(level + 1, frm);
  1828. printf("Company ID: 0x");
  1829. for (i = 0; i < 3; i++) {
  1830. company[i] = p_get_u8(frm);
  1831. printf("%02x", company[i]);
  1832. }
  1833. printf("\n");
  1834. avrcp_pdu_dump(level + 1, frm, ctype);
  1835. break;
  1836. default:
  1837. raw_dump(level, frm);
  1838. }
  1839. }
  1840. void avrcp_dump(int level, struct frame *frm, uint8_t hdr, uint16_t psm)
  1841. {
  1842. p_indent(level, frm);
  1843. switch (psm) {
  1844. case 0x17:
  1845. avrcp_control_dump(level, frm);
  1846. break;
  1847. case 0x1B:
  1848. avrcp_browsing_dump(level, frm, hdr);
  1849. break;
  1850. default:
  1851. raw_dump(level, frm);
  1852. }
  1853. }