1 From fa51192b912d296b8eec10f7d44c6c17eb1dd368 Mon Sep 17 00:00:00 2001
2 From: Xiangfu <xiangfu@openmobilefree.net>
3 Date: Fri, 12 Oct 2012 09:47:39 +0800
4 Subject: [PATCH 2/6] qi_lb60: add software usbboot support
6 JZ4740 CPU have a internal ROM have such kind of code, that make
7 JZ4740 can boot from USB
9 usbboot.S can downloads user program from the USB port to internal
10 SRAM and branches to the internal SRAM to execute the program
12 Signed-off-by: Xiangfu <xiangfu@openmobilefree.net>
14 board/qi/qi_lb60/Makefile | 1 +
15 board/qi/qi_lb60/qi_lb60-spl.c | 20 +
16 board/qi/qi_lb60/usbboot.S | 838 ++++++++++++++++++++++++++++++++++++++++
17 3 files changed, 859 insertions(+)
18 create mode 100644 board/qi/qi_lb60/usbboot.S
20 diff --git a/board/qi/qi_lb60/Makefile b/board/qi/qi_lb60/Makefile
21 index e399246..6dd8c6f 100644
22 --- a/board/qi/qi_lb60/Makefile
23 +++ b/board/qi/qi_lb60/Makefile
24 @@ -23,6 +23,7 @@ include $(TOPDIR)/config.mk
25 LIB = $(obj)lib$(BOARD).o
27 ifeq ($(CONFIG_SPL_BUILD),y)
29 COBJS := $(BOARD)-spl.o
32 diff --git a/board/qi/qi_lb60/qi_lb60-spl.c b/board/qi/qi_lb60/qi_lb60-spl.c
33 index 3fe3fa3..aea459c 100644
34 --- a/board/qi/qi_lb60/qi_lb60-spl.c
35 +++ b/board/qi/qi_lb60/qi_lb60-spl.c
38 #include <asm/jz4740.h>
40 +#define KEY_U_OUT (32 * 2 + 16)
41 +#define KEY_U_IN (32 * 3 + 19)
43 +extern void usb_boot(void);
45 +static void check_usb_boot(void)
47 + __gpio_as_input(KEY_U_IN);
48 + __gpio_enable_pull(KEY_U_IN);
49 + __gpio_as_output(KEY_U_OUT);
50 + __gpio_clear_pin(KEY_U_OUT);
52 + if (!__gpio_get_pin(KEY_U_IN)) {
53 + puts("[U] pressed, goto USBBOOT mode\n");
58 void nand_spl_boot(void)
60 __gpio_as_sdram_16bit_4720();
61 @@ -23,6 +41,8 @@ void nand_spl_boot(void)
69 puts("\nQi LB60 SPL: Starting U-Boot ...\n");
70 diff --git a/board/qi/qi_lb60/usbboot.S b/board/qi/qi_lb60/usbboot.S
72 index 0000000..c872266
74 +++ b/board/qi/qi_lb60/usbboot.S
77 + * for jz4740 usb boot
79 + * Copyright (c) 2009 Author: <jlwei@ingenic.cn>
81 + * See file CREDITS for list of people who contributed to this
84 + * This program is free software; you can redistribute it and/or
85 + * modify it under the terms of the GNU General Public License as
86 + * published by the Free Software Foundation; either version 2 of
87 + * the License, or (at your option) any later version.
89 + * This program is distributed in the hope that it will be useful,
90 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
91 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92 + * GNU General Public License for more details.
94 + * You should have received a copy of the GNU General Public License
95 + * along with this program; if not, write to the Free Software
96 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
104 + * Both NAND and USB boot load data to D-Cache first, then transfer
105 + * data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
106 + * So init caches first and then dispatch to a proper boot routine.
109 +.macro load_addr reg addr
110 + li \reg, 0x80000000
111 + addiu \reg, \reg, \addr
112 + la $2, usbboot_begin
113 + subu \reg, \reg, $2
117 + /* Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz. */
118 + la $9, 0xB0000000 /* CPCCR: Clock Control Register */
119 + la $8, 0x42041110 /* I:S:M:P=1:2:2:2 */
122 + la $9, 0xB0000010 /* CPPCR: PLL Control Register */
123 + la $8, 0x06000120 /* M=12 N=0 D=0 CLK=12*(M+2)/(N+2) */
126 + mtc0 $0, $26 /* CP0_ERRCTL, restore WST reset state */
129 + mtc0 $0, $16 /* CP0_CONFIG */
132 + /* Relocate code to beginning of the ram */
134 + la $2, usbboot_begin
147 + addiu $3, $3, usbboot_end
148 + la $4, usbboot_begin
153 + cache 0x0, 0($2) /* Index_Invalidate_I */
154 + cache 0x1, 0($2) /* Index_Writeback_Inv_D */
160 + load_addr $3, usb_boot_return
167 + li $2, 3 /* cacheable for kseg0 access */
168 + mtc0 $2, $16 /* CP0_CONFIG */
171 + li $2, 0x20000000 /* enable idx-store-data cache insn */
172 + mtc0 $2, $26 /* CP0_ERRCTL */
174 + ori $2, $28, 0 /* start address */
175 + ori $3, $2, 0x3fe0 /* end address, total 16KB */
176 + mtc0 $0, $28, 0 /* CP0_TAGLO */
177 + mtc0 $0, $28, 1 /* CP0_DATALO */
179 + cache 0x8, 0($2) /* Index_Store_Tag_I */
180 + cache 0x9, 0($2) /* Index_Store_Tag_D */
181 + bne $2, $3, cache_clear_a_line
182 + addiu $2, $2, 32 /* increment CACHE_LINE_SIZE */
184 + ori $2, $28, 0 /* start address */
185 + ori $3, $2, 0x3fe0 /* end address, total 16KB */
186 + la $4, 0x1ffff000 /* physical address and 4KB page mask */
189 + ori $5, $5, 1 /* V bit of the physical tag */
190 + mtc0 $5, $28, 0 /* CP0_TAGLO */
191 + cache 0x8, 0($2) /* Index_Store_Tag_I */
192 + cache 0x9, 0($2) /* Index_Store_Tag_D */
193 + bne $2, $3, cache_alloc_a_line
194 + addiu $2, $2, 32 /* increment CACHE_LINE_SIZE */
200 + * Transfer data from dcache to icache, then jump to icache.
201 + * Input parameters:
202 + * $19: data length in bytes
203 + * $20: jump target address
208 + addu $9, $8, $19 /* total 16KB */
211 + cache 0x0, 0($8) /* Index_Invalidate_I */
212 + cache 0x1, 0($8) /* Index_Writeback_Inv_D */
216 + /* flush write-buffer */
219 + /* Invalidate BTB */
220 + mfc0 $8, $16, 7 /* CP0_CONFIG */
226 + /* Overwrite config to disable ram initalisation */
234 + /* User code can return to here after executing itself in
235 + icache, by jumping to $31. */
241 + /* Enable the USB PHY */
242 + la $9, 0xB0000024 /* CPM_SCR */
244 + ori $8, 0x40 /* USBPHY_ENABLE */
247 + /* Initialize USB registers */
248 + la $27, 0xb3040000 /* USB registers base address */
250 + sb $0, 0x0b($27) /* INTRUSBE: disable common USB interrupts */
251 + sh $0, 0x06($27) /* INTRINE: disable EPIN interrutps */
252 + sh $0, 0x08($27) /* INTROUTE: disable EPOUT interrutps */
255 + sb $9, 0x01($27) /* POWER: HSENAB | SUSPENDM | SOFTCONN */
257 + /* Initialize USB states */
258 + li $22, 0 /* set EP0 to IDLE state */
259 + li $23, 1 /* no data stage */
261 + /* Main loop of polling the usb commands */
263 + lbu $9, 0x0a($27) /* read INTRUSB */
264 + andi $9, 0x04 /* check USB_INTR_RESET */
265 + beqz $9, check_intr_ep0in
268 + /* 1. Handle USB reset interrupt */
270 + lbu $9, 0x01($27) /* read POWER */
271 + andi $9, 0x10 /* test HS_MODE */
272 + bnez $9, _usb_set_maxpktsize
273 + li $9, 512 /* max packet size of HS mode */
274 + li $9, 64 /* max packet size of FS mode */
276 +_usb_set_maxpktsize:
278 + sb $8, 0x0e($27) /* set INDEX 1 */
280 + sh $9, 0x10($27) /* INMAXP */
281 + sb $0, 0x13($27) /* INCSRH */
282 + sh $9, 0x14($27) /* OUTMAXP */
283 + sb $0, 0x17($27) /* OUTCSRH */
286 + li $8, 0x48 /* INCSR_CDT && INCSR_FF */
287 + sb $8, 0x12($27) /* INCSR */
288 + li $8, 0x90 /* OUTCSR_CDT && OUTCSR_FF */
289 + sb $8, 0x16($27) /* OUTCSR */
291 + li $22, 0 /* set EP0 to IDLE state */
292 + li $23, 1 /* no data stage */
294 + /* 2. Check and handle EP0 interrupt */
296 + lhu $10, 0x02($27) /* read INTRIN */
297 + andi $9, $10, 0x1 /* check EP0 interrupt */
298 + beqz $9, check_intr_ep1in
302 + sb $0, 0x0e($27) /* set INDEX 0 */
303 + lbu $11, 0x12($27) /* read CSR0 */
305 + andi $9, $11, 0x04 /* check SENTSTALL */
306 + beqz $9, _ep0_setupend
311 + sb $9, 0x12($27) /* clear SENDSTALL and SENTSTALL */
312 + li $22, 0 /* set EP0 to IDLE state */
315 + andi $9, $11, 0x10 /* check SETUPEND */
316 + beqz $9, ep0_idle_state
320 + sb $9, 0x12($27) /* set SVDSETUPEND */
321 + li $22, 0 /* set EP0 to IDLE state */
324 + bnez $22, ep0_tx_state
327 + /* 2.1 Handle EP0 IDLE state interrupt */
328 + andi $9, $11, 0x01 /* check OUTPKTRDY */
329 + beqz $9, check_intr_ep1in
332 + /* Read 8-bytes setup packet from the FIFO */
333 + lw $25, 0x20($27) /* first word of setup packet */
334 + lw $26, 0x20($27) /* second word of setup packet */
336 + andi $9, $25, 0x60 /* bRequestType & USB_TYPE_MASK */
337 + beqz $9, _ep0_std_req
340 + /* 2.1.1 Vendor-specific setup request */
342 + li $22, 0 /* set EP0 to IDLE state */
343 + li $23, 1 /* NoData = 1 */
345 + andi $9, $25, 0xff00 /* check bRequest */
347 + beqz $9, __ep0_get_cpu_info
349 + beqz $8, __ep0_set_data_address
351 + beqz $8, __ep0_set_data_length
353 + beqz $8, __ep0_flush_caches
355 + beqz $8, __ep0_prog_start1
357 + beqz $8, __ep0_prog_start2
359 + b _ep0_idle_state_fini /* invalid request */
363 + load_addr $20, cpu_info_data /* data pointer to transfer */
364 + li $21, 8 /* bytes left to transfer */
365 + li $22, 1 /* set EP0 to TX state */
366 + li $23, 0 /* NoData = 0 */
368 + b _ep0_idle_state_fini
371 +__ep0_set_data_address:
374 + andi $8, $26, 0xffff
375 + or $20, $9, $8 /* data address of next transfer */
377 + b _ep0_idle_state_fini
380 +__ep0_set_data_length:
383 + andi $8, $26, 0xffff
384 + or $21, $9, $8 /* data length of next transfer */
386 + li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */
387 + sb $9, 0x12($27) /* CSR0 */
389 + /* We must write packet to FIFO before EP1-IN interrupt here. */
390 + b handle_epin1_intr
394 + /* Flush dcache and invalidate icache. */
396 + addi $9, $8, 0x3fe0 /* total 16KB */
399 + cache 0x0, 0($8) /* Index_Invalidate_I */
400 + cache 0x1, 0($8) /* Index_Writeback_Inv_D */
404 + /* flush write-buffer */
407 + /* Invalidate BTB */
408 + mfc0 $8, $16, 7 /* CP0_CONFIG */
414 + b _ep0_idle_state_fini
418 + li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */
419 + sb $9, 0x12($27) /* CSR0 */
423 + andi $8, $26, 0xffff
424 + or $20, $9, $8 /* target address */
427 + li $19, 0x2000 /* 16KB data length */
430 + li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */
431 + sb $9, 0x12($27) /* CSR0 */
435 + andi $8, $26, 0xffff
436 + or $20, $9, $8 /* target address */
438 + jalr $20 /* jump, and place the return address in $31 */
441 +__ep0_prog_start2_return:
442 +/* User code can return to here after executing itself, by jumping to $31 */
446 + /* 2.1.2 Standard setup request */
448 + andi $12, $25, 0xff00 /* check bRequest */
450 + sub $9, $12, 0x05 /* check USB_REQ_SET_ADDRESS */
451 + bnez $9, __ep0_req_set_config
454 + /* Handle USB_REQ_SET_ADDRESS */
456 + srl $9, $25, 16 /* get wValue */
457 + sb $9, 0x0($27) /* set FADDR */
458 + li $23, 1 /* NoData = 1 */
459 + b _ep0_idle_state_fini
462 +__ep0_req_set_config:
463 + sub $9, $12, 0x09 /* check USB_REQ_SET_CONFIGURATION */
464 + bnez $9, __ep0_req_get_desc
467 + /* Handle USB_REQ_SET_CONFIGURATION */
468 + li $23, 1 /* NoData = 1 */
469 + b _ep0_idle_state_fini
473 + sub $9, $12, 0x06 /* check USB_REQ_GET_DESCRIPTOR */
474 + bnez $9, _ep0_idle_state_fini
475 + li $23, 1 /* NoData = 1 */
477 + /* Handle USB_REQ_GET_DESCRIPTOR */
478 + li $23, 0 /* NoData = 0 */
480 + srl $9, $25, 24 /* wValue >> 8 */
481 + sub $8, $9, 0x01 /* check USB_DT_DEVICE */
482 + beqz $8, ___ep0_get_dev_desc
483 + srl $21, $26, 16 /* get wLength */
484 + sub $8, $9, 0x02 /* check USB_DT_CONFIG */
485 + beqz $8, ___ep0_get_conf_desc
486 + sub $8, $9, 0x03 /* check USB_DT_STRING */
487 + beqz $8, ___ep0_get_string_desc
488 + sub $8, $9, 0x06 /* check USB_DT_DEVICE_QUALIFIER */
489 + beqz $8, ___ep0_get_dev_qualifier
491 + b _ep0_idle_state_fini
494 +___ep0_get_dev_desc:
495 + load_addr $20, device_desc /* data pointer */
496 + li $22, 1 /* set EP0 to TX state */
498 + blez $8, _ep0_idle_state_fini /* wLength <= 18 */
500 + li $21, 18 /* max length of device_desc */
501 + b _ep0_idle_state_fini
504 +___ep0_get_dev_qualifier:
505 + load_addr $20, dev_qualifier /* data pointer */
506 + li $22, 1 /* set EP0 to TX state */
508 + blez $8, _ep0_idle_state_fini /* wLength <= 10 */
510 + li $21, 10 /* max length of dev_qualifier */
511 + b _ep0_idle_state_fini
514 +___ep0_get_conf_desc:
515 + load_addr $20, config_desc_fs /* data pointer of FS mode */
516 + lbu $8, 0x01($27) /* read POWER */
517 + andi $8, 0x10 /* test HS_MODE */
518 + beqz $8, ___ep0_get_conf_desc2
520 + load_addr $20, config_desc_hs /* data pointer of HS mode */
522 +___ep0_get_conf_desc2:
523 + li $22, 1 /* set EP0 to TX state */
525 + blez $8, _ep0_idle_state_fini /* wLength <= 32 */
527 + li $21, 32 /* max length of config_desc */
528 + b _ep0_idle_state_fini
531 +___ep0_get_string_desc:
532 + li $22, 1 /* set EP0 to TX state */
534 + srl $9, $25, 16 /* wValue & 0xff */
538 + beqz $8, ___ep0_get_string_manufacture
540 + beqz $8, ___ep0_get_string_product
543 +___ep0_get_string_lang_ids:
544 + load_addr $20, string_lang_ids /* data pointer */
545 + b _ep0_idle_state_fini
546 + li $21, 4 /* data length */
548 +___ep0_get_string_manufacture:
549 + load_addr $20, string_manufacture /* data pointer */
550 + b _ep0_idle_state_fini
551 + li $21, 16 /* data length */
553 +___ep0_get_string_product:
554 + load_addr $20, string_product /* data pointer */
555 + b _ep0_idle_state_fini
556 + li $21, 46 /* data length */
558 +_ep0_idle_state_fini:
559 + li $9, 0x40 /* SVDOUTPKTRDY */
560 + beqz $23, _ep0_idle_state_fini2
562 + ori $9, $9, 0x08 /* DATAEND */
563 +_ep0_idle_state_fini2:
564 + sb $9, 0x12($27) /* CSR0 */
565 + beqz $22, check_intr_ep1in
568 + /* 2.2 Handle EP0 TX state interrupt */
571 + bnez $9, check_intr_ep1in
574 + sub $9, $21, 64 /* max packetsize */
575 + blez $9, _ep0_tx_state2 /* data count <= 64 */
580 + beqz $19, _ep0_tx_state3 /* send ZLP */
581 + ori $18, $19, 0 /* record bytes to be transferred */
582 + sub $21, $21, $19 /* decrement data count */
584 +_ep0_fifo_write_loop:
585 + lbu $9, 0($20) /* read data */
586 + sb $9, 0x20($27) /* load FIFO */
587 + sub $19, $19, 1 /* decrement counter */
588 + bnez $19, _ep0_fifo_write_loop
589 + addi $20, $20, 1 /* increment data pointer */
591 + sub $9, $18, 64 /* max packetsize */
592 + beqz $9, _ep0_tx_state4
596 + /* transferred bytes < max packetsize */
597 + li $9, 0x0a /* set INPKTRDY and DATAEND */
598 + sb $9, 0x12($27) /* CSR0 */
599 + li $22, 0 /* set EP0 to IDLE state */
604 + /* transferred bytes == max packetsize */
605 + li $9, 0x02 /* set INPKTRDY */
606 + sb $9, 0x12($27) /* CSR0 */
610 + /* 3. Check and handle EP1 BULK-IN interrupt */
612 + andi $9, $10, 0x2 /* check EP1 IN interrupt */
613 + beqz $9, check_intr_ep1out
618 + sb $9, 0x0e($27) /* set INDEX 1 */
619 + lbu $9, 0x12($27) /* read INCSR */
621 + andi $8, $9, 0x2 /* check INCSR_FFNOTEMPT */
622 + bnez $8, _epin1_tx_state4
626 + lhu $9, 0x10($27) /* get INMAXP */
628 + blez $8, _epin1_tx_state1 /* bytes left <= INMAXP */
633 + beqz $19, _epin1_tx_state4 /* No data */
636 + sub $21, $21, $19 /* decrement data count */
638 + srl $5, $19, 2 /* # of word */
639 + andi $6, $19, 0x3 /* # of byte */
640 + beqz $5, _epin1_tx_state2
643 +_epin1_fifo_write_word:
644 + lw $9, 0($20) /* read data from source address */
645 + sw $9, 0x24($27) /* write FIFO */
646 + sub $5, $5, 1 /* decrement counter */
647 + bnez $5, _epin1_fifo_write_word
648 + addiu $20, $20, 4 /* increment dest address */
651 + beqz $6, _epin1_tx_state3
654 +_epin1_fifo_write_byte:
655 + lbu $9, 0($20) /* read data from source address */
656 + sb $9, 0x24($27) /* write FIFO */
657 + sub $6, $6, 1 /* decrement counter */
658 + bnez $6, _epin1_fifo_write_byte
659 + addiu $20, $20, 1 /* increment dest address */
663 + sb $9, 0x12($27) /* INCSR, set INPKTRDY */
666 + /* 4. Check and handle EP1 BULK-OUT interrupt */
668 + lhu $9, 0x04($27) /* read INTROUT */
670 + beqz $9, check_status_next
675 + sb $9, 0x0e($27) /* set INDEX 1 */
677 + lbu $9, 0x16($27) /* read OUTCSR */
678 + andi $9, 0x1 /* check OUTPKTRDY */
679 + beqz $9, check_status_next
683 + lhu $19, 0x18($27) /* read OUTCOUNT */
684 + srl $5, $19, 2 /* # of word */
685 + andi $6, $19, 0x3 /* # of byte */
686 + beqz $5, _epout1_rx_state1
689 +_epout1_fifo_read_word:
690 + lw $9, 0x24($27) /* read FIFO */
691 + sw $9, 0($20) /* store to dest address */
692 + sub $5, $5, 1 /* decrement counter */
693 + bnez $5, _epout1_fifo_read_word
694 + addiu $20, $20, 4 /* increment dest address */
697 + beqz $6, _epout1_rx_state2
700 +_epout1_fifo_read_byte:
701 + lbu $9, 0x24($27) /* read FIFO */
702 + sb $9, 0($20) /* store to dest address */
703 + sub $6, $6, 1 /* decrement counter */
704 + bnez $6, _epout1_fifo_read_byte
705 + addiu $20, $20, 1 /* increment dest address */
708 + sb $0, 0x16($27) /* clear OUTPKTRDY */
714 +/* Device/Configuration/Interface/Endpoint/String Descriptors */
718 + .byte 0x12 /* bLength */
719 + .byte 0x01 /* bDescriptorType */
720 + .byte 0x00 /* bcdUSB */
721 + .byte 0x02 /* bcdUSB */
722 + .byte 0x00 /* bDeviceClass */
723 + .byte 0x00 /* bDeviceSubClass */
724 + .byte 0x00 /* bDeviceProtocol */
725 + .byte 0x40 /* bMaxPacketSize0 */
726 + .byte 0x1a /* idVendor */
727 + .byte 0x60 /* idVendor */
728 + .byte 0x40 /* idProduct */
729 + .byte 0x47 /* idProduct */
730 + .byte 0x00 /* bcdDevice */
731 + .byte 0x01 /* bcdDevice */
732 + .byte 0x01 /* iManufacturer */
733 + .byte 0x02 /* iProduct */
734 + .byte 0x00 /* iSerialNumber */
735 + .byte 0x01 /* bNumConfigurations */
739 + .byte 0x0a /* bLength */
740 + .byte 0x06 /* bDescriptorType */
741 + .byte 0x00 /* bcdUSB */
742 + .byte 0x02 /* bcdUSB */
743 + .byte 0x00 /* bDeviceClass */
744 + .byte 0x00 /* bDeviceSubClass */
745 + .byte 0x00 /* bDeviceProtocol */
746 + .byte 0x40 /* bMaxPacketSize0 */
747 + .byte 0x01 /* bNumConfigurations */
748 + .byte 0x00 /* bRESERVED */
752 + .byte 0x09 /* bLength */
753 + .byte 0x02 /* bDescriptorType */
754 + .byte 0x20 /* wTotalLength */
755 + .byte 0x00 /* wTotalLength */
756 + .byte 0x01 /* bNumInterfaces */
757 + .byte 0x01 /* bConfigurationValue */
758 + .byte 0x00 /* iConfiguration */
759 + .byte 0xc0 /* bmAttributes */
760 + .byte 0x01 /* MaxPower */
762 + .byte 0x09 /* bLength */
763 + .byte 0x04 /* bDescriptorType */
764 + .byte 0x00 /* bInterfaceNumber */
765 + .byte 0x00 /* bAlternateSetting */
766 + .byte 0x02 /* bNumEndpoints */
767 + .byte 0xff /* bInterfaceClass */
768 + .byte 0x00 /* bInterfaceSubClass */
769 + .byte 0x50 /* bInterfaceProtocol */
770 + .byte 0x00 /* iInterface */
772 + .byte 0x07 /* bLength */
773 + .byte 0x05 /* bDescriptorType */
774 + .byte 0x01 /* bEndpointAddress */
775 + .byte 0x02 /* bmAttributes */
776 + .byte 0x00 /* wMaxPacketSize */
777 + .byte 0x02 /* wMaxPacketSize */
778 + .byte 0x00 /* bInterval */
780 + .byte 0x07 /* bLength */
781 + .byte 0x05 /* bDescriptorType */
782 + .byte 0x81 /* bEndpointAddress */
783 + .byte 0x02 /* bmAttributes */
784 + .byte 0x00 /* wMaxPacketSize */
785 + .byte 0x02 /* wMaxPacketSize */
786 + .byte 0x00 /* bInterval */
790 + .byte 0x09 /* bLength */
791 + .byte 0x02 /* bDescriptorType */
792 + .byte 0x20 /* wTotalLength */
793 + .byte 0x00 /* wTotalLength */
794 + .byte 0x01 /* bNumInterfaces */
795 + .byte 0x01 /* bConfigurationValue */
796 + .byte 0x00 /* iConfiguration */
797 + .byte 0xc0 /* bmAttributes */
798 + .byte 0x01 /* MaxPower */
800 + .byte 0x09 /* bLength */
801 + .byte 0x04 /* bDescriptorType */
802 + .byte 0x00 /* bInterfaceNumber */
803 + .byte 0x00 /* bAlternateSetting */
804 + .byte 0x02 /* bNumEndpoints */
805 + .byte 0xff /* bInterfaceClass */
806 + .byte 0x00 /* bInterfaceSubClass */
807 + .byte 0x50 /* bInterfaceProtocol */
808 + .byte 0x00 /* iInterface */
810 + .byte 0x07 /* bLength */
811 + .byte 0x05 /* bDescriptorType */
812 + .byte 0x01 /* bEndpointAddress */
813 + .byte 0x02 /* bmAttributes */
814 + .byte 0x40 /* wMaxPacketSize */
815 + .byte 0x00 /* wMaxPacketSize */
816 + .byte 0x00 /* bInterval */
818 + .byte 0x07 /* bLength */
819 + .byte 0x05 /* bDescriptorType */
820 + .byte 0x81 /* bEndpointAddress */
821 + .byte 0x02 /* bmAttributes */
822 + .byte 0x40 /* wMaxPacketSize */
823 + .byte 0x00 /* wMaxPacketSize */
824 + .byte 0x00 /* bInterval */