Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / periphery-lld / src / ut_alld_bq27500.c @ 1678f270

History | View | Annotate | Download (24.5 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
#include <aos_debug.h>
25
#include <chprintf.h>
26
#include <aos_thread.h>
27
#include <alld_bq27500.h>
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
bq27500_lld_control_status_t _try_unseal(BQ27500Driver* driver, uint16_t key0, uint16_t key1, apalTime_t timeout) {
45
  uint16_t dst;
46
  bq27500_lld_control_status_t ctrl;
47
  bq27500_lld_send_ctnl_data(driver, key1, timeout);
48
  aosThdUSleep(1);
49
  bq27500_lld_send_ctnl_data(driver, key0, timeout);
50
  aosThdUSleep(1);
51
  bq27500_lld_sub_command_call(driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, timeout);
52
  aosThdUSleep(1);
53
  bq27500_lld_std_command(driver, BQ27500_LLD_STD_CMD_Control, &dst, timeout);
54
  bq27500_lld_sub_command_read(driver, &ctrl.value, timeout);
55
  return ctrl;
56
}
57

    
58
uint8_t _bruteforce_sealed_key_bitflips(BaseSequentialStream* stream, BQ27500Driver* driver, uint16_t key0, uint16_t key1, apalTime_t timeout) {
59
  bq27500_lld_control_status_t ctrl;
60
  uint16_t k0;
61
  uint16_t k1 = key1;
62
  for (uint8_t i = 0; i < 16; i++) {
63
    k0 = key0 ^ (1 << i); // flip bit i
64
    ctrl = _try_unseal(driver, k0, k1, timeout);
65
    if (ctrl.content.ss == 0x0) {
66
      chprintf(stream, "\t\tSUCCESS!\n");
67
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
68
      return 1;
69
    }
70
  }
71
  k0 = key0;
72
  for (uint8_t i = 0; i < 16; i++) {
73
    k1 = key1 ^ (1 << i); // flip bit i
74
    ctrl = _try_unseal(driver, k0, k1, timeout);
75
    if (ctrl.content.ss == 0x0) {
76
      chprintf(stream, "\t\tSUCCESS!\n");
77
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
78
      return 1;
79
    }
80
  }
81
  return 0;
82
}
83

    
84
void _bruteforce_sealed_key(BaseSequentialStream* stream, BQ27500Driver* driver, apalTime_t timeout) {
85
  chprintf(stream, "start bruteforcing sealed keys...\n");
86
  bq27500_lld_control_status_t ctrl;
87
  uint16_t key0_reversed = 0x7236;
88
  uint16_t key1_reversed = 0x1404;
89
  uint16_t key0 = BQ27500_LLD_DEFAULT_UNSEAL_KEY0;
90
  uint16_t key1 = BQ27500_LLD_DEFAULT_UNSEAL_KEY1;
91
  uint16_t k0 = key0;
92
  uint16_t k1 = key1;
93

    
94
  // testing default keys in different orders
95
  chprintf(stream, "\ttry reversed byte order and different key order...\n");
96
  // default unseal keys
97
  ctrl = _try_unseal(driver, k0, k1, timeout);
98
  if (ctrl.content.ss == 0x0) {
99
    chprintf(stream, "\t\tSUCCESS!\n");
100
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
101
    return;
102
  }
103
  // default unseal keys in reversed order
104
  ctrl = _try_unseal(driver, k1, k0, timeout);
105
  if (ctrl.content.ss == 0x0) {
106
    chprintf(stream, "\t\tSUCCESS!\n");
107
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
108
    return;
109
  }
110
  // byte reversed keys
111
  k0 = key0_reversed;
112
  k1 = key1_reversed;
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
  // byte reversed 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
  chprintf(stream, "\t\tfailed\n");
127

    
128

    
129
  // testing single bit flips of the default keys in different orders
130
  chprintf(stream, "\ttry single bit flips of default keys...\n");
131
  // default unseal keys
132
  uint8_t result = 0;
133
  result = _bruteforce_sealed_key_bitflips(stream, driver, key0, key1, timeout);
134
  if (result == 1) {
135
    return;
136
  }
137
  // default unseal keys in reversed order
138
  result = _bruteforce_sealed_key_bitflips(stream, driver, key1, key0, timeout);
139
  if (result == 1) {
140
    return;
141
  }
142
  // byte reversed keys
143
  result = _bruteforce_sealed_key_bitflips(stream, driver, key0_reversed, key1_reversed, timeout);
144
  if (result == 1) {
145
    return;
146
  }
147
  // byte reversed keys in reversed order
148
  result = _bruteforce_sealed_key_bitflips(stream, driver, key1_reversed, key0_reversed, timeout);
149
  if (result == 1) {
150
    return;
151
  }
152
  chprintf(stream, "\t\tfailed\n");
153

    
154

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

    
239

    
240
  // full bruteforce
241
  chprintf(stream, "\tbruteforcing both keys...\t");
242
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
243
    chprintf(stream, "\t\ti: %u\n", i);
244
    for (uint32_t j = 0; j <= 0xFFFF; j++) {
245
      ctrl = _try_unseal(driver, i, j, timeout);
246
      if (ctrl.content.ss == 0x0) {
247
        chprintf(stream, "\t\tSUCCESS!\n");
248
        chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, j);
249
        return;
250
      }
251
    }
252
  }
