Dependents:   TimeZoneDemo EthernetJackTestCode MMEx_Challenge ntp_mem ... more

Committer:
segundo
Date:
Tue Nov 09 20:54:15 2010 +0000
Revision:
0:ac1725ba162c

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1
segundo 0:ac1725ba162c 2 /*
segundo 0:ac1725ba162c 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
segundo 0:ac1725ba162c 4
segundo 0:ac1725ba162c 5 Permission is hereby granted, free of charge, to any person obtaining a copy
segundo 0:ac1725ba162c 6 of this software and associated documentation files (the "Software"), to deal
segundo 0:ac1725ba162c 7 in the Software without restriction, including without limitation the rights
segundo 0:ac1725ba162c 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
segundo 0:ac1725ba162c 9 copies of the Software, and to permit persons to whom the Software is
segundo 0:ac1725ba162c 10 furnished to do so, subject to the following conditions:
segundo 0:ac1725ba162c 11
segundo 0:ac1725ba162c 12 The above copyright notice and this permission notice shall be included in
segundo 0:ac1725ba162c 13 all copies or substantial portions of the Software.
segundo 0:ac1725ba162c 14
segundo 0:ac1725ba162c 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
segundo 0:ac1725ba162c 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
segundo 0:ac1725ba162c 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
segundo 0:ac1725ba162c 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
segundo 0:ac1725ba162c 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
segundo 0:ac1725ba162c 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
segundo 0:ac1725ba162c 21 THE SOFTWARE.
segundo 0:ac1725ba162c 22 */
segundo 0:ac1725ba162c 23
segundo 0:ac1725ba162c 24 #include "UsbDevice.h"
segundo 0:ac1725ba162c 25
segundo 0:ac1725ba162c 26 #include "netCfg.h"
segundo 0:ac1725ba162c 27 #if NET_USB
segundo 0:ac1725ba162c 28
segundo 0:ac1725ba162c 29 //#define __DEBUG
segundo 0:ac1725ba162c 30 #include "dbg/dbg.h"
segundo 0:ac1725ba162c 31
segundo 0:ac1725ba162c 32 UsbDevice::UsbDevice( UsbHostMgr* pMgr, int hub, int port, int addr ) : m_pControlEp(NULL), /*m_controlEp( this, 0x00, false, USB_CONTROL, 8 ),*/
segundo 0:ac1725ba162c 33 m_pMgr(pMgr), m_connected(false), m_enumerated(false), m_hub(hub), m_port(port), m_addr(addr), m_refs(0),
segundo 0:ac1725ba162c 34 m_vid(0), m_pid(0)
segundo 0:ac1725ba162c 35 {
segundo 0:ac1725ba162c 36
segundo 0:ac1725ba162c 37 }
segundo 0:ac1725ba162c 38
segundo 0:ac1725ba162c 39 UsbDevice::~UsbDevice()
segundo 0:ac1725ba162c 40 {
segundo 0:ac1725ba162c 41 if(m_pControlEp)
segundo 0:ac1725ba162c 42 delete m_pControlEp;
segundo 0:ac1725ba162c 43 }
segundo 0:ac1725ba162c 44
segundo 0:ac1725ba162c 45 UsbErr UsbDevice::enumerate()
segundo 0:ac1725ba162c 46 {
segundo 0:ac1725ba162c 47 // USB_INT32S rc;
segundo 0:ac1725ba162c 48
segundo 0:ac1725ba162c 49 UsbErr rc;
segundo 0:ac1725ba162c 50
segundo 0:ac1725ba162c 51 DBG("Starting enumeration (m_pMgr = %p)\n", m_pMgr);
segundo 0:ac1725ba162c 52
segundo 0:ac1725ba162c 53 #if 1
segundo 0:ac1725ba162c 54 m_pMgr->resetPort(m_hub, m_port);
segundo 0:ac1725ba162c 55 #else
segundo 0:ac1725ba162c 56 wait_ms(100); /* USB 2.0 spec says atleast 50ms delay beore port reset */
segundo 0:ac1725ba162c 57 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
segundo 0:ac1725ba162c 58 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
segundo 0:ac1725ba162c 59 __WFI(); // Wait for port reset to complete...
segundo 0:ac1725ba162c 60 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
segundo 0:ac1725ba162c 61 wait_ms(200); /* Wait for 100 MS after port reset */
segundo 0:ac1725ba162c 62 #endif
segundo 0:ac1725ba162c 63
segundo 0:ac1725ba162c 64 DBG("Port reset\n");
segundo 0:ac1725ba162c 65
segundo 0:ac1725ba162c 66 wait_ms(200);
segundo 0:ac1725ba162c 67
segundo 0:ac1725ba162c 68 m_pControlEp = new UsbEndpoint( this, 0x00, false, USB_CONTROL, 8, 0 );
segundo 0:ac1725ba162c 69
segundo 0:ac1725ba162c 70 //EDCtrl->Control = 8 << 16;/* Put max pkt size = 8 */
segundo 0:ac1725ba162c 71 /* Read first 8 bytes of device desc */
segundo 0:ac1725ba162c 72 rc = controlReceive(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR, (USB_DESCRIPTOR_TYPE_DEVICE << 8)|(0), 0, m_controlDataBuf, 8);
segundo 0:ac1725ba162c 73 if (rc)
segundo 0:ac1725ba162c 74 {
segundo 0:ac1725ba162c 75 DBG("RC=%d",rc);
segundo 0:ac1725ba162c 76 return (rc);
segundo 0:ac1725ba162c 77 }
segundo 0:ac1725ba162c 78
segundo 0:ac1725ba162c 79 DBG("Got descriptor, max ep size is %d\n", m_controlDataBuf[7]);
segundo 0:ac1725ba162c 80
segundo 0:ac1725ba162c 81 m_pControlEp->updateSize(m_controlDataBuf[7]); /* Get max pkt size of endpoint 0 */
segundo 0:ac1725ba162c 82 rc = controlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_ADDRESS, m_addr, 0, NULL, 0); /* Set the device address to m_addr */
segundo 0:ac1725ba162c 83 if (rc)
segundo 0:ac1725ba162c 84 {
segundo 0:ac1725ba162c 85 // PRINT_Err(rc);
segundo 0:ac1725ba162c 86 return (rc);
segundo 0:ac1725ba162c 87 }
segundo 0:ac1725ba162c 88 wait_ms(2);
segundo 0:ac1725ba162c 89 //EDCtrl->Control = (EDCtrl->Control) | 1; /* Modify control pipe with address 1 */
segundo 0:ac1725ba162c 90
segundo 0:ac1725ba162c 91 //Update address
segundo 0:ac1725ba162c 92 m_pControlEp->updateAddr(m_addr);
segundo 0:ac1725ba162c 93 DBG("Ep addr is now %d", m_addr);
segundo 0:ac1725ba162c 94 /**/
segundo 0:ac1725ba162c 95
segundo 0:ac1725ba162c 96 //rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_DEVICE, 0, TDBuffer, 17); //Read full device descriptor
segundo 0:ac1725ba162c 97 rc = controlReceive(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR, (USB_DESCRIPTOR_TYPE_DEVICE << 8)|(0), 0, m_controlDataBuf, 17);
segundo 0:ac1725ba162c 98 if (rc)
segundo 0:ac1725ba162c 99 {
segundo 0:ac1725ba162c 100 //PRINT_Err(rc);
segundo 0:ac1725ba162c 101 return (rc);
segundo 0:ac1725ba162c 102 }
segundo 0:ac1725ba162c 103 /*
segundo 0:ac1725ba162c 104 rc = SerialCheckVidPid();
segundo 0:ac1725ba162c 105 if (rc != OK) {
segundo 0:ac1725ba162c 106 PRINT_Err(rc);
segundo 0:ac1725ba162c 107 return (rc);
segundo 0:ac1725ba162c 108 }
segundo 0:ac1725ba162c 109 */
segundo 0:ac1725ba162c 110 /**/
segundo 0:ac1725ba162c 111
segundo 0:ac1725ba162c 112 m_vid = *((uint16_t*)&m_controlDataBuf[8]);
segundo 0:ac1725ba162c 113 m_pid = *((uint16_t*)&m_controlDataBuf[10]);
segundo 0:ac1725ba162c 114
segundo 0:ac1725ba162c 115 DBG("VID: %02x, PID: %02x\n", m_vid, m_pid);
segundo 0:ac1725ba162c 116 /* Get the configuration descriptor */
segundo 0:ac1725ba162c 117 //rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, TDBuffer, 9);
segundo 0:ac1725ba162c 118 rc = controlReceive(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR, (USB_DESCRIPTOR_TYPE_CONFIGURATION << 8)|(0), 0, m_controlDataBuf, 9);
segundo 0:ac1725ba162c 119 if (rc)
segundo 0:ac1725ba162c 120 {
segundo 0:ac1725ba162c 121 //PRINT_Err(rc);
segundo 0:ac1725ba162c 122 return (rc);
segundo 0:ac1725ba162c 123 }
segundo 0:ac1725ba162c 124 /* Get the first configuration data */
segundo 0:ac1725ba162c 125 //rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, TDBuffer, *((uint16_t*)&TDBuffer[2]));
segundo 0:ac1725ba162c 126 rc = controlReceive(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR, (USB_DESCRIPTOR_TYPE_CONFIGURATION << 8)|(0), 0, m_controlDataBuf, *((uint16_t*)&m_controlDataBuf[2]));
segundo 0:ac1725ba162c 127 if (rc)
segundo 0:ac1725ba162c 128 {
segundo 0:ac1725ba162c 129 //PRINT_Err(rc);
segundo 0:ac1725ba162c 130 return (rc);
segundo 0:ac1725ba162c 131 }
segundo 0:ac1725ba162c 132
segundo 0:ac1725ba162c 133 DBG("Desc len is %d\n", *((uint16_t*)&m_controlDataBuf[2]));
segundo 0:ac1725ba162c 134
segundo 0:ac1725ba162c 135 DBG("Set configuration\n");
segundo 0:ac1725ba162c 136
segundo 0:ac1725ba162c 137 //rc = USBH_SET_CONFIGURATION(1);/* Select device configuration 1 */
segundo 0:ac1725ba162c 138 rc = controlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_CONFIGURATION, 1, 0, NULL, 0);
segundo 0:ac1725ba162c 139 if (rc)
segundo 0:ac1725ba162c 140 {
segundo 0:ac1725ba162c 141 // PRINT_Err(rc);
segundo 0:ac1725ba162c 142 return rc;
segundo 0:ac1725ba162c 143 }
segundo 0:ac1725ba162c 144 wait_ms(100);/* Some devices may require this delay */
segundo 0:ac1725ba162c 145
segundo 0:ac1725ba162c 146 m_enumerated = true;
segundo 0:ac1725ba162c 147 return USBERR_OK;
segundo 0:ac1725ba162c 148 }
segundo 0:ac1725ba162c 149
segundo 0:ac1725ba162c 150 bool UsbDevice::connected()
segundo 0:ac1725ba162c 151 {
segundo 0:ac1725ba162c 152 return m_connected;
segundo 0:ac1725ba162c 153 }
segundo 0:ac1725ba162c 154
segundo 0:ac1725ba162c 155 bool UsbDevice::enumerated()
segundo 0:ac1725ba162c 156 {
segundo 0:ac1725ba162c 157 return m_enumerated;
segundo 0:ac1725ba162c 158 }
segundo 0:ac1725ba162c 159
segundo 0:ac1725ba162c 160 int UsbDevice::getPid()
segundo 0:ac1725ba162c 161 {
segundo 0:ac1725ba162c 162 return m_pid;
segundo 0:ac1725ba162c 163 }
segundo 0:ac1725ba162c 164
segundo 0:ac1725ba162c 165 int UsbDevice::getVid()
segundo 0:ac1725ba162c 166 {
segundo 0:ac1725ba162c 167 return m_vid;
segundo 0:ac1725ba162c 168 }
segundo 0:ac1725ba162c 169
segundo 0:ac1725ba162c 170 UsbErr UsbDevice::getConfigurationDescriptor(int config, uint8_t** pBuf)
segundo 0:ac1725ba162c 171 {
segundo 0:ac1725ba162c 172 //For now olny one config
segundo 0:ac1725ba162c 173 *pBuf = m_controlDataBuf;
segundo 0:ac1725ba162c 174 return USBERR_OK;
segundo 0:ac1725ba162c 175 }
segundo 0:ac1725ba162c 176
segundo 0:ac1725ba162c 177 UsbErr UsbDevice::getInterfaceDescriptor(int config, int item, uint8_t** pBuf)
segundo 0:ac1725ba162c 178 {
segundo 0:ac1725ba162c 179 byte* desc_ptr = m_controlDataBuf;
segundo 0:ac1725ba162c 180
segundo 0:ac1725ba162c 181 /* if (desc_ptr[1] != USB_DESCRIPTOR_TYPE_CONFIGURATION)
segundo 0:ac1725ba162c 182 {
segundo 0:ac1725ba162c 183 return USBERR_BADCONFIG;
segundo 0:ac1725ba162c 184 }*/
segundo 0:ac1725ba162c 185
segundo 0:ac1725ba162c 186 if(item>=m_controlDataBuf[4])//Interfaces count
segundo 0:ac1725ba162c 187 return USBERR_NOTFOUND;
segundo 0:ac1725ba162c 188
segundo 0:ac1725ba162c 189 desc_ptr += desc_ptr[0];
segundo 0:ac1725ba162c 190
segundo 0:ac1725ba162c 191 *pBuf = NULL;
segundo 0:ac1725ba162c 192
segundo 0:ac1725ba162c 193 while (desc_ptr < m_controlDataBuf + *((uint16_t*)&m_controlDataBuf[2]))
segundo 0:ac1725ba162c 194 {
segundo 0:ac1725ba162c 195
segundo 0:ac1725ba162c 196 switch (desc_ptr[1]) {
segundo 0:ac1725ba162c 197 case USB_DESCRIPTOR_TYPE_INTERFACE:
segundo 0:ac1725ba162c 198 if(desc_ptr[2] == item)
segundo 0:ac1725ba162c 199 {
segundo 0:ac1725ba162c 200 *pBuf = desc_ptr;
segundo 0:ac1725ba162c 201 return USBERR_OK;
segundo 0:ac1725ba162c 202 }
segundo 0:ac1725ba162c 203 desc_ptr += desc_ptr[0]; // Move to next descriptor start
segundo 0:ac1725ba162c 204 break;
segundo 0:ac1725ba162c 205 }
segundo 0:ac1725ba162c 206
segundo 0:ac1725ba162c 207 }
segundo 0:ac1725ba162c 208
segundo 0:ac1725ba162c 209 if(*pBuf == NULL)
segundo 0:ac1725ba162c 210 return USBERR_NOTFOUND;
segundo 0:ac1725ba162c 211
segundo 0:ac1725ba162c 212 return USBERR_OK;
segundo 0:ac1725ba162c 213 }
segundo 0:ac1725ba162c 214
segundo 0:ac1725ba162c 215
segundo 0:ac1725ba162c 216 UsbErr UsbDevice::setConfiguration(int config)
segundo 0:ac1725ba162c 217 {
segundo 0:ac1725ba162c 218 return USBERR_OK;
segundo 0:ac1725ba162c 219 }
segundo 0:ac1725ba162c 220
segundo 0:ac1725ba162c 221 UsbErr UsbDevice::controlSend(byte requestType, byte request, word value, word index, const byte* buf, int len)
segundo 0:ac1725ba162c 222 {
segundo 0:ac1725ba162c 223 UsbErr rc;
segundo 0:ac1725ba162c 224 fillControlBuf(requestType, request, value, index, len);
segundo 0:ac1725ba162c 225 m_pControlEp->setNextToken(TD_SETUP);
segundo 0:ac1725ba162c 226 rc = m_pControlEp->transfer(m_controlBuf, 8);
segundo 0:ac1725ba162c 227 while(m_pControlEp->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 228 rc = (UsbErr) MIN(0, m_pControlEp->status());
segundo 0:ac1725ba162c 229 if(rc)
segundo 0:ac1725ba162c 230 return rc;
segundo 0:ac1725ba162c 231 if(len)
segundo 0:ac1725ba162c 232 {
segundo 0:ac1725ba162c 233 m_pControlEp->setNextToken(TD_OUT);
segundo 0:ac1725ba162c 234 rc = m_pControlEp->transfer((byte*)buf, len);
segundo 0:ac1725ba162c 235 while(m_pControlEp->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 236 rc = (UsbErr) MIN(0, m_pControlEp->status());
segundo 0:ac1725ba162c 237 if(rc)
segundo 0:ac1725ba162c 238 return rc;
segundo 0:ac1725ba162c 239 }
segundo 0:ac1725ba162c 240 m_pControlEp->setNextToken(TD_IN);
segundo 0:ac1725ba162c 241 rc = m_pControlEp->transfer(NULL, 0);
segundo 0:ac1725ba162c 242 while(m_pControlEp->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 243 rc = (UsbErr) MIN(0, m_pControlEp->status());
segundo 0:ac1725ba162c 244 if(rc)
segundo 0:ac1725ba162c 245 return rc;
segundo 0:ac1725ba162c 246 return USBERR_OK;
segundo 0:ac1725ba162c 247 }
segundo 0:ac1725ba162c 248
segundo 0:ac1725ba162c 249 UsbErr UsbDevice::controlReceive(byte requestType, byte request, word value, word index, const byte* buf, int len)
segundo 0:ac1725ba162c 250 {
segundo 0:ac1725ba162c 251 UsbErr rc;
segundo 0:ac1725ba162c 252 fillControlBuf(requestType, request, value, index, len);
segundo 0:ac1725ba162c 253 m_pControlEp->setNextToken(TD_SETUP);
segundo 0:ac1725ba162c 254 rc = m_pControlEp->transfer(m_controlBuf, 8);
segundo 0:ac1725ba162c 255 while(m_pControlEp->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 256 rc = (UsbErr) MIN(0, m_pControlEp->status());
segundo 0:ac1725ba162c 257 if(rc)
segundo 0:ac1725ba162c 258 return rc;
segundo 0:ac1725ba162c 259 if(len)
segundo 0:ac1725ba162c 260 {
segundo 0:ac1725ba162c 261 m_pControlEp->setNextToken(TD_IN);
segundo 0:ac1725ba162c 262 rc = m_pControlEp->transfer( (byte*) buf, len);
segundo 0:ac1725ba162c 263 while(m_pControlEp->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 264 rc = (UsbErr) MIN(0, m_pControlEp->status());
segundo 0:ac1725ba162c 265 if(rc)
segundo 0:ac1725ba162c 266 return rc;
segundo 0:ac1725ba162c 267 }
segundo 0:ac1725ba162c 268 m_pControlEp->setNextToken(TD_OUT);
segundo 0:ac1725ba162c 269 rc = m_pControlEp->transfer(NULL, 0);
segundo 0:ac1725ba162c 270 while(m_pControlEp->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 271 rc = (UsbErr) MIN(0, m_pControlEp->status());
segundo 0:ac1725ba162c 272 if(rc)
segundo 0:ac1725ba162c 273 return rc;
segundo 0:ac1725ba162c 274 return USBERR_OK;
segundo 0:ac1725ba162c 275 }
segundo 0:ac1725ba162c 276
segundo 0:ac1725ba162c 277 void UsbDevice::fillControlBuf(byte requestType, byte request, word value, word index, int len)
segundo 0:ac1725ba162c 278 {
segundo 0:ac1725ba162c 279 #ifdef __BIG_ENDIAN
segundo 0:ac1725ba162c 280 #error "Must implement BE to LE conv here"
segundo 0:ac1725ba162c 281 #endif
segundo 0:ac1725ba162c 282 m_controlBuf[0] = requestType;
segundo 0:ac1725ba162c 283 m_controlBuf[1] = request;
segundo 0:ac1725ba162c 284 //We are in LE so it's fine
segundo 0:ac1725ba162c 285 *((word*)&m_controlBuf[2]) = value;
segundo 0:ac1725ba162c 286 *((word*)&m_controlBuf[4]) = index;
segundo 0:ac1725ba162c 287 *((word*)&m_controlBuf[6]) = (word) len;
segundo 0:ac1725ba162c 288 }
segundo 0:ac1725ba162c 289
segundo 0:ac1725ba162c 290
segundo 0:ac1725ba162c 291 #endif