1 /*
2  * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3  */
4 
5 
6 //#include <aos/osal_debug.h>
7 #include <aos/kernel.h>
8 #include <aos/ble.h>
9 #include <aos/gatt.h>
10 //#include <yoc/partition.h>
11 
12 #include <yoc/ota_server.h>
13 
14 #define OTA_PACKET_SIZE (8192)
15 
16 #define OTA_PACKET_START (0xFF)
17 #define OTA_PACKET_END (0xFE)
18 
19 #ifndef MIN
20 # define MIN(a,b) ((a) < (b) ? (a) : (b))
21 #endif
22 
23 enum ota_cmd {
24     OTA_CMD_START = 0x01,
25     OTA_CMD_STOP = 0x02,
26     OTA_CMD_REQUEST = 0x03,
27     OTA_CMD_COMPLETE = 0x04,
28 };
29 
30 typedef struct _ota_start_t {
31     uint32_t cmd: 8;
32     uint32_t firmware_size: 24;
33     uint16_t packet_size;
34     uint8_t  timeout;
35 } ota_start_t;
36 
37 struct ota_rx_t {
38     uint8_t rx_buf[OTA_PACKET_SIZE];
39     uint16_t rx_len;
40     uint16_t expect_len;
41     uint16_t packet_id;
42     uint16_t packet_crc;
43 };
44 
45 static struct ota_rx_t ota_rx = {0};
46 
47 static struct ota_ctrl_t {
48     ota_state_en st;
49     uint32_t firmware_size;
50     uint16_t packet_size;
51     uint8_t  timeout;
52     uint16_t expect_packet_count;
53     uint16_t recv_packet_count;
54     uint8_t  retry_count;
55     aos_timer_t timer;
56     ota_event_callback_t cb;
57 } ota_ctrl;
58 
59 #define TAG "OTA"
60 
61 #define YOC_OTA_SERVICE_UUID                                                                      \
62     UUID128_DECLARE(0x7e, 0x31, 0x35, 0xd4, 0x12, 0xf3, 0x11, 0xe9, 0xab, 0x14, 0xd6, 0x63, 0xbd,  \
63                     0x87, 0x3d, 0x93)
64 
65 #define YOC_OTA_RX_UUID                                                                           \
66     UUID128_DECLARE(0x7e, 0x31, 0x35, 0xd4, 0x12, 0xf3, 0x11, 0xe9, 0xab, 0x14, 0xd6, 0x63, 0xbd,  \
67                     0x87, 0x3d, 0x94)
68 
69 #define YOC_OTA_TX_UUID                                                                           \
70     UUID128_DECLARE(0x7e, 0x31, 0x35, 0xd4, 0x12, 0xf3, 0x11, 0xe9, 0xab, 0x14, 0xd6, 0x63, 0xbd,  \
71                     0x87, 0x3d, 0x95)
72 
73 static int16_t g_yoc_ota_handle  = -1;
74 static int16_t g_conn_hanlde      = -1;
75 static int16_t g_tx_ccc_value     = 0;
76 
77 static char rx_char_des[] = "YoC OTA RX";
78 static char tx_char_des[] = "YoC OTA TX";
79 
80 enum {
81     YOC_OTA_IDX_SVC,
82 
83     YOC_OTA_IDX_RX_CHAR,
84     YOC_OTA_IDX_RX_VAL,
85     YOC_OTA_IDX_RX_DES,
86 
87     YOC_OTA_IDX_TX_CHAR,
88     YOC_OTA_IDX_TX_VAL,
89     YOC_OTA_IDX_TX_CCC,
90     YOC_OTA_IDX_TX_DES,
91 
92     YOC_OTA_IDX_MAX,
93 };
94 
95 //static struct bt_gatt_ccc_cfg_t ccc_data[2] = {};
96 static gatt_service                    uart_service;
97 
98 static gatt_attr_t uart_attrs[YOC_OTA_IDX_MAX] = {
99     [YOC_OTA_IDX_SVC] = GATT_PRIMARY_SERVICE_DEFINE(YOC_OTA_SERVICE_UUID),
100 
101     [YOC_OTA_IDX_RX_CHAR] = GATT_CHAR_DEFINE(YOC_OTA_RX_UUID, GATT_CHRC_PROP_WRITE_WITHOUT_RESP),
102     [YOC_OTA_IDX_RX_VAL] =
103     GATT_CHAR_VAL_DEFINE(YOC_OTA_RX_UUID, GATT_PERM_READ | GATT_PERM_WRITE),
104     [YOC_OTA_IDX_RX_DES] = GATT_CHAR_CUD_DEFINE(rx_char_des, GATT_PERM_READ),
105 
106     [YOC_OTA_IDX_TX_CHAR] =
107     GATT_CHAR_DEFINE(YOC_OTA_TX_UUID, GATT_CHRC_PROP_NOTIFY | GATT_CHRC_PROP_READ),
108     [YOC_OTA_IDX_TX_VAL] = GATT_CHAR_VAL_DEFINE(YOC_OTA_TX_UUID, GATT_PERM_READ),
109     [YOC_OTA_IDX_TX_CCC] = GATT_CHAR_CCC_DEFINE(),
110     [YOC_OTA_IDX_TX_DES] = GATT_CHAR_CUD_DEFINE(tx_char_des, GATT_PERM_READ),
111 };
112 
113 static partition_t ota_partition_handle = -1;
114 static partition_info_t *ota_partition_info;
115 
116 extern uint16_t crc16(uint16_t sedd, const volatile void *p_data, uint32_t size);
117 
ota_status_change(int state)118 static void ota_status_change(int state)
119 {
120     ota_ctrl.st = state;
121 
122     if (ota_ctrl.cb) {
123         ota_ctrl.cb(state);
124     }
125 
126     LOGD(TAG, "%d->%d", ota_ctrl.st, state);
127 }
128 
ota_reset()129 static void ota_reset()
130 {
131     ota_ctrl.st = 0;
132     ota_ctrl.firmware_size = 0;
133     ota_ctrl.packet_size = 0;
134     ota_ctrl.timeout = 0;
135     ota_ctrl.expect_packet_count = 0;
136     ota_ctrl.recv_packet_count = 0;
137     ota_ctrl.retry_count = 0;
138     aos_timer_stop(&ota_ctrl.timer);
139     memset(&ota_rx, 0, sizeof(ota_rx));
140 }
141 
ota_reset_rx()142 static void ota_reset_rx()
143 {
144     memset(&ota_rx, 0, sizeof(ota_rx));
145 }
146 
ota_partition_erase()147 static int ota_partition_erase()
148 {
149     if (partition_erase(ota_partition_handle, 0, (ota_partition_info->length + ota_partition_info->sector_size - 1) / ota_partition_info->sector_size) < 0) {
150         LOGE(TAG, "erase addr:%x\n");
151         return -1;
152     }
153 
154     LOGD(TAG, "erase length %d block %d succeed", ota_partition_info->length, (ota_partition_info->length + ota_partition_info->sector_size - 1) / ota_partition_info->sector_size);
155 
156     return 0;
157 }
158 
ota_partition_write(uint8_t * buffer,int length,int offset)159 static int ota_partition_write(uint8_t *buffer, int length, int offset)
160 {
161     if (partition_write(ota_partition_handle, offset + (ota_partition_info->sector_size << 1), (void *)buffer, length) >= 0) {
162         LOGD(TAG, "write addr:%x length:%x\n", offset, length);
163 
164         return length;
165     }
166 
167     LOGE(TAG, "write addr fail:%x length:%x\n", offset, length);
168     return -1;
169 }
170 
ota_partition_size()171 static inline uint32_t ota_partition_size()
172 {
173     return ota_partition_info->length - (ota_partition_info->sector_size << 1);
174 }
175 
conn_change(ble_event_en event,void * event_data)176 static void conn_change(ble_event_en event, void *event_data)
177 {
178     evt_data_gap_conn_change_t *e = (evt_data_gap_conn_change_t *)event_data;
179 
180     if (e->connected == CONNECTED) {
181         g_conn_hanlde = e->conn_handle;
182     } else {
183         g_conn_hanlde = -1;
184         ota_reset();
185         ota_partition_erase();
186         ota_status_change(OTA_ST_IDLE);
187     }
188 }
189 
ota_recv_data(const uint8_t * data,uint16_t len)190 static inline int ota_recv_data(const uint8_t *data, uint16_t len)
191 {
192     if (!data || !len || !ota_rx.expect_len) {
193         return -1;
194     }
195 
196     uint16_t cp_size = MIN(ota_rx.expect_len - ota_rx.rx_len, len);
197 
198     memcpy(ota_rx.rx_buf + ota_rx.rx_len, data, cp_size);
199 
200     ota_rx.rx_len += cp_size;
201 
202     if (ota_rx.rx_len >= ota_rx.expect_len) {
203         aos_timer_stop(&ota_ctrl.timer);
204     }
205 
206     /* the last data */
207     if (ota_rx.rx_len >= ota_rx.expect_len) {
208         uint16_t crc = crc16(0, ota_rx.rx_buf, ota_rx.rx_len);
209 
210         if (crc == ota_rx.packet_crc) {
211             ota_status_change(OTA_ST_FLASH);
212         } else {
213             LOGE(TAG, "crc err %x %x", crc, ota_rx.packet_crc);
214             ota_status_change(OTA_ST_REQUEST);
215         }
216     }
217 
218     if (ota_rx.rx_len > ota_rx.expect_len) {
219         LOGE(TAG, "ota packet err len %d,cp size %d, rx len %d expect len %d", len, cp_size , ota_ctrl.expect_packet_count, ota_rx.rx_len, ota_rx.expect_len);
220         ota_status_change(OTA_ST_REQUEST);
221     }
222 
223     return 0;
224 }
225 
event_char_write(ble_event_en event,void * event_data)226 void event_char_write(ble_event_en event, void *event_data)
227 {
228     evt_data_gatt_char_write_t *e            = (evt_data_gatt_char_write_t *)event_data;
229     int16_t                     hande_offset = 0;
230 
231     if (g_conn_hanlde != e->conn_handle) {
232         return;
233     }
234 
235     if (e->char_handle > g_yoc_ota_handle && e->char_handle < g_yoc_ota_handle + YOC_OTA_IDX_MAX) {
236         hande_offset = e->char_handle - g_yoc_ota_handle;
237     } else {
238         return;
239     }
240 
241     switch (hande_offset) {
242         case YOC_OTA_IDX_RX_VAL: {
243             switch (ota_ctrl.st) {
244                 case OTA_ST_IDLE: {
245                     /* ota start */
246                     if (e->len == 9 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_CMD_START
247                         && e->data[e->len - 1] == OTA_PACKET_END) {
248                         uint32_t firmware_size = e->data[2] << 16 | e->data[3] << 8 | e->data[4];
249                         uint16_t packet_size = e->data[5] << 8 | e->data[6];
250                         uint8_t timeout = e->data[7];
251 
252                         if (firmware_size > ota_partition_size() || packet_size > OTA_PACKET_SIZE) {
253                             LOGE(TAG, "unsupport ota param %d %d", firmware_size, packet_size);
254                             return;
255                         }
256 
257                         ota_ctrl.firmware_size = firmware_size;
258                         ota_ctrl.packet_size = packet_size;
259                         ota_ctrl.timeout = timeout;
260                         /* ota data formate */
261                         /* |head  | packet id | crc16 | firmware    | tail  | */
262                         /* |2Bytes| 2bytes    |2bytes |firmware size| 2Bytes| */
263                         ota_ctrl.expect_packet_count = (firmware_size + packet_size - 1) / packet_size;
264                         LOGI(TAG, "ota start firmware size %d packet size %d timeout %d expect packet count %d",
265                              firmware_size, packet_size, timeout, ota_ctrl.expect_packet_count);
266                         ota_status_change(OTA_ST_START);
267                     } else {
268                         LOGE(TAG, "unkonw packet, drop %d", e->len);
269                     }
270 
271                     break;
272                 }
273 
274                 case OTA_ST_DL: {
275                     /* ota stop */
276                     if (e->len == 3 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_CMD_STOP
277                         && e->data[2] == OTA_PACKET_END) {
278                         LOGI(TAG, "ota stop");
279                         ota_reset();
280                         ota_status_change(OTA_ST_STOP);
281                     }
282                     /* ota complete */
283                     else if (e->len == 3 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_CMD_COMPLETE
284                              && e->data[2] == OTA_PACKET_END) {
285                         LOGI(TAG, "ota complelte");
286                         ota_status_change(OTA_ST_COMPLETE);
287                     }
288                     /* ota data */
289                     else if (e->len > 6 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_PACKET_END && ota_rx.expect_len == 0) {
290                         uint16_t packet_id = e->data[2] << 8 | e->data[3];
291                         uint16_t packet_crc = e->data[4] << 8 | e->data[5];
292 
293                         if (packet_id >= ota_ctrl.expect_packet_count) {
294                             LOGE(TAG, "packet id overflow, drop %d\n", packet_id);
295                             return;
296                         }
297 
298                         if (packet_id == ota_ctrl.expect_packet_count - 1) {
299                             ota_rx.expect_len = ota_ctrl.firmware_size % ota_ctrl.packet_size;
300                         } else {
301                             ota_rx.expect_len = ota_ctrl.packet_size;
302                         }
303 
304                         ota_rx.packet_id = packet_id;
305                         ota_rx.packet_crc = packet_crc;
306                         ota_recv_data(e->data + 6, e->len - 6);
307                     } else if (ota_rx.expect_len) {
308                         ota_recv_data(e->data, e->len);
309                     }
310 
311                     break;
312                 }
313 
314                 default:
315                     LOGE(TAG, "invaild st %d\n", ota_ctrl.st);
316                     break;
317             }
318         }
319         break;
320     }
321 
322     e->len = 0;
323     return;
324 }
325 
event_char_read(ble_event_en event,void * event_data)326 void event_char_read(ble_event_en event, void *event_data)
327 {
328     evt_data_gatt_char_read_t *e            = (evt_data_gatt_char_read_t *)event_data;
329     int16_t                    hande_offset = 0;
330 
331     if (g_conn_hanlde == e->conn_handle) {
332         if (e->char_handle > g_yoc_ota_handle) {
333             hande_offset = e->char_handle - g_yoc_ota_handle;
334         } else {
335             return;
336         }
337 
338         switch (hande_offset) {
339             case YOC_OTA_IDX_RX_VAL:
340                 memcpy(e->data, ota_rx.rx_buf, MIN(e->len, sizeof(ota_rx.rx_buf)));
341                 e->len = MIN(e->len, sizeof(ota_rx.rx_buf));
342                 return;
343 
344             case YOC_OTA_IDX_RX_DES:
345                 memcpy(e->data, rx_char_des, MIN(e->len, strlen(rx_char_des)));
346                 e->len = MIN(e->len, strlen(rx_char_des));
347                 return;
348 
349             case YOC_OTA_IDX_TX_DES:
350                 memcpy(e->data, tx_char_des, MIN(e->len, strlen(tx_char_des)));
351                 e->len = MIN(e->len, strlen(tx_char_des));
352                 return;
353         }
354     }
355 
356     e->len = 0;
357     return;
358 }
359 
event_char_ccc_change(ble_event_en event,void * event_data)360 void event_char_ccc_change(ble_event_en event, void *event_data)
361 {
362     evt_data_gatt_char_ccc_change_t *e = (evt_data_gatt_char_ccc_change_t *)event_data;
363 
364     if (e->char_handle != g_yoc_ota_handle + YOC_OTA_IDX_TX_CCC) {
365         return;
366     }
367 
368     g_tx_ccc_value                     = e->ccc_value;
369 
370     LOGD(TAG, "ccc %d %d\n", e->char_handle, e->ccc_value);
371 }
372 
mtu_exchange(ble_event_en event,void * event_data)373 static void mtu_exchange(ble_event_en event, void *event_data)
374 {
375     evt_data_gatt_mtu_exchange_t *e = (evt_data_gatt_mtu_exchange_t *)event_data;
376 
377     if (e->err == 0) {
378         LOGD(TAG, "mtu get %d", ble_stack_gatt_mtu_get(e->conn_handle));
379     } else {
380         LOGE(TAG, "mtu exchange fail, %d", e->err);
381     }
382 }
383 
event_callback(ble_event_en event,void * event_data)384 static int event_callback(ble_event_en event, void *event_data)
385 {
386     switch (event) {
387         case EVENT_GAP_CONN_CHANGE:
388             conn_change(event, event_data);
389             break;
390 
391         case EVENT_GATT_CHAR_READ:
392             event_char_read(event, event_data);
393             break;
394 
395         case EVENT_GATT_CHAR_WRITE:
396             event_char_write(event, event_data);
397             break;
398 
399         case EVENT_GATT_CHAR_CCC_CHANGE:
400             event_char_ccc_change(event, event_data);
401             break;
402 
403         case EVENT_GATT_MTU_EXCHANGE:
404             mtu_exchange(event, event_data);
405             break;
406 
407         default:
408             break;
409     }
410 
411     return 0;
412 }
413 
414 
415 static ble_event_cb_t ble_ota_cb = {
416     .callback = event_callback,
417 };
418 
ota_request(uint32_t offset)419 static inline int ota_request(uint32_t offset)
420 {
421     LOGI(TAG, "request %d", offset);
422 
423     ota_reset_rx();
424 
425     aos_timer_change(&ota_ctrl.timer, ota_ctrl.timeout * 1000);
426     aos_timer_start(&ota_ctrl.timer);
427     static uint8_t send_buf[6] = {0xff, 0x03, 0x00, 0x00, 0x00, 0xfe};
428     send_buf[2] = offset >> 16 & 0xFF;
429     send_buf[3] = offset >> 8 & 0xFF;
430     send_buf[4] = offset >> 0 & 0xFF;
431     return ble_stack_gatt_notificate(g_conn_hanlde, g_yoc_ota_handle + YOC_OTA_IDX_TX_VAL, send_buf, sizeof(send_buf));
432 }
433 
ble_ota_process()434 void ble_ota_process()
435 {
436     if (g_conn_hanlde == -1) {
437         return;
438     }
439 
440     switch (ota_ctrl.st) {
441         case OTA_ST_START: {
442             /* ota start response */
443             if (g_tx_ccc_value != CCC_VALUE_NOTIFY) {
444                 aos_msleep(10);
445                 ota_status_change(OTA_ST_START);
446             } else {
447                 conn_param_t param = {
448                     0x06,
449                     0x06,
450                     0,
451                     100,
452                 };
453                 ble_stack_connect_param_update(g_conn_hanlde, &param);
454 
455                 uint8_t send_buf[4]  = {0xff, 0x01, 0x01, 0xfe};
456                 ble_stack_gatt_notificate(g_conn_hanlde, g_yoc_ota_handle + YOC_OTA_IDX_TX_VAL, send_buf, sizeof(send_buf));
457                 ota_status_change(OTA_ST_REQUEST);
458             }
459         }
460         break;
461 
462         case OTA_ST_REQUEST: {
463             uint32_t offset;
464             offset = ota_ctrl.packet_size * ota_ctrl.recv_packet_count;
465             ota_ctrl.retry_count++;
466 
467             if (ota_ctrl.retry_count > 10) {
468                 LOGE(TAG, "out of max try count %d", ota_ctrl.retry_count);
469                 ota_reset();
470                 ota_status_change(OTA_ST_IDLE);
471                 ble_stack_disconnect(g_conn_hanlde);
472                 return;
473             }
474 
475             ota_request(offset);
476 
477             ota_status_change(OTA_ST_DL);
478 
479         }
480         break;
481 
482         case OTA_ST_FLASH: {
483             ota_ctrl.retry_count = 0;
484 
485             ota_partition_write(ota_rx.rx_buf, ota_rx.rx_len, ota_ctrl.recv_packet_count * ota_ctrl.packet_size);
486 
487             ota_ctrl.recv_packet_count++;
488 
489             if (ota_ctrl.recv_packet_count < ota_ctrl.expect_packet_count) {
490                 ota_status_change(OTA_ST_REQUEST);
491             } else {
492                 LOGI(TAG, "all packet recv, %d", ota_ctrl.recv_packet_count);
493                 ota_status_change(OTA_ST_COMPLETE);
494             }
495         }
496         break;
497 
498         case OTA_ST_STOP: {
499             LOGI(TAG, "ota stop");
500             /* may disconnect */
501 
502             ota_status_change(OTA_ST_IDLE);
503         }
504         break;
505 
506         case OTA_ST_COMPLETE: {
507             LOGI(TAG, "ota reboot");
508             /* may disconnect */
509             /* ota start response */
510             uint8_t send_buf[4]  = {0xff, 0x04, 0x00, 0xfe};
511             ble_stack_gatt_notificate(g_conn_hanlde, g_yoc_ota_handle + YOC_OTA_IDX_TX_VAL, send_buf, sizeof(send_buf));
512             extern void mdelay(uint32_t ms);
513             mdelay(100);
514 
515             aos_reboot();
516         }
517         break;
518 
519         default:
520             break;
521     }
522 }
523 
ota_timeout(void * arg1,void * arg2)524 static void ota_timeout(void *arg1, void *arg2)
525 {
526     ota_reset_rx();
527     ota_status_change(OTA_ST_REQUEST);
528     LOGW(TAG, "timeout");
529 }
530 
ble_ota_init(ota_event_callback_t cb)531 int ble_ota_init(ota_event_callback_t cb)
532 {
533     int ret;
534 
535     init_param_t init = {
536         .dev_name     = NULL,
537         .dev_addr     = NULL,
538         .conn_num_max = 1,
539     };
540 
541     ble_stack_init(&init);
542 
543     ble_stack_event_register(&ble_ota_cb);
544 
545     ret = ble_stack_gatt_registe_service(&uart_service, uart_attrs, BLE_ARRAY_NUM(uart_attrs));
546 
547     if (ret < 0) {
548         return 0;
549     }
550 
551     g_yoc_ota_handle = ret;
552 
553     if (ota_partition_handle < 0) {
554         ota_partition_handle = partition_open("misc");
555 
556         if (ota_partition_handle < 0) {
557             LOGD(TAG, "ota partition open fail %d", ret);
558         }
559 
560         ota_partition_info = hal_flash_get_info(ota_partition_handle);
561     }
562 
563     aos_timer_new_ext(&ota_ctrl.timer, ota_timeout, NULL, 1000, 0, 0);
564 
565     ota_reset();
566 
567     ota_partition_erase();
568 
569     ota_ctrl.cb = cb;
570 
571     return 0;
572 }
573 
574