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(void)
246 unsigned int cmd
= serbuf
[2];
251 /* FM transmitter sends this: */
252 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
253 if(serbuf
[3] == 0x05)
256 /* RF Transmitter: Begin transmission */
257 unsigned char data
[] = {0x05, 0x02};
258 iap_send_pkt(data
, sizeof(data
));
260 /* FM remote sends this: */
261 /* FF 55 03 00 01 02 FA (1st thing sent) */
262 else if(serbuf
[3] == 0x02)
264 /* useful only for apple firmware */
269 /* EnterRemoteUIMode, FM transmitter sends FF 55 02 00 05 F9 */
272 /* ACK Pending (3000 ms) */
273 unsigned char data
[] = {0x00, 0x02, 0x06,
274 0x05, 0x00, 0x00, 0x0B, 0xB8};
275 iap_send_pkt(data
, sizeof(data
));
280 /* ExitRemoteUIMode */
288 /* RequestiPodSoftwareVersion, Ipod FM remote sends FF 55 02 00 09 F5 */
291 /* ReturniPodSoftwareVersion, ipod5G firmware version */
292 unsigned char data
[] = {0x00, 0x0A, 0x01, 0x02, 0x01};
293 iap_send_pkt(data
, sizeof(data
));
297 /* RequestiPodModelNum */
300 /* ipod is supposed to work only with 5G and nano 2G */
301 /*{0x00, 0x0E, 0x00, 0x0B, 0x00, 0x05, 0x50, 0x41, 0x31, 0x34,
302 0x37, 0x4C, 0x4C, 0x00}; PA147LL (IPOD 5G 60 GO) */
303 /* ReturniPodModelNum */
304 unsigned char data
[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
305 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
306 iap_send_pkt(data
, sizeof(data
));
310 /* RequestLingoProtocolVersion */
313 /* ReturnLingoProtocolVersion */
314 unsigned char data
[] = {0x00, 0x10, 0x00, 0x01, 0x05};
316 iap_send_pkt(data
, sizeof(data
));
320 /* IdentifyDeviceLingoes */
325 uint32_t lingoes
= get_u32(&serbuf
[3]);
328 /* FM transmitter sends this: */
329 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
331 /* GetAccessoryInfo */
332 unsigned char data2
[] = {0x00, 0x27, 0x00};
333 iap_send_pkt(data2
, sizeof(data2
));
334 /* RF Transmitter: Begin transmission */
335 unsigned char data3
[] = {0x05, 0x02};
336 iap_send_pkt(data3
, sizeof(data3
));
340 /* ipod fm remote sends this: */
341 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
342 if (lingoes
& (1 << 7)) /* bit 7 = RF tuner lingo */
344 /* GetDevAuthenticationInfo */
345 unsigned char data4
[] = {0x00, 0x14};
346 iap_send_pkt(data4
, sizeof(data4
));
351 /* RetDevAuthenticationInfo */
354 /* AckDevAuthenticationInfo */
355 unsigned char data0
[] = {0x00, 0x16, 0x00};
356 iap_send_pkt(data0
, sizeof(data0
));
357 /* GetAccessoryInfo */
358 unsigned char data1
[] = {0x00, 0x27, 0x00};
359 iap_send_pkt(data1
, sizeof(data1
));
360 /* AckDevAuthenticationStatus, mandatory to enable some hardware */
361 unsigned char data2
[] = {0x00, 0x19, 0x00};
362 iap_send_pkt(data2
, sizeof(data2
));
363 if (radio_present
== 1)
366 unsigned char data3
[] = {0x07, 0x01};
367 iap_send_pkt(data3
, sizeof(data3
));
369 iap_set_remote_volume();
373 /* RetDevAuthenticationSignature */
376 /* Isn't used since we don't send the 0x00 0x17 command */
383 /* RetIpodOptions (ipod video send this) */
384 unsigned char data
[] = {0x00, 0x25, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x01};
386 iap_send_pkt(data
, sizeof(data
));
390 /* default response is with cmd ok packet */
399 static void iap_handlepkt_mode2(void)
401 if(serbuf
[2] != 0) return;
402 iap_remotebtn
= BUTTON_NONE
;
403 iap_remotetick
= false;
405 if(serbuf
[0] >= 3 && serbuf
[3] != 0)
408 iap_remotebtn
|= BUTTON_RC_PLAY
;
410 iap_remotebtn
|= BUTTON_RC_VOL_UP
;
412 iap_remotebtn
|= BUTTON_RC_VOL_DOWN
;
414 iap_remotebtn
|= BUTTON_RC_RIGHT
;
416 iap_remotebtn
|= BUTTON_RC_LEFT
;
418 else if(serbuf
[0] >= 4 && serbuf
[4] != 0)
420 if(serbuf
[4] & 1) /* play */
422 if (audio_status() != AUDIO_STATUS_PLAY
)
424 iap_remotebtn
|= BUTTON_RC_PLAY
;
426 iap_remotetick
= false;
430 if(serbuf
[4] & 2) /* pause */
432 if (audio_status() == AUDIO_STATUS_PLAY
)
434 iap_remotebtn
|= BUTTON_RC_PLAY
;
436 iap_remotetick
= false;
440 if((serbuf
[4] & 128) && !iap_btnshuffle
) /* shuffle */
442 iap_btnshuffle
= true;
443 if(!global_settings
.playlist_shuffle
)
445 global_settings
.playlist_shuffle
= 1;
447 if (audio_status() & AUDIO_STATUS_PLAY
)
448 playlist_randomise(NULL
, current_tick
, true);
450 else if(global_settings
.playlist_shuffle
)
452 global_settings
.playlist_shuffle
= 0;
454 if (audio_status() & AUDIO_STATUS_PLAY
)
455 playlist_sort(NULL
, true);
459 iap_btnshuffle
= false;
461 else if(serbuf
[0] >= 5 && serbuf
[5] != 0)
463 if((serbuf
[5] & 1) && !iap_btnrepeat
) /* repeat */
465 int oldmode
= global_settings
.repeat_mode
;
466 iap_btnrepeat
= true;
468 if (oldmode
== REPEAT_ONE
)
469 global_settings
.repeat_mode
= REPEAT_OFF
;
470 else if (oldmode
== REPEAT_ALL
)
471 global_settings
.repeat_mode
= REPEAT_ONE
;
472 else if (oldmode
== REPEAT_OFF
)
473 global_settings
.repeat_mode
= REPEAT_ALL
;
476 if (audio_status() & AUDIO_STATUS_PLAY
)
477 audio_flush_and_reload_tracks();
480 iap_btnrepeat
= false;
482 if(serbuf
[5] & 16) /* ffwd */
484 iap_remotebtn
|= BUTTON_RC_RIGHT
;
486 if(serbuf
[5] & 32) /* frwd */
488 iap_remotebtn
|= BUTTON_RC_LEFT
;
493 static void iap_handlepkt_mode3(void)
495 unsigned int cmd
= serbuf
[2];
498 /* GetCurrentEQProfileIndex */
501 /* RetCurrentEQProfileIndex */
502 unsigned char data
[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00};
503 iap_send_pkt(data
, sizeof(data
));
507 /* SetRemoteEventNotification */
511 unsigned char data
[] = {0x03, 0x00, 0x00, 0x08};
512 iap_send_pkt(data
, sizeof(data
));
516 /* GetiPodStateInfo */
519 /* request ipod volume */
520 if (serbuf
[3] == 0x04)
522 iap_set_remote_volume();
527 /* SetiPodStateInfo */
530 if (serbuf
[3] == 0x04)
531 global_settings
.volume
= (-58)+((int)serbuf
[5]+1)/4;
532 sound_set_volume(global_settings
.volume
); /* indent BUG? */
538 static void cmd_ok_mode4(unsigned int cmd
)
540 unsigned char data
[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
541 data
[4] = (cmd
>> 8) & 0xFF;
542 data
[5] = (cmd
>> 0) & 0xFF;
543 iap_send_pkt(data
, sizeof(data
));
546 static void get_playlist_name(unsigned char *dest
,
547 unsigned long item_offset
,
550 if (item_offset
== 0) return;
552 struct dirent
* playlist_file
= NULL
;
554 dp
= opendir(global_settings
.playlist_catalog_dir
);
557 unsigned long nbr
= 0;
558 while ((nbr
< item_offset
) && ((playlist_file
= readdir(dp
)) != NULL
))
560 /*Increment only if there is a playlist extension*/
561 if ((extension
=strrchr(playlist_file
->d_name
, '.')) != NULL
){
562 if ((strcmp(extension
, ".m3u") == 0 ||
563 strcmp(extension
, ".m3u8") == 0))
567 if (playlist_file
!= NULL
) {
568 strlcpy(dest
, playlist_file
->d_name
, max_length
);
573 static void iap_handlepkt_mode4(void)
575 unsigned int cmd
= (serbuf
[2] << 8) | serbuf
[3];
578 /* GetAudioBookSpeed */
581 /* ReturnAudioBookSpeed */
582 unsigned char data
[] = {0x04, 0x00, 0x0A, 0x00};
583 data
[3] = iap_updateflag
? 0 : 1;
584 iap_send_pkt(data
, sizeof(data
));
588 /* SetAudioBookSpeed */
591 iap_updateflag
= serbuf
[4] ? 0 : 1;
592 /* respond with cmd ok packet */
597 /* RequestProtocolVersion */
600 /* ReturnProtocolVersion */
601 unsigned char data
[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
602 iap_send_pkt(data
, sizeof(data
));
609 memcpy(cur_dbrecord
, serbuf
+ 4, 5);
614 /* GetNumberCategorizedDBRecords */
617 /* ReturnNumberCategorizedDBRecords */
618 unsigned char data
[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
619 unsigned long num
= 0;
622 unsigned long nbr_total_playlists
= 0;
623 struct dirent
* playlist_file
= NULL
;
626 switch(serbuf
[4]) /* type number */
628 case 0x01: /* total number of playlists */
629 dp
= opendir(global_settings
.playlist_catalog_dir
);
630 while ((playlist_file
= readdir(dp
)) != NULL
)
632 /*Increment only if there is a playlist extension*/
633 if ((extension
=strrchr(playlist_file
->d_name
, '.'))
635 if ((strcmp(extension
, ".m3u") == 0 ||
636 strcmp(extension
, ".m3u8") == 0))
637 nbr_total_playlists
++;
641 /*Add 1 for the main playlist*/
642 num
= nbr_total_playlists
+ 1;
644 case 0x05: /* total number of songs */
648 put_u32(&data
[3], num
);
649 iap_send_pkt(data
, sizeof(data
));
653 /* RetrieveCategorizedDatabaseRecords */
656 /* ReturnCategorizedDatabaseRecord */
657 unsigned char data
[7 + MAX_PATH
] =
658 {0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00,
659 'R', 'O', 'C', 'K', 'B', 'O', 'X', '\0'};
661 unsigned long item_offset
= get_u32(&serbuf
[5]);
663 get_playlist_name(data
+ 7, item_offset
, MAX_PATH
);
664 /*Remove file extension*/
666 dot
= (strrchr(data
+7, '.'));
669 iap_send_pkt(data
, 7 + strlen(data
+7) + 1);
676 /* ReturnPlayStatus */
677 unsigned char data
[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
679 struct mp3entry
*id3
= audio_current_track();
680 unsigned long time_total
= id3
->length
;
681 unsigned long time_elapsed
= id3
->elapsed
;
682 int status
= audio_status();
683 put_u32(&data
[3], time_total
);
684 put_u32(&data
[7], 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 put_u32(&data
[3], playlist_pos
);
703 iap_send_pkt(data
, sizeof(data
));
707 /* GetIndexedPlayingTrackTitle */
709 /* GetIndexedPlayingTrackArtistName */
711 /* GetIndexedPlayingTrackAlbumName */
714 unsigned char data
[70] = {0x04, 0x00, 0xFF};
718 long tracknum
= get_u32(&serbuf
[4]);
721 memcpy(&id3
, audio_current_track(), sizeof(id3
));
722 tracknum
+= playlist_get_first_index(NULL
);
723 if(tracknum
>= playlist_amount())
724 tracknum
-= playlist_amount();
726 /* If the tracknumber is not the current one,
727 read id3 from disk */
728 if(playlist_next(0) != tracknum
)
730 struct playlist_track_info info
;
731 playlist_get_track_info(NULL
, tracknum
, &info
);
732 fd
= open(info
.filename
, O_RDONLY
);
733 memset(&id3
, 0, sizeof(struct mp3entry
));
734 get_metadata(&id3
, fd
, info
.filename
);
738 /* Return the requested track data */
742 len
= strlcpy((char *)&data
[3], id3
.title
, 64);
743 iap_send_pkt(data
, 4+len
);
746 len
= strlcpy((char *)&data
[3], id3
.artist
, 64);
747 iap_send_pkt(data
, 4+len
);
750 len
= strlcpy((char *)&data
[3], id3
.album
, 64);
751 iap_send_pkt(data
, 4+len
);
757 /* SetPlayStatusChangeNotification */
760 iap_pollspeed
= serbuf
[4] ? 1 : 0;
761 /* respond with cmd ok packet */
766 /* PlayCurrentSelection */
769 switch (cur_dbrecord
[0])
773 unsigned long item_offset
= get_u32(&cur_dbrecord
[1]);
775 unsigned char selected_playlist
776 [sizeof(global_settings
.playlist_catalog_dir
)
780 strcpy(selected_playlist
,
781 global_settings
.playlist_catalog_dir
);
782 int len
= strlen(selected_playlist
);
783 selected_playlist
[len
] = '/';
784 get_playlist_name (selected_playlist
+ len
+ 1,
787 ft_play_playlist(selected_playlist
,
788 global_settings
.playlist_catalog_dir
,
789 strrchr(selected_playlist
, '/') + 1);
802 case 0x01: /* play/pause */
803 iap_remotebtn
= BUTTON_RC_PLAY
;
805 iap_remotetick
= false;
808 case 0x02: /* stop */
809 iap_remotebtn
= BUTTON_RC_PLAY
|BUTTON_REPEAT
;
811 iap_remotetick
= false;
814 case 0x03: /* skip++ */
815 iap_remotebtn
= BUTTON_RC_RIGHT
;
817 iap_remotetick
= false;
819 case 0x04: /* skip-- */
820 iap_remotebtn
= BUTTON_RC_LEFT
;
822 iap_remotetick
= false;
824 case 0x05: /* ffwd */
825 iap_remotebtn
= BUTTON_RC_RIGHT
;
826 iap_remotetick
= false;
827 if(iap_pollspeed
) iap_pollspeed
= 5;
829 case 0x06: /* frwd */
830 iap_remotebtn
= BUTTON_RC_LEFT
;
831 iap_remotetick
= false;
832 if(iap_pollspeed
) iap_pollspeed
= 5;
834 case 0x07: /* end ffwd/frwd */
835 iap_remotebtn
= BUTTON_NONE
;
836 iap_remotetick
= false;
837 if(iap_pollspeed
) iap_pollspeed
= 1;
840 /* respond with cmd ok packet */
849 unsigned char data
[] = {0x04, 0x00, 0x2D, 0x00};
850 data
[3] = global_settings
.playlist_shuffle
? 1 : 0;
851 iap_send_pkt(data
, sizeof(data
));
858 if(serbuf
[4] && !global_settings
.playlist_shuffle
)
860 global_settings
.playlist_shuffle
= 1;
862 if (audio_status() & AUDIO_STATUS_PLAY
)
863 playlist_randomise(NULL
, current_tick
, true);
865 else if(!serbuf
[4] && global_settings
.playlist_shuffle
)
867 global_settings
.playlist_shuffle
= 0;
869 if (audio_status() & AUDIO_STATUS_PLAY
)
870 playlist_sort(NULL
, true);
873 /* respond with cmd ok packet */
882 unsigned char data
[] = {0x04, 0x00, 0x30, 0x00};
883 if(global_settings
.repeat_mode
== REPEAT_OFF
)
885 else if(global_settings
.repeat_mode
== REPEAT_ONE
)
889 iap_send_pkt(data
, sizeof(data
));
896 int oldmode
= global_settings
.repeat_mode
;
898 global_settings
.repeat_mode
= REPEAT_OFF
;
899 else if (serbuf
[4] == 1)
900 global_settings
.repeat_mode
= REPEAT_ONE
;
901 else if (serbuf
[4] == 2)
902 global_settings
.repeat_mode
= REPEAT_ALL
;
904 if (oldmode
!= global_settings
.repeat_mode
)
907 if (audio_status() & AUDIO_STATUS_PLAY
)
908 audio_flush_and_reload_tracks();
911 /* respond with cmd ok packet */
916 /* GetMonoDisplayImageLimits */
919 /* ReturnMonoDisplayImageLimits */
920 unsigned char data
[] = {0x04, 0x00, 0x34,
921 LCD_WIDTH
>> 8, LCD_WIDTH
& 0xff,
922 LCD_HEIGHT
>> 8, LCD_HEIGHT
& 0xff,
924 iap_send_pkt(data
, sizeof(data
));
928 /* GetNumPlayingTracks */
931 /* ReturnNumPlayingTracks */
932 unsigned char data
[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
933 unsigned long playlist_amt
= playlist_amount();
934 put_u32(&data
[3], playlist_amt
);
935 iap_send_pkt(data
, sizeof(data
));
939 /* SetCurrentPlayingTrack */
942 int paused
= (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE
));
943 long tracknum
= get_u32(&serbuf
[4]);
946 audio_skip(tracknum
- playlist_next(0));
950 /* respond with cmd ok packet */
957 /* default response is with cmd ok packet */
964 static void iap_handlepkt_mode7(void)
966 unsigned int cmd
= serbuf
[2];
974 /* GetAccessoryInfo */
975 unsigned char data
[] = {0x00, 0x27, 0x00};
976 iap_send_pkt(data
, sizeof(data
));
986 rmt_tuner_freq(serbuf
);
990 /* RdsReadyNotify, RDS station name 0x21 1E 00 + ASCII text*/
993 rmt_tuner_rds_data(serbuf
);
999 void iap_handlepkt(void)
1002 if(!iap_setupflag
) return;
1003 if(serbuf
[0] == 0) return;
1005 /* if we are waiting for a remote button to go out,
1006 delay the handling of the new packet */
1009 queue_post(&button_queue
, SYS_IAP_HANDLEPKT
, 0);
1013 unsigned char mode
= serbuf
[1];
1015 case 0: iap_handlepkt_mode0(); break;
1016 case 2: iap_handlepkt_mode2(); break;
1017 case 3: iap_handlepkt_mode3(); break;
1018 case 4: iap_handlepkt_mode4(); break;
1019 case 7: iap_handlepkt_mode7(); break;
1025 int remote_control_rx(void)
1027 int btn
= iap_remotebtn
;
1033 iap_remotebtn
= BUTTON_NONE
;
1034 iap_remotetick
= true;
1038 iap_remotetick
= true;
1043 const unsigned char *iap_get_serbuf(void)