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

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