25185a2d5617704a310e4f3cca28afad4319a333
[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  int    Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
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 int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
72 {
73         if( Pos != 0 )
74                 return -EINVAL;
75         strcpy(Dest, "system");
76         return 0;
77 }
78
79 tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
80 {
81         if( strcmp(Name, "system") != 0 )       return NULL;
82         return &gMouse_Pointer.Node;
83 }
84
85 static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
86 /**
87  * \brief IOCtl handler for the mouse
88  */
89 int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data)
90 {
91         tJoystick_NumValue      *numval = Data;
92         tPointer        *ptr = Node->ImplPtr;
93         switch(ID)
94         {
95         BASE_IOCTLS(DRV_TYPE_MOUSE, "Mouse", VERSION, csaIOCTL_NAMES);
96
97         case JOY_IOCTL_GETSETAXISLIMIT:
98                 if( !numval || !CheckMem(numval, sizeof(*numval)) )
99                         return -1;
100                 LOG("GetSetAxisLimit %i = %i", numval->Num, numval->Value);
101                 if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
102                         return 0;
103                 if(numval->Value != -1)
104                         ptr->AxisLimits[numval->Num] = numval->Value;
105                 return ptr->AxisLimits[numval->Num];
106
107         case JOY_IOCTL_GETSETAXISPOSITION:
108                 if( !numval || !CheckMem(numval, sizeof(*numval)) )
109                         return -1;
110                 if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
111                         return 0;
112                 if(numval->Value != -1)
113                         ptr->Axies[numval->Num].CursorPos = numval->Value;
114                 return ptr->Axies[numval->Num].CursorPos;
115         }
116         return -1;
117 }
118
119 /**
120  * \brief Read from a device
121  */
122 size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data)
123 {
124         tPointer *ptr = Node->ImplPtr;
125          int    n_buttons = ptr->FileHeader->NButtons;
126          int    n_axies = ptr->FileHeader->NAxies;
127
128         ENTER("pNode iLength pData", Node, Length, Data);
129
130         // TODO: Locking (Acquire)
131
132         Length = MIN(
133                 Length, 
134                 sizeof(tJoystick_FileHeader) + n_axies*sizeof(tJoystick_Axis) + n_buttons
135                 );
136
137         // Mark as checked
138         VFS_MarkAvaliable( Node, 0 );
139
140         // Check if more than the header is requested
141         if( Length > sizeof(tJoystick_FileHeader) )
142         {
143                 // Clear axis values and button states
144                 for( int i = 0; i < n_axies; i ++ )
145                         ptr->Axies[i].CurValue = 0;
146                 for( int i = 0; i < n_buttons; i ++ )
147                         ptr->Buttons[i] = 0;
148
149                 // Rebuild from device list
150                 for( tMouse *dev = ptr->FirstDev; dev; dev = dev->Next )
151                 {
152                         for( int i = 0; i < n_axies; i ++ )
153                                 ptr->Axies[i].CurValue += dev->LastAxisVal[i];
154                         for( int i = 0; i < n_buttons; i ++ )
155                         {
156                                 if( dev->ButtonState & (1 << i) )
157                                         ptr->Buttons[i] = 255;
158                         }
159                 }
160         }
161
162         memcpy( Data, ptr->FileData, Length );
163
164         // TODO: Locking (Release)
165
166         LEAVE('i', Length);
167         return Length;
168 }
169
170 // --- Device Interface ---
171 /*
172  * Register an input device
173  * - See Input/Mouse/include/mouse.h
174  */
175 tMouse *Mouse_Register(const char *Name, int NumButtons, int NumAxies)
176 {
177         tPointer *target;
178         tMouse   *ret;
179
180         // TODO: Multiple pointers?
181         target = &gMouse_Pointer;
182
183         if( NumButtons > MAX_BUTTONS )
184                 NumButtons = MAX_BUTTONS;
185         if( NumAxies > MAX_AXIES )
186                 NumAxies = MAX_AXIES;
187
188         ret = malloc( sizeof(tMouse) + sizeof(ret->LastAxisVal[0])*NumAxies );
189         if(!ret) {
190                 Log_Error("Mouse", "malloc() failed");
191                 return NULL;
192         }
193         ret->Next = NULL;
194         ret->Pointer = target;
195         ret->NumAxies = NumAxies;
196         ret->NumButtons = NumButtons;
197         ret->ButtonState = 0;
198         memset(ret->LastAxisVal, 0, sizeof(ret->LastAxisVal[0])*NumAxies );
199
200         // Add
201         // TODO: Locking
202         ret->Next = target->FirstDev;
203         target->FirstDev = ret;
204         if( ret->NumAxies > target->FileHeader->NAxies ) {
205                 // Clear new axis data
206                 memset(
207                         target->Axies + target->FileHeader->NAxies,
208                         0,
209                         (ret->NumAxies - target->FileHeader->NAxies)/sizeof(tJoystick_Axis)
210                         );
211                 target->FileHeader->NAxies = ret->NumAxies;
212                 target->Buttons = (void*)( target->Axies + ret->NumAxies );
213         }
214         if( ret->NumButtons > target->FileHeader->NButtons ) {
215                 // No need to move as buttons can expand out into space
216                 target->FileHeader->NButtons = ret->NumButtons;
217         }
218         // TODO: Locking
219
220         return ret;
221 }
222
223 /*
224  * Remove a mouse instance
225  * - See Input/Mouse/include/mouse.h
226  */
227 void Mouse_RemoveInstance(tMouse *Instance)
228 {
229 }
230
231 /*
232  * Handle a mouse event (movement or button press/release)
233  * - See Input/Mouse/include/mouse.h
234  */
235 void Mouse_HandleEvent(tMouse *Handle, Uint32 ButtonState, int *AxisDeltas)
236 {
237         tPointer *ptr;
238         
239         ENTER("pHandle xButtonState pAxisDeltas", Handle, ButtonState, AxisDeltas);
240
241         ptr = Handle->Pointer;
242
243         // Update device state
244         Handle->ButtonState = ButtonState;
245         memcpy(Handle->LastAxisVal, AxisDeltas, sizeof(*AxisDeltas)*Handle->NumAxies);
246
247         // Update cursor position
248         // TODO: Acceleration?
249         for( int i = 0; i < Handle->NumAxies; i ++ )
250         {
251                 ptr->Axies[i].CursorPos = MIN(MAX(0, ptr->Axies[i].CursorPos+AxisDeltas[i]), ptr->AxisLimits[i]);
252                 LOG("Axis %i: delta = %i, pos = %i", i, AxisDeltas[i], ptr->Axies[i].CursorPos);
253         }
254
255         VFS_MarkAvaliable( &ptr->Node, 1 );
256         LEAVE('-');
257 }
258

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