revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / USB / stack / usbdeviceclass.c
blob396f77ed06d4611213672daa2389a9e0b985c597
1 /*
2 Copyright (C) 2006 by Michal Schulz
3 $Id$
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #define DEBUG 1
23 #include <inttypes.h>
25 #include <aros/debug.h>
27 #include <exec/types.h>
28 #include <oop/oop.h>
30 #include <hidd/hidd.h>
31 #include <usb/usb.h>
33 #include <proto/oop.h>
34 #include <proto/utility.h>
36 #include "usb.h"
37 #include "misc.h"
39 /******************** Local utility functions area ********************/
41 static const char *unknown_name = "? unknown name ?";
42 static const char *unknown_manufacturer = "? unknown manufacturer ?";
43 static const char *unknown_serial = "? unknown serial ?";
45 static BOOL usb_SetAddress(OOP_Class *cl, OOP_Object *o, uint8_t address)
47 DeviceData *dev = OOP_INST_DATA(cl, o);
48 void *pipe = NULL;
50 USBDevice_Request request = {
51 bmRequestType: UT_WRITE_DEVICE,
52 bRequest: UR_SET_ADDRESS,
53 wValue: AROS_WORD2LE(address),
54 wIndex: AROS_WORD2LE(0),
55 wLength: AROS_WORD2LE(0)
58 if (dev->default_pipe)
59 pipe = dev->default_pipe;
60 else
61 pipe = HIDD_USBDrv_CreatePipe(dev->bus, PIPE_Control, dev->fast, dev->address, 0, 0, dev->maxpacket, 100);
63 BOOL ret = HIDD_USBDrv_ControlTransfer(dev->bus, pipe, &request, NULL, 0);
64 HIDD_USBDrv_DeletePipe(dev->bus, pipe);
66 dev->default_pipe = NULL;
68 if (ret)
70 D(bug("[USBDevice::New] testing address %d...\n", address));
71 usb_device_descriptor_t descriptor;
73 pipe = HIDD_USBDrv_CreatePipe(dev->bus, PIPE_Control, dev->fast, address, 0, 0, dev->maxpacket, 100);
75 USBDevice_Request request = {
76 bmRequestType: UT_READ_DEVICE,
77 bRequest: UR_GET_DESCRIPTOR,
78 wValue: AROS_WORD2LE(UDESC_DEVICE << 8),
79 wIndex: AROS_WORD2LE(0),
80 wLength: AROS_WORD2LE(USB_DEVICE_DESCRIPTOR_SIZE)
82 ret = HIDD_USBDrv_ControlTransfer(dev->bus, pipe, &request, &descriptor, sizeof(descriptor));
84 if (ret)
86 D(bug("[USBDevice::New] New address set correctly\n"));
87 dev->address = address;
88 dev->default_pipe = pipe;
89 return TRUE;
91 else
93 HIDD_USBDrv_DeletePipe(dev->bus, pipe);
94 return FALSE;
97 else return FALSE;
102 /******************** Implementation of interfaces ********************/
104 BOOL METHOD(USBDevice, Hidd_USBDevice, GetString)
106 DeviceData *dev = OOP_INST_DATA(cl, o);
108 if (msg->string)
110 USBDevice_Request request = {
111 bmRequestType: UT_READ_DEVICE,
112 bRequest: UR_GET_DESCRIPTOR,
113 wValue: AROS_WORD2LE(UDESC_STRING << 8 | (msg->id & 0xff)),
114 wIndex: AROS_WORD2LE(msg->language),
115 wLength: AROS_WORD2LE(1)
118 if (HIDD_USBDevice_ControlMessage(o, NULL, &request, msg->string, 1))
120 request.wLength = AROS_WORD2LE(msg->string->bLength);
121 if (HIDD_USBDrv_ControlTransfer(dev->bus, dev->default_pipe, &request, msg->string, msg->string->bLength))
123 return TRUE;
128 return FALSE;
131 OOP_Object *METHOD(USBDevice, Root, New)
133 D(bug("[USB] USBDevice::New()\n"));
135 BASE(cl->UserData)->LibNode.lib_OpenCnt++;
137 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
138 if (o)
140 DeviceData *dev = OOP_INST_DATA(cl, o);
141 usb_string_descriptor_t string;
142 uint16_t langid;
143 int i;
145 dev->tr = USBCreateTimer();
147 dev->address = GetTagData(aHidd_USBDevice_Address, 0, msg->attrList);
148 dev->hub = (OOP_Object *)GetTagData(aHidd_USBDevice_Hub, 0, msg->attrList);
149 dev->bus = (OOP_Object *)GetTagData(aHidd_USBDevice_Bus, 0, msg->attrList);
150 dev->fast = GetTagData(aHidd_USBDevice_Fast, TRUE, msg->attrList);
151 dev->maxpacket = GetTagData(aHidd_USBDevice_MaxPacketSize, 8, msg->attrList);
152 dev->iface = GetTagData(aHidd_USBDevice_Interface, 0, msg->attrList);
153 dev->default_pipe = NULL;
154 dev->config = USB_UNCONFIG_NO;
155 dev->next = (OOP_Object *)GetTagData(aHidd_USBDevice_Next, 0, msg->attrList);
158 * The USB bus object not in attrList. Try to get it from itself, with help of GetAttr call.
159 * It sounds ridiculous, but it might happen that the GetAttr is overrided already (it is
160 * the case of HUB embedded in the driver
163 if (!dev->bus && dev->hub)
164 OOP_GetAttr(dev->hub, aHidd_USBDevice_Bus, (IPTR*)&dev->bus);
166 D(bug("[USBDevice::New] Address=%02x, Interface=%02x, Bus=%p, Hub=%p\n", dev->address, dev->iface, dev->bus, dev->hub));
168 if (dev->bus)
170 if (!dev->default_pipe)
172 dev->default_pipe = HIDD_USBDevice_CreatePipe(o, PIPE_Control, 0, 0, 0, 100);
175 /* Address was either unknown or equals zero. In such case the right address has
176 * to be set */
177 if (dev->address == 0)
179 D(bug("[USBDevice::New] fetching new device address\n"));
180 uint8_t addr = HIDD_USB_AllocAddress(SD(cl)->usb, dev->bus);
181 D(bug("[USBDevice::New] trying address %d...\n", addr));
182 if (!usb_SetAddress(cl, o, addr))
183 HIDD_USB_FreeAddress(SD(cl)->usb, dev->bus, addr);
186 /* Check whether the address is set now */
187 if (!dev->address)
189 OOP_MethodID disp_mid = OOP_GetMethodID((STRPTR)IID_Root, moRoot_Dispose);
190 OOP_CoerceMethod(cl, o, &disp_mid);
191 o = NULL;
196 HIDD_USBDevice_GetDeviceDescriptor(o, &dev->descriptor);
198 D(bug("[USBDevice::New] Device %04x:%04x %02x/%02x/%02x at address %08x:%02x\n",
199 AROS_LE2WORD(dev->descriptor.idProduct), AROS_LE2WORD(dev->descriptor.idVendor),
200 dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass, dev->descriptor.bDeviceProtocol,
201 dev->bus, dev->address));
203 HIDD_USBDevice_GetString(o, USB_LANGUAGE_TABLE, 0, &string);
204 D(bug("[USBDevice::New] Default LangID=%04x\n", string.bString[0]));
205 langid = string.bString[0];
207 if (dev->descriptor.iProduct && HIDD_USBDevice_GetString(o, dev->descriptor.iProduct, langid, &string))
209 dev->product_name = AllocVecPooled(SD(cl)->MemPool, 1 + ((string.bLength - 2) >> 1));
211 for (i=0; i < (string.bLength - 2) >> 1; i++) {
212 dev->product_name[i] = AROS_LE2WORD(string.bString[i]);
214 dev->product_name[(string.bLength - 2) >> 1] = 0;
216 D(bug("[USBDevice::New] iProduct = \"%s\"\n", dev->product_name));
218 else {
219 dev->product_name = AllocVecPooled(SD(cl)->MemPool, 1 + strlen(unknown_name));
220 CopyMem(unknown_name, dev->product_name, strlen(unknown_name) + 1);
223 if (dev->descriptor.iManufacturer && HIDD_USBDevice_GetString(o, dev->descriptor.iManufacturer, langid, &string))
225 dev->manufacturer_name = AllocVecPooled(SD(cl)->MemPool, 1 + ((string.bLength - 2) >> 1));
227 for (i=0; i < (string.bLength - 2) >> 1; i++) {
228 dev->manufacturer_name[i] = AROS_LE2WORD(string.bString[i]);
230 dev->manufacturer_name[(string.bLength - 2) >> 1] = 0;
232 D(bug("[USBDevice::New] iManufacturer = \"%s\"\n", dev->manufacturer_name));
234 else {
235 dev->manufacturer_name = AllocVecPooled(SD(cl)->MemPool, 1 + strlen(unknown_manufacturer));
236 CopyMem(unknown_manufacturer, dev->manufacturer_name, strlen(unknown_manufacturer) + 1);
240 if (dev->descriptor.iSerialNumber && HIDD_USBDevice_GetString(o, dev->descriptor.iSerialNumber, langid, &string))
242 dev->serialnumber_name = AllocVecPooled(SD(cl)->MemPool, 1 + ((string.bLength - 2) >> 1));
244 for (i=0; i < (string.bLength - 2) >> 1; i++) {
245 dev->serialnumber_name[i] = AROS_LE2WORD(string.bString[i]);
247 dev->serialnumber_name[(string.bLength - 2) >> 1] = 0;
249 D(bug("[USBDevice::New] iSerial = \"%s\"\n", dev->serialnumber_name));
251 else {
252 dev->serialnumber_name = AllocVecPooled(SD(cl)->MemPool, 1 + strlen(unknown_serial));
253 CopyMem(unknown_serial, dev->serialnumber_name, strlen(unknown_serial) + 1);
257 D(bug("[USB] USBDevice::New() = %p\n",o));
259 if (!o)
260 BASE(cl->UserData)->LibNode.lib_OpenCnt--;
262 return o;
265 BOOL METHOD(USBDevice, Hidd_USBDevice, GetDescriptor)
267 USBDevice_Request req;
268 BOOL ret;
270 req.bmRequestType = UT_READ_DEVICE;
271 req.bRequest = UR_GET_DESCRIPTOR;
272 req.wValue = AROS_WORD2LE(msg->type << 8 | msg->index);
273 req.wIndex = AROS_WORD2LE(0);
274 req.wLength = AROS_WORD2LE(msg->length);
276 ret = HIDD_USBDevice_ControlMessage(o, NULL, &req, msg->descriptor, msg->length);
278 return ret;
281 BOOL METHOD(USBDevice, Hidd_USBDevice, GetConfigDescriptor)
283 return HIDD_USBDevice_GetDescriptor(o, UDESC_CONFIG, msg->index, USB_CONFIG_DESCRIPTOR_SIZE, msg->descriptor);
286 BOOL METHOD(USBDevice, Hidd_USBDevice, GetDeviceDescriptor)
288 return HIDD_USBDevice_GetDescriptor(o, UDESC_DEVICE, 0, USB_DEVICE_DESCRIPTOR_SIZE, msg->descriptor);
291 BOOL METHOD(USBDevice, Hidd_USBDevice, GetStatus)
293 USBDevice_Request req;
295 req.bmRequestType = UT_READ_DEVICE;
296 req.bRequest = UR_GET_STATUS;
297 req.wValue = AROS_WORD2LE(0);
298 req.wIndex = AROS_WORD2LE(0);
299 req.wLength = AROS_WORD2LE(sizeof(usb_status_t));
301 return HIDD_USBDevice_ControlMessage(o, NULL, &req, msg->status, sizeof(usb_status_t));
305 void * METHOD(USBDevice, Hidd_USBDevice, CreatePipe)
307 DeviceData *dev = OOP_INST_DATA(cl, o);
309 return HIDD_USBDrv_CreatePipe(dev->bus, msg->type, dev->fast, dev->address, msg->endpoint, msg->period, msg->maxpacket ? msg->maxpacket : dev->maxpacket, msg->timeout);
312 void METHOD(USBDevice, Hidd_USBDevice, DeletePipe)
314 DeviceData *dev = OOP_INST_DATA(cl, o);
316 HIDD_USBDrv_DeletePipe(dev->bus, msg->pipe);
319 void METHOD(USBDevice, Hidd_USBDevice, SetTimeout)
321 DeviceData *dev = OOP_INST_DATA(cl, o);
323 HIDD_USBDrv_SetTimeout(dev->bus, msg->pipe ? msg->pipe : dev->default_pipe, msg->timeout);
326 BOOL METHOD(USBDevice, Hidd_USBDevice, ControlMessage)
328 DeviceData *dev = OOP_INST_DATA(cl, o);
329 APTR pipe = msg->pipe ? msg->pipe : dev->default_pipe;
331 return HIDD_USBDrv_ControlTransfer(dev->bus, pipe, msg->request, msg->buffer, msg->length);
334 BOOL METHOD(USBDevice, Hidd_USBDevice, BulkTransfer)
336 DeviceData *dev = OOP_INST_DATA(cl, o);
337 APTR pipe = msg->pipe;
339 if (pipe)
340 return HIDD_USBDrv_BulkTransfer(dev->bus, pipe, msg->buffer, msg->length);
341 else
342 return FALSE;
345 static BOOL set_config(OOP_Object *o, int c)
347 USBDevice_Request req;
349 req.bmRequestType = UT_WRITE_DEVICE;
350 req.bRequest = UR_SET_CONFIG;
351 req.wValue = AROS_WORD2LE(c);
352 req.wIndex = AROS_WORD2LE(0);
353 req.wLength = AROS_WORD2LE(0);
355 return HIDD_USBDevice_ControlMessage(o, NULL, &req, NULL, 0);
358 static usb_interface_descriptor_t *find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
360 char *p = (char *)cd;
361 char *end = p + AROS_LE2WORD(cd->wTotalLength);
362 usb_interface_descriptor_t *d;
363 int curidx, lastidx, curaidx = 0;
365 for (curidx = lastidx = -1; p < end; ) {
366 d = (usb_interface_descriptor_t *)p;
367 D(bug("[USBDevice] find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
368 "type=%d\n",
369 ifaceidx, curidx, altidx, curaidx,
370 d->bLength, d->bDescriptorType));
371 if (d->bLength == 0) /* bad descriptor */
372 break;
373 p += d->bLength;
374 if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
375 if (d->bInterfaceNumber != lastidx) {
376 lastidx = d->bInterfaceNumber;
377 curidx++;
378 curaidx = 0;
379 } else
380 curaidx++;
381 if (ifaceidx == curidx && altidx == curaidx)
382 return (d);
385 return (NULL);
388 static inline usb_endpoint_descriptor_t *find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx,
389 int endptidx)
391 char *p = (char *)cd;
392 char *end = p + AROS_WORD2LE(cd->wTotalLength);
393 usb_interface_descriptor_t *d;
394 usb_endpoint_descriptor_t *e;
395 int curidx;
397 d = find_idesc(cd, ifaceidx, altidx);
398 if (d == NULL)
399 return (NULL);
400 if (endptidx >= d->bNumEndpoints) /* quick exit */
401 return (NULL);
403 curidx = -1;
404 for (p = (char *)d + d->bLength; p < end; ) {
405 e = (usb_endpoint_descriptor_t *)p;
406 if (e->bLength == 0) /* bad descriptor */
407 break;
408 p += e->bLength;
409 if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
410 return (NULL);
411 if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
412 curidx++;
413 if (curidx == endptidx)
414 return (e);
417 return (NULL);
421 static BOOL fill_iface(OOP_Class *cl, OOP_Object *o, int ifaceidx, int altidx)
423 DeviceData *dev = OOP_INST_DATA(cl, o);
424 char *p, *end;
425 InterfaceData *ifc = &dev->interfaces[ifaceidx];
426 usb_interface_descriptor_t *idesc;
427 int endpt, nendpt;
429 D(bug("[USBDevice] fill_iface: ifaceidx=%d altidx=%d\n",
430 ifaceidx, altidx));
432 idesc = find_idesc(dev->config_desc, ifaceidx, altidx);
433 if (idesc == NULL)
434 return FALSE;
436 ifc->interface = idesc;
437 ifc->index = ifaceidx;
438 ifc->altindex = altidx;
440 nendpt = ifc->interface->bNumEndpoints;
442 D(bug("[USBDevice] fill_iface: found idesc nendpt=%d\n", nendpt));
444 if (nendpt != 0)
446 ifc->endpoints = AllocVecPooled(SD(cl)->MemPool, nendpt * sizeof(EndpointData));
447 if (ifc->endpoints == NULL)
448 return FALSE;
449 } else
450 ifc->endpoints = NULL;
452 p = (char *)ifc->interface + ifc->interface->bLength;
453 end = (char *)dev->config_desc + AROS_LE2WORD(dev->config_desc->wTotalLength);
454 #define ed ((usb_endpoint_descriptor_t *)p)
456 for (endpt = 0; endpt < nendpt; endpt++)
458 D(bug("[USBDevice] fill_iface: endpt=%d\n", endpt));
459 for (; p < end; p += ed->bLength) {
460 D(bug("[USBDevice] fill_iface: p=%p end=%p "
461 "len=%d type=%d\n",
462 p, end, ed->bLength, ed->bDescriptorType));
463 if (p + ed->bLength <= end && ed->bLength != 0 &&
464 ed->bDescriptorType == UDESC_ENDPOINT)
465 goto found;
466 if (ed->bLength == 0 ||
467 ed->bDescriptorType == UDESC_INTERFACE)
468 break;
470 /* passed end, or bad desc */
471 bug("[USBDevice] fill_iface: bad descriptor(s): %s\n",
472 ed->bLength == 0 ? "0 length" :
473 ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":"out of data");
474 goto bad;
475 found:
476 D(bug("[USBDevice] fill_iface: endpoint descriptor %p\n", ed));
477 ifc->endpoints[endpt].endpoint = ed;
478 p += ed->bLength;
480 return TRUE;
482 bad:
483 if (ifc->endpoints != NULL) {
484 FreeVecPooled(SD(cl)->MemPool, ifc->endpoints);
485 ifc->endpoints = NULL;
487 return FALSE;
490 static void free_iface(OOP_Class *cl, OOP_Object *o, int i)
492 DeviceData *dev = OOP_INST_DATA(cl, o);
493 InterfaceData *iface = &dev->interfaces[i];
494 if (iface->endpoints)
495 FreeVecPooled(SD(cl)->MemPool, iface->endpoints);
498 BOOL METHOD(USBDevice, Hidd_USBDevice, Configure)
500 DeviceData *dev = OOP_INST_DATA(cl, o);
501 usb_config_descriptor_t cd, *cdp;
502 int i, length;
503 BOOL err;
505 D(bug("[USBDevice::Configure] Configure(%d)\n", msg->configNr));
507 if (dev->config != USB_UNCONFIG_NO)
509 int i, ifaces = dev->config_desc->bNumInterface;
510 for (i=0; i < ifaces; i++)
511 free_iface(cl, o, i);
512 FreeVecPooled(SD(cl)->MemPool, dev->interfaces);
513 FreeVecPooled(SD(cl)->MemPool, dev->config_desc);
514 dev->interfaces = NULL;
515 dev->config_desc = NULL;
516 dev->config = USB_UNCONFIG_NO;
519 if (msg->configNr == USB_UNCONFIG_INDEX)
521 D(bug("[USBDevice::Configure] Unconfiguring "));
522 if ((err = set_config(o, USB_UNCONFIG_NO)))
523 D(bug("with success\n"));
524 else
525 D(bug("with ERROR\n"));
526 return err;
529 HIDD_USBDevice_GetConfigDescriptor(o, 0, &cd);
530 length = AROS_LE2WORD(cd.wTotalLength);
532 D(bug("[USBDevice::Configure] Fetching config descriptor of length %d\n", length));
534 cdp = AllocVecPooled(SD(cl)->MemPool, length);
535 if (cdp == NULL)
536 return FALSE;
538 for (i=0; i < 3; i++)
540 if (HIDD_USBDevice_GetDescriptor(o, UDESC_CONFIG, msg->configNr, length, cdp))
541 break;
542 D(bug("[USBDevice::Configure] retry...\n"));
543 USBDelay(dev->tr, 200);
546 if (i == 3)
548 D(bug("[USBDevice::Configure] failed...\n"));
551 /* TODO: Power! Self powered? */
552 err = set_config(o, cdp->bConfigurationValue);
554 D(bug("[USBDevice::Configure] Allocating %d interfaces\n", cdp->bNumInterface ));
555 dev->interfaces = AllocVecPooled(SD(cl)->MemPool, sizeof(InterfaceData) * cdp->bNumInterface);
556 if (!dev->interfaces)
558 /* NOMEM! */
561 dev->config_desc = cdp;
562 dev->config = cdp->bConfigurationValue;
564 for (i = 0; i < cdp->bNumInterface; i++)
566 err = fill_iface(cl, o, i, 0);
567 if (!err)
569 D(bug("[USBDevice::Configure] error at interface %d\n", i));
570 while (--i >= 0)
571 free_iface(cl, o, i);
572 return FALSE;
576 return TRUE;
579 usb_interface_descriptor_t * METHOD(USBDevice, Hidd_USBDevice, GetInterface)
581 DeviceData *dev = OOP_INST_DATA(cl, o);
582 usb_interface_descriptor_t *d = NULL;
584 if (dev->config != USB_UNCONFIG_NO)
586 if (msg->interface < dev->config_desc->bNumInterface)
588 d = dev->interfaces[msg->interface].interface;
592 return d;
595 usb_endpoint_descriptor_t * METHOD(USBDevice, Hidd_USBDevice, GetEndpoint)
597 DeviceData *dev = OOP_INST_DATA(cl, o);
598 usb_endpoint_descriptor_t *d = NULL;
600 if (dev->config != USB_UNCONFIG_NO)
602 if (msg->interface < dev->config_desc->bNumInterface)
604 if (msg->endpoint < dev->interfaces[msg->interface].interface->bNumEndpoints)
606 d = dev->interfaces[msg->interface].endpoints[msg->endpoint].endpoint;
611 DumpDescriptor((usb_descriptor_t *)d);
613 return d;
616 void METHOD(USBDevice, Root, Dispose)
618 DeviceData *dev = OOP_INST_DATA(cl, o);
619 struct Library *base = &BASE(cl->UserData)->LibNode;
621 D(bug("[USB] USBDevice::Dispose\n"));
623 if (dev->next)
624 OOP_DisposeObject(dev->next);
626 // Do not unconfigure. The device may not exist already...
627 // HIDD_USBDevice_Configure(o, USB_UNCONFIG_INDEX);
629 if (dev->product_name && dev->product_name != unknown_name)
630 FreeVecPooled(SD(cl)->MemPool, dev->product_name);
632 if (dev->manufacturer_name && dev->manufacturer_name != unknown_manufacturer)
633 FreeVecPooled(SD(cl)->MemPool, dev->manufacturer_name);
635 if (dev->serialnumber_name && dev->serialnumber_name != unknown_serial)
636 FreeVecPooled(SD(cl)->MemPool, dev->serialnumber_name);
638 if (dev->default_pipe)
639 HIDD_USBDrv_DeletePipe(dev->bus, dev->default_pipe);
641 USBDeleteTimer(dev->tr);
643 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
645 base->lib_OpenCnt--;
648 void METHOD(USBDevice, Root, Get)
650 uint32_t idx;
651 DeviceData *dev = OOP_INST_DATA(cl, o);
653 if (IS_USBDEVICE_ATTR(msg->attrID, idx))
655 switch (idx)
657 case aoHidd_USBDevice_Address:
658 *msg->storage = dev->address;
659 break;
661 case aoHidd_USBDevice_Bus:
662 *msg->storage = (intptr_t)dev->bus;
663 break;
665 case aoHidd_USBDevice_Hub:
666 *msg->storage = (intptr_t)dev->hub;
667 break;
669 case aoHidd_USBDevice_Fast:
670 *msg->storage = dev->fast;
671 break;
673 case aoHidd_USBDevice_MaxPacketSize:
674 *msg->storage = dev->maxpacket;
675 break;
677 case aoHidd_USBDevice_ProductID:
678 *msg->storage = AROS_LE2WORD(dev->descriptor.idProduct);
679 break;
681 case aoHidd_USBDevice_VendorID:
682 *msg->storage = AROS_LE2WORD(dev->descriptor.idVendor);
683 break;
685 case aoHidd_USBDevice_ProductName:
686 *msg->storage = (intptr_t)dev->product_name;
687 break;
689 case aoHidd_USBDevice_ManufacturerName:
690 *msg->storage = (intptr_t)dev->manufacturer_name;
691 break;
693 case aoHidd_USBDevice_SerialNumber:
694 *msg->storage = (intptr_t)dev->serialnumber_name;
695 break;
697 case aoHidd_USBDevice_Next:
698 *msg->storage = (intptr_t)dev->next;
699 break;
701 case aoHidd_USBDevice_Interface:
702 *msg->storage = (intptr_t)dev->iface;
703 break;
705 case aoHidd_USBDevice_InterfaceNumber:
706 *msg->storage = dev->interfaces[dev->iface].interface->bInterfaceNumber;
707 break;
709 default:
710 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
711 break;
714 else
715 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
718 void METHOD(USBDevice, Root, Set)
720 uint32_t idx;
721 struct TagItem *tag;
722 struct TagItem *tags = msg->attrList;
724 while ((tag = NextTagItem(&tags)))
726 if (IS_USBDEVICE_ATTR(tag->ti_Tag, idx))
728 switch(idx)
730 case aoHidd_USBDevice_Address:
731 usb_SetAddress(cl, o, tag->ti_Data);
732 break;
734 default:
735 break;
739 else
740 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
743 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);