1 /*
2 *******************************************************************************
3 *                                              usb host module                                           *
4 *                                                                                                                                          *
5 *                             Copyright(C), 2006-2008, SoftWinners Co., Ltd.                       *
6 *                               All Rights Reserved
7 *
8 * File Name :
9 *
10 * Author : GLHuang(HoLiGun)
11 *
12 * Version : 1.0
13 *
14 * Date : 2008.07.xx
15 *
16 * Description :
17 *       usb request block的相关操作,包括分配/释放,发送/撤回
18 * History :
19 *******************************************************************************
20 */
21 
22 #include <string.h>
23 
24 //#include "usb_host_config.h"
25 #include <usb_os_platform.h>
26 #include <usb_host_common.h>
27 //#include "usb_host_base_types.h"
28 #include <usb_list.h>
29 
30 #include "usb_gen_hcd.h"
31 
32 #include <hal_osal.h>
33 
34 static u32 urb_sn_now = 0;  //
35 
36 void usb_kill_urb(struct urb *urb);
37 
38 
39 
40 
41 //用来打印msc_info结构
_debug_print_urb(struct urb * urb_input)42 void _debug_print_urb(struct urb *urb_input)
43 {
44     //__inf(" = %x",urb_input-> );
45     __inf("==print_urb=========================");
46     __inf("urb addr         = %x", urb_input);
47     __inf("lock_urb         = %x", urb_input->lock_urb);
48     __inf("wait_urb_timer   = %x", urb_input->wait_urb_timer);
49     __inf("hcpriv           = %x", urb_input->hcpriv);
50     __inf("bandwidth        = %x", urb_input->bandwidth);
51     __inf("use_count        = %x", urb_input->use_count);
52     __inf("reject           = %x", urb_input->reject);
53     __inf("dev              = %x", urb_input->dev);
54     __inf("pipe             = %x", urb_input->pipe);
55     __inf("status           = %x", urb_input->status);
56     __inf("transfer_flags   = %x", urb_input->transfer_flags);
57     __inf("transfer_buffer  = %x", urb_input->transfer_buffer);
58     __inf("transfer_dma     = %x", urb_input->transfer_dma);
59     __inf("transfer_buffer_length = %x", urb_input->transfer_buffer_length);
60     __inf("actual_length    = %x", urb_input->actual_length);
61     __inf("setup_packet     = %x", urb_input->setup_packet);
62     __inf("setup_dma        = %x", urb_input->setup_dma);
63     __inf("start_frame      = %x", urb_input->start_frame);
64     __inf("number_of_packets = %x", urb_input->number_of_packets);
65     __inf("interval         = %x", urb_input->interval);
66     __inf("error_count      = %x", urb_input->error_count);
67     __inf("context          = %x", urb_input->context);
68     __inf("complete         = %x", urb_input->complete);
69     // __inf("wrapper_urb      = %x", urb_input->wrapper_urb);
70     __inf("===========================");
71 }
72 
73 /*
74 ***********************************************************
75 *
76 * Description   :
77 *               初始化urb
78 * Arguments  :
79 *   @urb        :
80 * Returns       :
81 *               无
82 * Notes         :
83 *
84 ***********************************************************
85 */
usb_init_urb(struct urb * urb)86 void usb_init_urb(struct urb *urb)
87 {
88     if (urb == NULL)
89     {
90         hal_log_err("ERR: urb is NULL");
91         return;
92     }
93 
94     memset(urb, 0, sizeof(struct urb));
95 }
96 
97 /*
98 ***********************************************************
99 *
100 * Description   :
101 *               分配urb,并初始化urb
102 * Arguments  :
103 *   @urb        :
104 * Returns       :
105 *
106 * Notes         :
107 *
108 ***********************************************************
109 */
usb_alloc_urb(int iso_packets)110 struct urb *usb_alloc_urb(int iso_packets)
111 {
112     struct urb *urb;
113     urb = (struct urb *)hal_malloc(sizeof(struct urb) + iso_packets * sizeof(struct usb_iso_packet_descriptor));
114 
115     if (!urb)
116     {
117         hal_log_err("alloc_urb: kmalloc failed");
118         return NULL;
119     }
120 
121     usb_init_urb(urb);
122     return urb;
123 }
124 
125 /*
126 ***********************************************************
127 *
128 * Description   :
129 *               释放urb
130 * Arguments  :
131 *   @urb        :
132 * Returns       :
133 *
134 * Notes         :
135 *
136 ***********************************************************
137 */
usb_free_urb(struct urb * urb)138 void usb_free_urb(struct urb *urb)
139 {
140     if (urb)
141     {
142         hal_free(urb);
143         // urb = NULL;
144     }
145     else
146     {
147         hal_log_err("ERR: usb_free_urb: urb = NULL");
148     }
149 }
150 
151 /*
152 *************************************************************************************
153 *                     usb_submit_urb
154 *
155 * Description:
156 *     发送urb
157 *
158 * Arguments:
159 *     urb        :  input.  待提交的urb
160 *     mem_flags  :  input.
161 *
162 * Returns:
163 *     返回命令的执行结果
164 * note:
165 *
166 *************************************************************************************
167 */
usb_submit_urb(struct urb * urb,unsigned mem_flags)168 int usb_submit_urb(struct urb *urb, unsigned mem_flags)
169 {
170     int pipe, temp, max;
171     struct usb_host_virt_dev *dev;
172     //struct usb_operations *op;
173     int is_out;
174 
175     //--<1>--check input
176     if (!urb)
177     {
178         hal_log_err("ERR: usb_submit_urb: invalid argment");
179         return -EINVAL;
180     }
181 
182     if (urb->hcpriv || !urb->complete)
183     {
184         hal_log_err("ERR: usb_submit_urb: urb->hcpriv = 0x%x ,urb->complete = 0x%x input error ",
185                    urb->hcpriv, urb->complete);
186         return -EINVAL;
187     }
188 
189     //--<2>--check dev
190     dev = urb->dev;
191 
192     if (!dev || (dev->state < USB_STATE_DEFAULT) || (!dev->bus) || (dev->devnum < 0))
193     {
194         hal_log_err("ERR: usb_submit_urb: dev had ben destroied");
195         return -ENODEV;
196     }
197 
198     if (dev->state == USB_STATE_SUSPENDED)
199     {
200         hal_log_err("ERR: usb_submit_urb: dev had ben destroied");
201         return -EHOSTUNREACH;
202     }
203 
204     //--<3>--构造URB
205     urb_sn_now ++;
206     urb->urb_sn        = urb_sn_now;
207     urb->status        = -EINPROGRESS;
208     urb->actual_length = 0;
209     urb->bandwidth     = 0;
210     /* Lots of sanity checks, so HCDs can rely on clean data
211      * and don't need to duplicate tests
212      */
213     pipe   = urb->pipe;
214     temp   = usb_pipetype(pipe);
215     is_out = usb_pipeout(pipe);
216 
217     if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)
218     {
219         hal_log_err("ERR: usb_submit_urb: USB_STATE_CONFIGURED");
220         return -ENODEV;
221     }
222 
223     /* FIXME there should be a sharable lock protecting us against
224      * config/altsetting changes and disconnects, kicking in here.
225      * (here == before maxpacket, and eventually endpoint type,
226      * checks get made.)
227      */
228     max = usb_maxpacket(dev, pipe, is_out);
229 
230     if (max <= 0)
231     {
232         hal_log_err("bogus endpoint ep%d%s  (bad maxpacket %d)",
233                    usb_pipeendpoint(pipe), is_out ? "out" : "in",
234                    max);
235         return -EMSGSIZE;
236     }
237 
238 #if 0
239 
240     /* periodic transfers limit size per frame/uframe,
241      * but drivers only control those sizes for ISO.
242      * while we're checking, initialize return status.
243      */
244     if (temp == PIPE_ISOCHRONOUS)
245     {
246         int n, len;
247 
248         /* "high bandwidth" mode, 1-3 packets/uframe? */
249         if (dev->speed == USB_SPEED_HIGH)
250         {
251             int mult = 1 + ((max >> 11) & 0x03);
252             max &= 0x07ff;
253             max *= mult;
254         }
255 
256         if (urb->number_of_packets <= 0)
257         {
258             return -EINVAL;
259         }
260 
261         for (n = 0; n < urb->number_of_packets; n++)
262         {
263             len = urb->iso_frame_desc [n].length;
264 
265             if (len < 0 || len > max)
266             {
267                 return -EMSGSIZE;
268             }
269 
270             urb->iso_frame_desc [n].status = -EXDEV;
271             urb->iso_frame_desc [n].actual_length = 0;
272         }
273     }
274 
275 #endif
276 
277     /* the I/O buffer must be mapped/unmapped, except when length=0 */
278     if (urb->transfer_buffer_length < 0)
279     {
280         hal_log_err("ERR: urb->transfer_buffer_length must not be negative");
281         return -EMSGSIZE;
282     }
283 
284 #ifdef DEBUG
285     /* stuff that drivers shouldn't do, but which shouldn't
286      * cause problems in HCDs if they get it wrong.
287      */
288     {
289         unsigned int    orig_flags = urb->transfer_flags;
290         unsigned int    allowed;
291         /* enforce simple/standard policy */
292         allowed = URB_ASYNC_UNLINK; // affects later unlinks
293         allowed |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
294         allowed |= URB_NO_INTERRUPT;
295 
296         switch (temp)
297         {
298             case PIPE_BULK:
299                 if (is_out)
300                 {
301                     allowed |= URB_ZERO_PACKET;
302                 }
303 
304             /* FALLTHROUGH */
305             case PIPE_CONTROL:
306                 allowed |= URB_NO_FSBR; /* only affects UHCI */
307 
308             /* FALLTHROUGH */
309             default:            /* all non-iso endpoints */
310                 if (!is_out)
311                 {
312                     allowed |= URB_SHORT_NOT_OK;
313                 }
314 
315                 break;
316 
317             case PIPE_ISOCHRONOUS:
318                 allowed |= URB_ISO_ASAP;
319                 break;
320         }
321 
322         urb->transfer_flags &= allowed;
323 
324         /* fail if submitter gave bogus flags */
325         if (urb->transfer_flags != orig_flags)
326         {
327             hal_log_err("PANIC : BOGUS urb flags, %x --> %x",
328                        orig_flags, urb->transfer_flags);
329             return -EINVAL;
330         }
331     }
332 #endif
333 
334     /*
335      * Force periodic transfer intervals to be legal values that are
336      * a power of two (so HCDs don't need to).
337      *
338      * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
339      * supports different values... this uses EHCI/UHCI defaults (and
340      * EHCI can use smaller non-default values).
341      */
342     switch (temp)
343     {
344         case PIPE_ISOCHRONOUS:
345         case PIPE_INTERRUPT:
346 
347             /* too small? */
348             if (urb->interval <= 0)
349             {
350                 hal_log_err("ERR: urb->interval ERROR");
351                 return -EINVAL;
352             }
353 
354             /* too big? */
355             switch (dev->speed)
356             {
357                 case USB_SPEED_HIGH:    /* units are microframes */
358 
359                     // NOTE usb handles 2^15
360                     if (urb->interval > (1024 * 8))
361                     {
362                         urb->interval = 1024 * 8;
363                     }
364 
365                     temp = 1024 * 8;
366                     break;
367 
368                 case USB_SPEED_FULL:    /* units are frames/msec */
369                 case USB_SPEED_LOW:
370                     if (temp == PIPE_INTERRUPT)
371                     {
372                         if (urb->interval > 255)
373                         {
374                             return -EINVAL;
375                         }
376 
377                         // NOTE ohci only handles up to 32
378                         temp = 128;
379                     }
380                     else
381                     {
382                         if (urb->interval > 1024)
383                         {
384                             urb->interval = 1024;
385                         }
386 
387                         // NOTE usb and ohci handle up to 2^15
388                         temp = 1024;
389                     }
390 
391                     break;
392 
393                 default:
394                     return -EINVAL;
395             }
396 
397             /* power of two? */
398             while (temp > urb->interval)
399             {
400                 temp >>= 1;
401             }
402 
403             urb->interval = temp;
404     }
405 
406     return hcd_ops_submit_urb(urb, mem_flags);
407 }
408 
409 /*
410 ***********************************************************
411 *
412 * Description   :
413 *               撤回urb
414 * Arguments  :
415 *   @urb        :
416 * Returns       :
417 *
418 * Notes         :
419 *
420 ***********************************************************
421 */
usb_unlink_urb(struct urb * urb)422 int usb_unlink_urb(struct urb *urb)
423 {
424     if (!urb)
425     {
426         hal_log_err("ERR: usb_unlink_urb: input = NULL");
427         return -EINVAL;
428     }
429 
430     if (!(urb->transfer_flags & URB_ASYNC_UNLINK))
431     {
432         hal_log_err("ERR: usb_unlink_urb: URB_ASYNC_UNLINK");
433         usb_kill_urb(urb);
434         return 0;
435     }
436 
437     return hcd_ops_unlink_urb(urb, -ECONNRESET);
438 }
439 
440 /*
441 ***********************************************************
442 *
443 * Description   :
444 *
445 * Arguments  :
446 *   @urb        :
447 * Returns       :
448 *
449 * Notes         :
450 *
451 ***********************************************************
452 */
453 /* 和usb_unlink_urb()的区别 */
usb_kill_urb(struct urb * urb)454 void usb_kill_urb(struct urb *urb)
455 {
456     uint32_t flags;
457 
458     if (urb == NULL)
459     {
460         hal_log_err("ERR: usb_kill_urb: input error");
461         return;
462     }
463 
464     flags = hal_spin_lock_irqsave(&urb->lock_urb);
465     ++urb->reject;
466     hal_spin_unlock_irqrestore(&urb->lock_urb, flags);
467     hcd_ops_unlink_urb(urb, -ENOENT);
468     flags = hal_spin_lock_irqsave(&urb->lock_urb);
469     --urb->reject;
470     hal_spin_unlock_irqrestore(&urb->lock_urb, flags);
471 }
472 
473