Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / periphery-lld / src / ut_alld_bq27500.c @ 8a93b752

History | View | Annotate | Download (25.856 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2019  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
#include <ut_alld_bq27500.h>
20

    
21
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_BQ27500)) || defined(__DOXYGEN__)
22

    
23
#include <string.h>
24

    
25
/******************************************************************************/
26
/* LOCAL DEFINITIONS                                                          */
27
/******************************************************************************/
28

    
29
// change saved unseal keys to test bruteforcing
30
#ifdef BQ27500_UT_TEST_BRUTEFORCE
31

    
32
#ifdef BQ27500_LLD_DEFAULT_UNSEAL_KEY0
33
#undef BQ27500_LLD_DEFAULT_UNSEAL_KEY0
34
#define BQ27500_LLD_DEFAULT_UNSEAL_KEY0 0x1234
35
#endif
36

    
37
#ifdef BQ27500_LLD_DEFAULT_UNSEAL_KEY1
38
#undef BQ27500_LLD_DEFAULT_UNSEAL_KEY1
39
#define BQ27500_LLD_DEFAULT_UNSEAL_KEY1 0x5678
40
#endif
41

    
42
#endif
43

    
44
/******************************************************************************/
45
/* EXPORTED VARIABLES                                                         */
46
/******************************************************************************/
47

    
48
/******************************************************************************/
49
/* LOCAL TYPES                                                                */
50
/******************************************************************************/
51

    
52
/******************************************************************************/
53
/* LOCAL VARIABLES                                                            */
54
/******************************************************************************/
55

    
56
/******************************************************************************/
57
/* LOCAL FUNCTIONS                                                            */
58
/******************************************************************************/
59

    
60
bq27500_lld_control_status_t _try_unseal(BQ27500Driver* driver, uint16_t key0, uint16_t key1, apalTime_t timeout) {
61
  uint16_t dst;
62
  bq27500_lld_control_status_t ctrl;
63
  bq27500_lld_send_ctnl_data(driver, key1, timeout);
64
  aosThdUSleep(1);
65
  bq27500_lld_send_ctnl_data(driver, key0, timeout);
66
  aosThdUSleep(1);
67
  bq27500_lld_sub_command_call(driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, timeout);
68
  aosThdUSleep(1);
69
  bq27500_lld_std_command(driver, BQ27500_LLD_STD_CMD_Control, &dst, timeout);
70
  bq27500_lld_sub_command_read(driver, &ctrl.value, timeout);
71
  return ctrl;
72
}
73

    
74
uint8_t _bruteforce_sealed_key_bitflips(BaseSequentialStream* stream, BQ27500Driver* driver, uint16_t key0, uint16_t key1, apalTime_t timeout) {
75
  bq27500_lld_control_status_t ctrl;
76
  uint16_t k0;
77
  uint16_t k1 = key1;
78
  for (uint8_t i = 0; i < 16; i++) {
79
    k0 = key0 ^ (1 << i); // flip bit i
80
    ctrl = _try_unseal(driver, k0, k1, timeout);
81
    if (ctrl.content.ss == 0x0) {
82
      chprintf(stream, "\t\tSUCCESS!\n");
83
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
84
      return 1;
85
    }
86
  }
87
  k0 = key0;
88
  for (uint8_t i = 0; i < 16; i++) {
89
    k1 = key1 ^ (1 << i); // flip bit i
90
    ctrl = _try_unseal(driver, k0, k1, timeout);
91
    if (ctrl.content.ss == 0x0) {
92
      chprintf(stream, "\t\tSUCCESS!\n");
93
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
94
      return 1;
95
    }
96
  }
97
  return 0;
98
}
99

    
100
void _bruteforce_sealed_key(BaseSequentialStream* stream, BQ27500Driver* driver, apalTime_t timeout) {
101
  chprintf(stream, "start bruteforcing sealed keys...\n");
102
  bq27500_lld_control_status_t ctrl;
103
  uint16_t key0_reversed = 0x7236;
104
  uint16_t key1_reversed = 0x1404;
105
  uint16_t key0 = BQ27500_LLD_DEFAULT_UNSEAL_KEY0;
106
  uint16_t key1 = BQ27500_LLD_DEFAULT_UNSEAL_KEY1;
107
  uint16_t k0 = key0;
108
  uint16_t k1 = key1;
109

    
110
  // testing default keys in different orders
111
  chprintf(stream, "\ttry reversed byte order and different key order...\n");
112
  // default unseal keys
113
  ctrl = _try_unseal(driver, k0, k1, timeout);
114
  if (ctrl.content.ss == 0x0) {
115
    chprintf(stream, "\t\tSUCCESS!\n");
116
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
117
    return;
118
  }
119
  // default unseal keys in reversed order
120
  ctrl = _try_unseal(driver, k1, k0, timeout);
121
  if (ctrl.content.ss == 0x0) {
122
    chprintf(stream, "\t\tSUCCESS!\n");
123
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
124
    return;
125
  }
126
  // byte reversed keys
127
  k0 = key0_reversed;
128
  k1 = key1_reversed;
129
  ctrl = _try_unseal(driver, k0, k1, timeout);
130
  if (ctrl.content.ss == 0x0) {
131
    chprintf(stream, "\t\tSUCCESS!\n");
132
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
133
    return;
134
  }
135
  // byte reversed keys in reversed order
136
  ctrl = _try_unseal(driver, k1, k0, timeout);
137
  if (ctrl.content.ss == 0x0) {
138
    chprintf(stream, "\t\tSUCCESS!\n");
139
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
140
    return;
141
  }
142
  chprintf(stream, "\t\tfailed\n");
143

    
144

    
145
  // testing single bit flips of the default keys in different orders
146
  chprintf(stream, "\ttry single bit flips of default keys...\n");
147
  // default unseal keys
148
  uint8_t result = 0;
149
  result = _bruteforce_sealed_key_bitflips(stream, driver, key0, key1, timeout);
150
  if (result == 1) {
151
    return;
152
  }
153
  // default unseal keys in reversed order
154
  result = _bruteforce_sealed_key_bitflips(stream, driver, key1, key0, timeout);
155
  if (result == 1) {
156
    return;
157
  }
158
  // byte reversed keys
159
  result = _bruteforce_sealed_key_bitflips(stream, driver, key0_reversed, key1_reversed, timeout);
160
  if (result == 1) {
161
    return;
162
  }
163
  // byte reversed keys in reversed order
164
  result = _bruteforce_sealed_key_bitflips(stream, driver, key1_reversed, key0_reversed, timeout);
165
  if (result == 1) {
166
    return;
167
  }
168
  chprintf(stream, "\t\tfailed\n");
169

    
170

    
171
  // bruteforcing one of the keys, assuming only one of them was changed
172
  chprintf(stream, "\ttry bruteforcing a single key...\n");
173
  // default unseal key0
174
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
175
    ctrl = _try_unseal(driver, key0, i, timeout);
176
    if (ctrl.content.ss == 0x0) {
177
      chprintf(stream, "\t\tSUCCESS!\n");
178
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key0, i);
179
      return;
180
    }
