56bf9b520f14fefce67de5385f967173dd3cce9a
[tpg/acess2.git] / KernelLand / Modules / Input / Mouse / main.c
1 /*
2  * Acess2 Kernel - Mouse Mulitplexing Driver
3  * - By John Hodge (thePowersGang)
4  *
5  * main.c
6  * - Mouse mulitplexing
7  */
8 #define DEBUG   0
9 #define VERSION VER2(0,1)
10 #include <acess.h>
11 #include <modules.h>
12 #include <fs_devfs.h>
13 #include <Input/Mouse/include/mouse.h>
14 #include "include/mouse_int.h"
15
16 // === PROTOTYPES ===
17  int    Mouse_Install(char **Arguments);
18  int    Mouse_Cleanup(void);
19 // - "User" side
20 char    *Mouse_Root_ReadDir(tVFS_Node *Node, int Pos);
21 tVFS_Node       *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
22  int    Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
23 size_t  Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data);
24 // - Device Side
25 tMouse  *Mouse_Register(const char *Name, int NumButtons, int NumAxies);
26 void    Mouse_RemoveInstance(tMouse *Handle);
27 void    Mouse_HandleEvent(tMouse *Handle, Uint32 ButtonState, int *AxisDeltas);
28
29 // === GLOBALS ===
30 MODULE_DEFINE(0, VERSION, Mouse, Mouse_Install, Mouse_Cleanup, NULL);
31 tVFS_NodeType   gMouse_RootNodeType = {
32         .ReadDir = Mouse_Root_ReadDir,
33         .FindDir = Mouse_Root_FindDir
34 };
35 tVFS_NodeType   gMouse_DevNodeType = {
36         .IOCtl = Mouse_Dev_IOCtl,
37         .Read = Mouse_Dev_Read
38 };
39 tDevFS_Driver   gMouse_DevInfo = {
40         NULL, "Mouse",
41         { .Flags = VFS_FFLAG_DIRECTORY, .Type = &gMouse_RootNodeType, .Size = 1 }
42 };
43 tPointer        gMouse_Pointer;
44
45 // === CODE ===
46 /**
47  * \brief Initialise the keyboard driver
48  */
49 int Mouse_Install(char **Arguments)
50 {
51         /// - Register with DevFS
52         DevFS_AddDevice( &gMouse_DevInfo );
53
54         gMouse_Pointer.Node.Type = &gMouse_DevNodeType;
55         gMouse_Pointer.Node.ImplPtr = &gMouse_Pointer;
56         gMouse_Pointer.FileHeader = (void*)gMouse_Pointer.FileData;
57         gMouse_Pointer.Axies = (void*)( gMouse_Pointer.FileHeader + 1 );
58
59         return 0;
60 }
61
62 /**
63  * \brief Pre-unload cleanup function
64  */
65 int Mouse_Cleanup(void)
66 {
67         return 0;
68 }
69
70 // --- VFS Interface ---
71 char *Mouse_Root_ReadDir(tVFS_Node *Node, int Pos)
72 {
73         if( Pos != 0 )  return NULL;
74         return strdup("system");
75 }
76
77 tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
78 {
79         if( strcmp(Name, "system") != 0 )       return NULL;
80         return &gMouse_Pointer.Node;
81 }
82
83 static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
84 /**
85  * \brief IOCtl handler for the mouse
86  */
87 int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data)
88 {
89         tJoystick_NumValue      *numval = Data;
90         tPointer        *ptr = Node->ImplPtr;
91         switch(ID)
92         {
93         BASE_IOCTLS(DRV_TYPE_MOUSE, "Mouse", VERSION, csaIOCTL_NAMES);
94
95         case JOY_IOCTL_GETSETAXISLIMIT:
96                 if( !numval || !CheckMem(numval, sizeof(*numval)) )
97                         return -1;
98                 LOG("GetSetAxisLimit %i = %i", numval->Num, numval->Value);
99                 if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
100                         return 0;
101                 if(numval->Value != -1)
102                         ptr->AxisLimits[numval->Num] = numval->Value;
103                 return ptr->AxisLimits[numval->Num];
104
105         case JOY_IOCTL_GETSETAXISPOSITION:
106                 if( !numval || !CheckMem(numval, sizeof(*numval)) )
107                         return -1;
108                 if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
109                         return 0;
110                 if(numval->Value != -1)
111                         ptr->Axies[numval->Num].CursorPos = numval->Value;
112                 return ptr->Axies[numval->Num].CursorPos;
113         }
114         return -1;
115 }
116
117 /**
118  * \brief Read from a device
119  */
120 size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data)
121 {
122         tPointer *ptr = Node->ImplPtr;
123          int    n_buttons = ptr->FileHeader->NButtons;
124          int    n_axies = ptr->FileHeader->NAxies;
125
126         ENTER("pNode iLength pData", Node, Length, Data);
127
128         // TODO: Locking (Acquire)
129
130         Length = MIN(
131                 Length, 
132                 sizeof(tJoystick_FileHeader) + n_axies*sizeof(tJoystick_Axis) + n_buttons
133                 );
134
135         // Mark as checked
136         VFS_MarkAvaliable( Node, 0 );
137
138         // Check if more than the header is requested
139         if( Length > sizeof(tJoystick_FileHeader) )
140         {
141                 // Clear axis values and button states
142                 for( int i = 0; i < n_axies; i ++ )
143                         ptr->Axies[i].CurValue = 0;
144                 for( int i = 0; i < n_buttons; i ++ )
145                         ptr->Buttons[i] = 0;
146
147                 // Rebuild from device list
148                 for( tMouse *dev = ptr->FirstDev; dev; dev = dev->Next )
149                 {
150                         for( int i = 0; i < n_axies; i ++ )
151                                 ptr->Axies[i].CurValue += dev->LastAxisVal[i];
152                         for( int i = 0; i < n_buttons; i ++ )
153                         {
154                                 if( dev->ButtonState & (1 << i) )
155                                         ptr->Buttons[i] = 255;
156                         }
157                 }
158         }
159
160         memcpy( Data, ptr->FileData, Length );
161
162         // TODO: Locking (Release)
163
164         LEAVE('i', Length);
165         return Length;
166 }
167
168 // --- Device Interface ---
169 /*
170  * Register an input device
171  * - See Input/Mouse/include/mouse.h
172  */
173 tMouse *Mouse_Register(const char *Name, int NumButtons, int NumAxies)
174 {
175         tPointer *target;
176         tMouse   *ret;
177
178         // TODO: Multiple pointers?
179         target = &gMouse_Pointer;
180
181         if( NumButtons > MAX_BUTTONS )
182                 NumButtons = MAX_BUTTONS;
183         if( NumAxies > MAX_AXIES )
184                 NumAxies = MAX_AXIES;
185
186         ret = malloc( sizeof(tMouse) + sizeof(ret->LastAxisVal[0])*NumAxies );
187         if(!ret) {
188                 Log_Error("Mouse", "malloc() failed");
189                 return NULL;
190         }
191         ret->Next = NULL;
192         ret->Pointer = target;
193         ret->NumAxies = NumAxies;
194         ret->NumButtons = NumButtons;
195         ret->ButtonState = 0;
196         memset(ret->LastAxisVal, 0, sizeof(ret->LastAxisVal[0])*NumAxies );
197
198         // Add
199         // TODO: Locking
200         ret->Next = target->FirstDev;
201         target->FirstDev = ret;
202         if( ret->NumAxies > target->FileHeader->NAxies ) {
203                 // Clear new axis data
204                 memset(
205                         target->Axies + target->FileHeader->NAxies,
206                         0,
207                         (ret->NumAxies - target->FileHeader->NAxies)/sizeof(tJoystick_Axis)
208                         );
209                 target->FileHeader->NAxies = ret->NumAxies;
210                 target->Buttons = (void*)( target->Axies + ret->NumAxies );
211         }
212         if( ret->NumButtons > target->FileHeader->NButtons ) {
213                 // No need to move as buttons can expand out into space
214                 target->FileHeader->NButtons = ret->NumButtons;
215         }
216         // TODO: Locking
217
218         return ret;
219 }
220
221 /*
222  * Remove a mouse instance
223  * - See Input/Mouse/include/mouse.h
224  */
225 void Mouse_RemoveInstance(tMouse *Instance)
226 {
227 }
228
229 /*
230  * Handle a mouse event (movement or button press/release)
231  * - See Input/Mouse/include/mouse.h
232  */
233 void Mouse_HandleEvent(tMouse *Handle, Uint32 ButtonState, int *AxisDeltas)
234 {
235         tPointer *ptr;
236         
237         ENTER("pHandle xButtonState pAxisDeltas", Handle, ButtonState, AxisDeltas);
238
239         ptr = Handle->Pointer;
240
241         // Update device state
242         Handle->ButtonState = ButtonState;
243         memcpy(Handle->LastAxisVal, AxisDeltas, sizeof(*AxisDeltas)*Handle->NumAxies);
244
245         // Update cursor position
246         // TODO: Acceleration?
247         for( int i = 0; i < Handle->NumAxies; i ++ )
248         {
249                 ptr->Axies[i].CursorPos = MIN(MAX(0, ptr->Axies[i].CursorPos+AxisDeltas[i]), ptr->AxisLimits[i]);
250                 LOG("Axis %i: delta = %i, pos = %i", i, AxisDeltas[i], ptr->Axies[i].CursorPos);
251         }
252
253         VFS_MarkAvaliable( &ptr->Node, 1 );
254         LEAVE('-');
255 }
256

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