2 Copyright (C) 2006 by Michal Schulz
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.
23 #include <aros/debug.h>
24 #include <aros/libcall.h>
26 #include <exec/types.h>
29 #include <dos/dosextens.h>
31 #include <hidd/hidd.h>
34 #include <proto/oop.h>
35 #include <proto/dos.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
));
52 BASE(cl
->UserData
)->LibNode
.lib_OpenCnt
--;
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
);
68 void METHOD(USB
, Root
, Get
)
71 D(bug("[USB] USB::Get\n"));
73 if (IS_USB_ATTR(msg
->attrID
, idx
))
79 D(bug("[USB] USB Get Bus. *msg->storage = %p\n", *msg
->storage
));
82 ObtainSemaphore(&SD(cl
)->driverListLock
);
86 ForeachNode(&SD(cl
)->driverList
, driver
)
88 if ((IPTR
)driver
->d_Driver
== *msg
->storage
)
93 driver
= (usb_driver_t
*)GetSucc(&driver
->d_Node
);
96 driver
= (usb_driver_t
*)GetHead(&SD(cl
)->driverList
);
98 D(bug("[USB] driver=%p\n", driver
));
101 *msg
->storage
= (IPTR
)driver
->d_Driver
;
103 *msg
->storage
= (IPTR
)NULL
;
105 ReleaseSemaphore(&SD(cl
)->driverListLock
);
109 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
113 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
116 BOOL
METHOD(USB
, Hidd_USB
, AttachDriver
)
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
));
128 drv
->d_Driver
= msg
->driverObject
;
129 InitSemaphore(&drv
->d_Lock
);
131 for (i
=0; i
< (BITMAP_SIZE
/32); i
++) {
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
);
152 BOOL
METHOD(USB
, Hidd_USB
, DetachDriver
)
154 D(bug("[USB] USB::DetachDriver()\n"));
159 void METHOD(USB
, Hidd_USB
, AddClass
)
161 struct usb_ExtClass
*ec
= NULL
;
164 D(bug("[USB] USB::AddClass(\"%s\")\n", msg
->className
));
166 ForeachNode(&SD(cl
)->extClassList
, ec
)
168 if (!strcmp(msg
->className
, ec
->ec_ShortName
))
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
;
194 ObtainSemaphore(&SD(cl
)->driverListLock
);
195 ForeachNode(&SD(cl
)->driverList
, drv
)
197 if (drv
->d_Driver
== msg
->driverObject
)
200 ReleaseSemaphore(&SD(cl
)->driverListLock
);
204 ObtainSemaphore(&drv
->d_Lock
);
205 addr
= allocBitmap(drv
->bitmap
);
206 ReleaseSemaphore(&drv
->d_Lock
);
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
)
222 ReleaseSemaphore(&SD(cl
)->driverListLock
);
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
;
237 usb_device_descriptor_t descriptor
;
238 usb_config_descriptor_t config
;
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
);
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
)
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);
295 bug("[USB] Could not set device address\n");
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
));
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
},
324 switch(descriptor
.bDeviceClass
)
327 new_device
= OOP_NewObject(NULL
, (STRPTR
)CLID_Hidd_USBHub
, tags
);
328 HIDD_USBHub_OnOff(new_device
, TRUE
);
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
));
346 ec
->ec_LibBase
= OpenLibrary(ec
->ec_Node
.ln_Name
, 0);
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,);
357 new_device
= OOP_NewObject(NULL
, (STRPTR
)clid
, tags
);
361 tags
[2].ti_Data
= (intptr_t)new_device
;
362 break; /* One loop up */
374 FreeVecPooled(SD(cl
)->MemPool
, cdesc
);
376 ReleaseSemaphore(&drv
->d_Lock
);