181
  }
182
  chprintf(stream, "\t\tkey failed. 1/8\n");
183
  // reversed unseal key0
184
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
185
    ctrl = _try_unseal(driver, key0_reversed, i, timeout);
186
    if (ctrl.content.ss == 0x0) {
187
      chprintf(stream, "\t\tSUCCESS!\n");
188
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key0_reversed, i);
189
      return;
190
    }
191
  }
192
  chprintf(stream, "\t\tkey failed. 2/8\n");
193
  // default unseal key0 in reversed order
194
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
195
    ctrl = _try_unseal(driver, i, key0, timeout);
196
    if (ctrl.content.ss == 0x0) {
197
      chprintf(stream, "\t\tSUCCESS!\n");
198
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key0);
199
      return;
200
    }
201
  }
202
  chprintf(stream, "\t\tkey failed. 3/8\n");
203
  // reversed unseal key0 in reversed order
204
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
205
    ctrl = _try_unseal(driver, i, key0_reversed, timeout);
206
    if (ctrl.content.ss == 0x0) {
207
      chprintf(stream, "\t\tSUCCESS!\n");
208
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key0_reversed);
209
      return;
210
    }
211
  }
212
  chprintf(stream, "\t\tkey failed. 4/8\n");
213
  // default unseal key1
214
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
215
    ctrl = _try_unseal(driver, i, key1, timeout);
