A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 491 lines 16 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Alan Korr & Nick Robinson 11 * 12 * All files in this archive are subject to the GNU General Public License. 13 * See the file COPYING in the source tree root for full license agreement. 14 * 15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 16 * KIND, either express or implied. 17 * 18 ****************************************************************************/ 19#include "iap-core.h" 20#include "iap-lingo.h" 21#include "kernel.h" 22#include "system.h" 23#include "tuner.h" 24#if CONFIG_TUNER 25#include "ipod_remote_tuner.h" 26#endif 27 28/* 29 * This macro is meant to be used inside an IAP mode message handler. 30 * It is passed the expected minimum length of the message inbufferfer. 31 * If the inbufferfer does not have the required lenght an ACK 32 * packet with a Bad Parameter error is generated. 33 */ 34#define CHECKLEN(x) do { \ 35 if (len < (x)) { \ 36 cmd_ack(cmd, IAP_ACK_BAD_PARAM); \ 37 return; \ 38 }} while(0) 39 40/* Check for authenticated state, and return an ACK Not 41 * Authenticated on failure. 42 */ 43#define CHECKAUTH do { \ 44 if (!DEVICE_AUTHENTICATED) { \ 45 cmd_ack(cmd, IAP_ACK_NO_AUTHEN); \ 46 return; \ 47 }} while(0) 48 49 50static void cmd_ack(const unsigned char cmd, const unsigned char status) 51{ 52 IAP_TX_INIT(0x07, 0x00); 53 IAP_TX_PUT(status); 54 IAP_TX_PUT(cmd); 55 56 iap_send_tx(); 57} 58 59#define cmd_ok(cmd) cmd_ack((cmd), IAP_ACK_OK) 60 61void iap_handlepkt_mode7(const unsigned int len, const unsigned char *inbuffer) 62{ 63 /* Note that some of the Lingo Mode 7 commands are handled by 64 * ../firmware/drivers/tuner/ipod_remote_tuner.c as some of the 65 * commands are sourced with the remote as the master with the ipod acting 66 * as the slave. 67 */ 68 unsigned char cmd = inbuffer[1]; 69 unsigned char statusnotifymaskbyte = 0; 70 71 /* We expect at least two bytes in the inbuffer, one for the 72 * lingo and one for the command 73 */ 74 CHECKLEN(2); 75 76 /* Lingo 0x07 must have been negotiated */ 77 if (!DEVICE_LINGO_SUPPORTED(0x07)) { 78 cmd_ack(cmd, IAP_ACK_BAD_PARAM); 79 return; 80 } 81 82 switch (cmd) 83 { 84 /* case 00 ToIpod Ack 2/6 bytes*/ 85 case 0x00: 86 { 87 /* 0x00 OK 88 * 0x01 Unknown Track Category 89 * 0x02 Command Failed. Command is valid but did not succeed 90 * 0x03 Out Of Resources 91 * 0x04 Bad Parameter 92 * 0x05 Unknown Track ID 93 * 0x06 Command Pending. 94 * 0x07 Not Authenticated 95 * 96 * byte 1 is ID of command being acknowledged 97 * bytes 2-5 only if status byte is pending. timeout in ms. 98 */ 99 break; 100 } 101 102 /* case 0x01 ToAccessory GetTunerCaps 103 * This is sent by iap-lingo0.c through case 0x15 after device 104 * has been authenticated FF55020701F6 105 */ 106 107 /* case 02 ToIpod RetTunerCaps 8 bytes */ 108 case 0x02: 109 { 110 /* Capabilities are stored as bits in first 4 bytes, 111 * inbuffer[2] byte is bits 31:24 112 * inbuffer[3] byte is bits 23:16 113 * inbuffer[4] byte is bits 15:08 114 * inbuffer[5] byte is bits 07:00 115 * inbuffer[6] and inbuffer[7] are all reserved bits 116 * Bit 0 = AM Band 520-1710 Khz 117 * Bit 1 = FM Europe/US 87.5 - 108.0 Mhz 118 * Bit 2 = FM Japan 76.0 - 90.0 Mhz 119 * Bit 3 = FM Wide 76.0 - 108.0 Mhz 120 * Bit 4 = HD Radio Capable 121 * Bit 5:7 Reserved 122 * Bit 8 = Tuner Power On/Off Control Capable 123 * Bit 9 = Status Change Notification Capable 124 * Bit 10:15 Reserved 125 * Bit 17:16 Minimum FM Resolution ID Bits 126 * 00 = 200Khz, 01 = 100Khz, 10 = 50Khz, 11 = reserved 127 * Bit 18 = Tuner Seek Up/Down Capable 128 * Bit 19 = Tuner Seek RSSI Threshold. Only if 18=1 129 * Bit 20 = Force Monophonic mode capable 130 * Bit 21 = Stero Blend Capable 131 * Bit 22 = FM Tuner deemphasis select capable 132 * Bit 23 = AM Tuner Resolution 9Khz (0=10Khz Only) capable 133 * Bit 24 = Radio Data System (RDS/RBDS) data capable 134 * Bit 25 = Tuner Channel RSSI indicator capable 135 * Bit 26 = Stero Source Indicator capable 136 * Bit 27 = RDS/RBDS Raw mode capable 137 * Bit 31:28 Reserved 138 * 139 * ipod Tuner returns 07 5E 07 0E 10 4B 140 * Bytes 6,7 Reserved 141 * ???????? ???????? 142 * ???????? ???????? 143 * 00010000 01001011 144 * 145 * Byte 5 - 0E 146 * 00000000 147 * 76543210 148 * 00001110 149 * AM 150 * FM Europe/US 151 * FM Japan 152 * FM Wide 153 * 154 * Byte 4 - 07 155 * 11111100 156 * 54321098 157 * 00000111 158 * Tuner Power On/Off 159 * Status Change Notification 160 * ?? Should be reserved 161 * 162 * Byte 3 - 5E 163 * 22221111 164 * 32109876 165 * 01011110 166 * Tuner Seek Up/Down 167 * Tuner Seek RSSI Threshold 168 * Force Mono Mode Capable 169 * Stereo Blend Capable 170 * FM Tuner deemphasis select capable 171 * 172 * Byte 2 - 07 173 * 33222222 174 * 10987654 175 * 00000111 176 * RDS/RBDS Capable 177 * Tuner Channel RSSI Indicator 178 * Stereo Source 179 * 180 * Just need to see what we can use this data for 181 * Make a selection for the tuner mode to select 182 * Preference is 183 * 1st - 76 to 108 FM 184 * 2nd - 87.5 to 108 Fm 185 * 3rd - 76 to 90 Fm 186 * 4th - AM 187 * 188 */ 189 190 if ((inbuffer[4] & 0x03) >0) { 191 statusnotifymaskbyte = 0; 192 if ((inbuffer[4] >> 0) & 0x01) { 193 /* Supports Tuner Power On/Off, so set ON */ 194 statusnotifymaskbyte = 1; 195 } 196 if ((inbuffer[4] >> 1) & 0x01) { 197 /* Supports Status Change Notification so set ON */ 198 /* Apple 5/6/7G firmware does NOT enable this bit */ 199 /* statusnotifymaskbyte += 2; */ 200 } 201 IAP_TX_INIT(0x07, 0x05); 202 IAP_TX_PUT(statusnotifymaskbyte); 203 iap_send_tx(); 204 } 205 if ((inbuffer[5] >> 1) & 0x01) { 206 /* Supports FM Europe/US Tuner 87.5 - 108.0 Mhz */ 207 /* Apple firmware sends this before setting region */ 208 IAP_TX_INIT(0x07, 0x0E); 209 IAP_TX_PUT(0x00); 210 iap_send_tx(); 211 /* Apple firmware then sends region */ 212 IAP_TX_INIT(0x07, 0x08); 213 IAP_TX_PUT(0x02); 214 iap_send_tx(); 215 } else if ((inbuffer[5] >> 3) & 0x01) { 216 /* Supports FM Wide Tuner 76 - 108.0 Mhz */ 217 /* apple firmware send this before setting region */ 218 IAP_TX_INIT(0x07, 0x0E); 219 IAP_TX_PUT(0x00); 220 iap_send_tx(); 221 /* Apple firmware then send region */ 222 IAP_TX_INIT(0x07, 0x08); 223 IAP_TX_PUT(0x08); 224 iap_send_tx(); 225 } else if ((inbuffer[5] >> 2) & 0x01) { 226 /* Supports FM Japan Tuner 76 - 90.0 Mhz */ 227 /* apple firmware send this before setting region */ 228 IAP_TX_INIT(0x07, 0x0E); 229 IAP_TX_PUT(0x41); 230 iap_send_tx(); 231 /* Apple firmware then send region */ 232 IAP_TX_INIT(0x07, 0x08); 233 IAP_TX_PUT(0x04); 234 iap_send_tx(); 235 } else if ((inbuffer[5] >> 0) & 0x01) { 236 /* Supports AM Tuner */ 237 IAP_TX_INIT(0x07, 0x08); 238 IAP_TX_PUT(0x01); 239 iap_send_tx(); 240 } 241 242 if ((inbuffer[2] & 0x03) > 0) { 243 statusnotifymaskbyte = 0; 244 if ((inbuffer[2] >> 0) & 0x01) { 245 /* Supports RDS/RBDS Capable so set 246 *StatusChangeNotify for RDS/RBDS Data 247 */ 248 statusnotifymaskbyte = 1; 249 } 250 if ((inbuffer[2] >> 1) & 0x01) { 251 /* Supports Tuner Channel RSSi Indicator Capable so set */ 252 /* StatusChangeNotify for RSSI */ 253 /* Apple 5G firmware does NOT enable this bit so we wont */ 254 /* statusnotifymaskbyte += 2; */ 255 } 256 IAP_TX_INIT(0x07, 0x18); 257 IAP_TX_PUT(statusnotifymaskbyte); 258 iap_send_tx(); 259 } 260 261 if ((inbuffer[4] >> 2) & 0x01) { 262 /* Reserved */ 263 } 264 if ((inbuffer[4] >> 3) & 0x01) { 265 /* Reserved */ 266 } 267 if ((inbuffer[3] >> 1) & 0x01) { 268 /* Tuner Seek Up/Down` */ 269 } 270 if ((inbuffer[3] >> 2) & 0x01) { 271 /* Tuner Seek RSSI Threshold */ 272 } 273 if ((inbuffer[3] >> 3) & 0x01) { 274 /* Force Mono Mode */ 275 } 276 if ((inbuffer[3] >> 4) & 0x01) { 277 /* Stereo Blend */ 278 } 279 if ((inbuffer[3] >> 6) & 0x01) { 280 /* FM Tuner deemphasis */ 281 } 282 if ((inbuffer[2] >> 2) & 0x01) { 283 /* Stereo Source */ 284 } 285 break; 286 } 287 /* case 03 ToAccessory GetTunerCtrl 2 bytes */ 288 289 /* case 04 ToIpod RetTunerCtrl 3 bytes 290 * Bit 0 power is on (1) or Off (0) 291 * Bit 1 StatusChangeNotify is enabled (1) or disabled (0) 292 * Bit 3 RDS/RBDS Raw mode enabled 293 * 294 * Should/Can we do something with these? 295 */ 296 297 /* case 05 ToAccessory SetTunerCtrl 3 bytes 298 * Bits as per 0x04 above 299 * Bit 0/1 set through Lingo7 Cmd02 */ 300 301 /* case 06 ToAccessory GetTunerBand 2 bytes */ 302 303 /* case 07 ToIpod RetTunerBand 3 bytes 304 * Returns current band for Tuner. See 0x08 below 305 * 306 * Should/Can we do something with these? 307 */ 308 309 /* case 08 ToAccessory SetTuneBand 310 * Set Bit 0 for AM 311 * Set Bit 1 for FM Europe/U S 87.5-108Mhz 312 * Set Bit 2 for FM JApan 76.0-90.0Mhz 313 * Set Bit 3 for FM Wide 76.0-108Mhz 314 * Currently we send this after receiving capabilities 315 * on 0x02 above 316 */ 317 318 /* case 09 ToAccessory GetTunerFreq 2 bytes */ 319 320 /* case 0A ToIpod RetTunerFreq 7 bytes */ 321 case 0x0A: 322 { 323 /* Returns Frequency set and RSSI Power Levels 324 * These are sent as is to rmt_tuner_freq() in 325 * ../firmware/drivers/tuner/ipod_remote_tuner.c */ 326 rmt_tuner_freq(len, inbuffer); 327 break; 328 } 329 330 /* case 0B ToAccessory SetTunerFreq 6 bytes */ 331 332 /* case 0C ToAccessory GetTunerMode 2 bytes */ 333 334 /* case 0D ToIpod RetTunerMode 3 bytes 335 * Returns Tuner Mode Status in 8 bits as follows 336 * Bit 1:0 - FM Tuner Resolution 337 * Bit 2 Tuner is seeking up or down 338 * Bit 3 Tuner is seeking with RSSI min theshold enabled 339 * Bit 4 Force Mono Mode (1) or allow stereo (0) 340 * Bit 5 Stereo Blend enabled. Valid only if Bit 4 is 0 341 * Bit 6 FM Tuner Deemphasis 50uS (1) or 75uS (0) 342 * Bit 7 Reserved 0 343 */ 344 345 /* case 0E ToAccessory SetTunerMode 3 bytes 346 * See 0x0D for Bit Descriptions 347 * Bits set by Cmd 02 348 */ 349 350 /* case 0F ToAccessory GetTunerSeekRssi 2 bytes */ 351 352 /* case 10 ToIpod RetTunerSeekRssi 3 bytes 353 * Returns RSSI Value for seek operations 354 * value is 0 (min) - 255 (max) 355 */ 356 357 /* case 11 ToAccessory SetTunerSeekRssi 3 bytes */ 358 359 /* case 12 ToAccessory TunerSeekStart 3 bytes */ 360 361 /* case 13 ToIpod TunerSeekDone 7 bytes */ 362 case 0x13: 363 { 364 rmt_tuner_freq(len, inbuffer); 365 break; 366 } 367 368 /* case 14 ToAccessory GetTunerStatus 2 bytes */ 369 370 /* case 15 ToIpod RetTunerStatus 3 bytes */ 371 372 /* case 16 ToAccessory GetStatusNotifyMask 2 bytes */ 373 374 /* case 17 ToIpod RetStatusNotifyMask 3 bytes */ 375 376 /* case 18 ToAccessory SetStatusNotifyMask 3 bytes 377 * This is set by Cmd 02 378 */ 379 380 /* case 19 ToIpod StatusChangeNotify 3 bytes */ 381 case 0x19: 382 { 383 /* Returns StatusChangeNotify bits to ipod. 384 * Bit 0 set for RDS/RBDS data ready 385 * Bit 1 set for Tuner RSSI level change 386 * Bit 2 for Stereo Indicator changed 387 * If any of these are set we will request the data 388 * need to look at using these 389 */ 390 break; 391 } 392 393 /* case 1A ToAccessory GetRdsReadyStatus 2 bytes */ 394 395 /* case 1B ToIpod RetRdsReadyStatus 6 bytes */ 396 case 0x1B: 397 { 398 break; 399 } 400 /* case 1C ToAccessory GetRdsData 3 bytes */ 401 402 /* case 1D ToIpod RetRdsData NN bytes */ 403 case 0x1D: 404 { 405 rmt_tuner_rds_data(len, inbuffer); 406 break; 407 } 408 409 /* case 1E ToAccessory GetRdsNotifyMask 2 bytes*/ 410 411 /* case 1F ToIpod RetRdsNotifyMask 6 Bytes*/ 412 case 0x1F: 413 { 414 break; 415 } 416 417 /* case 20 ToAccessory SetRdsNotifyMask 6 bytes */ 418 419 /* case 21 ToIpod RdsReadyNotify NN bytes */ 420 case 0x21: 421 { 422 rmt_tuner_rds_data(len, inbuffer); 423 break; 424 } 425 /* case 22 Reserved */ 426 427 /* case 23 Reserved */ 428 429 /* case 24 Reserved */ 430 431 /* case 25 ToAccessory GetHDProgramServiceCount 0 bytes */ 432 433 /* case 26 ToIpod RetHDProgramServiceCount 1 bytes */ 434 case 0x26: 435 { 436 break; 437 } 438 439 /* case 27 ToAccessory GetHDProgramService 0 bytes */ 440 441 /* case 28 ToIpod RetHDProgramService 1 bytes */ 442 case 0x28: 443 { 444 break; 445 } 446 447 /* case 29 ToAccessory SetHDProgramService 1 bytes */ 448 449 /* case 2A ToAccessory GetHDDataReadyStatus 0 bytes */ 450 451 /* case 2B ToIpod RetHDDataReadyStatus 4 bytes */ 452 case 0x2B: 453 { 454 break; 455 } 456 457 /* case 2C ToAccessory GetHDData 1 bytes */ 458 459 /* case 2D ToIpod RetHDData NN bytes */ 460 case 0x2D: 461 { 462 break; 463 } 464 465 /* case 2E ToAccessory GetHDDataNotifyMask 0 bytes */ 466 467 /* case 2F ToIpod RetHDDataNotifyMask 4 bytes */ 468 case 0x2F: 469 { 470 break; 471 } 472 473 /* case 30 ToAccessory SetHDDataNotifyMask 4 bytes */ 474 475 /* case 31 ToIpod HDDataReadyNotify NN bytes */ 476 case 0x31: 477 { 478 break; 479 } 480 481 /* The default response is IAP_ACK_BAD_PARAM */ 482 default: 483 { 484#ifdef LOGF_ENABLE 485 logf("iap: Unsupported Mode07 Command"); 486#endif 487 cmd_ack(cmd, IAP_ACK_BAD_PARAM); 488 break; 489 } 490 } 491}