diff options
-rw-r--r-- | apps/SOURCES | 3 | ||||
-rw-r--r-- | apps/debug_menu.c | 8 | ||||
-rw-r--r-- | apps/features.txt | 4 | ||||
-rw-r--r-- | apps/iap.c | 730 | ||||
-rw-r--r-- | apps/keymaps/keymap-ipod.c | 53 | ||||
-rw-r--r-- | apps/lang/english.lang | 111 | ||||
-rw-r--r-- | apps/main.c | 7 | ||||
-rw-r--r-- | apps/menus/settings_menu.c | 6 | ||||
-rw-r--r-- | apps/misc.c | 12 | ||||
-rw-r--r-- | apps/playback.c | 9 | ||||
-rw-r--r-- | apps/playback.h | 2 | ||||
-rw-r--r-- | apps/settings.h | 3 | ||||
-rw-r--r-- | apps/settings_list.c | 9 | ||||
-rw-r--r-- | firmware/drivers/serial.c | 283 | ||||
-rw-r--r-- | firmware/export/config-ipod4g.h | 2 | ||||
-rw-r--r-- | firmware/export/config-ipodcolor.h | 2 | ||||
-rw-r--r-- | firmware/export/config-ipodnano.h | 2 | ||||
-rw-r--r-- | firmware/export/config-ipodvideo.h | 2 | ||||
-rw-r--r-- | firmware/export/iap.h | 31 | ||||
-rw-r--r-- | firmware/export/kernel.h | 2 | ||||
-rw-r--r-- | firmware/export/serial.h | 5 | ||||
-rw-r--r-- | firmware/target/arm/ipod/button-clickwheel.c | 4 | ||||
-rw-r--r-- | firmware/target/arm/ipod/button-target.h | 15 | ||||
-rw-r--r-- | firmware/target/arm/system-pp502x.c | 6 |
24 files changed, 1283 insertions, 28 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index c63bcb78e2..bd20136d1e 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -52,6 +52,9 @@ tagtree.c | |||
52 | #endif | 52 | #endif |
53 | filetree.c | 53 | filetree.c |
54 | scrobbler.c | 54 | scrobbler.c |
55 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
56 | iap.c | ||
57 | #endif | ||
55 | 58 | ||
56 | screen_access.c | 59 | screen_access.c |
57 | #ifdef HAVE_BUTTONBAR | 60 | #ifdef HAVE_BUTTONBAR |
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index abb6018a10..f390cced85 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -1195,6 +1195,14 @@ bool dbg_ports(void) | |||
1195 | lcd_puts(0, line++, buf); | 1195 | lcd_puts(0, line++, buf); |
1196 | #endif | 1196 | #endif |
1197 | 1197 | ||
1198 | #if defined(IPOD_ACCESSORY_PROTOCOL) | ||
1199 | extern unsigned char serbuf[]; | ||
1200 | snprintf(buf, sizeof(buf), "IAP PACKET: %02x %02x %02x %02x %02x %02x %02x %02x", | ||
1201 | serbuf[0], serbuf[1], serbuf[2], serbuf[3], serbuf[4], serbuf[5], | ||
1202 | serbuf[6], serbuf[7]); | ||
1203 | lcd_puts(0, line++, buf); | ||
1204 | #endif | ||
1205 | |||
1198 | #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) | 1206 | #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) |
1199 | line++; | 1207 | line++; |
1200 | snprintf(buf, sizeof(buf), "BATT: %03x UNK1: %03x", | 1208 | snprintf(buf, sizeof(buf), "BATT: %03x UNK1: %03x", |
diff --git a/apps/features.txt b/apps/features.txt index 0ddccced3c..4fbf427a23 100644 --- a/apps/features.txt +++ b/apps/features.txt | |||
@@ -181,3 +181,7 @@ usbstack | |||
181 | #if defined(HAVE_ACCESSORY_SUPPLY) | 181 | #if defined(HAVE_ACCESSORY_SUPPLY) |
182 | accessory_supply | 182 | accessory_supply |
183 | #endif | 183 | #endif |
184 | |||
185 | #if defined(IPOD_ACCESSORY_PROTOCOL) | ||
186 | serial_port | ||
187 | #endif | ||
diff --git a/apps/iap.c b/apps/iap.c new file mode 100644 index 0000000000..a15fd81a90 --- /dev/null +++ b/apps/iap.c | |||
@@ -0,0 +1,730 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: iap.c 17400 2008-05-07 14:30:29Z xxxxxx $ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr & Nick Robinson | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <stdio.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <stdarg.h> | ||
22 | #include <memory.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | #include "iap.h" | ||
26 | #include "button.h" | ||
27 | #include "config.h" | ||
28 | #include "cpu.h" | ||
29 | #include "system.h" | ||
30 | #include "kernel.h" | ||
31 | #include "serial.h" | ||
32 | |||
33 | #include "playlist.h" | ||
34 | #include "playback.h" | ||
35 | #include "audio.h" | ||
36 | #include "settings.h" | ||
37 | #include "metadata.h" | ||
38 | #include "gwps.h" | ||
39 | |||
40 | #include "button.h" | ||
41 | #include "action.h" | ||
42 | |||
43 | #define RX_BUFLEN 260 | ||
44 | #define TX_BUFLEN 128 | ||
45 | |||
46 | static volatile int iap_pollspeed = 0; | ||
47 | static volatile bool iap_remotetick = true; | ||
48 | static bool iap_setupflag = false, iap_updateflag = false; | ||
49 | static int iap_changedctr = 0; | ||
50 | |||
51 | static unsigned long iap_remotebtn = 0; | ||
52 | static int iap_repeatbtn = 0; | ||
53 | static bool iap_btnrepeat = false, iap_btnshuffle = false; | ||
54 | |||
55 | unsigned char serbuf[RX_BUFLEN]; | ||
56 | static int serbuf_i = 0; | ||
57 | |||
58 | static unsigned char response[TX_BUFLEN]; | ||
59 | static int responselen; | ||
60 | |||
61 | static void iap_task(void) | ||
62 | { | ||
63 | static int count = 0; | ||
64 | |||
65 | count += iap_pollspeed; | ||
66 | if (count < (500/10)) return; | ||
67 | |||
68 | /* exec every 500ms if pollspeed == 1 */ | ||
69 | count = 0; | ||
70 | queue_post(&button_queue, SYS_IAP_PERIODIC, 0); | ||
71 | } | ||
72 | |||
73 | void iap_setup(int ratenum) | ||
74 | { | ||
75 | iap_bitrate_set(ratenum); | ||
76 | iap_pollspeed = 0; | ||
77 | iap_remotetick = true; | ||
78 | iap_updateflag = false; | ||
79 | iap_changedctr = 0; | ||
80 | iap_setupflag = true; | ||
81 | iap_remotebtn = BUTTON_NONE; | ||
82 | tick_add_task(iap_task); | ||
83 | } | ||
84 | |||
85 | void iap_bitrate_set(int ratenum) | ||
86 | { | ||
87 | switch(ratenum) | ||
88 | { | ||
89 | case 0: | ||
90 | serial_bitrate(0); | ||
91 | break; | ||
92 | case 1: | ||
93 | serial_bitrate(9600); | ||
94 | break; | ||
95 | case 2: | ||
96 | serial_bitrate(19200); | ||
97 | break; | ||
98 | case 3: | ||
99 | serial_bitrate(38400); | ||
100 | break; | ||
101 | case 4: | ||
102 | serial_bitrate(57600); | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /* Message format: | ||
108 | 0xff | ||
109 | 0x55 | ||
110 | length | ||
111 | mode | ||
112 | command (2 bytes) | ||
113 | parameters (0-n bytes) | ||
114 | checksum (length+mode+parameters+checksum == 0) | ||
115 | */ | ||
116 | |||
117 | void iap_send_pkt(unsigned char * data, int len) | ||
118 | { | ||
119 | int i, chksum; | ||
120 | |||
121 | if(len > TX_BUFLEN-4) len = TX_BUFLEN-4; | ||
122 | responselen = len + 4; | ||
123 | |||
124 | response[0] = 0xFF; | ||
125 | response[1] = 0x55; | ||
126 | |||
127 | chksum = response[2] = len; | ||
128 | for(i = 0; i < len; i ++) | ||
129 | { | ||
130 | chksum += data[i]; | ||
131 | response[i+3] = data[i]; | ||
132 | } | ||
133 | |||
134 | response[i+3] = 0x100 - (chksum & 0xFF); | ||
135 | |||
136 | for(i = 0; i < responselen; i ++) | ||
137 | { | ||
138 | while (!tx_rdy()) ; | ||
139 | tx_writec(response[i]); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | int iap_getc(unsigned char x) | ||
144 | { | ||
145 | static unsigned char last_x = 0; | ||
146 | static bool newpkt = true; | ||
147 | static unsigned char chksum = 0; | ||
148 | |||
149 | /* Restart if the sync word is seen */ | ||
150 | if(x == 0x55 && last_x == 0xff/* && newpkt*/) | ||
151 | { | ||
152 | serbuf[0] = 0; | ||
153 | serbuf_i = 0; | ||
154 | chksum = 0; | ||
155 | newpkt = false; | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | if(serbuf_i >= RX_BUFLEN) | ||
160 | serbuf_i = 0; | ||
161 | |||
162 | serbuf[serbuf_i++] = x; | ||
163 | chksum += x; | ||
164 | } | ||
165 | last_x = x; | ||
166 | |||
167 | /* Broadcast to queue if we have a complete message */ | ||
168 | if(serbuf_i && (serbuf_i == serbuf[0]+2)) | ||
169 | { | ||
170 | serbuf_i = 0; | ||
171 | newpkt = true; | ||
172 | if(chksum == 0) | ||
173 | queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0); | ||
174 | } | ||
175 | return newpkt; | ||
176 | } | ||
177 | |||
178 | void iap_track_changed(void) | ||
179 | { | ||
180 | iap_changedctr = 1; | ||
181 | } | ||
182 | |||
183 | void iap_periodic(void) | ||
184 | { | ||
185 | if(!iap_setupflag) return; | ||
186 | if(!iap_pollspeed) return; | ||
187 | |||
188 | unsigned char data[] = {0x04, 0x00, 0x27, 0x04, 0x00, 0x00, 0x00, 0x00}; | ||
189 | unsigned long time_elapsed = audio_current_track()->elapsed; | ||
190 | |||
191 | time_elapsed += wps_state.ff_rewind_count; | ||
192 | |||
193 | data[3] = 0x04; // playing | ||
194 | |||
195 | /* If info has changed, don't flag it right away */ | ||
196 | if(iap_changedctr && iap_changedctr++ >= iap_pollspeed * 2) | ||
197 | { | ||
198 | /* track info has changed */ | ||
199 | iap_changedctr = 0; | ||
200 | data[3] = 0x01; // 0x02 has same effect? | ||
201 | iap_updateflag = true; | ||
202 | } | ||
203 | |||
204 | data[4] = time_elapsed >> 24; | ||
205 | data[5] = time_elapsed >> 16; | ||
206 | data[6] = time_elapsed >> 8; | ||
207 | data[7] = time_elapsed; | ||
208 | iap_send_pkt(data, sizeof(data)); | ||
209 | } | ||
210 | |||
211 | void iap_handlepkt(void) | ||
212 | { | ||
213 | |||
214 | if(!iap_setupflag) return; | ||
215 | if(serbuf[0] == 0) return; | ||
216 | |||
217 | /* if we are waiting for a remote button to go out, | ||
218 | delay the handling of the new packet */ | ||
219 | if(!iap_remotetick) | ||
220 | { | ||
221 | queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | /* Handle Mode 0 */ | ||
226 | if (serbuf[1] == 0x00) | ||
227 | { | ||
228 | switch (serbuf[2]) | ||
229 | { | ||
230 | /* get model info */ | ||
231 | case 0x0D: | ||
232 | { | ||
233 | unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10, | ||
234 | 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00}; | ||
235 | iap_send_pkt(data, sizeof(data)); | ||
236 | break; | ||
237 | } | ||
238 | /* No idea ??? */ | ||
239 | case 0x0F: | ||
240 | { | ||
241 | unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05}; | ||
242 | iap_send_pkt(data, sizeof(data)); | ||
243 | break; | ||
244 | } | ||
245 | /* FM transmitter sends this: FF 55 06 00 01 05 00 02 01 F1 (mode switch) */ | ||
246 | case 0x01: | ||
247 | { | ||
248 | if(serbuf[3] == 0x05) | ||
249 | { | ||
250 | sleep(HZ/3); | ||
251 | unsigned char data[] = {0x05, 0x02}; | ||
252 | iap_send_pkt(data, sizeof(data)); | ||
253 | } | ||
254 | break; | ||
255 | } | ||
256 | /* FM transmitter sends this: FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (???)*/ | ||
257 | case 0x13: | ||
258 | { | ||
259 | unsigned char data[] = {0x00, 0x02, 0x00, 0x13}; | ||
260 | iap_send_pkt(data, sizeof(data)); | ||
261 | unsigned char data2[] = {0x00, 0x27, 0x00}; | ||
262 | iap_send_pkt(data2, sizeof(data2)); | ||
263 | unsigned char data3[] = {0x05, 0x02}; | ||
264 | iap_send_pkt(data3, sizeof(data3)); | ||
265 | break; | ||
266 | } | ||
267 | /* FM transmitter sends this: FF 55 02 00 05 F9 (mode switch: AiR mode) */ | ||
268 | case 0x05: | ||
269 | { | ||
270 | unsigned char data[] = {0x00, 0x02, 0x06, 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28}; | ||
271 | iap_send_pkt(data, sizeof(data)); | ||
272 | unsigned char data2[] = {0x00, 0x02, 0x00, 0x05}; | ||
273 | iap_send_pkt(data2, sizeof(data2)); | ||
274 | break; | ||
275 | } | ||
276 | /* default response is with cmd ok packet */ | ||
277 | default: | ||
278 | { | ||
279 | unsigned char data[] = {0x00, 0x02, 0x00, 0x00}; | ||
280 | data[3] = serbuf[2]; //respond with cmd | ||
281 | iap_send_pkt(data, sizeof(data)); | ||
282 | break; | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | /* Handle Mode 2 */ | ||
287 | else if (serbuf[1] == 0x02) | ||
288 | { | ||
289 | if(serbuf[2] != 0) return; | ||
290 | iap_remotebtn = BUTTON_NONE; | ||
291 | iap_remotetick = false; | ||
292 | |||
293 | if(serbuf[0] >= 3 && serbuf[3] != 0) | ||
294 | { | ||
295 | if(serbuf[3] & 1) | ||
296 | iap_remotebtn |= BUTTON_RC_PLAY; | ||
297 | if(serbuf[3] & 2) | ||
298 | iap_remotebtn |= BUTTON_RC_VOL_UP; | ||
299 | if(serbuf[3] & 4) | ||
300 | iap_remotebtn |= BUTTON_RC_VOL_DOWN; | ||
301 | if(serbuf[3] & 8) | ||
302 | iap_remotebtn |= BUTTON_RC_RIGHT; | ||
303 | if(serbuf[3] & 16) | ||
304 | iap_remotebtn |= BUTTON_RC_LEFT; | ||
305 | } | ||
306 | else if(serbuf[0] >= 4 && serbuf[4] != 0) | ||
307 | { | ||
308 | if(serbuf[4] & 1) /* play */ | ||
309 | { | ||
310 | if (audio_status() != AUDIO_STATUS_PLAY) | ||
311 | { | ||
312 | iap_remotebtn |= BUTTON_RC_PLAY; | ||
313 | iap_repeatbtn = 2; | ||
314 | iap_remotetick = false; | ||
315 | iap_changedctr = 1; | ||
316 | } | ||
317 | } | ||
318 | if(serbuf[4] & 2) /* pause */ | ||
319 | { | ||
320 | if (audio_status() == AUDIO_STATUS_PLAY) | ||
321 | { | ||
322 | iap_remotebtn |= BUTTON_RC_PLAY; | ||
323 | iap_repeatbtn = 2; | ||
324 | iap_remotetick = false; | ||
325 | iap_changedctr = 1; | ||
326 | } | ||
327 | } | ||
328 | if((serbuf[4] & 128) && !iap_btnshuffle) /* shuffle */ | ||
329 | { | ||
330 | iap_btnshuffle = true; | ||
331 | if(!global_settings.playlist_shuffle) | ||
332 | { | ||
333 | global_settings.playlist_shuffle = 1; | ||
334 | settings_save(); | ||
335 | settings_apply(false); | ||
336 | if (audio_status() & AUDIO_STATUS_PLAY) | ||
337 | playlist_randomise(NULL, current_tick, true); | ||
338 | } | ||
339 | else if(global_settings.playlist_shuffle) | ||
340 | { | ||
341 | global_settings.playlist_shuffle = 0; | ||
342 | settings_save(); | ||
343 | settings_apply(false); | ||
344 | if (audio_status() & AUDIO_STATUS_PLAY) | ||
345 | playlist_sort(NULL, true); | ||
346 | } | ||
347 | } | ||
348 | else | ||
349 | iap_btnshuffle = false; | ||
350 | } | ||
351 | else if(serbuf[0] >= 5 && serbuf[5] != 0) | ||
352 | { | ||
353 | if((serbuf[5] & 1) && !iap_btnrepeat) /* repeat */ | ||
354 | { | ||
355 | int oldmode = global_settings.repeat_mode; | ||
356 | iap_btnrepeat = true; | ||
357 | |||
358 | if (oldmode == REPEAT_ONE) | ||
359 | global_settings.repeat_mode = REPEAT_OFF; | ||
360 | else if (oldmode == REPEAT_ALL) | ||
361 | global_settings.repeat_mode = REPEAT_ONE; | ||
362 | else if (oldmode == REPEAT_OFF) | ||
363 | global_settings.repeat_mode = REPEAT_ALL; | ||
364 | |||
365 | settings_save(); | ||
366 | settings_apply(false); | ||
367 | if (audio_status() & AUDIO_STATUS_PLAY) | ||
368 | audio_flush_and_reload_tracks(); | ||
369 | } | ||
370 | else | ||
371 | iap_btnrepeat = false; | ||
372 | |||
373 | if(serbuf[5] & 16) /* ffwd */ | ||
374 | { | ||
375 | iap_remotebtn |= BUTTON_RC_RIGHT; | ||
376 | } | ||
377 | if(serbuf[5] & 32) /* frwd */ | ||
378 | { | ||
379 | iap_remotebtn |= BUTTON_RC_LEFT; | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | /* Handle Mode 3 */ | ||
384 | else if (serbuf[1] == 0x03) | ||
385 | { | ||
386 | switch(serbuf[2]) | ||
387 | { | ||
388 | /* some kind of status packet? */ | ||
389 | case 0x01: | ||
390 | { | ||
391 | unsigned char data[] = {0x03, 0x02, 0x00, 0x00, 0x00, 0x00}; | ||
392 | iap_send_pkt(data, sizeof(data)); | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | /* Handle Mode 4 */ | ||
398 | else if (serbuf[1] == 0x04) | ||
399 | { | ||
400 | switch (((unsigned long)serbuf[2] << 8) | serbuf[3]) | ||
401 | { | ||
402 | /* Get data updated??? flag */ | ||
403 | case 0x0009: | ||
404 | { | ||
405 | unsigned char data[] = {0x04, 0x00, 0x0A, 0x00}; | ||
406 | data[3] = iap_updateflag ? 0 : 1; | ||
407 | iap_send_pkt(data, sizeof(data)); | ||
408 | break; | ||
409 | } | ||
410 | /* Set data updated??? flag */ | ||
411 | case 0x000B: | ||
412 | { | ||
413 | iap_updateflag = serbuf[4] ? 0 : 1; | ||
414 | /* respond with cmd ok packet */ | ||
415 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x0B}; | ||
416 | iap_send_pkt(data, sizeof(data)); | ||
417 | break; | ||
418 | } | ||
419 | /* Get iPod size? */ | ||
420 | case 0x0012: | ||
421 | { | ||
422 | unsigned char data[] = {0x04, 0x00, 0x13, 0x01, 0x0B}; | ||
423 | iap_send_pkt(data, sizeof(data)); | ||
424 | break; | ||
425 | } | ||
426 | /* Get count of given types */ | ||
427 | case 0x0018: | ||
428 | { | ||
429 | unsigned char data[] = {0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00}; | ||
430 | unsigned long num = 0; | ||
431 | switch(serbuf[4]) /* type number */ | ||
432 | { | ||
433 | case 0x01: /* total number of playlists */ | ||
434 | num = 1; | ||
435 | break; | ||
436 | case 0x05: /* total number of songs */ | ||
437 | num = 1; | ||
438 | } | ||
439 | data[3] = num >> 24; | ||
440 | data[4] = num >> 16; | ||
441 | data[5] = num >> 8; | ||
442 | data[6] = num; | ||
443 | iap_send_pkt(data, sizeof(data)); | ||
444 | break; | ||
445 | } | ||
446 | /* Get time and status */ | ||
447 | case 0x001C: | ||
448 | { | ||
449 | unsigned char data[] = {0x04, 0x00, 0x1D, 0x00, 0x00, 0x00, | ||
450 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
451 | struct mp3entry *id3 = audio_current_track(); | ||
452 | unsigned long time_total = id3->length; | ||
453 | unsigned long time_elapsed = id3->elapsed; | ||
454 | int status = audio_status(); | ||
455 | data[3] = time_total >> 24; | ||
456 | data[4] = time_total >> 16; | ||
457 | data[5] = time_total >> 8; | ||
458 | data[6] = time_total; | ||
459 | data[7] = time_elapsed >> 24; | ||
460 | data[8] = time_elapsed >> 16; | ||
461 | data[9] = time_elapsed >> 8; | ||
462 | data[10] = time_elapsed; | ||
463 | if (status == AUDIO_STATUS_PLAY) | ||
464 | data[11] = 0x01; /* play */ | ||
465 | else if (status & AUDIO_STATUS_PAUSE) | ||
466 | data[11] = 0x02; /* pause */ | ||
467 | iap_send_pkt(data, sizeof(data)); | ||
468 | break; | ||
469 | } | ||
470 | /* Get current pos in playlist */ | ||
471 | case 0x001E: | ||
472 | { | ||
473 | unsigned char data[] = {0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00}; | ||
474 | long playlist_pos = playlist_next(0); | ||
475 | playlist_pos -= playlist_get_first_index(NULL); | ||
476 | if(playlist_pos < 0) | ||
477 | playlist_pos += playlist_amount(); | ||
478 | data[3] = playlist_pos >> 24; | ||
479 | data[4] = playlist_pos >> 16; | ||
480 | data[5] = playlist_pos >> 8; | ||
481 | data[6] = playlist_pos; | ||
482 | iap_send_pkt(data, sizeof(data)); | ||
483 | break; | ||
484 | } | ||
485 | /* Get title of a song number */ | ||
486 | case 0x0020: | ||
487 | /* Get artist of a song number */ | ||
488 | case 0x0022: | ||
489 | /* Get album of a song number */ | ||
490 | case 0x0024: | ||
491 | { | ||
492 | unsigned char data[70] = {0x04, 0x00, 0xFF}; | ||
493 | struct mp3entry id3; | ||
494 | int fd; | ||
495 | long tracknum = (signed long)serbuf[4] << 24 | | ||
496 | (signed long)serbuf[5] << 16 | | ||
497 | (signed long)serbuf[6] << 8 | serbuf[7]; | ||
498 | data[2] = serbuf[3] + 1; | ||
499 | memcpy(&id3, audio_current_track(), sizeof(id3)); | ||
500 | tracknum += playlist_get_first_index(NULL); | ||
501 | if(tracknum >= playlist_amount()) | ||
502 | tracknum -= playlist_amount(); | ||
503 | |||
504 | /* If the tracknumber is not the current one, | ||
505 | read id3 from disk */ | ||
506 | if(playlist_next(0) != tracknum) | ||
507 | { | ||
508 | struct playlist_track_info info; | ||
509 | playlist_get_track_info(NULL, tracknum, &info); | ||
510 | fd = open(info.filename, O_RDONLY); | ||
511 | memset(&id3, 0, sizeof(struct mp3entry)); | ||
512 | get_metadata(&id3, fd, info.filename); | ||
513 | close(fd); | ||
514 | } | ||
515 | |||
516 | /* Return the requested track data */ | ||
517 | switch(serbuf[3]) | ||
518 | { | ||
519 | case 0x20: | ||
520 | strncpy((char *)&data[3], id3.title, 64); | ||
521 | iap_send_pkt(data, 4+strlen(id3.title)); | ||
522 | break; | ||
523 | case 0x22: | ||
524 | strncpy((char *)&data[3], id3.artist, 64); | ||
525 | iap_send_pkt(data, 4+strlen(id3.artist)); | ||
526 | break; | ||
527 | case 0x24: | ||
528 | strncpy((char *)&data[3], id3.album, 64); | ||
529 | iap_send_pkt(data, 4+strlen(id3.album)); | ||
530 | break; | ||
531 | } | ||
532 | break; | ||
533 | } | ||
534 | /* Set polling mode */ | ||
535 | case 0x0026: | ||
536 | { | ||
537 | iap_pollspeed = serbuf[4] ? 1 : 0; | ||
538 | /*responsed with cmd ok packet */ | ||
539 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x26}; | ||
540 | iap_send_pkt(data, sizeof(data)); | ||
541 | break; | ||
542 | } | ||
543 | /* AiR playback control */ | ||
544 | case 0x0029: | ||
545 | { | ||
546 | /* respond with cmd ok packet */ | ||
547 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x29}; | ||
548 | iap_send_pkt(data, sizeof(data)); | ||
549 | switch(serbuf[4]) | ||
550 | { | ||
551 | case 0x01: /* play/pause */ | ||
552 | iap_remotebtn = BUTTON_RC_PLAY; | ||
553 | iap_repeatbtn = 2; | ||
554 | iap_remotetick = false; | ||
555 | iap_changedctr = 1; | ||
556 | break; | ||
557 | case 0x02: /* stop */ | ||
558 | iap_remotebtn = BUTTON_RC_PLAY|BUTTON_REPEAT; | ||
559 | iap_repeatbtn = 2; | ||
560 | iap_remotetick = false; | ||
561 | iap_changedctr = 1; | ||
562 | break; | ||
563 | case 0x03: /* skip++ */ | ||
564 | iap_remotebtn = BUTTON_RC_RIGHT; | ||
565 | iap_repeatbtn = 2; | ||
566 | iap_remotetick = false; | ||
567 | break; | ||
568 | case 0x04: /* skip-- */ | ||
569 | iap_remotebtn = BUTTON_RC_LEFT; | ||
570 | iap_repeatbtn = 2; | ||
571 | iap_remotetick = false; | ||
572 | break; | ||
573 | case 0x05: /* ffwd */ | ||
574 | iap_remotebtn = BUTTON_RC_RIGHT; | ||
575 | iap_remotetick = false; | ||
576 | if(iap_pollspeed) iap_pollspeed = 5; | ||
577 | break; | ||
578 | case 0x06: /* frwd */ | ||
579 | iap_remotebtn = BUTTON_RC_LEFT; | ||
580 | iap_remotetick = false; | ||
581 | if(iap_pollspeed) iap_pollspeed = 5; | ||
582 | break; | ||
583 | case 0x07: /* end ffwd/frwd */ | ||
584 | iap_remotebtn = BUTTON_NONE; | ||
585 | iap_remotetick = false; | ||
586 | if(iap_pollspeed) iap_pollspeed = 1; | ||
587 | break; | ||
588 | } | ||
589 | break; | ||
590 | } | ||
591 | /* Get shuffle mode */ | ||
592 | case 0x002C: | ||
593 | { | ||
594 | unsigned char data[] = {0x04, 0x00, 0x2D, 0x00}; | ||
595 | data[3] = global_settings.playlist_shuffle ? 1 : 0; | ||
596 | iap_send_pkt(data, sizeof(data)); | ||
597 | break; | ||
598 | } | ||
599 | /* Set shuffle mode */ | ||
600 | case 0x002E: | ||
601 | { | ||
602 | if(serbuf[4] && !global_settings.playlist_shuffle) | ||
603 | { | ||
604 | global_settings.playlist_shuffle = 1; | ||
605 | settings_save(); | ||
606 | settings_apply(false); | ||
607 | if (audio_status() & AUDIO_STATUS_PLAY) | ||
608 | playlist_randomise(NULL, current_tick, true); | ||
609 | } | ||
610 | else if(!serbuf[4] && global_settings.playlist_shuffle) | ||
611 | { | ||
612 | global_settings.playlist_shuffle = 0; | ||
613 | settings_save(); | ||
614 | settings_apply(false); | ||
615 | if (audio_status() & AUDIO_STATUS_PLAY) | ||
616 | playlist_sort(NULL, true); | ||
617 | } | ||
618 | |||
619 | |||
620 | /* respond with cmd ok packet */ | ||
621 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x2E}; | ||
622 | iap_send_pkt(data, sizeof(data)); | ||
623 | break; | ||
624 | } | ||
625 | /* Get repeat mode */ | ||
626 | case 0x002F: | ||
627 | { | ||
628 | unsigned char data[] = {0x04, 0x00, 0x30, 0x00}; | ||
629 | if(global_settings.repeat_mode == REPEAT_OFF) | ||
630 | data[3] = 0; | ||
631 | else if(global_settings.repeat_mode == REPEAT_ONE) | ||
632 | data[3] = 1; | ||
633 | else | ||
634 | data[3] = 2; | ||
635 | iap_send_pkt(data, sizeof(data)); | ||
636 | break; | ||
637 | } | ||
638 | /* Set repeat mode */ | ||
639 | case 0x0031: | ||
640 | { | ||
641 | int oldmode = global_settings.repeat_mode; | ||
642 | if (serbuf[4] == 0) | ||
643 | global_settings.repeat_mode = REPEAT_OFF; | ||
644 | else if (serbuf[4] == 1) | ||
645 | global_settings.repeat_mode = REPEAT_ONE; | ||
646 | else if (serbuf[4] == 2) | ||
647 | global_settings.repeat_mode = REPEAT_ALL; | ||
648 | |||
649 | if (oldmode != global_settings.repeat_mode) | ||
650 | { | ||
651 | settings_save(); | ||
652 | settings_apply(false); | ||
653 | if (audio_status() & AUDIO_STATUS_PLAY) | ||
654 | audio_flush_and_reload_tracks(); | ||
655 | } | ||
656 | |||
657 | /* respond with cmd ok packet */ | ||
658 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x31}; | ||
659 | iap_send_pkt(data, sizeof(data)); | ||
660 | break; | ||
661 | } | ||
662 | /* Get Max Screen Size for Picture Upload??? */ | ||
663 | case 0x0033: | ||
664 | { | ||
665 | unsigned char data[] = {0x04, 0x00, 0x34, 0x01, 0x36, 0x00, 0xA8, 0x01}; | ||
666 | iap_send_pkt(data, sizeof(data)); | ||
667 | break; | ||
668 | } | ||
669 | /* Get number songs in current playlist */ | ||
670 | case 0x0035: | ||
671 | { | ||
672 | unsigned char data[] = {0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00}; | ||
673 | unsigned long playlist_amt = playlist_amount(); | ||
674 | data[3] = playlist_amt >> 24; | ||
675 | data[4] = playlist_amt >> 16; | ||
676 | data[5] = playlist_amt >> 8; | ||
677 | data[6] = playlist_amt; | ||
678 | iap_send_pkt(data, sizeof(data)); | ||
679 | break; | ||
680 | } | ||
681 | /* Jump to track number in current playlist */ | ||
682 | case 0x0037: | ||
683 | { | ||
684 | long tracknum = (signed long)serbuf[4] << 24 | | ||
685 | (signed long)serbuf[5] << 16 | | ||
686 | (signed long)serbuf[6] << 8 | serbuf[7]; | ||
687 | if (!wps_state.paused) | ||
688 | audio_pause(); | ||
689 | audio_skip(tracknum - playlist_next(0)); | ||
690 | if (!wps_state.paused) | ||
691 | audio_resume(); | ||
692 | |||
693 | /* respond with cmd ok packet */ | ||
694 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00}; | ||
695 | data[4] = serbuf[2]; | ||
696 | data[5] = serbuf[3]; | ||
697 | iap_send_pkt(data, sizeof(data)); | ||
698 | break; | ||
699 | } | ||
700 | default: | ||
701 | { | ||
702 | /* default response is with cmd ok packet */ | ||
703 | unsigned char data[] = {0x04, 0x00, 0x01, 0x00, 0x00, 0x00}; | ||
704 | data[4] = serbuf[2]; | ||
705 | data[5] = serbuf[3]; | ||
706 | iap_send_pkt(data, sizeof(data)); | ||
707 | break; | ||
708 | } | ||
709 | } | ||
710 | } | ||
711 | serbuf[0] = 0; | ||
712 | } | ||
713 | |||
714 | int remote_control_rx(void) | ||
715 | { | ||
716 | int btn = iap_remotebtn; | ||
717 | if(iap_repeatbtn) | ||
718 | { | ||
719 | iap_repeatbtn--; | ||
720 | if(!iap_repeatbtn) | ||
721 | { | ||
722 | iap_remotebtn = BUTTON_NONE; | ||
723 | iap_remotetick = true; | ||
724 | } | ||
725 | } | ||
726 | else | ||
727 | iap_remotetick = true; | ||
728 | |||
729 | return btn; | ||
730 | } | ||
diff --git a/apps/keymaps/keymap-ipod.c b/apps/keymaps/keymap-ipod.c index 5b735eb530..02854524d2 100644 --- a/apps/keymaps/keymap-ipod.c +++ b/apps/keymaps/keymap-ipod.c | |||
@@ -187,9 +187,62 @@ const struct button_mapping button_context_recscreen[] = { | |||
187 | }; /* button_context_recscreen */ | 187 | }; /* button_context_recscreen */ |
188 | #endif | 188 | #endif |
189 | 189 | ||
190 | #if BUTTON_REMOTE != 0 | ||
191 | /***************************************************************************** | ||
192 | * Remote control mappings | ||
193 | *****************************************************************************/ | ||
194 | |||
195 | static const struct button_mapping remote_button_context_standard[] = { | ||
196 | { ACTION_STD_PREV, BUTTON_RC_LEFT, BUTTON_NONE }, | ||
197 | { ACTION_STD_NEXT, BUTTON_RC_RIGHT, BUTTON_NONE }, | ||
198 | { ACTION_STD_CANCEL, BUTTON_RC_STOP, BUTTON_NONE }, | ||
199 | { ACTION_STD_OK, BUTTON_RC_PLAY, BUTTON_NONE }, | ||
200 | |||
201 | LAST_ITEM_IN_LIST | ||
202 | }; | ||
203 | |||
204 | static const struct button_mapping remote_button_context_wps[] = { | ||
205 | { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, | ||
206 | { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, | ||
207 | { ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP, BUTTON_NONE }, | ||
208 | { ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, | ||
209 | |||
210 | { ACTION_WPS_PLAY, BUTTON_RC_PLAY|BUTTON_REL, BUTTON_RC_PLAY }, | ||
211 | { ACTION_WPS_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_NONE }, | ||
212 | { ACTION_WPS_SKIPNEXT, BUTTON_RC_RIGHT|BUTTON_REL, BUTTON_RC_RIGHT }, | ||
213 | { ACTION_WPS_SEEKFWD, BUTTON_RC_RIGHT|BUTTON_REPEAT,BUTTON_NONE }, | ||
214 | { ACTION_WPS_STOPSEEK, BUTTON_RC_RIGHT|BUTTON_REL, BUTTON_RC_RIGHT|BUTTON_REPEAT }, | ||
215 | { ACTION_WPS_SKIPPREV, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT }, | ||
216 | { ACTION_WPS_SEEKBACK, BUTTON_RC_LEFT|BUTTON_REPEAT, BUTTON_NONE }, | ||
217 | { ACTION_WPS_STOPSEEK, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT|BUTTON_REPEAT }, | ||
218 | |||
219 | LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) | ||
220 | }; | ||
221 | |||
222 | |||
223 | static const struct button_mapping* get_context_mapping_remote( int context ) | ||
224 | { | ||
225 | context ^= CONTEXT_REMOTE; | ||
226 | |||
227 | switch (context) | ||
228 | { | ||
229 | case CONTEXT_WPS: | ||
230 | return remote_button_context_wps; | ||
231 | |||
232 | default: | ||
233 | return remote_button_context_standard; | ||
234 | } | ||
235 | } | ||
236 | #endif /* BUTTON_REMOTE != 0 */ | ||
237 | |||
190 | /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ | 238 | /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ |
191 | const struct button_mapping* get_context_mapping(int context) | 239 | const struct button_mapping* get_context_mapping(int context) |
192 | { | 240 | { |
241 | #if BUTTON_REMOTE != 0 | ||
242 | if (context&CONTEXT_REMOTE) | ||
243 | return get_context_mapping_remote(context); | ||
244 | #endif | ||
245 | |||
193 | switch (context) | 246 | switch (context) |
194 | { | 247 | { |
195 | case CONTEXT_STD: | 248 | case CONTEXT_STD: |
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index f0099e4ec9..f5f9ed3b80 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -11811,6 +11811,110 @@ | |||
11811 | gigabeatf: "High" | 11811 | gigabeatf: "High" |
11812 | </voice> | 11812 | </voice> |
11813 | </phrase> | 11813 | </phrase> |
11814 | <<<<<<< .mine | ||
11815 | <phrase> | ||
11816 | id: LANG_SERIAL_BITRATE | ||
11817 | desc: in system settings menu | ||
11818 | user: | ||
11819 | <source> | ||
11820 | *: none | ||
11821 | serial_port: "Serial Bitrate" | ||
11822 | </source> | ||
11823 | <dest> | ||
11824 | *: none | ||
11825 | serial_port: "Serial Bitrate" | ||
11826 | </dest> | ||
11827 | <voice> | ||
11828 | *: none | ||
11829 | serial_port: "Serial Bitrate" | ||
11830 | </voice> | ||
11831 | </phrase> | ||
11832 | <phrase> | ||
11833 | id: LANG_SERIAL_BITRATE_AUTO | ||
11834 | desc: in system settings menu | ||
11835 | user: | ||
11836 | <source> | ||
11837 | *: none | ||
11838 | serial_port: "Auto" | ||
11839 | </source> | ||
11840 | <dest> | ||
11841 | *: none | ||
11842 | serial_port: "Auto" | ||
11843 | </dest> | ||
11844 | <voice> | ||
11845 | *: none | ||
11846 | serial_port: "Automatic" | ||
11847 | </voice> | ||
11848 | </phrase> | ||
11849 | <phrase> | ||
11850 | id: LANG_SERIAL_BITRATE_9600 | ||
11851 | desc: in system settings menu | ||
11852 | user: | ||
11853 | <source> | ||
11854 | *: none | ||
11855 | serial_port: "9600" | ||
11856 | </source> | ||
11857 | <dest> | ||
11858 | *: none | ||
11859 | serial_port: "9600" | ||
11860 | </dest> | ||
11861 | <voice> | ||
11862 | *: none | ||
11863 | serial_port: "9600" | ||
11864 | </voice> | ||
11865 | </phrase> | ||
11866 | <phrase> | ||
11867 | id: LANG_SERIAL_BITRATE_19200 | ||
11868 | desc: in system settings menu | ||
11869 | user: | ||
11870 | <source> | ||
11871 | *: none | ||
11872 | serial_port: "19200" | ||
11873 | </source> | ||
11874 | <dest> | ||
11875 | *: none | ||
11876 | serial_port: "19200" | ||
11877 | </dest> | ||
11878 | <voice> | ||
11879 | *: none | ||
11880 | serial_port: "19200" | ||
11881 | </voice> | ||
11882 | </phrase> | ||
11883 | <phrase> | ||
11884 | id: LANG_SERIAL_BITRATE_38400 | ||
11885 | desc: in system settings menu | ||
11886 | user: | ||
11887 | <source> | ||
11888 | *: none | ||
11889 | serial_port: "38400" | ||
11890 | </source> | ||
11891 | <dest> | ||
11892 | *: none | ||
11893 | serial_port: "38400" | ||
11894 | </dest> | ||
11895 | <voice> | ||
11896 | *: none | ||
11897 | serial_port: "38400" | ||
11898 | </voice> | ||
11899 | </phrase> | ||
11900 | <phrase> | ||
11901 | id: LANG_SERIAL_BITRATE_57600 | ||
11902 | desc: in system settings menu | ||
11903 | user: | ||
11904 | <source> | ||
11905 | *: none | ||
11906 | serial_port: "57600" | ||
11907 | </source> | ||
11908 | <dest> | ||
11909 | *: none | ||
11910 | serial_port: "57600" | ||
11911 | </dest> | ||
11912 | <voice> | ||
11913 | *: none | ||
11914 | serial_port: "57600" | ||
11915 | </voice> | ||
11916 | </phrase> | ||
11917 | ======= | ||
11814 | <phrase> | 11918 | <phrase> |
11815 | id: LANG_VERY_SLOW | 11919 | id: LANG_VERY_SLOW |
11816 | desc: in settings_menu | 11920 | desc: in settings_menu |
@@ -11909,6 +12013,9 @@ | |||
11909 | *: "slash" | 12013 | *: "slash" |
11910 | </voice> | 12014 | </voice> |
11911 | </phrase> | 12015 | </phrase> |
12016 | <<<<<<< .mine | ||
12017 | >>>>>>> .r18116 | ||
12018 | ======= | ||
11912 | <phrase> | 12019 | <phrase> |
11913 | id: LANG_GAIN_LEFT | 12020 | id: LANG_GAIN_LEFT |
11914 | desc: in the recording screen | 12021 | desc: in the recording screen |
@@ -12110,6 +12217,9 @@ | |||
12110 | *: "Search Results" | 12217 | *: "Search Results" |
12111 | </voice> | 12218 | </voice> |
12112 | </phrase> | 12219 | </phrase> |
12220 | <<<<<<< .mine | ||
12221 | >>>>>>> .r18870 | ||
12222 | ======= | ||
12113 | <phrase> | 12223 | <phrase> |
12114 | id: LANG_QS_ITEMS | 12224 | id: LANG_QS_ITEMS |
12115 | desc: DEPRECATED | 12225 | desc: DEPRECATED |
@@ -12243,3 +12353,4 @@ | |||
12243 | quickscreen: "Set as Bottom Quickscreen Item" | 12353 | quickscreen: "Set as Bottom Quickscreen Item" |
12244 | </voice> | 12354 | </voice> |
12245 | </phrase> | 12355 | </phrase> |
12356 | >>>>>>> .r19041 | ||
diff --git a/apps/main.c b/apps/main.c index 111c5d1e78..45e6c77801 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -73,6 +73,10 @@ | |||
73 | #include "scrobbler.h" | 73 | #include "scrobbler.h" |
74 | #include "icon.h" | 74 | #include "icon.h" |
75 | 75 | ||
76 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
77 | #include "iap.h" | ||
78 | #endif | ||
79 | |||
76 | #if (CONFIG_CODEC == SWCODEC) | 80 | #if (CONFIG_CODEC == SWCODEC) |
77 | #include "playback.h" | 81 | #include "playback.h" |
78 | #endif | 82 | #endif |
@@ -583,6 +587,9 @@ static void init(void) | |||
583 | #if CONFIG_CHARGING | 587 | #if CONFIG_CHARGING |
584 | car_adapter_mode_init(); | 588 | car_adapter_mode_init(); |
585 | #endif | 589 | #endif |
590 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
591 | iap_setup(global_settings.serial_bitrate); | ||
592 | #endif | ||
586 | #ifdef HAVE_ACCESSORY_SUPPLY | 593 | #ifdef HAVE_ACCESSORY_SUPPLY |
587 | accessory_supply_set(global_settings.accessory_supply); | 594 | accessory_supply_set(global_settings.accessory_supply); |
588 | #endif | 595 | #endif |
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index d05726ea44..b6e5ad4171 100644 --- a/apps/menus/settings_menu.c +++ b/apps/menus/settings_menu.c | |||
@@ -247,6 +247,9 @@ MENUITEM_SETTING(line_in, &global_settings.line_in, linein_callback); | |||
247 | #if CONFIG_CHARGING | 247 | #if CONFIG_CHARGING |
248 | MENUITEM_SETTING(car_adapter_mode, &global_settings.car_adapter_mode, NULL); | 248 | MENUITEM_SETTING(car_adapter_mode, &global_settings.car_adapter_mode, NULL); |
249 | #endif | 249 | #endif |
250 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
251 | MENUITEM_SETTING(serial_bitrate, &global_settings.serial_bitrate, NULL); | ||
252 | #endif | ||
250 | #ifdef HAVE_ACCESSORY_SUPPLY | 253 | #ifdef HAVE_ACCESSORY_SUPPLY |
251 | MENUITEM_SETTING(accessory_supply, &global_settings.accessory_supply, NULL); | 254 | MENUITEM_SETTING(accessory_supply, &global_settings.accessory_supply, NULL); |
252 | #endif | 255 | #endif |
@@ -282,6 +285,9 @@ MAKE_MENU(system_menu, ID2P(LANG_SYSTEM), | |||
282 | #if CONFIG_CHARGING | 285 | #if CONFIG_CHARGING |
283 | &car_adapter_mode, | 286 | &car_adapter_mode, |
284 | #endif | 287 | #endif |
288 | #ifdef IPOD_ACCESSORY_PROTOCOL, | ||
289 | &serial_bitrate, | ||
290 | #endif | ||
285 | #ifdef HAVE_ACCESSORY_SUPPLY | 291 | #ifdef HAVE_ACCESSORY_SUPPLY |
286 | &accessory_supply, | 292 | &accessory_supply, |
287 | #endif | 293 | #endif |
diff --git a/apps/misc.c b/apps/misc.c index 11cdee17b9..8b73411549 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -61,6 +61,10 @@ | |||
61 | #include "playlist.h" | 61 | #include "playlist.h" |
62 | #include "yesno.h" | 62 | #include "yesno.h" |
63 | 63 | ||
64 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
65 | #include "iap.h" | ||
66 | #endif | ||
67 | |||
64 | #if (CONFIG_STORAGE & STORAGE_MMC) | 68 | #if (CONFIG_STORAGE & STORAGE_MMC) |
65 | #include "ata_mmc.h" | 69 | #include "ata_mmc.h" |
66 | #endif | 70 | #endif |
@@ -959,6 +963,14 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame | |||
959 | unplug_change(false); | 963 | unplug_change(false); |
960 | return SYS_PHONE_UNPLUGGED; | 964 | return SYS_PHONE_UNPLUGGED; |
961 | #endif | 965 | #endif |
966 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
967 | case SYS_IAP_PERIODIC: | ||
968 | iap_periodic(); | ||
969 | return SYS_IAP_PERIODIC; | ||
970 | case SYS_IAP_HANDLEPKT: | ||
971 | iap_handlepkt(); | ||
972 | return SYS_IAP_HANDLEPKT; | ||
973 | #endif | ||
962 | } | 974 | } |
963 | return 0; | 975 | return 0; |
964 | } | 976 | } |
diff --git a/apps/playback.c b/apps/playback.c index d2d9bb6a34..0f76666c1e 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -82,6 +82,10 @@ | |||
82 | #include "pcm_record.h" | 82 | #include "pcm_record.h" |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
86 | #include "iap.h" | ||
87 | #endif | ||
88 | |||
85 | #define PLAYBACK_VOICE | 89 | #define PLAYBACK_VOICE |
86 | 90 | ||
87 | /* default point to start buffer refill */ | 91 | /* default point to start buffer refill */ |
@@ -646,6 +650,9 @@ bool audio_has_changed_track(void) | |||
646 | { | 650 | { |
647 | if (track_changed) | 651 | if (track_changed) |
648 | { | 652 | { |
653 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
654 | iap_track_changed(); | ||
655 | #endif | ||
649 | track_changed = false; | 656 | track_changed = false; |
650 | return true; | 657 | return true; |
651 | } | 658 | } |
@@ -691,7 +698,7 @@ void audio_resume(void) | |||
691 | queue_send(&audio_queue, Q_AUDIO_PAUSE, false); | 698 | queue_send(&audio_queue, Q_AUDIO_PAUSE, false); |
692 | } | 699 | } |
693 | 700 | ||
694 | static void audio_skip(int direction) | 701 | void audio_skip(int direction) |
695 | { | 702 | { |
696 | if (playlist_check(ci.new_track + wps_offset + direction)) | 703 | if (playlist_check(ci.new_track + wps_offset + direction)) |
697 | { | 704 | { |
diff --git a/apps/playback.h b/apps/playback.h index d9f29cc56a..e65d5da150 100644 --- a/apps/playback.h +++ b/apps/playback.h | |||
@@ -33,7 +33,7 @@ int audio_track_count(void); | |||
33 | long audio_filebufused(void); | 33 | long audio_filebufused(void); |
34 | void audio_pre_ff_rewind(void); | 34 | void audio_pre_ff_rewind(void); |
35 | void audio_set_crossfade(int type); | 35 | void audio_set_crossfade(int type); |
36 | 36 | void audio_skip(int direction); | |
37 | void audio_hard_stop(void); /* Stops audio from serving playback */ | 37 | void audio_hard_stop(void); /* Stops audio from serving playback */ |
38 | 38 | ||
39 | enum | 39 | enum |
diff --git a/apps/settings.h b/apps/settings.h index b0117874cc..f9b3239e05 100644 --- a/apps/settings.h +++ b/apps/settings.h | |||
@@ -488,6 +488,9 @@ struct user_settings | |||
488 | bool peak_meter_clipcounter; /* clipping count indicator */ | 488 | bool peak_meter_clipcounter; /* clipping count indicator */ |
489 | #endif | 489 | #endif |
490 | bool car_adapter_mode; /* 0=off 1=on */ | 490 | bool car_adapter_mode; /* 0=off 1=on */ |
491 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
492 | int serial_bitrate; /* 0=auto 1=9600 2=19200 3=38400 4=57600 */ | ||
493 | #endif | ||
491 | #ifdef HAVE_ACCESSORY_SUPPLY | 494 | #ifdef HAVE_ACCESSORY_SUPPLY |
492 | bool accessory_supply; /* 0=off 1=on, accessory power supply for iPod */ | 495 | bool accessory_supply; /* 0=off 1=on, accessory power supply for iPod */ |
493 | #endif | 496 | #endif |
diff --git a/apps/settings_list.c b/apps/settings_list.c index 27739b29c9..e3874566ac 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c | |||
@@ -49,6 +49,9 @@ | |||
49 | #if CONFIG_TUNER | 49 | #if CONFIG_TUNER |
50 | #include "radio.h" | 50 | #include "radio.h" |
51 | #endif | 51 | #endif |
52 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
53 | #include "iap.h" | ||
54 | #endif | ||
52 | 55 | ||
53 | #define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT) | 56 | #define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT) |
54 | /** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h | 57 | /** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h |
@@ -595,6 +598,12 @@ const struct settings_list settings[] = { | |||
595 | OFFON_SETTING(NVRAM(1), car_adapter_mode, | 598 | OFFON_SETTING(NVRAM(1), car_adapter_mode, |
596 | LANG_CAR_ADAPTER_MODE, false, "car adapter mode", NULL), | 599 | LANG_CAR_ADAPTER_MODE, false, "car adapter mode", NULL), |
597 | #endif | 600 | #endif |
601 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
602 | CHOICE_SETTING(0, serial_bitrate, LANG_SERIAL_BITRATE, 0, "serial bitrate", | ||
603 | "auto,9600,19200,38400,57600", iap_bitrate_set, 5, ID2P(LANG_SERIAL_BITRATE_AUTO), | ||
604 | ID2P(LANG_SERIAL_BITRATE_9600),ID2P(LANG_SERIAL_BITRATE_19200), | ||
605 | ID2P(LANG_SERIAL_BITRATE_38400),ID2P(LANG_SERIAL_BITRATE_57600)), | ||
606 | #endif | ||
598 | #ifdef HAVE_ACCESSORY_SUPPLY | 607 | #ifdef HAVE_ACCESSORY_SUPPLY |
599 | OFFON_SETTING(0, accessory_supply, LANG_ACCESSORY_SUPPLY, | 608 | OFFON_SETTING(0, accessory_supply, LANG_ACCESSORY_SUPPLY, |
600 | true, "accessory power supply", accessory_supply_set), | 609 | true, "accessory power supply", accessory_supply_set), |
diff --git a/firmware/drivers/serial.c b/firmware/drivers/serial.c index 47fbf564ff..a496824261 100644 --- a/firmware/drivers/serial.c +++ b/firmware/drivers/serial.c | |||
@@ -18,7 +18,9 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <stdio.h> | ||
21 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #include <stdarg.h> | ||
22 | #include "button.h" | 24 | #include "button.h" |
23 | #include "config.h" | 25 | #include "config.h" |
24 | #include "cpu.h" | 26 | #include "cpu.h" |
@@ -28,6 +30,7 @@ | |||
28 | #include "adc.h" | 30 | #include "adc.h" |
29 | #include "lcd.h" | 31 | #include "lcd.h" |
30 | #include "serial.h" | 32 | #include "serial.h" |
33 | #include "iap.h" | ||
31 | 34 | ||
32 | #if CONFIG_CPU == IMX31L | 35 | #if CONFIG_CPU == IMX31L |
33 | #include "serial-imx31.h" | 36 | #include "serial-imx31.h" |
@@ -68,6 +71,35 @@ void serial_setup (void) | |||
68 | SCR1 = 0x10; /* Enable the receiver, no interrupt */ | 71 | SCR1 = 0x10; /* Enable the receiver, no interrupt */ |
69 | } | 72 | } |
70 | 73 | ||
74 | int tx_rdy(void) | ||
75 | { | ||
76 | /* a dummy */ | ||
77 | return 1; | ||
78 | } | ||
79 | |||
80 | int rx_rdy(void) | ||
81 | { | ||
82 | if(SSR1 & SCI_RDRF) | ||
83 | return 1; | ||
84 | else | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | void tx_writec(unsigned char c) | ||
89 | { | ||
90 | /* a dummy */ | ||
91 | } | ||
92 | |||
93 | unsigned char rx_readc(void) | ||
94 | { | ||
95 | char tmp; | ||
96 | /* Read byte and clear the Rx Full bit */ | ||
97 | tmp = RDR1; | ||
98 | and_b(~SCI_RDRF, &SSR1); | ||
99 | return tmp; | ||
100 | } | ||
101 | |||
102 | |||
71 | /* This function returns the received remote control code only if it is | 103 | /* This function returns the received remote control code only if it is |
72 | received without errors before or after the reception. | 104 | received without errors before or after the reception. |
73 | It therefore returns the received code on the second call after the | 105 | It therefore returns the received code on the second call after the |
@@ -87,11 +119,9 @@ int remote_control_rx(void) | |||
87 | return BUTTON_NONE; | 119 | return BUTTON_NONE; |
88 | } | 120 | } |
89 | 121 | ||
90 | if(SSR1 & SCI_RDRF) { | 122 | if(rx_rdy()) { |
91 | /* Read byte and clear the Rx Full bit */ | 123 | btn = rx_readc(); |
92 | btn = RDR1; | 124 | |
93 | and_b(~SCI_RDRF, &SSR1); | ||
94 | |||
95 | if(last_was_error) | 125 | if(last_was_error) |
96 | { | 126 | { |
97 | last_valid_button = BUTTON_NONE; | 127 | last_valid_button = BUTTON_NONE; |
@@ -149,16 +179,6 @@ int remote_control_rx(void) | |||
149 | #endif /* !HAVE_FMADC && !STORAGE_MMC */ | 179 | #endif /* !HAVE_FMADC && !STORAGE_MMC */ |
150 | #elif defined(CPU_COLDFIRE) && defined(HAVE_SERIAL) | 180 | #elif defined(CPU_COLDFIRE) && defined(HAVE_SERIAL) |
151 | 181 | ||
152 | void serial_tx(const unsigned char *buf) | ||
153 | { | ||
154 | while(*buf) { | ||
155 | while(!(USR0 & 0x04)) | ||
156 | { | ||
157 | }; | ||
158 | UTB0 = *buf++; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | void serial_setup (void) | 182 | void serial_setup (void) |
163 | { | 183 | { |
164 | UCR0 = 0x30; /* Reset transmitter */ | 184 | UCR0 = 0x30; /* Reset transmitter */ |
@@ -171,6 +191,25 @@ void serial_setup (void) | |||
171 | UCR0 = 0x04; /* Tx enable */ | 191 | UCR0 = 0x04; /* Tx enable */ |
172 | } | 192 | } |
173 | 193 | ||
194 | int tx_rdy(void) | ||
195 | { | ||
196 | if(USR0 & 0x04) | ||
197 | return 1; | ||
198 | else | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | int rx_rdy(void) | ||
203 | { | ||
204 | /* a dummy */ | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | void tx_writec(unsigned char c) | ||
209 | { | ||
210 | UTB0 = c; | ||
211 | } | ||
212 | |||
174 | #elif (CONFIG_CPU == IMX31L) | 213 | #elif (CONFIG_CPU == IMX31L) |
175 | 214 | ||
176 | void serial_setup(void) | 215 | void serial_setup(void) |
@@ -207,15 +246,216 @@ int rx_rdy(void) | |||
207 | return 0; | 246 | return 0; |
208 | } | 247 | } |
209 | 248 | ||
210 | void tx_writec(char c) | 249 | void tx_writec(unsigned char c) |
211 | { | 250 | { |
212 | UTXD1=(int) c; | 251 | UTXD1=(int) c; |
213 | } | 252 | } |
214 | 253 | ||
254 | #elif defined(IPOD_ACCESSORY_PROTOCOL) | ||
255 | static int autobaud = 0; | ||
256 | void serial_setup (void) | ||
257 | { | ||
258 | int tmp; | ||
259 | |||
260 | #if (MODEL_NUMBER == 3) || (MODEL_NUMBER == 8) | ||
261 | |||
262 | /* Route the Tx/Rx pins. 4G Ipod??? */ | ||
263 | outl(0x70000018, inl(0x70000018) & ~0xc00); | ||
264 | #elif (MODEL_NUMBER == 4) || (MODEL_NUMBER == 5) | ||
265 | |||
266 | /* Route the Tx/Rx pins. 5G Ipod */ | ||
267 | (*(volatile unsigned long *)(0x7000008C)) &= ~0x0C; | ||
268 | GPO32_ENABLE &= ~0x0C; | ||
269 | #endif | ||
270 | |||
271 | DEV_EN = DEV_EN | DEV_SER0; | ||
272 | CPU_HI_INT_DIS = SER0_MASK; | ||
273 | |||
274 | DEV_RS |= DEV_SER0; | ||
275 | sleep(1); | ||
276 | DEV_RS &= ~DEV_SER0; | ||
277 | |||
278 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
279 | SER0_DLM = 0x00; | ||
280 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
281 | SER0_IER = 0x01; | ||
282 | |||
283 | SER0_FCR = 0x07; /* Tx+Rx FIFO reset and FIFO enable */ | ||
284 | |||
285 | CPU_INT_EN |= HI_MASK; | ||
286 | CPU_HI_INT_EN |= SER0_MASK; | ||
287 | tmp = SER0_RBR; | ||
288 | |||
289 | serial_bitrate(0); | ||
290 | } | ||
291 | |||
292 | void serial_bitrate(int rate) | ||
293 | { | ||
294 | if(rate == 0) | ||
295 | { | ||
296 | autobaud = 2; | ||
297 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
298 | SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */ | ||
299 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | autobaud = 0; | ||
304 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
305 | SER0_DLL = 24000000L / rate / 16; | ||
306 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
307 | } | ||
308 | |||
309 | int tx_rdy(void) | ||
310 | { | ||
311 | if((SER0_LSR & 0x20)) | ||
312 | return 1; | ||
313 | else | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | int rx_rdy(void) | ||
318 | { | ||
319 | if((SER0_LSR & 0x1)) | ||
320 | return 1; | ||
321 | else | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | void tx_writec(unsigned char c) | ||
326 | { | ||
327 | SER0_THR =(int) c; | ||
328 | } | ||
329 | |||
330 | unsigned char rx_readc(void) | ||
331 | { | ||
332 | return (SER0_RBR & 0xFF); | ||
333 | } | ||
334 | |||
335 | void SERIAL0(void) | ||
336 | { | ||
337 | static int badbaud = 0; | ||
338 | static bool newpkt = true; | ||
339 | char temp; | ||
340 | |||
341 | while(rx_rdy()) | ||
342 | { | ||
343 | temp = rx_readc(); | ||
344 | if (newpkt && autobaud > 0) | ||
345 | { | ||
346 | if (autobaud == 1) | ||
347 | { | ||
348 | switch (temp) | ||
349 | { | ||
350 | case 0xFF: | ||
351 | case 0x55: | ||
352 | break; | ||
353 | case 0xFC: | ||
354 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
355 | SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */ | ||
356 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
357 | temp = 0xFF; | ||
358 | break; | ||
359 | case 0xE0: | ||
360 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
361 | SER0_DLL = 0x9C; /* 24000000/156/16 = 9615 baud */ | ||
362 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
363 | temp = 0xFF; | ||
364 | break; | ||
365 | default: | ||
366 | badbaud++; | ||
367 | if (badbaud >= 6) /* Switch baud detection mode */ | ||
368 | { | ||
369 | autobaud = 2; | ||
370 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
371 | SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */ | ||
372 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
373 | badbaud = 0; | ||
374 | } else { | ||
375 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
376 | SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */ | ||
377 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
378 | } | ||
379 | continue; | ||
380 | } | ||
381 | } else { | ||
382 | switch (temp) | ||
383 | { | ||
384 | case 0xFF: | ||
385 | case 0x55: | ||
386 | break; | ||
387 | case 0xFE: | ||
388 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
389 | SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */ | ||
390 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
391 | temp = 0xFF; | ||
392 | break; | ||
393 | case 0xFC: | ||
394 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
395 | SER0_DLL = 0x27; /* 24000000/39/16 = 38461 baud */ | ||
396 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
397 | temp = 0xFF; | ||
398 | break; | ||
399 | case 0xE0: | ||
400 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
401 | SER0_DLL = 0x4E; /* 24000000/78/16 = 19230 baud */ | ||
402 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
403 | temp = 0xFF; | ||
404 | break; | ||
405 | default: | ||
406 | badbaud++; | ||
407 | if (badbaud >= 6) /* Switch baud detection */ | ||
408 | { | ||
409 | autobaud = 1; | ||
410 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
411 | SER0_DLL = 0x1A; /* 24000000/26/16 = 57692 baud */ | ||
412 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
413 | badbaud = 0; | ||
414 | } else { | ||
415 | SER0_LCR = 0x80; /* Divisor latch enable */ | ||
416 | SER0_DLL = 0x0D; /* 24000000/13/16 = 115384 baud */ | ||
417 | SER0_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ | ||
418 | } | ||
419 | continue; | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | bool pkt = iap_getc(temp); | ||
424 | if(newpkt == true && pkt == false) | ||
425 | autobaud = 0; /* Found good baud */ | ||
426 | newpkt = pkt; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | #else /* Other targets */ | ||
431 | void serial_setup (void) | ||
432 | { | ||
433 | /* a dummy */ | ||
434 | } | ||
435 | |||
436 | int tx_rdy(void) | ||
437 | { | ||
438 | /* a dummy */ | ||
439 | return 1; | ||
440 | } | ||
441 | |||
442 | int rx_rdy(void) | ||
443 | { | ||
444 | /* a dummy */ | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | void tx_writec(unsigned char c) | ||
449 | { | ||
450 | /* a dummy */ | ||
451 | } | ||
452 | |||
453 | #endif | ||
454 | |||
215 | void dprintf(const char * str, ... ) | 455 | void dprintf(const char * str, ... ) |
216 | { | 456 | { |
217 | char dprintfbuff[256]; | 457 | char dprintfbuff[256]; |
218 | unsigned char * ptr; | 458 | char * ptr; |
219 | 459 | ||
220 | va_list ap; | 460 | va_list ap; |
221 | va_start(ap, str); | 461 | va_start(ap, str); |
@@ -224,7 +464,7 @@ void dprintf(const char * str, ... ) | |||
224 | vsnprintf(ptr,sizeof(dprintfbuff),str,ap); | 464 | vsnprintf(ptr,sizeof(dprintfbuff),str,ap); |
225 | va_end(ap); | 465 | va_end(ap); |
226 | 466 | ||
227 | serial_tx(ptr); | 467 | serial_tx((unsigned char *)ptr); |
228 | } | 468 | } |
229 | 469 | ||
230 | void serial_tx(const unsigned char * buf) | 470 | void serial_tx(const unsigned char * buf) |
@@ -241,10 +481,3 @@ void serial_tx(const unsigned char * buf) | |||
241 | } | 481 | } |
242 | } | 482 | } |
243 | } | 483 | } |
244 | |||
245 | #else /* Other targets */ | ||
246 | void serial_setup (void) | ||
247 | { | ||
248 | /* a dummy */ | ||
249 | } | ||
250 | #endif | ||
diff --git a/firmware/export/config-ipod4g.h b/firmware/export/config-ipod4g.h index 89b14f9907..f6c71f39d8 100644 --- a/firmware/export/config-ipod4g.h +++ b/firmware/export/config-ipod4g.h | |||
@@ -186,4 +186,6 @@ | |||
186 | 186 | ||
187 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 187 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
188 | 188 | ||
189 | #define IPOD_ACCESSORY_PROTOCOL | ||
190 | |||
189 | #endif | 191 | #endif |
diff --git a/firmware/export/config-ipodcolor.h b/firmware/export/config-ipodcolor.h index 47b7a4eacf..58a888a969 100644 --- a/firmware/export/config-ipodcolor.h +++ b/firmware/export/config-ipodcolor.h | |||
@@ -166,4 +166,6 @@ | |||
166 | 166 | ||
167 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 167 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
168 | 168 | ||
169 | #define IPOD_ACCESSORY_PROTOCOL | ||
170 | |||
169 | #endif | 171 | #endif |
diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h index 6017d0a2e8..8752181bb9 100644 --- a/firmware/export/config-ipodnano.h +++ b/firmware/export/config-ipodnano.h | |||
@@ -177,4 +177,6 @@ | |||
177 | 177 | ||
178 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 178 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
179 | 179 | ||
180 | #define IPOD_ACCESSORY_PROTOCOL | ||
181 | |||
180 | #endif | 182 | #endif |
diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h index d04e562086..ab974dc236 100644 --- a/firmware/export/config-ipodvideo.h +++ b/firmware/export/config-ipodvideo.h | |||
@@ -197,4 +197,6 @@ | |||
197 | 197 | ||
198 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 198 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
199 | 199 | ||
200 | #define IPOD_ACCESSORY_PROTOCOL | ||
201 | |||
200 | #endif | 202 | #endif |
diff --git a/firmware/export/iap.h b/firmware/export/iap.h new file mode 100644 index 0000000000..6c0b968ab0 --- /dev/null +++ b/firmware/export/iap.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: iap.h 17400 2008-05-07 20:22:16Z xxxxxx $ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef __IAP_H__ | ||
21 | #define __IAP_H__ | ||
22 | |||
23 | extern int iap_getc(unsigned char x); | ||
24 | extern void iap_write_pkt(unsigned char data, int len); | ||
25 | extern void iap_setup(int ratenum); | ||
26 | extern void iap_bitrate_set(int ratenum); | ||
27 | extern void iap_periodic(void); | ||
28 | extern void iap_handlepkt(void); | ||
29 | extern void iap_track_changed(void); | ||
30 | |||
31 | #endif | ||
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index ef65463e5d..29cf8f2eb9 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h | |||
@@ -78,6 +78,8 @@ | |||
78 | #define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5) | 78 | #define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5) |
79 | #define SYS_SCREENDUMP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0) | 79 | #define SYS_SCREENDUMP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0) |
80 | #define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1) | 80 | #define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1) |
81 | #define SYS_IAP_PERIODIC MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2) | ||
82 | #define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3) | ||
81 | 83 | ||
82 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) | 84 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) |
83 | 85 | ||
diff --git a/firmware/export/serial.h b/firmware/export/serial.h index 425fc66fc6..8a4780c3f1 100644 --- a/firmware/export/serial.h +++ b/firmware/export/serial.h | |||
@@ -22,8 +22,11 @@ | |||
22 | #ifndef __SERIAL_H__ | 22 | #ifndef __SERIAL_H__ |
23 | #define __SERIAL_H__ | 23 | #define __SERIAL_H__ |
24 | 24 | ||
25 | extern void serial_setup (void); | 25 | extern void serial_setup(void); |
26 | extern void serial_bitrate(int rate); | ||
26 | extern int remote_control_rx(void); | 27 | extern int remote_control_rx(void); |
27 | extern void serial_tx(const unsigned char *buf); | 28 | extern void serial_tx(const unsigned char *buf); |
29 | extern void tx_writec(unsigned char c); | ||
30 | extern int tx_rdy(void); | ||
28 | 31 | ||
29 | #endif | 32 | #endif |
diff --git a/firmware/target/arm/ipod/button-clickwheel.c b/firmware/target/arm/ipod/button-clickwheel.c index e36c928fb0..21bbca62f0 100644 --- a/firmware/target/arm/ipod/button-clickwheel.c +++ b/firmware/target/arm/ipod/button-clickwheel.c | |||
@@ -316,7 +316,11 @@ int button_read_device(void) | |||
316 | } | 316 | } |
317 | 317 | ||
318 | /* The int_btn variable is set in the button interrupt handler */ | 318 | /* The int_btn variable is set in the button interrupt handler */ |
319 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
320 | return int_btn | remote_control_rx(); | ||
321 | #else | ||
319 | return int_btn; | 322 | return int_btn; |
323 | #endif | ||
320 | } | 324 | } |
321 | 325 | ||
322 | bool button_hold(void) | 326 | bool button_hold(void) |
diff --git a/firmware/target/arm/ipod/button-target.h b/firmware/target/arm/ipod/button-target.h index a0ac372839..67bdc72955 100644 --- a/firmware/target/arm/ipod/button-target.h +++ b/firmware/target/arm/ipod/button-target.h | |||
@@ -50,7 +50,22 @@ void ipod_4g_button_int(void); | |||
50 | |BUTTON_LEFT|BUTTON_RIGHT|BUTTON_SCROLL_FWD\ | 50 | |BUTTON_LEFT|BUTTON_RIGHT|BUTTON_SCROLL_FWD\ |
51 | |BUTTON_SCROLL_BACK|BUTTON_PLAY) | 51 | |BUTTON_SCROLL_BACK|BUTTON_PLAY) |
52 | 52 | ||
53 | /* Remote control's buttons */ | ||
54 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
55 | #define BUTTON_RC_PLAY 0x00100000 | ||
56 | #define BUTTON_RC_STOP 0x00080000 | ||
57 | |||
58 | #define BUTTON_RC_LEFT 0x00040000 | ||
59 | #define BUTTON_RC_RIGHT 0x00020000 | ||
60 | #define BUTTON_RC_VOL_UP 0x00010000 | ||
61 | #define BUTTON_RC_VOL_DOWN 0x00008000 | ||
62 | |||
63 | #define BUTTON_REMOTE (BUTTON_RC_PLAY|BUTTON_RC_STOP\ | ||
64 | |BUTTON_RC_LEFT|BUTTON_RC_RIGHT\ | ||
65 | |BUTTON_RC_VOL_UP|BUTTON_RC_VOL_DOWN) | ||
66 | #else | ||
53 | #define BUTTON_REMOTE 0 | 67 | #define BUTTON_REMOTE 0 |
68 | #endif | ||
54 | 69 | ||
55 | /* This is for later | 70 | /* This is for later |
56 | #define BUTTON_SCROLL_TOUCH 0x00000200 | 71 | #define BUTTON_SCROLL_TOUCH 0x00000200 |
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c index d683b3a561..b1f178c8d5 100644 --- a/firmware/target/arm/system-pp502x.c +++ b/firmware/target/arm/system-pp502x.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #ifndef BOOTLOADER | 32 | #ifndef BOOTLOADER |
33 | extern void TIMER1(void); | 33 | extern void TIMER1(void); |
34 | extern void TIMER2(void); | 34 | extern void TIMER2(void); |
35 | extern void SERIAL0(void); | ||
35 | extern void ipod_mini_button_int(void); /* iPod Mini 1st gen only */ | 36 | extern void ipod_mini_button_int(void); /* iPod Mini 1st gen only */ |
36 | extern void ipod_4g_button_int(void); /* iPod 4th gen and higher only */ | 37 | extern void ipod_4g_button_int(void); /* iPod 4th gen and higher only */ |
37 | 38 | ||
@@ -78,6 +79,11 @@ void irq(void) | |||
78 | button_int(); | 79 | button_int(); |
79 | } | 80 | } |
80 | #endif | 81 | #endif |
82 | #ifdef IPOD_ACCESSORY_PROTOCOL | ||
83 | else if (CPU_HI_INT_STAT & SER0_MASK) { | ||
84 | SERIAL0(); | ||
85 | } | ||
86 | #endif | ||
81 | #ifdef HAVE_USBSTACK | 87 | #ifdef HAVE_USBSTACK |
82 | else if (CPU_INT_STAT & USB_MASK) { | 88 | else if (CPU_INT_STAT & USB_MASK) { |
83 | usb_drv_int(); | 89 | usb_drv_int(); |