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