- changed PKG_CONFIG_PATH setting in rpm script, so that systems
[barry.git] / src / protostructs.h
blob664d80a6bfc4564b42c3a854482fddca626463be
1 ///
2 /// \file protostructs.h
3 /// USB Blackberry bulk protocol API. This is split out from
4 /// protocol.h so that low level, packed structs can be
5 /// compiled separately from the application. This prevents
6 /// aliasing problems in the application, or using
7 /// -fno-strict-aliasing, which the library only needs.
8 ///
9 /// Do not include this in any Barry library header.
10 /// This may only be included from .cc files, in order
11 /// to hide aliasing concernes from the application.
12 ///
15 Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/)
17 This program is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 2 of the License, or
20 (at your option) any later version.
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26 See the GNU General Public License in the COPYING file at the
27 root directory of this project for more details.
30 #ifndef __BARRY_PROTOSTRUCTS_H__
31 #define __BARRY_PROTOSTRUCTS_H__
33 #include <stdint.h>
34 #include <sys/types.h>
36 // forward declarations
37 namespace Barry { class Data; }
39 namespace Barry { namespace Protocol {
41 ///////////////////////////////////////////////////////////////////////////////
42 union SizePacket
44 uint16_t size;
45 char buffer[4];
46 } __attribute__ ((packed));
49 ///////////////////////////////////////////////////////////////////////////////
50 // Record sub-field structs
52 struct GroupLink // used for Contacts records
54 uint32_t uniqueId;
55 uint16_t unknown;
56 } __attribute__ ((packed));
58 struct MessageAddress // used for Message records
60 uint8_t unknown[8];
61 uint8_t addr[1]; // 2 null terminated strings: first
62 // contains full name, second contains
63 // the email address
64 } __attribute__ ((packed));
68 ///////////////////////////////////////////////////////////////////////////////
69 // Record Field Formats
71 struct CommonField
73 uint16_t size; // including null terminator
74 uint8_t type;
76 union CommonFieldData
79 GroupLink link;
80 MessageAddress addr;
81 uint32_t uint32;
82 int32_t min1900;
83 uint16_t code;
84 uint8_t raw[1];
86 } __attribute__ ((packed)) u;
88 } __attribute__ ((packed));
89 #define COMMON_FIELD_HEADER_SIZE (sizeof(Barry::Protocol::CommonField) - sizeof(Barry::Protocol::CommonField::CommonFieldData))
90 #define COMMON_FIELD_MIN1900_SIZE (sizeof(int32_t))
92 struct CommandTableField
94 uint8_t size; // no null terminator
95 uint8_t code;
96 uint8_t name[1];
97 } __attribute__ ((packed));
98 #define COMMAND_FIELD_HEADER_SIZE (sizeof(Barry::Protocol::CommandTableField) - 1)
100 struct OldDBDBField
102 uint16_t dbNumber;
103 uint8_t unknown1;
104 uint32_t dbSize; // assumed from Cassis docs...
105 // always 0 in USB
106 uint16_t dbRecordCount;
107 uint16_t unknown2;
108 uint16_t nameSize; // includes null terminator
109 uint8_t name[1];
110 } __attribute__ ((packed));
111 #define OLD_DBDB_FIELD_HEADER_SIZE (sizeof(Barry::Protocol::OldDBDBField) - 1)
113 struct DBDBField
115 uint16_t dbNumber;
116 uint8_t unknown1;
117 uint32_t dbSize; // assumed from Cassis docs...
118 // always 0 in USB
119 uint32_t dbRecordCount;
120 uint16_t unknown2;
121 uint16_t nameSize; // includes null terminator
122 uint8_t unknown3;
123 uint8_t name[1]; // followed by 2 zeros!
124 uint16_t unknown; // this comes after the
125 // null terminated name, but
126 // is here for size calcs
127 } __attribute__ ((packed));
128 #define DBDB_FIELD_HEADER_SIZE (sizeof(Barry::Protocol::DBDBField) - 1)
130 struct RecordStateTableField
132 uint8_t rectype; // it is unknown exactly what
133 // this field does, but it
134 // shows up here and in the
135 // tagged record header, and
136 // for some of the records
137 // they must match when writing
138 uint16_t index;
139 uint32_t uniqueId; // matches the uniqueId of say,
140 // address book records
141 uint8_t flags; // bit 0x01 is the dirty flag
142 // don't know if any other bits
143 // are used
144 #define BARRY_RSTF_DIRTY 0x01
145 uint8_t unknown2[4];
146 } __attribute__ ((packed));
148 struct CalendarRecurrenceDataField // as documented in the Cassis project spec
150 uint8_t type;
151 #define CRDF_TYPE_DAY 0x01
152 #define CRDF_TYPE_MONTH_BY_DATE 0x03
153 #define CRDF_TYPE_MONTH_BY_DAY 0x04
154 #define CRDF_TYPE_YEAR_BY_DATE 0x05
155 #define CRDF_TYPE_YEAR_BY_DAY 0x06
156 #define CRDF_TYPE_WEEK 0x0c
158 uint8_t unknown; // always 0x01
159 uint16_t interval;
160 uint32_t startTime;
161 uint32_t endTime; // 0xFFFFFFFF for never
163 union Additional
165 // Note: blank fields should be set to 0
167 struct Day
169 uint8_t day[6]; // always zeros!
170 } __attribute__ ((packed)) day;
172 struct MonthByDate
174 uint8_t monthDay; // day of month to recur on
175 // (1-31)
176 uint8_t blank[5];
177 } __attribute__ ((packed)) month_by_date;
179 struct MonthByDay
181 uint8_t weekDay; // day of week to recur on (0-6)
182 uint8_t week; // week of month to recur on
183 // (1 to 5, first week, second
184 // week, etc)
185 uint8_t blank[4];
186 } __attribute__ ((packed)) month_by_day;
188 struct YearByDate
190 uint8_t monthDay; // day of month to recur on
191 // (1-31)
192 uint8_t blank;
193 uint8_t month; // month to recur on (1-12)
194 uint8_t blank_[3];
195 } __attribute__ ((packed)) year_by_date;
197 struct YearByDay
199 uint8_t weekDay; // day of week to recur on (0-6)
200 uint8_t week; // week of month (1 to 5)
201 uint8_t month; // (1-12)
202 uint8_t blank[3];
203 } __attribute__ ((packed)) year_by_day;
205 struct Week
207 uint8_t days; // bitmask
208 #define CRDF_WD_SUN 0x01
209 #define CRDF_WD_MON 0x02
210 #define CRDF_WD_TUE 0x04
211 #define CRDF_WD_WED 0x08
212 #define CRDF_WD_THU 0x10
213 #define CRDF_WD_FRI 0x20
214 #define CRDF_WD_SAT 0x40
216 uint8_t blank[5];
217 } __attribute__ ((packed)) week;
219 } __attribute__ ((packed)) u;
221 } __attribute__ ((packed));
222 #define CALENDAR_RECURRENCE_DATA_FIELD_SIZE sizeof(Barry::Protocol::CalendarRecurrenceDataField)
226 ///////////////////////////////////////////////////////////////////////////////
227 // Packed field structures - odd format used with Service Book records
229 struct PackedField_02
231 uint8_t code;
232 uint8_t size;
233 uint8_t type;
234 uint8_t raw[1];
235 } __attribute__ ((packed));
236 #define PACKED_FIELD_02_HEADER_SIZE (sizeof(Barry::Protocol::PackedField_02) - 1)
238 struct PackedField_10
240 uint8_t type;
241 uint8_t size;
242 uint8_t raw[1];
243 } __attribute__ ((packed));
244 #define PACKED_FIELD_10_HEADER_SIZE (sizeof(Barry::Protocol::PackedField_10) - 1)
249 ///////////////////////////////////////////////////////////////////////////////
250 // Service Book field and record structures
252 struct ServiceBookConfigField
254 uint8_t format;
255 uint8_t fields[1];
256 } __attribute__ ((packed));
257 #define SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE (sizeof(Barry::Protocol::ServiceBookConfigField) - 1)
260 ///////////////////////////////////////////////////////////////////////////////
261 // DB Command Parameter structures
263 struct DBC_Record
265 uint16_t recordIndex; // index comes from RecordStateTable
266 uint8_t data[1];
267 } __attribute__ ((packed));
268 #define DBC_RECORD_HEADER_SIZE (sizeof(Barry::Protocol::DBC_Record) - 1)
270 struct DBC_RecordFlags
272 uint8_t unknown;
273 uint16_t index;
274 uint8_t unknown2[5];
275 } __attribute__ ((packed));
276 #define DBC_RECORD_FLAGS_SIZE (sizeof(Barry::Protocol::DBC_RecordFlags))
278 struct DBC_TaggedUpload
280 uint8_t rectype; // it is unknown exactly what
281 // this field does, but it
282 // shows up here and in the
283 // RecordStateTable, and
284 // for some of the records
285 // they must match when writing
286 uint32_t uniqueId;
287 uint8_t unknown2;
288 uint8_t data[1];
289 } __attribute__ ((packed));
290 #define DBC_TAGGED_UPLOAD_HEADER_SIZE (sizeof(Barry::Protocol::DBC_TaggedUpload) - 1)
292 struct DBC_IndexedUpload
294 uint8_t unknown; // observed: 00 or 05
295 uint16_t index;
296 uint8_t data[1];
297 } __attribute__ ((packed));
298 #define DBC_INDEXED_UPLOAD_HEADER_SIZE (sizeof(Barry::Protocol::DBC_IndexedUpload) - 1)
300 struct PasswordChallenge
302 uint8_t remaining_tries; // number of password attempts
303 // the device will accept before
304 // committing suicide...
305 // starts at 10 and counts down
306 // on each bad password
307 uint8_t unknown; // observed as 0... probably just
308 // the top byte of a uint16
309 // remaining_tries, but I don't
310 // want to take that chance
311 uint16_t param; // seems to be a secondary command
312 // of some kind, observed as 0x14
313 // or 0x04, but purpose unknown
314 // possibly a send/receive flag
315 // bit (0x10/0x00)
316 union Hash
318 uint32_t seed;
319 uint8_t hash[20];
320 } __attribute__ ((packed)) u;
322 } __attribute__ ((packed));
323 #define PASSWORD_CHALLENGE_HEADER_SIZE (sizeof(Barry::Protocol::PasswordChallenge) - sizeof(Barry::Protocol::PasswordChallenge::Hash))
324 #define PASSWORD_CHALLENGE_SEED_SIZE (PASSWORD_CHALLENGE_HEADER_SIZE + sizeof(uint32_t))
325 #define PASSWORD_CHALLENGE_SIZE (sizeof(Barry::Protocol::PasswordChallenge))
327 struct AttributeFetch
329 uint16_t object;
330 uint16_t attribute;
331 uint8_t raw[1]; // used only in response
332 } __attribute__ ((packed));
333 #define ATTRIBUTE_FETCH_COMMAND_SIZE (sizeof(Barry::Protocol::AttributeFetch) - 1)
335 struct ModeSelect
337 uint8_t name[16];
338 struct ResponseBlock
340 uint8_t unknown[20];
341 } __attribute__ ((packed)) response;
342 } __attribute__ ((packed));
345 ///////////////////////////////////////////////////////////////////////////////
346 // Protocol command structures
348 struct SocketCommand
350 uint16_t socket;
351 uint8_t sequence; // incremented on each socket 0
352 // communication, replies return
353 // the same number from command
355 union PacketData
358 PasswordChallenge password;
359 AttributeFetch fetch;
360 ModeSelect mode;
361 uint8_t raw[1];
363 } __attribute__ ((packed)) u;
364 } __attribute__ ((packed));
365 #define SOCKET_COMMAND_HEADER_SIZE (sizeof(Barry::Protocol::SocketCommand) - sizeof(Barry::Protocol::SocketCommand::PacketData))
367 struct SequenceCommand
369 uint8_t unknown1;
370 uint8_t unknown2;
371 uint8_t unknown3;
372 uint32_t sequenceId;
373 } __attribute__ ((packed));
375 struct DBCommand
377 uint8_t operation; // see below
378 uint16_t databaseId; // value from the Database Database
380 union Parameters
383 DBC_Record record;
384 DBC_RecordFlags flags;
385 DBC_TaggedUpload tag_upload;
386 DBC_IndexedUpload index_upload;
387 uint8_t raw[1];
389 } __attribute__ ((packed)) u;
390 } __attribute__ ((packed));
391 #define DB_COMMAND_HEADER_SIZE (sizeof(Barry::Protocol::DBCommand) - sizeof(Barry::Protocol::DBCommand::Parameters))
395 ///////////////////////////////////////////////////////////////////////////////
396 // Protocol response parameter structures
398 struct DBR_OldDBDBRecord
400 uint16_t count; // number of fields in record
401 OldDBDBField field[1];
402 } __attribute__ ((packed));
403 #define OLD_DBDB_RECORD_HEADER_SIZE (sizeof(Barry::Protocol::DBR_OldDBDBRecord) - sizeof(Barry::Protocol::OldDBDBField))
405 struct DBR_DBDBRecord
407 uint16_t count;
408 uint8_t unknown[3];
409 DBDBField field[1];
410 } __attribute__ ((packed));
411 #define DBDB_RECORD_HEADER_SIZE (sizeof(Barry::Protocol::DBR_DBDBRecord) - sizeof(Barry::Protocol::DBDBField))
413 // Records with a uniqueId. This covers the following records:
415 // Old Contact records
416 // Old Service Book records
417 // Old Calendar records
419 struct DBR_OldTaggedRecord
421 uint8_t rectype;
422 uint16_t index;
423 uint32_t uniqueId;
424 uint8_t unknown2;
426 union TaggedData
428 CommonField field[1];
429 } __attribute__ ((packed)) u;
430 } __attribute__ ((packed));
431 #define DBR_OLD_TAGGED_RECORD_HEADER_SIZE (sizeof(Barry::Protocol::DBR_OldTaggedRecord) - sizeof(Barry::Protocol::DBR_OldTaggedRecord::TaggedData))
433 struct MessageRecord
435 uint8_t timeBlock[0x74];
436 CommonField field[1];
437 } __attribute__ ((packed));
438 #define MESSAGE_RECORD_HEADER_SIZE (sizeof(Barry::Protocol::MessageRecord) - sizeof(Barry::Protocol::CommonField))
442 ///////////////////////////////////////////////////////////////////////////////
443 // Protocol response structures
445 struct DBResponse
447 uint8_t operation;
449 union Parameters
452 DBR_OldTaggedRecord tagged;
453 DBR_OldDBDBRecord old_dbdb;
454 DBR_DBDBRecord dbdb;
456 } __attribute__ ((packed)) u;
458 } __attribute__ ((packed));
459 #define DB_RESPONSE_HEADER_SIZE (sizeof(Barry::Protocol::DBResponse) - sizeof(Barry::Protocol::DBResponse::Parameters))
463 ///////////////////////////////////////////////////////////////////////////////
464 // Database access command structure
466 // even fragmented packets have a tableCmd
467 struct DBAccess
469 uint8_t tableCmd;
471 union DBData
473 DBCommand command;
474 DBResponse response;
475 CommandTableField table[1];
476 uint8_t return_code;
477 uint8_t fragment[1];
479 } __attribute__ ((packed)) u;
480 } __attribute__ ((packed));
481 #define SB_DBACCESS_HEADER_SIZE (sizeof(Barry::Protocol::DBAccess) - sizeof(Barry::Protocol::DBAccess::DBData))
482 #define SB_DBACCESS_RETURN_CODE_SIZE (1)
486 ///////////////////////////////////////////////////////////////////////////////
487 // Main packet struct
489 struct Packet
491 uint16_t socket; // socket ID... 0 exists by default
492 uint16_t size; // total size of data packet
493 uint8_t command;
495 union PacketData
498 SocketCommand socket;
499 SequenceCommand sequence;
500 DBAccess db;
501 uint8_t raw[1];
503 } __attribute__ ((packed)) u;
504 } __attribute__ ((packed));
505 #define SB_PACKET_HEADER_SIZE (sizeof(Barry::Protocol::Packet) - sizeof(Barry::Protocol::Packet::PacketData))
507 // minimum required sizes for various responses
508 #define MIN_PACKET_SIZE 6
511 // maximum sizes
512 #define MAX_PACKET_SIZE 0x400 // anything beyond this needs to be
513 // fragmented
515 /////////////////////////////////////////////////////////////////////////////
517 // various useful sizes
520 #define SB_PACKET_DBACCESS_HEADER_SIZE (SB_PACKET_HEADER_SIZE + SB_DBACCESS_HEADER_SIZE)
521 #define SB_FRAG_HEADER_SIZE SB_PACKET_DBACCESS_HEADER_SIZE
523 #define SB_PACKET_COMMAND_HEADER_SIZE (SB_PACKET_DBACCESS_HEADER_SIZE + DB_COMMAND_HEADER_SIZE)
524 #define SB_PACKET_RESPONSE_HEADER_SIZE (SB_PACKET_DBACCESS_HEADER_SIZE + DB_RESPONSE_HEADER_SIZE)
526 #define SB_PACKET_DBDB_HEADER_SIZE (SB_PACKET_RESPONSE_HEADER_SIZE + DBDB_RECORD_HEADER_SIZE)
527 #define SB_PACKET_OLD_DBDB_HEADER_SIZE (SB_PACKET_RESPONSE_HEADER_SIZE + OLD_DBDB_RECORD_HEADER_SIZE)
529 #define SB_PACKET_UPLOAD_HEADER_SIZE (SB_PACKET_DBACCESS_HEADER_SIZE + UPLOAD_HEADER_SIZE)
531 #define SB_SEQUENCE_PACKET_SIZE (SB_PACKET_HEADER_SIZE + sizeof(Barry::Protocol::SequenceCommand))
532 #define SB_SOCKET_PACKET_HEADER_SIZE (SB_PACKET_HEADER_SIZE + SOCKET_COMMAND_HEADER_SIZE)
533 #define SB_MODE_PACKET_COMMAND_SIZE (SB_SOCKET_PACKET_HEADER_SIZE + sizeof(Barry::Protocol::ModeSelect) - sizeof(Barry::Protocol::ModeSelect::ResponseBlock))
534 #define SB_MODE_PACKET_RESPONSE_SIZE (SB_SOCKET_PACKET_HEADER_SIZE + sizeof(Barry::Protocol::ModeSelect))
537 // Macros
538 #define COMMAND(data) (((const Barry::Protocol::Packet *)data.GetData())->command)
539 #define IS_COMMAND(data, cmd) (COMMAND(data) == cmd)
540 #define MAKE_PACKET(var, data) const Barry::Protocol::Packet *var = (const Barry::Protocol::Packet *) data.GetData()
541 #define MAKE_PACKETPTR_BUF(var, ptr) Barry::Protocol::Packet *var = (Barry::Protocol::Packet *)ptr
542 #define MAKE_RECORD(type,var,data,off) type *var = (type *) (data.GetData() + (off))
543 #define MAKE_RECORD_PTR(type,var,data,off) type *var = (type *) (data + (off))
545 // fragmentation protocol
546 // send DATA first, then keep sending DATA packets, FRAGMENTing
547 // as required until finished, then send DONE. Both sides behave
548 // this way, so different sized data can be sent in both
549 // directions
551 // the fragmented piece only has a the param header, and then continues
552 // right on with the data
556 // checks packet size and throws BError if not right
557 void CheckSize(const Barry::Data &packet, size_t requiredsize = MIN_PACKET_SIZE);
558 unsigned int GetSize(const Barry::Data &packet);
560 }} // namespace Barry::Protocol
562 #endif