Merge branch 'master' of github.com:thepowersgang/acess2
[tpg/acess2.git] / KernelLand / Modules / USB / Core / usb_io.c
index dada0de..9d58c75 100644 (file)
 #include "usb.h"
 #include "usb_lowlevel.h"
 #include <workqueue.h>
-
-typedef struct sAsyncOp        tAsyncOp;
-
-struct sAsyncOp
-{
-       tAsyncOp        *Next;
-       tUSBEndpoint    *Endpt;
-        int    Length;
-       void    *Data;
-};
+#include <events.h>
+#include "usb_async.h"
 
 // === PROTOTYPES ===
 void   USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data);
 void   USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data);
-void   USB_AsyncCallback(void *Ptr, void *Buf, int Length);
+void   USB_SendData(tUSBInterface *Dev, int Endpoint, size_t Length, const void *Data);
+void   USB_WakeCallback(void *Ptr, void *Buf, size_t Length);
+void   USB_AsyncCallback(void *Ptr, void *Buf, size_t Length);
 void   USB_AsyncThread(void *unused);
 
 // === GLOBALS ===
@@ -55,17 +49,57 @@ void USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Valu
 }
 
 
-void USB_SendData(tUSBInterface *Dev, int Endpoint, int Length, void *Data)
+void USB_SendData(tUSBInterface *Dev, int Endpoint, size_t Length, const void *Data)
 {
-       Log_Warning("USB", "TODO: Implement USB_SendData");
+       tUSBHost *host;
+       tUSBEndpoint    *ep;
+       ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
+
+       ep = &Dev->Endpoints[Endpoint-1];
+       host = Dev->Dev->Host;
+
+       Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
+       for( size_t ofs = 0; ofs < Length; ofs += ep->MaxPacketSize )
+       {
+               size_t  len = MIN(Length - ofs, ep->MaxPacketSize);
+               
+               host->HostDef->BulkOUT(
+                       host->Ptr, Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum,
+                       0, (len == Length - ofs ? USB_WakeCallback : NULL), Proc_GetCurThread(),
+                       (char*)Data + ofs, len
+                       );
+       }
+       Threads_WaitEvents(THREAD_EVENT_SHORTWAIT);
+       
+       LEAVE('-');
 }
 
-void USB_RecvData(tUSBInterface *Dev, int Endpoint, int Length, void *Data)
+void USB_RecvData(tUSBInterface *Dev, int Endpoint, size_t Length, void *Data)
 {
-       Log_Warning("USB", "TODO: Implement USB_RecvData");
+       tUSBHost *host;
+       tUSBEndpoint    *ep;
+       ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
+
+       ep = &Dev->Endpoints[Endpoint-1];
+       host = Dev->Dev->Host;
+
+       Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
+       for( size_t ofs = 0; ofs < Length; ofs += ep->MaxPacketSize )
+       {
+               size_t  len = MIN(Length - ofs, ep->MaxPacketSize);
+               
+               host->HostDef->BulkIN(
+                       host->Ptr, Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum,
+                       0, (len == Length - ofs ? USB_WakeCallback : NULL), Proc_GetCurThread(),
+                       (char*)Data + ofs, len
+                       );
+       }
+       Threads_WaitEvents(THREAD_EVENT_SHORTWAIT);
+       
+       LEAVE('-');
 }
 
-void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, int Length, void *DataBuf, tUSB_DataCallback Callback)
+void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf, tUSB_DataCallback Callback)
 {
        tAsyncOp *op;
        tUSBHost *host;
@@ -82,19 +116,30 @@ void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, int Length, void *DataBuf,
        // TODO: Data toggle
 
        host = Dev->Dev->Host;
+       
        LOG("IN from %p %i:%i", host->Ptr, Dev->Dev->Address, op->Endpt->EndpointNum);
-       host->HostDef->SendIN(
-               host->Ptr, Dev->Dev->Address*16 + op->Endpt->EndpointNum,
-               0, USB_AsyncCallback, op,
-               DataBuf, Length
-               );
+       for( size_t ofs = 0; ofs < Length; ofs += op->Endpt->MaxPacketSize )
+       {
+               size_t  len = MIN(Length - ofs, op->Endpt->MaxPacketSize);
+               
+               host->HostDef->BulkIN(
+                       host->Ptr, Dev->Dev->Address*16 + op->Endpt->EndpointNum,
+                       0, (len == Length - ofs ? USB_AsyncCallback : NULL), op,
+                       (char*)DataBuf + ofs, len
+                       );
+       }
        
        LEAVE('-');
 
 //     Log_Warning("USB", "TODO: Implement USB_RecvDataA");
 }
 
-void USB_AsyncCallback(void *Ptr, void *Buf, int Length)
+void USB_WakeCallback(void *Ptr, void *Buf, size_t Length)
+{
+       Threads_PostEvent(Ptr, THREAD_EVENT_SHORTWAIT);
+}
+
+void USB_AsyncCallback(void *Ptr, void *Buf, size_t Length)
 {
        tAsyncOp *op = Ptr;
        op->Length = Length;
@@ -115,6 +160,8 @@ void USB_AsyncThread(void *Unused)
                iface->Driver->Endpoints[op->Endpt->EndpointIdx].DataAvail(
                        iface, op->Endpt->EndpointIdx,
                        op->Length, op->Data);
+               
+               free(op);
        }
 }
 

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