1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Alan Korr & Nick Robinson
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
31 #include "appevents.h"
41 #include "powermgmt.h"
44 #include "ipod_remote_tuner.h"
46 #define MAX_NAME_LENGTH 20
50 static volatile int iap_pollspeed
= 0;
51 static volatile bool iap_remotetick
= true;
52 static bool iap_setupflag
= false, iap_updateflag
= false;
53 static int iap_changedctr
= 0;
55 static unsigned long iap_remotebtn
= 0;
56 static int iap_repeatbtn
= 0;
57 static bool iap_btnrepeat
= false, iap_btnshuffle
= false;
59 static unsigned char serbuf
[RX_BUFLEN
];
60 static int serbuf_i
= 0;
62 static unsigned char response
[TX_BUFLEN
];
63 static int responselen
;
65 static char cur_dbrecord
[5] = {0};
67 static void iap_task(void)
71 count
+= iap_pollspeed
;
72 if (count
< (500/10)) return;
74 /* exec every 500ms if pollspeed == 1 */
76 queue_post(&button_queue
, SYS_IAP_PERIODIC
, 0);
79 /* called by playback when the next track starts */
80 static void iap_track_changed(void *ignored
)
86 void iap_setup(int ratenum
)
88 iap_bitrate_set(ratenum
);
90 iap_remotetick
= true;
91 iap_updateflag
= false;
94 iap_remotebtn
= BUTTON_NONE
;
95 tick_add_task(iap_task
);
96 add_event(PLAYBACK_EVENT_TRACK_CHANGE
, false, iap_track_changed
);
99 void iap_bitrate_set(int ratenum
)
107 serial_bitrate(9600);
110 serial_bitrate(19200);
113 serial_bitrate(38400);
116 serial_bitrate(57600);
127 parameters (0-n bytes)
128 checksum (length+mode+parameters+checksum == 0)
131 void iap_send_pkt(const unsigned char * data
, int len
)
135 if(len
> TX_BUFLEN
-4) len
= TX_BUFLEN
-4;
136 responselen
= len
+ 4;
141 chksum
= response
[2] = len
;
142 for(i
= 0; i
< len
; i
++)
145 response
[i
+3] = data
[i
];
148 response
[i
+3] = 0x100 - (chksum
& 0xFF);
150 for(i
= 0; i
< responselen
; i
++)
153 tx_writec(response
[i
]);
157 bool iap_getc(unsigned char x
)
159 static unsigned char last_x
= 0;
160 static bool newpkt
= true;
161 static unsigned char chksum
= 0;
163 /* Restart if the sync word is seen */
164 if(x
== 0x55 && last_x
== 0xff/* && newpkt*/)
173 if(serbuf_i
>= RX_BUFLEN
)
176 serbuf
[serbuf_i
++] = x
;
181 /* Broadcast to queue if we have a complete message */
182 if(serbuf_i
&& (serbuf_i
== serbuf
[0]+2))
187 queue_post(&button_queue
, SYS_IAP_HANDLEPKT
, 0);
192 void iap_periodic(void)
194 if(!iap_setupflag
) return;
195 if(!iap_pollspeed
) return;
197 /* PlayStatusChangeNotification */
198 unsigned char data
[] = {0x04, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x00};
199 unsigned long time_elapsed
= audio_current_track()->elapsed
;
201 time_elapsed
+= wps_get_ff_rewind_count();
203 data
[3] = 0x04; /* playing */
205 /* If info has changed, don't flag it right away */
206 if(iap_changedctr
&& iap_changedctr
++ >= iap_pollspeed
* 2)
208 /* track info has changed */
210 data
[3] = 0x01; /* 0x02 has same effect? */
211 iap_updateflag
= true;
214 data
[4] = time_elapsed
>> 24;
215 data
[5] = time_elapsed
>> 16;
216 data
[6] = time_elapsed
>> 8;
217 data
[7] = time_elapsed
;
218 iap_send_pkt(data
, sizeof(data
));
221 static void iap_set_remote_volume(void)
223 unsigned char data
[] = {0x03, 0x0D, 0x04, 0x00, 0x00};
224 data
[4] = (char)((global_settings
.volume
+58) * 4);
225 iap_send_pkt(data
, sizeof(data
));
228 static void cmd_ok_mode0(unsigned char cmd
)
230 unsigned char data
[] = {0x00, 0x02, 0x00, 0x00};
231 data
[3] = cmd
; /* respond with cmd */
232 iap_send_pkt(data
, sizeof(data
));
235 static void iap_handlepkt_mode0(void)
237 unsigned int cmd
= serbuf
[2];
242 /* FM transmitter sends this: */
243 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
244 if(serbuf
[3] == 0x05)
247 /* RF Transmitter: Begin transmission */
248 unsigned char data
[] = {0x05, 0x02};
249 iap_send_pkt(data
, sizeof(data
));
251 /* FM remote sends this: */
252 /* FF 55 03 00 01 02 FA (1st thing sent) */
253 else if(serbuf
[3] == 0x02)
255 /* useful only for apple firmware */
260 /* EnterRemoteUIMode, FM transmitter sends FF 55 02 00 05 F9 */
263 /* ACK Pending (3000 ms) */
264 unsigned char data
[] = {0x00, 0x02, 0x06,
265 0x05, 0x00, 0x00, 0x0B, 0xB8};
266 iap_send_pkt(data
, sizeof(data
));
271 /* ExitRemoteUIMode */
279 /* RequestiPodSoftwareVersion, Ipod FM remote sends FF 55 02 00 09 F5 */
282 /* ReturniPodSoftwareVersion, ipod5G firmware version */
283 unsigned char data
[] = {0x00, 0x0A, 0x01, 0x02, 0x01};
284 iap_send_pkt(data
, sizeof(data
));
288 /* RequestiPodModelNum */
291 /* ipod is supposed to work only with 5G and nano 2G */
292 /*{0x00, 0x0E, 0x00, 0x0B, 0x00, 0x05, 0x50, 0x41, 0x31, 0x34,
293 0x37, 0x4C, 0x4C, 0x00}; PA147LL (IPOD 5G 60 GO) */
294 /* ReturniPodModelNum */
295 unsigned char data
[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
296 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
297 iap_send_pkt(data
, sizeof(data
));
301 /* RequestLingoProtocolVersion */
304 /* ReturnLingoProtocolVersion */
305 unsigned char data
[] = {0x00, 0x10, 0x00, 0x01, 0x05};
307 iap_send_pkt(data
, sizeof(data
));
311 /* IdentifyDeviceLingoes */
316 if (serbuf
[6] == 0x35)
317 /* FM transmitter sends this: */
318 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
320 /* GetAccessoryInfo */
321 unsigned char data2
[] = {0x00, 0x27, 0x00};
322 iap_send_pkt(data2
, sizeof(data2
));
323 /* RF Transmitter: Begin transmission */
324 unsigned char data3
[] = {0x05, 0x02};
325 iap_send_pkt(data3
, sizeof(data3
));
330 /* ipod fm remote sends this: */
331 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
332 if (serbuf
[6] |= 0x80)
334 /* GetDevAuthenticationInfo */
335 unsigned char data4
[] = {0x00, 0x14};
336 iap_send_pkt(data4
, sizeof(data4
));
341 /* RetDevAuthenticationInfo */
344 /* AckDevAuthenticationInfo */
345 unsigned char data0
[] = {0x00, 0x16, 0x00};
346 iap_send_pkt(data0
, sizeof(data0
));
347 /* GetAccessoryInfo */
348 unsigned char data1
[] = {0x00, 0x27, 0x00};
349 iap_send_pkt(data1
, sizeof(data1
));
350 /* AckDevAuthenticationStatus, mandatory to enable some hardware */
351 unsigned char data2
[] = {0x00, 0x19, 0x00};
352 iap_send_pkt(data2
, sizeof(data2
));
353 if (radio_present
== 1)
356 unsigned char data3
[] = {0x07, 0x01};
357 iap_send_pkt(data3
, sizeof(data3
));
359 iap_set_remote_volume();
363 /* RetDevAuthenticationSignature */
366 /* Isn't used since we don't send the 0x00 0x17 command */
373 /* RetIpodOptions (ipod video send this) */
374 unsigned char data
[] = {0x00, 0x25, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x01};
376 iap_send_pkt(data
, sizeof(data
));
380 /* default response is with cmd ok packet */
389 static void iap_handlepkt_mode2(void)
391 if(serbuf
[2] != 0) return;
392 iap_remotebtn
= BUTTON_NONE
;
393 iap_remotetick
= false;
395 if(serbuf
[0] >= 3 && serbuf
[3] != 0)
398 iap_remotebtn
|= BUTTON_RC_PLAY
;
400 iap_remotebtn
|= BUTTON_RC_VOL_UP
;
402 iap_remotebtn
|= BUTTON_RC_VOL_DOWN
;
404 iap_remotebtn
|= BUTTON_RC_RIGHT
;
406 iap_remotebtn
|= BUTTON_RC_LEFT
;
408 else if(serbuf
[0] >= 4 && serbuf
[4] != 0)
410 if(serbuf
[4] & 1) /* play */
412 if (audio_status() != AUDIO_STATUS_PLAY
)
414 iap_remotebtn
|= BUTTON_RC_PLAY
;
416 iap_remotetick
= false;
420 if(serbuf
[4] & 2) /* pause */
422 if (audio_status() == AUDIO_STATUS_PLAY
)
424 iap_remotebtn
|= BUTTON_RC_PLAY
;
426 iap_remotetick
= false;
430 if((serbuf
[4] & 128) && !iap_btnshuffle
) /* shuffle */
432 iap_btnshuffle
= true;
433 if(!global_settings
.playlist_shuffle
)
435 global_settings
.playlist_shuffle
= 1;
437 if (audio_status() & AUDIO_STATUS_PLAY
)
438 playlist_randomise(NULL
, current_tick
, true);
440 else if(global_settings
.playlist_shuffle
)
442 global_settings
.playlist_shuffle
= 0;
444 if (audio_status() & AUDIO_STATUS_PLAY
)
445 playlist_sort(NULL
, true);
449 iap_btnshuffle
= false;
451 else if(serbuf
[0] >= 5 && serbuf
[5] != 0)
453 if((serbuf
[5] & 1) && !iap_btnrepeat
) /* repeat */
455 int oldmode
= global_settings
.repeat_mode
;
456 iap_btnrepeat
= true;
458 if (oldmode
== REPEAT_ONE
)
459 global_settings
.repeat_mode
= REPEAT_OFF
;
460 else if (oldmode
== REPEAT_ALL
)
461 global_settings
.repeat_mode
= REPEAT_ONE
;
462 else if (oldmode
== REPEAT_OFF
)
463 global_settings
.repeat_mode
= REPEAT_ALL
;
466 if (audio_status() & AUDIO_STATUS_PLAY
)
467 audio_flush_and_reload_tracks();
470 iap_btnrepeat
= false;
472 if(serbuf
[5] & 16) /* ffwd */
474 iap_remotebtn
|= BUTTON_RC_RIGHT
;
476 if(serbuf
[5] & 32) /* frwd */
478 iap_remotebtn
|= BUTTON_RC_LEFT
;
483 static void iap_handlepkt_mode3(void)
485 unsigned int cmd
= serbuf
[2];
488 /* GetCurrentEQProfileIndex */
491 /* RetCurrentEQProfileIndex */
492 unsigned char data
[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00};
493 iap_send_pkt(data
, sizeof(data
));
497 /* SetRemoteEventNotification */
501 unsigned char data
[] = {0x03, 0x00, 0x00, 0x08};
502 iap_send_pkt(data
, sizeof(data
));
506 /* GetiPodStateInfo */
509 /* request ipod volume */
510 if (serbuf
[3] == 0x04)
512 iap_set_remote_volume();
517 /* SetiPodStateInfo */
520 if (serbuf
[3] == 0x04)
521 global_settings
.volume
= (-58)+((int)serbuf
[5]+1)/4;
522 sound_set_volume(global_settings
.volume
); /* indent BUG? */
528 static void cmd_ok_mode4(unsigned int cmd
)
530 unsigned char data
[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
531 data
[4] = (cmd
>> 8) & 0xFF;
532 data
[5] = (cmd
>> 0) & 0xFF;
533 iap_send_pkt(data
, sizeof(data
));
536 static void get_playlist_name(unsigned char *dest
,
537 unsigned long item_offset
,
540 if (item_offset
== 0) return;
542 struct dirent
* playlist_file
= NULL
;
544 dp
= opendir(global_settings
.playlist_catalog_dir
);
547 unsigned long nbr
= 0;
548 while ((nbr
< item_offset
) && ((playlist_file
= readdir(dp
)) != NULL
))
550 /*Increment only if there is a playlist extension*/
551 if ((extension
=strrchr(playlist_file
->d_name
, '.')) != NULL
){
552 if ((strcmp(extension
, ".m3u") == 0 ||
553 strcmp(extension
, ".m3u8") == 0))
557 if (playlist_file
!= NULL
) {
558 strlcpy(dest
, playlist_file
->d_name
, max_length
);
563 static void iap_handlepkt_mode4(void)
565 unsigned int cmd
= (serbuf
[2] << 8) | serbuf
[3];
568 /* GetAudioBookSpeed */
571 /* ReturnAudioBookSpeed */
572 unsigned char data
[] = {0x04, 0x00, 0x0A, 0x00};
573 data
[3] = iap_updateflag
? 0 : 1;
574 iap_send_pkt(data
, sizeof(data
));
578 /* SetAudioBookSpeed */
581 iap_updateflag
= serbuf
[4] ? 0 : 1;
582 /* respond with cmd ok packet */
587 /* RequestProtocolVersion */
590 /* ReturnProtocolVersion */
591 unsigned char data
[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
592 iap_send_pkt(data
, sizeof(data
));
599 memcpy(cur_dbrecord
, serbuf
+ 4, 5);
604 /* GetNumberCategorizedDBRecords */
607 /* ReturnNumberCategorizedDBRecords */
608 unsigned char data
[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
609 unsigned long num
= 0;
612 unsigned long nbr_total_playlists
= 0;
613 struct dirent
* playlist_file
= NULL
;
616 switch(serbuf
[4]) /* type number */
618 case 0x01: /* total number of playlists */
619 dp
= opendir(global_settings
.playlist_catalog_dir
);
620 while ((playlist_file
= readdir(dp
)) != NULL
)
622 /*Increment only if there is a playlist extension*/
623 if ((extension
=strrchr(playlist_file
->d_name
, '.'))
625 if ((strcmp(extension
, ".m3u") == 0 ||
626 strcmp(extension
, ".m3u8") == 0))
627 nbr_total_playlists
++;
631 /*Add 1 for the main playlist*/
632 num
= nbr_total_playlists
+ 1;
634 case 0x05: /* total number of songs */
642 iap_send_pkt(data
, sizeof(data
));
646 /* RetrieveCategorizedDatabaseRecords */
649 /* ReturnCategorizedDatabaseRecord */
650 unsigned char data
[7 + MAX_NAME_LENGTH
] =
651 {0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00,
652 'R', 'O', 'C', 'K', 'B', 'O', 'X', '\0'};
654 unsigned long item_offset
= (serbuf
[5] << 24) | (serbuf
[6] << 16) |
655 (serbuf
[7] << 8) | serbuf
[8];
657 get_playlist_name(data
+ 7, item_offset
, MAX_NAME_LENGTH
);
658 /*Remove file extension*/
660 dot
= (strrchr(data
+7, '.'));
663 iap_send_pkt(data
, sizeof(data
));
670 /* ReturnPlayStatus */
671 unsigned char data
[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
673 struct mp3entry
*id3
= audio_current_track();
674 unsigned long time_total
= id3
->length
;
675 unsigned long time_elapsed
= id3
->elapsed
;
676 int status
= audio_status();
677 data
[3] = time_total
>> 24;
678 data
[4] = time_total
>> 16;
679 data
[5] = time_total
>> 8;
680 data
[6] = time_total
;
681 data
[7] = time_elapsed
>> 24;
682 data
[8] = time_elapsed
>> 16;
683 data
[9] = time_elapsed
>> 8;
684 data
[10] = time_elapsed
;
685 if (status
== AUDIO_STATUS_PLAY
)
686 data
[11] = 0x01; /* play */
687 else if (status
& AUDIO_STATUS_PAUSE
)
688 data
[11] = 0x02; /* pause */
689 iap_send_pkt(data
, sizeof(data
));
693 /* GetCurrentPlayingTrackIndex */
696 /* ReturnCurrentPlayingTrackIndex */
697 unsigned char data
[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00};
698 long playlist_pos
= playlist_next(0);
699 playlist_pos
-= playlist_get_first_index(NULL
);
701 playlist_pos
+= playlist_amount();
702 data
[3] = playlist_pos
>> 24;
703 data
[4] = playlist_pos
>> 16;
704 data
[5] = playlist_pos
>> 8;
705 data
[6] = playlist_pos
;
706 iap_send_pkt(data
, sizeof(data
));
710 /* GetIndexedPlayingTrackTitle */
712 /* GetIndexedPlayingTrackArtistName */
714 /* GetIndexedPlayingTrackAlbumName */
717 unsigned char data
[70] = {0x04, 0x00, 0xFF};
721 long tracknum
= (signed long)serbuf
[4] << 24 |
722 (signed long)serbuf
[5] << 16 |
723 (signed long)serbuf
[6] << 8 | serbuf
[7];
725 memcpy(&id3
, audio_current_track(), sizeof(id3
));
726 tracknum
+= playlist_get_first_index(NULL
);
727 if(tracknum
>= playlist_amount())
728 tracknum
-= playlist_amount();
730 /* If the tracknumber is not the current one,
731 read id3 from disk */
732 if(playlist_next(0) != tracknum
)
734 struct playlist_track_info info
;
735 playlist_get_track_info(NULL
, tracknum
, &info
);
736 fd
= open(info
.filename
, O_RDONLY
);
737 memset(&id3
, 0, sizeof(struct mp3entry
));
738 get_metadata(&id3
, fd
, info
.filename
);
742 /* Return the requested track data */
746 len
= strlcpy((char *)&data
[3], id3
.title
, 64);
747 iap_send_pkt(data
, 4+len
);
750 len
= strlcpy((char *)&data
[3], id3
.artist
, 64);
751 iap_send_pkt(data
, 4+len
);
754 len
= strlcpy((char *)&data
[3], id3
.album
, 64);
755 iap_send_pkt(data
, 4+len
);
761 /* SetPlayStatusChangeNotification */
764 iap_pollspeed
= serbuf
[4] ? 1 : 0;
765 /* respond with cmd ok packet */
770 /* PlayCurrentSelection */
773 switch (cur_dbrecord
[0])
777 unsigned long item_offset
= (cur_dbrecord
[1] << 24)|
778 (cur_dbrecord
[2] << 16)|
779 (cur_dbrecord
[3] << 8) |
781 unsigned char selected_playlist
782 [sizeof(global_settings
.playlist_catalog_dir
) + 1 + MAX_NAME_LENGTH
] = {0};
784 strcpy(selected_playlist
,
785 global_settings
.playlist_catalog_dir
);
786 int len
= strlen(selected_playlist
);
787 selected_playlist
[len
] = '/';
788 get_playlist_name (selected_playlist
+ len
+ 1,
791 ft_play_playlist(selected_playlist
,
792 global_settings
.playlist_catalog_dir
,
793 strrchr(selected_playlist
, '/') + 1);
806 case 0x01: /* play/pause */
807 iap_remotebtn
= BUTTON_RC_PLAY
;
809 iap_remotetick
= false;
812 case 0x02: /* stop */
813 iap_remotebtn
= BUTTON_RC_PLAY
|BUTTON_REPEAT
;
815 iap_remotetick
= false;
818 case 0x03: /* skip++ */
819 iap_remotebtn
= BUTTON_RC_RIGHT
;
821 iap_remotetick
= false;
823 case 0x04: /* skip-- */
824 iap_remotebtn
= BUTTON_RC_LEFT
;
826 iap_remotetick
= false;
828 case 0x05: /* ffwd */
829 iap_remotebtn
= BUTTON_RC_RIGHT
;
830 iap_remotetick
= false;
831 if(iap_pollspeed
) iap_pollspeed
= 5;
833 case 0x06: /* frwd */
834 iap_remotebtn
= BUTTON_RC_LEFT
;
835 iap_remotetick
= false;
836 if(iap_pollspeed
) iap_pollspeed
= 5;
838 case 0x07: /* end ffwd/frwd */
839 iap_remotebtn
= BUTTON_NONE
;
840 iap_remotetick
= false;
841 if(iap_pollspeed
) iap_pollspeed
= 1;
844 /* respond with cmd ok packet */
853 unsigned char data
[] = {0x04, 0x00, 0x2D, 0x00};
854 data
[3] = global_settings
.playlist_shuffle
? 1 : 0;
855 iap_send_pkt(data
, sizeof(data
));
862 if(serbuf
[4] && !global_settings
.playlist_shuffle
)
864 global_settings
.playlist_shuffle
= 1;
866 if (audio_status() & AUDIO_STATUS_PLAY
)
867 playlist_randomise(NULL
, current_tick
, true);
869 else if(!serbuf
[4] && global_settings
.playlist_shuffle
)
871 global_settings
.playlist_shuffle
= 0;
873 if (audio_status() & AUDIO_STATUS_PLAY
)
874 playlist_sort(NULL
, true);
877 /* respond with cmd ok packet */
886 unsigned char data
[] = {0x04, 0x00, 0x30, 0x00};
887 if(global_settings
.repeat_mode
== REPEAT_OFF
)
889 else if(global_settings
.repeat_mode
== REPEAT_ONE
)
893 iap_send_pkt(data
, sizeof(data
));
900 int oldmode
= global_settings
.repeat_mode
;
902 global_settings
.repeat_mode
= REPEAT_OFF
;
903 else if (serbuf
[4] == 1)
904 global_settings
.repeat_mode
= REPEAT_ONE
;
905 else if (serbuf
[4] == 2)
906 global_settings
.repeat_mode
= REPEAT_ALL
;
908 if (oldmode
!= global_settings
.repeat_mode
)
911 if (audio_status() & AUDIO_STATUS_PLAY
)
912 audio_flush_and_reload_tracks();
915 /* respond with cmd ok packet */
920 /* GetMonoDisplayImageLimits */
923 /* ReturnMonoDisplayImageLimits */
924 unsigned char data
[] = {0x04, 0x00, 0x34,
925 LCD_WIDTH
>> 8, LCD_WIDTH
& 0xff,
926 LCD_HEIGHT
>> 8, LCD_HEIGHT
& 0xff,
928 iap_send_pkt(data
, sizeof(data
));
932 /* GetNumPlayingTracks */
935 /* ReturnNumPlayingTracks */
936 unsigned char data
[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
937 unsigned long playlist_amt
= playlist_amount();
938 data
[3] = playlist_amt
>> 24;
939 data
[4] = playlist_amt
>> 16;
940 data
[5] = playlist_amt
>> 8;
941 data
[6] = playlist_amt
;
942 iap_send_pkt(data
, sizeof(data
));
946 /* SetCurrentPlayingTrack */
949 int paused
= (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE
));
950 long tracknum
= (signed long)serbuf
[4] << 24 |
951 (signed long)serbuf
[5] << 16 |
952 (signed long)serbuf
[6] << 8 | serbuf
[7];
954 audio_skip(tracknum
- playlist_next(0));
958 /* respond with cmd ok packet */
965 /* default response is with cmd ok packet */
972 static void iap_handlepkt_mode7(void)
974 unsigned int cmd
= serbuf
[2];
982 /* GetAccessoryInfo */
983 unsigned char data
[] = {0x00, 0x27, 0x00};
984 iap_send_pkt(data
, sizeof(data
));
994 rmt_tuner_freq(serbuf
);
998 /* RdsReadyNotify, RDS station name 0x21 1E 00 + ASCII text*/
1001 rmt_tuner_rds_data(serbuf
);
1007 void iap_handlepkt(void)
1010 if(!iap_setupflag
) return;
1011 if(serbuf
[0] == 0) return;
1013 /* if we are waiting for a remote button to go out,
1014 delay the handling of the new packet */
1017 queue_post(&button_queue
, SYS_IAP_HANDLEPKT
, 0);
1021 unsigned char mode
= serbuf
[1];
1023 case 0: iap_handlepkt_mode0(); break;
1024 case 2: iap_handlepkt_mode2(); break;
1025 case 3: iap_handlepkt_mode3(); break;
1026 case 4: iap_handlepkt_mode4(); break;
1027 case 7: iap_handlepkt_mode7(); break;
1033 int remote_control_rx(void)
1035 int btn
= iap_remotebtn
;
1041 iap_remotebtn
= BUTTON_NONE
;
1042 iap_remotetick
= true;
1046 iap_remotetick
= true;
1051 const unsigned char *iap_get_serbuf(void)