Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1702 | - | 1 | /* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ |
2 | /* USB functions */ |
||
3 | #ifndef _usb_h_ |
||
4 | #define _usb_h_ |
||
5 | |||
6 | #include <Max3421e.h> |
||
7 | #include "ch9.h" |
||
8 | |||
9 | /* Common setup data constant combinations */ |
||
10 | #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type |
||
11 | #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' |
||
12 | #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type |
||
13 | /* HID requests */ |
||
14 | #define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE |
||
15 | #define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE |
||
16 | #define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE |
||
17 | |||
18 | #define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec |
||
19 | #define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted |
||
20 | #define USB_RETRY_LIMIT 3 //retry limit for a transfer |
||
21 | #define USB_SETTLE_DELAY 200 //settle delay in milliseconds |
||
22 | #define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code |
||
23 | |||
24 | #define USB_NUMDEVICES 2 //number of USB devices |
||
25 | |||
26 | /* USB state machine states */ |
||
27 | |||
28 | #define USB_STATE_MASK 0xf0 |
||
29 | |||
30 | #define USB_STATE_DETACHED 0x10 |
||
31 | #define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 |
||
32 | #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 |
||
33 | #define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 |
||
34 | #define USB_ATTACHED_SUBSTATE_SETTLE 0x20 |
||
35 | #define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 |
||
36 | #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 |
||
37 | #define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 |
||
38 | #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 |
||
39 | #define USB_STATE_ADDRESSING 0x70 |
||
40 | #define USB_STATE_CONFIGURING 0x80 |
||
41 | #define USB_STATE_RUNNING 0x90 |
||
42 | #define USB_STATE_ERROR 0xa0 |
||
43 | |||
44 | // byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE |
||
45 | |||
46 | /* USB Setup Packet Structure */ |
||
47 | typedef struct { |
||
48 | union { // offset description |
||
49 | byte bmRequestType; // 0 Bit-map of request type |
||
50 | struct { |
||
51 | byte recipient: 5; // Recipient of the request |
||
52 | byte type: 2; // Type of request |
||
53 | byte direction: 1; // Direction of data X-fer |
||
54 | }; |
||
55 | }ReqType_u; |
||
56 | byte bRequest; // 1 Request |
||
57 | union { |
||
58 | unsigned int wValue; // 2 Depends on bRequest |
||
59 | struct { |
||
60 | byte wValueLo; |
||
61 | byte wValueHi; |
||
62 | }; |
||
63 | }wVal_u; |
||
64 | unsigned int wIndex; // 4 Depends on bRequest |
||
65 | unsigned int wLength; // 6 Depends on bRequest |
||
66 | } SETUP_PKT, *PSETUP_PKT; |
||
67 | |||
68 | /* Endpoint information structure */ |
||
69 | /* bToggle of endpoint 0 initialized to 0xff */ |
||
70 | /* during enumeration bToggle is set to 00 */ |
||
71 | typedef struct { |
||
72 | byte epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints ) |
||
73 | byte Attr; // Endpoint transfer type. |
||
74 | unsigned int MaxPktSize; // Maximum packet size. |
||
75 | byte Interval; // Polling interval in frames. |
||
76 | byte sndToggle; //last toggle value, bitmask for HCTL toggle bits |
||
77 | byte rcvToggle; //last toggle value, bitmask for HCTL toggle bits |
||
78 | /* not sure if both are necessary */ |
||
79 | } EP_RECORD; |
||
80 | /* device record structure */ |
||
81 | typedef struct { |
||
82 | EP_RECORD* epinfo; //device endpoint information |
||
83 | byte devclass; //device class |
||
84 | } DEV_RECORD; |
||
85 | |||
86 | |||
87 | |||
88 | class USB : public MAX3421E { |
||
89 | //data structures |
||
90 | /* device table. Filled during enumeration */ |
||
91 | /* index corresponds to device address */ |
||
92 | /* each entry contains pointer to endpoint structure */ |
||
93 | /* and device class to use in various places */ |
||
94 | //DEV_RECORD devtable[ USB_NUMDEVICES + 1 ]; |
||
95 | //EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device |
||
96 | |||
97 | //byte usb_task_state; |
||
98 | |||
99 | public: |
||
100 | USB( void ); |
||
101 | byte getUsbTaskState( void ); |
||
102 | void setUsbTaskState( byte state ); |
||
103 | EP_RECORD* getDevTableEntry( byte addr, byte ep ); |
||
104 | void setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr ); |
||
105 | 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 ); |
||
106 | /* Control requests */ |
||
107 | byte getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
108 | byte getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
109 | byte getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
110 | byte setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
111 | byte setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
112 | /**/ |
||
113 | byte setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
114 | byte getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
115 | byte getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
116 | 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 ); |
||
117 | 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 ); |
||
118 | byte getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
119 | byte setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
120 | /**/ |
||
121 | byte ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
122 | byte ctrlStatus( byte ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
123 | byte inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
124 | byte outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
125 | byte dispatchPkt( byte token, byte ep, unsigned int nak_limit = USB_NAK_LIMIT ); |
||
126 | void Task( void ); |
||
127 | private: |
||
128 | void init(); |
||
129 | }; |
||
130 | |||
131 | //get device descriptor |
||
132 | inline byte USB::getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) { |
||
133 | return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit )); |
||
134 | } |
||
135 | //get configuration descriptor |
||
136 | inline byte USB::getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit ) { |
||
137 | return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit )); |
||
138 | } |
||
139 | //get string descriptor |
||
140 | inline byte USB::getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit ) { |
||
141 | return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit )); |
||
142 | } |
||
143 | //set address |
||
144 | inline byte USB::setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit ) { |
||
145 | return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit )); |
||
146 | } |
||
147 | //set configuration |
||
148 | inline byte USB::setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit ) { |
||
149 | return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit )); |
||
150 | } |
||
151 | //class requests |
||
152 | inline byte USB::setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit ) { |
||
153 | return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit )); |
||
154 | } |
||
155 | inline byte USB::getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit ) { |
||
156 | return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit )); |
||
157 | } |
||
158 | //get HID report descriptor |
||
159 | inline byte USB::getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) { |
||
160 | return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit )); |
||
161 | } |
||
162 | 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 ) { |
||
163 | return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); |
||
164 | } |
||
165 | 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 |
||
166 | return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit )); |
||
167 | } |
||
168 | /* returns one byte of data in dataptr */ |
||
169 | inline byte USB::getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit ) { |
||
170 | return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit )); |
||
171 | } |
||
172 | inline byte USB::setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit ) { |
||
173 | return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit )); |
||
174 | } |
||
175 | #endif //_usb_h_ |