2 Copyright © 2014, The AROS Development Team. All rights reserved.
5 Desc: Virtual XHCI USB host controller
14 #include <aros/debug.h>
15 #include <aros/macros.h>
16 #include <aros/asmcall.h>
17 #include <aros/symbolsets.h>
19 #include <proto/exec.h>
20 #include <proto/stdc.h>
21 #include <proto/arossupport.h>
23 #include <devices/usb.h>
24 #include <devices/usb_hub.h>
25 #include <devices/newstyle.h>
26 #include <devices/usbhardware.h>
28 #include "vxhci_device.h"
30 #include LC_LIBDEFS_FILE
32 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
) {
33 mybug(0, ("[VXHCI] cmdQueryDevice: Entering function\n"));
35 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
37 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
41 while((tag
= LibNextTagItem(&taglist
)) != NULL
) {
42 switch (tag
->ti_Tag
) {
43 case UHA_Manufacturer
:
44 *((STRPTR
*) tag
->ti_Data
) = "The AROS Development Team";
48 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
52 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
56 *((STRPTR
*) tag
->ti_Data
) ="©2014 The AROS Development Team";
61 static char productname
[100];
62 sprintf(productname
, "VXHCI (USB%x.%x ports)", AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>8)&0xf, AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>4)&0xf);
63 *((STRPTR
*) tag
->ti_Data
) = productname
;
69 static char description
[100];
70 sprintf(description
, "Virtual XHCI (USB%x.%x ports)", AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>8)&0xf, AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>4)&0xf);
71 *((STRPTR
*) tag
->ti_Data
) = description
;
75 case UHA_Capabilities
:
77 if( (AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
) >= 0x200) && (AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
) < 0x300)) {
78 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB20
);
80 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB30
);
83 *((ULONG
*) tag
->ti_Data
) = (UHCF_USB20
|UHCF_USB30
);
92 mybug_unit(0, ("Done\n\n"));
94 ioreq
->iouh_Actual
= count
;
98 BOOL
cmdAbortIO(struct IOUsbHWReq
*ioreq
) {
99 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
100 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
102 /* If not quick I/O, reply the message */
103 if (!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
)) {
104 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
110 WORD
cmdUsbReset(struct IOUsbHWReq
*ioreq
) {
111 mybug(0, ("[VXHCI] cmdUsbReset: Entering function\n"));
113 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
115 /* We should do a proper reset sequence with a real driver */
116 unit
->state
= UHSF_RESET
;
117 unit
->roothub
.addr
= 0;
118 unit
->state
= UHSF_OPERATIONAL
;
119 mybug_unit(0, ("Done\n\n"));
123 WORD
cmdControlXFer(struct IOUsbHWReq
*ioreq
) {
124 mybug(0, ("[VXHCI] cmdControlXFer: Entering function\n"));
126 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
128 mybug_unit(0, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
129 mybug_unit(0, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
132 Check the status of the controller
133 We might encounter these states:
134 UHSB_OPERATIONAL USB can be used for transfers
135 UHSB_RESUMING USB is currently resuming
136 UHSB_SUSPENDED USB is in suspended state
137 UHSB_RESET USB is just inside a reset phase
140 if(unit
->state
== UHSF_OPERATIONAL
) {
141 mybug_unit(0, ("Unit state is operational\n"));
143 mybug_unit(-1, ("Unit state is not operational!\n"));
144 return UHIOERR_USBOFFLINE
;
147 if(ioreq
->iouh_DevAddr
== unit
->roothub
.addr
) {
148 return(cmdControlXFerRootHub(ioreq
));
154 WORD
cmdControlXFerRootHub(struct IOUsbHWReq
*ioreq
) {
155 mybug(0, ("[VXHCI] cmdControlXFerRootHub: Entering function\n"));
157 UWORD bmRequestType
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_STANDARD
| URTF_CLASS
| URTF_VENDOR
);
158 UWORD bmRequestDirection
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_IN
| URTF_OUT
);
159 UWORD bmRequestRecipient
= (ioreq
->iouh_SetupData
.bmRequestType
) & (URTF_DEVICE
| URTF_INTERFACE
| URTF_ENDPOINT
| URTF_OTHER
);
161 UWORD bRequest
= (ioreq
->iouh_SetupData
.bRequest
);
162 UWORD wIndex
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
);
163 UWORD wValue
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wValue
);
164 UWORD wLength
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
166 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
167 struct VXHCIPort
*port
= NULL
;
169 /* Endpoint 0 is used for control transfers only and can not be assigned to any other function. */
170 if(ioreq
->iouh_Endpoint
!= 0) {
171 mybug_unit(-1, ("Wrong endpoint number! %ld\n", ioreq
->iouh_Endpoint
));
172 return UHIOERR_BADPARAMS
;
175 /* Check the request */
176 if(bmRequestDirection
) {
177 mybug_unit(0, ("Request direction is device to host\n"));
179 switch(bmRequestType
) {
181 mybug_unit(0, ("URTF_STANDARD\n"));
183 switch(bmRequestRecipient
) {
185 mybug_unit(0, ("URTF_DEVICE\n"));
188 case USR_GET_DESCRIPTOR
:
189 mybug_unit(0, ("USR_GET_DESCRIPTOR\n"));
191 switch( (wValue
>>8) ) {
193 mybug_unit(0, ("UDT_DEVICE\n"));
194 mybug_unit(0, ("GetDeviceDescriptor (%ld)\n", wLength
));
196 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbStdDevDesc
)) ? sizeof(struct UsbStdDevDesc
) : wLength
;
197 CopyMem((APTR
) &unit
->roothub
.devdesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
199 mybug_unit(0, ("Done\n\n"));
200 return UHIOERR_NO_ERROR
;
203 case UDT_CONFIGURATION
:
204 mybug_unit(0, ("UDT_CONFIGURATION\n"));
205 mybug_unit(0, ("GetConfigDescriptor (%ld)\n", wLength
));
207 ioreq
->iouh_Actual
= (wLength
> sizeof(struct RHConfig
)) ? sizeof(struct RHConfig
) : wLength
;
208 CopyMem((APTR
) &unit
->roothub
.config
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
210 //bug("sizeof(struct RHConfig) = %ld (should be 25)\n", sizeof(struct RHConfig));
211 mybug_unit(0, ("Done\n\n"));
212 return UHIOERR_NO_ERROR
;
217 mybug_unit(0, ("UDT_STRING id %d\n", (wValue
& 0xff)));
220 switch( (wValue
& 0xff) ) {
222 mybug_unit(0, ("GetStringDescriptor (%ld)\n", wLength
));
224 /* This is our root hub string descriptor */
225 struct UsbStdStrDesc
*strdesc
= (struct UsbStdStrDesc
*) ioreq
->iouh_Data
;
227 strdesc
->bLength
= sizeof(struct UsbStdStrDesc
);
228 strdesc
->bDescriptorType
= UDT_STRING
;
231 strdesc
->bString
[0] = AROS_WORD2LE(0x0409); // English (Yankee)
232 ioreq
->iouh_Actual
= sizeof(struct UsbStdStrDesc
);
233 mybug_unit(0, ("Done\n\n"));
234 return UHIOERR_NO_ERROR
;
236 ioreq
->iouh_Actual
= wLength
;
237 mybug_unit(0, ("Done\n\n"));
238 return UHIOERR_NO_ERROR
;
244 return cmdGetString(ioreq
, "The AROS Development Team.");
248 char roothubname
[100];
249 sprintf(roothubname
, "VXHCI root hub (USB%x.%x)", AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>8)&0xf, AROS_LE2WORD(unit
->roothub
.devdesc
.bcdUSB
>>4)&0xf);
250 return cmdGetString(ioreq
, roothubname
);
255 return cmdGetString(ioreq
, "Standard Config");
259 return cmdGetString(ioreq
, "Hub interface");
270 bug("[VXHCI] cmdControlXFerRootHub: UDT_INTERFACE\n");
274 bug("[VXHCI] cmdControlXFerRootHub: UDT_ENDPOINT\n");
277 case UDT_DEVICE_QUALIFIER
:
278 bug("[VXHCI] cmdControlXFerRootHub: UDT_DEVICE_QUALIFIER\n");
281 case UDT_OTHERSPEED_QUALIFIER
:
282 bug("[VXHCI] cmdControlXFerRootHub: UDT_OTHERSPEED_QUALIFIER\n");
285 case UDT_INTERFACE_POWER
:
286 bug("[VXHCI] cmdControlXFerRootHub: UDT_INTERFACE_POWER\n");
290 bug("[VXHCI] cmdControlXFerRootHub: UDT_OTG\n");
294 bug("[VXHCI] cmdControlXFerRootHub: UDT_DEBUG\n");
297 case UDT_INTERFACE_ASSOCIATION
:
298 bug("[VXHCI] cmdControlXFerRootHub: UDT_INTERFACE_ASSOCIATION\n");
302 bug("[VXHCI] cmdControlXFerRootHub: UDT_SECURITY\n");
305 case UDT_ENCRYPTION_TYPE
:
306 bug("[VXHCI] cmdControlXFerRootHub: UDT_ENCRYPTION_TYPE\n");
310 bug("[VXHCI] cmdControlXFerRootHub: UDT_BOS\n");
311 /* TODO: Arbitrary, set real values according to the host controller */
312 unit
->roothub
.bosdesc
.wTotalLength
= 16;
313 unit
->roothub
.bosdesc
.bNumDeviceCaps
= 2;
315 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbStdBOSDesc
)) ? sizeof(struct UsbStdBOSDesc
) : wLength
;
316 CopyMem((APTR
) &unit
->roothub
.bosdesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
318 mybug_unit(0, ("Done\n\n"));
319 return UHIOERR_NO_ERROR
;
322 case UDT_DEVICE_CAPABILITY
:
323 bug("[VXHCI] cmdControlXFerRootHub: UDT_DEVICE_CAPABILITY\n");
326 case UDT_WIRELESS_EP_COMP
:
327 bug("[VXHCI] cmdControlXFerRootHub: UDT_WIRELESS_EP_COMP\n");
331 bug("[VXHCI] cmdControlXFerRootHub: switch( (wValue>>8) ) %ld\n", (wValue
>>8));
334 } /* switch( (wValue>>8) ) */
335 break; /* case USR_GET_DESCRIPTOR */
338 mybug_unit(0, ("USR_GET_STATUS\n"));
339 ((UWORD
*) ioreq
->iouh_Data
)[0] = AROS_WORD2LE(U_GSF_SELF_POWERED
);
340 ioreq
->iouh_Actual
= wLength
;
341 mybug_unit(0, ("Done\n\n"));
342 return UHIOERR_NO_ERROR
;
345 //case USR_GET_INTERFACE: //Undefined. Hubs are allowed to support only one interface.
347 } /* switch(bRequest) */
348 break; /* case URTF_DEVICE: */
350 /* switch(bmRequestRecipient) */
352 mybug_unit(0, ("URTF_INTERFACE\n"));
355 /* switch(bmRequestRecipient) */
357 mybug_unit(0, ("URTF_ENDPOINT\n"));
360 /* switch(bmRequestRecipient) */
362 mybug_unit(0, ("URTF_OTHER\n"));
365 /* switch(bmRequestRecipient) */
367 mybug_unit(0, ("Request defaulting %ld\n", bRequest
));
370 } /* switch(bmRequestRecipient) */
373 /* switch(bmRequestType) */
375 mybug_unit(0, ("URTF_CLASS\n"));
377 switch(bmRequestRecipient
) {
379 mybug_unit(0, ("URTF_DEVICE\n"));
383 mybug_unit(-1, ("USR_GET_STATUS\n"));
384 UWORD
*mptr
= ioreq
->iouh_Data
;
385 if(wLength
< sizeof(struct UsbHubStatus
)) {
390 ioreq
->iouh_Actual
= 4;
391 mybug_unit(-1, ("Something done, check me...\n\n"));
392 return UHIOERR_NO_ERROR
;
395 /* switch(bRequest) */
396 case USR_GET_DESCRIPTOR
:
397 mybug_unit(0, ("[VXHCI] cmdControlXFerRootHub: USR_GET_DESCRIPTOR\n"));
399 switch( (wValue
>>8) ) {
401 mybug_unit(0, ("UDT_SSHUB\n"));
402 mybug_unit(0, ("GetRootHubDescriptor USB3.0 (%ld)\n", wLength
));
404 ioreq
->iouh_Actual
= (wLength
> sizeof(struct UsbSSHubDesc
)) ? sizeof(struct UsbSSHubDesc
) : wLength
;
405 CopyMem((APTR
) &unit
->roothub
.hubdesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
407 mybug_unit(0, ("Done\n\n"));
408 return UHIOERR_NO_ERROR
;
411 } /* switch( (wValue>>8) ) */
413 mybug_unit(0, ("Done\n\n"));
414 return UHIOERR_NO_ERROR
;
417 } /* switch(bRequest) */
420 /* switch(bmRequestRecipient) */
422 mybug_unit(0, ("URTF_OTHER\n"));
426 mybug_unit(0, ("USR_GET_STATUS\n"));
427 if(wLength
!= sizeof(struct UsbPortStatus
)) {
428 mybug_unit(-1, ("Invalid port status structure!\n\n"));
432 ForeachNode(&unit
->roothub
.port_list
, port
) {
433 if(port
->number
== wIndex
) {
434 mybug_unit(0, ("Found port %d named %s\n", port
->number
, port
->name
));
436 struct UsbPortStatus
*usbportstatus
= (struct UsbPortStatus
*) ioreq
->iouh_Data
;
438 usbportstatus
->wPortStatus
= 0;
439 usbportstatus
->wPortChange
= 0;
441 mybug_unit(0, ("Done\n\n"));
442 return UHIOERR_NO_ERROR
;
446 mybug_unit(-1, ("Port not found!\n\n"));
449 } /* switch(bRequest) */
452 } /* case URTF_CLASS */
455 /* switch(bmRequestType) */
457 mybug_unit(0, ("URTF_VENDOR\n"));
460 } /* switch(bmRequestType) */
462 } else { /* if(bmRequestDirection) */
463 mybug_unit(0, ("Request direction is host to device\n"));
465 switch(bmRequestType
) {
467 mybug_unit(0, ("[VXHCI] cmdControlXFerRootHub: URTF_STANDARD\n"));
469 switch(bmRequestRecipient
) {
471 mybug_unit(0, ("[VXHCI] cmdControlXFerRootHub: URTF_DEVICE\n"));
474 case USR_SET_ADDRESS
:
475 mybug_unit(0, ("USR_SET_ADDRESS\n"));
476 unit
->roothub
.addr
= wValue
;
477 ioreq
->iouh_Actual
= wLength
;
478 mybug_unit(0, ("Done\n\n"));
479 return UHIOERR_NO_ERROR
;
482 case USR_SET_CONFIGURATION
:
483 /* We do not have alternative configuration */
484 mybug_unit(0, ("USR_SET_CONFIGURATION\n"));
485 ioreq
->iouh_Actual
= wLength
;
486 mybug_unit(0, ("Done\n\n"));
487 return UHIOERR_NO_ERROR
;
490 //case USR_SET_INTERFACE: //Undefined. Hubs are allowed to support only one interface.
492 } /* switch(bRequest) */
496 mybug_unit(0, ("URTF_INTERFACE\n"));
500 mybug_unit(0, ("URTF_ENDPOINT\n"));
504 mybug_unit(0, ("URTF_OTHER\n"));
507 } /* switch(bmRequestRecipient) */
511 mybug_unit(0, ("URTF_CLASS\n"));
512 switch(bmRequestRecipient
) {
514 mybug_unit(0, ("URTF_OTHER\n"));
517 case USR_SET_FEATURE
:
518 mybug_unit(0, ("USR_SET_FEATURE\n"));
522 mybug_unit(0, ("UFS_PORT_POWER\n"));
524 ForeachNode(&unit
->roothub
.port_list
, port
) {
525 if(port
->number
== wIndex
) {
526 mybug_unit(0, ("Found port %d named %s\n", port
->number
, port
->name
));
527 mybug_unit(0, ("Done\n\n"));
528 return UHIOERR_NO_ERROR
;
532 mybug_unit(-1, ("Port not found!\n\n"));
535 case UFS_PORT_CONNECTION
:
536 case UFS_PORT_ENABLE
:
537 case UFS_PORT_SUSPEND
:
538 case UFS_PORT_OVER_CURRENT
:
540 case UFS_PORT_LOW_SPEED
:
541 case UFS_C_PORT_CONNECTION
:
542 case UFS_C_PORT_ENABLE
:
543 case UFS_C_PORT_SUSPEND
:
544 case UFS_C_PORT_OVER_CURRENT
:
545 case UFS_C_PORT_RESET
:
547 } /* switch(wValue) */
549 } /* switch(bRequest) */
551 } /* switch(bmRequestRecipient) */
555 mybug_unit(0, ("URTF_VENDOR\n"));
558 } /* switch(bmRequestType) */
560 } /* if(bmRequestDirection) */
562 D( mybug_unit(-1, ("bmRequestDirection "));
563 switch (bmRequestDirection
) {
565 mybug(-1, ("URTF_IN\n"));
568 mybug(-1, ("URTF_OUT\n"));
572 mybug_unit(-1, ("bmRequestType "));
573 switch(bmRequestType
) {
575 mybug(-1, ("URTF_STANDARD\n"));
578 mybug(-1, ("URTF_CLASS\n"));
581 mybug(-1, ("URTF_VENDOR\n"));
585 mybug_unit(-1, ("bmRequestRecipient "));
586 switch (bmRequestRecipient
) {
588 mybug(-1, ("URTF_DEVICE\n"));
591 mybug(-1, ("URTF_INTERFACE\n"));
594 mybug(-1, ("URTF_ENDPOINT\n"));
597 mybug(-1, ("URTF_OTHER\n"));
601 mybug_unit(-1, ("bRequest "));
604 bug("USR_GET_STATUS\n");
606 case USR_CLEAR_FEATURE
:
607 mybug(-1, ("USR_CLEAR_FEATURE\n"));
609 case USR_SET_FEATURE
:
610 mybug(-1, ("USR_SET_FEATURE\n"));
612 case USR_SET_ADDRESS
:
613 mybug(-1, ("USR_SET_ADDRESS\n"));
615 case USR_GET_DESCRIPTOR
:
616 mybug(-1, ("USR_GET_DESCRIPTOR\n"));
618 case USR_SET_DESCRIPTOR
:
619 mybug(-1, ("USR_SET_DESCRIPTOR\n"));
621 case USR_GET_CONFIGURATION
:
622 mybug(-1, ("USR_GET_CONFIGURATION\n"););
624 case USR_SET_CONFIGURATION
:
625 mybug(-1, ("USR_SET_CONFIGURATION\n"));
627 case USR_GET_INTERFACE
:
628 mybug(-1, ("USR_GET_INTERFACE\n"));
630 case USR_SET_INTERFACE
:
631 mybug(-1, ("USR_SET_INTERFACE\n"));
633 case USR_SYNCH_FRAME
:
634 mybug(-1, ("USR_SYNCH_FRAME\n"));
638 mybug_unit(-1, ("wIndex %x\n", wIndex
));
639 mybug_unit(-1, ("wValue %x\n", wValue
));
640 mybug_unit(-1, ("wLength %d\n", wLength
));
642 mybug_unit(-1, ("Nothing done!\n\n")) );
643 return UHIOERR_BADPARAMS
;
646 WORD
cmdIntXFer(struct IOUsbHWReq
*ioreq
) {
647 mybug(-1, ("[VXHCI] cmdIntXFer: Entering function\n"));
649 struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
651 mybug_unit(-1, ("ioreq->iouh_DevAddr %lx\n", ioreq
->iouh_DevAddr
));
652 mybug_unit(-1, ("unit->roothub.addr %lx\n", unit
->roothub
.addr
));
655 Check the status of the controller
656 We might encounter these states:
657 UHSB_OPERATIONAL USB can be used for transfers
658 UHSB_RESUMING USB is currently resuming
659 UHSB_SUSPENDED USB is in suspended state
660 UHSB_RESET USB is just inside a reset phase
663 if(unit
->state
== UHSF_OPERATIONAL
) {
664 mybug_unit(0, ("Unit state is operational\n"));
666 mybug_unit(-1, ("Unit state is not operational!\n"));
667 return UHIOERR_USBOFFLINE
;
670 if(ioreq
->iouh_DevAddr
== unit
->roothub
.addr
) {
671 mybug_unit(-1, ("Entering cmdIntXFerRootHub\n"));
672 return(cmdIntXFerRootHub(ioreq
));
675 mybug_unit(-1, ("Nothing done!\n\n"));
679 WORD
cmdIntXFerRootHub(struct IOUsbHWReq
*ioreq
) {
680 mybug(-1, ("[VXHCI] cmdIntXFerRootHub: Entering function\n"));
681 D(struct VXHCIUnit
*unit
= (struct VXHCIUnit
*) ioreq
->iouh_Req
.io_Unit
);
683 mybug_unit(-1, ("Nothing done!\n\n"));
687 WORD
cmdGetString(struct IOUsbHWReq
*ioreq
, char *cstring
) {
688 mybug(0, ("[VXHCI] cmdGetString: Entering function\n"));
690 UWORD wLength
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
692 struct UsbStdStrDesc
*strdesc
= (struct UsbStdStrDesc
*) ioreq
->iouh_Data
;
693 strdesc
->bDescriptorType
= UDT_STRING
;
694 strdesc
->bLength
= (strlen(cstring
)*sizeof(strdesc
->bString
))+sizeof(strdesc
->bLength
) + sizeof(strdesc
->bDescriptorType
);
697 ioreq
->iouh_Actual
= 2;
698 while(ioreq
->iouh_Actual
<wLength
) {
699 strdesc
->bString
[(ioreq
->iouh_Actual
-2)/sizeof(strdesc
->bString
)] = AROS_WORD2LE(*cstring
);
700 ioreq
->iouh_Actual
+= sizeof(strdesc
->bString
);
703 mybug(0, ("[VXHCI] cmdGetString: Done\n\n"));
704 return UHIOERR_NO_ERROR
;
709 ioreq
->iouh_Actual
= wLength
;
710 mybug(0, ("[VXHCI] cmdGetString: Done\n\n"));
711 return UHIOERR_NO_ERROR
;
714 return UHIOERR_BADPARAMS
;