3 /*-----------------------------------------------------------------------------
\r
5 * Common USB code for FX2
\r
7 *-----------------------------------------------------------------------------
\r
9 * Code taken from USRP2 firmware (GNU Radio Project), version 3.0.2,
\r
11 * Copyright 2003 Free Software Foundation, Inc.
\r
13 *-----------------------------------------------------------------------------
\r
15 * This code is part of usbjtag. usbjtag is free software; you can redistribute
\r
17 * it and/or modify it under the terms of the GNU General Public License as
\r
19 * published by the Free Software Foundation; either version 2 of the License,
\r
21 * or (at your option) any later version. usbjtag is distributed in the hope
\r
23 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
\r
25 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
27 * GNU General Public License for more details. You should have received a
\r
29 * copy of the GNU General Public License along with this program in the file
\r
31 * COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin
\r
33 * St, Fifth Floor, Boston, MA 02110-1301 USA
\r
35 *-----------------------------------------------------------------------------
\r
41 #include "usb_common.h"
\r
43 #include "fx2regs.h"
\r
45 #include "syncdelay.h"
\r
47 #include "fx2utils.h"
\r
51 #include "usb_descriptors.h"
\r
53 #include "usb_requests.h"
\r
57 extern xdata char str0[];
\r
59 extern xdata char str1[];
\r
61 extern xdata char str2[];
\r
63 extern xdata char str3[];
\r
65 extern xdata char str4[];
\r
67 extern xdata char str5[];
\r
71 volatile bit _usb_got_SUDAV;
\r
75 unsigned char _usb_config = 0;
\r
77 unsigned char _usb_alt_setting = 0; // FIXME really 1/interface
\r
81 xdata unsigned char *current_device_descr;
\r
83 xdata unsigned char *current_devqual_descr;
\r
85 xdata unsigned char *current_config_descr;
\r
87 xdata unsigned char *other_config_descr;
\r
93 setup_descriptors (void)
\r
97 if (USBCS & bmHSM){ // high speed mode
\r
99 current_device_descr = high_speed_device_descr;
\r
101 current_devqual_descr = high_speed_devqual_descr;
\r
103 current_config_descr = high_speed_config_descr;
\r
105 other_config_descr = full_speed_config_descr;
\r
107 EP8AUTOINLENH = 0x02; SYNCDELAY; // Size in bytes of the IN data automatically commited (512 bytes here)
\r
109 EP8AUTOINLENL = 0x00; SYNCDELAY; // Can use signal PKTEND if you want to commit a shorter packet
\r
115 current_device_descr = full_speed_device_descr;
\r
117 current_devqual_descr = full_speed_devqual_descr;
\r
119 current_config_descr = full_speed_config_descr;
\r
121 other_config_descr = high_speed_config_descr;
\r
123 EP8AUTOINLENH = 0x00; SYNCDELAY; // Size in bytes of the IN data automatically commited (64 bytes here)
\r
125 EP8AUTOINLENL = 0x40; SYNCDELAY; // Can use signal PKTEND if you want to commit a shorter packet
\r
131 // whack the type fields
\r
133 // FIXME, may not be required.
\r
135 // current_config_descr[1] = DT_CONFIG;
\r
137 // other_config_descr[1] = DT_OTHER_SPEED;
\r
145 isr_SUDAV (void) interrupt
\r
151 _usb_got_SUDAV = 1;
\r
159 isr_USBRESET (void) interrupt
\r
165 setup_descriptors ();
\r
173 isr_HIGHSPEED (void) interrupt
\r
179 setup_descriptors ();
\r
187 usb_install_handlers (void)
\r
191 setup_descriptors (); // ensure that they're set before use
\r
195 hook_uv (UV_SUDAV, (unsigned short) isr_SUDAV);
\r
197 hook_uv (UV_USBRESET, (unsigned short) isr_USBRESET);
\r
199 hook_uv (UV_HIGHSPEED, (unsigned short) isr_HIGHSPEED);
\r
203 USBIE = bmSUDAV | bmURES | bmHSGRANT;
\r
209 // On the FX2 the only plausible endpoints are 0, 1, 2, 4, 6, 8
\r
211 // This doesn't check to see that they're enabled
\r
217 plausible_endpoint (unsigned char ep)
\r
221 ep &= ~0x80; // ignore direction bit
\r
237 return (ep & 0x1) == 0; // must be even
\r
243 // return pointer to control and status register for endpoint.
\r
245 // only called with plausible_endpoints
\r
249 xdata volatile unsigned char *
\r
251 epcs (unsigned char ep)
\r
255 if (ep == 0x01) // ep1 has different in and out CS regs
\r
267 ep &= ~0x80; // ignore direction bit
\r
271 if (ep == 0x00) // ep0
\r
277 return EP2CS + (ep >> 1); // 2, 4, 6, 8 are consecutive
\r
285 usb_handle_setup_packet (void)
\r
289 _usb_got_SUDAV = 0;
\r
293 // handle the standard requests...
\r
297 switch (bRequestType & bmRT_TYPE_MASK){
\r
301 case bmRT_TYPE_CLASS:
\r
303 case bmRT_TYPE_RESERVED:
\r
305 fx2_stall_ep0 (); // we don't handle these. indicate error
\r
311 case bmRT_TYPE_VENDOR:
\r
313 // call the application code.
\r
315 // If it handles the command it returns non-zero
\r
319 if (!app_vendor_cmd ())
\r
327 case bmRT_TYPE_STD:
\r
329 // these are the standard requests...
\r
333 if ((bRequestType & bmRT_DIR_MASK) == bmRT_DIR_IN){
\r
337 ////////////////////////////////////
\r
339 // handle the IN requests
\r
341 ////////////////////////////////////
\r
349 case RQ_GET_CONFIG:
\r
351 EP0BUF[0] = _usb_config; // FIXME app should handle
\r
361 // --------------------------------
\r
365 case RQ_GET_INTERFACE:
\r
367 EP0BUF[0] = _usb_alt_setting; // FIXME app should handle
\r
377 // --------------------------------
\r
389 SUDPTRH = MSB (current_device_descr);
\r
391 SUDPTRL = LSB (current_device_descr);
\r
399 SUDPTRH = MSB (current_devqual_descr);
\r
401 SUDPTRL = LSB (current_devqual_descr);
\r
409 if (0 && wValueL != 1) // FIXME only a single configuration
\r
415 SUDPTRH = MSB (current_config_descr);
\r
417 SUDPTRL = LSB (current_config_descr);
\r
425 case DT_OTHER_SPEED:
\r
427 if (0 && wValueL != 1) // FIXME only a single configuration
\r
433 SUDPTRH = MSB (other_config_descr);
\r
435 SUDPTRL = LSB (other_config_descr);
\r
445 if (wValueL >= nstring_descriptors)
\r
451 xdata char *p = string_descriptors[wValueL];
\r
465 fx2_stall_ep0 (); // invalid request
\r
475 // --------------------------------
\r
479 case RQ_GET_STATUS:
\r
481 switch (bRequestType & bmRT_RECIP_MASK){
\r
483 case bmRT_RECIP_DEVICE:
\r
497 case bmRT_RECIP_INTERFACE:
\r
511 case bmRT_RECIP_ENDPOINT:
\r
513 if (plausible_endpoint (wIndexL)){
\r
515 EP0BUF[0] = *epcs (wIndexL) & bmEPSTALL;
\r
545 // --------------------------------
\r
549 case RQ_SYNCH_FRAME: // not implemented
\r
567 ////////////////////////////////////
\r
569 // handle the OUT requests
\r
571 ////////////////////////////////////
\r
579 case RQ_SET_CONFIG:
\r
583 _usb_config = wValueL; // FIXME app should handle
\r
589 case RQ_SET_INTERFACE:
\r
591 _usb_alt_setting = wValueL; // FIXME app should handle
\r
597 // --------------------------------
\r
601 case RQ_CLEAR_FEATURE:
\r
603 switch (bRequestType & bmRT_RECIP_MASK){
\r
607 case bmRT_RECIP_DEVICE:
\r
611 case FS_DEV_REMOTE_WAKEUP:
\r
623 case bmRT_RECIP_ENDPOINT:
\r
625 if (wValueL == FS_ENDPOINT_HALT && plausible_endpoint (wIndexL)){
\r
627 *epcs (wIndexL) &= ~bmEPSTALL;
\r
629 fx2_reset_data_toggle (wIndexL);
\r
653 // --------------------------------
\r
657 case RQ_SET_FEATURE:
\r
659 switch (bRequestType & bmRT_RECIP_MASK){
\r
663 case bmRT_RECIP_DEVICE:
\r
669 // hardware handles this after we complete SETUP phase handshake
\r
675 case FS_DEV_REMOTE_WAKEUP:
\r
691 case bmRT_RECIP_ENDPOINT:
\r
695 case FS_ENDPOINT_HALT:
\r
697 if (plausible_endpoint (wIndexL))
\r
699 *epcs (wIndexL) |= bmEPSTALL;
\r
721 // --------------------------------
\r
725 case RQ_SET_ADDRESS: // handled by fx2 hardware
\r
727 case RQ_SET_DESCR: // not implemented
\r
743 } // bmRT_TYPE_MASK
\r
747 // ack handshake phase of device request
\r