216
    if (ctrl.content.ss == 0x0) {
217
      chprintf(stream, "\t\tSUCCESS!\n");
218
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key1);
219
      return;
220
    }
221
  }
222
  chprintf(stream, "\t\tkey failed. 5/8\n");
223
  // reversed unseal key1
224
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
225
    ctrl = _try_unseal(driver, i, key1_reversed, timeout);
226
    if (ctrl.content.ss == 0x0) {
227
      chprintf(stream, "\t\tSUCCESS!\n");
228
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key1_reversed);
229
      return;
230
    }
231
  }
232
  chprintf(stream, "\t\tkey failed. 6/8\n");
233
  // default unseal key1 in reversed order
234
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
235
    ctrl = _try_unseal(driver, key1, i, timeout);
236
    if (ctrl.content.ss == 0x0) {
237
      chprintf(stream, "\t\tSUCCESS!\n");
238
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key1, i);
239
      return;
240
    }
241
  }
242
  chprintf(stream, "\t\tkey failed. 7/8\n");
243
  // reversed unseal key1 in reversed order
244
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
245
    ctrl = _try_unseal(driver, key1_reversed, i, timeout);
246
    if (ctrl.content.ss == 0x0) {
247
      chprintf(stream, "\t\tSUCCESS!\n");
248
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key1_reversed, i);
249
      return;
250
    }
251
  }
252
  chprintf(stream, "\t\tkey failed. 8/8\n");
253
  chprintf(stream, "\t\tfailed\n");
254

    
255

    
256
  // full bruteforce
257
  chprintf(stream, "\tbruteforcing both keys...\t");
258
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
259
    chprintf(stream, "\t\ti: %u\n", i);
260
    for (uint32_t j = 0; j <= 0xFFFF; j++) {
261
      ctrl = _try_unseal(driver, i, j, timeout);
262
      if (ctrl.content.ss == 0x0) {
263
        chprintf(stream, "\t\tSUCCESS!\n");
264
        chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, j);
265
        return;
266
      }
267
    }
268
  }
269

    
270
  chprintf(stream, "\t\tfailed, no keys could be found");
271
}
272

    
273
/******************************************************************************/
274
/* EXPORTED FUNCTIONS                                                         */
275
/******************************************************************************/
276

    
277
aos_utresult_t utAlldBq27500Func(BaseSequentialStream* stream, aos_unittest_t* ut)
278
{
279
  aosDbgCheck(ut->data != NULL && ((ut_bq27500data_t*)(ut->data))->driver != NULL);
280

    
281
  // local variables
282
  aos_utresult_t result = {0, 0};
283
  uint32_t status;
284
  bq27500_lld_batlow_t bl;
285
  bq27500_lld_batgood_t bg;
286
  uint16_t dst;
287
  bq27500_lld_flags_t flags;
288
  uint16_t subdata = 0;
289
  uint8_t original_length;
290
  char original_name[8+1];
291
  uint8_t val = 0x00;
292
  uint8_t block[32];
293
  char new_name[] = "test";
294
  uint8_t new_lenght;
295
  char name[8+1] = {'\0'};
296
  uint8_t sum = 0;
297
  bool success;
298
  bool success2;
299

    
300
  chprintf(stream, "read battery low gpio...\n");
301
  status = bq27500_lld_read_batlow(((ut_bq27500data_t*)ut->data)->driver, &bl);
302
  chprintf(stream, "\t\tbattery low: 0x%X\n", bl);
303
  if (status == APAL_STATUS_SUCCESS) {
304
    aosUtPassed(stream, &result);
305
  } else {
306
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
307
  }
308

    
309
  chprintf(stream, "read battery good gpio...\n");
310
  status = bq27500_lld_read_batgood(((ut_bq27500data_t*)ut->data)->driver, &bg);
311
  chprintf(stream, "\t\tbattery good: 0x%X\n", bg);
312
  if (status == APAL_STATUS_SUCCESS) {
313
    aosUtPassed(stream, &result);
314
  } else {
315
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
316
  }
317

    
318
  chprintf(stream, "std command FLAGS...\n");
319
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Flags, &flags.value, ((ut_bq27500data_t*)ut->data)->timeout);
320
  chprintf(stream, "\t\tflags: 0x%04X\n", flags.value);
