Commit FS#8624 by Linus Nielsen, Ryan Press, Craig Elliott, and Kenderes Tamas. Adds preliminary support for numerous accessories that use the ipod serial port on the dock connector. See IpodAccessories for a list of tested devices.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19585 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
f921f74873
commit
70e9c7aed3
24 changed files with 1283 additions and 28 deletions
|
@ -52,6 +52,9 @@ tagtree.c
|
|||
#endif
|
||||
filetree.c
|
||||
scrobbler.c
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
iap.c
|
||||
#endif
|
||||
|
||||
screen_access.c
|
||||
#ifdef HAVE_BUTTONBAR
|
||||
|
|
|
@ -1195,6 +1195,14 @@ bool dbg_ports(void)
|
|||
lcd_puts(0, line++, buf);
|
||||
#endif
|
||||
|
||||
#if defined(IPOD_ACCESSORY_PROTOCOL)
|
||||
extern unsigned char serbuf[];
|
||||
snprintf(buf, sizeof(buf), "IAP PACKET: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
serbuf[0], serbuf[1], serbuf[2], serbuf[3], serbuf[4], serbuf[5],
|
||||
serbuf[6], serbuf[7]);
|
||||
lcd_puts(0, line++, buf);
|
||||
#endif
|
||||
|
||||
#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
|
||||
line++;
|
||||
snprintf(buf, sizeof(buf), "BATT: %03x UNK1: %03x",
|
||||
|
|
|
@ -181,3 +181,7 @@ usbstack
|
|||
#if defined(HAVE_ACCESSORY_SUPPLY)
|
||||
accessory_supply
|
||||
#endif
|
||||
|
||||
#if defined(IPOD_ACCESSORY_PROTOCOL)
|
||||
serial_port
|
||||
#endif
|
||||
|
|
730
apps/iap.c
Normal file
730
apps/iap.c
Normal file
|
@ -0,0 +1,730 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id: iap.c 17400 2008-05-07 14:30:29Z xxxxxx $
|
||||
*
|
||||
* Copyright (C) 2002 by Alan Korr & Nick Robinson
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "iap.h"
|
||||
#include "button.h"
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "serial.h"
|
||||
|
||||
#include "playlist.h"
|
||||
#include "playback.h"
|
||||
#include "audio.h"
|
||||
#include "settings.h"
|
||||
#include "metadata.h"
|
||||
#include "gwps.h"
|
||||
|
||||
#include "button.h"
|
||||
#include "action.h"
|
||||
|
||||
#define RX_BUFLEN 260
|
||||
#define TX_BUFLEN 128
|
||||
|
||||
static volatile int iap_pollspeed = 0;
|
||||
static volatile bool iap_remotetick = true;
|
||||
static bool iap_setupflag = false, iap_updateflag = false;
|
||||
static int iap_changedctr = 0;
|
||||
|
||||
static unsigned long iap_remotebtn = 0;
|
||||
static int iap_repeatbtn = 0;
|
||||
static bool iap_btnrepeat = false, iap_btnshuffle = false;
|
||||
|
||||
unsigned char serbuf[RX_BUFLEN];
|
||||
static int serbuf_i = 0;
|
||||
|
||||
static unsigned char response[TX_BUFLEN];
|
||||
static int responselen;
|
||||
|
||||
static void iap_task(void)
|
||||
{
|
||||
static int count = 0;
|
||||
|
||||
count += iap_pollspeed;
|
||||
if (count < (500/10)) return;
|
||||
|
||||
/* exec every 500ms if pollspeed == 1 */
|
||||
count = 0;
|
||||
queue_post(&button_queue, SYS_IAP_PERIODIC, 0);
|
||||
}
|
||||
|
||||
void iap_setup(int ratenum)
|
||||
{
|
||||
iap_bitrate_set(ratenum);
|
||||
iap_pollspeed = 0;
|
||||
iap_remotetick = true;
|
||||
iap_updateflag = false;
|
||||
iap_changedctr = 0;
|
||||
iap_setupflag = true;
|
||||
iap_remotebtn = BUTTON_NONE;
|
||||
tick_add_task(iap_task);
|
||||
}
|
||||
|
||||
void iap_bitrate_set(int ratenum)
|
||||
{
|
||||
switch(ratenum)
|
||||
{
|
||||
case 0:
|
||||
serial_bitrate(0);
|
||||
break;
|
||||
case 1:
|
||||
serial_bitrate(9600);
|
||||
break;
|
||||
case 2:
|
||||
serial_bitrate(19200);
|
||||
break;
|
||||
case 3:
|
||||
serial_bitrate(38400);
|
||||
break;
|
||||
case 4:
|
||||
serial_bitrate(57600);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Message format:
|
||||
0xff
|
||||
0x55
|
||||
length
|
||||
mode
|
||||
command (2 bytes)
|
||||
parameters (0-n bytes)
|
||||
checksum (length+mode+parameters+checksum == 0)
|
||||
*/
|
||||
|
||||
void iap_send_pkt(unsigned char * data, int len)
|
||||
{
|
||||
int i, chksum;
|
||||
|
||||
if(len > TX_BUFLEN-4) len = TX_BUFLEN-4;
|
||||
responselen = len + 4;
|
||||
|
||||
response[0] = 0xFF;
|
||||
response[1] = 0x55;
|
||||
|
||||
chksum = response[2] = len;
|
||||
for(i = 0; i < len; i ++)
|
||||
{
|
||||
chksum += data[i];
|
||||
response[i+3] = data[i];
|
||||
}
|
||||
|
||||
response[i+3] = 0x100 - (chksum & 0xFF);
|
||||
|
||||
for(i = 0; i < responselen; i ++)
|
||||
{
|
||||
while (!tx_rdy()) ;
|
||||
tx_writec(response[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int iap_getc(unsigned char x)
|
||||
{
|
||||
static unsigned char last_x = 0;
|
||||
static bool newpkt = true;
|
||||
static unsigned char chksum = 0;
|
||||
|
||||
/* Restart if the sync word is seen */
|
||||
if(x == 0x55 && last_x == 0xff/* && newpkt*/)
|
||||
{
|
||||
serbuf[0] = 0;
|
||||
serbuf_i = 0;
|
||||
chksum = 0;
|
||||
newpkt = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(serbuf_i >= RX_BUFLEN)
|
||||
serbuf_i = 0;
|
||||
|
||||
serbuf[serbuf_i++] = x;
|
||||
chksum += x;
|
||||
}
|
||||
last_x = x;
|
||||
|
||||
/* Broadcast to queue if we have a complete message */
|
||||
if(serbuf_i && (serbuf_i == serbuf[0]+2))
|
||||
{
|
||||
serbuf_i = 0;
|
||||
newpkt = true;
|
||||
if(chksum == 0)
|
||||
queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
|
||||
}
|
||||
return newpkt;
|
||||
}
|
||||
|
||||
void iap_track_changed(void)
|
||||
{
|
||||
iap_changedctr = 1;
|
||||
}
|
||||
|
||||
void iap_periodic(void)
|
||||
{
|
||||
if(!iap_setupflag) return;
|
||||
if(!iap_pollspeed) return;
|
||||
|
||||
unsigned char data[] = {0x04, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned long time_elapsed = audio_current_track()->elapsed;
|
||||
|
||||
time_elapsed += wps_state.ff_rewind_count;
|
||||
|
||||
data[3] = 0x04; // playing
|
||||
|
||||
/* If info has changed, don't flag it right away */
|
||||
if(iap_changedctr && iap_changedctr++ >= iap_pollspeed * 2)
|
||||
{
|
||||
/* track info has changed */
|
||||
iap_changedctr = 0;
|
||||
data[3] = 0x01; // 0x02 has same effect?
|
||||
iap_updateflag = true;
|
||||
}
|
||||
|
||||
data[4] = time_elapsed >> 24;
|
||||
data[5] = time_elapsed >> 16;
|
||||
data[6] = time_elapsed >> 8;
|
||||
data[7] = time_elapsed;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
}
|
||||
|
||||
void iap_handlepkt(void)
|
||||
{
|
||||
|
||||
if(!iap_setupflag) return;
|
||||
if(serbuf[0] == 0) return;
|
||||
|
||||
/* if we are waiting for a remote button to go out,
|
||||
delay the handling of the new packet */
|
||||
if(!iap_remotetick)
|
||||
{
|
||||
queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle Mode 0 */
|
||||
if (serbuf[1] == 0x00)
|
||||
{
|
||||
switch (serbuf[2])
|
||||
{
|
||||
/* get model info */
|
||||
case 0x0D:
|
||||
{
|
||||
unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
|
||||
'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* No idea ??? */
|
||||
case 0x0F:
|
||||
{
|
||||
unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* FM transmitter sends this: FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
|
||||
case 0x01:
|
||||
{
|
||||
if(serbuf[3] == 0x05)
|
||||
{
|
||||
sleep(HZ/3);
|
||||
unsigned char data[] = {0x05, 0x02};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* FM transmitter sends this: FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (???)*/
|
||||
case 0x13:
|
||||
{
|
||||
unsigned char data[] = {0x00, 0x02, 0x00, 0x13};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
unsigned char data2[] = {0x00, 0x27, 0x00};
|
||||
iap_send_pkt(data2, sizeof(data2));
|
||||
unsigned char data3[] = {0x05, 0x02};
|
||||
iap_send_pkt(data3, sizeof(data3));
|
||||
break;
|
||||
}
|
||||
/* FM transmitter sends this: FF 55 02 00 05 F9 (mode switch: AiR mode) */
|
||||
case 0x05:
|
||||
{
|
||||
unsigned char data[] = {0x00, 0x02, 0x06, 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
unsigned char data2[] = {0x00, 0x02, 0x00, 0x05};
|
||||
iap_send_pkt(data2, sizeof(data2));
|
||||
break;
|
||||
}
|
||||
/* default response is with cmd ok packet */
|
||||
default:
|
||||
{
|
||||
unsigned char data[] = {0x00, 0x02, 0x00, 0x00};
|
||||
data[3] = serbuf[2]; //respond with cmd
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Handle Mode 2 */
|
||||
else if (serbuf[1] == 0x02)
|
||||
{
|
||||
if(serbuf[2] != 0) return;
|
||||
iap_remotebtn = BUTTON_NONE;
|
||||
iap_remotetick = false;
|
||||
|
||||
if(serbuf[0] >= 3 && serbuf[3] != 0)
|
||||
{
|
||||
if(serbuf[3] & 1)
|
||||
iap_remotebtn |= BUTTON_RC_PLAY;
|
||||
if(serbuf[3] & 2)
|
||||
iap_remotebtn |= BUTTON_RC_VOL_UP;
|
||||
if(serbuf[3] & 4)
|
||||
iap_remotebtn |= BUTTON_RC_VOL_DOWN;
|
||||
if(serbuf[3] & 8)
|
||||
iap_remotebtn |= BUTTON_RC_RIGHT;
|
||||
if(serbuf[3] & 16)
|
||||
iap_remotebtn |= BUTTON_RC_LEFT;
|
||||
}
|
||||
else if(serbuf[0] >= 4 && serbuf[4] != 0)
|
||||
{
|
||||
if(serbuf[4] & 1) /* play */
|
||||
{
|
||||
if (audio_status() != AUDIO_STATUS_PLAY)
|
||||
{
|
||||
iap_remotebtn |= BUTTON_RC_PLAY;
|
||||
iap_repeatbtn = 2;
|
||||
iap_remotetick = false;
|
||||
iap_changedctr = 1;
|
||||
}
|
||||
}
|
||||
if(serbuf[4] & 2) /* pause */
|
||||
{
|
||||
if (audio_status() == AUDIO_STATUS_PLAY)
|
||||
{
|
||||
iap_remotebtn |= BUTTON_RC_PLAY;
|
||||
iap_repeatbtn = 2;
|
||||
iap_remotetick = false;
|
||||
iap_changedctr = 1;
|
||||
}
|
||||
}
|
||||
if((serbuf[4] & 128) && !iap_btnshuffle) /* shuffle */
|
||||
{
|
||||
iap_btnshuffle = true;
|
||||
if(!global_settings.playlist_shuffle)
|
||||
{
|
||||
global_settings.playlist_shuffle = 1;
|
||||
settings_save();
|
||||
settings_apply(false);
|
||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||
playlist_randomise(NULL, current_tick, true);
|
||||
}
|
||||
else if(global_settings.playlist_shuffle)
|
||||
{
|
||||
global_settings.playlist_shuffle = 0;
|
||||
settings_save();
|
||||
settings_apply(false);
|
||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||
playlist_sort(NULL, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
iap_btnshuffle = false;
|
||||
}
|
||||
else if(serbuf[0] >= 5 && serbuf[5] != 0)
|
||||
{
|
||||
if((serbuf[5] & 1) && !iap_btnrepeat) /* repeat */
|
||||
{
|
||||
int oldmode = global_settings.repeat_mode;
|
||||
iap_btnrepeat = true;
|
||||
|
||||
if (oldmode == REPEAT_ONE)
|
||||
global_settings.repeat_mode = REPEAT_OFF;
|
||||
else if (oldmode == REPEAT_ALL)
|
||||
global_settings.repeat_mode = REPEAT_ONE;
|
||||
else if (oldmode == REPEAT_OFF)
|
||||
global_settings.repeat_mode = REPEAT_ALL;
|
||||
|
||||
settings_save();
|
||||
settings_apply(false);
|
||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||
audio_flush_and_reload_tracks();
|
||||
}
|
||||
else
|
||||
iap_btnrepeat = false;
|
||||
|
||||
if(serbuf[5] & 16) /* ffwd */
|
||||
{
|
||||
iap_remotebtn |= BUTTON_RC_RIGHT;
|
||||
}
|
||||
if(serbuf[5] & 32) /* frwd */
|
||||
{
|
||||
iap_remotebtn |= BUTTON_RC_LEFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Handle Mode 3 */
|
||||
else if (serbuf[1] == 0x03)
|
||||
{
|
||||
switch(serbuf[2])
|
||||
{
|
||||
/* some kind of status packet? */
|
||||
case 0x01:
|
||||
{
|
||||
unsigned char data[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Handle Mode 4 */
|
||||
else if (serbuf[1] == 0x04)
|
||||
{
|
||||
switch (((unsigned long)serbuf[2] << 8) | serbuf[3])
|
||||
{
|
||||
/* Get data updated??? flag */
|
||||
case 0x0009:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x0A, 0x00};
|
||||
data[3] = iap_updateflag ? 0 : 1;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Set data updated??? flag */
|
||||
case 0x000B:
|
||||
{
|
||||
iap_updateflag = serbuf[4] ? 0 : 1;
|
||||
/* respond with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x0B};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get iPod size? */
|
||||
case 0x0012:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x13, 0x01, 0x0B};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get count of given types */
|
||||
case 0x0018:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned long num = 0;
|
||||
switch(serbuf[4]) /* type number */
|
||||
{
|
||||
case 0x01: /* total number of playlists */
|
||||
num = 1;
|
||||
break;
|
||||
case 0x05: /* total number of songs */
|
||||
num = 1;
|
||||
}
|
||||
data[3] = num >> 24;
|
||||
data[4] = num >> 16;
|
||||
data[5] = num >> 8;
|
||||
data[6] = num;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get time and status */
|
||||
case 0x001C:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
struct mp3entry *id3 = audio_current_track();
|
||||
unsigned long time_total = id3->length;
|
||||
unsigned long time_elapsed = id3->elapsed;
|
||||
int status = audio_status();
|
||||
data[3] = time_total >> 24;
|
||||
data[4] = time_total >> 16;
|
||||
data[5] = time_total >> 8;
|
||||
data[6] = time_total;
|
||||
data[7] = time_elapsed >> 24;
|
||||
data[8] = time_elapsed >> 16;
|
||||
data[9] = time_elapsed >> 8;
|
||||
data[10] = time_elapsed;
|
||||
if (status == AUDIO_STATUS_PLAY)
|
||||
data[11] = 0x01; /* play */
|
||||
else if (status & AUDIO_STATUS_PAUSE)
|
||||
data[11] = 0x02; /* pause */
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get current pos in playlist */
|
||||
case 0x001E:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00};
|
||||
long playlist_pos = playlist_next(0);
|
||||
playlist_pos -= playlist_get_first_index(NULL);
|
||||
if(playlist_pos < 0)
|
||||
playlist_pos += playlist_amount();
|
||||
data[3] = playlist_pos >> 24;
|
||||
data[4] = playlist_pos >> 16;
|
||||
data[5] = playlist_pos >> 8;
|
||||
data[6] = playlist_pos;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get title of a song number */
|
||||
case 0x0020:
|
||||
/* Get artist of a song number */
|
||||
case 0x0022:
|
||||
/* Get album of a song number */
|
||||
case 0x0024:
|
||||
{
|
||||
unsigned char data[70] = {0x04, 0x00, 0xFF};
|
||||
struct mp3entry id3;
|
||||
int fd;
|
||||
long tracknum = (signed long)serbuf[4] << 24 |
|
||||
(signed long)serbuf[5] << 16 |
|
||||
(signed long)serbuf[6] << 8 | serbuf[7];
|
||||
data[2] = serbuf[3] + 1;
|
||||
memcpy(&id3, audio_current_track(), sizeof(id3));
|
||||
tracknum += playlist_get_first_index(NULL);
|
||||
if(tracknum >= playlist_amount())
|
||||
tracknum -= playlist_amount();
|
||||
|
||||
/* If the tracknumber is not the current one,
|
||||
read id3 from disk */
|
||||
if(playlist_next(0) != tracknum)
|
||||
{
|
||||
struct playlist_track_info info;
|
||||
playlist_get_track_info(NULL, tracknum, &info);
|
||||
fd = open(info.filename, O_RDONLY);
|
||||
memset(&id3, 0, sizeof(struct mp3entry));
|
||||
get_metadata(&id3, fd, info.filename);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Return the requested track data */
|
||||
switch(serbuf[3])
|
||||
{
|
||||
case 0x20:
|
||||
strncpy((char *)&data[3], id3.title, 64);
|
||||
iap_send_pkt(data, 4+strlen(id3.title));
|
||||
break;
|
||||
case 0x22:
|
||||
strncpy((char *)&data[3], id3.artist, 64);
|
||||
iap_send_pkt(data, 4+strlen(id3.artist));
|
||||
break;
|
||||
case 0x24:
|
||||
strncpy((char *)&data[3], id3.album, 64);
|
||||
iap_send_pkt(data, 4+strlen(id3.album));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Set polling mode */
|
||||
case 0x0026:
|
||||
{
|
||||
iap_pollspeed = serbuf[4] ? 1 : 0;
|
||||
/*responsed with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x26};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* AiR playback control */
|
||||
case 0x0029:
|
||||
{
|
||||
/* respond with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x29};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
switch(serbuf[4])
|
||||
{
|
||||
case 0x01: /* play/pause */
|
||||
iap_remotebtn = BUTTON_RC_PLAY;
|
||||
iap_repeatbtn = 2;
|
||||
iap_remotetick = false;
|
||||
iap_changedctr = 1;
|
||||
break;
|
||||
case 0x02: /* stop */
|
||||
iap_remotebtn = BUTTON_RC_PLAY|BUTTON_REPEAT;
|
||||
iap_repeatbtn = 2;
|
||||
iap_remotetick = false;
|
||||
iap_changedctr = 1;
|
||||
break;
|
||||
case 0x03: /* skip++ */
|
||||
iap_remotebtn = BUTTON_RC_RIGHT;
|
||||
iap_repeatbtn = 2;
|
||||
iap_remotetick = false;
|
||||
break;
|
||||
case 0x04: /* skip-- */
|
||||
iap_remotebtn = BUTTON_RC_LEFT;
|
||||
iap_repeatbtn = 2;
|
||||
iap_remotetick = false;
|
||||
break;
|
||||
case 0x05: /* ffwd */
|
||||
iap_remotebtn = BUTTON_RC_RIGHT;
|
||||
iap_remotetick = false;
|
||||
if(iap_pollspeed) iap_pollspeed = 5;
|
||||
break;
|
||||
case 0x06: /* frwd */
|
||||
iap_remotebtn = BUTTON_RC_LEFT;
|
||||
iap_remotetick = false;
|
||||
if(iap_pollspeed) iap_pollspeed = 5;
|
||||
break;
|
||||
case 0x07: /* end ffwd/frwd */
|
||||
iap_remotebtn = BUTTON_NONE;
|
||||
iap_remotetick = false;
|
||||
if(iap_pollspeed) iap_pollspeed = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Get shuffle mode */
|
||||
case 0x002C:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x2D, 0x00};
|
||||
data[3] = global_settings.playlist_shuffle ? 1 : 0;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Set shuffle mode */
|
||||
case 0x002E:
|
||||
{
|
||||
if(serbuf[4] && !global_settings.playlist_shuffle)
|
||||
{
|
||||
global_settings.playlist_shuffle = 1;
|
||||
settings_save();
|
||||
settings_apply(false);
|
||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||
playlist_randomise(NULL, current_tick, true);
|
||||
}
|
||||
else if(!serbuf[4] && global_settings.playlist_shuffle)
|
||||
{
|
||||
global_settings.playlist_shuffle = 0;
|
||||
settings_save();
|
||||
settings_apply(false);
|
||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||
playlist_sort(NULL, true);
|
||||
}
|
||||
|
||||
|
||||
/* respond with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x2E};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get repeat mode */
|
||||
case 0x002F:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x30, 0x00};
|
||||
if(global_settings.repeat_mode == REPEAT_OFF)
|
||||
data[3] = 0;
|
||||
else if(global_settings.repeat_mode == REPEAT_ONE)
|
||||
data[3] = 1;
|
||||
else
|
||||
data[3] = 2;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Set repeat mode */
|
||||
case 0x0031:
|
||||
{
|
||||
int oldmode = global_settings.repeat_mode;
|
||||
if (serbuf[4] == 0)
|
||||
global_settings.repeat_mode = REPEAT_OFF;
|
||||
else if (serbuf[4] == 1)
|
||||
global_settings.repeat_mode = REPEAT_ONE;
|
||||
else if (serbuf[4] == 2)
|
||||
global_settings.repeat_mode = REPEAT_ALL;
|
||||
|
||||
if (oldmode != global_settings.repeat_mode)
|
||||
{
|
||||
settings_save();
|
||||
settings_apply(false);
|
||||
if (audio_status() & AUDIO_STATUS_PLAY)
|
||||
audio_flush_and_reload_tracks();
|
||||
}
|
||||
|
||||
/* respond with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x31};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get Max Screen Size for Picture Upload??? */
|
||||
case 0x0033:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x34, 0x01, 0x36, 0x00, 0xA8, 0x01};
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Get number songs in current playlist */
|
||||
case 0x0035:
|
||||
{
|
||||
unsigned char data[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned long playlist_amt = playlist_amount();
|
||||
data[3] = playlist_amt >> 24;
|
||||
data[4] = playlist_amt >> 16;
|
||||
data[5] = playlist_amt >> 8;
|
||||
data[6] = playlist_amt;
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
/* Jump to track number in current playlist */
|
||||
case 0x0037:
|
||||
{
|
||||
long tracknum = (signed long)serbuf[4] << 24 |
|
||||
(signed long)serbuf[5] << 16 |
|
||||
(signed long)serbuf[6] << 8 | serbuf[7];
|
||||
if (!wps_state.paused)
|
||||
audio_pause();
|
||||
audio_skip(tracknum - playlist_next(0));
|
||||
if (!wps_state.paused)
|
||||
audio_resume();
|
||||
|
||||
/* respond with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
|
||||
data[4] = serbuf[2];
|
||||
data[5] = serbuf[3];
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* default response is with cmd ok packet */
|
||||
unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00};
|
||||
data[4] = serbuf[2];
|
||||
data[5] = serbuf[3];
|
||||
iap_send_pkt(data, sizeof(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
serbuf[0] = 0;
|
||||
}
|
||||
|
||||
int remote_control_rx(void)
|
||||
{
|
||||
int btn = iap_remotebtn;
|
||||
if(iap_repeatbtn)
|
||||
{
|
||||
iap_repeatbtn--;
|
||||
if(!iap_repeatbtn)
|
||||
{
|
||||
iap_remotebtn = BUTTON_NONE;
|
||||
iap_remotetick = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
iap_remotetick = true;
|
||||
|
||||
return btn;
|
||||
}
|
|
@ -187,9 +187,62 @@ const struct button_mapping button_context_recscreen[] = {
|
|||
}; /* button_context_recscreen */
|
||||
#endif
|
||||
|
||||
#if BUTTON_REMOTE != 0
|
||||
/*****************************************************************************
|
||||
* Remote control mappings
|
||||
*****************************************************************************/
|
||||
|
||||
static const struct button_mapping remote_button_context_standard[] = {
|
||||
{ ACTION_STD_PREV, BUTTON_RC_LEFT, BUTTON_NONE },
|
||||
{ ACTION_STD_NEXT, BUTTON_RC_RIGHT, BUTTON_NONE },
|
||||
{ ACTION_STD_CANCEL, BUTTON_RC_STOP, BUTTON_NONE },
|
||||
{ ACTION_STD_OK, BUTTON_RC_PLAY, BUTTON_NONE },
|
||||
|
||||
LAST_ITEM_IN_LIST
|
||||
};
|
||||
|
||||
static const struct button_mapping remote_button_context_wps[] = {
|
||||
{ ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN, BUTTON_NONE },
|
||||
{ ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP, BUTTON_NONE },
|
||||
{ ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
|
||||
|
||||
{ ACTION_WPS_PLAY, BUTTON_RC_PLAY|BUTTON_REL, BUTTON_RC_PLAY },
|
||||
{ ACTION_WPS_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_WPS_SKIPNEXT, BUTTON_RC_RIGHT|BUTTON_REL, BUTTON_RC_RIGHT },
|
||||
{ ACTION_WPS_SEEKFWD, BUTTON_RC_RIGHT|BUTTON_REPEAT,BUTTON_NONE },
|
||||
{ ACTION_WPS_STOPSEEK, BUTTON_RC_RIGHT|BUTTON_REL, BUTTON_RC_RIGHT|BUTTON_REPEAT },
|
||||
{ ACTION_WPS_SKIPPREV, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT },
|
||||
{ ACTION_WPS_SEEKBACK, BUTTON_RC_LEFT|BUTTON_REPEAT, BUTTON_NONE },
|
||||
{ ACTION_WPS_STOPSEEK, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT|BUTTON_REPEAT },
|
||||
|
||||
LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
|
||||
};
|
||||
|
||||
|
||||
static const struct button_mapping* get_context_mapping_remote( int context )
|
||||
{
|
||||
context ^= CONTEXT_REMOTE;
|
||||
|
||||
switch (context)
|
||||
{
|
||||
case CONTEXT_WPS:
|
||||
return remote_button_context_wps;
|
||||
|
||||
default:
|
||||
return remote_button_context_standard;
|
||||
}
|
||||
}
|
||||
#endif /* BUTTON_REMOTE != 0 */
|
||||
|
||||
/* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */
|
||||
const struct button_mapping* get_context_mapping(int context)
|
||||
{
|
||||
#if BUTTON_REMOTE != 0
|
||||
if (context&CONTEXT_REMOTE)
|
||||
return get_context_mapping_remote(context);
|
||||
#endif
|
||||
|
||||
switch (context)
|
||||
{
|
||||
case CONTEXT_STD:
|
||||
|
|
|
@ -11811,6 +11811,110 @@
|
|||
gigabeatf: "High"
|
||||
</voice>
|
||||
</phrase>
|
||||
<<<<<<< .mine
|
||||
<phrase>
|
||||
id: LANG_SERIAL_BITRATE
|
||||
desc: in system settings menu
|
||||
user:
|
||||
<source>
|
||||
*: none
|
||||
serial_port: "Serial Bitrate"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
serial_port: "Serial Bitrate"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
serial_port: "Serial Bitrate"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_SERIAL_BITRATE_AUTO
|
||||
desc: in system settings menu
|
||||
user:
|
||||
<source>
|
||||
*: none
|
||||
serial_port: "Auto"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
serial_port: "Auto"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
serial_port: "Automatic"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_SERIAL_BITRATE_9600
|
||||
desc: in system settings menu
|
||||
user:
|
||||
<source>
|
||||
*: none
|
||||
serial_port: "9600"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
serial_port: "9600"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
serial_port: "9600"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_SERIAL_BITRATE_19200
|
||||
desc: in system settings menu
|
||||
user:
|
||||
<source>
|
||||
*: none
|
||||
serial_port: "19200"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
serial_port: "19200"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
serial_port: "19200"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_SERIAL_BITRATE_38400
|
||||
desc: in system settings menu
|
||||
user:
|
||||
<source>
|
||||
*: none
|
||||
serial_port: "38400"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
serial_port: "38400"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
serial_port: "38400"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
id: LANG_SERIAL_BITRATE_57600
|
||||
desc: in system settings menu
|
||||
user:
|
||||
<source>
|
||||
*: none
|
||||
serial_port: "57600"
|
||||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
serial_port: "57600"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
serial_port: "57600"
|
||||
</voice>
|
||||
</phrase>
|
||||
=======
|
||||
<phrase>
|
||||
id: LANG_VERY_SLOW
|
||||
desc: in settings_menu
|
||||
|
@ -11909,6 +12013,9 @@
|
|||
*: "slash"
|
||||
</voice>
|
||||
</phrase>
|
||||
<<<<<<< .mine
|
||||
>>>>>>> .r18116
|
||||
=======
|
||||
<phrase>
|
||||
id: LANG_GAIN_LEFT
|
||||
desc: in the recording screen
|
||||
|
@ -12110,6 +12217,9 @@
|
|||
*: "Search Results"
|
||||
</voice>
|
||||
</phrase>
|
||||
<<<<<<< .mine
|
||||
>>>>>>> .r18870
|
||||
=======
|
||||
<phrase>
|
||||
id: LANG_QS_ITEMS
|
||||
desc: DEPRECATED
|
||||
|
@ -12243,3 +12353,4 @@
|
|||
quickscreen: "Set as Bottom Quickscreen Item"
|
||||
</voice>
|
||||
</phrase>
|
||||
>>>>>>> .r19041
|
||||
|
|
|
@ -73,6 +73,10 @@
|
|||
#include "scrobbler.h"
|
||||
#include "icon.h"
|
||||
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
#include "iap.h"
|
||||
#endif
|
||||
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
#include "playback.h"
|
||||
#endif
|
||||
|
@ -583,6 +587,9 @@ static void init(void)
|
|||
#if CONFIG_CHARGING
|
||||
car_adapter_mode_init();
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
iap_setup(global_settings.serial_bitrate);
|
||||
#endif
|
||||
#ifdef HAVE_ACCESSORY_SUPPLY
|
||||
accessory_supply_set(global_settings.accessory_supply);
|
||||
#endif
|
||||
|
|
|
@ -247,6 +247,9 @@ MENUITEM_SETTING(line_in, &global_settings.line_in, linein_callback);
|
|||
#if CONFIG_CHARGING
|
||||
MENUITEM_SETTING(car_adapter_mode, &global_settings.car_adapter_mode, NULL);
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
MENUITEM_SETTING(serial_bitrate, &global_settings.serial_bitrate, NULL);
|
||||
#endif
|
||||
#ifdef HAVE_ACCESSORY_SUPPLY
|
||||
MENUITEM_SETTING(accessory_supply, &global_settings.accessory_supply, NULL);
|
||||
#endif
|
||||
|
@ -282,6 +285,9 @@ MAKE_MENU(system_menu, ID2P(LANG_SYSTEM),
|
|||
#if CONFIG_CHARGING
|
||||
&car_adapter_mode,
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL,
|
||||
&serial_bitrate,
|
||||
#endif
|
||||
#ifdef HAVE_ACCESSORY_SUPPLY
|
||||
&accessory_supply,
|
||||
#endif
|
||||
|
|
12
apps/misc.c
12
apps/misc.c
|
@ -61,6 +61,10 @@
|
|||
#include "playlist.h"
|
||||
#include "yesno.h"
|
||||
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
#include "iap.h"
|
||||
#endif
|
||||
|
||||
#if (CONFIG_STORAGE & STORAGE_MMC)
|
||||
#include "ata_mmc.h"
|
||||
#endif
|
||||
|
@ -958,6 +962,14 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
|
|||
case SYS_PHONE_UNPLUGGED:
|
||||
unplug_change(false);
|
||||
return SYS_PHONE_UNPLUGGED;
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
case SYS_IAP_PERIODIC:
|
||||
iap_periodic();
|
||||
return SYS_IAP_PERIODIC;
|
||||
case SYS_IAP_HANDLEPKT:
|
||||
iap_handlepkt();
|
||||
return SYS_IAP_HANDLEPKT;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -82,6 +82,10 @@
|
|||
#include "pcm_record.h"
|
||||
#endif
|
||||
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
#include "iap.h"
|
||||
#endif
|
||||
|
||||
#define PLAYBACK_VOICE
|
||||
|
||||
/* default point to start buffer refill */
|
||||
|
@ -646,6 +650,9 @@ bool audio_has_changed_track(void)
|
|||
{
|
||||
if (track_changed)
|
||||
{
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
iap_track_changed();
|
||||
#endif
|
||||
track_changed = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -691,7 +698,7 @@ void audio_resume(void)
|
|||
queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
|
||||
}
|
||||
|
||||
static void audio_skip(int direction)
|
||||
void audio_skip(int direction)
|
||||
{
|
||||
if (playlist_check(ci.new_track + wps_offset + direction))
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ int audio_track_count(void);
|
|||
long audio_filebufused(void);
|
||||
void audio_pre_ff_rewind(void);
|
||||
void audio_set_crossfade(int type);
|
||||
|
||||
void audio_skip(int direction);
|
||||
void audio_hard_stop(void); /* Stops audio from serving playback */
|
||||
|
||||
enum
|
||||
|
|
|
@ -488,6 +488,9 @@ struct user_settings
|
|||
bool peak_meter_clipcounter; /* clipping count indicator */
|
||||
#endif
|
||||
bool car_adapter_mode; /* 0=off 1=on */
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
int serial_bitrate; /* 0=auto 1=9600 2=19200 3=38400 4=57600 */
|
||||
#endif
|
||||
#ifdef HAVE_ACCESSORY_SUPPLY
|
||||
bool accessory_supply; /* 0=off 1=on, accessory power supply for iPod */
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
#if CONFIG_TUNER
|
||||
#include "radio.h"
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
#include "iap.h"
|
||||
#endif
|
||||
|
||||
#define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT)
|
||||
/** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h
|
||||
|
@ -595,6 +598,12 @@ const struct settings_list settings[] = {
|
|||
OFFON_SETTING(NVRAM(1), car_adapter_mode,
|
||||
LANG_CAR_ADAPTER_MODE, false, "car adapter mode", NULL),
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
CHOICE_SETTING(0, serial_bitrate, LANG_SERIAL_BITRATE, 0, "serial bitrate",
|
||||
"auto,9600,19200,38400,57600", iap_bitrate_set, 5, ID2P(LANG_SERIAL_BITRATE_AUTO),
|
||||
ID2P(LANG_SERIAL_BITRATE_9600),ID2P(LANG_SERIAL_BITRATE_19200),
|
||||
ID2P(LANG_SERIAL_BITRATE_38400),ID2P(LANG_SERIAL_BITRATE_57600)),
|
||||
#endif
|
||||
#ifdef HAVE_ACCESSORY_SUPPLY
|
||||
OFFON_SETTING(0, accessory_supply, LANG_ACCESSORY_SUPPLY,
|
||||
true, "accessory power supply", accessory_supply_set),
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include "button.h"
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
|
@ -28,6 +30,7 @@
|
|||
#include "adc.h"
|
||||
#include "lcd.h"
|
||||
#include "serial.h"
|
||||
#include "iap.h"
|
||||
|
||||
#if CONFIG_CPU == IMX31L
|
||||
#include "serial-imx31.h"
|
||||
|
@ -68,6 +71,35 @@ void serial_setup (void)
|
|||
SCR1 = 0x10; /* Enable the receiver, no interrupt */
|
||||
}
|
||||
|
||||
int tx_rdy(void)
|
||||
{
|
||||
/* a dummy */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rx_rdy(void)
|
||||
{
|
||||
if(SSR1 & SCI_RDRF)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tx_writec(unsigned char c)
|
||||
{
|
||||
/* a dummy */
|
||||
}
|
||||
|
||||
unsigned char rx_readc(void)
|
||||
{
|
||||
char tmp;
|
||||
/* Read byte and clear the Rx Full bit */
|
||||
tmp = RDR1;
|
||||
and_b(~SCI_RDRF, &SSR1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/* This function returns the received remote control code only if it is
|
||||
received without errors before or after the reception.
|
||||
It therefore returns the received code on the second call after the
|
||||
|
@ -87,11 +119,9 @@ int remote_control_rx(void)
|
|||
return BUTTON_NONE;
|
||||
}
|
||||
|
||||
if(SSR1 & SCI_RDRF) {
|
||||
/* Read byte and clear the Rx Full bit */
|
||||
btn = RDR1;
|
||||
and_b(~SCI_RDRF, &SSR1);
|
||||
|
||||
if(rx_rdy()) {
|
||||
btn = rx_readc();
|
||||
|
||||
if(last_was_error)
|
||||
{
|
||||
last_valid_button = BUTTON_NONE;
|
||||
|
@ -149,16 +179,6 @@ int remote_control_rx(void)
|
|||
#endif /* !HAVE_FMADC && !STORAGE_MMC */
|
||||
#elif defined(CPU_COLDFIRE) && defined(HAVE_SERIAL)
|
||||
|
||||
void serial_tx(const unsigned char *buf)
|
||||
{
|
||||
while(*buf) {
|
||||
while(!(USR0 & 0x04))
|
||||
{
|
||||
};
|
||||
UTB0 = *buf++;
|
||||
}
|
||||
}
|
||||
|
||||
void serial_setup (void)
|
||||
{
|
||||
UCR0 = 0x30; /* Reset transmitter */
|
||||
|
@ -171,6 +191,25 @@ void serial_setup (void)
|
|||
UCR0 = 0x04; /* Tx enable */
|
||||
}
|
||||
|
||||
int tx_rdy(void)
|
||||
{
|
||||
if(USR0 & 0x04)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rx_rdy(void)
|
||||
{
|
||||
/* a dummy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tx_writec(unsigned char c)
|
||||
{
|
||||
UTB0 = c;
|
||||
}
|
||||
|
||||
#elif (CONFIG_CPU == IMX31L)
|
||||
|
||||
void serial_setup(void)
|
||||
|
@ -207,15 +246,216 @@ int rx_rdy(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tx_writec(char c)
|
||||
void tx_writec(unsigned char c)
|
||||
{
|
||||
UTXD1=(int) c;
|
||||
}
|
||||
|
||||
#elif defined(IPOD_ACCESSORY_PROTOCOL)
|
||||
static int autobaud = 0;
|
||||
void serial_setup (void)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
#if (MODEL_NUMBER == 3) || (MODEL_NUMBER == 8)
|
||||
|
||||
/* Route the Tx/Rx pins. 4G Ipod??? */
|
||||
outl(0x70000018, inl(0x70000018) & ~0xc00);
|
||||
#elif (MODEL_NUMBER == 4) || (MODEL_NUMBER == 5)
|
||||
|
||||
/* Route the Tx/Rx pins. 5G Ipod */
|
||||
(*(volatile unsigned long *)(0x7000008C)) &= ~0x0C;
|
||||
GPO32_ENABLE &= ~0x0C;
|
||||
#endif
|
||||
|
||||
DEV_EN = DEV_EN | DEV_SER0;
|
||||
CPU_HI_INT_DIS = SER0_MASK;
|
||||
|
||||
DEV_RS |= DEV_SER0;
|
||||
sleep(1);
|
||||
DEV_RS &= ~DEV_SER0;
|
||||
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLM = 0x00;
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
SER0_IER = 0x01;
|
||||
|
||||
SER0_FCR = 0x07; /* Tx+Rx FIFO reset and FIFO enable */
|
||||
|
||||
CPU_INT_EN |= HI_MASK;
|
||||
CPU_HI_INT_EN |= SER0_MASK;
|
||||
tmp = SER0_RBR;
|
||||
|
||||
serial_bitrate(0);
|
||||
}
|
||||
|
||||
void serial_bitrate(int rate)
|
||||
{
|
||||
if(rate == 0)
|
||||
{
|
||||
autobaud = 2;
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
return;
|
||||
}
|
||||
|
||||
autobaud = 0;
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 24000000L / rate / 16;
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
}
|
||||
|
||||
int tx_rdy(void)
|
||||
{
|
||||
if((SER0_LSR & 0x20))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rx_rdy(void)
|
||||
{
|
||||
if((SER0_LSR & 0x1))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tx_writec(unsigned char c)
|
||||
{
|
||||
SER0_THR =(int) c;
|
||||
}
|
||||
|
||||
unsigned char rx_readc(void)
|
||||
{
|
||||
return (SER0_RBR & 0xFF);
|
||||
}
|
||||
|
||||
void SERIAL0(void)
|
||||
{
|
||||
static int badbaud = 0;
|
||||
static bool newpkt = true;
|
||||
char temp;
|
||||
|
||||
while(rx_rdy())
|
||||
{
|
||||
temp = rx_readc();
|
||||
if (newpkt && autobaud > 0)
|
||||
{
|
||||
if (autobaud == 1)
|
||||
{
|
||||
switch (temp)
|
||||
{
|
||||
case 0xFF:
|
||||
case 0x55:
|
||||
break;
|
||||
case 0xFC:
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
temp = 0xFF;
|
||||
break;
|
||||
case 0xE0:
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x9C; /* 24000000/156/16 = 9615 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
temp = 0xFF;
|
||||
break;
|
||||
default:
|
||||
badbaud++;
|
||||
if (badbaud >= 6) /* Switch baud detection mode */
|
||||
{
|
||||
autobaud = 2;
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
badbaud = 0;
|
||||
} else {
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
switch (temp)
|
||||
{
|
||||
case 0xFF:
|
||||
case 0x55:
|
||||
break;
|
||||
case 0xFE:
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
temp = 0xFF;
|
||||
break;
|
||||
case 0xFC:
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x27; /* 24000000/39/16 = 38461 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
temp = 0xFF;
|
||||
break;
|
||||
case 0xE0:
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
temp = 0xFF;
|
||||
break;
|
||||
default:
|
||||
badbaud++;
|
||||
if (badbaud >= 6) /* Switch baud detection */
|
||||
{
|
||||
autobaud = 1;
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
badbaud = 0;
|
||||
} else {
|
||||
SER0_LCR = 0x80; /* Divisor latch enable */
|
||||
SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */
|
||||
SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool pkt = iap_getc(temp);
|
||||
if(newpkt == true && pkt == false)
|
||||
autobaud = 0; /* Found good baud */
|
||||
newpkt = pkt;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Other targets */
|
||||
void serial_setup (void)
|
||||
{
|
||||
/* a dummy */
|
||||
}
|
||||
|
||||
int tx_rdy(void)
|
||||
{
|
||||
/* a dummy */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rx_rdy(void)
|
||||
{
|
||||
/* a dummy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tx_writec(unsigned char c)
|
||||
{
|
||||
/* a dummy */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void dprintf(const char * str, ... )
|
||||
{
|
||||
char dprintfbuff[256];
|
||||
unsigned char * ptr;
|
||||
char * ptr;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
|
@ -224,7 +464,7 @@ void dprintf(const char * str, ... )
|
|||
vsnprintf(ptr,sizeof(dprintfbuff),str,ap);
|
||||
va_end(ap);
|
||||
|
||||
serial_tx(ptr);
|
||||
serial_tx((unsigned char *)ptr);
|
||||
}
|
||||
|
||||
void serial_tx(const unsigned char * buf)
|
||||
|
@ -241,10 +481,3 @@ void serial_tx(const unsigned char * buf)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Other targets */
|
||||
void serial_setup (void)
|
||||
{
|
||||
/* a dummy */
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -186,4 +186,6 @@
|
|||
|
||||
#define ICODE_ATTR_TREMOR_NOT_MDCT
|
||||
|
||||
#define IPOD_ACCESSORY_PROTOCOL
|
||||
|
||||
#endif
|
||||
|
|
|
@ -166,4 +166,6 @@
|
|||
|
||||
#define ICODE_ATTR_TREMOR_NOT_MDCT
|
||||
|
||||
#define IPOD_ACCESSORY_PROTOCOL
|
||||
|
||||
#endif
|
||||
|
|
|
@ -177,4 +177,6 @@
|
|||
|
||||
#define ICODE_ATTR_TREMOR_NOT_MDCT
|
||||
|
||||
#define IPOD_ACCESSORY_PROTOCOL
|
||||
|
||||
#endif
|
||||
|
|
|
@ -197,4 +197,6 @@
|
|||
|
||||
#define ICODE_ATTR_TREMOR_NOT_MDCT
|
||||
|
||||
#define IPOD_ACCESSORY_PROTOCOL
|
||||
|
||||
#endif
|
||||
|
|
31
firmware/export/iap.h
Normal file
31
firmware/export/iap.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id: iap.h 17400 2008-05-07 20:22:16Z xxxxxx $
|
||||
*
|
||||
* Copyright (C) 2002 by Alan Korr
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __IAP_H__
|
||||
#define __IAP_H__
|
||||
|
||||
extern int iap_getc(unsigned char x);
|
||||
extern void iap_write_pkt(unsigned char data, int len);
|
||||
extern void iap_setup(int ratenum);
|
||||
extern void iap_bitrate_set(int ratenum);
|
||||
extern void iap_periodic(void);
|
||||
extern void iap_handlepkt(void);
|
||||
extern void iap_track_changed(void);
|
||||
|
||||
#endif
|
|
@ -78,6 +78,8 @@
|
|||
#define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5)
|
||||
#define SYS_SCREENDUMP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0)
|
||||
#define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1)
|
||||
#define SYS_IAP_PERIODIC MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2)
|
||||
#define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3)
|
||||
|
||||
#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT)
|
||||
|
||||
|
|
|
@ -22,8 +22,11 @@
|
|||
#ifndef __SERIAL_H__
|
||||
#define __SERIAL_H__
|
||||
|
||||
extern void serial_setup (void);
|
||||
extern void serial_setup(void);
|
||||
extern void serial_bitrate(int rate);
|
||||
extern int remote_control_rx(void);
|
||||
extern void serial_tx(const unsigned char *buf);
|
||||
extern void tx_writec(unsigned char c);
|
||||
extern int tx_rdy(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -316,7 +316,11 @@ int button_read_device(void)
|
|||
}
|
||||
|
||||
/* The int_btn variable is set in the button interrupt handler */
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
return int_btn | remote_control_rx();
|
||||
#else
|
||||
return int_btn;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool button_hold(void)
|
||||
|
|
|
@ -50,7 +50,22 @@ void ipod_4g_button_int(void);
|
|||
|BUTTON_LEFT|BUTTON_RIGHT|BUTTON_SCROLL_FWD\
|
||||
|BUTTON_SCROLL_BACK|BUTTON_PLAY)
|
||||
|
||||
/* Remote control's buttons */
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
#define BUTTON_RC_PLAY 0x00100000
|
||||
#define BUTTON_RC_STOP 0x00080000
|
||||
|
||||
#define BUTTON_RC_LEFT 0x00040000
|
||||
#define BUTTON_RC_RIGHT 0x00020000
|
||||
#define BUTTON_RC_VOL_UP 0x00010000
|
||||
#define BUTTON_RC_VOL_DOWN 0x00008000
|
||||
|
||||
#define BUTTON_REMOTE (BUTTON_RC_PLAY|BUTTON_RC_STOP\
|
||||
|BUTTON_RC_LEFT|BUTTON_RC_RIGHT\
|
||||
|BUTTON_RC_VOL_UP|BUTTON_RC_VOL_DOWN)
|
||||
#else
|
||||
#define BUTTON_REMOTE 0
|
||||
#endif
|
||||
|
||||
/* This is for later
|
||||
#define BUTTON_SCROLL_TOUCH 0x00000200
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#ifndef BOOTLOADER
|
||||
extern void TIMER1(void);
|
||||
extern void TIMER2(void);
|
||||
extern void SERIAL0(void);
|
||||
extern void ipod_mini_button_int(void); /* iPod Mini 1st gen only */
|
||||
extern void ipod_4g_button_int(void); /* iPod 4th gen and higher only */
|
||||
|
||||
|
@ -78,6 +79,11 @@ void irq(void)
|
|||
button_int();
|
||||
}
|
||||
#endif
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
else if (CPU_HI_INT_STAT & SER0_MASK) {
|
||||
SERIAL0();
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_USBSTACK
|
||||
else if (CPU_INT_STAT & USB_MASK) {
|
||||
usb_drv_int();
|
||||
|
|
Loading…
Reference in a new issue