diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-11-24 20:28:04 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-12-12 04:45:16 -0500 |
commit | 17f7f76940214af91bfefcf9a2ca156701d905e6 (patch) | |
tree | ba11ca3a5c1d5cc8d8b0db004f252db23ffd3158 /drivers/usb/renesas_usbhs/mod_gadget.c | |
parent | ced6e09e6ec4f52c9bd76d6b8debd67517fdcc1c (diff) |
usb: renesas_usbhs: add basic USB_REQ_GET_STATUS support
This patch adds basic get-status support for chapter 9 test.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/renesas_usbhs/mod_gadget.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 3130089eacff..812960ba95e1 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -305,6 +305,104 @@ struct usbhsg_recip_handle req_set_feature = { | |||
305 | }; | 305 | }; |
306 | 306 | ||
307 | /* | 307 | /* |
308 | * USB_TYPE_STANDARD / get status functions | ||
309 | */ | ||
310 | static void __usbhsg_recip_send_complete(struct usb_ep *ep, | ||
311 | struct usb_request *req) | ||
312 | { | ||
313 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | ||
314 | |||
315 | /* free allocated recip-buffer/usb_request */ | ||
316 | kfree(ureq->pkt.buf); | ||
317 | usb_ep_free_request(ep, req); | ||
318 | } | ||
319 | |||
320 | static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv, | ||
321 | unsigned short status) | ||
322 | { | ||
323 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | ||
324 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); | ||
325 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
326 | struct usb_request *req; | ||
327 | unsigned short *buf; | ||
328 | |||
329 | /* alloc new usb_request for recip */ | ||
330 | req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC); | ||
331 | if (!req) { | ||
332 | dev_err(dev, "recip request allocation fail\n"); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | /* alloc recip data buffer */ | ||
337 | buf = kmalloc(sizeof(*buf), GFP_ATOMIC); | ||
338 | if (!buf) { | ||
339 | usb_ep_free_request(&dcp->ep, req); | ||
340 | dev_err(dev, "recip data allocation fail\n"); | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | /* recip data is status */ | ||
345 | *buf = cpu_to_le16(status); | ||
346 | |||
347 | /* allocated usb_request/buffer will be freed */ | ||
348 | req->complete = __usbhsg_recip_send_complete; | ||
349 | req->buf = buf; | ||
350 | req->length = sizeof(*buf); | ||
351 | req->zero = 0; | ||
352 | |||
353 | /* push packet */ | ||
354 | pipe->handler = &usbhs_fifo_pio_push_handler; | ||
355 | usbhsg_queue_push(dcp, usbhsg_req_to_ureq(req)); | ||
356 | } | ||
357 | |||
358 | static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv, | ||
359 | struct usbhsg_uep *uep, | ||
360 | struct usb_ctrlrequest *ctrl) | ||
361 | { | ||
362 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
363 | unsigned short status = 1 << USB_DEVICE_SELF_POWERED; | ||
364 | |||
365 | __usbhsg_recip_send_status(gpriv, status); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int usbhsg_recip_handler_std_get_interface(struct usbhs_priv *priv, | ||
371 | struct usbhsg_uep *uep, | ||
372 | struct usb_ctrlrequest *ctrl) | ||
373 | { | ||
374 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
375 | unsigned short status = 0; | ||
376 | |||
377 | __usbhsg_recip_send_status(gpriv, status); | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv, | ||
383 | struct usbhsg_uep *uep, | ||
384 | struct usb_ctrlrequest *ctrl) | ||
385 | { | ||
386 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
387 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
388 | unsigned short status = 0; | ||
389 | |||
390 | if (usbhs_pipe_is_stall(pipe)) | ||
391 | status = 1 << USB_ENDPOINT_HALT; | ||
392 | |||
393 | __usbhsg_recip_send_status(gpriv, status); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | struct usbhsg_recip_handle req_get_status = { | ||
399 | .name = "get status", | ||
400 | .device = usbhsg_recip_handler_std_get_device, | ||
401 | .interface = usbhsg_recip_handler_std_get_interface, | ||
402 | .endpoint = usbhsg_recip_handler_std_get_endpoint, | ||
403 | }; | ||
404 | |||
405 | /* | ||
308 | * USB_TYPE handler | 406 | * USB_TYPE handler |
309 | */ | 407 | */ |
310 | static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | 408 | static int usbhsg_recip_run_handle(struct usbhs_priv *priv, |
@@ -431,6 +529,9 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | |||
431 | case USB_REQ_SET_FEATURE: | 529 | case USB_REQ_SET_FEATURE: |
432 | recip_handler = &req_set_feature; | 530 | recip_handler = &req_set_feature; |
433 | break; | 531 | break; |
532 | case USB_REQ_GET_STATUS: | ||
533 | recip_handler = &req_get_status; | ||
534 | break; | ||
434 | } | 535 | } |
435 | } | 536 | } |
436 | 537 | ||