321
  chprintf(stream, "\t\tbattery detected: 0x%X\n", flags.content.bat_det);
322
  chprintf(stream, "\t\tbattery fully charged: 0x%X\n", flags.content.fc);
323
  if (status == APAL_STATUS_SUCCESS) {
324
    aosUtPassed(stream, &result);
325
  } else {
326
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
327
  }
328

    
329
  chprintf(stream, "std command CTNL...\n");
330
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
331
  if (status == APAL_STATUS_SUCCESS) {
332
    aosUtPassed(stream, &result);
333
  } else {
334
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
335
  }
336

    
337
  chprintf(stream, "sub command: CTRL Status...\n");
338
  aosThdUSleep(1);
339
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
340
  aosThdUSleep(1);
341
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
342
  aosThdUSleep(1);
343
  bq27500_lld_control_status_t ctrl;
344
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
345
  chprintf(stream, "\t\tdst: 0x%X\n", ctrl.value);
346
  chprintf(stream, "\t\tsleep: 0x%X\n", ctrl.content.sleep);
347
  chprintf(stream, "\t\thibernate: 0x%X\n", ctrl.content.hibernate);
348
  if (status == APAL_STATUS_SUCCESS) {
349
    aosUtPassed(stream, &result);
350
  } else {
351
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
352
  }
353

    
354
  chprintf(stream, "sub command: firmware version...\n");
355
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_FW_VERSION, ((ut_bq27500data_t*)ut->data)->timeout);
356
  aosThdMSleep(1);
357
  bq27500_lld_version_t version;
358
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &version.value, ((ut_bq27500data_t*)ut->data)->timeout);
359
  chprintf(stream, "\t\tfirmware version: %X%X-%X%X\n", version.content.major_high, version.content.major_low, version.content.minor_high, version.content.minor_low);
360
  if (status == APAL_STATUS_SUCCESS) {
361
    aosUtPassed(stream, &result);
362
  } else {
363
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
364
  }
365

    
366
  chprintf(stream, "sub command: hardware version...\n");
367
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_HW_VERSION, ((ut_bq27500data_t*)ut->data)->timeout);
368
  aosThdMSleep(1);
369
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &version.value, ((ut_bq27500data_t*)ut->data)->timeout);
370
  chprintf(stream, "\t\thardware version: %X%X-%X%X\n", version.content.major_high, version.content.major_low, version.content.minor_high, version.content.minor_low);
371
  if (status == APAL_STATUS_SUCCESS) {
372
    aosUtPassed(stream, &result);
373
  } else {
374
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
375
  }
376

    
377
  chprintf(stream, "ext command: device name length...\n");
378
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceNameLength, BQ27500_LLD_EXT_CMD_READ, &original_length, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
379
  chprintf(stream, "\t\tdevice name length: %d \n", original_length);
380
  if (status == APAL_STATUS_SUCCESS && original_length <= 8) {
381
    aosUtPassed(stream, &result);
382
  } else {
383
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
384
    original_length = 8;
385
  }
386

    
387
  chprintf(stream, "ext command: device name (read)...\n");
388
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceName, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)original_name, original_length, 0, ((ut_bq27500data_t*)ut->data)->timeout);
389
  original_name[original_length] = '\0';
390
  chprintf(stream, "\t\tdevice name: %s\n", original_name);
