Takuya Urakawa / F401RE-USBHost

Dependencies:   FATFileSystem

Dependents:   F401RE-USBHostMIDI_RecieveExample

Fork of F401RE-USBHost by Norimasa Okamoto

Committer:
va009039
Date:
Thu Jan 23 08:32:54 2014 +0000
Revision:
2:0cdac6bcc534
Parent:
1:c072d9e580b0
add retry in token transfer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:5160ee0c522d 1 // Simple USBHost for FRDM-KL46Z
va009039 0:5160ee0c522d 2 #include "USBHost.h"
va009039 0:5160ee0c522d 3 #include <algorithm>
va009039 0:5160ee0c522d 4
va009039 0:5160ee0c522d 5 template <bool>struct CtAssert;
va009039 0:5160ee0c522d 6 template <>struct CtAssert<true> {};
va009039 0:5160ee0c522d 7 #define CTASSERT(A) CtAssert<A>();
va009039 0:5160ee0c522d 8
va009039 1:c072d9e580b0 9
va009039 1:c072d9e580b0 10 #ifdef _USB_DBG
va009039 1:c072d9e580b0 11 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
va009039 1:c072d9e580b0 12 #define USB_DBG_HEX(A,B) debug_hex(A,B)
va009039 0:5160ee0c522d 13 void debug_hex(uint8_t* buf, int size);
va009039 1:c072d9e580b0 14 #else
va009039 1:c072d9e580b0 15 #define USB_DBG(...) while(0)
va009039 1:c072d9e580b0 16 #define USB_DBG_HEX(A,B) while(0)
va009039 1:c072d9e580b0 17 #endif
va009039 1:c072d9e580b0 18
va009039 0:5160ee0c522d 19 #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
va009039 0:5160ee0c522d 20 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
va009039 0:5160ee0c522d 21
va009039 0:5160ee0c522d 22 USBHost* USBHost::inst = NULL;
va009039 0:5160ee0c522d 23
va009039 0:5160ee0c522d 24 USBHost* USBHost::getHostInst()
va009039 0:5160ee0c522d 25 {
va009039 0:5160ee0c522d 26 if (inst == NULL) {
va009039 0:5160ee0c522d 27 inst = new USBHost();
va009039 0:5160ee0c522d 28 inst->init();
va009039 0:5160ee0c522d 29 }
va009039 0:5160ee0c522d 30 return inst;
va009039 0:5160ee0c522d 31 }
va009039 0:5160ee0c522d 32
va009039 0:5160ee0c522d 33 USBHost::USBHost() {
va009039 0:5160ee0c522d 34 }
va009039 0:5160ee0c522d 35
va009039 2:0cdac6bcc534 36 /* virtual */ bool USBHost::enumeration() {
va009039 1:c072d9e580b0 37 uint8_t desc[64];
va009039 0:5160ee0c522d 38 MaxPacketSize0 = 8;
va009039 1:c072d9e580b0 39 dev_addr = 0;
va009039 1:c072d9e580b0 40 USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(dev_addr);
va009039 1:c072d9e580b0 41 wait_ms(100);
va009039 0:5160ee0c522d 42 SETUP_PACKET setup_get_descriptor = {0x80, GET_DESCRIPTOR, 1<<8, 0, 0};
va009039 0:5160ee0c522d 43 int result = ControlRead(&setup_get_descriptor, desc, 8);
va009039 1:c072d9e580b0 44 if (result < 8) {
va009039 1:c072d9e580b0 45 USB_DBG("result=%d %02x", result, LastStatus);
va009039 1:c072d9e580b0 46 return false;
va009039 1:c072d9e580b0 47 }
va009039 0:5160ee0c522d 48 USB_DBG_HEX(desc, result);
va009039 0:5160ee0c522d 49 MaxPacketSize0 = desc[7];
va009039 0:5160ee0c522d 50
va009039 1:c072d9e580b0 51 SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0};
va009039 1:c072d9e580b0 52 result = ControlWrite(&setup_set_address);
va009039 1:c072d9e580b0 53 if (result < 0) {
va009039 1:c072d9e580b0 54 USB_DBG("result=%d %02x", result, LastStatus);
va009039 1:c072d9e580b0 55 return false;
va009039 1:c072d9e580b0 56 }
va009039 1:c072d9e580b0 57 wait_ms(100);
va009039 2:0cdac6bcc534 58 dev_addr = 1;
va009039 1:c072d9e580b0 59
va009039 0:5160ee0c522d 60 result = ControlRead(&setup_get_descriptor, desc, sizeof(desc));
va009039 1:c072d9e580b0 61 if (result < 8) {
va009039 1:c072d9e580b0 62 USB_DBG("result=%d", result);
va009039 1:c072d9e580b0 63 return false;
va009039 1:c072d9e580b0 64 }
va009039 1:c072d9e580b0 65 USB_DBG_HEX(desc, result);
va009039 0:5160ee0c522d 66
va009039 0:5160ee0c522d 67 setup_get_descriptor.wValue = 2<<8; // config descriptor
va009039 0:5160ee0c522d 68 result = ControlRead(&setup_get_descriptor, desc, 4);
va009039 1:c072d9e580b0 69 if (result != 4) {
va009039 1:c072d9e580b0 70 USB_DBG("result=%d", result);
va009039 1:c072d9e580b0 71 return false;
va009039 1:c072d9e580b0 72 }
va009039 0:5160ee0c522d 73 USB_DBG_HEX(desc, 4);
va009039 0:5160ee0c522d 74
va009039 0:5160ee0c522d 75 int TotalLength = desc[2]|desc[3]<<8;
va009039 0:5160ee0c522d 76 uint8_t* buf = new uint8_t[TotalLength];
va009039 0:5160ee0c522d 77 result = ControlRead(&setup_get_descriptor, buf, TotalLength);
va009039 1:c072d9e580b0 78 if (result != TotalLength) {
va009039 1:c072d9e580b0 79 USB_DBG("result=%d TotalLength=%d %02x", result, TotalLength, LastStatus);
va009039 1:c072d9e580b0 80 return false;
va009039 1:c072d9e580b0 81 }
va009039 0:5160ee0c522d 82 USB_DBG_HEX(buf, TotalLength);
va009039 0:5160ee0c522d 83
va009039 0:5160ee0c522d 84 for(int i = 0; i < TotalLength; ) {
va009039 0:5160ee0c522d 85 int Length = buf[i];
va009039 0:5160ee0c522d 86 uint8_t DescriptorType = buf[i+1];
va009039 0:5160ee0c522d 87 if (DescriptorType == 0x05) { // endpoint
va009039 0:5160ee0c522d 88 uint8_t EndpointAddress = buf[i+2];
va009039 0:5160ee0c522d 89 uint8_t Attributes = buf[i+3];
va009039 0:5160ee0c522d 90 if (Attributes == 0x03) { // interrupt
va009039 0:5160ee0c522d 91 if (EndpointAddress & 0x80) {
va009039 0:5160ee0c522d 92 ep_int_in = EndpointAddress;
va009039 0:5160ee0c522d 93 }
va009039 0:5160ee0c522d 94 } else if (Attributes == 0x02) { // bulk
va009039 0:5160ee0c522d 95 if (EndpointAddress & 0x80) {
va009039 0:5160ee0c522d 96 ep_bulk_in = EndpointAddress;
va009039 0:5160ee0c522d 97 } else {
va009039 0:5160ee0c522d 98 ep_bulk_out = EndpointAddress;
va009039 0:5160ee0c522d 99 }
va009039 0:5160ee0c522d 100 }
va009039 0:5160ee0c522d 101 }
va009039 0:5160ee0c522d 102 USB_DBG_HEX(buf+i, Length);
va009039 0:5160ee0c522d 103 i += Length;
va009039 0:5160ee0c522d 104 }
va009039 0:5160ee0c522d 105 delete[] buf;
va009039 0:5160ee0c522d 106
va009039 1:c072d9e580b0 107 // config = 1
va009039 1:c072d9e580b0 108 SETUP_PACKET setup_set_config = {0x00, SET_CONFIGURATION, 1, 0, 0};
va009039 1:c072d9e580b0 109 result = ControlWrite(&setup_set_config);
va009039 1:c072d9e580b0 110 if (result < 0) {
va009039 1:c072d9e580b0 111 USB_DBG("set config: %02x", LastStatus);
va009039 1:c072d9e580b0 112 if (lowSpeed && LastStatus == STALL) { // TODO:
va009039 1:c072d9e580b0 113 wait_ms(100);
va009039 1:c072d9e580b0 114 return true;
va009039 1:c072d9e580b0 115 }
va009039 1:c072d9e580b0 116 return false;
va009039 1:c072d9e580b0 117 }
va009039 1:c072d9e580b0 118 wait_ms(100);
va009039 1:c072d9e580b0 119 return true;
va009039 0:5160ee0c522d 120 }
va009039 0:5160ee0c522d 121
va009039 0:5160ee0c522d 122 int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) {
va009039 2:0cdac6bcc534 123 setAddr(dev_addr);
va009039 0:5160ee0c522d 124 token_setup(setup, size); // setup stage
va009039 2:0cdac6bcc534 125 if (LastStatus != ACK) {
va009039 2:0cdac6bcc534 126 USB_DBG("setup %02x", LastStatus);
va009039 1:c072d9e580b0 127 return -1;
va009039 1:c072d9e580b0 128 }
va009039 1:c072d9e580b0 129 rx_data01[0] = DATA1;
va009039 0:5160ee0c522d 130 int read_len = 0;
va009039 0:5160ee0c522d 131 while(read_len < size) {
va009039 0:5160ee0c522d 132 int size2 = std::min(size-read_len, MaxPacketSize0);
va009039 0:5160ee0c522d 133 int result = token_in(0, data+read_len, size2);
va009039 2:0cdac6bcc534 134 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 1:c072d9e580b0 135 if (result < 0) {
va009039 2:0cdac6bcc534 136 USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
va009039 1:c072d9e580b0 137 return result;
va009039 1:c072d9e580b0 138 }
va009039 0:5160ee0c522d 139 read_len += result;
va009039 0:5160ee0c522d 140 if (result < MaxPacketSize0) {
va009039 0:5160ee0c522d 141 break;
va009039 0:5160ee0c522d 142 }
va009039 0:5160ee0c522d 143 }
va009039 1:c072d9e580b0 144 tx_data01[0] = rx_data01[0];
va009039 1:c072d9e580b0 145 int result = token_out(0); // status stage
va009039 1:c072d9e580b0 146 if (result < 0) {
va009039 1:c072d9e580b0 147 USB_DBG("status token_out %02x", LastStatus);
va009039 1:c072d9e580b0 148 if (LastStatus == STALL) {
va009039 1:c072d9e580b0 149 return read_len;
va009039 1:c072d9e580b0 150 }
va009039 1:c072d9e580b0 151 return result;
va009039 1:c072d9e580b0 152 }
va009039 0:5160ee0c522d 153 return read_len;
va009039 0:5160ee0c522d 154 }
va009039 0:5160ee0c522d 155
va009039 0:5160ee0c522d 156 int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) {
va009039 2:0cdac6bcc534 157 setAddr(dev_addr);
va009039 2:0cdac6bcc534 158 token_setup(setup, size); // setup stage
va009039 2:0cdac6bcc534 159 if (LastStatus != ACK) {
va009039 2:0cdac6bcc534 160 USB_DBG("setup %02x", LastStatus);
va009039 1:c072d9e580b0 161 return -1;
va009039 1:c072d9e580b0 162 }
va009039 2:0cdac6bcc534 163
va009039 1:c072d9e580b0 164 tx_data01[0] = DATA1;
va009039 1:c072d9e580b0 165 int write_len = 0;
va009039 0:5160ee0c522d 166 if (data != NULL) {
va009039 1:c072d9e580b0 167 write_len = token_out(0, data, size);
va009039 1:c072d9e580b0 168 if (write_len < 0) {
va009039 1:c072d9e580b0 169 return -1;
va009039 1:c072d9e580b0 170 }
va009039 0:5160ee0c522d 171 }
va009039 1:c072d9e580b0 172 rx_data01[0] = tx_data01[0];
va009039 1:c072d9e580b0 173 int result = token_in(0); // status stage
va009039 1:c072d9e580b0 174 if (result < 0) {
va009039 1:c072d9e580b0 175 return result;
va009039 1:c072d9e580b0 176 }
va009039 1:c072d9e580b0 177 return write_len;
va009039 0:5160ee0c522d 178 }
va009039 0:5160ee0c522d 179
va009039 0:5160ee0c522d 180 int USBHost::InterruptRead(uint8_t* data, int size) {
va009039 2:0cdac6bcc534 181 setAddr(dev_addr);
va009039 2:0cdac6bcc534 182 setEndpoint();
va009039 2:0cdac6bcc534 183 const int retryLimit = 0;
va009039 2:0cdac6bcc534 184 return token_in(ep_int_in & 0x7f, data, size, retryLimit);
va009039 0:5160ee0c522d 185 }
va009039 0:5160ee0c522d 186
va009039 0:5160ee0c522d 187 int USBHost::BulkRead(uint8_t* data, int size) {
va009039 2:0cdac6bcc534 188 setAddr(dev_addr);
va009039 2:0cdac6bcc534 189 setEndpoint();
va009039 1:c072d9e580b0 190 const int max_packet_size = 64;
va009039 1:c072d9e580b0 191 int read_len = 0;
va009039 1:c072d9e580b0 192 while(read_len < size) {
va009039 1:c072d9e580b0 193 int size2 = std::min(size-read_len, max_packet_size);
va009039 1:c072d9e580b0 194 int result = token_in(ep_bulk_in & 0x7f, data+read_len, size2);
va009039 1:c072d9e580b0 195 if (result < 0) {
va009039 1:c072d9e580b0 196 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 1:c072d9e580b0 197 return result;
va009039 1:c072d9e580b0 198 }
va009039 1:c072d9e580b0 199 read_len += result;
va009039 1:c072d9e580b0 200 if (result < max_packet_size) {
va009039 1:c072d9e580b0 201 break;
va009039 1:c072d9e580b0 202 }
va009039 1:c072d9e580b0 203 }
va009039 1:c072d9e580b0 204 return read_len;
va009039 0:5160ee0c522d 205 }
va009039 0:5160ee0c522d 206
va009039 0:5160ee0c522d 207 int USBHost::BulkWrite(const uint8_t* data, int size) {
va009039 2:0cdac6bcc534 208 setAddr(dev_addr);
va009039 2:0cdac6bcc534 209 setEndpoint();
va009039 1:c072d9e580b0 210 const int max_packet_size = 64;
va009039 1:c072d9e580b0 211 int write_len = 0;
va009039 1:c072d9e580b0 212 while(write_len < size) {
va009039 1:c072d9e580b0 213 int size2 = std::min(size-write_len, max_packet_size);
va009039 1:c072d9e580b0 214 int result = token_out(ep_bulk_out, data+write_len, size2);
va009039 1:c072d9e580b0 215 if (result < 0) {
va009039 1:c072d9e580b0 216 //USB_DBG("token_in result=%d %02x", result, LastStatus);
va009039 1:c072d9e580b0 217 return result;
va009039 1:c072d9e580b0 218 }
va009039 1:c072d9e580b0 219 write_len += result;
va009039 1:c072d9e580b0 220 if (result < max_packet_size) {
va009039 1:c072d9e580b0 221 break;
va009039 1:c072d9e580b0 222 }
va009039 1:c072d9e580b0 223 }
va009039 1:c072d9e580b0 224 return write_len;
va009039 0:5160ee0c522d 225 }
va009039 0:5160ee0c522d 226