1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Tomasz Malesinski
11 * Copyright (C) 2008 by Maurus Cuelenaere
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
34 unsigned char *out_buf
;
37 void (*out_done
)(int, unsigned char *, int);
38 unsigned char out_in_progress
;
40 unsigned char *in_buf
;
44 void (*in_done
)(int, unsigned char *, int);
47 unsigned char halt
[2];
48 unsigned char enabled
[2];
49 short max_pkt_size
[2];
54 static unsigned char setup_pkt_buf
[8];
55 static struct usb_endpoint endpoints
[USB_NUM_ENDPOINTS
];
58 #define ZVM_SPECIFIC asm volatile( \
59 "LDR R12, =0x50FFC000\n" \
66 static bool high_speed_mode
= false;
68 static inline void or_int_value(volatile unsigned short *a
, volatile unsigned short *b
, unsigned long r
, unsigned long value
)
70 set_int_value(*a
, *b
, (r
| value
));
72 static inline void bc_int_value(volatile unsigned short *a
, volatile unsigned short *b
, unsigned long r
, unsigned long value
)
74 set_int_value(*a
, *b
, (r
& ~value
));
77 static inline void nop_f(void)
82 #define NOP asm volatile("nop\n");
84 static inline int ep_index(int n
, bool dir
)
86 return (n
<< 1) | dir
;
89 static inline bool epidx_dir(int idx
)
94 static inline int epidx_n(int idx
)
99 static inline void usb_select_endpoint(int idx
)
101 /* Select the endpoint */
102 ISP1583_DFLOW_EPINDEX
= idx
;
103 /* The delay time from the Write Endpoint Index register to the Read Data Port register must be at least 190 ns.
104 * The delay time from the Write Endpoint Index register to the Write Data Port register must be at least 100 ns.
109 static inline void usb_select_setup_endpoint(void)
111 /* Select the endpoint */
112 ISP1583_DFLOW_EPINDEX
= DFLOW_EPINDEX_EP0SETUP
;
113 /* The delay time from the Write Endpoint Index register to the Read Data Port register must be at least 190 ns.
114 * The delay time from the Write Endpoint Index register to the Write Data Port register must be at least 100 ns.
119 static void usb_setup_endpoint(int idx
, int max_pkt_size
, int type
)
121 if(epidx_n(idx
)!=EP_CONTROL
)
123 usb_select_endpoint(idx
);
124 ISP1583_DFLOW_MAXPKSZ
= max_pkt_size
& 0x7FF;
125 ISP1583_DFLOW_EPTYPE
= (DFLOW_EPTYPE_NOEMPKT
| DFLOW_EPTYPE_DBLBUF
| (type
& 0x3));
127 /* clear buffer ... */
128 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_CLBUF
;
129 /* ... twice because of double buffering */
130 usb_select_endpoint(idx
);
131 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_CLBUF
;
134 struct usb_endpoint
*ep
;
135 ep
= &(endpoints
[epidx_n(idx
)]);
136 ep
->halt
[epidx_dir(idx
)] = 0;
137 ep
->enabled
[epidx_dir(idx
)] = 0;
138 ep
->out_in_progress
= 0;
142 ep
->max_pkt_size
[epidx_dir(idx
)] = max_pkt_size
;
145 static void usb_enable_endpoint(int idx
)
147 if(epidx_n(idx
)!=EP_CONTROL
)
149 usb_select_endpoint(idx
);
150 /* Enable interrupt */
151 or_int_value(&ISP1583_INIT_INTEN_A
, &ISP1583_INIT_INTEN_B
, ISP1583_INIT_INTEN_READ
, 1 << (10 + idx
));
152 /* Enable endpoint */
153 ISP1583_DFLOW_EPTYPE
|= DFLOW_EPTYPE_ENABLE
;
156 endpoints
[epidx_n(idx
)].enabled
[epidx_dir(idx
)] = 1;
159 static void usb_disable_endpoint(int idx, bool set_struct)
161 usb_select_endpoint(idx);
162 ISP1583_DFLOW_EPTYPE &= ~DFLOW_EPTYPE_ENABLE;
163 bc_int_value(&ISP1583_INIT_INTEN_A, &ISP1583_INIT_INTEN_B, ISP1583_INIT_INTEN_READ, 1 << (10 + idx));
166 endpoints[epidx_n(idx)].enabled[epidx_dir(idx)] = 0;
169 static int usb_get_packet(unsigned char *buf
, int max_len
)
172 len
= ISP1583_DFLOW_BUFLEN
;
174 if (max_len
< 0 || max_len
> len
)
180 unsigned short d
= ISP1583_DFLOW_DATA
;
185 buf
[i
] = (d
>> 8) & 0xff;
191 static int usb_receive(int n
)
193 logf("usb_receive(%d)", n
);
196 if (endpoints
[n
].halt
[DIR_RX
]
197 || !endpoints
[n
].enabled
[DIR_RX
]
198 || endpoints
[n
].in_min_len
< 0
199 || !endpoints
[n
].in_ack
)
202 endpoints
[n
].in_ack
= 0;
204 usb_select_endpoint(ep_index(n
, DIR_RX
));
206 len
= usb_get_packet(endpoints
[n
].in_buf
+ endpoints
[n
].in_ptr
,
207 endpoints
[n
].in_max_len
- endpoints
[n
].in_ptr
);
208 endpoints
[n
].in_ptr
+= len
;
210 if (endpoints
[n
].in_ptr
>= endpoints
[n
].in_min_len
)
212 endpoints
[n
].in_min_len
= -1;
213 if (endpoints
[n
].in_done
)
214 (*(endpoints
[n
].in_done
))(n
, endpoints
[n
].in_buf
,
215 endpoints
[n
].in_ptr
);
221 static bool usb_out_buffer_full(int ep
)
223 usb_select_endpoint(ep_index(ep
, DIR_TX
));
224 if (ISP1583_DFLOW_EPTYPE
& 4) /* Check if type=bulk and double buffering is set */
225 return (ISP1583_DFLOW_BUFSTAT
& 3) == 3; /* Return true if both buffers are filled */
227 return (ISP1583_DFLOW_BUFSTAT
& 3) != 0; /* Return true if one of the buffers are filled */
230 static int usb_send(int n
)
232 logf("usb_send(%d)", n
);
233 int max_pkt_size
, len
;
237 if (endpoints
[n
].halt
[DIR_TX
]
238 || !endpoints
[n
].enabled
[DIR_TX
]
239 || !endpoints
[n
].out_in_progress
)
241 logf("NOT SEND TO EP!");
245 if (endpoints
[n
].out_ptr
< 0)
247 endpoints
[n
].out_in_progress
= 0;
248 if (endpoints
[n
].out_done
)
249 (*(endpoints
[n
].out_done
))(n
, endpoints
[n
].out_buf
,
250 endpoints
[n
].out_len
);
251 logf("ALREADY SENT TO EP!");
255 if (usb_out_buffer_full(n
))
257 logf("BUFFER FULL!");
261 usb_select_endpoint(ep_index(n
, DIR_TX
));
262 max_pkt_size
= endpoints
[n
].max_pkt_size
[DIR_TX
];
263 len
= endpoints
[n
].out_len
- endpoints
[n
].out_ptr
;
264 if (len
> max_pkt_size
)
267 if(len
< max_pkt_size
)
268 ISP1583_DFLOW_BUFLEN
= len
;
270 p
= endpoints
[n
].out_buf
+ endpoints
[n
].out_ptr
;
274 ISP1583_DFLOW_DATA
= p
[i
] | (p
[i
+ 1] << 8);
278 ISP1583_DFLOW_DATA
= p
[i
];
280 endpoints
[n
].out_ptr
+= len
;
283 if (endpoints[n].out_ptr == endpoints[n].out_len
284 && len < max_pkt_size)
286 if (endpoints
[n
].out_ptr
== endpoints
[n
].out_len
)
287 endpoints
[n
].out_ptr
= -1;
293 static void usb_stall_endpoint(int idx
)
295 usb_select_endpoint(idx
);
296 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_STALL
;
297 endpoints
[epidx_n(idx
)].halt
[epidx_dir(idx
)] = 1;
300 static void usb_unstall_endpoint(int idx
)
302 usb_select_endpoint(idx
);
303 ISP1583_DFLOW_CTRLFUN
&= ~DFLOW_CTRLFUN_STALL
;
304 ISP1583_DFLOW_EPTYPE
&= ~DFLOW_EPTYPE_ENABLE
;
305 ISP1583_DFLOW_EPTYPE
|= DFLOW_EPTYPE_ENABLE
;
306 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_CLBUF
;
307 if (epidx_dir(idx
) == DIR_TX
)
308 endpoints
[epidx_n(idx
)].out_in_progress
= 0;
311 endpoints
[epidx_n(idx
)].in_min_len
= -1;
312 endpoints
[epidx_n(idx
)].in_ack
= 0;
314 endpoints
[epidx_n(idx
)].halt
[epidx_dir(idx
)] = 0;
317 static void usb_status_ack(int ep
, int dir
)
319 logf("usb_status_ack(%d)", dir
);
321 usb_select_setup_endpoint();
323 usb_select_endpoint(ep_index(ep
, dir
));
325 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_STATUS
;
328 static void usb_data_stage_enable(int ep
, int dir
)
330 logf("usb_data_stage_enable(%d)", dir
);
331 usb_select_endpoint(ep_index(ep
, dir
));
332 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_DSEN
;
335 static void usb_handle_setup_rx(void)
338 usb_select_setup_endpoint();
339 len
= usb_get_packet(setup_pkt_buf
, 8);
343 ISP1583_DFLOW_CTRLFUN
|= DFLOW_CTRLFUN_STATUS
; /* Acknowledge packet */
344 usb_core_control_request((struct usb_ctrlrequest
*)setup_pkt_buf
);
348 usb_drv_stall(EP_CONTROL
, true, false);
349 usb_drv_stall(EP_CONTROL
, true, true);
350 logf("usb_handle_setup_rx() failed");
354 logf("usb_handle_setup_rx(): %02x %02x %02x %02x %02x %02x %02x %02x", setup_pkt_buf
[0], setup_pkt_buf
[1], setup_pkt_buf
[2], setup_pkt_buf
[3], setup_pkt_buf
[4], setup_pkt_buf
[5], setup_pkt_buf
[6], setup_pkt_buf
[7]);
357 static void usb_handle_data_int(int ep
, int dir
)
364 len
= usb_receive(ep
);
365 endpoints
[ep
].in_ack
= 1;
367 logf("usb_handle_data_int(%d, %d) finished", ep
, dir
);
370 bool usb_drv_powered(void)
373 return (ISP1583_INIT_OTG
& INIT_OTG_BSESS_VALID
) ? true : false;
375 return (ISP1583_INIT_MODE
& INIT_MODE_VBUSSTAT
) ? true : false;
379 static void setup_endpoints(void)
382 int max_pkt_size
= (high_speed_mode
? 512 : 64);
384 usb_setup_endpoint(ep_index(EP_CONTROL
, DIR_RX
), 64,
385 USB_ENDPOINT_XFER_CONTROL
);
386 usb_setup_endpoint(ep_index(EP_CONTROL
, DIR_TX
), 64,
387 USB_ENDPOINT_XFER_CONTROL
);
389 for(i
= 1; i
< USB_NUM_ENDPOINTS
-1; i
++)
391 usb_setup_endpoint(ep_index(i
, DIR_RX
), max_pkt_size
,
392 USB_ENDPOINT_XFER_BULK
);
393 usb_setup_endpoint(ep_index(i
, DIR_TX
), max_pkt_size
,
394 USB_ENDPOINT_XFER_BULK
);
397 usb_enable_endpoint(ep_index(EP_CONTROL
, DIR_RX
));
398 usb_enable_endpoint(ep_index(EP_CONTROL
, DIR_TX
));
400 for (i
= 1; i
< USB_NUM_ENDPOINTS
-1; i
++)
402 usb_enable_endpoint(ep_index(i
, DIR_RX
));
403 usb_enable_endpoint(ep_index(i
, DIR_TX
));
409 #if 0 /* currently unused */
410 static void usb_helper(void)
412 if(ISP1583_GEN_INT_READ
& ISP1583_INIT_INTEN_READ
)
414 logf("Helper detected interrupt... [%d]", (int)current_tick
);
420 void usb_drv_init(void)
422 /* Disable interrupt at CPU level */
425 /* Unlock the device's registers */
426 ISP1583_GEN_UNLCKDEV
= ISP1583_UNLOCK_CODE
;
428 /* Soft reset the device */
429 ISP1583_INIT_MODE
= INIT_MODE_SFRESET
;
431 /* Enable CLKAON & GLINTENA */
432 ISP1583_INIT_MODE
= STANDARD_INIT_MODE
;
434 /* Disable all OTG functions */
435 ISP1583_INIT_OTG
= 0;
438 logf("BUS_CONF/DA0:%d MODE0/DA1: %d MODE1: %d", (bool)(ISP1583_INIT_MODE
& INIT_MODE_TEST0
), (bool)(ISP1583_INIT_MODE
& INIT_MODE_TEST1
), (bool)(ISP1583_INIT_MODE
& INIT_MODE_TEST2
));
439 logf("Chip ID: 0x%x", ISP1583_GEN_CHIPID
);
440 //logf("INV0: 0x% IRQEDGE: 0x%x IRQPORT: 0x%x", IO_GIO_INV0, IO_GIO_IRQEDGE, IO_GIO_IRQPORT);
443 /*Set interrupt generation to target-specific mode +
444 * Set the control pipe to ACK only interrupt +
445 * Set the IN pipe to ACK only interrupt +
446 * Set OUT pipe to ACK and NYET interrupt
449 ISP1583_INIT_INTCONF
= 0x54 | INT_CONF_TARGET
;
450 /* Clear all interrupts */
451 set_int_value(ISP1583_GEN_INT_A
, ISP1583_GEN_INT_B
, 0xFFFFFFFF);
452 /* Enable USB interrupts */
453 set_int_value(ISP1583_INIT_INTEN_A
, ISP1583_INIT_INTEN_B
, STANDARD_INTEN
);
457 /* Enable interrupt at CPU level */
462 /* Clear device address and disable it */
463 ISP1583_INIT_ADDRESS
= 0;
465 /* Turn SoftConnect on */
466 ISP1583_INIT_MODE
|= INIT_MODE_SOFTCT
;
470 //tick_add_task(usb_helper);
472 logf("usb_init_device() finished");
475 int usb_drv_port_speed(void)
477 return (int)high_speed_mode
;
480 void usb_drv_exit(void)
482 logf("usb_drv_exit()");
485 ISP1583_INIT_MODE
&= ~INIT_MODE_SOFTCT
;
486 ISP1583_INIT_ADDRESS
= 0;
488 /* Disable interrupts */
489 set_int_value(ISP1583_INIT_INTEN_A
, ISP1583_INIT_INTEN_B
, 0);
490 /* and the CPU's one... */
494 /* Send usb controller to suspend mode */
495 ISP1583_INIT_MODE
= INIT_MODE_GOSUSP
;
496 ISP1583_INIT_MODE
= 0;
498 //tick_remove_task(usb_helper);
503 void usb_drv_stall(int endpoint
, bool stall
, bool in
)
505 logf("%sstall EP%d %s", (stall
? "" : "un"), endpoint
, (in
? "RX" : "TX" ));
507 usb_stall_endpoint(ep_index(endpoint
, (int)in
));
509 usb_unstall_endpoint(ep_index(endpoint
, (int)in
));
512 bool usb_drv_stalled(int endpoint
, bool in
)
514 return (endpoints
[endpoint
].halt
[(int)in
] == 1);
517 static void out_callback(int ep
, unsigned char *buf
, int len
)
520 logf("out_callback(%d, 0x%x, %d)", ep
, (int)buf
, len
);
521 usb_status_ack(ep
, DIR_RX
);
522 usb_core_transfer_complete(ep
, true, 0, len
); /* 0=>status succeeded, haven't worked out status failed yet... */
525 static void in_callback(int ep
, unsigned char *buf
, int len
)
528 logf("in_callback(%d, 0x%x, %d)", ep
, (int)buf
, len
);
529 usb_status_ack(ep
, DIR_TX
);
530 usb_core_transfer_complete(ep
, false, 0, len
);
533 int usb_drv_recv(int ep
, void* ptr
, int length
)
535 logf("usb_drv_recv(%d, 0x%x, %d)", ep
, (int)ptr
, length
);
536 if(ep
== EP_CONTROL
&& length
== 0 && ptr
== NULL
)
538 usb_status_ack(ep
, DIR_TX
);
541 endpoints
[ep
].in_done
= in_callback
;
542 endpoints
[ep
].in_buf
= ptr
;
543 endpoints
[ep
].in_max_len
= length
;
544 endpoints
[ep
].in_min_len
= length
;
545 endpoints
[ep
].in_ptr
= 0;
548 usb_data_stage_enable(ep
, DIR_RX
);
549 return usb_receive(ep
);
552 return usb_receive(ep
);
555 int usb_drv_send_nonblocking(int ep
, void* ptr
, int length
)
557 /* First implement DMA... */
558 return usb_drv_send(ep
, ptr
, length
);
561 static void usb_drv_wait(int ep
, bool send
)
563 logf("usb_drv_wait(%d, %d)", ep
, send
);
566 while (endpoints
[ep
].out_in_progress
)
571 while (endpoints
[ep
].in_ack
)
576 int usb_drv_send(int ep
, void* ptr
, int length
)
578 logf("usb_drv_send_nb(%d, 0x%x, %d)", ep
, (int)ptr
, length
);
579 if(ep
== EP_CONTROL
&& length
== 0 && ptr
== NULL
)
581 usb_status_ack(ep
, DIR_RX
);
584 if(endpoints
[ep
].out_in_progress
== 1)
586 endpoints
[ep
].out_done
= out_callback
;
587 endpoints
[ep
].out_buf
= ptr
;
588 endpoints
[ep
].out_len
= length
;
589 endpoints
[ep
].out_ptr
= 0;
590 endpoints
[ep
].out_in_progress
= 1;
593 int rc
= usb_send(ep
);
594 usb_data_stage_enable(ep
, DIR_TX
);
595 usb_drv_wait(ep
, DIR_TX
);
602 void usb_drv_reset_endpoint(int ep
, bool send
)
604 logf("reset endpoint(%d, %d)", ep
, send
);
605 usb_setup_endpoint(ep_index(ep
, (int)send
), endpoints
[ep
].max_pkt_size
[(int)send
], endpoints
[ep
].type
);
606 usb_enable_endpoint(ep_index(ep
, (int)send
));
609 void usb_drv_cancel_all_transfers(void)
611 logf("usb_drv_cancel_all_tranfers()");
614 for(i
=0;i
<USB_NUM_ENDPOINTS
-1;i
++)
615 endpoints
[i
].halt
[0] = endpoints
[i
].halt
[1] = 1;
618 int usb_drv_request_endpoint(int type
, int dir
)
622 if (type
!= USB_ENDPOINT_XFER_BULK
)
625 bit
=(dir
& USB_DIR_IN
)? 2:1;
627 for (i
=1; i
< USB_NUM_ENDPOINTS
; i
++) {
628 if((endpoints
[i
].allocation
& bit
)!=0)
630 endpoints
[i
].allocation
|= bit
;
637 void usb_drv_release_endpoint(int ep
)
639 int mask
= (ep
& USB_DIR_IN
)? ~2:~1;
640 endpoints
[ep
& 0x7f].allocation
&= mask
;
643 static void bus_reset(void)
645 /* Enable CLKAON & GLINTENA */
646 ISP1583_INIT_MODE
= STANDARD_INIT_MODE
;
647 /* Enable USB interrupts */
648 ISP1583_INIT_INTCONF
= 0x54 | INT_CONF_TARGET
;
649 set_int_value(ISP1583_INIT_INTEN_A
, ISP1583_INIT_INTEN_B
, STANDARD_INTEN
);
651 /* Disable all OTG functions */
652 ISP1583_INIT_OTG
= 0;
654 /* Clear device address and enable it */
655 ISP1583_INIT_ADDRESS
= INIT_ADDRESS_DEVEN
;
659 /* Reset endpoints to default */
662 logf("bus reset->done");
665 /* Method for handling interrupts, must be called from usb-<target>.c */
666 void IRAM_ATTR
usb_drv_int(void)
669 ints
= ISP1583_GEN_INT_READ
& ISP1583_INIT_INTEN_READ
;
674 /* Unlock the device's registers */
675 ISP1583_GEN_UNLCKDEV
= ISP1583_UNLOCK_CODE
;
677 //logf(" handling int [0x%lx & 0x%lx = 0x%x]", ISP1583_GEN_INT_READ, ISP1583_INIT_INTEN_READ, (int)ints);
679 if(ints
& INT_IEBRST
) /* Bus reset */
682 high_speed_mode
= false;
684 usb_core_bus_reset();
685 /* Mask bus reset interrupt */
686 set_int_value(ISP1583_GEN_INT_A
, ISP1583_GEN_INT_B
, INT_IEBRST
);
689 if(ints
& INT_IEP0SETUP
) /* EP0SETUP interrupt */
692 usb_handle_setup_rx();
694 if(ints
& INT_IEHS_STA
) /* change from full-speed to high-speed mode -> endpoints need to get reconfigured!! */
697 high_speed_mode
= true;
700 if(ints
& INT_EP_MASK
) /* Endpoints interrupt */
702 unsigned long ep_event
;
703 unsigned short i
= 10;
704 ep_event
= ints
& INT_EP_MASK
;
710 if(ep_event
& (1 << i
))
712 logf("EP%d %s interrupt", (i
- 10) / 2, i
% 2 ? "RX" : "TX");
713 usb_handle_data_int((i
- 10) / 2, i
% 2);
714 ep_event
&= ~(1 << i
);
719 if(ints
& INT_IERESM
&& !(ints
& INT_IESUSP
)) /* Resume status: status change from suspend to resume (active) */
723 if(ints
& INT_IESUSP
&& !(ints
& INT_IERESM
)) /* Suspend status: status change from active to suspend */
727 if(ints
& INT_IEDMA
) /* change in the DMA Interrupt Reason register */
731 if(ints
& INT_IEVBUS
) /* transition from LOW to HIGH on VBUS */
735 /* Mask all (enabled) interrupts */
736 set_int_value(ISP1583_GEN_INT_A
, ISP1583_GEN_INT_B
, ints
);
741 void usb_drv_set_address(int address
)
743 logf("usb_drv_set_address(0x%x)", address
);
744 ISP1583_INIT_ADDRESS
= (address
& 0x7F) | INIT_ADDRESS_DEVEN
;
749 void usb_drv_set_test_mode(int mode
)
751 logf("usb_drv_set_test_mode(%d)", mode
);
754 ISP1583_GEN_TSTMOD
= 0;
758 ISP1583_GEN_TSTMOD
= GEN_TSTMOD_JSTATE
;
761 ISP1583_GEN_TSTMOD
= GEN_TSTMOD_KSTATE
;
764 ISP1583_GEN_TSTMOD
= GEN_TSTMOD_SE0_NAK
;
767 //REG_PORTSC1 |= PORTSCX_PTC_PACKET;
770 //REG_PORTSC1 |= PORTSCX_PTC_FORCE_EN;
776 int dbg_usb_num_items(void)
778 return 2+USB_NUM_ENDPOINTS
*2;
781 const char* dbg_usb_item(int selected_item
, void *data
,
782 char *buffer
, size_t buffer_len
)
784 if(selected_item
< 2)
786 switch(selected_item
)
789 snprintf(buffer
, buffer_len
, "USB connected: %s", (usb_drv_connected() ? "Yes" : "No"));
792 snprintf(buffer
, buffer_len
, "HS mode: %s", (high_speed_mode
? "Yes" : "No"));
798 int n
= ep_index((selected_item
- 2) / 2, (selected_item
- 2) % 2);
799 if(endpoints
[n
].enabled
== false)
800 snprintf(buffer
, buffer_len
, "EP%d[%s]: DISABLED", epidx_n(n
), (epidx_dir(n
) ? "TX" : "RX"));
805 if(endpoints
[n
].out_in_progress
)
806 snprintf(buffer
, buffer_len
, "EP%d[TX]: TRANSFERRING DATA -> %d bytes/%d bytes", epidx_n(n
), (endpoints
[n
].out_len
- endpoints
[n
].out_ptr
), endpoints
[n
].out_len
);
808 snprintf(buffer
, buffer_len
, "EP%d[TX]: STANDBY", epidx_n(n
));
812 if(endpoints
[n
].in_buf
&& !endpoints
[n
].in_ack
)
813 snprintf(buffer
, buffer_len
, "EP%d[RX]: RECEIVING DATA -> %d bytes/%d bytes", epidx_n(n
), endpoints
[n
].in_ptr
, endpoints
[n
].in_max_len
);
815 snprintf(buffer
, buffer_len
, "EP%d[RX]: STANDBY", epidx_n(n
));