253

    
254
  chprintf(stream, "\t\tfailed, no keys could be found");
255
}
256

    
257
aos_utresult_t utAlldBq27500Func(BaseSequentialStream* stream, aos_unittest_t* ut)
258
{
259
  aosDbgCheck(ut->data != NULL && ((ut_bq27500data_t*)(ut->data))->driver != NULL);
260

    
261
  // local variables
262
  aos_utresult_t result = {0, 0};
263
  uint32_t status;
264
  bq27500_lld_batlow_t bl;
265
  bq27500_lld_batgood_t bg;
266
  uint16_t dst;
267
  bq27500_lld_flags_t flags;
268
  uint16_t subdata = 0;
269
  uint8_t original_length;
270
  char original_name[8+1];
271
  uint8_t val = 0x00;
272
  uint8_t block[32];
273
  char new_name[] = "test";
274
  uint8_t new_lenght;
275
  char name[8+1] = {'\0'};
276
  uint8_t sum = 0;
277
  bool success;
278
  bool success2;
279

    
280
  chprintf(stream, "read battery low gpio...\n");
281
  status = bq27500_lld_read_batlow(((ut_bq27500data_t*)ut->data)->driver, &bl);
282
  chprintf(stream, "\t\tbattery low: 0x%X\n", bl);
283
  if (status == APAL_STATUS_SUCCESS) {
284
    aosUtPassed(stream, &result);
285
  } else {
286
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
287
  }
288

    
289
  chprintf(stream, "read battery good gpio...\n");
290
  status = bq27500_lld_read_batgood(((ut_bq27500data_t*)ut->data)->driver, &bg);
291
  chprintf(stream, "\t\tbattery good: 0x%X\n", bg);
292
  if (status == APAL_STATUS_SUCCESS) {
293
    aosUtPassed(stream, &result);
294
  } else {
295
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
296
  }
297

    
298
  chprintf(stream, "std command FLAGS...\n");
299
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Flags, &flags.value, ((ut_bq27500data_t*)ut->data)->timeout);
300
  chprintf(stream, "\t\tflags: 0x%04X\n", flags.value);
301
  chprintf(stream, "\t\tbattery detected: 0x%X\n", flags.content.bat_det);
302
  chprintf(stream, "\t\tbattery fully charged: 0x%X\n", flags.content.fc);
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, "std command CTNL...\n");
310
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
311
  if (status == APAL_STATUS_SUCCESS) {
312
    aosUtPassed(stream, &result);
313
  } else {
314
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
315
  }
316

    
317
  chprintf(stream, "sub command: CTRL Status...\n");
318
  aosThdUSleep(1);
319
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
320
  aosThdUSleep(1);
321
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
322
  aosThdUSleep(1);
323
  bq27500_lld_control_status_t ctrl;
324
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
325
  chprintf(stream, "\t\tdst: 0x%X\n", ctrl.value);
326
  chprintf(stream, "\t\tsleep: 0x%X\n", ctrl.content.sleep);