391
  if (status == APAL_STATUS_SUCCESS) {
392
    aosUtPassed(stream, &result);
393
  } else {
394
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
395
  }
396

    
397
  chprintf(stream, "battery info std commands...\n");
398
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Temperatur, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
399
  chprintf(stream, "\t\ttemperature: %fK (%fC) \n", (float)dst/10.0f, (float)dst/10.0f-273.5f);
400
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_FullAvailableCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
401
  chprintf(stream, "\t\tfull available capacity: %umAh \n", dst);
402
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_FullChargeCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
403
  chprintf(stream, "\t\tfull charge capacity: %umAh \n", dst);
404
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_RemainingCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
405
  chprintf(stream, "\t\tremaining capacity: %umAh \n", dst);
406
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Voltage, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
407
  chprintf(stream, "\t\tvoltage: %umV \n", dst);
408
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_AverageCurrent, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
409
  chprintf(stream, "\t\taverage current: %dmA \n", (int8_t)dst);
410
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_AveragePower, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
411
  chprintf(stream, "\t\taverage power: %dmW \n", (int8_t)dst);
412
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_TimeToFull, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
413
  if (dst != (uint16_t)~0) {
414
    chprintf(stream, "\t\ttime to full: %umin \n", dst);
415
  } else {
416
    chprintf(stream, "\t\ttime to full: (not charging) \n", dst);
417
  }
418
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_TimeToEmpty, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
419
  if (dst != (uint16_t)~0) {
420
    chprintf(stream, "\t\ttime to empty: %umin \n", dst);
421
  } else {
422
    chprintf(stream, "\t\ttime to empty: (not discharging) \n", dst);
423
  }
424
  if (status == APAL_STATUS_SUCCESS) {
425
    aosUtPassed(stream, &result);
426
  } else {
427
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
428
  }
429

    
430
  chprintf(stream, "check sealed state...\n");
431
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
432
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
433
  aosThdMSleep(1);
434
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
435
  chprintf(stream, "\t\tsealed: 0x%X\n", ctrl.content.ss);
436
  chprintf(stream, "\t\tfull access sealed: 0x%X\n", ctrl.content.fas);
437
  if (status == APAL_STATUS_SUCCESS) {
438
    aosUtPassed(stream, &result);
439
  } else {
440
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
441
  }
442

    
443
  chprintf(stream, "unseale...\n");
444
  status = bq27500_lld_send_ctnl_data(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_DEFAULT_UNSEAL_KEY1, ((ut_bq27500data_t*)ut->data)->timeout);
445
  aosThdMSleep(1);
446
  status |= bq27500_lld_send_ctnl_data(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_DEFAULT_UNSEAL_KEY0, ((ut_bq27500data_t*)ut->data)->timeout);
447
  aosThdMSleep(1);
448
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
449
  aosThdMSleep(1);
450
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
451
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
452
  if (status == APAL_STATUS_SUCCESS && ctrl.content.ss == 0x0) {
453
    aosUtPassed(stream, &result);
454
  } else {
455
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
456
    _bruteforce_sealed_key(stream, ((ut_bq27500data_t*)ut->data)->driver, ((ut_bq27500data_t*)ut->data)->timeout);
457
  }
458

    
459
  chprintf(stream, "read device name from data flash...\n");
460
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataControl, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
461
  aosThdMSleep(50);
462
  val = 0x30;
463
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashClass, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
464
  aosThdMSleep(50);
465
  val = 0;
466
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashBlock, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
467
  aosThdMSleep(50);
468
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)block, original_length, 13, ((ut_bq27500data_t*)ut->data)->timeout);
469
  block[original_length] = '\0';
470
  chprintf(stream, "\t\tdevice name: %s\n", block);
471
  if (status == APAL_STATUS_SUCCESS && (strcmp((char*)block, (char*)original_name) == 0)) {
472
    aosUtPassed(stream, &result);
473
  } else {
474
    chprintf(stream, "\t\tread data: ");
475
    for (uint8_t blockIdx = 0; blockIdx < original_length; blockIdx++) {
476
      chprintf(stream, "0x%02X\n", block[blockIdx]);
477
    }
478
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
479
  }
