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"
49 static volatile int iap_pollspeed
= 0;
50 static volatile bool iap_remotetick
= true;
51 static bool iap_setupflag
= false, iap_updateflag
= false;
52 static int iap_changedctr
= 0;
54 static unsigned long iap_remotebtn
= 0;
55 static int iap_repeatbtn
= 0;
56 static bool iap_btnrepeat
= false, iap_btnshuffle
= false;
58 static unsigned char serbuf
[RX_BUFLEN
];
59 static int serbuf_i
= 0;
61 static unsigned char response
[TX_BUFLEN
];
62 static int responselen
;
64 static char cur_dbrecord
[5] = {0};
66 static void put_u32(unsigned char *buf
, uint32_t data
)
68 buf
[0] = (data
>> 24) & 0xFF;
69 buf
[1] = (data
>> 16) & 0xFF;
70 buf
[2] = (data
>> 8) & 0xFF;
71 buf
[3] = (data
>> 0) & 0xFF;
74 static uint32_t get_u32(const unsigned char *buf
)
76 return (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | buf
[3];
79 static void iap_task(void)
83 count
+= iap_pollspeed
;
84 if (count
< (500/10)) return;
86 /* exec every 500ms if pollspeed == 1 */
88 queue_post(&button_queue
, SYS_IAP_PERIODIC
, 0);
91 /* called by playback when the next track starts */
92 static void iap_track_changed(void *ignored
)
98 void iap_setup(int ratenum
)
100 iap_bitrate_set(ratenum
);
102 iap_remotetick
= true;
103 iap_updateflag
= false;
105 iap_setupflag
= true;
106 iap_remotebtn
= BUTTON_NONE
;
107 tick_add_task(iap_task
);
108 add_event(PLAYBACK_EVENT_TRACK_CHANGE
, false, iap_track_changed
);
111 void iap_bitrate_set(int ratenum
)
119 serial_bitrate(9600);
122 serial_bitrate(19200);
125 serial_bitrate(38400);
128 serial_bitrate(57600);
139 parameters (0-n bytes)
140 checksum (length+mode+parameters+checksum == 0)
143 void iap_send_pkt(const unsigned char * data
, int len
)
147 if(len
> TX_BUFLEN
-4) len
= TX_BUFLEN
-4;
148 responselen
= len
+ 4;
153 chksum
= response
[2] = len
;
154 for(i
= 0; i
< len
; i
++)
157 response
[i
+3] = data
[i
];
160 response
[i
+3] = 0x100 - (chksum
& 0xFF);
162 for(i
= 0; i
< responselen
; i
++)
165 tx_writec(response
[i
]);
169 bool iap_getc(unsigned char x
)
171 static unsigned char last_x
= 0;
172 static bool newpkt
= true;
173 static unsigned char chksum
= 0;
175 /* Restart if the sync word is seen */
176 if(x
== 0x55 && last_x
== 0xff/* && newpkt*/)
185 if(serbuf_i
>= RX_BUFLEN
)
188 serbuf
[serbuf_i
++] = x
;
193 /* Broadcast to queue if we have a complete message */
194 if(serbuf_i
&& (serbuf_i
== serbuf
[0]+2))
199 queue_post(&button_queue
, SYS_IAP_HANDLEPKT
, 0);
204 void iap_periodic(void)
206 if(!iap_setupflag
) return;
207 if(!iap_pollspeed
) return;
209 /* PlayStatusChangeNotification */
210 unsigned char data
[] = {0x04, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x00};
211 unsigned long time_elapsed
= audio_current_track()->elapsed
;
213 time_elapsed
+= wps_get_ff_rewind_count();
215 data
[3] = 0x04; /* playing */
217 /* If info has changed, don't flag it right away */
218 if(iap_changedctr
&& iap_changedctr
++ >= iap_pollspeed
* 2)
220 /* track info has changed */
222 data
[3] = 0x01; /* 0x02 has same effect? */
223 iap_updateflag
= true;
226 put_u32(&data
[4], time_elapsed
);
227 iap_send_pkt(data
, sizeof(data
));
230 static void iap_set_remote_volume(void)
232 unsigned char data
[] = {0x03, 0x0D, 0x04, 0x00, 0x00};
233 data
[4] = (char)((global_settings
.volume
+58) * 4);
234 iap_send_pkt(data
, sizeof(data
));
237 static void cmd_ok_mode0(unsigned char cmd
)
239 unsigned char data
[] = {0x00, 0x02, 0x00, 0x00};
240 data
[3] = cmd
; /* respond with cmd */
241 iap_send_pkt(data
, sizeof(data
));
244 static void iap_handlepkt_mode0(unsigned int len
, const unsigned char *buf
)
246 (void)len
; /* len currently unused */
248 unsigned int cmd
= buf
[1];
253 /* FM transmitter sends this: */
254 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
258 /* RF Transmitter: Begin transmission */
259 unsigned char data
[] = {0x05, 0x02};
260 iap_send_pkt(data
, sizeof(data
));
262 /* FM remote sends this: */
263 /* FF 55 03 00 01 02 FA (1st thing sent) */
264 else if (buf
[2] == 0x02)
266 /* useful only for apple firmware */
271 /* EnterRemoteUIMode, FM transmitter sends FF 55 02 00 05 F9 */
274 /* ACK Pending (3000 ms) */
275 unsigned char data
[] = {0x00, 0x02, 0x06,
276 0x05, 0x00, 0x00, 0x0B, 0xB8};
277 iap_send_pkt(data
, sizeof(data
));
282 /* ExitRemoteUIMode */
290 /* RequestiPodSoftwareVersion, Ipod FM remote sends FF 55 02 00 09 F5 */
293 /* ReturniPodSoftwareVersion, ipod5G firmware version */
294 unsigned char data
[] = {0x00, 0x0A, 0x01, 0x02, 0x01};
295 iap_send_pkt(data
, sizeof(data
));
299 /* RequestiPodModelNum */
302 /* ipod is supposed to work only with 5G and nano 2G */
303 /*{0x00, 0x0E, 0x00, 0x0B, 0x00, 0x05, 0x50, 0x41, 0x31, 0x34,
304 0x37, 0x4C, 0x4C, 0x00}; PA147LL (IPOD 5G 60 GO) */
305 /* ReturniPodModelNum */
306 unsigned char data
[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
307 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
308 iap_send_pkt(data
, sizeof(data
));
312 /* RequestLingoProtocolVersion */
315 /* ReturnLingoProtocolVersion */
316 unsigned char data
[] = {0x00, 0x10, 0x00, 0x01, 0x05};
318 iap_send_pkt(data
, sizeof(data
));
322 /* IdentifyDeviceLingoes */
327 uint32_t lingoes
= get_u32(&buf
[2]);
330 /* FM transmitter sends this: */
331 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
333 /* GetAccessoryInfo */
334 unsigned char data2
[] = {0x00, 0x27, 0x00};
335 iap_send_pkt(data2
, sizeof(data2
));
336 /* RF Transmitter: Begin transmission */
337 unsigned char data3
[] = {0x05, 0x02};
338 iap_send_pkt(data3
, sizeof(data3
));
342 /* ipod fm remote sends this: */
343 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
344 if (lingoes
& (1 << 7)) /* bit 7 = RF tuner lingo */
346 /* GetDevAuthenticationInfo */
347 unsigned char data4
[] = {0x00, 0x14};
348 iap_send_pkt(data4
, sizeof(data4
));
353 /* RetDevAuthenticationInfo */
356 /* AckDevAuthenticationInfo */
357 unsigned char data0
[] = {0x00, 0x16, 0x00};
358 iap_send_pkt(data0
, sizeof(data0
));
359 /* GetAccessoryInfo */
360 unsigned char data1
[] = {0x00, 0x27, 0x00};
361 iap_send_pkt(data1
, sizeof(data1
));
362 /* AckDevAuthenticationStatus, mandatory to enable some hardware */
363 unsigned char data2
[] = {0x00, 0x19, 0x00};
364 iap_send_pkt(data2
, sizeof(data2
));
365 if (radio_present
== 1)
368 unsigned char data3
[] = {0x07, 0x01};
369 iap_send_pkt(data3
, sizeof(data3
));
371 iap_set_remote_volume();
375 /* RetDevAuthenticationSignature */
378 /* Isn't used since we don't send the 0x00 0x17 command */
385 /* RetIpodOptions (ipod video send this) */
386 unsigned char data
[] = {0x00, 0x25, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x01};
388 iap_send_pkt(data
, sizeof(data
));
392 /* default response is with cmd ok packet */
401 static void iap_handlepkt_mode2(unsigned int len
, const unsigned char *buf
)
403 if(buf
[1] != 0) return;
404 iap_remotebtn
= BUTTON_NONE
;
405 iap_remotetick
= false;
407 if(len
>= 3 && buf
[2] != 0)
410 iap_remotebtn
|= BUTTON_RC_PLAY
;
412 iap_remotebtn
|= BUTTON_RC_VOL_UP
;
414 iap_remotebtn
|= BUTTON_RC_VOL_DOWN
;
416 iap_remotebtn
|= BUTTON_RC_RIGHT
;
418 iap_remotebtn
|= BUTTON_RC_LEFT
;
420 else if(len
>= 4 && buf
[3] != 0)
422 if(buf
[3] & 1) /* play */
424 if (audio_status() != AUDIO_STATUS_PLAY
)
426 iap_remotebtn
|= BUTTON_RC_PLAY
;
428 iap_remotetick
= false;
432 if(buf
[3] & 2) /* pause */
434 if (audio_status() == AUDIO_STATUS_PLAY
)
436 iap_remotebtn
|= BUTTON_RC_PLAY
;
438 iap_remotetick
= false;
442 if((buf
[3] & 128) && !iap_btnshuffle
) /* shuffle */
444 iap_btnshuffle
= true;
445 if(!global_settings
.playlist_shuffle
)
447 global_settings
.playlist_shuffle
= 1;
449 if (audio_status() & AUDIO_STATUS_PLAY
)
450 playlist_randomise(NULL
, current_tick
, true);
452 else if(global_settings
.playlist_shuffle
)
454 global_settings
.playlist_shuffle
= 0;
456 if (audio_status() & AUDIO_STATUS_PLAY
)
457 playlist_sort(NULL
, true);
461 iap_btnshuffle
= false;
463 else if(len
>= 5 && buf
[4] != 0)
465 if((buf
[4] & 1) && !iap_btnrepeat
) /* repeat */
467 int oldmode
= global_settings
.repeat_mode
;
468 iap_btnrepeat
= true;
470 if (oldmode
== REPEAT_ONE
)
471 global_settings
.repeat_mode
= REPEAT_OFF
;
472 else if (oldmode
== REPEAT_ALL
)
473 global_settings
.repeat_mode
= REPEAT_ONE
;
474 else if (oldmode
== REPEAT_OFF
)
475 global_settings
.repeat_mode
= REPEAT_ALL
;
478 if (audio_status() & AUDIO_STATUS_PLAY
)
479 audio_flush_and_reload_tracks();
482 iap_btnrepeat
= false;
484 if(buf
[4] & 16) /* ffwd */
486 iap_remotebtn
|= BUTTON_RC_RIGHT
;
488 if(buf
[4] & 32) /* frwd */
490 iap_remotebtn
|= BUTTON_RC_LEFT
;
495 static void iap_handlepkt_mode3(unsigned int len
, const unsigned char *buf
)
497 (void)len
; /* len currently unused */
499 unsigned int cmd
= buf
[1];
502 /* GetCurrentEQProfileIndex */
505 /* RetCurrentEQProfileIndex */
506 unsigned char data
[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00};
507 iap_send_pkt(data
, sizeof(data
));
511 /* SetRemoteEventNotification */
515 unsigned char data
[] = {0x03, 0x00, 0x00, 0x08};
516 iap_send_pkt(data
, sizeof(data
));
520 /* GetiPodStateInfo */
523 /* request ipod volume */
526 iap_set_remote_volume();
531 /* SetiPodStateInfo */
535 global_settings
.volume
= (-58)+((int)buf
[4]+1)/4;
536 sound_set_volume(global_settings
.volume
); /* indent BUG? */
542 static void cmd_ok_mode4(unsigned int cmd
)
544 unsigned char data
[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
545 data
[4] = (cmd
>> 8) & 0xFF;
546 data
[5] = (cmd
>> 0) & 0xFF;
547 iap_send_pkt(data
, sizeof(data
));
550 static void get_playlist_name(unsigned char *dest
,
551 unsigned long item_offset
,
554 if (item_offset
== 0) return;
556 struct dirent
* playlist_file
= NULL
;
558 dp
= opendir(global_settings
.playlist_catalog_dir
);
561 unsigned long nbr
= 0;
562 while ((nbr
< item_offset
) && ((playlist_file
= readdir(dp
)) != NULL
))
564 /*Increment only if there is a playlist extension*/
565 if ((extension
=strrchr(playlist_file
->d_name
, '.')) != NULL
){
566 if ((strcmp(extension
, ".m3u") == 0 ||
567 strcmp(extension
, ".m3u8") == 0))
571 if (playlist_file
!= NULL
) {
572 strlcpy(dest
, playlist_file
->d_name
, max_length
);
577 static void iap_handlepkt_mode4(unsigned int len
, const unsigned char *buf
)
579 (void)len
; /* len currently unused */
581 unsigned int cmd
= (buf
[1] << 8) | buf
[2];
584 /* GetAudioBookSpeed */
587 /* ReturnAudioBookSpeed */
588 unsigned char data
[] = {0x04, 0x00, 0x0A, 0x00};
589 data
[3] = iap_updateflag
? 0 : 1;
590 iap_send_pkt(data
, sizeof(data
));
594 /* SetAudioBookSpeed */
597 iap_updateflag
= buf
[3] ? 0 : 1;
598 /* respond with cmd ok packet */
603 /* RequestProtocolVersion */
606 /* ReturnProtocolVersion */
607 unsigned char data
[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
608 iap_send_pkt(data
, sizeof(data
));
615 memcpy(cur_dbrecord
, buf
+ 3, 5);
620 /* GetNumberCategorizedDBRecords */
623 /* ReturnNumberCategorizedDBRecords */
624 unsigned char data
[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
625 unsigned long num
= 0;
628 unsigned long nbr_total_playlists
= 0;
629 struct dirent
* playlist_file
= NULL
;
632 switch(buf
[3]) /* type number */
634 case 0x01: /* total number of playlists */
635 dp
= opendir(global_settings
.playlist_catalog_dir
);
636 while ((playlist_file
= readdir(dp
)) != NULL
)
638 /*Increment only if there is a playlist extension*/
639 if ((extension
=strrchr(playlist_file
->d_name
, '.'))
641 if ((strcmp(extension
, ".m3u") == 0 ||
642 strcmp(extension
, ".m3u8") == 0))
643 nbr_total_playlists
++;
647 /*Add 1 for the main playlist*/
648 num
= nbr_total_playlists
+ 1;
650 case 0x05: /* total number of songs */
654 put_u32(&data
[3], num
);
655 iap_send_pkt(data
, sizeof(data
));
659 /* RetrieveCategorizedDatabaseRecords */
662 /* ReturnCategorizedDatabaseRecord */
663 unsigned char data
[7 + MAX_PATH
] =
664 {0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00,
665 'R', 'O', 'C', 'K', 'B', 'O', 'X', '\0'};
667 unsigned long item_offset
= get_u32(&buf
[4]);
669 get_playlist_name(data
+ 7, item_offset
, MAX_PATH
);
670 /*Remove file extension*/
672 dot
= (strrchr(data
+7, '.'));
675 iap_send_pkt(data
, 7 + strlen(data
+7) + 1);
682 /* ReturnPlayStatus */
683 unsigned char data
[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
685 struct mp3entry
*id3
= audio_current_track();
686 unsigned long time_total
= id3
->length
;
687 unsigned long time_elapsed
= id3
->elapsed
;
688 int status
= audio_status();
689 put_u32(&data
[3], time_total
);
690 put_u32(&data
[7], time_elapsed
);
691 if (status
== AUDIO_STATUS_PLAY
)
692 data
[11] = 0x01; /* play */
693 else if (status
& AUDIO_STATUS_PAUSE
)
694 data
[11] = 0x02; /* pause */
695 iap_send_pkt(data
, sizeof(data
));
699 /* GetCurrentPlayingTrackIndex */
702 /* ReturnCurrentPlayingTrackIndex */
703 unsigned char data
[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00};
704 long playlist_pos
= playlist_next(0);
705 playlist_pos
-= playlist_get_first_index(NULL
);
707 playlist_pos
+= playlist_amount();
708 put_u32(&data
[3], playlist_pos
);
709 iap_send_pkt(data
, sizeof(data
));
713 /* GetIndexedPlayingTrackTitle */
715 /* GetIndexedPlayingTrackArtistName */
717 /* GetIndexedPlayingTrackAlbumName */
720 unsigned char data
[70] = {0x04, 0x00, 0xFF};
724 long tracknum
= get_u32(&buf
[3]);
727 memcpy(&id3
, audio_current_track(), sizeof(id3
));
728 tracknum
+= playlist_get_first_index(NULL
);
729 if(tracknum
>= playlist_amount())
730 tracknum
-= playlist_amount();
732 /* If the tracknumber is not the current one,
733 read id3 from disk */
734 if(playlist_next(0) != tracknum
)
736 struct playlist_track_info info
;
737 playlist_get_track_info(NULL
, tracknum
, &info
);
738 fd
= open(info
.filename
, O_RDONLY
);
739 memset(&id3
, 0, sizeof(struct mp3entry
));
740 get_metadata(&id3
, fd
, info
.filename
);
744 /* Return the requested track data */
748 len
= strlcpy((char *)&data
[3], id3
.title
, 64);
749 iap_send_pkt(data
, 4+len
);
752 len
= strlcpy((char *)&data
[3], id3
.artist
, 64);
753 iap_send_pkt(data
, 4+len
);
756 len
= strlcpy((char *)&data
[3], id3
.album
, 64);
757 iap_send_pkt(data
, 4+len
);
763 /* SetPlayStatusChangeNotification */
766 iap_pollspeed
= buf
[3] ? 1 : 0;
767 /* respond with cmd ok packet */
772 /* PlayCurrentSelection */
775 switch (cur_dbrecord
[0])
779 unsigned long item_offset
= get_u32(&cur_dbrecord
[1]);
781 unsigned char selected_playlist
782 [sizeof(global_settings
.playlist_catalog_dir
)
786 strcpy(selected_playlist
,
787 global_settings
.playlist_catalog_dir
);
788 int len
= strlen(selected_playlist
);
789 selected_playlist
[len
] = '/';
790 get_playlist_name (selected_playlist
+ len
+ 1,
793 ft_play_playlist(selected_playlist
,
794 global_settings
.playlist_catalog_dir
,
795 strrchr(selected_playlist
, '/') + 1);
808 case 0x01: /* play/pause */
809 iap_remotebtn
= BUTTON_RC_PLAY
;
811 iap_remotetick
= false;
814 case 0x02: /* stop */
815 iap_remotebtn
= BUTTON_RC_PLAY
|BUTTON_REPEAT
;
817 iap_remotetick
= false;
820 case 0x03: /* skip++ */
821 iap_remotebtn
= BUTTON_RC_RIGHT
;
823 iap_remotetick
= false;
825 case 0x04: /* skip-- */
826 iap_remotebtn
= BUTTON_RC_LEFT
;
828 iap_remotetick
= false;
830 case 0x05: /* ffwd */
831 iap_remotebtn
= BUTTON_RC_RIGHT
;
832 iap_remotetick
= false;
833 if(iap_pollspeed
) iap_pollspeed
= 5;
835 case 0x06: /* frwd */
836 iap_remotebtn
= BUTTON_RC_LEFT
;
837 iap_remotetick
= false;
838 if(iap_pollspeed
) iap_pollspeed
= 5;
840 case 0x07: /* end ffwd/frwd */
841 iap_remotebtn
= BUTTON_NONE
;
842 iap_remotetick
= false;
843 if(iap_pollspeed
) iap_pollspeed
= 1;
846 /* respond with cmd ok packet */
855 unsigned char data
[] = {0x04, 0x00, 0x2D, 0x00};
856 data
[3] = global_settings
.playlist_shuffle
? 1 : 0;
857 iap_send_pkt(data
, sizeof(data
));
864 if(buf
[3] && !global_settings
.playlist_shuffle
)
866 global_settings
.playlist_shuffle
= 1;
868 if (audio_status() & AUDIO_STATUS_PLAY
)
869 playlist_randomise(NULL
, current_tick
, true);
871 else if(!buf
[3] && global_settings
.playlist_shuffle
)
873 global_settings
.playlist_shuffle
= 0;
875 if (audio_status() & AUDIO_STATUS_PLAY
)
876 playlist_sort(NULL
, true);
879 /* respond with cmd ok packet */
888 unsigned char data
[] = {0x04, 0x00, 0x30, 0x00};
889 if(global_settings
.repeat_mode
== REPEAT_OFF
)
891 else if(global_settings
.repeat_mode
== REPEAT_ONE
)
895 iap_send_pkt(data
, sizeof(data
));
902 int oldmode
= global_settings
.repeat_mode
;
904 global_settings
.repeat_mode
= REPEAT_OFF
;
905 else if (buf
[3] == 1)
906 global_settings
.repeat_mode
= REPEAT_ONE
;
907 else if (buf
[3] == 2)
908 global_settings
.repeat_mode
= REPEAT_ALL
;
910 if (oldmode
!= global_settings
.repeat_mode
)
913 if (audio_status() & AUDIO_STATUS_PLAY
)
914 audio_flush_and_reload_tracks();
917 /* respond with cmd ok packet */
922 /* GetMonoDisplayImageLimits */
925 /* ReturnMonoDisplayImageLimits */
926 unsigned char data
[] = {0x04, 0x00, 0x34,
927 LCD_WIDTH
>> 8, LCD_WIDTH
& 0xff,
928 LCD_HEIGHT
>> 8, LCD_HEIGHT
& 0xff,
930 iap_send_pkt(data
, sizeof(data
));
934 /* GetNumPlayingTracks */
937 /* ReturnNumPlayingTracks */
938 unsigned char data
[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
939 unsigned long playlist_amt
= playlist_amount();
940 put_u32(&data
[3], playlist_amt
);
941 iap_send_pkt(data
, sizeof(data
));
945 /* SetCurrentPlayingTrack */
948 int paused
= (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE
));
949 long tracknum
= get_u32(&buf
[3]);
952 audio_skip(tracknum
- playlist_next(0));
956 /* respond with cmd ok packet */
963 /* default response is with cmd ok packet */
970 static void iap_handlepkt_mode7(unsigned int len
, const unsigned char *buf
)
972 unsigned int cmd
= buf
[1];
980 /* GetAccessoryInfo */
981 unsigned char data
[] = {0x00, 0x27, 0x00};
982 iap_send_pkt(data
, sizeof(data
));
992 rmt_tuner_freq(len
, buf
);
996 /* RdsReadyNotify, RDS station name 0x21 1E 00 + ASCII text*/
999 rmt_tuner_rds_data(len
, buf
);
1005 void iap_handlepkt(void)
1007 if(!iap_setupflag
) return;
1008 if(serbuf
[0] == 0) return;
1010 /* if we are waiting for a remote button to go out,
1011 delay the handling of the new packet */
1014 queue_post(&button_queue
, SYS_IAP_HANDLEPKT
, 0);
1018 /* get length and payload from serbuf */
1019 unsigned int len
= serbuf
[0];
1020 unsigned char *payload
= &serbuf
[1];
1022 unsigned char mode
= payload
[0];
1024 case 0: iap_handlepkt_mode0(len
, payload
); break;
1025 case 2: iap_handlepkt_mode2(len
, payload
); break;
1026 case 3: iap_handlepkt_mode3(len
, payload
); break;
1027 case 4: iap_handlepkt_mode4(len
, payload
); break;
1028 case 7: iap_handlepkt_mode7(len
, payload
); break;
1034 int remote_control_rx(void)
1036 int btn
= iap_remotebtn
;
1042 iap_remotebtn
= BUTTON_NONE
;
1043 iap_remotetick
= true;
1047 iap_remotetick
= true;
1052 const unsigned char *iap_get_serbuf(void)