diff options
author | Ralf Ertzinger <rockbox@camperquake.de> | 2013-06-22 10:08:23 +0100 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2013-11-10 18:41:24 +0100 |
commit | b170c73f922e3457b923b4e7fcbec794a8885c77 (patch) | |
tree | 89fbdbd8c25af5101a29a1ede3b896332a4e205c /apps/iap/iap-core.h | |
parent | 500b137308a6ee5c2aba873734a8956d70472f56 (diff) | |
download | rockbox-b170c73f922e3457b923b4e7fcbec794a8885c77.tar.gz rockbox-b170c73f922e3457b923b4e7fcbec794a8885c77.zip |
Updated IAP commands.
Originally written and uploaded by Lalufu (Ralf Ertzinger) in Feb 2012.
They have been condensed into a single patch and some further additions
by Andy Potter.
Currently includes Authentication V2 support from iPod to Accessory,
RF/BlueTooth transmitter support, selecting a playlist and selecting a
track from the current playlist. Does not support uploading Album Art
or podcasts. Has been tested on the following iPods,
4th Gen Grayscale, 4th Gen Color/Photo, Mini 2nd Gen, Nano 1st Gen and
Video 5.5Gen.
Change-Id: Ie8fc098361844132f0228ecbe3c48da948726f5e
Co-Authored by: Andy Potter <liveboxandy@gmail.com>
Reviewed-on: http://gerrit.rockbox.org/533
Reviewed-by: Frank Gevaerts <frank@gevaerts.be>
Diffstat (limited to 'apps/iap/iap-core.h')
-rw-r--r-- | apps/iap/iap-core.h | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/apps/iap/iap-core.h b/apps/iap/iap-core.h new file mode 100644 index 0000000000..d06e3c300c --- /dev/null +++ b/apps/iap/iap-core.h | |||
@@ -0,0 +1,250 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
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 | #ifndef _IAP_CORE_H | ||
20 | #define _IAP_CORE_H | ||
21 | |||
22 | #include <stdint.h> | ||
23 | #include <string.h> | ||
24 | #include "timefuncs.h" | ||
25 | #include "metadata.h" | ||
26 | #include "playlist.h" | ||
27 | #include "iap.h" | ||
28 | |||
29 | #define LOGF_ENABLE | ||
30 | /* #undef LOGF_ENABLE */ | ||
31 | #ifdef LOGF_ENABLE | ||
32 | #include "logf.h" | ||
33 | #endif | ||
34 | |||
35 | /* The Model ID of the iPod we emulate. Currently a 160GB classic */ | ||
36 | #define IAP_IPOD_MODEL (0x00130200U) | ||
37 | |||
38 | /* The firmware version we emulate. Currently 2.0.3 */ | ||
39 | #define IAP_IPOD_FIRMWARE_MAJOR (2) | ||
40 | #define IAP_IPOD_FIRMWARE_MINOR (0) | ||
41 | #define IAP_IPOD_FIRMWARE_REV (3) | ||
42 | |||
43 | /* Status code for IAP ack messages */ | ||
44 | #define IAP_ACK_OK (0x00) /* Success */ | ||
45 | #define IAP_ACK_UNKNOWN_DB (0x01) /* Unknown Database Category */ | ||
46 | #define IAP_ACK_CMD_FAILED (0x02) /* Command failed */ | ||
47 | #define IAP_ACK_NO_RESOURCE (0x03) /* Out of resources */ | ||
48 | #define IAP_ACK_BAD_PARAM (0x04) /* Bad parameter */ | ||
49 | #define IAP_ACK_UNKNOWN_ID (0x05) /* Unknown ID */ | ||
50 | #define IAP_ACK_PENDING (0x06) /* Command pending */ | ||
51 | #define IAP_ACK_NO_AUTHEN (0x07) /* Not authenticated */ | ||
52 | #define IAP_ACK_BAD_AUTHEN (0x08) /* Bad authentication version */ | ||
53 | /* 0x09 reserved */ | ||
54 | #define IAP_ACK_CERT_INVAL (0x0A) /* Certificate invalid */ | ||
55 | #define IAP_ACK_CERT_PERM (0x0B) /* Certificate permissions invalid */ | ||
56 | /* 0x0C-0x10 reserved */ | ||
57 | #define IAP_ACK_RES_INVAL (0x11) /* Invalid accessory resistor value */ | ||
58 | |||
59 | /* Add a button to the remote button bitfield. Also set iap_repeatbtn=1 | ||
60 | * to ensure a button press is at least delivered once. | ||
61 | */ | ||
62 | #define REMOTE_BUTTON(x) do { \ | ||
63 | iap_remotebtn |= (x); \ | ||
64 | iap_timeoutbtn = 3; \ | ||
65 | iap_repeatbtn = 2; \ | ||
66 | } while(0) | ||
67 | |||
68 | /* States of the extended command support */ | ||
69 | enum interface_state { | ||
70 | IST_STANDARD, /* General state, support lingo 0x00 commands */ | ||
71 | IST_EXTENDED, /* Extended Interface lingo (0x04) negotiated */ | ||
72 | }; | ||
73 | |||
74 | /* States of the authentication state machine */ | ||
75 | enum authen_state { | ||
76 | AUST_NONE, /* Initial state, no message sent */ | ||
77 | AUST_INIT, /* Remote side has requested authentication */ | ||
78 | AUST_CERTREQ, /* Remote certificate requested */ | ||
79 | AUST_CERTBEG, /* Certificate is being received */ | ||
80 | AUST_CERTDONE, /* Certificate received */ | ||
81 | AUST_CHASENT, /* Challenge sent */ | ||
82 | AUST_CHADONE, /* Challenge response received */ | ||
83 | AUST_AUTH, /* Authentication complete */ | ||
84 | }; | ||
85 | |||
86 | /* State of authentication */ | ||
87 | struct auth_t { | ||
88 | enum authen_state state; /* Current state of authentication */ | ||
89 | unsigned char max_section; /* The maximum number of certificate sections */ | ||
90 | unsigned char next_section; /* The next expected section number */ | ||
91 | }; | ||
92 | |||
93 | /* State of GetAccessoryInfo */ | ||
94 | enum accinfo_state { | ||
95 | ACCST_NONE, /* Initial state, no message sent */ | ||
96 | ACCST_INIT, /* Send out initial GetAccessoryInfo */ | ||
97 | ACCST_SENT, /* Wait for initial RetAccessoryInfo */ | ||
98 | ACCST_DATA, /* Query device information, according to capabilities */ | ||
99 | }; | ||
100 | |||
101 | /* A struct describing an attached device and it's current | ||
102 | * state | ||
103 | */ | ||
104 | struct device_t { | ||
105 | struct auth_t auth; /* Authentication state */ | ||
106 | enum accinfo_state accinfo; /* Accessory information state */ | ||
107 | uint32_t lingoes; /* Negotiated lingoes */ | ||
108 | uint32_t notifications; /* Requested notifications. These are just the | ||
109 | * notifications explicitly requested by the | ||
110 | * device | ||
111 | */ | ||
112 | uint32_t changed_notifications; /* Tracks notifications that changed since the last | ||
113 | * call to SetRemoteEventNotification or GetRemoteEventStatus | ||
114 | */ | ||
115 | bool do_notify; /* Notifications enabled */ | ||
116 | bool do_power_notify; /* Whether to send power change notifications. | ||
117 | * These are sent automatically to all devices | ||
118 | * that used IdentifyDeviceLingoes to identify | ||
119 | * themselves, independent of other notifications | ||
120 | */ | ||
121 | |||
122 | uint32_t trackpos_ms; /* These fields are to save the current state */ | ||
123 | uint32_t track_index; /* of various fields so we can send a notification */ | ||
124 | uint32_t chapter_index; /* if they change */ | ||
125 | unsigned char play_status; | ||
126 | bool mute; | ||
127 | unsigned char volume; | ||
128 | unsigned char power_state; | ||
129 | unsigned char battery_level; | ||
130 | uint32_t equalizer_index; | ||
131 | unsigned char shuffle; | ||
132 | unsigned char repeat; | ||
133 | struct tm datetime; | ||
134 | unsigned char alarm_state; | ||
135 | unsigned char alarm_hour; | ||
136 | unsigned char alarm_minute; | ||
137 | unsigned char backlight; | ||
138 | bool hold; | ||
139 | unsigned char soundcheck; | ||
140 | unsigned char audiobook; | ||
141 | uint16_t trackpos_s; | ||
142 | uint32_t capabilities; /* Capabilities of the device, as returned by type 0 | ||
143 | * of GetAccessoryInfo | ||
144 | */ | ||
145 | uint32_t capabilities_queried; /* Capabilities already queried */ | ||
146 | }; | ||
147 | |||
148 | extern struct device_t device; | ||
149 | #define DEVICE_AUTHENTICATED (device.auth.state == AUST_AUTH) | ||
150 | #define DEVICE_AUTH_RUNNING ((device.auth.state != AUST_NONE) && (device.auth.state != AUST_AUTH)) | ||
151 | #define DEVICE_LINGO_SUPPORTED(x) (device.lingoes & BIT_N((x)&0x1f)) | ||
152 | |||
153 | extern unsigned long iap_remotebtn; | ||
154 | extern unsigned int iap_timeoutbtn; | ||
155 | extern int iap_repeatbtn; | ||
156 | |||
157 | extern unsigned char* iap_txpayload; | ||
158 | extern unsigned char* iap_txnext; | ||
159 | |||
160 | /* These are a number of helper macros to manage the dynamic TX buffer content | ||
161 | * These macros DO NOT CHECK for buffer overflow. iap_send_tx() will, but | ||
162 | * it might be too late at that point. See the current size of TX_BUFLEN | ||
163 | */ | ||
164 | |||
165 | /* Initialize the TX buffer with a lingo and command ID. This will reset the | ||
166 | * data pointer, effectively invalidating unsent information in the TX buffer. | ||
167 | * There are two versions of this, one for 1 byte command IDs (all Lingoes except | ||
168 | * 0x04) and one for two byte command IDs (Lingo 0x04) | ||
169 | */ | ||
170 | #define IAP_TX_INIT(lingo, command) do { \ | ||
171 | iap_txnext = iap_txpayload; \ | ||
172 | IAP_TX_PUT((lingo)); \ | ||
173 | IAP_TX_PUT((command)); \ | ||
174 | } while (0) | ||
175 | |||
176 | #define IAP_TX_INIT4(lingo, command) do { \ | ||
177 | iap_txnext = iap_txpayload; \ | ||
178 | IAP_TX_PUT((lingo)); \ | ||
179 | IAP_TX_PUT_U16((command)); \ | ||
180 | } while (0) | ||
181 | |||
182 | /* Put an unsigned char into the TX buffer */ | ||
183 | #define IAP_TX_PUT(data) *(iap_txnext++) = (data) | ||
184 | |||
185 | /* Put a 16bit unsigned quantity into the TX buffer */ | ||
186 | #define IAP_TX_PUT_U16(data) do { \ | ||
187 | put_u16(iap_txnext, (data)); \ | ||
188 | iap_txnext += 2; \ | ||
189 | } while (0) | ||
190 | |||
191 | /* Put a 32bit unsigned quantity into the TX buffer */ | ||
192 | #define IAP_TX_PUT_U32(data) do { \ | ||
193 | put_u32(iap_txnext, (data)); \ | ||
194 | iap_txnext += 4; \ | ||
195 | } while (0) | ||
196 | |||
197 | /* Put an arbitrary amount of data (identified by a char pointer and | ||
198 | * a length) into the TX buffer | ||
199 | */ | ||
200 | #define IAP_TX_PUT_DATA(data, len) do { \ | ||
201 | memcpy(iap_txnext, (unsigned char *)(data), (len)); \ | ||
202 | iap_txnext += (len); \ | ||
203 | } while(0) | ||
204 | |||
205 | /* Put a NULL terminated string into the TX buffer, including the | ||
206 | * NULL byte | ||
207 | */ | ||
208 | #define IAP_TX_PUT_STRING(str) IAP_TX_PUT_DATA((str), strlen((str))+1) | ||
209 | |||
210 | /* Put a NULL terminated string into the TX buffer, taking care not to | ||
211 | * overflow the buffer. If the string does not fit into the TX buffer | ||
212 | * it will be truncated, but always NULL terminated. | ||
213 | * | ||
214 | * This function is expensive compared to the other IAP_TX_PUT_* | ||
215 | * functions | ||
216 | */ | ||
217 | #define IAP_TX_PUT_STRLCPY(str) iap_tx_strlcpy(str) | ||
218 | |||
219 | extern unsigned char lingo_versions[32][2]; | ||
220 | #define LINGO_SUPPORTED(x) (LINGO_MAJOR((x)&0x1f) > 0) | ||
221 | #define LINGO_MAJOR(x) (lingo_versions[(x)&0x1f][0]) | ||
222 | #define LINGO_MINOR(x) (lingo_versions[(x)&0x1f][1]) | ||
223 | |||
224 | void put_u16(unsigned char *buf, const uint16_t data); | ||
225 | void put_u32(unsigned char *buf, const uint32_t data); | ||
226 | uint32_t get_u32(const unsigned char *buf); | ||
227 | uint16_t get_u16(const unsigned char *buf); | ||
228 | void iap_tx_strlcpy(const unsigned char *str); | ||
229 | |||
230 | void iap_reset_auth(struct auth_t* auth); | ||
231 | void iap_reset_device(struct device_t* device); | ||
232 | |||
233 | void iap_shuffle_state(bool state); | ||
234 | void iap_repeat_state(unsigned char state); | ||
235 | void iap_repeat_next(void); | ||
236 | void iap_fill_power_state(void); | ||
237 | |||
238 | void iap_send_tx(void); | ||
239 | |||
240 | extern enum interface_state interface_state; | ||
241 | void iap_interface_state_change(const enum interface_state new); | ||
242 | |||
243 | extern bool iap_btnrepeat; | ||
244 | extern bool iap_btnshuffle; | ||
245 | |||
246 | uint32_t iap_get_trackpos(void); | ||
247 | uint32_t iap_get_trackindex(void); | ||
248 | void iap_get_trackinfo(const unsigned int track, struct mp3entry* id3); | ||
249 | |||
250 | #endif | ||