1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  USB device layer				File: usbd.c
5    *
6    *  This module deals with devices (things connected to USB buses)
7    *
8    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
9    *
10    *********************************************************************
11    *
12    *  Copyright 2000,2001,2002,2003
13    *  Broadcom Corporation. All rights reserved.
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accordance with the following terms and
17    *  conditions.  Subject to these conditions, you may download,
18    *  copy, install, use, modify and distribute modified or unmodified
19    *  copies of this software in source and/or binary form.  No title
20    *  or ownership is transferred hereby.
21    *
22    *  1) Any source code used, modified or distributed must reproduce
23    *     and retain this copyright notice and list of conditions
24    *     as they appear in the source file.
25    *
26    *  2) No right is granted to use any trade name, trademark, or
27    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
28    *     name may not be used to endorse or promote products derived
29    *     from this software without the prior written permission of
30    *     Broadcom Corporation.
31    *
32    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44    *     THE POSSIBILITY OF SUCH DAMAGE.
45    ********************************************************************* */
46
47
48#ifndef _CFE_
49#include <stdio.h>
50#include <time.h>
51#include <memory.h>
52#include <stdint.h>
53#include "usbhack.h"
54#else
55#include "lib_types.h"
56#include "lib_string.h"
57#include "lib_printf.h"
58#include "cfe_timer.h"
59#endif
60
61#include "lib_malloc.h"
62#include "lib_queue.h"
63#include "usbchap9.h"
64#include "usbd.h"
65
66/*  *********************************************************************
67    *  Globals
68    ********************************************************************* */
69
70int usb_noisy = 0;
71
72
73/*  *********************************************************************
74    *  usb_create_pipe(dev,epaddr,mps,flags)
75    *
76    *  Create a pipe, causing the corresponding endpoint to
77    *  be created in the host controller driver.  Pipes form the
78    *  basic "handle" for unidirectional communications with a
79    *  USB device.
80    *
81    *  Input parameters:
82    *  	   dev - device we're talking about
83    *  	   epaddr - endpoint address open, usually from the endpoint
84    *  	             descriptor
85    *  	   mps - maximum packet size understood by the device
86    *  	   flags - flags for this pipe (UP_xxx flags)
87    *
88    *  Return value:
89    *  	   <0 if error
90    *  	   0 if ok
91    ********************************************************************* */
92
93int usb_create_pipe(usbdev_t *dev,int epaddr,int mps,int flags)
94{
95    usbpipe_t *pipe;
96    int pipeidx;
97
98    pipeidx = USB_EPADDR_TO_IDX(epaddr);
99
100    if (dev->ud_pipes[pipeidx] != NULL) {
101	printf("Trying to create a pipe that was already created!\n");
102	return 0;
103	}
104
105    pipe = KMALLOC(sizeof(usbpipe_t),0);
106
107    if (!pipe) return -1;
108
109    pipe->up_flags = flags;
110    pipe->up_num = pipeidx;
111    pipe->up_mps = mps;
112    pipe->up_dev = dev;
113    if (dev->ud_flags & UD_FLAG_LOWSPEED) flags |= UP_TYPE_LOWSPEED;
114    pipe->up_hwendpoint = UBEPTCREATE(dev->ud_bus,
115				      dev->ud_address,
116				      USB_ENDPOINT_ADDRESS(epaddr),
117				      mps,
118				      flags);
119
120    dev->ud_pipes[pipeidx] = pipe;
121
122    return 0;
123}
124
125/*  *********************************************************************
126    *  usb_open_pipe(dev,epdesc)
127    *
128    *  Open a pipe given an endpoint descriptor - this is the
129    *  normal way pipes get open, since you've just selected a
130    *  configuration and have the descriptors handy with all
131    *  the information you need.
132    *
133    *  Input parameters:
134    *  	   dev - device we're talking to
135    *  	   epdesc - endpoint descriptor
136    *
137    *  Return value:
138    *  	   <0 if error
139    *  	   else endpoint/pipe number (from descriptor)
140    ********************************************************************* */
141
142int usb_open_pipe(usbdev_t *dev,usb_endpoint_descr_t *epdesc)
143{
144    int res;
145    int flags = 0;
146
147    if (USB_ENDPOINT_DIR_IN(epdesc->bEndpointAddress)) flags |= UP_TYPE_IN;
148    else flags |= UP_TYPE_OUT;
149
150    switch (epdesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) {
151	case USB_ENDPOINT_TYPE_CONTROL:
152	    flags |= UP_TYPE_CONTROL;
153	    break;
154	case USB_ENDPOINT_TYPE_ISOCHRONOUS:
155	    flags |= UP_TYPE_ISOC;
156	    break;
157	case USB_ENDPOINT_TYPE_BULK:
158	    flags |= UP_TYPE_BULK;
159	    break;
160	case USB_ENDPOINT_TYPE_INTERRUPT:
161	    flags |= UP_TYPE_INTR;
162	    break;
163	}
164
165    res = usb_create_pipe(dev,
166			  epdesc->bEndpointAddress,
167			  GETUSBFIELD(epdesc,wMaxPacketSize),
168			  flags);
169
170    if (res < 0) return res;
171
172    return epdesc->bEndpointAddress;
173}
174
175
176/*  *********************************************************************
177    *  usb_destroy_pipe(dev,epaddr)
178    *
179    *  Close(destroy) an open pipe and remove endpoint descriptor
180    *
181    *  Input parameters:
182    *  	   dev - device we're talking to
183    *  	   epaddr - pipe to close
184    *
185    *  Return value:
186    *  	   nothing
187    ********************************************************************* */
188
189void usb_destroy_pipe(usbdev_t *dev,int epaddr)
190{
191    usbpipe_t *pipe;
192    int pipeidx;
193
194    pipeidx = USB_EPADDR_TO_IDX(epaddr);
195
196    pipe = dev->ud_pipes[pipeidx];
197    if (!pipe) return;
198
199    if (dev->ud_pipes[pipeidx]) {
200	UBEPTDELETE(dev->ud_bus,
201		    dev->ud_pipes[pipeidx]->up_hwendpoint);
202	}
203
204    KFREE(dev->ud_pipes[pipeidx]);
205    dev->ud_pipes[pipeidx] = NULL;
206}
207
208/*  *********************************************************************
209    *  usb_destroy_device(dev)
210    *
211    *  Delete an entire USB device, closing its pipes and freeing
212    *  the device data structure
213    *
214    *  Input parameters:
215    *  	   dev - device to destroy
216    *
217    *  Return value:
218    *  	   nothing
219    ********************************************************************* */
220
221void usb_destroy_device(usbdev_t *dev)
222{
223    int idx;
224
225    for (idx = 0; idx < UD_MAX_PIPES; idx++) {
226	if (dev->ud_pipes[idx]) {
227	    UBEPTDELETE(dev->ud_bus,
228			dev->ud_pipes[idx]->up_hwendpoint);
229	    KFREE(dev->ud_pipes[idx]);
230	    }
231	}
232
233    dev->ud_bus->ub_devices[dev->ud_address] = NULL;
234
235    KFREE(dev);
236}
237
238
239/*  *********************************************************************
240    *  usb_create_device(bus,lowspeed)
241    *
242    *  Create a new USB device.  This device will be set to
243    *  communicate on address zero (default address) and will be
244    *  ready for basic stuff so we can figure out what it is.
245    *  The control pipe will be open, so you can start requesting
246    *  descriptors right away.
247    *
248    *  Input parameters:
249    *  	   bus - bus to create device on
250    *  	   lowspeed - true if it's a lowspeed device (the hubs tell
251    *  	     us these things)
252    *
253    *  Return value:
254    *  	   usb device structure, or NULL
255    ********************************************************************* */
256
257usbdev_t *usb_create_device(usbbus_t *bus,int lowspeed)
258{
259    usbdev_t *dev;
260    int pipeflags;
261
262    /*
263     * Create the device structure.
264     */
265
266    dev = KMALLOC(sizeof(usbdev_t),0);
267    memset(dev,0,sizeof(usbdev_t));
268
269    dev->ud_bus = bus;
270    dev->ud_address = 0;		/* default address */
271    dev->ud_parent = NULL;
272    dev->ud_flags = 0;
273
274    /*
275     * Adjust things based on the target device speed
276     */
277
278    pipeflags = UP_TYPE_CONTROL;
279    if (lowspeed) {
280	pipeflags |= UP_TYPE_LOWSPEED;
281	dev->ud_flags |= UD_FLAG_LOWSPEED;
282	}
283
284    /*
285     * Create the control pipe.
286     */
287
288    usb_create_pipe(dev,0,
289		    USB_CONTROL_ENDPOINT_MIN_SIZE,
290		    pipeflags);
291
292    return dev;
293}
294
295/*  *********************************************************************
296    *  usb_make_request(dev,epaddr,buf,len,flags)
297    *
298    *  Create a template request structure with basic fields
299    *  ready to go.  A shorthand routine.
300    *
301    *  Input parameters:
302    *  	   dev- device we're talking to
303    *  	   epaddr - endpoint address, from usb_open_pipe()
304    *  	   buf,length - user buffer and buffer length
305    *  	   flags - transfer direction, etc. (UR_xxx flags)
306    *
307    *  Return value:
308    *  	   usbreq_t pointer, or NULL
309    ********************************************************************* */
310
311usbreq_t *usb_make_request(usbdev_t *dev,int epaddr,uint8_t *buf,int length,int flags)
312{
313    usbreq_t *ur;
314    usbpipe_t *pipe;
315    int pipeidx;
316
317    pipeidx = USB_EPADDR_TO_IDX(epaddr);
318
319    pipe = dev->ud_pipes[pipeidx];
320
321    if (pipe == NULL) return NULL;
322
323    ur = KMALLOC(sizeof(usbreq_t),0);
324    memset(ur,0,sizeof(usbreq_t));
325
326    ur->ur_dev = dev;
327    ur->ur_pipe = pipe;
328    ur->ur_buffer = buf;
329    ur->ur_length = length;
330    ur->ur_flags = flags;
331    ur->ur_callback = NULL;
332
333    return ur;
334
335}
336
337/*  *********************************************************************
338    *  usb_poll(bus)
339    *
340    *  Handle device-driver polling - simply vectors to host controller
341    *  driver.
342    *
343    *  Input parameters:
344    *  	   bus - bus structure
345    *
346    *  Return value:
347    *  	   nothing
348    ********************************************************************* */
349
350void usb_poll(usbbus_t *bus)
351{
352    UBINTR(bus);
353}
354
355/*  *********************************************************************
356    *  usb_daemon(bus)
357    *
358    *  Polls for topology changes and initiates a bus scan if
359    *  necessary.
360    *
361    *  Input parameters:
362    *  	   bus - bus to  watch
363    *
364    *  Return value:
365    *  	   nothing
366    ********************************************************************* */
367
368void usb_daemon(usbbus_t *bus)
369{
370    /*
371     * Just see if someone flagged a need for a scan here
372     * and start the bus scan if necessary.
373     *
374     * The actual scanning is a hub function, starting at the
375     * root hub, so the code for that is over there.
376     */
377
378    if (bus->ub_flags & UB_FLG_NEEDSCAN) {
379	bus->ub_flags &= ~UB_FLG_NEEDSCAN;
380	usb_scan(bus);
381	}
382}
383
384/*  *********************************************************************
385    *  usb_cancel_request(ur)
386    *
387    *  Cancel a pending usb transfer request.
388    *
389    *  Input parameters:
390    *  	   ur - request to cancel
391    *
392    *  Return value:
393    *  	   0 if ok
394    *  	   else error (could not find request)
395    ********************************************************************* */
396
397int usb_cancel_request(usbreq_t *ur)
398{
399    printf("usb_cancel_request is not implemented.\n");
400    return 0;
401}
402
403/*  *********************************************************************
404    *  usb_free_request(ur)
405    *
406    *  Return a transfer request to the free pool.
407    *
408    *  Input parameters:
409    *  	   ur - request to return
410    *
411    *  Return value:
412    *  	   nothing
413    ********************************************************************* */
414
415void usb_free_request(usbreq_t *ur)
416{
417    if (ur->ur_inprogress) {
418	printf("Yow!  Tried to free a request that was in progress!\n");
419	return;
420	}
421    KFREE(ur);
422}
423
424/*  *********************************************************************
425    *  usb_delay_ms(bus,ms)
426    *
427    *  Wait a while, calling the polling routine as we go.
428    *
429    *  Input parameters:
430    *  	   bus - bus we're talking to
431    *  	   ms - how long to wait
432    *
433    *  Return value:
434    *  	   nothing
435    ********************************************************************* */
436
437
438void usb_delay_ms(usbbus_t *bus,int ms)
439{
440#ifdef _CFE_
441    cfe_sleep(1+((ms*CFE_HZ)/1000));
442#else
443    mydelay(ms);
444#endif
445}
446
447/*  *********************************************************************
448    *  usb_queue_request(ur)
449    *
450    *  Call the transfer handler in the host controller driver to
451    *  set up a transfer descriptor
452    *
453    *  Input parameters:
454    *  	   ur - request to queue
455    *
456    *  Return value:
457    *  	   0 if ok
458    *  	   else error
459    ********************************************************************* */
460
461int usb_queue_request(usbreq_t *ur)
462{
463    int res;
464
465    ur->ur_inprogress = 1;
466    ur->ur_xferred = 0;
467    res = UBXFER(ur->ur_dev->ud_bus,
468		 ur->ur_pipe->up_hwendpoint,
469		 ur);
470    return res;
471}
472
473/*  *********************************************************************
474    *  usb_wait_request(ur)
475    *
476    *  Wait until a request completes, calling the polling routine
477    *  as we wait.
478    *
479    *  Input parameters:
480    *  	   ur - request to wait for
481    *
482    *  Return value:
483    *  	   request status
484    ********************************************************************* */
485
486int usb_wait_request(usbreq_t *ur)
487{
488    while ((volatile int) (ur->ur_inprogress)) {
489	usb_poll(ur->ur_dev->ud_bus);
490	}
491
492    return ur->ur_status;
493}
494
495/*  *********************************************************************
496    *  usb_sync_request(ur)
497    *
498    *  Synchronous request - call usb_queue and then usb_wait
499    *
500    *  Input parameters:
501    *  	   ur - request to submit
502    *
503    *  Return value:
504    *  	   status of request
505    ********************************************************************* */
506
507int usb_sync_request(usbreq_t *ur)
508{
509    usb_queue_request(ur);
510    return usb_wait_request(ur);
511}
512
513/*  *********************************************************************
514    *  usb_simple_request(dev,reqtype,bRequest,wValue,wIndex)
515    *
516    *  Handle a simple USB control pipe request.  These are OUT
517    *  requests with no data phase.
518    *
519    *  Input parameters:
520    *  	   dev - device we're talking to
521    *  	   reqtype - request type (bmRequestType) for descriptor
522    *  	   wValue - wValue for descriptor
523    *  	   wIndex - wIndex for descriptor
524    *
525    *  Return value:
526    *  	   0 if ok
527    *  	   else error
528    ********************************************************************* */
529
530int usb_simple_request(usbdev_t *dev,uint8_t reqtype,int bRequest,int wValue,int wIndex)
531{
532    return usb_std_request(dev,reqtype,bRequest,wValue,wIndex,NULL,0);
533
534}
535
536
537/*  *********************************************************************
538    *  usb_set_configuration(dev,config)
539    *
540    *  Set the current configuration for a USB device.
541    *
542    *  Input parameters:
543    *  	   dev - device we're talking to
544    *  	   config - bConfigValue for the device
545    *
546    *  Return value:
547    *  	   request status
548    ********************************************************************* */
549
550int usb_set_configuration(usbdev_t *dev,int config)
551{
552    int res;
553
554    res = usb_simple_request(dev,0x00,USB_REQUEST_SET_CONFIGURATION,config,0);
555
556    return res;
557}
558
559
560/*  *********************************************************************
561    *  usb_new_address(bus)
562    *
563    *  Return the next available address for the specified bus
564    *
565    *  Input parameters:
566    *  	   bus - bus to assign an address for
567    *
568    *  Return value:
569    *  	   new address, <0 if error
570    ********************************************************************* */
571
572int usb_new_address(usbbus_t *bus)
573{
574    int idx;
575
576    for (idx = 1; idx < USB_MAX_DEVICES; idx++) {
577	if (bus->ub_devices[idx] == NULL) return idx;
578	}
579
580    return -1;
581}
582
583/*  *********************************************************************
584    *  usb_set_address(dev,address)
585    *
586    *  Set the address of a device.  This also puts the device
587    *  in the master device table for the bus and reconfigures the
588    *  address of the control pipe.
589    *
590    *  Input parameters:
591    *  	   dev - device we're talking to
592    *  	   address - new address (1..127)
593    *
594    *  Return value:
595    *  	   request status
596    ********************************************************************* */
597
598int usb_set_address(usbdev_t *dev,int address)
599{
600    int res;
601    int idx;
602    usbpipe_t *pipe;
603
604    res = usb_simple_request(dev,0x00,USB_REQUEST_SET_ADDRESS,address,0);
605
606    if (res == 0) {
607	dev->ud_bus->ub_devices[address] = dev;
608	dev->ud_address = address;
609	for (idx = 0; idx < UD_MAX_PIPES; idx++) {
610	    pipe = dev->ud_pipes[idx];
611	    if (pipe && pipe->up_hwendpoint) {
612		UBEPTSETADDR(dev->ud_bus,pipe->up_hwendpoint,address);
613		}
614	    }
615	}
616
617    return res;
618}
619
620/*  *********************************************************************
621    *  usb_set_ep0mps(dev,mps)
622    *
623    *  Set the maximum packet size of endpoint zero (mucks with the
624    *  endpoint in the host controller)
625    *
626    *  Input parameters:
627    *  	   dev - device we're talking to
628    *  	   mps - max packet size for endpoint zero
629    *
630    *  Return value:
631    *  	   request status
632    ********************************************************************* */
633
634int usb_set_ep0mps(usbdev_t *dev,int mps)
635{
636    usbpipe_t *pipe;
637
638    pipe = dev->ud_pipes[0];
639    if (pipe && pipe->up_hwendpoint) {
640	UBEPTSETMPS(dev->ud_bus,pipe->up_hwendpoint,mps);
641	}
642    if (pipe) {
643	pipe->up_mps = mps;
644	}
645
646    return 0;
647}
648
649/*  *********************************************************************
650    *  usb_clear_stall(dev,epaddr)
651    *
652    *  Clear a stall condition on the specified pipe
653    *
654    *  Input parameters:
655    *  	   dev - device we're talking to
656    *  	   epaddr - endpoint address
657    *
658    *  Return value:
659    *  	   0 if ok
660    *  	   else error
661    ********************************************************************* */
662int usb_clear_stall(usbdev_t *dev,int epaddr)
663{
664    uint8_t *requestbuf;
665    usb_device_request_t *req;
666    usbreq_t *ur;
667    int res;
668    int pipeidx;
669
670    /*
671     * Clear the stall in the hardware.
672     */
673
674    pipeidx = USB_EPADDR_TO_IDX(epaddr);
675
676    UBEPTCLEARTOGGLE(dev->ud_bus,dev->ud_pipes[pipeidx]->up_hwendpoint);
677
678    /*
679     * Do the "clear stall" request.   Note that we should do this
680     * without calling usb_simple_request, since usb_simple_request
681     * may itself stall.
682     */
683
684    requestbuf = KMALLOC(32,0);
685
686    req = (usb_device_request_t *) requestbuf;
687
688    req->bmRequestType = 0x02;
689    req->bRequest = USB_REQUEST_CLEAR_FEATURE;
690    PUTUSBFIELD(req,wValue,0);		/* ENDPOINT_HALT */
691    PUTUSBFIELD(req,wIndex,epaddr);
692    PUTUSBFIELD(req,wLength,0);
693
694    ur = usb_make_request(dev,0,requestbuf,
695			  sizeof(usb_device_request_t),
696			  UR_FLAG_SETUP);
697    res = usb_sync_request(ur);
698    usb_free_request(ur);
699    ur = usb_make_request(dev,0,requestbuf,0,UR_FLAG_STATUS_IN);
700    res = usb_sync_request(ur);
701    usb_free_request(ur);
702
703    KFREE(requestbuf);
704
705    return 0;
706}
707
708
709
710/*  *********************************************************************
711    *  usb_std_request(dev,bmRequestType,bRequest,wValue,
712    *                   wIndex,buffer,length)
713    *
714    *  Do a standard control request on the control pipe,
715    *  with the appropriate setup, data, and status phases.
716    *
717    *  Input parameters:
718    *  	   dev - dev we're talking to
719    *  	   bmRequestType,bRequest,wValue,wIndex - fields for the
720    *  	            USB request structure
721    *  	   buffer - user buffer
722    *  	   length - length of user buffer
723    *
724    *  Return value:
725    *  	   number of bytes transferred
726    ********************************************************************* */
727
728int usb_std_request(usbdev_t *dev,uint8_t bmRequestType,
729			   uint8_t bRequest,uint16_t wValue,
730			   uint16_t wIndex,uint8_t *buffer,int length)
731{
732    usbpipe_t *pipe = dev->ud_pipes[0];
733    usbreq_t *ur;
734    int res;
735    usb_device_request_t *req;
736    uint8_t *databuf = NULL;
737
738    req = KMALLOC(32,0);
739
740    if ((buffer != NULL) && (length !=0)) {
741	databuf = KMALLOC(length,0);
742	if (!(bmRequestType & USBREQ_DIR_IN)) {
743	    memcpy(databuf,buffer,length);
744	    }
745	else {
746	    memset(databuf,0,length);
747	    }
748	}
749
750    req->bmRequestType = bmRequestType;
751    req->bRequest = bRequest;
752    PUTUSBFIELD(req,wValue,wValue);
753    PUTUSBFIELD(req,wIndex,wIndex);
754    PUTUSBFIELD(req,wLength,length);
755
756    ur = usb_make_request(dev,0,(uint8_t *)req,sizeof(usb_device_request_t),UR_FLAG_SETUP);
757    res = usb_sync_request(ur);
758    usb_free_request(ur);
759
760    if (length != 0) {
761	if (bmRequestType & USBREQ_DIR_IN) {
762	    ur = usb_make_request(dev,0,databuf,length,UR_FLAG_IN);
763	    }
764	else {
765	    ur = usb_make_request(dev,0,databuf,length,UR_FLAG_OUT);
766	    }
767
768	res = usb_sync_request(ur);
769
770	if (res == 4) {		/* STALL */
771	    usb_clear_stall(dev,pipe->up_num);
772	    usb_free_request(ur);
773	    if (databuf) KFREE(databuf);
774	    KFREE(req);
775	    return 0;
776	    }
777
778	length = ur->ur_xferred;
779	usb_free_request(ur);
780	}
781
782    if ((length != 0) && (databuf != NULL) && (bmRequestType & USBREQ_DIR_IN)) {
783	memcpy(buffer,databuf,length);
784	}
785
786    if (bmRequestType & USBREQ_DIR_IN) {
787	ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_OUT);
788	}
789    else {
790	ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_IN);
791	}
792
793    res = usb_sync_request(ur);
794    usb_free_request(ur);
795
796    if (res == 4) {		/* STALL */
797	usb_clear_stall(dev,pipe->up_num);
798	if (databuf) KFREE(databuf);
799	KFREE(req);
800	return 0;
801	}
802
803    if (databuf) KFREE(databuf);
804    KFREE(req);
805
806    return length;
807}
808
809
810
811
812/*  *********************************************************************
813    *  usb_get_descriptor(dev,reqtype,dsctype,dscidx,respbuf,buflen)
814    *
815    *  Request a descriptor from the device.
816    *
817    *  Input parameters:
818    *  	   dev - device we're talking to
819    *  	   reqtype - bmRequestType field for descriptor we want
820    *  	   dsctype - descriptor type we want
821    *  	   dscidx - index of descriptor we want (often zero)
822    *  	   respbuf - response buffer
823    *  	   buflen - length of response buffer
824    *
825    *  Return value:
826    *  	   number of bytes transferred
827    ********************************************************************* */
828
829int usb_get_descriptor(usbdev_t *dev,uint8_t reqtype,int dsctype,int dscidx,
830		       uint8_t *respbuf,int buflen)
831{
832    return usb_std_request(dev,
833			   reqtype,USB_REQUEST_GET_DESCRIPTOR,
834			   USB_DESCRIPTOR_TYPEINDEX(dsctype,dscidx),
835			   0,
836			   respbuf,buflen);
837}
838
839/*  *********************************************************************
840    *  usb_get_string(dev,id,buf,maxlen)
841    *
842    *  Request a string from the device, converting it from
843    *  unicode to ascii (brutally).
844    *
845    *  Input parameters:
846    *  	   dev - device we're talking to
847    *  	   id - string ID
848    *  	   buf - buffer to receive string (null terminated)
849    *  	   maxlen - length of buffer
850    *
851    *  Return value:
852    *  	   number of characters in returned string
853    ********************************************************************* */
854
855int usb_get_string(usbdev_t *dev,int id,char *buf,int maxlen)
856{
857    int amtcopy;
858    uint8_t *respbuf;
859    int idx;
860    usb_string_descr_t *sdscr;
861
862    respbuf = KMALLOC(maxlen*2+2,0);
863    sdscr = (usb_string_descr_t *) respbuf;
864
865    /*
866     * First time just get the header of the descriptor so we can
867     * get the string length
868     */
869
870    amtcopy = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_STRING_DESCRIPTOR_TYPE,id,
871				 respbuf,2);
872
873    /*
874     * now do it again to get the whole string.
875     */
876
877    if (maxlen > sdscr->bLength) maxlen = sdscr->bLength;
878
879    amtcopy = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_STRING_DESCRIPTOR_TYPE,id,
880				 respbuf,maxlen);
881
882    *buf = '\0';
883    amtcopy = sdscr->bLength - 2;
884    if (amtcopy <= 0) return amtcopy;
885
886    for (idx = 0; idx < amtcopy; idx+=2) {
887	*buf++ = sdscr->bString[idx];
888	}
889
890    *buf = '\0';
891
892    KFREE(respbuf);
893
894    return amtcopy;
895}
896
897
898
899/*  *********************************************************************
900    *  usb_get_device_descriptor(dev,dscr,smallflg)
901    *
902    *  Request the device descriptor for the device. This is often
903    *  the first descriptor requested, so it needs to be done in
904    *  stages so we can find out how big the control pipe is.
905    *
906    *  Input parameters:
907    *  	   dev - device we're talking to
908    *  	   dscr - pointer to buffer to receive descriptor
909    *  	   smallflg - TRUE to request just 8 bytes.
910    *
911    *  Return value:
912    *  	   number of bytes copied
913    ********************************************************************* */
914
915int usb_get_device_descriptor(usbdev_t *dev,usb_device_descr_t *dscr,int smallflg)
916{
917    int res;
918    uint8_t *respbuf;
919    int amtcopy;
920
921    /*
922     * Smallflg truncates the request 8 bytes.  We need to do this for
923     * the very first transaction to a USB device in order to determine
924     * the size of its control pipe.  Bad things will happen if you
925     * try to retrieve more data than the control pipe will hold.
926     *
927     * So, be conservative at first and get the first 8 bytes of the
928     * descriptor.   Byte 7 is bMaxPacketSize0, the size of the control
929     * pipe.  Then you can go back and submit a bigger request for
930     * everything else.
931     */
932
933    amtcopy = smallflg ? USB_CONTROL_ENDPOINT_MIN_SIZE : sizeof(usb_device_descr_t);
934
935    respbuf = KMALLOC(64,0);
936    res = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_DEVICE_DESCRIPTOR_TYPE,0,respbuf,amtcopy);
937    memcpy(dscr,respbuf,amtcopy);
938    KFREE(respbuf);
939    return res;
940
941}
942
943/*  *********************************************************************
944    *  usb_get_config_descriptor(dev,dscr,idx,maxlen)
945    *
946    *  Request the configuration descriptor from the device.
947    *
948    *  Input parameters:
949    *  	   dev - device we're talking to
950    *  	   dscr - descriptor buffer (receives data from device)
951    *  	   idx - index of config we want (usually zero)
952    *  	   maxlen - total size of buffer to receive descriptor
953    *
954    *  Return value:
955    *  	   number of bytes copied
956    ********************************************************************* */
957
958int usb_get_config_descriptor(usbdev_t *dev,usb_config_descr_t *dscr,int idx,int maxlen)
959{
960    int res;
961    uint8_t *respbuf;
962
963    respbuf = KMALLOC(maxlen,0);
964    res = usb_get_descriptor(dev,USBREQ_DIR_IN,
965			     USB_CONFIGURATION_DESCRIPTOR_TYPE,idx,
966			     respbuf,maxlen);
967    memcpy(dscr,respbuf,maxlen);
968    KFREE(respbuf);
969    return res;
970
971}
972
973
974
975/*  *********************************************************************
976    *  usb_get_device_status(dev,status)
977    *
978    *  Request status from the device (status descriptor)
979    *
980    *  Input parameters:
981    *  	   dev - device we're talking to
982    *  	   status - receives device_status structure
983    *
984    *  Return value:
985    *  	   number of bytes returned
986    ********************************************************************* */
987
988int usb_get_device_status(usbdev_t *dev,usb_device_status_t *status)
989{
990    return usb_std_request(dev,
991			   USBREQ_DIR_IN,
992			   0,
993			   0,
994			   0,
995			   (uint8_t *) status,
996			   sizeof(usb_device_status_t));
997}
998
999
1000/*  *********************************************************************
1001    *  usb_complete_request(ur,status)
1002    *
1003    *  Called when a usb request completes - pass status to
1004    *  caller and call the callback if there is one.
1005    *
1006    *  Input parameters:
1007    *  	   ur - usbreq_t to complete
1008    *  	   status - completion status
1009    *
1010    *  Return value:
1011    *  	   nothing
1012    ********************************************************************* */
1013
1014void usb_complete_request(usbreq_t *ur,int status)
1015{
1016    ur->ur_status = status;
1017    ur->ur_inprogress = 0;
1018    if (ur->ur_callback) (*(ur->ur_callback))(ur);
1019}
1020
1021
1022/*  *********************************************************************
1023    *  usb_initroot(bus)
1024    *
1025    *  Initialize the root hub for the bus - we need to do this
1026    *  each time a bus is configured.
1027    *
1028    *  Input parameters:
1029    *  	   bus - bus to initialize
1030    *
1031    *  Return value:
1032    *  	   nothing
1033    ********************************************************************* */
1034
1035void usb_initroot(usbbus_t *bus)
1036{
1037    usbdev_t *dev;
1038    usb_driver_t *drv;
1039    int addr;
1040    int res;
1041    uint8_t *buf;
1042    int len;
1043    usb_config_descr_t cfgdescr;
1044
1045    /*
1046     * Create a device for the root hub.
1047     */
1048
1049    dev = usb_create_device(bus,0);
1050    bus->ub_roothub = dev;
1051
1052    /*
1053     * Get the device descriptor.  Make sure it's a hub.
1054     */
1055
1056    res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),TRUE);
1057
1058    if (dev->ud_devdescr.bDeviceClass != USB_DEVICE_CLASS_HUB) {
1059	printf("Error! Root device is not a hub!\n");
1060	return;
1061	}
1062
1063    /*
1064     * Set up the max packet size for the control endpoint,
1065     * then get the rest of the descriptor.
1066     */
1067
1068    usb_set_ep0mps(dev,dev->ud_devdescr.bMaxPacketSize0);
1069    res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),FALSE);
1070
1071    /*
1072     * Obtain a new address and set the address of the
1073     * root hub to this address.
1074     */
1075
1076    addr = usb_new_address(dev->ud_bus);
1077    res = usb_set_address(dev,addr);
1078
1079    /*
1080     * Get the configuration descriptor and all the
1081     * associated interface and endpoint descriptors.
1082     */
1083
1084    res = usb_get_config_descriptor(dev,&cfgdescr,0,
1085				    sizeof(usb_config_descr_t));
1086    if (res != sizeof(usb_config_descr_t)) {
1087	printf("[a]usb_get_config_descriptor returns %d\n",res);
1088	}
1089
1090    len = GETUSBFIELD(&cfgdescr,wTotalLength);
1091    buf = KMALLOC(len,0);
1092
1093    res = usb_get_config_descriptor(dev,(usb_config_descr_t *)buf,0,len);
1094    if (res != len) {
1095	printf("[b]usb_get_config_descriptor returns %d\n",res);
1096	}
1097
1098    dev->ud_cfgdescr = (usb_config_descr_t *) buf;
1099
1100    /*
1101     * Select the configuration.  Not really needed for our poor
1102     * imitation root hub, but it's the right thing to do.
1103     */
1104
1105    usb_set_configuration(dev,cfgdescr.bConfigurationValue);
1106
1107    /*
1108     * Find the driver for this.  It had better be the hub
1109     * driver.
1110     */
1111
1112    drv = usb_find_driver(dev);
1113
1114    /*
1115     * Call the attach method.
1116     */
1117
1118    (*(drv->udrv_attach))(dev,drv);
1119
1120    /*
1121     * Hub should now be operational.
1122     */
1123
1124}
1125
1126
1127/*  *********************************************************************
1128    *  usb_find_cfg_descr(dev,dtype,idx)
1129    *
1130    *  Find a configuration descriptor - we retrieved all the config
1131    *  descriptors during discovery, this lets us dig out the one
1132    *  we want.
1133    *
1134    *  Input parameters:
1135    *  	   dev - device we are talking to
1136    *  	   dtype - descriptor type to find
1137    *  	   idx - index of descriptor if there's more than one
1138    *
1139    *  Return value:
1140    *  	   pointer to descriptor or NULL if not found
1141    ********************************************************************* */
1142
1143void *usb_find_cfg_descr(usbdev_t *dev,int dtype,int idx)
1144{
1145    uint8_t *endptr;
1146    uint8_t *ptr;
1147    usb_config_descr_t  *cfgdscr;
1148
1149    if (dev->ud_cfgdescr == NULL) return NULL;
1150
1151    ptr = (uint8_t *) dev->ud_cfgdescr;
1152    endptr = ptr + GETUSBFIELD((dev->ud_cfgdescr),wTotalLength);
1153
1154    while (ptr < endptr) {
1155
1156	cfgdscr = (usb_config_descr_t *) ptr;
1157
1158	if (cfgdscr->bDescriptorType == dtype) {
1159	    if (idx == 0) return (void *) ptr;
1160	    else idx--;
1161	    }
1162
1163	ptr += cfgdscr->bLength;
1164
1165	}
1166
1167    return NULL;
1168}
1169