Merge branch 'master' of git://localhost/acess2
[tpg/acess2.git] / KernelLand / Modules / USB / Core / usb_io.c
1 /*
2  * Acess2 USB Stack
3  * - By John Hodge (thePowersGang)
4  *
5  * usb_io.c
6  * - High-level IO
7  */
8 #define DEBUG   0
9
10 #include <usb_core.h>
11 #include "usb.h"
12 #include "usb_lowlevel.h"
13 #include <workqueue.h>
14 #include <events.h>
15 #include "usb_async.h"
16
17 // === PROTOTYPES ===
18 void    USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data);
19 void    USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data);
20 void    USB_SendData(tUSBInterface *Dev, int Endpoint, size_t Length, const void *Data);
21 void    USB_WakeCallback(void *Ptr, void *Buf, size_t Length);
22 void    USB_AsyncCallback(void *Ptr, void *Buf, size_t Length);
23 void    USB_AsyncThread(void *unused);
24
25 // === GLOBALS ===
26 tWorkqueue      gUSB_AsyncQueue;
27
28 // === CODE ===
29 void USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data)
30 {
31         USB_int_ReadDescriptor(Iface->Dev, 0, Type, Index, Length, Data);
32 }
33
34 void USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data)
35 {
36          int    endpt;
37
38         // Sanity check
39         if(Endpoint < 0 || Endpoint >= Iface->nEndpoints)
40                 return ;        
41
42         // Get endpoint number
43         if(Endpoint)
44                 endpt = Iface->Endpoints[Endpoint-1].EndpointNum;
45         else
46                 endpt = 0;
47         
48         USB_int_Request(Iface->Dev, endpt, Type, Req, Value, Index, Len, Data);
49 }
50
51
52 void USB_SendData(tUSBInterface *Dev, int Endpoint, size_t Length, const void *Data)
53 {
54         tUSBHost *host;
55         tUSBEndpoint    *ep;
56         void    *dest_hdl;
57         ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
58
59         host = Dev->Dev->Host;
60         ep = &Dev->Endpoints[Endpoint-1];
61         dest_hdl = Dev->Dev->EndpointHandles[ep->EndpointNum];
62         LOG("dest_hdl = %p", dest_hdl);
63         if( !dest_hdl ) {
64                 Log_Notice("USB", "_SendData on uninitialised enpoint (%p#%i)", Dev->Dev, ep->EndpointNum);
65                 LEAVE('-');
66                 return;
67         }
68
69         Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
70         host->HostDef->SendBulk(host->Ptr, dest_hdl, USB_WakeCallback, Proc_GetCurThread(), 1, (void*)Data, Length);
71         Threads_WaitEvents(THREAD_EVENT_SHORTWAIT);
72         
73         LEAVE('-');
74 }
75
76 void USB_RecvData(tUSBInterface *Dev, int Endpoint, size_t Length, void *Data)
77 {
78         tUSBHost *host;
79         tUSBEndpoint    *ep;
80         void    *dest_hdl;
81         ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
82
83         host = Dev->Dev->Host;
84         ep = &Dev->Endpoints[Endpoint-1];
85         dest_hdl = Dev->Dev->EndpointHandles[ep->EndpointNum];
86         LOG("dest_hdl = %p", dest_hdl);
87         if( !dest_hdl ) {
88                 Log_Notice("USB", "_RecvData on uninitialised enpoint (%p#%i)", Dev->Dev, ep->EndpointNum);
89                 LEAVE('-');
90                 return;
91         }
92
93         Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
94         host->HostDef->SendBulk(host->Ptr, dest_hdl, USB_WakeCallback, Proc_GetCurThread(), 0, Data, Length);
95         Threads_WaitEvents(THREAD_EVENT_SHORTWAIT);
96         
97         LEAVE('-');
98 }
99
100 void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf)
101 {
102         tAsyncOp *op;
103         tUSBHost *host;
104         void    *dest_hdl;
105
106         ENTER("pDev iEndpoint iLength pDataBuf", Dev, Endpoint, Length, DataBuf); 
107
108         op = malloc(sizeof(*op));
109         op->Next = NULL;
110         op->Endpt = &Dev->Endpoints[Endpoint-1];
111         op->Length = Length;
112         op->Data = DataBuf;
113
114         host = Dev->Dev->Host;
115         dest_hdl = Dev->Dev->EndpointHandles[op->Endpt->EndpointNum];
116         if( !dest_hdl ) {
117                 Log_Notice("USB", "_SendData on uninitialised enpoint (%p#%i)", Dev->Dev, op->Endpt->EndpointNum);
118                 LEAVE('-');
119                 return;
120         }
121         
122         LOG("IN from %p %i:%i", host->Ptr, Dev->Dev->Address, op->Endpt->EndpointNum);
123         host->HostDef->SendBulk(host->Ptr, dest_hdl, USB_AsyncCallback, op, 0, DataBuf, Length);
124         
125         LEAVE('-');
126
127 //      Log_Warning("USB", "TODO: Implement USB_RecvDataA");
128 }
129
130 void USB_WakeCallback(void *Ptr, void *Buf, size_t Length)
131 {
132         Threads_PostEvent(Ptr, THREAD_EVENT_SHORTWAIT);
133 }
134
135 void USB_AsyncCallback(void *Ptr, void *Buf, size_t Length)
136 {
137         tAsyncOp *op = Ptr;
138         op->Length = Length;
139         LOG("adding %p to work queue", op);
140         Workqueue_AddWork(&gUSB_AsyncQueue, op);
141 }
142
143 void USB_AsyncThread(void *Unused)
144 {
145         Threads_SetName("USB Async IO Thread");
146         for(;;)
147         {
148                 tAsyncOp *op = Workqueue_GetWork(&gUSB_AsyncQueue);
149                 tUSBInterface   *iface = op->Endpt->Interface;
150
151                 LOG("op = %p", op);     
152
153                 iface->Driver->Endpoints[op->Endpt->EndpointIdx].DataAvail(
154                         iface, op->Endpt->EndpointIdx,
155                         op->Length, op->Data);
156                 
157                 free(op);
158         }
159 }
160

UCC git Repository :: git.ucc.asn.au