first adaption of 'usbport' by Benedikt Sauter
[ppcskel.git] / usb / core / core.c
1 /*
2  * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
3  * All rights reserved.
4  *
5  * Short descripton of file:
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions 
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright 
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above 
15  *     copyright notice, this list of conditions and the following 
16  *     disclaimer in the documentation and/or other materials provided 
17  *     with the distribution.
18  *   * Neither the name of the FH Augsburg nor the names of its 
19  *     contributors may be used to endorse or promote products derived 
20  *     from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
25  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //#include <stdlib.h>
36 #include "core.h"
37 #include "../host/host.h"
38 #include "usb.h"
39 #include "../usbspec/usb11spec.h"
40 #include "../lib/list.h"
41 #include "../../malloc.h"
42
43 /**
44  * Initialize USB stack.
45  */
46 void usb_init()
47 {
48   core.drivers = list_create();
49   core.devices = list_create();
50   core.nextaddress = 1;
51   hcdi_init();
52 }
53
54 /**
55  * Get next free usb device address.
56  */
57 u8 usb_next_address()
58 {
59   u8 addr = core.nextaddress;
60   core.nextaddress++;
61   return addr;
62 }
63
64
65 /**
66  * Call this function periodically for 
67  * control and transfer management.
68  */
69 void usb_periodic()
70 {
71   // call ever registered driver  
72   usb_driver *drv;
73   element *iterator = core.drivers->head;
74   while (iterator != NULL) {
75     drv = (usb_driver *) iterator->data;
76     drv->check();
77     iterator = iterator->next;
78   }
79 }
80
81
82 /** 
83  * Enumerate new device and create data structures 
84  * for the core. usb_add_device expected that
85  * the device answers to address zero.
86  */
87 usb_device *usb_add_device()
88 {
89   usb_device *dev = (usb_device *) malloc(sizeof(usb_device));
90   dev->address = 0;
91   dev->bMaxPacketSize0 = 8;     /* send at first time only 8 bytes */
92
93   dev->epSize[0] = 64;
94   dev->epSize[1] = 64;
95   dev->epSize[2] = 64;
96
97   dev->epTogl[0] = 0;
98   dev->epTogl[1] = 0;
99   dev->epTogl[2] = 0;
100
101   char buf[64];
102   u8 devdescr_size;
103   u8 address = usb_next_address();
104
105   /* ask first 8 bytes of device descriptor with this special 
106    * GET Descriptor Request, when device address = 0
107    */
108   usb_control_msg(dev, 0x80, GET_DESCRIPTOR, 1, 0, 64, buf, 8, 0);
109
110   dev->bMaxPacketSize0 = (u8) buf[7];   /* setup real ep0 fifo size */
111   devdescr_size = (u8) buf[0];  /* save real length of device descriptor */
112
113   /* define new adress */
114   usb_control_msg(dev, 0x00, SET_ADDRESS, address << 8, 0, 0, buf, 8, 0);
115   dev->address = address;
116
117   /* get complete device descriptor */
118   usb_control_msg(dev, 0x80, GET_DESCRIPTOR, 1, 0, devdescr_size, buf, 8,
119                   0);
120
121   /* save only really neccessary values for this small usbstack */
122   dev->bDeviceClass = (u8) buf[4];
123   dev->bDeviceSubClass = (u8) buf[5];
124   dev->bDeviceProtocoll = (u8) buf[6];
125   dev->idVendor = (u16) (buf[9] << 8) | (buf[8]);
126   dev->idProduct = (u16) (buf[11] << 8) | (buf[10]);
127   dev->bcdDevice = (u16) (buf[13] << 8) | (buf[12]);
128
129   // string descriptoren werden nicht im arbeitsspeicher gehalten -> on demand mit 
130   // entprechenden funktionen
131   // hier muss man noch mehr abholen, konfigurationene, interfaces und endpunkte
132
133   /* add device to device list */
134   element *tmp = (element *) malloc(sizeof(element));
135   tmp->data = (void *) dev;
136   list_add_tail(core.devices, tmp);
137
138   usb_probe_driver();
139
140   return dev;
141 }
142
143 /**
144  * Find currently detached device and remove
145  * data structures
146  */
147 u8 usb_remove_device(usb_device * dev)
148 {
149   // FIXME!!!! dieser quatsch ist nur temporaer
150   free(core.devices->head);
151   free(core.devices);
152   core.devices = list_create();
153   return 1;
154 }
155
156 /**
157  * Register new driver at usb stack.
158  */
159 u8 usb_register_driver(usb_driver * dev)
160 {
161   /* add driver to driver list */
162   element *tmp = (element *) malloc(sizeof(element));
163   tmp->data = (void *) dev;
164   tmp->next = NULL;
165   list_add_tail(core.drivers, tmp);
166
167
168   /** 
169    * first check to find a suitable device 
170    * (root hub drivers need this call here)
171    */
172   dev->probe();
173
174   return 1;
175 }
176
177
178 /**
179  * Call every probe function from every registered
180  * driver, to check if there is a valid driver
181  * for the new device.  
182  */
183 void usb_probe_driver()
184 {
185   // call ever registered driver  
186   usb_driver *drv;
187   element *iterator = core.drivers->head;
188   while (iterator != NULL) {
189     drv = (usb_driver *) iterator->data;
190     drv->probe();
191     iterator = iterator->next;
192   }
193 }
194
195 /**
196  * Not implemented.
197  */
198 usb_irp *usb_get_irp()
199 {
200   return 0;
201 }
202
203 /**
204  * Not implemented.
205  */
206 u8 usb_remove_irp(usb_irp * irp)
207 {
208
209   return 1;
210 }
211
212 /**
213  * Takes usb_irp and split it into
214  * several usb packeges (SETUP,IN,OUT)
215  * In the usbstack they are transported with the
216  * usb_transfer_descriptor data structure.
217  */
218 u16 usb_submit_irp(usb_irp * irp)
219 {
220   usb_transfer_descriptor *td;
221   u8 runloop = 1;
222   u16 restlength = irp->len;
223   char *td_buf_ptr = irp->buffer;
224
225   //u8 togl=irp->dev->epTogl[(irp->endpoint & 0x7F)];
226   u8 togl = irp->dev->epTogl[(irp->endpoint & 0x7F)];
227   //u8 togl=0;
228
229   switch (irp->type) {
230   case USB_CTRL:
231
232     /* alle requests mit dem gleichen algorithmus zerteilen
233      * das einzige ist der spezielle get_Device_descriptor request
234      * bei dem eine laenge von 64 angegeben ist.
235      * wenn man an adresse 0 einen get_device_desciptor schickt
236      * dann reichen die ersten 8 byte.
237      */
238
239       /***************** Setup Stage ***********************/
240     td = usb_create_transfer_descriptor(irp);
241     td->pid = USB_PID_SETUP;
242     td->buffer = irp->buffer;
243     td->actlen = 8;             /* control message are always 8 bytes */
244
245     togl = 0;
246     td->togl = togl;            /* start with data0 */
247     if (togl == 0)
248       togl = 1;
249     else
250       togl = 0;
251       /**** send token ****/
252     hcdi_enqueue(td);
253
254       /***************** Data Stage ***********************/
255       /**
256        * You can see at bit 7 of bmRequestType if this stage is used,
257        * default requests are always 8 byte greate, from
258        * host to device. Stage 3 is only neccessary if the request
259        * expected datas from the device.
260        * bit7 - 1 = from device to host -> yes we need data stage
261        * bit7 - 0 = from host to device -> no send zero packet
262        *
263        * nach einem setup token kann nur ein IN token in stage 3 folgen
264        * nie aber ein OUT. Ein Zero OUT wird nur als Bestaetigung benoetigt.
265        *
266        *
267        * bit7 = 1
268        *  Device to Host
269        *  - es kommen noch Daten mit PID_IN an
270        *  - host beendet mit PID_OUT DATA1 Zero
271        * bit7 - 0
272        *  Host zu Device (wie set address)
273        *  - device sendet ein PID_IN DATA1 Zero Packet als bestaetigung
274        */
275     usb_device_request *setup = (usb_device_request *) irp->buffer;
276     u8 bmRequestType = setup->bmRequestType;
277
278     if (bmRequestType & 0x80) { /* check bit 7 of bmRequestType */
279
280       /* schleife die die tds generiert */
281       while (runloop) {
282         td = usb_create_transfer_descriptor(irp);
283         td->actlen = irp->epsize;
284         /* stop loop if all bytes are send */
285         if (restlength <= irp->epsize) {
286           runloop = 0;
287           td->actlen = restlength;
288         }
289
290         td->buffer = td_buf_ptr;
291         /* move pointer for next packet */
292         td_buf_ptr = td_buf_ptr + irp->epsize;
293
294         td->pid = USB_PID_IN;
295         td->togl = togl;
296         if (togl == 0)
297           togl = 1;
298         else
299           togl = 0;
300
301         /* wenn device descriptor von adresse 0 angefragt wird werden nur
302          * die ersten 8 byte abgefragt
303          */
304         if (setup->bRequest == GET_DESCRIPTOR && (setup->wValue >> 8) == 1
305             && td->devaddress == 0) {
306           runloop = 0;          /* stop loop */
307         }
308
309           /**** send token ****/
310         hcdi_enqueue(td);
311
312         /* pruefe ob noch weitere Pakete vom Device abgeholt werden muessen */
313         restlength = restlength - irp->epsize;
314       }
315     }
316
317
318
319
320       /***************** Status Stage ***********************/
321     /* Zero packet for end */
322     td = usb_create_transfer_descriptor(irp);
323     td->togl = 1;               /* zero data packet = always DATA1 packet */
324     td->actlen = 0;
325     td->buffer = NULL;
326
327       /**
328        * bit7 = 1, host beendet mit PID_OUT DATA1 Zero
329        * bit7 = 0, device sendet ein PID_IN DATA1 Zero Packet als bestaetigung
330        */
331     if (bmRequestType & 0x80) { /* check bit 7 of bmRequestType */
332       td->pid = USB_PID_OUT;
333     } else {
334       td->pid = USB_PID_IN;
335     }
336       /**** send token ****/
337     hcdi_enqueue(td);
338     free(td);
339
340
341     break;
342   case USB_BULK:
343
344     core.stdout("bulk\r\n");
345     //u8 runloop=1;
346     //u16 restlength = irp->len;
347     //char * td_buf_ptr=irp->buffer;
348
349     /* schleife die die tds generiert */
350     while (runloop) {
351
352       td = usb_create_transfer_descriptor(irp);
353       td->endpoint = td->endpoint & 0x7F;       /* clear direction bit */
354
355       /* max packet size for given endpoint */
356       td->actlen = irp->epsize;
357
358       /* Generate In Packet  */
359       if (irp->endpoint & 0x80)
360         td->pid = USB_PID_IN;
361       else
362         /* Generate Out Packet */
363         td->pid = USB_PID_OUT;
364
365       /* stop loop if all bytes are send */
366       if (restlength <= irp->epsize) {
367         runloop = 0;
368         td->actlen = restlength;
369       }
370
371       td->buffer = td_buf_ptr;
372       /* move pointer for next packet */
373       td_buf_ptr = td_buf_ptr + irp->epsize;
374
375       td->togl = togl;
376       if (togl == 0)
377         togl = 1;
378       else
379         togl = 0;
380         /**** send token ****/
381       hcdi_enqueue(td);
382       free(td);
383     }
384     /* next togl */
385     //if(td->pid == USB_PID_OUT) {
386     //if(togl==0) togl=1; else togl=0;
387     //}
388     irp->dev->epTogl[(irp->endpoint & 0x7F)] = togl;
389
390     break;
391   }
392
393   return 1;
394 }
395
396
397
398 /** 
399  * Create a transfer descriptor with an parent irp.
400  */
401 usb_transfer_descriptor *usb_create_transfer_descriptor(usb_irp * irp)
402 {
403   usb_transfer_descriptor *td =
404       (usb_transfer_descriptor *) malloc(sizeof(usb_transfer_descriptor));
405
406   td->devaddress = irp->dev->address;
407   td->endpoint = irp->endpoint;
408   td->iso = 0;
409   td->state = USB_TRANSFER_DESCR_NONE;
410
411   return td;
412 }