480

    
481
  chprintf(stream, "change device name in data flash to \"test\"...\n");
482
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_WRITE, (uint8_t*)new_name, 5, 13, ((ut_bq27500data_t*)ut->data)->timeout);
483
  aosThdMSleep(50);
484
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)block, 32, 0, ((ut_bq27500data_t*)ut->data)->timeout);
485
  // compute blockdata checksum
486
  status |= bq27500_lld_compute_blockdata_checksum(block, &sum);
487
  // write checksum to BlockDataChecksum, triggering the write of BlackData
488
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataCheckSum, BQ27500_LLD_EXT_CMD_WRITE, &sum, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
489
  aosThdMSleep(50);
490
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceNameLength, BQ27500_LLD_EXT_CMD_READ, &new_lenght, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
491
  aosThdMSleep(50);
492
  // read out device name, to see if changing it was successfull
493
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceName, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)name, new_lenght, 0, ((ut_bq27500data_t*)ut->data)->timeout);
494
  name[new_lenght] = '\0';
495
  chprintf(stream, "\t\tdevice name: %s\n", name);
496
  success = (strcmp(name, new_name) == 0);
497

    
498
  // change device name back to original name
499
  val = 0x00;
500
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataControl, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
501
  aosThdMSleep(50);
502
  val = 0x30;
503
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashClass, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
504
  aosThdMSleep(50);
505
  val = 0;
506
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashBlock, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
507
  aosThdMSleep(50);
508
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_WRITE, (uint8_t*)original_name, 7, 13, ((ut_bq27500data_t*)ut->data)->timeout);
509
  aosThdMSleep(50);
510
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)block, 32, 0, ((ut_bq27500data_t*)ut->data)->timeout);
511
  // compute blockdata checksum
512
  sum = 0;
513
  status |= bq27500_lld_compute_blockdata_checksum(block, &sum);
514
  // write checksum to BlockDataChecksum, triggering the write of BlackData
515
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataCheckSum, BQ27500_LLD_EXT_CMD_WRITE, &sum, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
516
  aosThdMSleep(1000);
517
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceNameLength, BQ27500_LLD_EXT_CMD_READ, &original_length, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
518
  aosThdMSleep(50);
519
  // read device name, to see if changing it back to the original name was successfull
520
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceName, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)name, original_length, 0, ((ut_bq27500data_t*)ut->data)->timeout);
521
  success2 = (strcmp(name, original_name) == 0);
522
  name[original_length] = '\0';
523
  chprintf(stream, "\t\tchanged back to name: %s, original_name: %s\n", name, original_name);
524
  if (status == APAL_STATUS_OK && ((success && success2) || (ctrl.content.sleep == 0))) {
525
    aosUtPassed(stream, &result);
526
  } else {
527
    aosUtFailedMsg(stream, &result, "0x%08X, changing: 0x%X - changing back: 0x%X\n", status, success, success2);
528
  }
529

    
530
  chprintf(stream, "seal...\n");
531
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
532
  aosThdMSleep(50);
533
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_SEALED, ((ut_bq27500data_t*)ut->data)->timeout);
534
  aosThdMSleep(50);
535
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
536
  aosThdMSleep(50);
537
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
538
  aosThdMSleep(50);
539
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
540
  if (status == APAL_STATUS_SUCCESS && ctrl.content.ss == 0x1) {
541
    aosUtPassed(stream, &result);
542
  } else {
543
    chprintf(stream, "\tfailed (0x%X)\n", status);
544
    aosUtFailedMsg(stream, &result, "0x%08X, ctrl 0x%X\n", status, subdata);
545
    ++result.failed;
546
  }
547

    
548
  aosUtInfoMsg(stream,"driver object memory footprint: %u bytes\n", sizeof(BQ27500Driver));
549

    
550
  return result;
551
}
552

    
553
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_BQ27500) */
554