rework more XPCU code. INT_* still needs to be moved
[usb-driver] / xpcu.c
CommitLineData
cbfa0ac6
MG
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
f92c0fbc 4#include <string.h>
cbfa0ac6
MG
5#include <strings.h>
6#include <usb.h>
f92c0fbc 7#include <errno.h>
cbfa0ac6 8#include "usb-driver.h"
6c235d59 9#include "xpcu.h"
cbfa0ac6 10
f92c0fbc
MG
11static struct usb_bus *busses = NULL;
12
13int xpcu_deviceinfo(struct xpcu_s *xpcu, struct usb_get_device_data *ugdd) {
cbfa0ac6
MG
14 int i,j,k,l;
15 int len = 0;
f92c0fbc 16 unsigned char *buf = NULL;
cbfa0ac6
MG
17 WDU_CONFIGURATION **pConfigs, **pActiveConfig;
18 WDU_INTERFACE **pActiveInterface;
19
f92c0fbc
MG
20 if (ugdd->dwUniqueID != (unsigned long)xpcu)
21 return -ENODEV;
22
23 if (ugdd->dwBytes)
24 buf = ugdd->pBuf;
25
cbfa0ac6
MG
26 if (buf) {
27 struct usb_device_info *udi = (struct usb_device_info*)(buf+len);
28
29 udi->Descriptor.bLength = sizeof(WDU_DEVICE_DESCRIPTOR);
30 udi->Descriptor.bDescriptorType = xpcu->dev->descriptor.bDescriptorType;
31 udi->Descriptor.bcdUSB = xpcu->dev->descriptor.bcdUSB;
32 udi->Descriptor.bDeviceClass = xpcu->dev->descriptor.bDeviceClass;
33 udi->Descriptor.bDeviceSubClass = xpcu->dev->descriptor.bDeviceSubClass;
34 udi->Descriptor.bDeviceProtocol = xpcu->dev->descriptor.bDeviceProtocol;
35 udi->Descriptor.bMaxPacketSize0 = xpcu->dev->descriptor.bMaxPacketSize0;
36 udi->Descriptor.idVendor = xpcu->dev->descriptor.idVendor;
37 udi->Descriptor.idProduct = xpcu->dev->descriptor.idProduct;
38 udi->Descriptor.bcdDevice = xpcu->dev->descriptor.bcdDevice;
39 udi->Descriptor.iManufacturer = xpcu->dev->descriptor.iManufacturer;
40 udi->Descriptor.iProduct = xpcu->dev->descriptor.iProduct;
41 udi->Descriptor.iSerialNumber = xpcu->dev->descriptor.iSerialNumber;
42 udi->Descriptor.bNumConfigurations = xpcu->dev->descriptor.bNumConfigurations;
43
44 /* TODO: Fix Pipe0! */
45 udi->Pipe0.dwNumber = 0x00;
46 udi->Pipe0.dwMaximumPacketSize = xpcu->dev->descriptor.bMaxPacketSize0;
47 udi->Pipe0.type = 0;
48 udi->Pipe0.direction = WDU_DIR_IN_OUT;
49 udi->Pipe0.dwInterval = 0;
50
51 pConfigs = &(udi->pConfigs);
52 pActiveConfig = &(udi->pActiveConfig);
53 pActiveInterface = &(udi->pActiveInterface[0]);
54 }
55
56 len = sizeof(struct usb_device_info);
57
58 for (i=0; i<xpcu->dev->descriptor.bNumConfigurations; i++)
59 {
60 struct usb_config_descriptor *conf_desc = &xpcu->dev->config[i];
61 WDU_INTERFACE **pInterfaces;
62 WDU_ALTERNATE_SETTING **pAlternateSettings[conf_desc->bNumInterfaces];
63 WDU_ALTERNATE_SETTING **pActiveAltSetting[conf_desc->bNumInterfaces];
64
65 if (buf) {
66 WDU_CONFIGURATION *cfg = (WDU_CONFIGURATION*)(buf+len);
67
68 *pConfigs = cfg;
69 *pActiveConfig = cfg;
70
71 cfg->Descriptor.bLength = conf_desc->bLength;
72 cfg->Descriptor.bDescriptorType = conf_desc->bDescriptorType;
73 cfg->Descriptor.wTotalLength = conf_desc->wTotalLength;
74 cfg->Descriptor.bNumInterfaces = conf_desc->bNumInterfaces;
75 cfg->Descriptor.bConfigurationValue = conf_desc->bConfigurationValue;
76 cfg->Descriptor.iConfiguration = conf_desc->iConfiguration;
77 cfg->Descriptor.bmAttributes = conf_desc->bmAttributes;
78 cfg->Descriptor.MaxPower = conf_desc->MaxPower;
79
80 cfg->dwNumInterfaces = conf_desc->bNumInterfaces;
81
82 pInterfaces = &(cfg->pInterfaces);
83 }
84 len += sizeof(WDU_CONFIGURATION);
85
86 if (buf) {
87 *pInterfaces = (WDU_INTERFACE*)(buf+len);
88 for (j=0; j<conf_desc->bNumInterfaces; j++) {
89 WDU_INTERFACE *iface = (WDU_INTERFACE*)(buf+len);
90
91 pActiveInterface[j] = iface;
92
93 pAlternateSettings[j] = &(iface->pAlternateSettings);
94 iface->dwNumAltSettings = xpcu->dev->config[i].interface[j].num_altsetting;
95 pActiveAltSetting[j] = &(iface->pActiveAltSetting);
96
97 len += sizeof(WDU_INTERFACE);
98 }
99 } else {
100 len += sizeof(WDU_INTERFACE) * conf_desc->bNumInterfaces;
101 }
102
103 for (j=0; j<conf_desc->bNumInterfaces; j++)
104 {
105 struct usb_interface *interface = &xpcu->dev->config[i].interface[j];
106
107 if (buf) {
108 *pAlternateSettings[j] = (WDU_ALTERNATE_SETTING*)(buf+len);
109 /* FIXME: */
110 *pActiveAltSetting[j] = (WDU_ALTERNATE_SETTING*)(buf+len);
111 }
112
113 for(k=0; k<interface->num_altsetting; k++)
114 {
115 unsigned char bNumEndpoints = interface->altsetting[k].bNumEndpoints;
116 WDU_ENDPOINT_DESCRIPTOR **pEndpointDescriptors;
117 WDU_PIPE_INFO **pPipes;
118
119 if (buf) {
120 WDU_ALTERNATE_SETTING *altset = (WDU_ALTERNATE_SETTING*)(buf+len);
121
122 altset->Descriptor.bLength = interface->altsetting[k].bLength;
123 altset->Descriptor.bDescriptorType = interface->altsetting[k].bDescriptorType;
124 altset->Descriptor.bInterfaceNumber = interface->altsetting[k].bInterfaceNumber;
125 altset->Descriptor.bAlternateSetting = interface->altsetting[k].bAlternateSetting;
126 altset->Descriptor.bNumEndpoints = interface->altsetting[k].bNumEndpoints;
127 altset->Descriptor.bInterfaceClass = interface->altsetting[k].bInterfaceClass;
128 altset->Descriptor.bInterfaceSubClass = interface->altsetting[k].bInterfaceSubClass;
129 altset->Descriptor.bInterfaceProtocol = interface->altsetting[k].bInterfaceProtocol;
130 altset->Descriptor.iInterface = interface->altsetting[k].iInterface;
131 pEndpointDescriptors = &(altset->pEndpointDescriptors);
132 pPipes = &(altset->pPipes);
133
134 }
135 len +=sizeof(WDU_ALTERNATE_SETTING);
136
137 if (buf) {
138 *pEndpointDescriptors = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len);
139 for (l = 0; l < bNumEndpoints; l++) {
140 WDU_ENDPOINT_DESCRIPTOR *ed = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len);
141
142 ed->bLength = interface->altsetting[k].endpoint[l].bLength;
143 ed->bDescriptorType = interface->altsetting[k].endpoint[l].bDescriptorType;
144 ed->bEndpointAddress = interface->altsetting[k].endpoint[l].bEndpointAddress;
145 ed->bmAttributes = interface->altsetting[k].endpoint[l].bmAttributes;
146 ed->wMaxPacketSize = interface->altsetting[k].endpoint[l].wMaxPacketSize;
147 ed->bInterval = interface->altsetting[k].endpoint[l].bInterval;
148
149 len += sizeof(WDU_ENDPOINT_DESCRIPTOR);
150 }
151
152 *pPipes = (WDU_PIPE_INFO*)(buf+len);
153 for (l = 0; l < bNumEndpoints; l++) {
154 WDU_PIPE_INFO *pi = (WDU_PIPE_INFO*)(buf+len);
155
156 pi->dwNumber = interface->altsetting[k].endpoint[l].bEndpointAddress;
157 pi->dwMaximumPacketSize = WDU_GET_MAX_PACKET_SIZE(interface->altsetting[k].endpoint[l].wMaxPacketSize);
158 pi->type = interface->altsetting[k].endpoint[l].bmAttributes & USB_ENDPOINT_TYPE_MASK;
159 if (pi->type == PIPE_TYPE_CONTROL)
160 pi->direction = WDU_DIR_IN_OUT;
161 else
162 {
163 pi->direction = interface->altsetting[k].endpoint[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK ? WDU_DIR_IN : WDU_DIR_OUT;
164 }
165
166 pi->dwInterval = interface->altsetting[k].endpoint[l].bInterval;
167
168 len += sizeof(WDU_PIPE_INFO);
169 }
170 } else {
171 len +=(sizeof(WDU_ENDPOINT_DESCRIPTOR)+sizeof(WDU_PIPE_INFO))*bNumEndpoints;
172 }
173 }
174 }
175 }
176
177 return len;
178}
179
6234190b 180static int xpcu_claim(struct xpcu_s *xpcu, int claim) {
cbfa0ac6
MG
181 int ret = 0;
182 static int claimed = 0;
183
184 if (xpcu->interface < 0)
185 return -1;
186
187 if (claim == XPCU_CLAIM) {
188 if (claimed)
189 return 0;
190
191 ret = usb_claim_interface(xpcu->handle, xpcu->interface);
192 if (!ret) {
193 claimed = 1;
194 ret = usb_set_altinterface(xpcu->handle, xpcu->alternate);
195 if (ret)
196 fprintf(stderr, "usb_set_altinterface: %d\n", ret);
197 } else {
198 fprintf(stderr, "usb_claim_interface: %d -> %d (%s)\n",
199 xpcu->interface, ret, usb_strerror());
200 }
201 } else {
202 if (!claimed)
203 return 0;
204
205 ret = usb_release_interface(xpcu->handle, xpcu->interface);
206 if (!ret)
207 claimed = 0;
208 }
209
210 return ret;
211}
212
6c235d59
MG
213int xpcu_transfer(struct xpcu_s *xpcu, struct usb_transfer *ut) {
214 int ret = 0;
215
f92c0fbc
MG
216 if (ut->dwUniqueID != (unsigned long)xpcu)
217 return -ENODEV;
218
6c235d59
MG
219 xpcu_claim(xpcu, XPCU_CLAIM);
220 /* http://www.jungo.com/support/documentation/windriver/802/wdusb_man_mhtml/node55.html#SECTION001213000000000000000 */
221 if (ut->dwPipeNum == 0) { /* control pipe */
222 int requesttype, request, value, index, size;
223 requesttype = ut->SetupPacket[0];
224 request = ut->SetupPacket[1];
225 value = ut->SetupPacket[2] | (ut->SetupPacket[3] << 8);
226 index = ut->SetupPacket[4] | (ut->SetupPacket[5] << 8);
227 size = ut->SetupPacket[6] | (ut->SetupPacket[7] << 8);
228 DPRINTF("requesttype: %x, request: %x, value: %u, index: %u, size: %u\n", requesttype, request, value, index, size);
229 ret = usb_control_msg(xpcu->handle, requesttype, request, value, index, ut->pBuffer, size, ut->dwTimeout);
230 } else {
231 if (ut->fRead) {
232 ret = usb_bulk_read(xpcu->handle, ut->dwPipeNum, ut->pBuffer, ut->dwBufferSize, ut->dwTimeout);
233 } else {
234 ret = usb_bulk_write(xpcu->handle, ut->dwPipeNum, ut->pBuffer, ut->dwBufferSize, ut->dwTimeout);
235 }
236 xpcu_claim(xpcu, XPCU_RELEASE);
237 }
238
239 if (ret < 0) {
240 fprintf(stderr, "usb_transfer: %d (%s)\n", ret, usb_strerror());
241 } else {
242 ut->dwBytesTransferred = ret;
243 ret = 0;
244 }
245
246 return ret;
247}
248
0c2db148 249void xpcu_set_interface(struct xpcu_s *xpcu, struct usb_set_interface *usi) {
f92c0fbc
MG
250 if (usi->dwUniqueID != (unsigned long)xpcu)
251 return;
252
0c2db148
MG
253 if (xpcu->dev) {
254 if (!xpcu->handle) {
255 xpcu->handle = usb_open(xpcu->dev);
256#ifndef NO_USB_RESET
257 if (xpcu->handle) {
258 usb_reset(xpcu->handle);
259 xpcu->handle = usb_open(xpcu->dev);
260 }
261#endif
262 }
263
264 xpcu->interface = xpcu->dev->config[0].interface[usi->dwInterfaceNum].altsetting[usi->dwAlternateSetting].bInterfaceNumber;
265 xpcu->alternate = usi->dwAlternateSetting;
266 }
267}
268
f92c0fbc
MG
269static void xpcu_init(void) {
270 if (busses)
271 return;
272
273 usb_init();
274 usb_find_busses();
275 usb_find_devices();
276
277 busses = usb_get_busses();
278}
279
280
281struct xpcu_s *xpcu_find(struct event *e) {
cbfa0ac6 282 static struct xpcu_s xpcu;
f92c0fbc
MG
283 char* devpos;
284 struct usb_bus *bus;
285 int busnum = -1, devnum = -1;
286 int i;
cbfa0ac6
MG
287
288 bzero(&xpcu, sizeof(xpcu));
289 xpcu.interface = -1;
290 xpcu.alternate = -1;
291
f92c0fbc
MG
292 xpcu_init();
293
294 devpos = getenv("XILINX_USB_DEV");
295 if (devpos != NULL) {
296 int j;
297 char *devstr = NULL, *remainder;
298
299 DPRINTF("XILINX_USB_DEV=%s\n", devpos);
300
301 for (j = 0; j < strlen(devpos) && devpos[j] != 0; j++) {
302 if (devpos[j] == ':') {
303 devpos[j] = 0;
304 devstr = &(devpos[j+1]);
305 }
306 }
307
308 if (devstr && strlen(devstr) > 0) {
309 busnum = strtol(devpos, &remainder, 10);
310 if (devpos == remainder) {
311 busnum = -1;
312 } else {
313 devnum = strtol(devstr, &remainder, 10);
314 if (devstr == remainder) {
315 busnum = -1;
316 devnum = -1;
317 } else {
318 fprintf(stderr,"Using XILINX platform cable USB at %03d:%03d\n",
319 busnum, devnum);
320 }
321 }
322 }
323 }
324
325 for (i = 0; i < e->dwNumMatchTables; i++) {
326
327 DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
328 e->matchTables[i].VendorId,
329 e->matchTables[i].ProductId,
330 e->matchTables[i].bDeviceClass,
331 e->matchTables[i].bDeviceSubClass,
332 e->matchTables[i].bInterfaceClass,
333 e->matchTables[i].bInterfaceSubClass,
334 e->matchTables[i].bInterfaceProtocol);
335
336 for (bus = busses; bus; bus = bus->next) {
337 struct usb_device *dev;
338
339 if ((devnum != -1) && (strtol(bus->dirname, NULL, 10) != busnum))
340 continue;
341
342 for (dev = bus->devices; dev; dev = dev->next) {
343 struct usb_device_descriptor *desc = &(dev->descriptor);
344
345 if((desc->idVendor == e->matchTables[i].VendorId) &&
346 (desc->idProduct == e->matchTables[i].ProductId) &&
347 (desc->bDeviceClass == e->matchTables[i].bDeviceClass) &&
348 (desc->bDeviceSubClass == e->matchTables[i].bDeviceSubClass) &&
349 ((devnum == -1) || (strtol(dev->filename, NULL, 10) == devnum)) ) {
350 int ac;
351 for (ac = 0; ac < desc->bNumConfigurations; ac++) {
352 struct usb_interface *interface = dev->config[ac].interface;
353 int ai;
354
355 for (ai = 0; ai < interface->num_altsetting; ai++) {
356
357 DPRINTF("intclass: %x, intsubclass: %x, intproto: %x\n",
358 interface->altsetting[i].bInterfaceClass,
359 interface->altsetting[i].bInterfaceSubClass,
360 interface->altsetting[i].bInterfaceProtocol);
361
362 if ((interface->altsetting[ai].bInterfaceSubClass == e->matchTables[i].bInterfaceSubClass) &&
363 (interface->altsetting[ai].bInterfaceProtocol == e->matchTables[i].bInterfaceProtocol)){
364 /* TODO: check interfaceClass! */
365 DPRINTF("found device with libusb\n");
366 xpcu.dev = dev;
367 xpcu.card_type = e->dwCardType;
368 }
369 }
370 }
371 }
372 }
373 }
374 }
cbfa0ac6 375
f92c0fbc
MG
376 if (!xpcu.dev)
377 return NULL;
cbfa0ac6
MG
378
379 return &xpcu;
380}
6234190b 381
f92c0fbc
MG
382void xpcu_found(struct xpcu_s *xpcu, struct event *e) {
383 if (e->handle && e->handle == (unsigned long)xpcu && xpcu->dev) {
384 struct usb_interface *interface = xpcu->dev->config->interface;
385
386 e->dwCardType = xpcu->card_type;
387 e->dwAction = 1;
388 e->dwEventId = 1;
389 e->u.Usb.dwUniqueID = e->handle;
390 e->matchTables[0].VendorId = xpcu->dev->descriptor.idVendor;
391 e->matchTables[0].ProductId = xpcu->dev->descriptor.idProduct;
392 e->matchTables[0].bDeviceClass = xpcu->dev->descriptor.bDeviceClass;
393 e->matchTables[0].bDeviceSubClass = xpcu->dev->descriptor.bDeviceSubClass;
394 e->matchTables[0].bInterfaceClass = interface->altsetting[0].bInterfaceClass;
395 e->matchTables[0].bInterfaceSubClass = interface->altsetting[0].bInterfaceSubClass;
396 e->matchTables[0].bInterfaceProtocol = interface->altsetting[0].bInterfaceProtocol;
6234190b 397 }
f92c0fbc
MG
398}
399
400void xpcu_close(struct xpcu_s *xpcu, struct event *e) {
401 if (e->handle != (unsigned long)xpcu)
402 return;
6234190b 403
f92c0fbc
MG
404 if(xpcu) {
405 if (xpcu->handle) {
406 xpcu_claim(xpcu, XPCU_RELEASE);
407 usb_close(xpcu->handle);
408 }
409
410 xpcu->handle = NULL;
411 xpcu->interface = -1;
412 xpcu->alternate = -1;
413 busses = NULL;
414 }
6234190b 415}
Impressum, Datenschutz