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