revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / USB / stack / usbclass.c
blob1d561aacda643c3e90478c0e6da30bd3506c9f5b
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 0
23 #include <aros/debug.h>
24 #include <aros/libcall.h>
26 #include <exec/types.h>
27 #include <oop/oop.h>
28 #include <dos/dos.h>
29 #include <dos/dosextens.h>
31 #include <hidd/hidd.h>
32 #include <usb/usb.h>
34 #include <proto/oop.h>
35 #include <proto/dos.h>
37 #include <stdint.h>
39 #include "usb.h"
40 #include "misc.h"
42 OOP_Object *METHOD(USB, Root, New)
44 D(bug("[USB] USB::New()\n"));
46 BASE(cl->UserData)->LibNode.lib_OpenCnt++;
48 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
49 D(bug("[USB] USB::New() = %p\n", o));
51 if (!o)
52 BASE(cl->UserData)->LibNode.lib_OpenCnt--;
54 return o;
57 void METHOD(USB, Root, Dispose)
59 struct Library *base = &BASE(cl->UserData)->LibNode;
61 D(bug("[USB] USB::Dispose\n"));
63 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
65 base->lib_OpenCnt--;
68 void METHOD(USB, Root, Get)
70 uint32_t idx;
71 D(bug("[USB] USB::Get\n"));
73 if (IS_USB_ATTR(msg->attrID, idx))
75 switch (idx)
77 case aoHidd_USB_Bus:
79 D(bug("[USB] USB Get Bus. *msg->storage = %p\n", *msg->storage));
80 usb_driver_t *driver;
82 ObtainSemaphore(&SD(cl)->driverListLock);
84 if (*msg->storage)
86 ForeachNode(&SD(cl)->driverList, driver)
88 if ((IPTR)driver->d_Driver == *msg->storage)
89 break;
92 if (driver)
93 driver = (usb_driver_t *)GetSucc(&driver->d_Node);
95 else
96 driver = (usb_driver_t *)GetHead(&SD(cl)->driverList);
98 D(bug("[USB] driver=%p\n", driver));
100 if (driver)
101 *msg->storage = (IPTR)driver->d_Driver;
102 else
103 *msg->storage = (IPTR)NULL;
105 ReleaseSemaphore(&SD(cl)->driverListLock);
106 break;
108 default:
109 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
112 else
113 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
116 BOOL METHOD(USB, Hidd_USB, AttachDriver)
118 BOOL retval = FALSE;
119 D(bug("[USB] USB::AttachDriver(%p)\n", msg->driverObject));
121 if (msg->driverObject)
123 usb_driver_t *drv = AllocPooled(SD(cl)->MemPool, sizeof(struct usb_driver));
125 if (drv)
127 int i;
128 drv->d_Driver = msg->driverObject;
129 InitSemaphore(&drv->d_Lock);
131 for (i=0; i < (BITMAP_SIZE/32); i++) {
132 drv->bitmap[i] = 0;
134 setBitmap(drv->bitmap, 0);
135 setBitmap(drv->bitmap, 1);
137 ObtainSemaphore(&SD(cl)->driverListLock);
138 AddTail(&SD(cl)->driverList, &drv->d_Node);
139 ReleaseSemaphore(&SD(cl)->driverListLock);
141 //HIDD_USBHub_OnOff(drv->d_Driver, FALSE);
142 HIDD_USBHub_OnOff(drv->d_Driver, TRUE);
144 retval = TRUE;
149 return retval;
152 BOOL METHOD(USB, Hidd_USB, DetachDriver)
154 D(bug("[USB] USB::DetachDriver()\n"));
156 return FALSE;
159 void METHOD(USB, Hidd_USB, AddClass)
161 struct usb_ExtClass *ec = NULL;
162 int found = 0;
164 D(bug("[USB] USB::AddClass(\"%s\")\n", msg->className));
166 ForeachNode(&SD(cl)->extClassList, ec)
168 if (!strcmp(msg->className, ec->ec_ShortName))
170 found = 1;
171 break;
175 if (!found)
177 D(bug("[USB] Class not on the list. Adding it.\n"));
179 ec = AllocVecPooled(SD(cl)->MemPool, sizeof(struct usb_ExtClass));
181 ec->ec_Node.ln_Name = AllocVecPooled(SD(cl)->MemPool, strlen(msg->className)+1);
182 CopyMem(msg->className, ec->ec_Node.ln_Name, strlen(msg->className)+1);
183 ec->ec_ShortName = AllocVecPooled(SD(cl)->MemPool, strlen(msg->className)+1);
184 CopyMem(msg->className, (char *)ec->ec_ShortName, strlen(msg->className)+1);
185 AddTail(&SD(cl)->extClassList, &ec->ec_Node);
189 uint8_t METHOD(USB, Hidd_USB, AllocAddress)
191 struct usb_driver *drv = NULL;
192 uint8_t addr = 0;
194 ObtainSemaphore(&SD(cl)->driverListLock);
195 ForeachNode(&SD(cl)->driverList, drv)
197 if (drv->d_Driver == msg->driverObject)
198 break;
200 ReleaseSemaphore(&SD(cl)->driverListLock);
202 if (drv)
204 ObtainSemaphore(&drv->d_Lock);
205 addr = allocBitmap(drv->bitmap);
206 ReleaseSemaphore(&drv->d_Lock);
209 return addr;
212 void METHOD(USB, Hidd_USB, FreeAddress)
214 struct usb_driver *drv = NULL;
216 ObtainSemaphore(&SD(cl)->driverListLock);
217 ForeachNode(&SD(cl)->driverList, drv)
219 if (drv->d_Driver == msg->driverObject)
220 break;
222 ReleaseSemaphore(&SD(cl)->driverListLock);
224 if (drv)
226 ObtainSemaphore(&drv->d_Lock);
227 freeBitmap(drv->bitmap, msg->address);
228 ReleaseSemaphore(&drv->d_Lock);
232 OOP_Object *METHOD(USB, Hidd_USB, NewDevice)
234 OOP_Object *new_device = NULL;
235 APTR pipe;
236 OOP_Object *bus;
237 usb_device_descriptor_t descriptor;
238 usb_config_descriptor_t config;
239 void *cdesc;
240 uint8_t address;
242 USBDevice_Request request = {
243 bmRequestType: UT_READ_DEVICE,
244 bRequest: UR_GET_DESCRIPTOR,
245 wValue: AROS_WORD2LE(UDESC_DEVICE << 8),
246 wIndex: AROS_WORD2LE(0),
247 wLength: AROS_WORD2LE(8)
250 memset(&descriptor, 0, sizeof(descriptor));
252 OOP_GetAttr(msg->hub, aHidd_USBDevice_Bus, (IPTR*)&bus);
254 if (bus)
256 struct usb_ExtClass *ec;
257 struct usb_driver *drv = NULL;
259 ObtainSemaphore(&SD(cl)->driverListLock);
260 ForeachNode(&SD(cl)->driverList, drv)
262 if (drv->d_Driver == bus)
263 break;
265 ReleaseSemaphore(&SD(cl)->driverListLock);
267 ObtainSemaphore(&drv->d_Lock);
269 pipe = HIDD_USBDrv_CreatePipe(bus, PIPE_Control, msg->fast, 0, 0, 0, 8, 100);
271 HIDD_USBDrv_ControlTransfer(bus, pipe, &request, &descriptor, 8);
272 D(bug("[USB] USB::NewDevice()\n"));
274 DumpDescriptor(&descriptor);
277 if ((address = HIDD_USB_AllocAddress(o, bus)))
279 USBDevice_Request req = {
280 bmRequestType: UT_WRITE_DEVICE,
281 bRequest: UR_SET_ADDRESS,
282 wValue: AROS_WORD2LE(address),
283 wIndex: AROS_WORD2LE(0),
284 wLength: AROS_WORD2LE(0)
287 HIDD_USBDrv_ControlTransfer(bus, pipe, &req, NULL, 0);
289 HIDD_USBDrv_DeletePipe(bus, pipe);
291 pipe = HIDD_USBDrv_CreatePipe(bus, PIPE_Control, msg->fast, address, 0, 0, descriptor.bMaxPacketSize, 100);
293 if (!pipe)
295 bug("[USB] Could not set device address\n");
296 return NULL;
300 request.wValue = AROS_WORD2LE(UDESC_CONFIG << 8);
301 request.wLength = AROS_WORD2LE(USB_CONFIG_DESCRIPTOR_SIZE);
303 HIDD_USBDrv_ControlTransfer(bus, pipe, &request, &config, USB_CONFIG_DESCRIPTOR_SIZE);
305 cdesc = AllocVecPooled(SD(cl)->MemPool, AROS_LE2WORD(config.wTotalLength));
306 if (cdesc)
308 request.wLength = config.wTotalLength;
309 HIDD_USBDrv_ControlTransfer(bus, pipe, &request, cdesc, AROS_LE2WORD(config.wTotalLength));
312 HIDD_USBDrv_DeletePipe(bus, pipe);
314 struct TagItem tags[] = {
315 { aHidd_USBDevice_Interface, 0 },
316 { aHidd_USBDevice_Address, address },
317 { aHidd_USBDevice_Next, 0 },
318 { aHidd_USBDevice_Hub, (uintptr_t)msg->hub },
319 { aHidd_USBDevice_Fast, msg->fast },
320 { aHidd_USBDevice_MaxPacketSize, descriptor.bMaxPacketSize },
321 { TAG_DONE, 0UL },
324 switch(descriptor.bDeviceClass)
326 case UDCLASS_HUB:
327 new_device = OOP_NewObject(NULL, (STRPTR)CLID_Hidd_USBHub, tags);
328 HIDD_USBHub_OnOff(new_device, TRUE);
329 break;
331 default:
333 int i;
335 /* Try a match for every interface */
336 for (i = config.bNumInterface; i > 0; i--)
338 D(bug("[USB] Looking for a driver for interface no. %d\n", i));
339 tags[0].ti_Data = i - 1;
341 ForeachNode(&SD(cl)->extClassList, ec)
343 D(bug("[USB] Trying external class \"%s\"\n", ec->ec_Node.ln_Name));
345 if (!ec->ec_LibBase)
346 ec->ec_LibBase = OpenLibrary(ec->ec_Node.ln_Name, 0);
348 if (ec->ec_LibBase)
350 void *clid = AROS_LVO_CALL3(void *,
351 AROS_LCA(usb_device_descriptor_t *, &descriptor, A0),
352 AROS_LCA(usb_config_descriptor_t *, cdesc, A1),
353 AROS_LCA(int, i - 1, D0),
354 struct Library *, ec->ec_LibBase, 5,);
355 if (clid)
357 new_device = OOP_NewObject(NULL, (STRPTR)clid, tags);
359 if (new_device)
361 tags[2].ti_Data = (intptr_t)new_device;
362 break; /* One loop up */
369 break;
373 if (cdesc)
374 FreeVecPooled(SD(cl)->MemPool, cdesc);
376 ReleaseSemaphore(&drv->d_Lock);
379 return new_device;