diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/usb/arcotg_dcd.c | 116 | ||||
-rw-r--r-- | firmware/drivers/usb/arcotg_dcd.h | 1 |
2 files changed, 70 insertions, 47 deletions
diff --git a/firmware/drivers/usb/arcotg_dcd.c b/firmware/drivers/usb/arcotg_dcd.c index 8555a923c3..46dc0ca29b 100644 --- a/firmware/drivers/usb/arcotg_dcd.c +++ b/firmware/drivers/usb/arcotg_dcd.c | |||
@@ -238,20 +238,14 @@ void usb_arcotg_dcd_irq(void) | |||
238 | /* copy data from queue head to local buffer */ | 238 | /* copy data from queue head to local buffer */ |
239 | memcpy(&dcd_controller.local_setup_buff, | 239 | memcpy(&dcd_controller.local_setup_buff, |
240 | (uint8_t *) &dev_qh[0].setup_buffer, 8); | 240 | (uint8_t *) &dev_qh[0].setup_buffer, 8); |
241 | |||
241 | /* ack setup packet*/ | 242 | /* ack setup packet*/ |
242 | UDC_ENDPTSETUPSTAT = UDC_ENDPTSETUPSTAT; | 243 | UDC_ENDPTSETUPSTAT = UDC_ENDPTSETUPSTAT; |
243 | setup_received_int(&dcd_controller.local_setup_buff); | 244 | setup_received_int(&dcd_controller.local_setup_buff); |
244 | } | 245 | } |
245 | /* | ||
246 | if (UDC_ENDPTCOMPLETE) { | ||
247 | UDC_ENDPTCOMPLETE = UDC_ENDPTCOMPLETE; | ||
248 | }*/ | ||
249 | } | ||
250 | 246 | ||
251 | for (i = 0; i < USB_MAX_ENDPOINTS; i++) { | 247 | if (UDC_ENDPTCOMPLETE) { |
252 | if ((UDC_ENDPTCOMPLETE & (1 << i)) == 1) { | 248 | dtd_complete(); |
253 | logf("COMPLETE on %d", i); | ||
254 | UDC_ENDPTCOMPLETE |= (1 << i); | ||
255 | } | 249 | } |
256 | } | 250 | } |
257 | 251 | ||
@@ -287,7 +281,6 @@ static void setup_received_int(struct usb_ctrlrequest* request) | |||
287 | int handled = 0; /* set to zero if we do not handle the message, */ | 281 | int handled = 0; /* set to zero if we do not handle the message, */ |
288 | /* and should pass it to the driver */ | 282 | /* and should pass it to the driver */ |
289 | 283 | ||
290 | logf("setup_int"); | ||
291 | into_usb_ctrlrequest(request); | 284 | into_usb_ctrlrequest(request); |
292 | 285 | ||
293 | /* handle all requests we support */ | 286 | /* handle all requests we support */ |
@@ -307,7 +300,6 @@ static void setup_received_int(struct usb_ctrlrequest* request) | |||
307 | break; | 300 | break; |
308 | 301 | ||
309 | case USB_REQ_GET_STATUS: | 302 | case USB_REQ_GET_STATUS: |
310 | logf("sending status.."); | ||
311 | response.buf = &dcd_controller.usb_state; | 303 | response.buf = &dcd_controller.usb_state; |
312 | response.length = 2; | 304 | response.length = 2; |
313 | 305 | ||
@@ -317,38 +309,33 @@ static void setup_received_int(struct usb_ctrlrequest* request) | |||
317 | 309 | ||
318 | case USB_REQ_CLEAR_FEATURE: | 310 | case USB_REQ_CLEAR_FEATURE: |
319 | case USB_REQ_SET_FEATURE: | 311 | case USB_REQ_SET_FEATURE: |
320 | /* we only support set/clear feature for endpoint */ | 312 | if (request->bRequestType != USB_RECIP_ENDPOINT) { |
321 | if (request->bRequestType == USB_RECIP_ENDPOINT) { | 313 | break; |
322 | int dir = (request->wIndex & 0x0080) ? EP_DIR_IN : EP_DIR_OUT; | ||
323 | int num = (request->wIndex & 0x000f); | ||
324 | struct usb_ep *ep; | ||
325 | |||
326 | if (request->wValue != 0 || | ||
327 | request->wLength != 0 || | ||
328 | (num * 2 + dir) > USB_MAX_PIPES) { | ||
329 | break; | ||
330 | } | ||
331 | ep = &dcd_controller.endpoints[num * 2 + dir]; | ||
332 | |||
333 | if (request->bRequest == USB_REQ_SET_FEATURE) { | ||
334 | logf("SET_FEATURE doing set_halt"); | ||
335 | handled = usb_arcotg_dcd_set_halt(ep, 1); | ||
336 | } else { | ||
337 | logf("CLEAR_FEATURE doing clear_halt"); | ||
338 | handled = usb_arcotg_dcd_set_halt(ep, 0); | ||
339 | } | ||
340 | |||
341 | if (handled == 0) { | ||
342 | handled = 1; /* dont pass it to driver */ | ||
343 | } | ||
344 | } | 314 | } |
345 | #if 0 | 315 | |
346 | if (rc == 0) { | 316 | int dir = (request->wIndex & 0x0080) ? EP_DIR_IN : EP_DIR_OUT; |
347 | /* send status only if _arcotg_ep_set_halt success */ | 317 | int num = (request->wIndex & 0x000f); |
348 | if (ep0_prime_status(udc, EP_DIR_IN)) | 318 | struct usb_ep *ep; |
349 | Ep0Stall(udc); | 319 | |
320 | if (request->wValue != 0 || | ||
321 | request->wLength != 0 || | ||
322 | (num * 2 + dir) > USB_MAX_PIPES) { | ||
323 | break; | ||
350 | } | 324 | } |
351 | #endif | 325 | ep = &dcd_controller.endpoints[num * 2 + dir]; |
326 | |||
327 | if (request->bRequest == USB_REQ_SET_FEATURE) { | ||
328 | logf("HALT"); | ||
329 | handled = usb_arcotg_dcd_set_halt(ep, true); | ||
330 | } else { | ||
331 | logf("UNHALT"); | ||
332 | handled = usb_arcotg_dcd_set_halt(ep, false); | ||
333 | } | ||
334 | |||
335 | if (handled == 0) { | ||
336 | handled = 1; /* dont pass it to driver */ | ||
337 | } | ||
338 | |||
352 | break; | 339 | break; |
353 | } | 340 | } |
354 | 341 | ||
@@ -427,6 +414,35 @@ static void port_change_int(void) | |||
427 | } | 414 | } |
428 | } | 415 | } |
429 | 416 | ||
417 | static void dtd_complete(void) { | ||
418 | |||
419 | uint32_t bit_pos; | ||
420 | int i, ep_num, direction, bit_mask, status; | ||
421 | |||
422 | /* clear the bits in the register */ | ||
423 | bit_pos = UDC_ENDPTCOMPLETE; | ||
424 | UDC_ENDPTCOMPLETE = bit_pos; | ||
425 | |||
426 | if (!bit_pos) { | ||
427 | return; | ||
428 | } | ||
429 | |||
430 | for (i = 0; i < USB_MAX_ENDPOINTS * 2; i++) { | ||
431 | ep_num = i >> 1; | ||
432 | direction = i % 2; | ||
433 | |||
434 | bit_mask = 1 << (ep_num + 16 * direction); | ||
435 | |||
436 | if (!(bit_pos & bit_mask)) { | ||
437 | continue; | ||
438 | } | ||
439 | |||
440 | logf(" "); | ||
441 | logf("TRAFFIC"); | ||
442 | logf(" -> on ep %d dir %d", i, direction); | ||
443 | } | ||
444 | } | ||
445 | |||
430 | static void suspend_int(void) | 446 | static void suspend_int(void) |
431 | { | 447 | { |
432 | dcd_controller.resume_state = dcd_controller.usb_state; | 448 | dcd_controller.resume_state = dcd_controller.usb_state; |
@@ -500,6 +516,7 @@ int usb_arcotg_dcd_enable(struct usb_ep* ep, | |||
500 | unsigned char mult = 0, zlt = 0; | 516 | unsigned char mult = 0, zlt = 0; |
501 | int retval = 0; | 517 | int retval = 0; |
502 | char *val = NULL; /* for debug */ | 518 | char *val = NULL; /* for debug */ |
519 | struct timer t; | ||
503 | 520 | ||
504 | /* catch bogus parameter */ | 521 | /* catch bogus parameter */ |
505 | if (!ep) { | 522 | if (!ep) { |
@@ -695,33 +712,41 @@ int usb_arcotg_dcd_set_halt(struct usb_ep* ep, bool halt) | |||
695 | goto out; | 712 | goto out; |
696 | } | 713 | } |
697 | 714 | ||
698 | status = 0; | ||
699 | dir = ep_is_in(ep) ? USB_RECV : USB_SEND; | 715 | dir = ep_is_in(ep) ? USB_RECV : USB_SEND; |
700 | 716 | ||
717 | logf("modify halt of %d", ep->ep_num); | ||
701 | tmp_epctrl = UDC_ENDPTCTRL(ep->ep_num); | 718 | tmp_epctrl = UDC_ENDPTCTRL(ep->ep_num); |
719 | logf("reg %x", tmp_epctrl); | ||
702 | 720 | ||
703 | if (halt) { | 721 | if (halt) { |
722 | logf("halting..."); | ||
704 | /* set the stall bit */ | 723 | /* set the stall bit */ |
705 | if (dir) { | 724 | if (dir) { |
725 | logf("..tx.."); | ||
706 | tmp_epctrl |= EPCTRL_TX_EP_STALL; | 726 | tmp_epctrl |= EPCTRL_TX_EP_STALL; |
707 | } else { | 727 | } else { |
728 | logf("..rx.."); | ||
708 | tmp_epctrl |= EPCTRL_RX_EP_STALL; | 729 | tmp_epctrl |= EPCTRL_RX_EP_STALL; |
709 | } | 730 | } |
710 | } else { | 731 | } else { |
732 | logf("UNhalting..."); | ||
711 | /* clear the stall bit and reset data toggle */ | 733 | /* clear the stall bit and reset data toggle */ |
712 | if (dir) { | 734 | if (dir) { |
735 | logf("..tx.."); | ||
713 | tmp_epctrl &= ~EPCTRL_TX_EP_STALL; | 736 | tmp_epctrl &= ~EPCTRL_TX_EP_STALL; |
714 | tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST; | 737 | tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST; |
715 | } else { | 738 | } else { |
739 | logf("..rx.."); | ||
716 | tmp_epctrl &= ~EPCTRL_RX_EP_STALL; | 740 | tmp_epctrl &= ~EPCTRL_RX_EP_STALL; |
717 | tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST; | 741 | tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST; |
718 | } | 742 | } |
719 | } | 743 | } |
720 | UDC_ENDPTCTRL(ep->ep_num) = tmp_epctrl; | 744 | UDC_ENDPTCTRL(ep->ep_num) = tmp_epctrl; |
745 | logf("reg %x", tmp_epctrl); | ||
721 | 746 | ||
722 | out: | 747 | out: |
723 | logf("%s %s halt rc=%d", ep->name, halt ? "set" : "clear", status); | 748 | logf("%s %s halt", ep->name, halt ? "set" : "clear"); |
724 | return status; | 749 | return 0; |
725 | } | 750 | } |
726 | 751 | ||
727 | int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* res) | 752 | int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* res) |
@@ -748,7 +773,6 @@ int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* res) | |||
748 | td = &dev_td[index]; | 773 | td = &dev_td[index]; |
749 | qh = &dev_qh[index]; | 774 | qh = &dev_qh[index]; |
750 | mask = 1 << (15 + index); | 775 | mask = 1 << (15 + index); |
751 | logf("sending mask: %x", mask); | ||
752 | 776 | ||
753 | do { | 777 | do { |
754 | /* calculate how much to copy and send */ | 778 | /* calculate how much to copy and send */ |
@@ -1011,10 +1035,8 @@ static int usb_ack(struct usb_ctrlrequest * s, int error) | |||
1011 | res.length = 0; | 1035 | res.length = 0; |
1012 | 1036 | ||
1013 | if (s->bRequestType & 0x80) { | 1037 | if (s->bRequestType & 0x80) { |
1014 | logf("ack in"); | ||
1015 | return usb_arcotg_dcd_receive(NULL, &res); | 1038 | return usb_arcotg_dcd_receive(NULL, &res); |
1016 | } else { | 1039 | } else { |
1017 | logf("ack out"); | ||
1018 | return usb_arcotg_dcd_send(NULL, &res); | 1040 | return usb_arcotg_dcd_send(NULL, &res); |
1019 | } | 1041 | } |
1020 | } | 1042 | } |
diff --git a/firmware/drivers/usb/arcotg_dcd.h b/firmware/drivers/usb/arcotg_dcd.h index 253101fea5..79f03f1bcc 100644 --- a/firmware/drivers/usb/arcotg_dcd.h +++ b/firmware/drivers/usb/arcotg_dcd.h | |||
@@ -158,6 +158,7 @@ int usb_arcotg_dcd_receive(struct usb_ep* ep, struct usb_response* res); | |||
158 | /* interrupt handlers */ | 158 | /* interrupt handlers */ |
159 | static void setup_received_int(struct usb_ctrlrequest* request); | 159 | static void setup_received_int(struct usb_ctrlrequest* request); |
160 | static void port_change_int(void); | 160 | static void port_change_int(void); |
161 | static void dtd_complete(void); | ||
161 | static void reset_int(void); | 162 | static void reset_int(void); |
162 | static void suspend_int(void); | 163 | static void suspend_int(void); |
163 | static void resume_int(void); | 164 | static void resume_int(void); |