summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertrik Sikken <bertrik@sikken.nl>2011-04-21 21:50:39 +0000
committerBertrik Sikken <bertrik@sikken.nl>2011-04-21 21:50:39 +0000
commit9ea20660ca9815aba437472d31c6eda2330cff67 (patch)
tree0ede1d94a620f2aa5c750257b8a73607e43ab8a1
parentc77b01428328c347825937a28ec04d809a9db41e (diff)
downloadrockbox-9ea20660ca9815aba437472d31c6eda2330cff67.tar.gz
rockbox-9ea20660ca9815aba437472d31c6eda2330cff67.zip
iap: split iap_handlepkt into a function per mode
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29755 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/iap.c1141
1 files changed, 578 insertions, 563 deletions
diff --git a/apps/iap.c b/apps/iap.c
index d432a16dc3..7447c67ba9 100644
--- a/apps/iap.c
+++ b/apps/iap.c
@@ -218,636 +218,651 @@ static void iap_set_remote_volume(void)
218 iap_send_pkt(data, sizeof(data)); 218 iap_send_pkt(data, sizeof(data));
219} 219}
220 220
221void iap_handlepkt(void) 221static void iap_handlepkt_mode0(void)
222{ 222{
223 unsigned int cmd = serbuf[2];
224 switch (cmd) {
225
226 case 0x24:
227 {
228 /* ipod video send this */
229 unsigned char data[] = {0x00, 0x25, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x01};
231 iap_send_pkt(data, sizeof(data));
232 break;
233 }
223 234
224 if(!iap_setupflag) return; 235 case 0x18:
225 if(serbuf[0] == 0) return; 236 {
226 237 /* ciphered authentication command */
227 /* if we are waiting for a remote button to go out, 238 /* Isn't used since we don't send the 0x00 0x17 command */
228 delay the handling of the new packet */ 239 break;
229 if(!iap_remotetick) 240 }
230 {
231 queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
232 return;
233 }
234 241
235 /* Handle Mode 0 */ 242 case 0x15:
236 if (serbuf[1] == 0x00)
237 {
238 switch (serbuf[2])
239 { 243 {
240 case 0x24: 244 unsigned char data0[] = {0x00, 0x16, 0x00};
241 { 245 iap_send_pkt(data0, sizeof(data0));
242 /* ipod video send this */ 246 unsigned char data1[] = {0x00, 0x27, 0x00};
243 unsigned char data[] = {0x00, 0x25, 0x00, 0x00, 0x00, 247 iap_send_pkt(data1, sizeof(data1));
244 0x00, 0x00, 0x00, 0x00,0x01}; 248 /* authentication ack, mandatory to enable some hardware */
245 iap_send_pkt(data, sizeof(data)); 249 unsigned char data2[] = {0x00, 0x19, 0x00};
246 break; 250 iap_send_pkt(data2, sizeof(data2));
247 } 251 if (radio_present == 1)
252 {
253 /* get tuner capacities */
254 unsigned char data3[] = {0x07, 0x01};
255 iap_send_pkt(data3, sizeof(data3));
256 }
257 iap_set_remote_volume();
258 break;
259 }
248 260
249 case 0x18: 261 case 0x13:
250 { 262 {
251 /* ciphered authentication command */ 263 unsigned char data[] = {0x00, 0x02, 0x00, 0x13};
252 /* Isn't used since we don't send the 0x00 0x17 command */ 264 iap_send_pkt(data, sizeof(data));
253 break;
254 }
255 265
256 case 0x15: 266 if (serbuf[6] == 0x35)
267 /* FM transmitter sends this: */
268 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
257 { 269 {
258 unsigned char data0[] = {0x00, 0x16, 0x00}; 270 unsigned char data2[] = {0x00, 0x27, 0x00};
259 iap_send_pkt(data0, sizeof(data0));
260 unsigned char data1[] = {0x00, 0x27, 0x00};
261 iap_send_pkt(data1, sizeof(data1));
262 /* authentication ack, mandatory to enable some hardware */
263 unsigned char data2[] = {0x00, 0x19, 0x00};
264 iap_send_pkt(data2, sizeof(data2)); 271 iap_send_pkt(data2, sizeof(data2));
265 if (radio_present == 1) 272 unsigned char data3[] = {0x05, 0x02};
266 { 273 iap_send_pkt(data3, sizeof(data3));
267 /* get tuner capacities */
268 unsigned char data3[] = {0x07, 0x01};
269 iap_send_pkt(data3, sizeof(data3));
270 }
271 iap_set_remote_volume();
272 break;
273 } 274 }
274 275
275 case 0x13: 276 else
276 { 277 {
277 unsigned char data[] = {0x00, 0x02, 0x00, 0x13}; 278 /* ipod fm remote sends this: */
278 iap_send_pkt(data, sizeof(data)); 279 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
279 280 if (serbuf[6] |= 0x80)
280 if (serbuf[6] == 0x35) 281 radio_present = 1;
281 /* FM transmitter sends this: */ 282 unsigned char data4[] = {0x00, 0x14};
282 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/ 283 iap_send_pkt(data4, sizeof(data4));
283 {
284 unsigned char data2[] = {0x00, 0x27, 0x00};
285 iap_send_pkt(data2, sizeof(data2));
286 unsigned char data3[] = {0x05, 0x02};
287 iap_send_pkt(data3, sizeof(data3));
288 }
289
290 else
291 {
292 /* ipod fm remote sends this: */
293 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
294 if (serbuf[6] |= 0x80)
295 radio_present = 1;
296 unsigned char data4[] = {0x00, 0x14};
297 iap_send_pkt(data4, sizeof(data4));
298 }
299 break;
300 } 284 }
285 break;
286 }
301 287
302 /* Init */ 288 /* Init */
303 case 0x0F: 289 case 0x0F:
304 { 290 {
305 unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05}; 291 unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05};
306 data[2] = serbuf[3]; 292 data[2] = serbuf[3];
307 iap_send_pkt(data, sizeof(data)); 293 iap_send_pkt(data, sizeof(data));
308 break; 294 break;
309 } 295 }
310 296
311 /* get model info */ 297 /* get model info */
312 case 0x0D: 298 case 0x0D:
313 { 299 {
314 /* ipod is supposed to work only with 5G and nano 2G */ 300 /* ipod is supposed to work only with 5G and nano 2G */
315 /*{0x00, 0x0E, 0x00, 0x0B, 0x00, 0x05, 0x50, 0x41, 0x31, 0x34, 301 /*{0x00, 0x0E, 0x00, 0x0B, 0x00, 0x05, 0x50, 0x41, 0x31, 0x34,
316 0x37, 0x4C, 0x4C, 0x00}; PA147LL (IPOD 5G 60 GO) */ 302 0x37, 0x4C, 0x4C, 0x00}; PA147LL (IPOD 5G 60 GO) */
317 unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10, 303 unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
318 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00}; 304 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
319 iap_send_pkt(data, sizeof(data)); 305 iap_send_pkt(data, sizeof(data));
320 break; 306 break;
321 } 307 }
322 308
323 /* Ipod FM remote sends this: FF 55 02 00 09 F5 */ 309 /* Ipod FM remote sends this: FF 55 02 00 09 F5 */
324 case 0x09: 310 case 0x09:
325 { 311 {
326 /* ipod5G firmware version */ 312 /* ipod5G firmware version */
327 unsigned char data[] = {0x00, 0x0A, 0x01, 0x02, 0x01 }; 313 unsigned char data[] = {0x00, 0x0A, 0x01, 0x02, 0x01 };
328 iap_send_pkt(data, sizeof(data)); 314 iap_send_pkt(data, sizeof(data));
329 break; 315 break;
330 } 316 }
317
318 /* FM transmitter sends this: */
319 /* FF 55 02 00 05 F9 (mode switch: AiR mode) */
320 case 0x05:
321 {
322 unsigned char data[] = {0x00, 0x02, 0x06,
323 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28};
324 iap_send_pkt(data, sizeof(data));
325 unsigned char data2[] = {0x00, 0x02, 0x00, 0x05};
326 iap_send_pkt(data2, sizeof(data2));
327 break;
328 }
331 329
330 case 0x01:
331 {
332 /* FM transmitter sends this: */ 332 /* FM transmitter sends this: */
333 /* FF 55 02 00 05 F9 (mode switch: AiR mode) */ 333 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
334 case 0x05: 334 if(serbuf[3] == 0x05)
335 { 335 {
336 unsigned char data[] = {0x00, 0x02, 0x06, 336 sleep(HZ/3);
337 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28}; 337 unsigned char data[] = {0x05, 0x02};
338 iap_send_pkt(data, sizeof(data)); 338 iap_send_pkt(data, sizeof(data));
339 unsigned char data2[] = {0x00, 0x02, 0x00, 0x05};
340 iap_send_pkt(data2, sizeof(data2));
341 break;
342 } 339 }
343 340 /* FM remote sends this: */
344 case 0x01: 341 /* FF 55 03 00 01 02 FA (1st thing sent) */
342 else if(serbuf[3] == 0x02)
345 { 343 {
346 /* FM transmitter sends this: */ 344 /* useful only for apple firmware */
347 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
348 if(serbuf[3] == 0x05)
349 {
350 sleep(HZ/3);
351 unsigned char data[] = {0x05, 0x02};
352 iap_send_pkt(data, sizeof(data));
353 }
354 /* FM remote sends this: */
355 /* FF 55 03 00 01 02 FA (1st thing sent) */
356 else if(serbuf[3] == 0x02)
357 {
358 /* useful only for apple firmware */
359 }
360 break;
361 } 345 }
346 break;
347 }
362 348
363 /* default response is with cmd ok packet */ 349 /* default response is with cmd ok packet */
364 default: 350 default:
365 { 351 {
366 unsigned char data[] = {0x00, 0x02, 0x00, 0x00}; 352 unsigned char data[] = {0x00, 0x02, 0x00, 0x00};
367 data[3] = serbuf[2]; /* respond with cmd */ 353 data[3] = cmd; /* respond with cmd */
368 iap_send_pkt(data, sizeof(data)); 354 iap_send_pkt(data, sizeof(data));
369 break; 355 break;
370 }
371 } 356 }
372 } 357 }
373 /* Handle Mode 2 */ 358}
374 else if (serbuf[1] == 0x02) 359
360static void iap_handlepkt_mode2(void)
361{
362 if(serbuf[2] != 0) return;
363 iap_remotebtn = BUTTON_NONE;
364 iap_remotetick = false;
365
366 if(serbuf[0] >= 3 && serbuf[3] != 0)
375 { 367 {
376 if(serbuf[2] != 0) return; 368 if(serbuf[3] & 1)
377 iap_remotebtn = BUTTON_NONE; 369 iap_remotebtn |= BUTTON_RC_PLAY;
378 iap_remotetick = false; 370 if(serbuf[3] & 2)
379 371 iap_remotebtn |= BUTTON_RC_VOL_UP;
380 if(serbuf[0] >= 3 && serbuf[3] != 0) 372 if(serbuf[3] & 4)
373 iap_remotebtn |= BUTTON_RC_VOL_DOWN;
374 if(serbuf[3] & 8)
375 iap_remotebtn |= BUTTON_RC_RIGHT;
376 if(serbuf[3] & 16)
377 iap_remotebtn |= BUTTON_RC_LEFT;
378 }
379 else if(serbuf[0] >= 4 && serbuf[4] != 0)
380 {
381 if(serbuf[4] & 1) /* play */
381 { 382 {
382 if(serbuf[3] & 1) 383 if (audio_status() != AUDIO_STATUS_PLAY)
383 iap_remotebtn |= BUTTON_RC_PLAY;
384 if(serbuf[3] & 2)
385 iap_remotebtn |= BUTTON_RC_VOL_UP;
386 if(serbuf[3] & 4)
387 iap_remotebtn |= BUTTON_RC_VOL_DOWN;
388 if(serbuf[3] & 8)
389 iap_remotebtn |= BUTTON_RC_RIGHT;
390 if(serbuf[3] & 16)
391 iap_remotebtn |= BUTTON_RC_LEFT;
392 }
393 else if(serbuf[0] >= 4 && serbuf[4] != 0)
394 {
395 if(serbuf[4] & 1) /* play */
396 { 384 {
397 if (audio_status() != AUDIO_STATUS_PLAY) 385 iap_remotebtn |= BUTTON_RC_PLAY;
398 { 386 iap_repeatbtn = 2;
399 iap_remotebtn |= BUTTON_RC_PLAY; 387 iap_remotetick = false;
400 iap_repeatbtn = 2; 388 iap_changedctr = 1;
401 iap_remotetick = false;
402 iap_changedctr = 1;
403 }
404 }
405 if(serbuf[4] & 2) /* pause */
406 {
407 if (audio_status() == AUDIO_STATUS_PLAY)
408 {
409 iap_remotebtn |= BUTTON_RC_PLAY;
410 iap_repeatbtn = 2;
411 iap_remotetick = false;
412 iap_changedctr = 1;
413 }
414 } 389 }
415 if((serbuf[4] & 128) && !iap_btnshuffle) /* shuffle */ 390 }
391 if(serbuf[4] & 2) /* pause */
392 {
393 if (audio_status() == AUDIO_STATUS_PLAY)
416 { 394 {
417 iap_btnshuffle = true; 395 iap_remotebtn |= BUTTON_RC_PLAY;
418 if(!global_settings.playlist_shuffle) 396 iap_repeatbtn = 2;
419 { 397 iap_remotetick = false;
420 global_settings.playlist_shuffle = 1; 398 iap_changedctr = 1;
421 settings_save();
422 if (audio_status() & AUDIO_STATUS_PLAY)
423 playlist_randomise(NULL, current_tick, true);
424 }
425 else if(global_settings.playlist_shuffle)
426 {
427 global_settings.playlist_shuffle = 0;
428 settings_save();
429 if (audio_status() & AUDIO_STATUS_PLAY)
430 playlist_sort(NULL, true);
431 }
432 } 399 }
433 else
434 iap_btnshuffle = false;
435 } 400 }
436 else if(serbuf[0] >= 5 && serbuf[5] != 0) 401 if((serbuf[4] & 128) && !iap_btnshuffle) /* shuffle */
437 { 402 {
438 if((serbuf[5] & 1) && !iap_btnrepeat) /* repeat */ 403 iap_btnshuffle = true;
404 if(!global_settings.playlist_shuffle)
439 { 405 {
440 int oldmode = global_settings.repeat_mode; 406 global_settings.playlist_shuffle = 1;
441 iap_btnrepeat = true;
442
443 if (oldmode == REPEAT_ONE)
444 global_settings.repeat_mode = REPEAT_OFF;
445 else if (oldmode == REPEAT_ALL)
446 global_settings.repeat_mode = REPEAT_ONE;
447 else if (oldmode == REPEAT_OFF)
448 global_settings.repeat_mode = REPEAT_ALL;
449
450 settings_save(); 407 settings_save();
451 if (audio_status() & AUDIO_STATUS_PLAY) 408 if (audio_status() & AUDIO_STATUS_PLAY)
452 audio_flush_and_reload_tracks(); 409 playlist_randomise(NULL, current_tick, true);
453 } 410 }
454 else 411 else if(global_settings.playlist_shuffle)
455 iap_btnrepeat = false;
456
457 if(serbuf[5] & 16) /* ffwd */
458 { 412 {
459 iap_remotebtn |= BUTTON_RC_RIGHT; 413 global_settings.playlist_shuffle = 0;
460 } 414 settings_save();
461 if(serbuf[5] & 32) /* frwd */ 415 if (audio_status() & AUDIO_STATUS_PLAY)
462 { 416 playlist_sort(NULL, true);
463 iap_remotebtn |= BUTTON_RC_LEFT;
464 } 417 }
465 } 418 }
419 else
420 iap_btnshuffle = false;
466 } 421 }
467 /* Handle Mode 3 */ 422 else if(serbuf[0] >= 5 && serbuf[5] != 0)
468 else if (serbuf[1] == 0x03)
469 { 423 {
470 switch(serbuf[2]) 424 if((serbuf[5] & 1) && !iap_btnrepeat) /* repeat */
471 { 425 {
472 /* some kind of status packet? */ 426 int oldmode = global_settings.repeat_mode;
473 case 0x01: 427 iap_btnrepeat = true;
474 { 428
475 unsigned char data[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00}; 429 if (oldmode == REPEAT_ONE)
476 iap_send_pkt(data, sizeof(data)); 430 global_settings.repeat_mode = REPEAT_OFF;
477 break; 431 else if (oldmode == REPEAT_ALL)
478 } 432 global_settings.repeat_mode = REPEAT_ONE;
433 else if (oldmode == REPEAT_OFF)
434 global_settings.repeat_mode = REPEAT_ALL;
479 435
480 case 0x08: 436 settings_save();
481 { 437 if (audio_status() & AUDIO_STATUS_PLAY)
482 /* ACK */ 438 audio_flush_and_reload_tracks();
483 unsigned char data[] = {0x03, 0x00, 0x00, 0x08}; 439 }
484 iap_send_pkt(data, sizeof(data)); 440 else
485 break; 441 iap_btnrepeat = false;
486 } 442
487 443 if(serbuf[5] & 16) /* ffwd */
488 case 0x0C: 444 {
489 { 445 iap_remotebtn |= BUTTON_RC_RIGHT;
490 /* request ipod volume */ 446 }
491 if (serbuf[3] == 0x04) 447 if(serbuf[5] & 32) /* frwd */
492 { 448 {
493 iap_set_remote_volume(); 449 iap_remotebtn |= BUTTON_RC_LEFT;
494 }
495 break;
496 }
497 /* get volume from accessory */
498 case 0x0E:
499 if (serbuf[3] == 0x04)
500 global_settings.volume = (-58)+((int)serbuf[5]+1)/4;
501 sound_set_volume(global_settings.volume);
502 break;
503 } 450 }
504 } 451 }
505 /* Handle Mode 4 */ 452}
506 else if (serbuf[1] == 0x04) 453
454static void iap_handlepkt_mode3(void)
455{
456 unsigned int cmd = serbuf[2];
457 switch (cmd)
507 { 458 {
508 switch (((unsigned long)serbuf[2] << 8) | serbuf[3]) 459 /* some kind of status packet? */
460 case 0x01:
509 { 461 {
510 /* Get data updated??? flag */ 462 unsigned char data[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00};
511 case 0x0009: 463 iap_send_pkt(data, sizeof(data));
512 { 464 break;
513 unsigned char data[] = {0x04, 0x00, 0x0A, 0x00}; 465 }
514 data[3] = iap_updateflag ? 0 : 1; 466
515 iap_send_pkt(data, sizeof(data)); 467 case 0x08:
516 break; 468 {
517 } 469 /* ACK */
518 /* Set data updated??? flag */ 470 unsigned char data[] = {0x03, 0x00, 0x00, 0x08};
519 case 0x000B: 471 iap_send_pkt(data, sizeof(data));
520 { 472 break;
521 iap_updateflag = serbuf[4] ? 0 : 1; 473 }
522 /* respond with cmd ok packet */ 474
523 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x0B}; 475 case 0x0C:
524 iap_send_pkt(data, sizeof(data)); 476 {
525 break; 477 /* request ipod volume */
526 } 478 if (serbuf[3] == 0x04)
527 /* Get iPod size? */
528 case 0x0012:
529 {
530 unsigned char data[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
531 iap_send_pkt(data, sizeof(data));
532 break;
533 }
534 /* Get count of given types */
535 case 0x0018:
536 {
537 unsigned char data[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
538 unsigned long num = 0;
539 switch(serbuf[4]) /* type number */
540 {
541 case 0x01: /* total number of playlists */
542 num = 1;
543 break;
544 case 0x05: /* total number of songs */
545 num = 1;
546 }
547 data[3] = num >> 24;
548 data[4] = num >> 16;
549 data[5] = num >> 8;
550 data[6] = num;
551 iap_send_pkt(data, sizeof(data));
552 break;
553 }
554 /* Get time and status */
555 case 0x001C:
556 {
557 unsigned char data[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
559 struct mp3entry *id3 = audio_current_track();
560 unsigned long time_total = id3->length;
561 unsigned long time_elapsed = id3->elapsed;
562 int status = audio_status();
563 data[3] = time_total >> 24;
564 data[4] = time_total >> 16;
565 data[5] = time_total >> 8;
566 data[6] = time_total;
567 data[7] = time_elapsed >> 24;
568 data[8] = time_elapsed >> 16;
569 data[9] = time_elapsed >> 8;
570 data[10] = time_elapsed;
571 if (status == AUDIO_STATUS_PLAY)
572 data[11] = 0x01; /* play */
573 else if (status & AUDIO_STATUS_PAUSE)
574 data[11] = 0x02; /* pause */
575 iap_send_pkt(data, sizeof(data));
576 break;
577 }
578 /* Get current pos in playlist */
579 case 0x001E:
580 {
581 unsigned char data[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00};
582 long playlist_pos = playlist_next(0);
583 playlist_pos -= playlist_get_first_index(NULL);
584 if(playlist_pos < 0)
585 playlist_pos += playlist_amount();
586 data[3] = playlist_pos >> 24;
587 data[4] = playlist_pos >> 16;
588 data[5] = playlist_pos >> 8;
589 data[6] = playlist_pos;
590 iap_send_pkt(data, sizeof(data));
591 break;
592 }
593 /* Get title of a song number */
594 case 0x0020:
595 /* Get artist of a song number */
596 case 0x0022:
597 /* Get album of a song number */
598 case 0x0024:
599 {
600 unsigned char data[70] = {0x04, 0x00, 0xFF};
601 struct mp3entry id3;
602 int fd;
603 size_t len;
604 long tracknum = (signed long)serbuf[4] << 24 |
605 (signed long)serbuf[5] << 16 |
606 (signed long)serbuf[6] << 8 | serbuf[7];
607 data[2] = serbuf[3] + 1;
608 memcpy(&id3, audio_current_track(), sizeof(id3));
609 tracknum += playlist_get_first_index(NULL);
610 if(tracknum >= playlist_amount())
611 tracknum -= playlist_amount();
612
613 /* If the tracknumber is not the current one,
614 read id3 from disk */
615 if(playlist_next(0) != tracknum)
616 {
617 struct playlist_track_info info;
618 playlist_get_track_info(NULL, tracknum, &info);
619 fd = open(info.filename, O_RDONLY);
620 memset(&id3, 0, sizeof(struct mp3entry));
621 get_metadata(&id3, fd, info.filename);
622 close(fd);
623 }
624
625 /* Return the requested track data */
626 switch(serbuf[3])
627 {
628 case 0x20:
629 len = strlcpy((char *)&data[3], id3.title, 64);
630 iap_send_pkt(data, 4+len);
631 break;
632 case 0x22:
633 len = strlcpy((char *)&data[3], id3.artist, 64);
634 iap_send_pkt(data, 4+len);
635 break;
636 case 0x24:
637 len = strlcpy((char *)&data[3], id3.album, 64);
638 iap_send_pkt(data, 4+len);
639 break;
640 }
641 break;
642 }
643 /* Set polling mode */
644 case 0x0026:
645 { 479 {
646 iap_pollspeed = serbuf[4] ? 1 : 0; 480 iap_set_remote_volume();
647 /*responsed with cmd ok packet */
648 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x26};
649 iap_send_pkt(data, sizeof(data));
650 break;
651 } 481 }
652 /* AiR playback control */ 482 break;
653 case 0x0029: 483 }
654 { 484 /* get volume from accessory */
655 /* respond with cmd ok packet */ 485 case 0x0E:
656 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x29}; 486 {
657 iap_send_pkt(data, sizeof(data)); 487 if (serbuf[3] == 0x04)
658 switch(serbuf[4]) 488 global_settings.volume = (-58)+((int)serbuf[5]+1)/4;
659 { 489 sound_set_volume(global_settings.volume); /* indent BUG? */
660 case 0x01: /* play/pause */ 490 break;
661 iap_remotebtn = BUTTON_RC_PLAY; 491 }
662 iap_repeatbtn = 2; 492 }
663 iap_remotetick = false; 493}
664 iap_changedctr = 1; 494
665 break; 495static void iap_handlepkt_mode4(void)
666 case 0x02: /* stop */ 496{
667 iap_remotebtn = BUTTON_RC_PLAY|BUTTON_REPEAT; 497 unsigned int cmd = (serbuf[2] << 8) | serbuf[3];
668 iap_repeatbtn = 2; 498 switch (cmd)
669 iap_remotetick = false; 499 {
670 iap_changedctr = 1; 500 /* Get data updated??? flag */
671 break; 501 case 0x0009:
672 case 0x03: /* skip++ */ 502 {
673 iap_remotebtn = BUTTON_RC_RIGHT; 503 unsigned char data[] = {0x04, 0x00, 0x0A, 0x00};
674 iap_repeatbtn = 2; 504 data[3] = iap_updateflag ? 0 : 1;
675 iap_remotetick = false; 505 iap_send_pkt(data, sizeof(data));
676 break; 506 break;
677 case 0x04: /* skip-- */ 507 }
678 iap_remotebtn = BUTTON_RC_LEFT; 508 /* Set data updated??? flag */
679 iap_repeatbtn = 2; 509 case 0x000B:
680 iap_remotetick = false; 510 {
681 break; 511 iap_updateflag = serbuf[4] ? 0 : 1;
682 case 0x05: /* ffwd */ 512 /* respond with cmd ok packet */
683 iap_remotebtn = BUTTON_RC_RIGHT; 513 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x0B};
684 iap_remotetick = false; 514 iap_send_pkt(data, sizeof(data));
685 if(iap_pollspeed) iap_pollspeed = 5; 515 break;
686 break; 516 }
687 case 0x06: /* frwd */ 517 /* Get iPod size? */
688 iap_remotebtn = BUTTON_RC_LEFT; 518 case 0x0012:
689 iap_remotetick = false; 519 {
690 if(iap_pollspeed) iap_pollspeed = 5; 520 unsigned char data[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
691 break; 521 iap_send_pkt(data, sizeof(data));
692 case 0x07: /* end ffwd/frwd */ 522 break;
693 iap_remotebtn = BUTTON_NONE; 523 }
694 iap_remotetick = false; 524 /* Get count of given types */
695 if(iap_pollspeed) iap_pollspeed = 1; 525 case 0x0018:
696 break; 526 {
697 } 527 unsigned char data[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
698 break; 528 unsigned long num = 0;
529 switch(serbuf[4]) /* type number */
530 {
531 case 0x01: /* total number of playlists */
532 num = 1;
533 break;
534 case 0x05: /* total number of songs */
535 num = 1;
536 }
537 data[3] = num >> 24;
538 data[4] = num >> 16;
539 data[5] = num >> 8;
540 data[6] = num;
541 iap_send_pkt(data, sizeof(data));
542 break;
543 }
544 /* Get time and status */
545 case 0x001C:
546 {
547 unsigned char data[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
549 struct mp3entry *id3 = audio_current_track();
550 unsigned long time_total = id3->length;
551 unsigned long time_elapsed = id3->elapsed;
552 int status = audio_status();
553 data[3] = time_total >> 24;
554 data[4] = time_total >> 16;
555 data[5] = time_total >> 8;
556 data[6] = time_total;
557 data[7] = time_elapsed >> 24;
558 data[8] = time_elapsed >> 16;
559 data[9] = time_elapsed >> 8;
560 data[10] = time_elapsed;
561 if (status == AUDIO_STATUS_PLAY)
562 data[11] = 0x01; /* play */
563 else if (status & AUDIO_STATUS_PAUSE)
564 data[11] = 0x02; /* pause */
565 iap_send_pkt(data, sizeof(data));
566 break;
567 }
568 /* Get current pos in playlist */
569 case 0x001E:
570 {
571 unsigned char data[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00};
572 long playlist_pos = playlist_next(0);
573 playlist_pos -= playlist_get_first_index(NULL);
574 if(playlist_pos < 0)
575 playlist_pos += playlist_amount();
576 data[3] = playlist_pos >> 24;
577 data[4] = playlist_pos >> 16;
578 data[5] = playlist_pos >> 8;
579 data[6] = playlist_pos;
580 iap_send_pkt(data, sizeof(data));
581 break;
582 }
583 /* Get title of a song number */
584 case 0x0020:
585 /* Get artist of a song number */
586 case 0x0022:
587 /* Get album of a song number */
588 case 0x0024:
589 {
590 unsigned char data[70] = {0x04, 0x00, 0xFF};
591 struct mp3entry id3;
592 int fd;
593 size_t len;
594 long tracknum = (signed long)serbuf[4] << 24 |
595 (signed long)serbuf[5] << 16 |
596 (signed long)serbuf[6] << 8 | serbuf[7];
597 data[2] = serbuf[3] + 1;
598 memcpy(&id3, audio_current_track(), sizeof(id3));
599 tracknum += playlist_get_first_index(NULL);
600 if(tracknum >= playlist_amount())
601 tracknum -= playlist_amount();
602
603 /* If the tracknumber is not the current one,
604 read id3 from disk */
605 if(playlist_next(0) != tracknum)
606 {
607 struct playlist_track_info info;
608 playlist_get_track_info(NULL, tracknum, &info);
609 fd = open(info.filename, O_RDONLY);
610 memset(&id3, 0, sizeof(struct mp3entry));
611 get_metadata(&id3, fd, info.filename);
612 close(fd);
613 }
614
615 /* Return the requested track data */
616 switch(serbuf[3])
617 {
618 case 0x20:
619 len = strlcpy((char *)&data[3], id3.title, 64);
620 iap_send_pkt(data, 4+len);
621 break;
622 case 0x22:
623 len = strlcpy((char *)&data[3], id3.artist, 64);
624 iap_send_pkt(data, 4+len);
625 break;
626 case 0x24:
627 len = strlcpy((char *)&data[3], id3.album, 64);
628 iap_send_pkt(data, 4+len);
629 break;
699 } 630 }
700 /* Get shuffle mode */ 631 break;
701 case 0x002C: 632 }
633 /* Set polling mode */
634 case 0x0026:
635 {
636 iap_pollspeed = serbuf[4] ? 1 : 0;
637 /*responsed with cmd ok packet */
638 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x26};
639 iap_send_pkt(data, sizeof(data));
640 break;
641 }
642 /* AiR playback control */
643 case 0x0029:
644 {
645 /* respond with cmd ok packet */
646 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x29};
647 iap_send_pkt(data, sizeof(data));
648 switch(serbuf[4])
702 { 649 {
703 unsigned char data[] = {0x04, 0x00, 0x2D, 0x00}; 650 case 0x01: /* play/pause */
704 data[3] = global_settings.playlist_shuffle ? 1 : 0; 651 iap_remotebtn = BUTTON_RC_PLAY;
705 iap_send_pkt(data, sizeof(data)); 652 iap_repeatbtn = 2;
706 break; 653 iap_remotetick = false;
654 iap_changedctr = 1;
655 break;
656 case 0x02: /* stop */
657 iap_remotebtn = BUTTON_RC_PLAY|BUTTON_REPEAT;
658 iap_repeatbtn = 2;
659 iap_remotetick = false;
660 iap_changedctr = 1;
661 break;
662 case 0x03: /* skip++ */
663 iap_remotebtn = BUTTON_RC_RIGHT;
664 iap_repeatbtn = 2;
665 iap_remotetick = false;
666 break;
667 case 0x04: /* skip-- */
668 iap_remotebtn = BUTTON_RC_LEFT;
669 iap_repeatbtn = 2;
670 iap_remotetick = false;
671 break;
672 case 0x05: /* ffwd */
673 iap_remotebtn = BUTTON_RC_RIGHT;
674 iap_remotetick = false;
675 if(iap_pollspeed) iap_pollspeed = 5;
676 break;
677 case 0x06: /* frwd */
678 iap_remotebtn = BUTTON_RC_LEFT;
679 iap_remotetick = false;
680 if(iap_pollspeed) iap_pollspeed = 5;
681 break;
682 case 0x07: /* end ffwd/frwd */
683 iap_remotebtn = BUTTON_NONE;
684 iap_remotetick = false;
685 if(iap_pollspeed) iap_pollspeed = 1;
686 break;
707 } 687 }
708 /* Set shuffle mode */ 688 break;
709 case 0x002E: 689 }
690 /* Get shuffle mode */
691 case 0x002C:
692 {
693 unsigned char data[] = {0x04, 0x00, 0x2D, 0x00};
694 data[3] = global_settings.playlist_shuffle ? 1 : 0;
695 iap_send_pkt(data, sizeof(data));
696 break;
697 }
698 /* Set shuffle mode */
699 case 0x002E:
700 {
701 if(serbuf[4] && !global_settings.playlist_shuffle)
710 { 702 {
711 if(serbuf[4] && !global_settings.playlist_shuffle) 703 global_settings.playlist_shuffle = 1;
712 { 704 settings_save();
713 global_settings.playlist_shuffle = 1; 705 if (audio_status() & AUDIO_STATUS_PLAY)
714 settings_save(); 706 playlist_randomise(NULL, current_tick, true);
715 if (audio_status() & AUDIO_STATUS_PLAY)
716 playlist_randomise(NULL, current_tick, true);
717 }
718 else if(!serbuf[4] && global_settings.playlist_shuffle)
719 {
720 global_settings.playlist_shuffle = 0;
721 settings_save();
722 if (audio_status() & AUDIO_STATUS_PLAY)
723 playlist_sort(NULL, true);
724 }
725
726
727 /* respond with cmd ok packet */
728 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x2E};
729 iap_send_pkt(data, sizeof(data));
730 break;
731 } 707 }
732 /* Get repeat mode */ 708 else if(!serbuf[4] && global_settings.playlist_shuffle)
733 case 0x002F:
734 { 709 {
735 unsigned char data[] = {0x04, 0x00, 0x30, 0x00}; 710 global_settings.playlist_shuffle = 0;
736 if(global_settings.repeat_mode == REPEAT_OFF) 711 settings_save();
737 data[3] = 0; 712 if (audio_status() & AUDIO_STATUS_PLAY)
738 else if(global_settings.repeat_mode == REPEAT_ONE) 713 playlist_sort(NULL, true);
739 data[3] = 1;
740 else
741 data[3] = 2;
742 iap_send_pkt(data, sizeof(data));
743 break;
744 } 714 }
745 /* Set repeat mode */
746 case 0x0031:
747 {
748 int oldmode = global_settings.repeat_mode;
749 if (serbuf[4] == 0)
750 global_settings.repeat_mode = REPEAT_OFF;
751 else if (serbuf[4] == 1)
752 global_settings.repeat_mode = REPEAT_ONE;
753 else if (serbuf[4] == 2)
754 global_settings.repeat_mode = REPEAT_ALL;
755 715
756 if (oldmode != global_settings.repeat_mode) 716
757 { 717 /* respond with cmd ok packet */
758 settings_save(); 718 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x2E};
759 if (audio_status() & AUDIO_STATUS_PLAY) 719 iap_send_pkt(data, sizeof(data));
760 audio_flush_and_reload_tracks(); 720 break;
761 } 721 }
722 /* Get repeat mode */
723 case 0x002F:
724 {
725 unsigned char data[] = {0x04, 0x00, 0x30, 0x00};
726 if(global_settings.repeat_mode == REPEAT_OFF)
727 data[3] = 0;
728 else if(global_settings.repeat_mode == REPEAT_ONE)
729 data[3] = 1;
730 else
731 data[3] = 2;
732 iap_send_pkt(data, sizeof(data));
733 break;
734 }
735 /* Set repeat mode */
736 case 0x0031:
737 {
738 int oldmode = global_settings.repeat_mode;
739 if (serbuf[4] == 0)
740 global_settings.repeat_mode = REPEAT_OFF;
741 else if (serbuf[4] == 1)
742 global_settings.repeat_mode = REPEAT_ONE;
743 else if (serbuf[4] == 2)
744 global_settings.repeat_mode = REPEAT_ALL;
762 745
763 /* respond with cmd ok packet */ 746 if (oldmode != global_settings.repeat_mode)
764 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x31};
765 iap_send_pkt(data, sizeof(data));
766 break;
767 }
768 /* Get Screen Size */
769 case 0x0033:
770 { 747 {
771 unsigned char data[] = {0x04, 0x00, 0x34, 748 settings_save();
772 LCD_WIDTH >> 8, LCD_WIDTH & 0xff, 749 if (audio_status() & AUDIO_STATUS_PLAY)
773 LCD_HEIGHT >> 8, LCD_HEIGHT & 0xff, 750 audio_flush_and_reload_tracks();
774 0x01};
775 iap_send_pkt(data, sizeof(data));
776 break;
777 }
778 /* Get number songs in current playlist */
779 case 0x0035:
780 {
781 unsigned char data[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
782 unsigned long playlist_amt = playlist_amount();
783 data[3] = playlist_amt >> 24;
784 data[4] = playlist_amt >> 16;
785 data[5] = playlist_amt >> 8;
786 data[6] = playlist_amt;
787 iap_send_pkt(data, sizeof(data));
788 break;
789 }
790 /* Jump to track number in current playlist */
791 case 0x0037:
792 {
793 int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE));
794 long tracknum = (signed long)serbuf[4] << 24 |
795 (signed long)serbuf[5] << 16 |
796 (signed long)serbuf[6] << 8 | serbuf[7];
797 audio_pause();
798 audio_skip(tracknum - playlist_next(0));
799 if (!paused)
800 audio_resume();
801
802 /* respond with cmd ok packet */
803 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
804 data[4] = serbuf[2];
805 data[5] = serbuf[3];
806 iap_send_pkt(data, sizeof(data));
807 break;
808 }
809 default:
810 {
811 /* default response is with cmd ok packet */
812 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
813 data[4] = serbuf[2];
814 data[5] = serbuf[3];
815 iap_send_pkt(data, sizeof(data));
816 break;
817 } 751 }
752
753 /* respond with cmd ok packet */
754 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x31};
755 iap_send_pkt(data, sizeof(data));
756 break;
757 }
758 /* Get Screen Size */
759 case 0x0033:
760 {
761 unsigned char data[] = {0x04, 0x00, 0x34,
762 LCD_WIDTH >> 8, LCD_WIDTH & 0xff,
763 LCD_HEIGHT >> 8, LCD_HEIGHT & 0xff,
764 0x01};
765 iap_send_pkt(data, sizeof(data));
766 break;
767 }
768 /* Get number songs in current playlist */
769 case 0x0035:
770 {
771 unsigned char data[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
772 unsigned long playlist_amt = playlist_amount();
773 data[3] = playlist_amt >> 24;
774 data[4] = playlist_amt >> 16;
775 data[5] = playlist_amt >> 8;
776 data[6] = playlist_amt;
777 iap_send_pkt(data, sizeof(data));
778 break;
779 }
780 /* Jump to track number in current playlist */
781 case 0x0037:
782 {
783 int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE));
784 long tracknum = (signed long)serbuf[4] << 24 |
785 (signed long)serbuf[5] << 16 |
786 (signed long)serbuf[6] << 8 | serbuf[7];
787 audio_pause();
788 audio_skip(tracknum - playlist_next(0));
789 if (!paused)
790 audio_resume();
791
792 /* respond with cmd ok packet */
793 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
794 data[4] = serbuf[2];
795 data[5] = serbuf[3];
796 iap_send_pkt(data, sizeof(data));
797 break;
798 }
799 default:
800 {
801 /* default response is with cmd ok packet */
802 unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
803 data[4] = serbuf[2];
804 data[5] = serbuf[3];
805 iap_send_pkt(data, sizeof(data));
806 break;
818 } 807 }
819 } 808 }
820 /* Handle Mode 7 */ 809}
821 else if (serbuf[1] == 0x07) 810
811static void iap_handlepkt_mode7(void)
812{
813 unsigned int cmd = serbuf[2];
814 switch (cmd)
822 { 815 {
823 switch(serbuf[2]) 816 /* tuner capabilities */
817 case 0x02:
824 { 818 {
825 /* tuner capabilities */ 819 /* do nothing */
826 case 0x02: 820
827 { 821 unsigned char data[] = {0x00, 0x27, 0x00};
828 /* do nothing */ 822 iap_send_pkt(data, sizeof(data));
829 823 break;
830 unsigned char data[] = {0x00, 0x27, 0x00}; 824 }
831 iap_send_pkt(data, sizeof(data)); 825 /* actual tuner frequency */
832 break; 826 case 0x0A:
833 } 827 /* fall through */
834 /* actual tuner frequency */ 828 /* tuner frequency from scan */
835 case 0x0A: 829 case 0x13:
836 /* fall through */ 830 {
837 /* tuner frequency from scan */ 831 rmt_tuner_freq(serbuf);
838 case 0x13: 832 break;
839 { 833 }
840 rmt_tuner_freq(serbuf); 834 /* RDS station name 0x21 1E 00 + ASCII text*/
841 break; 835 case 0x21:
842 } 836 {
843 /* RDS station name 0x21 1E 00 + ASCII text*/ 837 rmt_tuner_rds_data(serbuf);
844 case 0x21: 838 break;
845 {
846 rmt_tuner_rds_data(serbuf);
847 break;
848 }
849 } 839 }
850 } 840 }
841}
842
843void iap_handlepkt(void)
844{
845
846 if(!iap_setupflag) return;
847 if(serbuf[0] == 0) return;
848
849 /* if we are waiting for a remote button to go out,
850 delay the handling of the new packet */
851 if(!iap_remotetick)
852 {
853 queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
854 return;
855 }
856
857 unsigned char mode = serbuf[1];
858 switch (mode) {
859 case 0: iap_handlepkt_mode0(); break;
860 case 2: iap_handlepkt_mode2(); break;
861 case 3: iap_handlepkt_mode3(); break;
862 case 4: iap_handlepkt_mode4(); break;
863 case 7: iap_handlepkt_mode7(); break;
864 }
865
851 serbuf[0] = 0; 866 serbuf[0] = 0;
852} 867}
853 868