3 * - By John Hodge (thePowersGang)
12 #include "usb_lowlevel.h"
13 #include <workqueue.h>
15 #include "usb_async.h"
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);
26 tWorkqueue gUSB_AsyncQueue;
29 void USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data)
31 USB_int_ReadDescriptor(Iface->Dev, 0, Type, Index, Length, Data);
34 void USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data)
39 if(Endpoint < 0 || Endpoint >= Iface->nEndpoints)
42 // Get endpoint number
44 endpt = Iface->Endpoints[Endpoint-1].EndpointNum;
48 USB_int_Request(Iface->Dev->Host, Iface->Dev->Address, endpt, Type, Req, Value, Index, Len, Data);
52 void USB_SendData(tUSBInterface *Dev, int Endpoint, size_t Length, const void *Data)
56 ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
58 ep = &Dev->Endpoints[Endpoint-1];
59 host = Dev->Dev->Host;
61 Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
62 for( size_t ofs = 0; ofs < Length; ofs += ep->MaxPacketSize )
64 size_t len = MIN(Length - ofs, ep->MaxPacketSize);
66 host->HostDef->BulkOUT(
67 host->Ptr, Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum,
68 0, (len == Length - ofs ? USB_WakeCallback : NULL), Proc_GetCurThread(),
69 (char*)Data + ofs, len
72 Threads_WaitEvents(THREAD_EVENT_SHORTWAIT);
77 void USB_RecvData(tUSBInterface *Dev, int Endpoint, size_t Length, void *Data)
81 ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
83 ep = &Dev->Endpoints[Endpoint-1];
84 host = Dev->Dev->Host;
86 Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
87 for( size_t ofs = 0; ofs < Length; ofs += ep->MaxPacketSize )
89 size_t len = MIN(Length - ofs, ep->MaxPacketSize);
91 host->HostDef->BulkIN(
92 host->Ptr, Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum,
93 0, (len == Length - ofs ? USB_WakeCallback : NULL), Proc_GetCurThread(),
94 (char*)Data + ofs, len
97 Threads_WaitEvents(THREAD_EVENT_SHORTWAIT);
102 void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf, tUSB_DataCallback Callback)
107 ENTER("pDev iEndpoint iLength pDataBuf", Dev, Endpoint, Length, DataBuf);
109 op = malloc(sizeof(*op));
111 op->Endpt = &Dev->Endpoints[Endpoint-1];
115 // TODO: Handle transfers that are larger than one packet
118 host = Dev->Dev->Host;
120 LOG("IN from %p %i:%i", host->Ptr, Dev->Dev->Address, op->Endpt->EndpointNum);
121 for( size_t ofs = 0; ofs < Length; ofs += op->Endpt->MaxPacketSize )
123 size_t len = MIN(Length - ofs, op->Endpt->MaxPacketSize);
125 host->HostDef->BulkIN(
126 host->Ptr, Dev->Dev->Address*16 + op->Endpt->EndpointNum,
127 0, (len == Length - ofs ? USB_AsyncCallback : NULL), op,
128 (char*)DataBuf + ofs, len
134 // Log_Warning("USB", "TODO: Implement USB_RecvDataA");
137 void USB_WakeCallback(void *Ptr, void *Buf, size_t Length)
139 Threads_PostEvent(Ptr, THREAD_EVENT_SHORTWAIT);
142 void USB_AsyncCallback(void *Ptr, void *Buf, size_t Length)
146 LOG("adding %p to work queue", op);
147 Workqueue_AddWork(&gUSB_AsyncQueue, op);
150 void USB_AsyncThread(void *Unused)
152 Threads_SetName("USB Async IO Thread");
155 tAsyncOp *op = Workqueue_GetWork(&gUSB_AsyncQueue);
156 tUSBInterface *iface = op->Endpt->Interface;
160 iface->Driver->Endpoints[op->Endpt->EndpointIdx].DataAvail(
161 iface, op->Endpt->EndpointIdx,
162 op->Length, op->Data);