summaryrefslogtreecommitdiff
path: root/apps/iap.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/iap.c')
-rw-r--r--apps/iap.c208
1 files changed, 174 insertions, 34 deletions
diff --git a/apps/iap.c b/apps/iap.c
index 29cee22ab5..741ff9fb0c 100644
--- a/apps/iap.c
+++ b/apps/iap.c
@@ -37,11 +37,12 @@
37#include "settings.h" 37#include "settings.h"
38#include "metadata.h" 38#include "metadata.h"
39#include "wps.h" 39#include "wps.h"
40 40#include "sound.h"
41#include "action.h" 41#include "action.h"
42#include "powermgmt.h"
42 43
43#define RX_BUFLEN 260 44#include "tuner.h"
44#define TX_BUFLEN 128 45#include "ipod_remote_tuner.h"
45 46
46static volatile int iap_pollspeed = 0; 47static volatile int iap_pollspeed = 0;
47static volatile bool iap_remotetick = true; 48static volatile bool iap_remotetick = true;
@@ -115,7 +116,7 @@ void iap_bitrate_set(int ratenum)
115 checksum (length+mode+parameters+checksum == 0) 116 checksum (length+mode+parameters+checksum == 0)
116*/ 117*/
117 118
118static void iap_send_pkt(const unsigned char * data, int len) 119void iap_send_pkt(const unsigned char * data, int len)
119{ 120{
120 int i, chksum; 121 int i, chksum;
121 122
@@ -192,15 +193,15 @@ void iap_periodic(void)
192 unsigned long time_elapsed = audio_current_track()->elapsed; 193 unsigned long time_elapsed = audio_current_track()->elapsed;
193 194
194 time_elapsed += wps_get_ff_rewind_count(); 195 time_elapsed += wps_get_ff_rewind_count();
195 196
196 data[3] = 0x04; // playing 197 data[3] = 0x04; /* playing */
197 198
198 /* If info has changed, don't flag it right away */ 199 /* If info has changed, don't flag it right away */
199 if(iap_changedctr && iap_changedctr++ >= iap_pollspeed * 2) 200 if(iap_changedctr && iap_changedctr++ >= iap_pollspeed * 2)
200 { 201 {
201 /* track info has changed */ 202 /* track info has changed */
202 iap_changedctr = 0; 203 iap_changedctr = 0;
203 data[3] = 0x01; // 0x02 has same effect? 204 data[3] = 0x01; /* 0x02 has same effect? */
204 iap_updateflag = true; 205 iap_updateflag = true;
205 } 206 }
206 207
@@ -211,12 +212,19 @@ void iap_periodic(void)
211 iap_send_pkt(data, sizeof(data)); 212 iap_send_pkt(data, sizeof(data));
212} 213}
213 214
215void iap_set_remote_volume(void)
216{
217 unsigned char data[] = {0x03, 0x0D, 0x04, 0x00, 0x00};
218 data[4] = (char)((global_settings.volume+58) * 4);
219 iap_send_pkt(data, sizeof(data));
220}
221
214void iap_handlepkt(void) 222void iap_handlepkt(void)
215{ 223{
216 224
217 if(!iap_setupflag) return; 225 if(!iap_setupflag) return;
218 if(serbuf[0] == 0) return; 226 if(serbuf[0] == 0) return;
219 227
220 /* if we are waiting for a remote button to go out, 228 /* if we are waiting for a remote button to go out,
221 delay the handling of the new packet */ 229 delay the handling of the new packet */
222 if(!iap_remotetick) 230 if(!iap_remotetick)
@@ -224,63 +232,140 @@ void iap_handlepkt(void)
224 queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0); 232 queue_post(&button_queue, SYS_IAP_HANDLEPKT, 0);
225 return; 233 return;
226 } 234 }
227 235
228 /* Handle Mode 0 */ 236 /* Handle Mode 0 */
229 if (serbuf[1] == 0x00) 237 if (serbuf[1] == 0x00)
230 { 238 {
231 switch (serbuf[2]) 239 switch (serbuf[2])
232 { 240 {
233 /* get model info */ 241 case 0x24:
234 case 0x0D:
235 { 242 {
236 unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10, 243 /* ipod video send this */
237 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00}; 244 unsigned char data[] = {0x00, 0x25, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00,0x01};
238 iap_send_pkt(data, sizeof(data)); 246 iap_send_pkt(data, sizeof(data));
239 break; 247 break;
240 } 248 }
241 /* No idea ??? */ 249
242 case 0x0F: 250 case 0x18:
243 { 251 {
244 unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05}; 252 /* ciphered authentication command */
245 iap_send_pkt(data, sizeof(data)); 253 /* Isn't used since we don't send the 0x00 0x17 command */
246 break; 254 break;
247 } 255 }
248 /* FM transmitter sends this: FF 55 06 00 01 05 00 02 01 F1 (mode switch) */ 256
249 case 0x01: 257 case 0x15:
250 { 258 {
251 if(serbuf[3] == 0x05) 259 unsigned char data0[] = {0x00, 0x16, 0x00};
260 iap_send_pkt(data0, sizeof(data0));
261 unsigned char data1[] = {0x00, 0x27, 0x00};
262 iap_send_pkt(data1, sizeof(data1));
263 /* authentication ack, mandatory to enable some hardware */
264 unsigned char data2[] = {0x00, 0x19, 0x00};
265 iap_send_pkt(data2, sizeof(data2));
266 if (radio_present == 1)
252 { 267 {
253 sleep(HZ/3); 268 /* get tuner capacities */
254 unsigned char data[] = {0x05, 0x02}; 269 unsigned char data3[] = {0x07, 0x01};
255 iap_send_pkt(data, sizeof(data)); 270 iap_send_pkt(data3, sizeof(data3));
256 } 271 }
272 iap_set_remote_volume();
257 break; 273 break;
258 } 274 }
259 /* FM transmitter sends this: FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (???)*/ 275
260 case 0x13: 276 case 0x13:
261 { 277 {
262 unsigned char data[] = {0x00, 0x02, 0x00, 0x13}; 278 unsigned char data[] = {0x00, 0x02, 0x00, 0x13};
263 iap_send_pkt(data, sizeof(data)); 279 iap_send_pkt(data, sizeof(data));
264 unsigned char data2[] = {0x00, 0x27, 0x00}; 280
265 iap_send_pkt(data2, sizeof(data2)); 281 if (serbuf[6] == 0x35)
266 unsigned char data3[] = {0x05, 0x02}; 282 /* FM transmitter sends this: */
267 iap_send_pkt(data3, sizeof(data3)); 283 /* FF 55 0E 00 13 00 00 00 35 00 00 00 04 00 00 00 00 A6 (??)*/
284 {
285 unsigned char data2[] = {0x00, 0x27, 0x00};
286 iap_send_pkt(data2, sizeof(data2));
287 unsigned char data3[] = {0x05, 0x02};
288 iap_send_pkt(data3, sizeof(data3));
289 }
290
291 else
292 {
293 /* ipod fm remote sends this: */
294 /* FF 55 0E 00 13 00 00 00 8D 00 00 00 0E 00 00 00 03 41 */
295 if (serbuf[6] |= 0x80)
296 radio_present = 1;
297 unsigned char data4[] = {0x00, 0x14};
298 iap_send_pkt(data4, sizeof(data4));
299 }
268 break; 300 break;
269 } 301 }
270 /* FM transmitter sends this: FF 55 02 00 05 F9 (mode switch: AiR mode) */ 302
303 /* Init */
304 case 0x0F:
305 {
306 unsigned char data[] = {0x00, 0x10, 0x00, 0x01, 0x05};
307 data[2] = serbuf[3];
308 iap_send_pkt(data, sizeof(data));
309 break;
310 }
311
312 /* get model info */
313 case 0x0D:
314 {
315 /* ipod is supposed to work only with 5G and nano 2G */
316 /*{0x00, 0x0E, 0x00, 0x0B, 0x00, 0x05, 0x50, 0x41, 0x31, 0x34,
317 0x37, 0x4C, 0x4C, 0x00}; PA147LL (IPOD 5G 60 GO) */
318 unsigned char data[] = {0x00, 0x0E, 0x00, 0x0B, 0x00, 0x10,
319 'R', 'O', 'C', 'K', 'B', 'O', 'X', 0x00};
320 iap_send_pkt(data, sizeof(data));
321 break;
322 }
323
324 /* Ipod FM remote sends this: FF 55 02 00 09 F5 */
325 case 0x09:
326 {
327 /* ipod5G firmware version */
328 unsigned char data[] = {0x00, 0x0A, 0x01, 0x02, 0x01 };
329 iap_send_pkt(data, sizeof(data));
330 break;
331 }
332
333 /* FM transmitter sends this: */
334 /* FF 55 02 00 05 F9 (mode switch: AiR mode) */
271 case 0x05: 335 case 0x05:
272 { 336 {
273 unsigned char data[] = {0x00, 0x02, 0x06, 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28}; 337 unsigned char data[] = {0x00, 0x02, 0x06,
338 0x05, 0x00, 0x00, 0x0B, 0xB8, 0x28};
274 iap_send_pkt(data, sizeof(data)); 339 iap_send_pkt(data, sizeof(data));
275 unsigned char data2[] = {0x00, 0x02, 0x00, 0x05}; 340 unsigned char data2[] = {0x00, 0x02, 0x00, 0x05};
276 iap_send_pkt(data2, sizeof(data2)); 341 iap_send_pkt(data2, sizeof(data2));
277 break; 342 break;
278 } 343 }
344
345 case 0x01:
346 {
347 /* FM transmitter sends this: */
348 /* FF 55 06 00 01 05 00 02 01 F1 (mode switch) */
349 if(serbuf[3] == 0x05)
350 {
351 sleep(HZ/3);
352 unsigned char data[] = {0x05, 0x02};
353 iap_send_pkt(data, sizeof(data));
354 }
355 /* FM remote sends this: */
356 /* FF 55 03 00 01 02 FA (1st thing sent) */
357 else if(serbuf[3] == 0x02)
358 {
359 /* useful only for apple firmware */
360 }
361 break;
362 }
363
279 /* default response is with cmd ok packet */ 364 /* default response is with cmd ok packet */
280 default: 365 default:
281 { 366 {
282 unsigned char data[] = {0x00, 0x02, 0x00, 0x00}; 367 unsigned char data[] = {0x00, 0x02, 0x00, 0x00};
283 data[3] = serbuf[2]; //respond with cmd 368 data[3] = serbuf[2]; /* respond with cmd */
284 iap_send_pkt(data, sizeof(data)); 369 iap_send_pkt(data, sizeof(data));
285 break; 370 break;
286 } 371 }
@@ -395,6 +480,30 @@ void iap_handlepkt(void)
395 iap_send_pkt(data, sizeof(data)); 480 iap_send_pkt(data, sizeof(data));
396 break; 481 break;
397 } 482 }
483
484 case 0x08:
485 {
486 /* ACK */
487 unsigned char data[] = {0x03, 0x00, 0x00, 0x08};
488 iap_send_pkt(data, sizeof(data));
489 break;
490 }
491
492 case 0x0C:
493 {
494 /* request ipod volume */
495 if (serbuf[3] == 0x04)
496 {
497 iap_set_remote_volume();
498 }
499 break;
500 }
501 /* get volume from accessory */
502 case 0x0E:
503 if (serbuf[3] == 0x04)
504 global_settings.volume = (-58)+((int)serbuf[5]+1)/4;
505 sound_set_volume(global_settings.volume);
506 break;
398 } 507 }
399 } 508 }
400 /* Handle Mode 4 */ 509 /* Handle Mode 4 */
@@ -712,6 +821,37 @@ void iap_handlepkt(void)
712 } 821 }
713 } 822 }
714 } 823 }
824 /* Handle Mode 7 */
825 else if (serbuf[1] == 0x07)
826 {
827 switch(serbuf[2])
828 {
829 /* tuner capabilities */
830 case 0x02:
831 {
832 /* do nothing */
833
834 unsigned char data[] = {0x00, 0x27, 0x00};
835 iap_send_pkt(data, sizeof(data));
836 break;
837 }
838 /* actual tuner frequency */
839 case 0x0A:
840 /* fall through */
841 /* tuner frequency from scan */
842 case 0x13:
843 {
844 rmt_tuner_freq();
845 break;
846 }
847 /* RDS station name 0x21 1E 00 + ASCII text*/
848 case 0x21:
849 {
850 rmt_tuner_rds_data();
851 break;
852 }
853 }
854 }
715 serbuf[0] = 0; 855 serbuf[0] = 0;
716} 856}
717 857