327
  chprintf(stream, "\t\thibernate: 0x%X\n", ctrl.content.hibernate);
328
  if (status == APAL_STATUS_SUCCESS) {
329
    aosUtPassed(stream, &result);
330
  } else {
331
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
332
  }
333

    
334
  chprintf(stream, "sub command: firmware version...\n");
335
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_FW_VERSION, ((ut_bq27500data_t*)ut->data)->timeout);
336
  aosThdMSleep(1);
337
  bq27500_lld_version_t version;
338
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &version.value, ((ut_bq27500data_t*)ut->data)->timeout);
339
  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);
340
  if (status == APAL_STATUS_SUCCESS) {
341
    aosUtPassed(stream, &result);
342
  } else {
343
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
344
  }
345

    
346
  chprintf(stream, "sub command: hardware version...\n");
347
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_HW_VERSION, ((ut_bq27500data_t*)ut->data)->timeout);
348
  aosThdMSleep(1);
349
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &version.value, ((ut_bq27500data_t*)ut->data)->timeout);
350
  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);
351
  if (status == APAL_STATUS_SUCCESS) {
352
    aosUtPassed(stream, &result);
353
  } else {
354
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
355
  }
356

    
357
  chprintf(stream, "ext command: device name length...\n");
358
  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);
359
  chprintf(stream, "\t\tdevice name length: %d \n", original_length);
360
  if (status == APAL_STATUS_SUCCESS && original_length <= 8) {
361
    aosUtPassed(stream, &result);
362
  } else {
363
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
364
    original_length = 8;
365
  }
366

    
367
  chprintf(stream, "ext command: device name (read)...\n");
368
  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);
369
  original_name[original_length] = '\0';
370
  chprintf(stream, "\t\tdevice name: %s\n", original_name);
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, "battery info std commands...\n");
378
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Temperatur, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
379
  chprintf(stream, "\t\ttemperature: %fK (%fC) \n", (float)dst/10.0f, (float)dst/10.0f-273.5f);
380
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_FullAvailableCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
381
  chprintf(stream, "\t\tfull available capacity: %umAh \n", dst);
382
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_FullChargeCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
383
  chprintf(stream, "\t\tfull charge capacity: %umAh \n", dst);
384
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_RemainingCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
385
  chprintf(stream, "\t\tremaining capacity: %umAh \n", dst);
386
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Voltage, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
387
  chprintf(stream, "\t\tvoltage: %umV \n", dst);
388
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_AverageCurrent, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
389
  chprintf(stream, "\t\taverage current: %dmA \n", (int8_t)dst);
390
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_AveragePower, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
391
  chprintf(stream, "\t\taverage power: %dmW \n", (int8_t)dst);
392
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_TimeToFull, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
393
  if (dst != (uint16_t)~0) {
394
    chprintf(stream, "\t\ttime to full: %umin \n", dst);
395
  } else {
396
    chprintf(stream, "\t\ttime to full: (not charging) \n", dst);
397
  }
398
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_TimeToEmpty, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
399
  if (dst != (uint16_t)~0) {
400
    chprintf(stream, "\t\ttime to empty: %umin \n", dst);
401
  } else {
402
    chprintf(stream, "\t\ttime to empty: (not discharging) \n", dst);
403
  }
404
  if (status == APAL_STATUS_SUCCESS) {
405
    aosUtPassed(stream, &result);
406
  } else {
407
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
408
  }
409

    
410
  chprintf(stream, "check sealed state...\n");
411
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
412
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
413
  aosThdMSleep(1);
414
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
415
  chprintf(stream, "\t\tsealed: 0x%X\n", ctrl.content.ss);
416
  chprintf(stream, "\t\tfull access sealed: 0x%X\n", ctrl.content.fas);
417
  if (status == APAL_STATUS_SUCCESS) {
418
    aosUtPassed(stream, &result);
419
  } else {
420
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
421
  }
422

    
423
  chprintf(stream, "unseale...\n");
424
  status = bq27500_lld_send_ctnl_data(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_DEFAULT_UNSEAL_KEY1, ((ut_bq27500data_t*)ut->data)->timeout);
425
  aosThdMSleep(1);
