// TODO: Async
extern void USB_SendData(tUSBInterface *Dev, int Endpoint, size_t Length, const void *Data);
extern void USB_RecvData(tUSBInterface *Dev, int Endpoint, size_t Length, void *Data);
-extern void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf, tUSB_DataCallback Callback);
+extern void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf);
#endif
host->RootHubDev.ParentHub = NULL;
host->RootHubDev.Host = host;
host->RootHubDev.Address = 0;
+ host->RootHubDev.EndpointHandles[0] = HostDef->InitControl(ControllerPtr, 0);
// host->RootHubIf.Next = NULL;
host->RootHubIf.Dev = &host->RootHubDev;
tUSBInterface *Interface;
int EndpointIdx; // Interface endpoint index
int EndpointNum; // Device endpoint num
+ void *EndpointHandle;
int PollingPeriod; // In 1ms intervals
int MaxPacketSize; // In bytes
tUSBHost *Host;
int Address;
+ void *EndpointHandles[16];
+
struct sDescriptor_Device DevDesc;
int nInterfaces;
}
USB_int_SendSetupSetAddress(dev->Host, dev->Address);
LOG("Assigned address %i", dev->Address);
-
+
+ dev->EndpointHandles[0] = dev->Host->HostDef->InitControl(dev->Host->Ptr, dev->Address << 4);
+ for( int i = 1; i < 16; i ++ )
+ dev->EndpointHandles[i] = 0;
+
// 2. Get device information
{
struct sDescriptor_Device desc;
dev_if->Endpoints[k].Type = endpt->Attributes | (endpt->Address & 0x80);
dev_if->Endpoints[k].PollingAtoms = 0;
dev_if->Endpoints[k].InputData = NULL;
+
+ // TODO: Register endpoint early
}
// Initialise driver
else
endpt = 0;
- USB_int_Request(Iface->Dev->Host, Iface->Dev->Address, endpt, Type, Req, Value, Index, Len, Data);
+ USB_int_Request(Iface->Dev, endpt, Type, Req, Value, Index, Len, Data);
}
{
tUSBHost *host;
tUSBEndpoint *ep;
- void *dest_hdl = (void*)(Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum + 1);
+ void *dest_hdl;
ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
- ep = &Dev->Endpoints[Endpoint-1];
host = Dev->Dev->Host;
+ ep = &Dev->Endpoints[Endpoint-1];
+ dest_hdl = Dev->Dev->EndpointHandles[ep->EndpointNum];
+ LOG("dest_hdl = %p", dest_hdl);
+ if( !dest_hdl ) {
+ dest_hdl = host->HostDef->InitControl(host->Ptr, Dev->Dev->Address*16 + ep->EndpointNum);
+ Dev->Dev->EndpointHandles[ep->EndpointNum] = dest_hdl;
+ LOG("dest_hdl = %p (allocated)", dest_hdl);
+ }
Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
host->HostDef->SendBulk(host->Ptr, dest_hdl, USB_WakeCallback, Proc_GetCurThread(), 1, (void*)Data, Length);
{
tUSBHost *host;
tUSBEndpoint *ep;
- void *dest_hdl = (void*)(Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum + 1);
+ void *dest_hdl;
ENTER("pDev iEndpoint iLength pData", Dev, Endpoint, Length, Data);
- ep = &Dev->Endpoints[Endpoint-1];
host = Dev->Dev->Host;
+ ep = &Dev->Endpoints[Endpoint-1];
+ dest_hdl = Dev->Dev->EndpointHandles[ep->EndpointNum];
+ LOG("dest_hdl = %p", dest_hdl);
+ if( !dest_hdl ) {
+ dest_hdl = host->HostDef->InitControl(host->Ptr, Dev->Dev->Address*16 + ep->EndpointNum);
+ Dev->Dev->EndpointHandles[ep->EndpointNum] = dest_hdl;
+ LOG("dest_hdl = %p (allocated)", dest_hdl);
+ }
Threads_ClearEvent(THREAD_EVENT_SHORTWAIT);
host->HostDef->SendBulk(host->Ptr, dest_hdl, USB_WakeCallback, Proc_GetCurThread(), 0, Data, Length);
LEAVE('-');
}
-void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf, tUSB_DataCallback Callback)
+void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, size_t Length, void *DataBuf)
{
tAsyncOp *op;
tUSBHost *host;
- void *dest_hdl = (void*)(Dev->Dev->Address*16 + Dev->Endpoints[Endpoint-1].EndpointNum + 1);
+ void *dest_hdl;
ENTER("pDev iEndpoint iLength pDataBuf", Dev, Endpoint, Length, DataBuf);
op->Length = Length;
op->Data = DataBuf;
- // TODO: Handle transfers that are larger than one packet
- // TODO: Data toggle
-
host = Dev->Dev->Host;
+ dest_hdl = Dev->Dev->EndpointHandles[op->Endpt->EndpointNum];
+ if( !dest_hdl ) {
+ dest_hdl = host->HostDef->InitControl(host->Ptr, Dev->Dev->Address*16 + op->Endpt->EndpointNum);
+ Dev->Dev->EndpointHandles[op->Endpt->EndpointNum] = dest_hdl;
+ LOG("dest_hdl = %p (allocated)", dest_hdl);
+ }
LOG("IN from %p %i:%i", host->Ptr, Dev->Dev->Address, op->Endpt->EndpointNum);
host->HostDef->SendBulk(host->Ptr, dest_hdl, USB_AsyncCallback, op, 0, DataBuf, Length);
#include <events.h>
// === PROTOTYPES ===
-void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data);
+void *USB_int_Request(tUSBDevice *Dev, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data);
void USB_int_WakeThread(void *Thread, void *Data, size_t Length);
int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address);
int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest);
int _UTF16to8(Uint16 *Input, int InputLen, char *Dest);
// === CODE ===
-void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data)
+void *USB_int_Request(tUSBDevice *Device, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data)
{
+ tUSBHost *Host = Device->Host;
void *hdl;
// TODO: Sanity check (and check that Type is valid)
struct sDeviceRequest req;
- int dest = Addr * 16 + EndPt; // TODO: Validate
- void *dest_hdl = (void*)(dest+1); // TODO: Get registered handle instead
tThread *thisthread = Proc_GetCurThread();
+ void *dest_hdl;
+
+ ENTER("pDevice xEndPt iType iReq iVal iIndx iLen pData",
+ Device, EndPt, Type, Req, Val, Indx, Len, Data);
- ENTER("pHost xdest iType iReq iVal iIndx iLen pData",
- Host, dest, Type, Req, Val, Indx, Len, Data);
+ if( EndPt < 0 || EndPt >= 16 ) {
+ LEAVE('n');
+ return NULL;
+ }
+
+ dest_hdl = Device->EndpointHandles[EndPt];
+ if( !dest_hdl ) {
+ dest_hdl = Host->HostDef->InitControl(Host->Ptr, Device->Address*16 + EndPt);
+ Device->EndpointHandles[EndPt] = dest_hdl;
+ }
req.ReqType = Type;
req.Request = Req;
int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
{
- USB_int_Request(Host, 0, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL);
+ USB_int_Request(&Host->RootHubDev, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL);
return 0;
}
int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
{
struct sDeviceRequest req;
- int dest = Dev->Address*16 + Endpoint;
- void *dest_hdl = (void*)(dest+1); // TODO: Get correct handle
+ void *dest_hdl;
+
+ dest_hdl = Dev->EndpointHandles[Endpoint];
+ if( !dest_hdl ) {
+ dest_hdl = Dev->Host->HostDef->InitControl(Dev->Host->Ptr, Dev->Address*16 + Endpoint);
+ Dev->EndpointHandles[Endpoint] = dest_hdl;
+ }
- ENTER("pDev xdest iType iIndex iLength pDest",
- Dev, dest, Type, Index, Length, Dest);
+ ENTER("pDev xEndpoint iType iIndex iLength pDest",
+ Dev, Endpoint, Type, Index, Length, Dest);
req.ReqType = 0x80;
req.ReqType |= ((Type >> 8) & 0x3) << 5; // Bits 5/6
#ifndef _USB_LOWLEVEL_H_
#define _USB_LOWLEVEL_H_
-extern void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data);
+extern void *USB_int_Request(tUSBDevice *Dev, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data);
extern int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address);
extern int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest);
extern char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index);
// --- Read and parse report descriptor ---
// NOTE: Also does sub-driver selection and initialisation
- Uint8 *report_data = alloca(report_len);
+ Uint8 report_data[report_len];
USB_ReadDescriptor(Dev, 0x1022, 0, report_len, report_data);
HID_int_ParseReport(Dev, report_data, report_len, &gHID_RootCallbacks);
int Dest = (int)Endpt-1;
int Tgl = 0;
+ if( Endpt == NULL ) {
+ Log_Error("UHCI", "Passed a NULL Endpoint handle");
+ LEAVE('n');
+ return NULL;
+ }
+
// Sanity check Endpt
- if( (tVAddr)Endpt > 0x7FF ) {
+ if( (tVAddr)Endpt > 0x800 ) {
LEAVE('n');
return NULL;
}
ENTER("pPtr pEndpt pCb pCbData bOutbound pData iLength", Ptr, Dest, Cb, CbData, bOutbound, Data, Length);
+ if( Endpt == NULL ) {
+ Log_Error("UHCI", "Passed a NULL Endpoint handle");
+ LEAVE('n');
+ return NULL;
+ }
+
+ // Sanity check Endpt
// TODO: Validation
// TODO: Data toggle