Merge branch 'master' of github.com:thepowersgang/acess2
[tpg/acess2.git] / KernelLand / Modules / USB / Core / portctl.c
1 /*
2  * Acess2 USB Stack
3  * - By John Hodge (thePowersGang)
4  *
5  * portctl.c
6  * - Port control code
7  */
8 #define DEBUG   1
9 #define SANITY  1
10 #include <acess.h>
11 #include "usb.h"
12 #include <workqueue.h>
13 #include <timers.h>
14 #include <usb_hub.h>
15
16 // === PROTOTYPES ===
17 void    USB_PortCtl_Init(void);
18 void    USB_PortCtl_Worker(void *Unused);
19 void    USB_PortCtl_SetPortFeature(tUSBHub *Hub, int Port, int Feat);
20 void    USB_PortCtl_ClearPortFeature(tUSBHub *Hub, int Port, int Feat);
21  int    USB_PortCtl_GetPortStatus(tUSBHub *Hub, int Port, int Flag);
22
23 // === GLOBALS === 
24 tWorkqueue      gUSB_PortCtl_WorkQueue;
25
26 // === CODE ===
27 void USB_PortCtl_Init(void)
28 {
29         Workqueue_Init(&gUSB_PortCtl_WorkQueue, "USB Port Reset Work Queue", offsetof(tUSBHubPort, ListNext));
30         Proc_SpawnWorker(USB_PortCtl_Worker, NULL);
31 }
32
33 void USB_PortCtl_Worker(void *Unused)
34 {
35         Threads_SetName("USB PortCtl Worker");
36         for(;;)
37         {
38                 tUSBHubPort *port;
39                 tUSBHub *hub;
40                
41                 port = Workqueue_GetWork(&gUSB_PortCtl_WorkQueue);
42                 if( !port ) {
43                         Log_Warning("USB", "PortCtl Workqueue returned NULL");
44                         break;
45                 }
46                 hub = (tUSBHub*)(port - port->PortNum) - 1;
47
48                 LOG("port = %p, hub = %p", port, hub);
49
50                 switch(port->Status)
51                 {
52                 case 1:
53                         // Assert reset
54                         USB_PortCtl_SetPortFeature(hub, port->PortNum, PORT_RESET);
55                         LOG("Port reset starting");
56                         // Wait 50 ms
57                         Time_Delay(50);
58                         USB_PortCtl_ClearPortFeature(hub, port->PortNum, PORT_RESET);
59                         Time_Delay(10); // May take up to 2ms for reset to clear
60                         // Enable port
61                         LOG("Port enabling");
62                         USB_PortCtl_SetPortFeature(hub, port->PortNum, PORT_ENABLE);
63                         // Begin connect processing
64                         port->Status = 2;
65                         USB_DeviceConnected(hub, port->PortNum);
66                         break;
67                 }
68         }
69 }
70
71 void USB_PortCtl_BeginReset(tUSBHub *Hub, int Port)
72 {
73         LOG("Starting %p %i", Hub, Port);
74         // Set status field in hub structure
75         Hub->Ports[Port].Status = 1;
76         Hub->Ports[Port].PortNum = Port;
77         // Add to the work queue
78         Workqueue_AddWork(&gUSB_PortCtl_WorkQueue, &Hub->Ports[Port]);
79 }
80
81 void USB_PortCtl_SetPortFeature(tUSBHub *Hub, int Port, int Feat)
82 {
83         if( Hub->Interface->Driver == NULL ) {
84                 // - Host Port
85                 tUSBHost        *host = Hub->Interface->Dev->Host;
86                 ASSERT(host->HostDef->SetPortFeature);
87                 host->HostDef->SetPortFeature(host->Ptr, Port, Feat);
88         }
89         else {
90                 // - Hub Port
91                 Hub_SetPortFeature(Hub->Interface, Port, Feat);
92         }
93 }
94
95 void USB_PortCtl_ClearPortFeature(tUSBHub *Hub, int Port, int Feat)
96 {
97         if( Hub->Interface->Driver == NULL ) {
98                 // - Host Port
99                 tUSBHost        *host = Hub->Interface->Dev->Host;
100                 ASSERT(host->HostDef->ClearPortFeature);
101                 host->HostDef->ClearPortFeature(host->Ptr, Port, Feat);
102         }
103         else {
104                 // - Hub Port
105                 Hub_ClearPortFeature(Hub->Interface, Port, Feat);
106         }
107 }
108
109 int USB_PortCtl_GetPortStatus(tUSBHub *Hub, int Port, int Flag)
110 {
111         if( Hub->Interface->Driver == NULL ) {
112                 // - Host Port
113                 tUSBHost        *host = Hub->Interface->Dev->Host;
114                 ASSERT(host->HostDef->GetPortStatus);
115                 return host->HostDef->GetPortStatus(host->Ptr, Port, Flag);
116         }
117         else {
118                 // - Hub Port
119                 return Hub_GetPortStatus(Hub->Interface, Port, Flag);
120         }
121         return 0;
122 }
123

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