User | Revision | Line number | New contents of line |
RichardUK |
0:63d45df56584
|
1
|
/*
|
RichardUK |
0:63d45df56584
|
2
|
A host controller driver from the mBed device.
|
RichardUK |
0:63d45df56584
|
3
|
Copyright (C) 2012 Richard e Collins - richard.collins@linux.com
|
RichardUK |
0:63d45df56584
|
4
|
|
RichardUK |
0:63d45df56584
|
5
|
This program is free software: you can redistribute it and/or modify
|
RichardUK |
0:63d45df56584
|
6
|
it under the terms of the GNU General Public License as published by
|
RichardUK |
0:63d45df56584
|
7
|
the Free Software Foundation, either version 3 of the License, or
|
RichardUK |
0:63d45df56584
|
8
|
(at your option) any later version.
|
RichardUK |
0:63d45df56584
|
9
|
|
RichardUK |
0:63d45df56584
|
10
|
This program is distributed in the hope that it will be useful,
|
RichardUK |
0:63d45df56584
|
11
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
RichardUK |
0:63d45df56584
|
12
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
RichardUK |
0:63d45df56584
|
13
|
GNU General Public License for more details.
|
RichardUK |
0:63d45df56584
|
14
|
|
RichardUK |
0:63d45df56584
|
15
|
You should have received a copy of the GNU General Public License
|
RichardUK |
0:63d45df56584
|
16
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
RichardUK |
0:63d45df56584
|
17
|
*/
|
RichardUK |
0:63d45df56584
|
18
|
|
RichardUK |
0:63d45df56584
|
19
|
#include <mbed.h>
|
RichardUK |
0:63d45df56584
|
20
|
#include "UsbHost.h"
|
RichardUK |
0:63d45df56584
|
21
|
#include "UsbHostController.h"
|
RichardUK |
0:63d45df56584
|
22
|
#include "HardwareDefines.h"
|
RichardUK |
0:63d45df56584
|
23
|
#include "Debug.h"
|
RichardUK |
0:63d45df56584
|
24
|
#include "UsbStructures.h"
|
RichardUK |
0:63d45df56584
|
25
|
#include "UsbEnums.h"
|
RichardUK |
0:63d45df56584
|
26
|
|
RichardUK |
0:63d45df56584
|
27
|
//Do #if 0 to enable debug log on the host controller driver.
|
RichardUK |
0:63d45df56584
|
28
|
#if 1
|
RichardUK |
0:63d45df56584
|
29
|
#undef DEBUG
|
RichardUK |
0:63d45df56584
|
30
|
#define DEBUG(...) do {} while(0)
|
RichardUK |
0:63d45df56584
|
31
|
#endif
|
RichardUK |
0:63d45df56584
|
32
|
|
RichardUK |
0:63d45df56584
|
33
|
namespace USB
|
RichardUK |
0:63d45df56584
|
34
|
{
|
RichardUK |
0:63d45df56584
|
35
|
|
RichardUK |
0:63d45df56584
|
36
|
uint32_t controlTransferDataLength = 0;
|
RichardUK |
0:63d45df56584
|
37
|
|
RichardUK |
0:63d45df56584
|
38
|
Host::Host()
|
RichardUK |
0:63d45df56584
|
39
|
{
|
RichardUK |
0:63d45df56584
|
40
|
for( int n = 0 ; n < MAX_DEVICES ; n++ )
|
RichardUK |
0:63d45df56584
|
41
|
{
|
RichardUK |
0:63d45df56584
|
42
|
devices[n] = NULL;
|
RichardUK |
0:63d45df56584
|
43
|
}
|
RichardUK |
0:63d45df56584
|
44
|
|
RichardUK |
0:63d45df56584
|
45
|
driver = HostController::get();
|
RichardUK |
0:63d45df56584
|
46
|
driver->Init(this,deviceZero);
|
RichardUK |
0:63d45df56584
|
47
|
}
|
RichardUK |
0:63d45df56584
|
48
|
|
RichardUK |
0:63d45df56584
|
49
|
Host::~Host()
|
RichardUK |
0:63d45df56584
|
50
|
{
|
RichardUK |
0:63d45df56584
|
51
|
}
|
RichardUK |
0:63d45df56584
|
52
|
|
RichardUK |
0:63d45df56584
|
53
|
Device* Host::AllocateDevice(int endpointZeroMaxPacketSize,int hubPortStatus)
|
RichardUK |
0:63d45df56584
|
54
|
{
|
RichardUK |
0:63d45df56584
|
55
|
for( int n = 0 ; n < MAX_DEVICES ; n++ )
|
RichardUK |
0:63d45df56584
|
56
|
{
|
RichardUK |
0:63d45df56584
|
57
|
if( devices[n] == NULL )
|
RichardUK |
0:63d45df56584
|
58
|
{
|
RichardUK |
0:63d45df56584
|
59
|
devices[n] = (Device *)driver->AllocateMemoryPoolItem();
|
RichardUK |
0:63d45df56584
|
60
|
devices[n]->id = (uint8_t)(n+1);//The device is +1 as device 0 is the host controller.
|
RichardUK |
0:63d45df56584
|
61
|
devices[n]->endpointZeroMaxPacketSize = endpointZeroMaxPacketSize;
|
RichardUK |
0:63d45df56584
|
62
|
devices[n]->lowspeed = (hubPortStatus&ROOTHUB_LOW_SPEED_DEVICE_ATTACHED) ? 1 : 0;
|
RichardUK |
0:63d45df56584
|
63
|
|
RichardUK |
0:63d45df56584
|
64
|
return devices[n];
|
RichardUK |
0:63d45df56584
|
65
|
}
|
RichardUK |
0:63d45df56584
|
66
|
}
|
RichardUK |
0:63d45df56584
|
67
|
return NULL;
|
RichardUK |
0:63d45df56584
|
68
|
}
|
RichardUK |
0:63d45df56584
|
69
|
|
RichardUK |
0:63d45df56584
|
70
|
void Host::SendControlTransferData(Device* device,int dataToggle)
|
RichardUK |
0:63d45df56584
|
71
|
{
|
RichardUK |
0:63d45df56584
|
72
|
driver->QueueControlTransferStage(
|
RichardUK |
0:63d45df56584
|
73
|
device->id,
|
RichardUK |
0:63d45df56584
|
74
|
device->controlTransferDirToHost == 1 ? TDD_IN : TDD_OUT,
|
RichardUK |
0:63d45df56584
|
75
|
0,
|
RichardUK |
0:63d45df56584
|
76
|
device->endpointZeroMaxPacketSize,
|
RichardUK |
0:63d45df56584
|
77
|
device->lowspeed,
|
RichardUK |
0:63d45df56584
|
78
|
dataToggle,
|
RichardUK |
0:63d45df56584
|
79
|
device->controlTransferData,
|
RichardUK |
0:63d45df56584
|
80
|
device->controlTransferDataLength);
|
RichardUK |
0:63d45df56584
|
81
|
|
RichardUK |
0:63d45df56584
|
82
|
device->controlTransferState = CTS_DATA;
|
RichardUK |
0:63d45df56584
|
83
|
}
|
RichardUK |
0:63d45df56584
|
84
|
|
RichardUK |
0:63d45df56584
|
85
|
void Host::SendControlTransferAcknowledge(Device* device,int dataToggle)
|
RichardUK |
0:63d45df56584
|
86
|
{
|
RichardUK |
0:63d45df56584
|
87
|
//Send empty packet to ACK.
|
RichardUK |
0:63d45df56584
|
88
|
driver->QueueControlTransferStage(
|
RichardUK |
0:63d45df56584
|
89
|
device->id,
|
RichardUK |
0:63d45df56584
|
90
|
device->controlTransferDirToHost == 0 ? TDD_IN : TDD_OUT,
|
RichardUK |
0:63d45df56584
|
91
|
0,
|
RichardUK |
0:63d45df56584
|
92
|
device->endpointZeroMaxPacketSize,
|
RichardUK |
0:63d45df56584
|
93
|
device->lowspeed,
|
RichardUK |
0:63d45df56584
|
94
|
dataToggle,
|
RichardUK |
0:63d45df56584
|
95
|
NULL,0);
|
RichardUK |
0:63d45df56584
|
96
|
|
RichardUK |
0:63d45df56584
|
97
|
device->controlTransferState = CTS_ACK;
|
RichardUK |
0:63d45df56584
|
98
|
}
|
RichardUK |
0:63d45df56584
|
99
|
|
RichardUK |
0:63d45df56584
|
100
|
Device* Host::getDevice(int deviceID)
|
RichardUK |
0:63d45df56584
|
101
|
{
|
RichardUK |
0:63d45df56584
|
102
|
if( deviceID == 0 )
|
RichardUK |
0:63d45df56584
|
103
|
{
|
RichardUK |
0:63d45df56584
|
104
|
return deviceZero;
|
RichardUK |
0:63d45df56584
|
105
|
}
|
RichardUK |
0:63d45df56584
|
106
|
|
RichardUK |
0:63d45df56584
|
107
|
deviceID--;
|
RichardUK |
0:63d45df56584
|
108
|
if( deviceID > -1 && deviceID < MAX_DEVICES )
|
RichardUK |
0:63d45df56584
|
109
|
{
|
RichardUK |
0:63d45df56584
|
110
|
return devices[deviceID];
|
RichardUK |
0:63d45df56584
|
111
|
}
|
RichardUK |
0:63d45df56584
|
112
|
return NULL;
|
RichardUK |
0:63d45df56584
|
113
|
}
|
RichardUK |
0:63d45df56584
|
114
|
|
RichardUK |
0:63d45df56584
|
115
|
void Host::Update()
|
RichardUK |
0:63d45df56584
|
116
|
{
|
RichardUK |
0:63d45df56584
|
117
|
driver->Update();
|
RichardUK |
0:63d45df56584
|
118
|
}
|
RichardUK |
0:63d45df56584
|
119
|
|
RichardUK |
0:63d45df56584
|
120
|
int Host::getDeviceDescriptor(int deviceID,DeviceDescription &description)
|
RichardUK |
0:63d45df56584
|
121
|
{
|
RichardUK |
0:63d45df56584
|
122
|
return ControlTransfer(deviceID,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_DEVICE << 8), 0, (uint8_t*)&description, sizeof(description),DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
123
|
}
|
RichardUK |
0:63d45df56584
|
124
|
|
RichardUK |
0:63d45df56584
|
125
|
const uint8_t* Host::getConfigurationDescriptor(int deviceID,int index)
|
RichardUK |
0:63d45df56584
|
126
|
{
|
RichardUK |
0:63d45df56584
|
127
|
uint8_t* buf = driver->getScratchRam();
|
RichardUK |
0:63d45df56584
|
128
|
ControlTransfer(deviceID,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_CONFIG << 8)|index, 0,buf,255,DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
129
|
return (const uint8_t*)buf;
|
RichardUK |
0:63d45df56584
|
130
|
}
|
RichardUK |
0:63d45df56584
|
131
|
|
RichardUK |
0:63d45df56584
|
132
|
const char* Host::getStringDescriptor(int deviceID,int index)
|
RichardUK |
0:63d45df56584
|
133
|
{
|
RichardUK |
0:63d45df56584
|
134
|
Device* dev = getDevice(deviceID);
|
RichardUK |
0:63d45df56584
|
135
|
if( dev == NULL )
|
RichardUK |
0:63d45df56584
|
136
|
{
|
RichardUK |
0:63d45df56584
|
137
|
return "error";
|
RichardUK |
0:63d45df56584
|
138
|
}
|
RichardUK |
0:63d45df56584
|
139
|
|
RichardUK |
0:63d45df56584
|
140
|
uint8_t* buf = driver->getScratchRam();
|
RichardUK |
0:63d45df56584
|
141
|
ControlTransfer(deviceID,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_STRING << 8)|index, dev->languageID,buf,255,DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
142
|
|
RichardUK |
0:63d45df56584
|
143
|
uint8_t* string = buf;
|
RichardUK |
0:63d45df56584
|
144
|
int len = buf[0];
|
RichardUK |
0:63d45df56584
|
145
|
for( int n = 2 ; n < len ; n += 2 )
|
RichardUK |
0:63d45df56584
|
146
|
{
|
RichardUK |
0:63d45df56584
|
147
|
*string++ = buf[n];
|
RichardUK |
0:63d45df56584
|
148
|
}
|
RichardUK |
0:63d45df56584
|
149
|
*string = 0;
|
RichardUK |
0:63d45df56584
|
150
|
return (char*)buf;
|
RichardUK |
0:63d45df56584
|
151
|
}
|
RichardUK |
0:63d45df56584
|
152
|
|
RichardUK |
0:63d45df56584
|
153
|
int Host::setConfiguration(int deviceID,int configuration)
|
RichardUK |
0:63d45df56584
|
154
|
{
|
RichardUK |
0:63d45df56584
|
155
|
return ControlTransfer(deviceID,LIBUSB_ENDPOINT_OUT, LIBUSB_REQUEST_SET_CONFIGURATION,configuration, 0,NULL,0,DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
156
|
}
|
RichardUK |
0:63d45df56584
|
157
|
|
RichardUK |
0:63d45df56584
|
158
|
/*
|
RichardUK |
0:63d45df56584
|
159
|
* Control transfer uses three stages, the setup stage where the request is sent.
|
RichardUK |
0:63d45df56584
|
160
|
* The optional Data Stage consists of one or multiple IN or OUT transfers.
|
RichardUK |
0:63d45df56584
|
161
|
* The setup request indicates the amount of data to be transmitted in this stage.
|
RichardUK |
0:63d45df56584
|
162
|
* If it exceeds the maximum packet size, data will be sent in multiple transfers each being the maximum packet length except for the last packet.
|
RichardUK |
0:63d45df56584
|
163
|
* Status Stage reports the status of the overall request and this once again varies due to direction of transfer. Status reporting is always performed by the function.
|
RichardUK |
0:63d45df56584
|
164
|
*/
|
RichardUK |
0:63d45df56584
|
165
|
int Host::ControlTransfer(int deviceID,uint8_t requestType, uint8_t request, uint16_t value, uint16_t index,const uint8_t *data, uint16_t length, uint32_t timeout)
|
RichardUK |
0:63d45df56584
|
166
|
{
|
RichardUK |
0:63d45df56584
|
167
|
DEBUG("ControlTransfer");
|
RichardUK |
0:63d45df56584
|
168
|
|
RichardUK |
0:63d45df56584
|
169
|
Device* device = getDevice(deviceID);
|
RichardUK |
0:63d45df56584
|
170
|
|
RichardUK |
0:63d45df56584
|
171
|
//Remeber the packet we are sending so that when we get the responce from the setup packet we can then ask for or send the data.
|
RichardUK |
0:63d45df56584
|
172
|
device->controlTransferData = data;
|
RichardUK |
0:63d45df56584
|
173
|
device->controlTransferDataLength = length;
|
RichardUK |
0:63d45df56584
|
174
|
device->controlTransferDirToHost = (requestType & LIBUSB_ENDPOINT_IN) ? 1 : 0;
|
RichardUK |
0:63d45df56584
|
175
|
device->controlTransferState = CTS_SETUP;
|
RichardUK |
0:63d45df56584
|
176
|
|
RichardUK |
0:63d45df56584
|
177
|
//First do the setup packet.
|
RichardUK |
0:63d45df56584
|
178
|
SetupPacket* sp = (SetupPacket*)driver->AllocateMemoryPoolItem();
|
RichardUK |
0:63d45df56584
|
179
|
|
RichardUK |
0:63d45df56584
|
180
|
sp->requestType = requestType;
|
RichardUK |
0:63d45df56584
|
181
|
sp->request = request;
|
RichardUK |
0:63d45df56584
|
182
|
sp->value = value;
|
RichardUK |
0:63d45df56584
|
183
|
sp->index = index;
|
RichardUK |
0:63d45df56584
|
184
|
sp->length = length;
|
RichardUK |
0:63d45df56584
|
185
|
|
RichardUK |
0:63d45df56584
|
186
|
DEBUG("Setup %d %d %d %d %d",sp->requestType,sp->request,sp->value,sp->index,sp->length);
|
RichardUK |
0:63d45df56584
|
187
|
|
RichardUK |
0:63d45df56584
|
188
|
driver->QueueControlTransferStage(deviceID,TDD_SETUP,0,device->endpointZeroMaxPacketSize,device->lowspeed,TOGGLE_DATA0,(const uint8_t*)sp,sizeof(SetupPacket));
|
RichardUK |
0:63d45df56584
|
189
|
|
RichardUK |
0:63d45df56584
|
190
|
while(device->controlTransferState != CTS_IDLE)
|
RichardUK |
0:63d45df56584
|
191
|
{
|
RichardUK |
0:63d45df56584
|
192
|
wait_ms(100);
|
RichardUK |
0:63d45df56584
|
193
|
};
|
RichardUK |
0:63d45df56584
|
194
|
|
RichardUK |
0:63d45df56584
|
195
|
//Free this up.
|
RichardUK |
0:63d45df56584
|
196
|
driver->FreeMemoryPoolItem(sp);
|
RichardUK |
0:63d45df56584
|
197
|
DEBUG("Done, recived %d",controlTransferDataLength);
|
RichardUK |
0:63d45df56584
|
198
|
|
RichardUK |
0:63d45df56584
|
199
|
return 0;
|
RichardUK |
0:63d45df56584
|
200
|
}
|
RichardUK |
0:63d45df56584
|
201
|
|
RichardUK |
0:63d45df56584
|
202
|
int Host::BulkTransfer(int deviceID,uint8_t endpoint,const uint8_t* data,int length,int callbackID)
|
RichardUK |
0:63d45df56584
|
203
|
{
|
RichardUK |
0:63d45df56584
|
204
|
DEBUG("ControlTransfer");
|
RichardUK |
0:63d45df56584
|
205
|
|
RichardUK |
0:63d45df56584
|
206
|
Device* device = getDevice(deviceID);
|
RichardUK |
0:63d45df56584
|
207
|
/*
|
RichardUK |
0:63d45df56584
|
208
|
driver->QueueControlTransferStage(deviceID,(endpoint&LIBUSB_ENDPOINT_IN) ? TDD_IN : TDD_OUT,endpoint,device->endpointZeroMaxPacketSize,device->lowspeed,TOGGLE_DATA0,data,length);
|
RichardUK |
0:63d45df56584
|
209
|
|
RichardUK |
0:63d45df56584
|
210
|
while(device->controlTransferState != CTS_IDLE)
|
RichardUK |
0:63d45df56584
|
211
|
{
|
RichardUK |
0:63d45df56584
|
212
|
wait_ms(100);
|
RichardUK |
0:63d45df56584
|
213
|
};
|
RichardUK |
0:63d45df56584
|
214
|
*/
|
RichardUK |
0:63d45df56584
|
215
|
|
RichardUK |
0:63d45df56584
|
216
|
return 0;
|
RichardUK |
0:63d45df56584
|
217
|
}
|
RichardUK |
0:63d45df56584
|
218
|
|
RichardUK |
0:63d45df56584
|
219
|
|
RichardUK |
0:63d45df56584
|
220
|
void Host::AddDevice(int hub,int port,int hubPortStatus)
|
RichardUK |
0:63d45df56584
|
221
|
{
|
RichardUK |
0:63d45df56584
|
222
|
DEBUG("AddDevice(%d,%d,%08x)",hub,port,hubPortStatus);
|
RichardUK |
0:63d45df56584
|
223
|
DeviceDescription description;
|
RichardUK |
0:63d45df56584
|
224
|
description.length = sizeof(DeviceDescription);
|
RichardUK |
0:63d45df56584
|
225
|
|
RichardUK |
0:63d45df56584
|
226
|
//Setup device zero.
|
RichardUK |
0:63d45df56584
|
227
|
deviceZero->endpointZeroMaxPacketSize = 8;
|
RichardUK |
0:63d45df56584
|
228
|
deviceZero->lowspeed = (hubPortStatus&ROOTHUB_LOW_SPEED_DEVICE_ATTACHED) ? 1 : 0;
|
RichardUK |
0:63d45df56584
|
229
|
|
RichardUK |
0:63d45df56584
|
230
|
//For the enumeration we'll use device zero, once done will set the device address and get the rest of the details.
|
RichardUK |
0:63d45df56584
|
231
|
//Now we add the first endpoint, endpoint zero by default.
|
RichardUK |
0:63d45df56584
|
232
|
//Once added we'll read the device's config and add endpoints for them.
|
RichardUK |
0:63d45df56584
|
233
|
//I add my endpoints to the host controller and leave them there.
|
RichardUK |
0:63d45df56584
|
234
|
//I set the direction code so that the direction is read from the transfer descriptor.
|
RichardUK |
0:63d45df56584
|
235
|
//This means that I need less endpoint objects.
|
RichardUK |
0:63d45df56584
|
236
|
//I leave them attached with not transfers to do. That is ok and as per the spec.
|
RichardUK |
0:63d45df56584
|
237
|
//Old devices may only have a max packet size of 8 bytes.
|
RichardUK |
0:63d45df56584
|
238
|
|
RichardUK |
0:63d45df56584
|
239
|
//Using device 0 for the setup and enum phase of the newley connected device.
|
RichardUK |
0:63d45df56584
|
240
|
//We do this just to get some info on the device and then send a 'set address' command.
|
RichardUK |
0:63d45df56584
|
241
|
//At that point we'll start using it's real ID.
|
RichardUK |
0:63d45df56584
|
242
|
DEBUG("Getting endpoint zero maxPacketSize");
|
RichardUK |
0:63d45df56584
|
243
|
ControlTransfer(0,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_DEVICE << 8), 0, (uint8_t*)&description,8,DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
244
|
|
RichardUK |
0:63d45df56584
|
245
|
|
RichardUK |
0:63d45df56584
|
246
|
//Now allocate the device and it's ID.
|
RichardUK |
0:63d45df56584
|
247
|
DEBUG("Allocating device");
|
RichardUK |
0:63d45df56584
|
248
|
Device* device = AllocateDevice(description.maxPacketSize,hubPortStatus);
|
RichardUK |
0:63d45df56584
|
249
|
|
RichardUK |
0:63d45df56584
|
250
|
//Now correct the endpoint's max packet size. Needs this for when we setup the endpoint descriptor for a transfer.
|
RichardUK |
0:63d45df56584
|
251
|
DEBUG("endpointZeroMaxPacketSize(%d)",device->endpointZeroMaxPacketSize);
|
RichardUK |
0:63d45df56584
|
252
|
|
RichardUK |
0:63d45df56584
|
253
|
//Set the devices new address.
|
RichardUK |
0:63d45df56584
|
254
|
DEBUG("Setting device address to %d",device->id);
|
RichardUK |
0:63d45df56584
|
255
|
ControlTransfer(0,LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_DEVICE, LIBUSB_REQUEST_SET_ADDRESS, device->id,0,NULL,0,DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
256
|
|
RichardUK |
0:63d45df56584
|
257
|
//New ID is now set, so we can free the object used when it was called device zero.
|
RichardUK |
0:63d45df56584
|
258
|
driver->DetachDevice(0);
|
RichardUK |
0:63d45df56584
|
259
|
|
RichardUK |
0:63d45df56584
|
260
|
//Now fetch the full device description.
|
RichardUK |
0:63d45df56584
|
261
|
DEBUG("Getting device description");
|
RichardUK |
0:63d45df56584
|
262
|
getDeviceDescriptor(device->id,description);
|
RichardUK |
0:63d45df56584
|
263
|
|
RichardUK |
0:63d45df56584
|
264
|
DEBUG("idVendor(0x%04x) idProduct(0x%04x)",description.idVendor,description.idProduct);
|
RichardUK |
0:63d45df56584
|
265
|
|
RichardUK |
0:63d45df56584
|
266
|
//Get the language ID.
|
RichardUK |
0:63d45df56584
|
267
|
uint16_t* lang = (uint16_t*)driver->AllocateMemoryPoolItem();
|
RichardUK |
0:63d45df56584
|
268
|
ControlTransfer(device->id,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,LIBUSB_DT_STRING<<8,0,(uint8_t*)lang,16,DEFAULT_TIMEOUT);
|
RichardUK |
0:63d45df56584
|
269
|
device->languageID = lang[1];
|
RichardUK |
0:63d45df56584
|
270
|
driver->FreeMemoryPoolItem(lang);
|
RichardUK |
0:63d45df56584
|
271
|
|
RichardUK |
0:63d45df56584
|
272
|
//Set the first config by default, will get most things up and running.
|
RichardUK |
0:63d45df56584
|
273
|
const USB::ConfigurationDescription* config = (const USB::ConfigurationDescription*)getConfigurationDescriptor(device->id,0);
|
RichardUK |
0:63d45df56584
|
274
|
wait_ms(100);
|
RichardUK |
0:63d45df56584
|
275
|
setConfiguration(device->id,config->configID);
|
RichardUK |
0:63d45df56584
|
276
|
wait_ms(100);
|
RichardUK |
0:63d45df56584
|
277
|
|
RichardUK |
0:63d45df56584
|
278
|
//Tell the app's inherted code about this new device.
|
RichardUK |
0:63d45df56584
|
279
|
onConnected(device->id,description);
|
RichardUK |
0:63d45df56584
|
280
|
}
|
RichardUK |
0:63d45df56584
|
281
|
|
RichardUK |
0:63d45df56584
|
282
|
void Host::TransferDone(TransferDescriptor *transfer)
|
RichardUK |
0:63d45df56584
|
283
|
{
|
RichardUK |
0:63d45df56584
|
284
|
DEBUG("TransferDone, device(%d) errorCount(%d) status(%d) direction(%d) dataToggle(%d)",transfer->deviceID,transfer->errorCount,transfer->conditionCode,transfer->direction,transfer->dataToggle);
|
RichardUK |
0:63d45df56584
|
285
|
|
RichardUK |
0:63d45df56584
|
286
|
//Get the device this TD that has just been done for.
|
RichardUK |
0:63d45df56584
|
287
|
Device* device = getDevice(transfer->deviceID);
|
RichardUK |
0:63d45df56584
|
288
|
|
RichardUK |
0:63d45df56584
|
289
|
//See if this was a setup packet, if so do we have data to ask for, if not then just ack the transaction.
|
RichardUK |
0:63d45df56584
|
290
|
//TODO: Error checking!
|
RichardUK |
0:63d45df56584
|
291
|
switch( device->controlTransferState )
|
RichardUK |
0:63d45df56584
|
292
|
{
|
RichardUK |
0:63d45df56584
|
293
|
case CTS_SETUP:
|
RichardUK |
0:63d45df56584
|
294
|
if( device->controlTransferData != NULL )
|
RichardUK |
0:63d45df56584
|
295
|
{
|
RichardUK |
0:63d45df56584
|
296
|
SendControlTransferData(device,transfer->dataToggle);
|
RichardUK |
0:63d45df56584
|
297
|
}
|
RichardUK |
0:63d45df56584
|
298
|
else
|
RichardUK |
0:63d45df56584
|
299
|
{
|
RichardUK |
0:63d45df56584
|
300
|
SendControlTransferAcknowledge(device,transfer->dataToggle);
|
RichardUK |
0:63d45df56584
|
301
|
}
|
RichardUK |
0:63d45df56584
|
302
|
break;
|
RichardUK |
0:63d45df56584
|
303
|
|
RichardUK |
0:63d45df56584
|
304
|
case CTS_DATA:
|
RichardUK |
0:63d45df56584
|
305
|
controlTransferDataLength = (transfer->bufferEnd - device->controlTransferData) + 1;
|
RichardUK |
0:63d45df56584
|
306
|
SendControlTransferAcknowledge(device,transfer->dataToggle);
|
RichardUK |
0:63d45df56584
|
307
|
break;
|
RichardUK |
0:63d45df56584
|
308
|
|
RichardUK |
0:63d45df56584
|
309
|
case CTS_ACK:
|
RichardUK |
0:63d45df56584
|
310
|
device->controlTransferState = CTS_IDLE;
|
RichardUK |
0:63d45df56584
|
311
|
break;
|
RichardUK |
0:63d45df56584
|
312
|
}
|
RichardUK |
0:63d45df56584
|
313
|
}
|
RichardUK |
0:63d45df56584
|
314
|
|
RichardUK |
0:63d45df56584
|
315
|
};//namespace USB
|