• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 #include "common/utility.h"
19 #include "drivers.h"
20 #include "myudb.h"
21 #include "myudb_usbdesc.h"
22 #include <string.h>
23 
24 #if (VCD_EN || DUMP_STR_EN)
25 
26 typedef struct myudb_cfg {
27     u16 id;
28     u16 response_len;
29 
30     u8 *response;
31     u32 tick_sync;
32 
33     u8 stall;
34     u8 rptr;
35     u16 cmd_len;
36 } myudb_cfg_t;
37 
38 myudb_cfg_t myudb = {0x120};
39 
40 static USB_Request_Header_t control_request;
41 
42 my_fifo_t *myudb_print_fifo = 0;
43 
44 //		USB device handling
45 // -----------------------------------------------------------------------------------------
46 enum {
47     MYUDB_USB_IRQ_SETUP_REQ = 0,
48     MYUDB_USB_IRQ_DATA_REQ,
49 };
50 
51 // -----------------------------------------------------------------------------------------
myudb_usb_send_response(void)52 void myudb_usb_send_response(void)
53 {
54     u16 n;
55     if (myudb.response_len < 8) {
56         n = myudb.response_len;
57     } else {
58         n = 8;
59     }
60     myudb.response_len -= n;
61     usbhw_reset_ctrl_ep_ptr();
62     while (n-- > 0) {
63         usbhw_write_ctrl_ep_data(*myudb.response);
64         ++myudb.response;
65     }
66 }
67 
myudb_usb_prepare_desc_data(void)68 void myudb_usb_prepare_desc_data(void)
69 {
70     u8 value_l = (control_request.wValue) & 0xff;
71     u8 value_h = (control_request.wValue >> 8) & 0xff;
72 
73     myudb.response = 0;
74     myudb.response_len = 0;
75 
76     switch (value_h) {
77         case DTYPE_Device:
78             myudb.response = myudb_usbdesc_get_device();
79             myudb.response_len = sizeof(USB_Descriptor_Device_t);
80             break;
81 
82         case DTYPE_Configuration:
83             myudb.response = myudb_usbdesc_get_configuration();
84             myudb.response_len = sizeof(MYUDB_USB_Descriptor_Configuration_t);
85             break;
86 
87         case DTYPE_String:
88             if (MYUDB_USB_STRING_LANGUAGE == value_l) {
89                 myudb.response = myudb_usbdesc_get_language();
90                 myudb.response_len = sizeof(LANGUAGE_ID_ENG);
91             } else if (MYUDB_USB_STRING_VENDOR == value_l) {
92                 myudb.response = myudb_usbdesc_get_vendor();
93                 myudb.response_len = sizeof(MYUDB_STRING_VENDOR);
94             } else if (MYUDB_USB_STRING_PRODUCT == value_l) {
95                 myudb.response = myudb_usbdesc_get_product();
96                 myudb.response_len = sizeof(MYUDB_STRING_PRODUCT);
97             } else if (MYUDB_USB_STRING_SERIAL == value_l) {
98                 myudb.response = myudb_usbdesc_get_serial();
99                 myudb.response_len = sizeof(MYUDB_STRING_SERIAL);
100             } else {
101                 myudb.stall = 1;
102             }
103             break;
104 
105         default:
106             myudb.stall = 1;
107             break;
108     }
109 
110     if (control_request.wLength < myudb.response_len) {
111         myudb.response_len = control_request.wLength;
112     }
113 
114     return;
115 }
116 
myudb_usb_handle_in_class_intf_req()117 void myudb_usb_handle_in_class_intf_req()
118 {
119     u8 property = control_request.bRequest;
120     switch (property) {
121         case 0x00:
122             usbhw_write_ctrl_ep_data(0x00);
123             break;
124         default:
125             myudb.stall = 1;
126             break;
127     }
128 }
129 
myudb_usb_handle_request(u8 data_request)130 void myudb_usb_handle_request(u8 data_request)
131 {
132     u8 bmRequestType = control_request.bmRequestType;
133     u8 bRequest = control_request.bRequest;
134 
135     usbhw_reset_ctrl_ep_ptr();
136     switch (bmRequestType) {
137         case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
138             if (REQ_GetDescriptor == bRequest) {
139                 if (MYUDB_USB_IRQ_SETUP_REQ == data_request) {
140                     myudb_usb_prepare_desc_data();
141                 }
142                 myudb_usb_send_response();
143             }
144             break;
145         case (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE):
146             myudb_usb_handle_in_class_intf_req();
147             break;
148         case (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_INTERFACE):
149             if (MYUDB_USB_IRQ_SETUP_REQ == data_request) {
150                 if (bRequest == 0xc0) {  // Get board version
151                     usbhw_reset_ctrl_ep_ptr();
152                     usbhw_write_ctrl_ep_data(myudb.id);
153                     usbhw_write_ctrl_ep_data(myudb.id >> 8);
154                 } else {
155                     myudb.stall = 1;
156                 }
157             }
158             break;
159         case (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE):  // 0xc0
160             if (MYUDB_USB_IRQ_SETUP_REQ == data_request) {
161                 if (bRequest == 0xc0) {  // Get board version
162                     usbhw_reset_ctrl_ep_ptr();
163                     usbhw_write_ctrl_ep_data(0x40);
164                     usbhw_write_ctrl_ep_data(0x25);
165                     usbhw_write_ctrl_ep_data(0x40);
166                     usbhw_write_ctrl_ep_data(0x05);
167                     usbhw_write_ctrl_ep_data(0x03);
168                     usbhw_write_ctrl_ep_data(0x00);
169                     usbhw_write_ctrl_ep_data(0x01);
170                     usbhw_write_ctrl_ep_data(0x00);
171                 } else if (bRequest == 0xc6) {  //
172                     usbhw_reset_ctrl_ep_ptr();
173                     usbhw_write_ctrl_ep_data(0x04);
174                 } else {
175                     myudb.stall = 1;
176                 }
177             }
178             break;
179         case (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE):  // 0x40
180             myudb.stall = 1;
181             break;
182         default:
183             myudb.stall = 1;
184             break;
185     }
186 
187     return;
188 }
189 
myudb_usb_handle_ctl_ep_setup()190 void myudb_usb_handle_ctl_ep_setup()
191 {
192     usbhw_reset_ctrl_ep_ptr();
193     control_request.bmRequestType = usbhw_read_ctrl_ep_data();
194     control_request.bRequest = usbhw_read_ctrl_ep_data();
195     control_request.wValue = usbhw_read_ctrl_ep_u16();
196     control_request.wIndex = usbhw_read_ctrl_ep_u16();
197     control_request.wLength = usbhw_read_ctrl_ep_u16();
198     myudb.stall = 0;
199     myudb_usb_handle_request(MYUDB_USB_IRQ_SETUP_REQ);
200     if (myudb.stall)
201         usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_STALL);
202     else
203         usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK);
204 }
205 
myudb_usb_handle_ctl_ep_data(void)206 void myudb_usb_handle_ctl_ep_data(void)
207 {
208     usbhw_reset_ctrl_ep_ptr();
209     myudb.stall = 0;
210     myudb_usb_handle_request(MYUDB_USB_IRQ_DATA_REQ);
211     if (myudb.stall)
212         usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_STALL);
213     else
214         usbhw_write_ctrl_ep_ctrl(FLD_EP_DAT_ACK);
215 }
216 
myudb_usb_handle_ctl_ep_status()217 void myudb_usb_handle_ctl_ep_status()
218 {
219     if (myudb.stall)
220         usbhw_write_ctrl_ep_ctrl(FLD_EP_STA_STALL);
221     else
222         usbhw_write_ctrl_ep_ctrl(FLD_EP_STA_ACK);
223 }
224 
myudb_print_fifo_full(void)225 _attribute_ram_code_ int myudb_print_fifo_full(void)
226 {
227     u8 n = myudb_print_fifo->wptr - myudb_print_fifo->rptr;
228     return n >= myudb_print_fifo->num;
229 }
230 
usb_send_status_pkt(u8 status,u8 buffer_num,u8 * pkt,u16 len)231 _attribute_ram_code_ void usb_send_status_pkt(u8 status, u8 buffer_num, u8 *pkt, u16 len)
232 {
233     u8 *p = myudb_print_fifo->p + (myudb_print_fifo->wptr & (myudb_print_fifo->num - 1)) * myudb_print_fifo->size;
234     if (len > 272) {
235         len = 272;
236     }
237     *p++ = len + 2;
238     *p++ = (len + 2) >> 8;
239     p += 2;
240     *p++ = status;
241     *p++ = buffer_num;
242     while (len--) {
243         *p++ = *pkt++;
244     }
245     myudb_print_fifo->wptr++;
246 }
247 
usb_send_str_data(char * str,u8 * ph,int n)248 _attribute_ram_code_ void usb_send_str_data(char *str, u8 *ph, int n)
249 {
250     u32 rie = core_interrupt_disable();
251     u8 *ps = myudb_print_fifo->p + (myudb_print_fifo->wptr & (myudb_print_fifo->num - 1)) * myudb_print_fifo->size;
252     ;
253     u8 *pd = ps;
254 
255     int ns = str ? strlen(str) : 0;
256     if (ns > myudb_print_fifo->size - 12) {
257         ns = myudb_print_fifo->size - 12;
258         n = 0;
259     }
260     if (n + ns > myudb_print_fifo->size - 12) {
261         n = myudb_print_fifo->size - 12 - ns;
262     }
263 
264     int len = n + ns + 2 + 3;
265     *pd++ = len;
266     *pd++ = len >> 8;
267     *pd++ = 0;
268     *pd++ = 0;
269     *pd++ = 0x82;
270     *pd++ = 8;
271 
272     *pd++ = 0x22;
273     *pd++ = n;
274     *pd++ = n >> 8;
275 
276     while (n--) {
277         *pd++ = *ph++;
278     }
279     while (ns--) {
280         *pd++ = *str++;
281     }
282     myudb_print_fifo->wptr++;
283     core_restore_interrupt(rie);
284 }
285 
usb_send_str_u32s(char * str,u32 d0,u32 d1,u32 d2,u32 d3)286 _attribute_ram_code_ void usb_send_str_u32s(char *str, u32 d0, u32 d1, u32 d2, u32 d3)
287 {
288     u32 d[4];
289     d[0] = d0;
290     d[1] = d1;
291     d[2] = d2;
292     d[3] = d3;
293     usb_send_str_data(str, (u8 *)d, 16);
294 }
295 
myudb_to_usb()296 _attribute_ram_code_ void myudb_to_usb()
297 {
298     static u16 len = 0;
299     static u8 *p = 0;
300 
301     if (usbhw_is_ep_busy(MYUDB_EDP_IN_HCI))
302         return;
303     if (!p && (myudb_print_fifo->wptr != myudb_print_fifo->rptr)) {  // first packet
304         p = myudb_print_fifo->p + (myudb_print_fifo->rptr++ & (myudb_print_fifo->num - 1)) * myudb_print_fifo->size;
305         len = p[0] + p[1] * 256;
306         p += 4;
307     }
308     if (p) {
309         int n = len < 64 ? len : 64;
310         usbhw_reset_ep_ptr(MYUDB_EDP_IN_HCI);
311         for (int i = 0; i < n; i++) {
312             usbhw_write_ep_data(MYUDB_EDP_IN_HCI, *p++);
313         }
314         usbhw_data_ep_ack(MYUDB_EDP_IN_HCI);
315         len -= n;
316         if (n < 64) {
317             p = 0;
318         }
319     }
320 }
321 
usb_send_str_int(char * str,int w)322 int usb_send_str_int(char *str, int w)
323 {
324     if (myudb_print_fifo_full()) {
325         return -1;
326     }
327     int len;
328 
329     u32 rie = core_interrupt_disable();
330     char buf[13], tmp, *p;
331     int u;
332     char symbol = ' ';
333     int int_len = 0;
334     int n = strlen(str);
335     if (n == 0) {
336         return -2;
337     }
338 
339     p = buf + 12;
340     *p = '\0';
341     u = w;
342     if (w < 0) {
343         symbol = '-';
344         u = -w;
345     }
346     do {  // at least one time..
347         tmp = u % 10;
348         *--p = tmp + '0';
349         u /= 10;
350         int_len++;
351     } while (u);
352 
353     u8 *pd = myudb_print_fifo->p + (myudb_print_fifo->wptr & (myudb_print_fifo->num - 1)) * myudb_print_fifo->size;
354     len = n + 2 + 1 + 1 + int_len;  // str_len + '0x20' + symbol + int_len
355     *pd++ = len;
356     *pd++ = len >> 8;
357 
358     *pd++ = 0;
359     *pd++ = 0;
360     *pd++ = 0x82;
361     *pd++ = 8;
362 
363     *pd++ = 0x20;
364     while (n--) {
365         *pd++ = *str++;
366     }
367     *pd++ = symbol;
368     while (int_len--) {
369         *pd++ = *p++;
370     }
371     myudb_print_fifo->wptr++;
372     core_restore_interrupt(rie);
373     return len;
374 }
375 
376 #define USB_ENDPOINT_BULK_OUT_FLAG (1 << (MYUDB_EDP_OUT_HCI & 7))
377 
myudb_usb_get_packet(u8 * p)378 _attribute_ram_code_ int myudb_usb_get_packet(u8 *p)
379 {
380     if (reg_usb_irq & USB_ENDPOINT_BULK_OUT_FLAG) {
381         // clear interrupt flag
382         reg_usb_irq = USB_ENDPOINT_BULK_OUT_FLAG;
383 
384         // read data
385         int n = reg_usb_ep_ptr(MYUDB_EDP_OUT_HCI);
386         reg_usb_ep_ptr(MYUDB_EDP_OUT_HCI) = 0;
387         for (int i = 0; i < n; i++) {
388             p[myudb.cmd_len++] = reg_usb_ep_dat(MYUDB_EDP_OUT_HCI);
389         }
390         reg_usb_ep_ctrl(MYUDB_EDP_OUT_HCI) = 1;  // ACK
391         if (n < 64) {
392             n = myudb.cmd_len;
393             myudb.cmd_len = 0;
394             return n;
395         }
396     }
397     return 0;
398 }
399 
400 func_myudb_hci_cmd_cb_t myudb_hci_cmd_cb = 0;
401 
myudb_register_hci_cb(void * p)402 void myudb_register_hci_cb(void *p)
403 {
404     myudb_hci_cmd_cb = p;
405 }
406 
407 func_myudb_hci_cmd_cb_t myudb_hci_debug_cb = 0;
myudb_register_hci_debug_cb(void * p)408 void myudb_register_hci_debug_cb(void *p)
409 {
410     myudb_hci_debug_cb = p;
411 }
412 
413 #define MYHCI_FW_DOWNLOAD 0xfe
414 int fw_download = 0;
415 
myudb_mem_cmd(u8 * p,int nbyte)416 _attribute_ram_code_ int myudb_mem_cmd(u8 *p, int nbyte)
417 {
418     int len = nbyte;
419     int cmd = p[0];
420     u8 rsp[280];
421 
422     int ret = 0;
423 
424     //////////////////////////  Memory Read ////////////////////////////////////
425     if (cmd == 0x28 && len >= 8) {
426         usb_send_status_pkt(0x81, 8, p, 12);
427         rsp[0] = 0x29;
428         memcpy(rsp + 1, p + 1, 5);
429         int type = p[1];
430         u32 adr = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
431         int n = p[6] | (p[7] << 8);
432         if (n > 256) {
433             n = 256;
434         }
435 
436         if (type == 0) {
437             memcpy(rsp + 6, (void *)(adr | 0), n);
438         } else if (type == 1) {
439             for (int i = 0; i < n; i++) {
440                 rsp[i + 6] = analog_read_reg8(adr + i);
441             }
442         } else if (type == 2 || type == 3) {
443             // flash
444             flash_read_page(adr, n, rsp + 6);
445         }
446 
447         usb_send_status_pkt(0x82, 8, rsp, n + 6);
448     } else if (cmd == 0x2a && len > 6) {
449         //////////////////////////  Memory Write ////////////////////////////////////
450         usb_send_status_pkt(0x81, 8, p, 12);
451         rsp[0] = 0x2b;
452         memcpy(rsp + 1, p + 1, 16);
453         u8 type = p[1];
454         u32 adr = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);
455         int n = len - 6;
456 
457         if (type == 0) {  // RAM
458             memcpy((void *)adr, p + 6, n);
459         } else if (type == 1) {  // Analog Register
460             for (int i = 0; i < n; i++) {
461                 analog_write_reg8(adr + i, p[i + 6]);
462             }
463         } else if (type == 2) {  // flash
464             if (fw_download && (adr & 0xfff) == 0) {
465                 flash_erase_sector(adr);
466             }
467             flash_write_page(adr, n, p + 6);
468         } else if (type == 3) {
469             int nb = p[6];
470             if (n > 1)
471                 nb += p[7] << 8;
472             if (n > 2)
473                 nb += p[8] << 16;
474             if (n > 3)
475                 nb += p[9] << 24;
476 
477             if (nb) {
478                 for (int i = 0; i < nb; i += 4096) {
479                     flash_erase_sector(adr + i);
480                 }
481             } else {
482                 flash_erase_chip();
483             }
484         } else if (type == MYHCI_FW_DOWNLOAD) {
485             core_interrupt_disable();
486 
487             myudb_print_fifo->rptr = myudb_print_fifo->wptr;
488             ret = MYHCI_FW_DOWNLOAD;
489         }
490         usb_send_status_pkt(0x82, 8, rsp, 14);
491     } else {
492         ret = 1;
493     }
494     return ret;
495 }
496 
497 u8 buff_usb_cmd[320];
myudb_hci_cmd_from_usb(void)498 _attribute_ram_code_ int myudb_hci_cmd_from_usb(void)
499 {
500     fw_download = 0;
501     do {
502         int n = myudb_usb_get_packet(buff_usb_cmd);
503         if (n) {
504             int r = myudb_mem_cmd(buff_usb_cmd, n);
505             if (r == MYHCI_FW_DOWNLOAD) {
506                 fw_download = MYHCI_FW_DOWNLOAD;
507             } else if (buff_usb_cmd[0] == 0x11 && myudb_hci_debug_cb && !fw_download) {
508                 myudb_hci_debug_cb(buff_usb_cmd, n);
509             } else if (r && myudb_hci_cmd_cb && !fw_download) {
510                 myudb_hci_cmd_cb(buff_usb_cmd, n);
511             }
512         }
513         if (fw_download) {
514             myudb_to_usb();
515         }
516     } while (fw_download);
517 
518     return 0;
519 }
520 
udb_usb_handle_irq(void)521 void udb_usb_handle_irq(void)
522 {
523     if (1) {  // do nothing when in suspend. Maybe not unnecessary
524         u32 irq = usbhw_get_ctrl_ep_irq();
525         if (irq & FLD_CTRL_EP_IRQ_SETUP) {
526             usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_SETUP);
527             myudb_usb_handle_ctl_ep_setup();
528             if (!myudb.tick_sync) {
529                 myudb.tick_sync = clock_time() | 1;
530             }
531         }
532         if (irq & FLD_CTRL_EP_IRQ_DATA) {
533             usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_DATA);
534             myudb_usb_handle_ctl_ep_data();
535         }
536         if (irq & FLD_CTRL_EP_IRQ_STA) {
537             usbhw_clr_ctrl_ep_irq(FLD_CTRL_EP_IRQ_STA);
538             myudb_usb_handle_ctl_ep_status();
539         }
540 
541         if (reg_usb_irq_mask & FLD_USB_IRQ_RESET_O) {
542             reg_usb_irq_mask |= FLD_USB_IRQ_RESET_O;  // Clear USB reset flag
543             myudb_usb_bulkout_ready();
544         }
545         myudb.stall = 0;
546     }
547 
548     myudb_to_usb();
549 
550     myudb_hci_cmd_from_usb();
551 
552     if (myudb.tick_sync && clock_time_exceed(myudb.tick_sync, 10000)) {
553         myudb.tick_sync = clock_time() | 1;
554         log_sync(SL_STACK_EN);
555     }
556 }
557 
myudb_usb_bulkout_ready(void)558 void myudb_usb_bulkout_ready(void)
559 {
560     reg_usb_ep_ctrl(MYUDB_EDP_OUT_HCI) = FLD_EP_DAT_ACK;
561 }
562 
myudb_usb_init(u16 id,void * p_print)563 void myudb_usb_init(u16 id, void *p_print)
564 {
565     if (!myudb_print_fifo) {
566         myudb_print_fifo = p_print;
567     }
568 
569     myudb_print_fifo->wptr = myudb_print_fifo->rptr = 0;
570 
571     memset(&myudb, 0, sizeof(myudb));
572 
573     myudb.id = id;
574     reg_usb_ep_max_size = (128 >> 2);
575     reg_usb_ep8_send_thre = 0x40;
576     reg_usb_ep8_send_max = 128 >> 3;
577     reg_usb_ep_buf_addr(MYUDB_EDP_IN_HCI) = 128;
578     reg_usb_ep_buf_addr(MYUDB_EDP_OUT_HCI) = 192;
579     reg_usb_ep_buf_addr(MYUDB_EDP_IN_VCD) = 0;
580     reg_usb_ep8_fifo_mode = 1;
581     reg_usb_mdev &= ~BIT(3);  // vendor command: bRequest[7] = 0
582 
583     usbhw_enable_manual_interrupt(FLD_CTRL_EP_AUTO_STD | FLD_CTRL_EP_AUTO_DESC);
584 
585     myudb_usb_bulkout_ready();
586     usbhw_data_ep_ack(MYUDB_EDP_IN_HCI);  // add log 1st log info
587 }
588 
usb_send_upper_tester_result(u8 err)589 _attribute_ram_code_ void usb_send_upper_tester_result(u8 err)
590 {
591     u32 rie = core_interrupt_disable();
592     u8 *ps = myudb_print_fifo->p + (myudb_print_fifo->wptr & (myudb_print_fifo->num - 1)) * myudb_print_fifo->size;
593     ;
594 
595     *((u32 *)ps) = 3;
596     u8 *pd = (ps + 4);
597 
598     *pd++ = 0x04;  // HCI_TYPE_EVENT;
599     *pd++ = 0xF0;  // HCI_EVT_HT_ERR_FLAG;
600     *pd++ = err;
601 
602     myudb_print_fifo->wptr++;
603     core_restore_interrupt(rie);
604 }
605 
606 #endif  // ending of #if(VCD_EN || DUMP_STR_EN)
607