00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "m_desktop.h"
00023 #include "data.h"
00024 #include "protocol.h"
00025 #include "protostructs.h"
00026 #include "packet.h"
00027 #include "endian.h"
00028 #include "error.h"
00029 #include "usbwrap.h"
00030 #include "controller.h"
00031 #include <stdexcept>
00032 #include <sstream>
00033
00034 #include "debug.h"
00035
00036 namespace Barry { namespace Mode {
00037
00038
00039
00040
00041
00042 Desktop::Desktop(Controller &con)
00043 : m_con(con)
00044 , m_ModeSocket(0)
00045 {
00046 }
00047
00048 Desktop::~Desktop()
00049 {
00050 }
00051
00052
00053
00054
00055 void Desktop::LoadCommandTable()
00056 {
00057 char rawCommand[] = { 6, 0, 0x0a, 0, 0x40, 0, 0, 1, 0, 0 };
00058 *((uint16_t*) rawCommand) = htobs(m_socket->GetSocket());
00059
00060 Data command(rawCommand, sizeof(rawCommand));
00061 Data response;
00062
00063 try {
00064 m_socket->Packet(command, response);
00065
00066 MAKE_PACKET(rpack, response);
00067 while( rpack->command != SB_COMMAND_DB_DONE ) {
00068 m_socket->NextRecord(response);
00069
00070 rpack = (const Protocol::Packet *) response.GetData();
00071 if( rpack->command == SB_COMMAND_DB_DATA && btohs(rpack->size) > 10 ) {
00072
00073
00074 m_commandTable.Clear();
00075 m_commandTable.Parse(response, 6);
00076 }
00077 }
00078
00079 ddout(m_commandTable);
00080
00081 }
00082 catch( Usb::Error & ) {
00083 eout("Desktop: error getting command table");
00084 eeout(command, response);
00085 throw;
00086 }
00087 }
00088
00089 void Desktop::LoadDBDB()
00090 {
00091 Data command, response;
00092 DBPacket packet(*this, command, response);
00093 packet.GetDBDB();
00094
00095 m_socket->Packet(packet);
00096
00097 while( packet.Command() != SB_COMMAND_DB_DONE ) {
00098 if( packet.Command() == SB_COMMAND_DB_DATA ) {
00099 m_dbdb.Clear();
00100 m_dbdb.Parse(response);
00101 }
00102
00103
00104 m_socket->NextRecord(response);
00105 }
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 void Desktop::Open(const char *password)
00141 {
00142 if( m_ModeSocket ) {
00143 m_socket->Close();
00144 m_socket.reset();
00145 m_ModeSocket = 0;
00146 }
00147
00148 m_ModeSocket = m_con.SelectMode(Controller::Desktop);
00149 RetryPassword(password);
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 void Desktop::RetryPassword(const char *password)
00170 {
00171 if( m_socket.get() != 0 )
00172 throw std::logic_error("Socket alreay open in RetryPassword");
00173
00174 m_socket = m_con.m_zero.Open(m_ModeSocket, password);
00175
00176
00177 LoadCommandTable();
00178 LoadDBDB();
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 unsigned int Desktop::GetDBID(const std::string &name) const
00193 {
00194 unsigned int ID = 0;
00195
00196 if( !m_dbdb.GetDBNumber(name, ID) ) {
00197 throw Error("Desktop: database name not found: " + name);
00198 }
00199 return ID;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 unsigned int Desktop::GetDBCommand(CommandType ct)
00209 {
00210 unsigned int cmd = 0;
00211 const char *cmdName = "Unknown";
00212
00213 switch( ct )
00214 {
00215 case DatabaseAccess:
00216 cmdName = "Database Access";
00217 cmd = m_commandTable.GetCommand(cmdName);
00218 break;
00219 default:
00220 throw std::logic_error("Desktop: unknown command type");
00221 }
00222
00223 if( cmd == 0 ) {
00224 std::ostringstream oss;
00225 oss << "Desktop: unable to get command code: " << cmdName;
00226 throw Error(oss.str());
00227 }
00228
00229 return cmd;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 void Desktop::GetRecordStateTable(unsigned int dbId, RecordStateTable &result)
00240 {
00241 dout("Database ID: " << dbId);
00242
00243
00244 result.Clear();
00245
00246 Data command, response;
00247 DBPacket packet(*this, command, response);
00248 packet.GetRecordStateTable(dbId);
00249
00250 m_socket->Packet(packet);
00251 result.Parse(response);
00252
00253
00254 while( packet.Command() != SB_COMMAND_DB_DONE )
00255 m_socket->NextRecord(response);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 void Desktop::AddRecord(unsigned int dbId, Builder &build)
00267 {
00268 dout("Database ID: " << dbId);
00269
00270 Data command, response;
00271 DBPacket packet(*this, command, response);
00272
00273 if( packet.SetRecord(dbId, build) ) {
00274
00275 std::ostringstream oss;
00276
00277 m_socket->Packet(packet);
00278
00279
00280 if( packet.Command() != SB_COMMAND_DB_DONE ) {
00281 oss << "Desktop: device responded with unexpected packet command code: "
00282 << "0x" << std::hex << packet.Command();
00283 throw Error(oss.str());
00284 }
00285
00286 if( packet.ReturnCode() != 0 ) {
00287 oss << "Desktop: device responded with error code (command: "
00288 << packet.Command() << ", code: "
00289 << packet.ReturnCode() << ")";
00290 throw Error(oss.str());
00291 }
00292 }
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302 void Desktop::GetRecord(unsigned int dbId,
00303 unsigned int stateTableIndex,
00304 Parser &parser)
00305 {
00306 dout("Database ID: " << dbId);
00307
00308 Data command, response;
00309 DBPacket packet(*this, command, response);
00310 packet.GetRecordByIndex(dbId, stateTableIndex);
00311
00312 m_socket->Packet(packet);
00313
00314
00315 if( response.GetSize() < SB_PACKET_RESPONSE_HEADER_SIZE ) {
00316 eeout(command, response);
00317
00318 std::ostringstream oss;
00319 oss << "Desktop: invalid response packet size of "
00320 << std::dec << response.GetSize();
00321 eout(oss.str());
00322 throw Error(oss.str());
00323 }
00324 if( packet.Command() != SB_COMMAND_DB_DATA ) {
00325 eeout(command, response);
00326
00327 std::ostringstream oss;
00328 oss << "Desktop: unexpected command of 0x"
00329 << std::setbase(16) << packet.Command()
00330 << " instead of expected 0x"
00331 << std::setbase(16) << (unsigned int)SB_COMMAND_DB_DATA;
00332 eout(oss.str());
00333 throw Error(oss.str());
00334 }
00335
00336
00337 packet.Parse(parser);
00338
00339
00340 while( packet.Command() != SB_COMMAND_DB_DONE )
00341 m_socket->NextRecord(response);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350 void Desktop::SetRecord(unsigned int dbId, unsigned int stateTableIndex,
00351 Builder &build)
00352 {
00353 dout("Database ID: " << dbId << " Index: " << stateTableIndex);
00354
00355 Data command, response;
00356 DBPacket packet(*this, command, response);
00357
00358
00359 if( !packet.SetRecordByIndex(dbId, stateTableIndex, build) ) {
00360 throw std::logic_error("Desktop: no data available in SetRecord");
00361 }
00362
00363 m_socket->Packet(packet);
00364
00365 std::ostringstream oss;
00366
00367
00368 if( packet.Command() != SB_COMMAND_DB_DONE ) {
00369 oss << "Desktop: device responded with unexpected packet command code: "
00370 << "0x" << std::hex << packet.Command();
00371 throw Error(oss.str());
00372 }
00373
00374 if( packet.ReturnCode() != 0 ) {
00375 oss << "Desktop: device responded with error code (command: "
00376 << packet.Command() << ", code: "
00377 << packet.ReturnCode() << ")";
00378 throw Error(oss.str());
00379 }
00380 }
00381
00382
00383
00384
00385
00386
00387 void Desktop::ClearDirty(unsigned int dbId, unsigned int stateTableIndex)
00388 {
00389 dout("Database ID: " << dbId);
00390
00391 Data command, response;
00392 DBPacket packet(*this, command, response);
00393 packet.SetRecordFlags(dbId, stateTableIndex, 0);
00394
00395 m_socket->Packet(packet);
00396
00397
00398 while( packet.Command() != SB_COMMAND_DB_DONE )
00399 m_socket->NextRecord(response);
00400 }
00401
00402
00403
00404
00405
00406
00407 void Desktop::DeleteRecord(unsigned int dbId, unsigned int stateTableIndex)
00408 {
00409 dout("Database ID: " << dbId);
00410
00411 Data command, response;
00412 DBPacket packet(*this, command, response);
00413 packet.DeleteRecordByIndex(dbId, stateTableIndex);
00414
00415 m_socket->Packet(packet);
00416
00417
00418 while( packet.Command() != SB_COMMAND_DB_DONE )
00419 m_socket->NextRecord(response);
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 void Desktop::LoadDatabase(unsigned int dbId, Parser &parser)
00446 {
00447 dout("Database ID: " << dbId);
00448
00449 Data command, response;
00450 DBPacket packet(*this, command, response);
00451 packet.GetRecords(dbId);
00452
00453 m_socket->Packet(packet);
00454
00455 while( packet.Command() != SB_COMMAND_DB_DONE ) {
00456 if( packet.Command() == SB_COMMAND_DB_DATA ) {
00457
00458
00459 packet.Parse(parser);
00460 }
00461
00462
00463 m_socket->NextRecord(response);
00464 }
00465 }
00466
00467 void Desktop::SaveDatabase(unsigned int dbId, Builder &builder)
00468 {
00469 dout("Database ID: " << dbId);
00470
00471
00472
00473
00474
00475
00476
00477
00478 Data command, response;
00479 DBPacket packet(*this, command, response);
00480 packet.ClearDatabase(dbId);
00481
00482
00483 m_socket->Packet(packet, 60000);
00484 if( packet.ReturnCode() != 0 ) {
00485 std::ostringstream oss;
00486 oss << "Desktop: could not clear database: (command: "
00487 << "0x" << std::hex << packet.Command() << ", code: "
00488 << "0x" << std::hex << packet.ReturnCode() << ")";
00489 throw Error(oss.str());
00490 }
00491
00492
00493 if( packet.Command() != SB_COMMAND_DB_DONE ) {
00494 eeout(command, response);
00495 throw Error("Desktop: error clearing database, bad response");
00496 }
00497
00498
00499 bool first = true;
00500 while( packet.SetRecord(dbId, builder) ) {
00501 dout("Database ID: " << dbId);
00502
00503 m_socket->Packet(packet, first ? 60000 : -1);
00504 first = false;
00505
00506 std::ostringstream oss;
00507
00508 if( packet.Command() != SB_COMMAND_DB_DONE ) {
00509 oss << "Desktop: device responded with unexpected packet command code: "
00510 << "0x" << std::hex << packet.Command();
00511 throw Error(oss.str());
00512 }
00513
00514 if( packet.ReturnCode() != 0 ) {
00515 oss << "Desktop: device responded with error code (command: "
00516 << packet.Command() << ", code: "
00517 << packet.ReturnCode() << ")";
00518 throw Error(oss.str());
00519 }
00520 }
00521 }
00522
00523 }}
00524