Modules/USB - Working on UHCI callbacks
[tpg/acess2.git] / Modules / USB / Core / usb.c
1 /*
2  * Acess 2 USB Stack
3  * USB Packet Control
4  */
5 #define DEBUG   1
6 #include <acess.h>
7 #include <vfs.h>
8 #include <drv_pci.h>
9 #include "usb.h"
10 #include "usb_proto.h"
11
12 // === IMPORTS ===
13 extern tUSBHost *gUSB_Hosts;
14
15 // === STRUCTURES ===
16
17 // === PROTOTYPES ===
18 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts);
19 void    USB_DeviceConnected(tUSBHub *Hub, int Port);
20 void    USB_DeviceDisconnected(tUSBHub *Hub, int Port);
21 void    *USB_GetDeviceDataPtr(tUSBDevice *Dev);
22 void    USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr);
23  int    USB_int_AllocateAddress(tUSBHost *Host);
24  int    USB_int_SendSetupSetAddress(tUSBHost *Host, int Address);
25
26 // === CODE ===
27 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
28 {
29         tUSBHost        *host;
30         
31         host = malloc(sizeof(tUSBHost) + nPorts*sizeof(void*));
32         if(!host) {
33                 // Oh, bugger.
34                 return NULL;
35         }
36         host->HostDef = HostDef;
37         host->Ptr = ControllerPtr;
38         memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
39
40         host->RootHubDev.Next = NULL;
41         host->RootHubDev.ParentHub = NULL;
42         host->RootHubDev.Host = host;
43         host->RootHubDev.Address = 0;
44         host->RootHubDev.Driver = NULL;
45         host->RootHubDev.Data = NULL;
46
47         host->RootHub.Device = NULL;
48         host->RootHub.CheckPorts = NULL;
49         host->RootHub.nPorts = nPorts;
50         memset(host->RootHub.Devices, 0, sizeof(void*)*nPorts);
51
52         // TODO: Lock
53         host->Next = gUSB_Hosts;
54         gUSB_Hosts = host;
55
56         // Initialise?
57         HostDef->CheckPorts(ControllerPtr);
58         
59         return &host->RootHub;
60 }
61
62 void USB_DeviceConnected(tUSBHub *Hub, int Port)
63 {
64         tUSBDevice      *dev;
65         if( Port >= Hub->nPorts )       return ;
66         if( Hub->Devices[Port] )        return ;
67
68         ENTER("pHub iPort", Hub, Port);
69
70         // 0. Perform port init? (done in hub?) 
71         
72         // Create structure
73         dev = malloc(sizeof(tUSBDevice));
74         dev->Next = NULL;
75         dev->ParentHub = Hub;
76         dev->Host = Hub->Device->Host;
77         dev->Address = 0;
78         dev->Driver = 0;
79         dev->Data = 0;
80
81         // 1. Assign an address
82         dev->Address = USB_int_AllocateAddress(dev->Host);
83         if(dev->Address == 0) {
84                 Log_Error("USB", "No addresses avaliable on host %p", dev->Host);
85                 free(dev);
86                 LEAVE('-');
87                 return ;
88         }
89         USB_int_SendSetupSetAddress(dev->Host, dev->Address);
90         LOG("Assigned address %i", dev->Address);
91         
92         // 2. Get device information
93
94         // Done.
95         LEAVE('-');
96 }
97
98 void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
99 {
100         
101 }
102
103 void *USB_GetDeviceDataPtr(tUSBDevice *Dev) { return Dev->Data; }
104 void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr) { Dev->Data = Ptr; }
105
106 int USB_int_AllocateAddress(tUSBHost *Host)
107 {
108          int    i;
109         for( i = 1; i < 128; i ++ )
110         {
111                 if(Host->AddressBitmap[i/8] & (1 << i))
112                         continue ;
113                 return i;
114         }
115         return 0;
116 }
117
118 int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
119 {
120         struct sDeviceRequest   req;
121         req.ReqType = 0;        // bmRequestType
122         req.Request = 5;        // SET_ADDRESS
123         req.Value = Address & 0x7F;     // wValue
124         req.Index = 0;  // wIndex
125         req.Length = 0; // wLength
126         
127         // Addr 0:0, Data Toggle = 0, no interrupt
128         return Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, FALSE, &req, sizeof(req)) == NULL;
129 }
130
131 int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
132 {
133         const int       ciMaxPacketSize = 0x400;
134         struct sDeviceRequest   req;
135          int    bToggle = 0;
136         void    *final;
137
138         req.ReqType = 0x80;
139         req.Request = 6;        // GET_DESCRIPTOR
140         req.Value = ((Type & 0xFF) << 8) | (Index & 0xFF);
141         req.Index = 0;  // TODO: Language ID
142         req.Length = Length;
143         
144         Dev->Host->HostDef->SendSETUP(
145                 Dev->Host->Ptr, Dev->Address, Endpoint,
146                 0, NULL,
147                 &req, sizeof(req)
148                 );
149         
150         bToggle = 1;
151         while( Length > ciMaxPacketSize )
152         {
153                 Dev->Host->HostDef->SendIN(
154                         Dev->Host->Ptr, Dev->Address, Endpoint,
155                         bToggle, NULL,
156                         Dest, ciMaxPacketSize
157                         );
158                 bToggle = !bToggle;
159                 Length -= ciMaxPacketSize;
160         }
161
162         final = Dev->Host->HostDef->SendIN(
163                 Dev->Host->Ptr, Dev->Address, Endpoint,
164                 bToggle, INVLPTR,
165                 Dest, Length
166                 );
167
168         while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 )
169                 Time_Delay(1);
170
171         return 0;
172 }

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