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