A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Tomasz Malesinski
11 * Copyright (C) 2008 by Maurus Cuelenaere
12 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "usb_ch9.h"
25#include "usb_drv.h"
26#include "usb_core.h"
27#include "isp1583.h"
28#include "thread.h"
29#include "logf.h"
30#include "stdio.h"
31
32struct usb_endpoint
33{
34 unsigned char *out_buf;
35 short out_len;
36 short out_ptr;
37 void (*out_done)(int, unsigned char *, int);
38 unsigned char out_in_progress;
39
40 unsigned char *in_buf;
41 short in_min_len;
42 short in_max_len;
43 short in_ptr;
44 void (*in_done)(int, unsigned char *, int);
45 unsigned char in_ack;
46
47 unsigned char halt[2];
48 unsigned char enabled[2];
49 short max_pkt_size[2];
50 short type;
51 char allocation;
52};
53
54static unsigned char setup_pkt_buf[8];
55static struct usb_endpoint endpoints[USB_NUM_ENDPOINTS];
56
57#if 0
58#define ZVM_SPECIFIC asm volatile( \
59 "LDR R12, =0x50FFC000\n" \
60 "LDRH R12, [R12]\n" \
61 : : : "r12");
62#else
63#define ZVM_SPECIFIC
64#endif
65
66static bool high_speed_mode = false;
67
68static inline void or_int_value(volatile unsigned short *a, volatile unsigned short *b, unsigned long r, unsigned long value)
69{
70 set_int_value(*a, *b, (r | value));
71}
72static inline void bc_int_value(volatile unsigned short *a, volatile unsigned short *b, unsigned long r, unsigned long value)
73{
74 set_int_value(*a, *b, (r & ~value));
75}
76
77static inline void nop_f(void)
78{
79 yield();
80}
81
82#define NOP asm volatile("nop\n");
83
84static inline int ep_index(int n, bool dir)
85{
86 return (n << 1) | dir;
87}
88
89static inline bool epidx_dir(int idx)
90{
91 return idx & 1;
92}
93
94static inline int epidx_n(int idx)
95{
96 return idx >> 1;
97}
98
99static inline void usb_select_endpoint(int idx)
100{
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.
105 */
106 NOP;
107}
108
109static inline void usb_select_setup_endpoint(void)
110{
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.
115 */
116 NOP;
117}
118
119static void usb_setup_endpoint(int idx, int max_pkt_size, int type)
120{
121 if(epidx_n(idx)!=EP_CONTROL)
122 {
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));
126
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;
132 }
133
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;
139 ep->in_min_len = -1;
140 ep->in_ack = 0;
141 ep->type = type;
142 ep->max_pkt_size[epidx_dir(idx)] = max_pkt_size;
143}
144
145static void usb_enable_endpoint(int idx)
146{
147 if(epidx_n(idx)!=EP_CONTROL)
148 {
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;
154 }
155
156 endpoints[epidx_n(idx)].enabled[epidx_dir(idx)] = 1;
157}
158/*
159static void usb_disable_endpoint(int idx, bool set_struct)
160{
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));
164
165 if(set_struct)
166 endpoints[epidx_n(idx)].enabled[epidx_dir(idx)] = 0;
167}
168*/
169static int usb_get_packet(unsigned char *buf, int max_len)
170{
171 int len, i;
172 len = ISP1583_DFLOW_BUFLEN;
173
174 if (max_len < 0 || max_len > len)
175 max_len = len;
176
177 i = 0;
178 while (i < len)
179 {
180 unsigned short d = ISP1583_DFLOW_DATA;
181 if (i < max_len)
182 buf[i] = d & 0xff;
183 i++;
184 if (i < max_len)
185 buf[i] = (d >> 8) & 0xff;
186 i++;
187 }
188 return max_len;
189}
190
191static int usb_receive(int n)
192{
193 logf("usb_receive(%d)", n);
194 int len;
195
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)
200 return -1;
201
202 endpoints[n].in_ack = 0;
203
204 usb_select_endpoint(ep_index(n, DIR_RX));
205
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;
209
210 if (endpoints[n].in_ptr >= endpoints[n].in_min_len)
211 {
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);
216 }
217 logf("receive_end");
218 return 0;
219}
220
221static bool usb_out_buffer_full(int ep)
222{
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 */
226 else
227 return (ISP1583_DFLOW_BUFSTAT & 3) != 0; /* Return true if one of the buffers are filled */
228}
229
230static int usb_send(int n)
231{
232 logf("usb_send(%d)", n);
233 int max_pkt_size, len;
234 int i;
235 unsigned char *p;
236
237 if (endpoints[n].halt[DIR_TX]
238 || !endpoints[n].enabled[DIR_TX]
239 || !endpoints[n].out_in_progress)
240 {
241 logf("NOT SEND TO EP!");
242 return -1;
243 }
244
245 if (endpoints[n].out_ptr < 0)
246 {
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!");
252 return -1;
253 }
254
255 if (usb_out_buffer_full(n))
256 {
257 logf("BUFFER FULL!");
258 return -1;
259 }
260
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)
265 len = max_pkt_size;
266
267 if(len < max_pkt_size)
268 ISP1583_DFLOW_BUFLEN = len;
269
270 p = endpoints[n].out_buf + endpoints[n].out_ptr;
271 i = 0;
272 while (len - i >= 2)
273 {
274 ISP1583_DFLOW_DATA = p[i] | (p[i + 1] << 8);
275 i += 2;
276 }
277 if (i < len)
278 ISP1583_DFLOW_DATA = p[i];
279
280 endpoints[n].out_ptr += len;
281
282/*
283 if (endpoints[n].out_ptr == endpoints[n].out_len
284 && len < max_pkt_size)
285*/
286 if (endpoints[n].out_ptr == endpoints[n].out_len)
287 endpoints[n].out_ptr = -1;
288
289 logf("send_end");
290 return 0;
291}
292
293static void usb_stall_endpoint(int idx)
294{
295 usb_select_endpoint(idx);
296 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_STALL;
297 endpoints[epidx_n(idx)].halt[epidx_dir(idx)] = 1;
298}
299
300static void usb_unstall_endpoint(int idx)
301{
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;
309 else
310 {
311 endpoints[epidx_n(idx)].in_min_len = -1;
312 endpoints[epidx_n(idx)].in_ack = 0;
313 }
314 endpoints[epidx_n(idx)].halt[epidx_dir(idx)] = 0;
315}
316
317static void usb_status_ack(int ep, int dir)
318{
319 logf("usb_status_ack(%d)", dir);
320 if(ep == EP_CONTROL)
321 usb_select_setup_endpoint();
322 else
323 usb_select_endpoint(ep_index(ep, dir));
324
325 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_STATUS;
326}
327
328static void usb_data_stage_enable(int ep, int dir)
329{
330 logf("usb_data_stage_enable(%d)", dir);
331 usb_select_endpoint(ep_index(ep, dir));
332 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_DSEN;
333}
334
335static void usb_handle_setup_rx(void)
336{
337 int len;
338 usb_select_setup_endpoint();
339 len = usb_get_packet(setup_pkt_buf, 8);
340
341 if (len == 8)
342 {
343 ISP1583_DFLOW_CTRLFUN |= DFLOW_CTRLFUN_STATUS; /* Acknowledge packet */
344 usb_core_legacy_control_request((struct usb_ctrlrequest*)setup_pkt_buf);
345 }
346 else
347 {
348 usb_drv_stall(EP_CONTROL, true, false);
349 usb_drv_stall(EP_CONTROL, true, true);
350 logf("usb_handle_setup_rx() failed");
351 return;
352 }
353
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]);
355}
356
357static void usb_handle_data_int(int ep, int dir)
358{
359 int len;
360 if (dir == DIR_TX)
361 len = usb_send(ep);
362 else
363 {
364 len = usb_receive(ep);
365 endpoints[ep].in_ack = 1;
366 }
367 logf("usb_handle_data_int(%d, %d) finished", ep, dir);
368 (void)len;
369}
370
371bool usb_drv_powered(void)
372{
373#if 0
374 return (ISP1583_INIT_OTG & INIT_OTG_BSESS_VALID) ? true : false;
375#else
376 return (ISP1583_INIT_MODE & INIT_MODE_VBUSSTAT) ? true : false;
377#endif
378}
379
380static void setup_endpoints(void)
381{
382 int i;
383 int max_pkt_size = (high_speed_mode ? 512 : 64);
384
385 usb_setup_endpoint(ep_index(EP_CONTROL, DIR_RX), 64,
386 USB_ENDPOINT_XFER_CONTROL);
387 usb_setup_endpoint(ep_index(EP_CONTROL, DIR_TX), 64,
388 USB_ENDPOINT_XFER_CONTROL);
389
390 for(i = 1; i < USB_NUM_ENDPOINTS-1; i++)
391 {
392 usb_setup_endpoint(ep_index(i, DIR_RX), max_pkt_size,
393 USB_ENDPOINT_XFER_BULK);
394 usb_setup_endpoint(ep_index(i, DIR_TX), max_pkt_size,
395 USB_ENDPOINT_XFER_BULK);
396 }
397
398 usb_enable_endpoint(ep_index(EP_CONTROL, DIR_RX));
399 usb_enable_endpoint(ep_index(EP_CONTROL, DIR_TX));
400
401 for (i = 1; i < USB_NUM_ENDPOINTS-1; i++)
402 {
403 usb_enable_endpoint(ep_index(i, DIR_RX));
404 usb_enable_endpoint(ep_index(i, DIR_TX));
405 }
406
407 ZVM_SPECIFIC;
408}
409
410#if 0 /* currently unused */
411static void usb_helper(void)
412{
413 if(ISP1583_GEN_INT_READ & ISP1583_INIT_INTEN_READ)
414 {
415 logf("Helper detected interrupt... [%d]", (int)current_tick);
416 usb_drv_int();
417 }
418}
419#endif
420
421void usb_drv_init(void)
422{
423 /* Disable interrupt at CPU level */
424 DIS_INT_CPU_TARGET;
425
426 /* Unlock the device's registers */
427 ISP1583_GEN_UNLCKDEV = ISP1583_UNLOCK_CODE;
428
429 /* Soft reset the device */
430 ISP1583_INIT_MODE = INIT_MODE_SFRESET;
431 sleep(10);
432 /* Enable CLKAON & GLINTENA */
433 ISP1583_INIT_MODE = STANDARD_INIT_MODE;
434
435 /* Disable all OTG functions */
436 ISP1583_INIT_OTG = 0;
437
438#ifdef DEBUG
439 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));
440 logf("Chip ID: 0x%x", ISP1583_GEN_CHIPID);
441 //logf("INV0: 0x% IRQEDGE: 0x%x IRQPORT: 0x%x", IO_GIO_INV0, IO_GIO_IRQEDGE, IO_GIO_IRQPORT);
442#endif
443
444 /*Set interrupt generation to target-specific mode +
445 * Set the control pipe to ACK only interrupt +
446 * Set the IN pipe to ACK only interrupt +
447 * Set OUT pipe to ACK and NYET interrupt
448 */
449
450 ISP1583_INIT_INTCONF = 0x54 | INT_CONF_TARGET;
451 /* Clear all interrupts */
452 set_int_value(ISP1583_GEN_INT_A, ISP1583_GEN_INT_B, 0xFFFFFFFF);
453 /* Enable USB interrupts */
454 set_int_value(ISP1583_INIT_INTEN_A, ISP1583_INIT_INTEN_B, STANDARD_INTEN);
455
456 ZVM_SPECIFIC;
457
458 /* Enable interrupt at CPU level */
459 EN_INT_CPU_TARGET;
460
461 setup_endpoints();
462
463 /* Clear device address and disable it */
464 ISP1583_INIT_ADDRESS = 0;
465
466 /* Turn SoftConnect on */
467 ISP1583_INIT_MODE |= INIT_MODE_SOFTCT;
468
469 ZVM_SPECIFIC;
470
471 //tick_add_task(usb_helper);
472
473 logf("usb_init_device() finished");
474}
475
476int usb_drv_port_speed(void)
477{
478 return (int)high_speed_mode;
479}
480
481void usb_drv_exit(void)
482{
483 logf("usb_drv_exit()");
484
485 /* Disable device */
486 ISP1583_INIT_MODE &= ~INIT_MODE_SOFTCT;
487 ISP1583_INIT_ADDRESS = 0;
488
489 /* Disable interrupts */
490 set_int_value(ISP1583_INIT_INTEN_A, ISP1583_INIT_INTEN_B, 0);
491 /* and the CPU's one... */
492 DIS_INT_CPU_TARGET;
493
494
495 /* Send usb controller to suspend mode */
496 ISP1583_INIT_MODE = INIT_MODE_GOSUSP;
497 ISP1583_INIT_MODE = 0;
498
499 //tick_remove_task(usb_helper);
500
501 ZVM_SPECIFIC;
502}
503
504void usb_drv_stall(int endpoint, bool stall, bool in)
505{
506 logf("%sstall EP%d %s", (stall ? "" : "un"), endpoint, (in ? "RX" : "TX" ));
507 if (stall)
508 usb_stall_endpoint(ep_index(endpoint, (int)in));
509 else
510 usb_unstall_endpoint(ep_index(endpoint, (int)in));
511}
512
513bool usb_drv_stalled(int endpoint, bool in)
514{
515 return (endpoints[endpoint].halt[(int)in] == 1);
516}
517
518static void out_callback(int ep, unsigned char *buf, int len)
519{
520 (void)buf;
521 logf("out_callback(%d, 0x%x, %d)", ep, (int)buf, len);
522 usb_status_ack(ep, DIR_RX);
523 usb_core_transfer_complete(ep, true, 0, len); /* 0=>status succeeded, haven't worked out status failed yet... */
524}
525
526static void in_callback(int ep, unsigned char *buf, int len)
527{
528 (void)buf;
529 logf("in_callback(%d, 0x%x, %d)", ep, (int)buf, len);
530 usb_status_ack(ep, DIR_TX);
531 usb_core_transfer_complete(ep, false, 0, len);
532}
533
534int usb_drv_recv_nonblocking(int ep, void* ptr, int length)
535{
536 logf("usb_drv_recv_nonblocking(%d, 0x%x, %d)", ep, (int)ptr, length);
537 if(ep == EP_CONTROL && length == 0 && ptr == NULL)
538 {
539 usb_status_ack(ep, DIR_TX);
540 return 0;
541 }
542 endpoints[ep].in_done = in_callback;
543 endpoints[ep].in_buf = ptr;
544 endpoints[ep].in_max_len = length;
545 endpoints[ep].in_min_len = length;
546 endpoints[ep].in_ptr = 0;
547 if(ep == EP_CONTROL)
548 {
549 usb_data_stage_enable(ep, DIR_RX);
550 return usb_receive(ep);
551 }
552 else
553 return usb_receive(ep);
554}
555
556int usb_drv_send_nonblocking(int ep, void* ptr, int length)
557{
558 /* First implement DMA... */
559 return usb_drv_send(ep, ptr, length);
560}
561
562static void usb_drv_wait(int ep, bool send)
563{
564 logf("usb_drv_wait(%d, %d)", ep, send);
565 if(send)
566 {
567 while (endpoints[ep].out_in_progress)
568 nop_f();
569 }
570 else
571 {
572 while (endpoints[ep].in_ack)
573 nop_f();
574 }
575}
576
577int usb_drv_send(int ep, void* ptr, int length)
578{
579 logf("usb_drv_send_nb(%d, 0x%x, %d)", ep, (int)ptr, length);
580 if(ep == EP_CONTROL && length == 0 && ptr == NULL)
581 {
582 usb_status_ack(ep, DIR_RX);
583 return 0;
584 }
585 if(endpoints[ep].out_in_progress == 1)
586 return -1;
587 endpoints[ep].out_done = out_callback;
588 endpoints[ep].out_buf = ptr;
589 endpoints[ep].out_len = length;
590 endpoints[ep].out_ptr = 0;
591 endpoints[ep].out_in_progress = 1;
592 if(ep == EP_CONTROL)
593 {
594 int rc = usb_send(ep);
595 usb_data_stage_enable(ep, DIR_TX);
596 usb_drv_wait(ep, DIR_TX);
597 return rc;
598 }
599 else
600 return usb_send(ep);
601}
602
603void usb_drv_reset_endpoint(int ep, bool send)
604{
605 logf("reset endpoint(%d, %d)", ep, send);
606 usb_setup_endpoint(ep_index(ep, (int)send), endpoints[ep].max_pkt_size[(int)send], endpoints[ep].type);
607 usb_enable_endpoint(ep_index(ep, (int)send));
608}
609
610void usb_drv_cancel_all_transfers(void)
611{
612 logf("usb_drv_cancel_all_tranfers()");
613 int i;
614
615 for(i=0;i<USB_NUM_ENDPOINTS-1;i++)
616 endpoints[i].halt[0] = endpoints[i].halt[1] = 1;
617}
618
619int usb_drv_request_endpoint(int type, int dir)
620{
621 int i, bit;
622
623 if (type != USB_ENDPOINT_XFER_BULK)
624 return -1;
625
626 bit=(dir & USB_DIR_IN)? 2:1;
627
628 for (i=1; i < USB_NUM_ENDPOINTS; i++) {
629 if((endpoints[i].allocation & bit)!=0)
630 continue;
631 endpoints[i].allocation |= bit;
632 return i | dir;
633 }
634
635 return -1;
636}
637
638void usb_drv_release_endpoint(int ep)
639{
640 int mask = (ep & USB_DIR_IN)? ~2:~1;
641 endpoints[ep & 0x7f].allocation &= mask;
642}
643
644static void bus_reset(void)
645{
646 /* Enable CLKAON & GLINTENA */
647 ISP1583_INIT_MODE = STANDARD_INIT_MODE;
648 /* Enable USB interrupts */
649 ISP1583_INIT_INTCONF = 0x54 | INT_CONF_TARGET;
650 set_int_value(ISP1583_INIT_INTEN_A, ISP1583_INIT_INTEN_B, STANDARD_INTEN);
651
652 /* Disable all OTG functions */
653 ISP1583_INIT_OTG = 0;
654
655 /* Clear device address and enable it */
656 ISP1583_INIT_ADDRESS = INIT_ADDRESS_DEVEN;
657
658 ZVM_SPECIFIC;
659
660 /* Reset endpoints to default */
661 setup_endpoints();
662
663 logf("bus reset->done");
664}
665
666/* Method for handling interrupts, must be called from usb-<target>.c */
667void IRAM_ATTR usb_drv_int(void)
668{
669 unsigned long ints;
670 ints = ISP1583_GEN_INT_READ & ISP1583_INIT_INTEN_READ;
671
672 if(!ints)
673 return;
674
675 /* Unlock the device's registers */
676 ISP1583_GEN_UNLCKDEV = ISP1583_UNLOCK_CODE;
677
678 //logf(" handling int [0x%lx & 0x%lx = 0x%x]", ISP1583_GEN_INT_READ, ISP1583_INIT_INTEN_READ, (int)ints);
679
680 if(ints & INT_IEBRST) /* Bus reset */
681 {
682 logf("BRESET");
683 high_speed_mode = false;
684 bus_reset();
685 usb_core_bus_reset();
686 /* Mask bus reset interrupt */
687 set_int_value(ISP1583_GEN_INT_A, ISP1583_GEN_INT_B, INT_IEBRST);
688 return;
689 }
690 if(ints & INT_IEP0SETUP) /* EP0SETUP interrupt */
691 {
692 logf("EP0SETUP");
693 usb_handle_setup_rx();
694 }
695 if(ints & INT_IEHS_STA) /* change from full-speed to high-speed mode -> endpoints need to get reconfigured!! */
696 {
697 logf("HS_STA");
698 high_speed_mode = true;
699 setup_endpoints();
700 }
701 if(ints & INT_EP_MASK) /* Endpoints interrupt */
702 {
703 unsigned long ep_event;
704 unsigned short i = 10;
705 ep_event = ints & INT_EP_MASK;
706 while(ep_event)
707 {
708 if(i>25)
709 break;
710
711 if(ep_event & (1 << i))
712 {
713 logf("EP%d %s interrupt", (i - 10) / 2, i % 2 ? "RX" : "TX");
714 usb_handle_data_int((i - 10) / 2, i % 2);
715 ep_event &= ~(1 << i);
716 }
717 i++;
718 }
719 }
720 if(ints & INT_IERESM && !(ints & INT_IESUSP)) /* Resume status: status change from suspend to resume (active) */
721 {
722 logf("RESM");
723 }
724 if(ints & INT_IESUSP && !(ints & INT_IERESM)) /* Suspend status: status change from active to suspend */
725 {
726 logf("SUSP");
727 }
728 if(ints & INT_IEDMA) /* change in the DMA Interrupt Reason register */
729 {
730 logf("DMA");
731 }
732 if(ints & INT_IEVBUS) /* transition from LOW to HIGH on VBUS */
733 {
734 logf("VBUS");
735 }
736 /* Mask all (enabled) interrupts */
737 set_int_value(ISP1583_GEN_INT_A, ISP1583_GEN_INT_B, ints);
738
739 ZVM_SPECIFIC;
740}
741
742void usb_drv_set_address(int address)
743{
744 logf("usb_drv_set_address(0x%x)", address);
745 ISP1583_INIT_ADDRESS = (address & 0x7F) | INIT_ADDRESS_DEVEN;
746
747 ZVM_SPECIFIC;
748}
749
750void usb_drv_set_test_mode(int mode)
751{
752 logf("usb_drv_set_test_mode(%d)", mode);
753 switch(mode){
754 case 0:
755 ISP1583_GEN_TSTMOD = 0;
756 /* Power cycle... */
757 break;
758 case 1:
759 ISP1583_GEN_TSTMOD = GEN_TSTMOD_JSTATE;
760 break;
761 case 2:
762 ISP1583_GEN_TSTMOD = GEN_TSTMOD_KSTATE;
763 break;
764 case 3:
765 ISP1583_GEN_TSTMOD = GEN_TSTMOD_SE0_NAK;
766 break;
767 case 4:
768 //REG_PORTSC1 |= PORTSCX_PTC_PACKET;
769 break;
770 case 5:
771 //REG_PORTSC1 |= PORTSCX_PTC_FORCE_EN;
772 break;
773 }
774}
775
776#ifndef BOOTLOADER
777int dbg_usb_num_items(void)
778{
779 return 2+USB_NUM_ENDPOINTS*2;
780}
781
782const char* dbg_usb_item(int selected_item, void *data,
783 char *buffer, size_t buffer_len)
784{
785 if(selected_item < 2)
786 {
787 switch(selected_item)
788 {
789 case 0:
790 snprintf(buffer, buffer_len, "USB connected: %s", (usb_drv_connected() ? "Yes" : "No"));
791 return buffer;
792 case 1:
793 snprintf(buffer, buffer_len, "HS mode: %s", (high_speed_mode ? "Yes" : "No"));
794 return buffer;
795 }
796 }
797 else
798 {
799 int n = ep_index((selected_item - 2) / 2, (selected_item - 2) % 2);
800 if(endpoints[n].enabled == false)
801 snprintf(buffer, buffer_len, "EP%d[%s]: DISABLED", epidx_n(n), (epidx_dir(n) ? "TX" : "RX"));
802 else
803 {
804 if(epidx_dir(n))
805 {
806 if(endpoints[n].out_in_progress)
807 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 else
809 snprintf(buffer, buffer_len, "EP%d[TX]: STANDBY", epidx_n(n));
810 }
811 else
812 {
813 if(endpoints[n].in_buf && !endpoints[n].in_ack)
814 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 else
816 snprintf(buffer, buffer_len, "EP%d[RX]: STANDBY", epidx_n(n));
817 }
818 }
819 return buffer;
820 }
821 return NULL;
822 (void)data;
823}
824#endif