426
  status |= bq27500_lld_send_ctnl_data(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_DEFAULT_UNSEAL_KEY0, ((ut_bq27500data_t*)ut->data)->timeout);
427
  aosThdMSleep(1);
428
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
429
  aosThdMSleep(1);
430
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
431
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
432
  if (status == APAL_STATUS_SUCCESS && ctrl.content.ss == 0x0) {
433
    aosUtPassed(stream, &result);
434
  } else {
435
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
436
    _bruteforce_sealed_key(stream, ((ut_bq27500data_t*)ut->data)->driver, ((ut_bq27500data_t*)ut->data)->timeout);
437
  }
438

    
439
  chprintf(stream, "read device name from data flash...\n");
440
  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);
441
  aosThdMSleep(50);
442
  val = 0x30;
443
  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);
444
  aosThdMSleep(50);
445
  val = 0;
446
  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);
447
  aosThdMSleep(50);
448
  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);
449
  block[original_length] = '\0';
450
  chprintf(stream, "\t\tdevice name: %s\n", block);
451
  if (status == APAL_STATUS_SUCCESS && (strcmp((char*)block, (char*)original_name) == 0)) {
452
    aosUtPassed(stream, &result);
453
  } else {
454
    chprintf(stream, "\t\tread data: ");
455
    for (uint8_t blockIdx = 0; blockIdx < original_length; blockIdx++) {
456
      chprintf(stream, "0x%02X\n", block[blockIdx]);
457
    }
458
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
459
  }
460

    
461
  chprintf(stream, "change device name in data flash to \"test\"...\n");
462
  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);
463
  aosThdMSleep(50);
464
  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);
465
  // compute blockdata checksum
466
  status |= bq27500_lld_compute_blockdata_checksum(block, &sum);
467
  // write checksum to BlockDataChecksum, triggering the write of BlackData
468
  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);
469
  aosThdMSleep(50);
470
  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);
471
  aosThdMSleep(50);
472
  // read out device name, to see if changing it was successfull
473
  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);
474
  name[new_lenght] = '\0';
475
  chprintf(stream, "\t\tdevice name: %s\n", name);
476
  success = (strcmp(name, new_name) == 0);
477

    
478
  // change device name back to original name
479
  val = 0x00;
480
  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);
481
  aosThdMSleep(50);
482
  val = 0x30;
483
  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);
484
  aosThdMSleep(50);
485
  val = 0;
486
  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);
487
  aosThdMSleep(50);
488
  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);
489
  aosThdMSleep(50);
490
  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);
491
  // compute blockdata checksum
492
  sum = 0;
493
  status |= bq27500_lld_compute_blockdata_checksum(block, &sum);
494
  // write checksum to BlockDataChecksum, triggering the write of BlackData
495
  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);
496
  aosThdMSleep(1000);
497
  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);
498
  aosThdMSleep(50);
499
  // read device name, to see if changing it back to the original name was successfull
500
  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);
501
  success2 = (strcmp(name, original_name) == 0);
502
  name[original_length] = '\0';
503
  chprintf(stream, "\t\tchanged back to name: %s, original_name: %s\n", name, original_name);
504
  if (status == APAL_STATUS_OK && ((success && success2) || (ctrl.content.sleep == 0))) {
505
    aosUtPassed(stream, &result);
506
  } else {
507
    aosUtFailedMsg(stream, &result, "0x%08X, changing: 0x%X - changing back: 0x%X\n", status, success, success2);
508
  }
509

    
510
  chprintf(stream, "seal...\n");
511
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
512
  aosThdMSleep(50);
513
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_SEALED, ((ut_bq27500data_t*)ut->data)->timeout);
514
  aosThdMSleep(50);
515
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
516
  aosThdMSleep(50);
517
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
518
  aosThdMSleep(50);
519
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
520
  if (status == APAL_STATUS_SUCCESS && ctrl.content.ss == 0x1) {
521
    aosUtPassed(stream, &result);
522
  } else {
523
    chprintf(stream, "\tfailed (0x%X)\n", status);
524
    aosUtFailedMsg(stream, &result, "0x%08X, ctrl 0x%X\n", status, subdata);
525
    ++result.failed;
526
  }
527

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

    
530
  return result;
531
}
532

    
533
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_BQ27500) */
534