]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/usb/base/usb.c
Merge branch 'master' into can-usb1
[lincan.git] / embedded / libs4c / usb / base / usb.c
1 /*****************************************************/
2 /***   Module : USB module                         ***/
3 /***   Author : Roman Bartosinski (C) 28.04.2002   ***/
4 /***   Modify : 08.08.2002, 16.04.2003             ***/
5 /*****************************************************/
6
7 //#include "hal.h"
8 #include <stdio.h>
9 #include <string.h>
10 #include <system_def.h>
11 #include <endian.h>
12 #if __BYTE_ORDER == __BIG_ENDIAN
13   #include <byteswap.h>
14 #endif
15
16 //#include <usb/pdiusb.h> /* to by tu pak nemelo bejt vubec ... */
17 #include <usb/usb.h>
18 #include <usb/usbdebug.h>
19
20 #include <usb/usb_srq.h> /* temporary include - standard control request responses */
21
22 /* ep0 buffer */
23   xdata unsigned char ep0_buffer[ MAX_CONTROL_XFER_DATA_SIZE];
24
25   
26 /* usb initialize */
27   int usb_init( usb_device_t *udev) {
28     int ret = 0;
29     usb_debug_print( DEBUG_LEVEL_LOW, ("init_usb\r\n"));
30     /* create dynamic fields - endpoints */
31
32     udev->ep_events = 0;
33     udev->flags = 0;
34     udev->configuration = 0;
35     //udev->altinterface = 0;
36     udev->ep0.udev = udev;
37     udev->ep0.flags = USB_STATE_IDLE;
38     udev->ep0.epnum = 0;
39
40 //    usb_init_stdreq_fnc( udev);
41
42     if ( usb_udev_is_fnc(udev,init)) {
43       ret = usb_udev_init( udev);
44     }
45     return ret;
46   }
47
48   
49 // connecting to USB by SoftConnect
50   int usb_connect( usb_device_t *udev) {
51     int ret = 0;
52     usb_debug_print( DEBUG_LEVEL_LOW,("USB:ON\n"));
53
54     udev->ep_events = 0;
55     udev->flags = 0;
56     udev->configuration = 0;
57     //udev->altinterface = 0;
58     udev->ep0.flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
59
60     if ( usb_udev_is_fnc(udev,connect)) {
61       ret = usb_udev_connect( udev);
62     }
63     return ret;
64   }
65
66   
67   int usb_disconnect( usb_device_t *udev) {
68     int ret = 0;
69     usb_debug_print( DEBUG_LEVEL_LOW,("USB:OFF\n"));
70
71     udev->flags &= ~USB_FLAG_CONFIGURED;
72     udev->configuration = 0;
73     udev->ep_events = 0;
74     //udev->altinterface = 0;
75     udev->ep0.flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
76
77     if ( usb_udev_is_fnc(udev,disconnect)) {
78       ret = usb_udev_disconnect( udev);
79     }
80     return ret;
81   }
82
83   
84   void usb_stall( usb_ep_t *ep) {
85     usb_debug_print( DEBUG_LEVEL_HIGH, ("USB:STALL %1d\n", ep->epnum));
86     if ( usb_udev_is_fnc(ep->udev,stall)) {
87       usb_udev_stall( ep);
88     }
89   }
90
91   
92   int usb_check_events( usb_device_t *udev)
93   {
94     int ret = 0;
95     if ( usb_udev_is_fnc( udev, check_events)) {
96       ret = usb_udev_check_events( udev);
97     }
98     return ret;
99   }
100
101
102 // ************************************
103 // ***  Control transfer functions  ***
104 // ************************************
105
106   void usb_complete_control_transfer(usb_ep_t *ep0, int status) {
107     usb_debug_print( DEBUG_LEVEL_HIGH, ( "CCT:st=%d", status));
108    #ifdef USB_WITH_CB_FNC
109     if ( ep0->complete_fnc )
110       ep0->complete_fnc( ep0, status);
111     ep0->next_pkt_fnc = NULL;
112     ep0->complete_fnc = NULL;
113    #endif /*USB_WITH_CB_FNC*/
114     ep0->flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
115   }
116
117 /* Send any data in the data phase of the control transfer */
118   void usb_send_control_data( usb_device_t *udev, unsigned char *pData, unsigned short len) {
119     usb_ep_t *ep0 = &(udev->ep0);
120     usb_debug_print( DEBUG_LEVEL_HIGH, ( "SCD:ptr=%p,s=%d\n", pData, len));
121     ep0->efnc = NULL;
122     ep0->ptr = pData;
123     ep0->actual = 0;
124     if ( ep0->size > len) ep0->size = len;
125     
126     /* Schedule TX processing for later execution */
127     ep0->flags = (ep0->flags & ~USB_STATE_MASK) | USB_STATE_TRANSMIT;
128     udev->flags |= USB_FLAG_EVENT_TX0;
129   }
130
131   void usb_set_control_endfnc( usb_device_t *udev, endfnc_t *efnc) { //REENTRANT_SIGN {
132     udev->ep0.efnc = efnc;
133   }
134
135   void usb_ack_setup( usb_ep_t *ep) {
136     usb_udev_ack_setup(ep->udev);
137   }
138
139   
140 /*************************************************************
141  *** Control endpoint0 responses
142  *************************************************************/
143   int usb_control_response( usb_device_t *udev) {
144     int ret = 0;
145     usb_ep_t *ep0 = &(udev->ep0);
146     
147 /* response to interrupt BusReset */
148     if ( udev->flags & USB_FLAG_BUS_RESET) {
149       udev->flags &= ~(USB_FLAG_BUS_RESET | USB_FLAG_SUSPEND); // usb_flags.bus_reset = 0; usb_flags.configured = 0;
150       usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "USBreset\n"));
151       ret = 1;
152     }
153 /* response to interrupt Suspend */
154     if ( udev->flags & USB_FLAG_SUSPEND) {
155       udev->flags &= ~(USB_FLAG_SUSPEND); //usb_flags.suspend = 0;
156       usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "USBsuspend\n"));
157       ret = 1;
158     }
159
160     
161 /* response to interrupt SetupPacket execute response to standard device request or vendor request */
162     if ( udev->flags & USB_FLAG_SETUP) {
163       unsigned char type, req;
164       USB_DEVICE_REQUEST *preq = &(udev->request);
165
166       ep0->ptr = NULL;
167       ep0->size = 0;
168       ep0->actual = 0;
169       ep0->efnc = NULL;
170       ep0->flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
171       udev->flags &= ~USB_FLAG_SETUP;   // usb_flags.setup_packet = 0;
172      #ifdef USB_WITH_CB_FNC
173       ep0->next_pkt_fnc = NULL;
174       ep0->complete_fnc = NULL;
175      #endif /*USB_WITH_CB_FNC*/
176       
177       if ( usb_udev_read_endpoint(ep0, preq, sizeof( USB_DEVICE_REQUEST)) 
178                                    != sizeof( USB_DEVICE_REQUEST)) {
179         usb_udev_stall( ep0);
180         return -1;
181       }
182      #if __BYTE_ORDER == __BIG_ENDIAN
183       preq->wValue  = bswap_16( preq->wValue);
184       preq->wIndex  = bswap_16( preq->wIndex);
185       preq->wLength = bswap_16( preq->wLength);
186      #endif
187       usb_debug_print( DEBUG_LEVEL_MEDIUM,( "SePa:x%02X,x%02X,x%04X,x%04X,x%04X\n", preq->bmRequestType, preq->bRequest, preq->wValue, preq->wIndex, preq->wLength));
188       
189       // acknowledge setup here
190       if(usb_udev_is_fnc( udev, ack_control_setup)) {
191         usb_udev_ack_control_setup(udev);
192       }
193       
194       ep0->size = preq->wLength;
195       if ((( preq->bmRequestType & USB_DATA_DIR_MASK) == USB_DATA_DIR_FROM_HOST) && preq->wLength) {
196         ep0->ptr = ep0_buffer;
197         ep0->flags = (ep0->flags & ~USB_STATE_MASK) | USB_STATE_RECEIVE;
198       }
199       
200       type = preq->bmRequestType & USB_REQUEST_TYPE_MASK;
201       req = preq->bRequest & USB_REQUEST_MASK;
202       if ( type == USB_STANDARD_REQUEST) {
203         int ret = -1;
204         usb_debug_print( DEBUG_LEVEL_HIGH, ( "StdReq-%d\n", req));
205 /*        
206         if ( (udev->stdreq[ req]) != NULL) {
207           ret = udev->stdreq[ req]( udev);
208         }
209         if( ret < 0)
210           udev->ack_setup( udev);
211 */          
212         switch( req) {
213           case USB_REQUEST_GET_STATUS:        ret=usb_stdreq_get_status( udev); break;
214           case USB_REQUEST_CLEAR_FEATURE:     ret=usb_stdreq_clear_feature( udev); break;
215           case USB_REQUEST_SET_FEATURE:       ret=usb_stdreq_set_feature( udev); break;
216           case USB_REQUEST_SET_ADDRESS:       ret=usb_stdreq_set_address( udev); break;
217
218           case USB_REQUEST_GET_DESCRIPTOR:    ret=usb_stdreq_get_descriptor( udev); break;
219 //          case USB_REQUEST_SET_DESCRIPTOR:    break;
220           case USB_REQUEST_GET_CONFIGURATION: ret=usb_stdreq_get_configuration( udev); break;
221           case USB_REQUEST_SET_CONFIGURATION: ret=usb_stdreq_set_configuration( udev); break;
222           case USB_REQUEST_GET_INTERFACE:     ret=usb_stdreq_get_interface( udev); break;
223           case USB_REQUEST_SET_INTERFACE:     ret=usb_stdreq_set_interface( udev); break;
224 //          case USB_REQUEST_SYNC_FRAME:        break;
225 //          default:                            ret=-1; break;
226         }
227         if (ret<0)
228           usb_udev_stall( ep0);
229       } else {
230         if ( type == USB_VENDOR_REQUEST) {
231 //putchar('#');
232          #ifdef USB_WITH_CB_FNC
233           int ret = -1;
234 //         if(USBVendorRequestCBFnc != NULL)
235 //         ret = USBVendorRequestCBFnc(&usb_ep0, &dreq);
236           if ( udev->vendor_fnc != NULL)
237             ret = udev->vendor_fnc( udev);
238           if ( ret < 0)
239             usb_udev_stall( ep0);
240 //         #else /*USB_WITH_CB_FNC*/
241 //          if ( USBVendorRequest(&dreq) == -1)
242 //          udev->ack_setup( udev);
243          #endif /*USB_WITH_CB_FNC*/
244         } else if ( type == USB_CLASS_REQUEST) {
245          #ifdef USB_WITH_CB_FNC
246           int ret = -1;
247 //         if(USBClassRequestCBFnc != NULL)
248 //         ret = USBClassRequestCBFnc(&usb_ep0, &dreq);
249           if( udev->class_fnc != NULL)
250             ret = udev->class_fnc( udev);
251           if( ret < 0)
252             usb_udev_stall( ep0);
253 //         #else /*USB_WITH_CB_FNC*/
254 //          if ( USBClassRequest(&dreq) == -1)
255 //          udev->ack_setup( udev);
256          #endif /*USB_WITH_CB_FNC*/
257         } else
258             usb_udev_stall( ep0);
259       }
260       ret = 1;
261     }
262     
263 /* response to interrupt Ep0RxInt  - receive data */
264     if ( udev->flags & USB_FLAG_EVENT_RX0) {
265       int i;
266       udev->flags &= ~USB_FLAG_EVENT_RX0;
267       usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "Ep0Rx\n"));
268       if (( ep0->flags & USB_STATE_MASK) == USB_STATE_RECEIVE) {
269         usb_debug_print( DEBUG_LEVEL_HIGH, ( "RCV:p=%04lX,s=%d\n", (unsigned long)ep0->ptr, ep0->size));
270
271         i = usb_udev_read_endpoint(ep0, ep0->ptr, ep0->max_packet_size);
272         ep0->actual += i;
273         ep0->ptr +=i;
274
275        #ifdef USB_WITH_CB_FNC
276        if ( ep0->next_pkt_fnc ) {
277           if( ep0->next_pkt_fnc( ep0, i, USB_NEXT_PKT_REC) < 0) {
278             usb_udev_stall( ep0);
279             return -1;
280           }
281         }
282        #endif /*USB_WITH_CB_FNC*/
283
284         if (( i != ep0->max_packet_size) || ( ep0->actual >= ep0->size)) {
285           usb_complete_control_transfer( ep0, USB_COMPLETE_OK );
286           if ( ep0->efnc) {
287             ep0->efnc(ep0);
288           }
289         }
290       } else {
291         ep0->flags &= ~USB_STATE_MASK; //state = USB_STATE_IDLE;
292       }
293     }
294
295 /* response to interrupt Ep0TxInt */
296     if ( udev->flags & USB_FLAG_EVENT_TX0) { 
297       short i = ep0->size - ep0->actual;
298       udev->flags &= ~USB_FLAG_EVENT_TX0;
299 //usb_debug_print( DEBUG_LEVEL_LOW, ("0S-%d(%d){%d}\n", ep0->state, ep0->size, ep0->max_packet_size));
300       usb_debug_print( DEBUG_LEVEL_MEDIUM, ( "EP0Tx:i=%d\n", i));
301
302       if (( ep0->flags & USB_STATE_MASK) == USB_STATE_TRANSMIT) {
303       
304         if(i > ep0->max_packet_size) i = ep0->max_packet_size;
305
306         if ( i > 0 ) {
307          #ifdef USB_WITH_CB_FNC
308           if ( ep0->next_pkt_fnc) {
309             if( ep0->next_pkt_fnc( ep0, i, USB_NEXT_PKT_SEND) < 0) {
310               usb_udev_stall( ep0);
311               return -1;
312             }
313           }
314          #endif /*USB_WITH_CB_FNC*/
315     usb_debug_print( DEBUG_LEVEL_HIGH, ("Wr(%d)\n",i));
316           usb_udev_write_endpoint( ep0, ep0->ptr, i);
317           ep0->actual += i;
318           ep0->ptr +=i;
319
320           if( i != ep0->max_packet_size) {
321             /* last packed without full size has been sent, state can change to idle */
322             usb_complete_control_transfer( ep0, USB_COMPLETE_OK );
323           }
324         } else {
325            usb_udev_ack_setup( udev);   // Send zero packet at the end ???
326           usb_complete_control_transfer( ep0, USB_COMPLETE_OK );
327         }
328       }
329       ret = 1;
330     }
331
332     return ret;
333   }
334
335