1 /*
2 * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com
3 * MAX3421E USB host controller support
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the authors nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /* USB functions */
31 #ifndef _usb_h_
32 #define _usb_h_
33
34 #include <Max3421e.h>
35 #include "ch9.h"
36
37 /* Common setup data constant combinations */
38 #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
39 #define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface'
40 #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type
41 /* HID requests */
42 #define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
43 #define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
44 #define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
45
46 #define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
47 #define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted
48 #define USB_RETRY_LIMIT 3 //retry limit for a transfer
49 #define USB_SETTLE_DELAY 200 //settle delay in milliseconds
50 #define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
51
52 #define USB_NUMDEVICES 2 //number of USB devices
53
54 /* USB state machine states */
55
56 #define USB_STATE_MASK 0xf0
57
58 #define USB_STATE_DETACHED 0x10
59 #define USB_DETACHED_SUBSTATE_INITIALIZE 0x11
60 #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12
61 #define USB_DETACHED_SUBSTATE_ILLEGAL 0x13
62 #define USB_ATTACHED_SUBSTATE_SETTLE 0x20
63 #define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
64 #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40
65 #define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50
66 #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60
67 #define USB_STATE_ADDRESSING 0x70
68 #define USB_STATE_CONFIGURING 0x80
69 #define USB_STATE_RUNNING 0x90
70 #define USB_STATE_ERROR 0xa0
71
72 // byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE
73
74 /* USB Setup Packet Structure */
75 typedef struct {
76 union { // offset description
77 byte bmRequestType; // 0 Bit-map of request type
78 struct {
79 byte recipient: 5; // Recipient of the request
80 byte type: 2; // Type of request
81 byte direction: 1; // Direction of data X-fer
82 };
83 }ReqType_u;
84 byte bRequest; // 1 Request
85 union {
86 unsigned int wValue; // 2 Depends on bRequest
87 struct {
88 byte wValueLo;
89 byte wValueHi;
90 };
91 }wVal_u;
92 unsigned int wIndex; // 4 Depends on bRequest
93 unsigned int wLength; // 6 Depends on bRequest
94 } SETUP_PKT, *PSETUP_PKT;
95
96 /* Endpoint information structure */
97 /* bToggle of endpoint 0 initialized to 0xff */
98 /* during enumeration bToggle is set to 00 */
99 typedef struct {
100 byte epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
101 byte Attr; // Endpoint transfer type.
102 unsigned int MaxPktSize; // Maximum packet size.
103 byte Interval; // Polling interval in frames.
104 byte sndToggle; //last toggle value, bitmask for HCTL toggle bits
105 byte rcvToggle; //last toggle value, bitmask for HCTL toggle bits
106 /* not sure if both are necessary */
107 } EP_RECORD;
108 /* device record structure */
109 typedef struct {
110 EP_RECORD* epinfo; //device endpoint information
111 byte devclass; //device class
112 } DEV_RECORD;
113
114
115
116 class USB : public MAX3421E {
117 //data structures
118 /* device table. Filled during enumeration */
119 /* index corresponds to device address */
120 /* each entry contains pointer to endpoint structure */
121 /* and device class to use in various places */
122 //DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
123 //EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
124
125 //byte usb_task_state;
126
127 public:
128 USB( void );
129 byte getUsbTaskState( void );
130 void setUsbTaskState( byte state );
131 EP_RECORD* getDevTableEntry( byte addr, byte ep );
132 void setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr );
133 byte ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
134 /* Control requests */
135 byte getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
136 byte getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
137 byte getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
138 byte setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit = USB_NAK_LIMIT );
139 byte setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit = USB_NAK_LIMIT );
140 /**/
141 byte setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit = USB_NAK_LIMIT );
142 byte getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
143 byte getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
144 byte setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
145 byte getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
146 byte getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
147 byte setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit = USB_NAK_LIMIT );
148 /**/
149 byte ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );
150 byte ctrlStatus( byte ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );
151 byte inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT );
152 int newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT);
153 byte outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT );
154 byte dispatchPkt( byte token, byte ep, unsigned int nak_limit = USB_NAK_LIMIT );
155 void Task( void );
156 private:
157 void init();
158 };
159
160 //get device descriptor
getDevDescr(byte addr,byte ep,unsigned int nbytes,char * dataptr,unsigned int nak_limit)161 inline byte USB::getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) {
162 return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit ));
163 }
164 //get configuration descriptor
getConfDescr(byte addr,byte ep,unsigned int nbytes,byte conf,char * dataptr,unsigned int nak_limit)165 inline byte USB::getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit ) {
166 return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit ));
167 }
168 //get string descriptor
getStrDescr(byte addr,byte ep,unsigned int nbytes,byte index,unsigned int langid,char * dataptr,unsigned int nak_limit)169 inline byte USB::getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit ) {
170 return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit ));
171 }
172 //set address
setAddr(byte oldaddr,byte ep,byte newaddr,unsigned int nak_limit)173 inline byte USB::setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit ) {
174 return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit ));
175 }
176 //set configuration
setConf(byte addr,byte ep,byte conf_value,unsigned int nak_limit)177 inline byte USB::setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit ) {
178 return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit ));
179 }
180 //class requests
setProto(byte addr,byte ep,byte interface,byte protocol,unsigned int nak_limit)181 inline byte USB::setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit ) {
182 return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit ));
183 }
getProto(byte addr,byte ep,byte interface,char * dataptr,unsigned int nak_limit)184 inline byte USB::getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit ) {
185 return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit ));
186 }
187 //get HID report descriptor
getReportDescr(byte addr,byte ep,unsigned int nbytes,char * dataptr,unsigned int nak_limit)188 inline byte USB::getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) {
189 return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit ));
190 }
setReport(byte addr,byte ep,unsigned int nbytes,byte interface,byte report_type,byte report_id,char * dataptr,unsigned int nak_limit)191 inline byte USB::setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) {
192 return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));
193 }
getReport(byte addr,byte ep,unsigned int nbytes,byte interface,byte report_type,byte report_id,char * dataptr,unsigned int nak_limit)194 inline byte USB::getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) { // ** RI 04/11/09
195 return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));
196 }
197 /* returns one byte of data in dataptr */
getIdle(byte addr,byte ep,byte interface,byte reportID,char * dataptr,unsigned int nak_limit)198 inline byte USB::getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit ) {
199 return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit ));
200 }
setIdle(byte addr,byte ep,byte interface,byte reportID,byte duration,unsigned int nak_limit)201 inline byte USB::setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit ) {
202 return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit ));
203 }
204 #endif //_usb_h_
205