Modules - Implementing mouse multiplexer
[tpg/acess2.git] / KernelLand / Modules / USB / HID / keyboard.c
1 /*
2  * Acess2 USB Stack HID Driver
3  * - By John Hodge (thePowersGang)
4  *
5  * keyboard.c
6  * - Keyboard translation
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include <fs_devfs.h>
11 #include "hid_reports.h"
12 #include <Input/Keyboard/include/keyboard.h>
13
14 typedef struct sUSB_Keyboard    tUSB_Keyboard;
15
16 // === STRUCTURES ===
17 struct sUSB_Keyboard
18 {
19         void    *Next;  // Is this needed? (I think main.c wants it)
20         tUSB_DataCallback       DataAvail;
21         
22         tKeyboard *Info;
23          int    bIsBoot;
24         
25         // Boot keyboard hackery
26         Uint8   oldmods;
27         Uint8   oldkeys[6];
28         
29          int    CollectionDepth;
30 };
31
32 // === PROTOTYPES ===
33 void    HID_Kb_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data);
34
35 tHID_ReportCallbacks    *HID_Kb_Report_Collection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
36 void    HID_Kb_Report_EndCollection(tUSBInterface *Dev);
37 void    HID_Kb_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
38
39 // === GLOBALS ===
40 tHID_ReportCallbacks    gHID_Kb_ReportCBs = {
41         .Collection = HID_Kb_Report_Collection,
42         .EndCollection = HID_Kb_Report_EndCollection,
43         .Input = HID_Kb_Report_Input
44 };
45
46 // === CODE ===
47 void HID_Kb_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
48 {
49         tUSB_Keyboard   *info;
50         info = USB_GetDeviceDataPtr(Dev);
51
52         LOG("info = %p", info);
53         
54         if( info->bIsBoot )
55         {
56                 Uint8   *bytes = Data;
57                 Uint8   modchange = bytes[0] ^ info->oldmods;
58                 LOG("modchange = %x", modchange);
59                 // Modifiers
60                 const int firstmod = 224;       // from qemu
61                 for( int i = 0; i < 8; i ++ )
62                 {
63                         if( !(modchange & (1 << i)) )   continue ;
64                         if( bytes[0] & (1 << i) ) {
65                                 LOG("mod press %i", firstmod+i);
66                                 Keyboard_HandleKey(info->Info, firstmod + i);
67                         }
68                         else {
69                                 LOG("mod release %i", firstmod+i);
70                                 Keyboard_HandleKey(info->Info, (1 << 31)|(firstmod + i));
71                         }
72                 }
73                 info->oldmods = bytes[0];
74                 
75                 // Keycodes
76                 // - Presses
77                 for( int i = 0; i < 6; i ++ )
78                 {
79                          int    j;
80                         Uint8   code = bytes[2+i];
81                         // Check if the button was pressed before
82                         for( j = 0; j < 6; j ++ )
83                         {
84                                 if( info->oldkeys[j] == code )
85                                 {
86                                         info->oldkeys[j] = 0;
87                                         break;
88                                 }
89                         }
90                         // Press?
91                         if( j == 6 ) {
92                                 LOG("press %i", code);
93                                 Keyboard_HandleKey(info->Info, (0 << 31)|code);
94                         }
95                 }
96                 // - Check for releases
97                 for( int i = 0; i < 6; i ++ )
98                 {
99                         if( info->oldkeys[i] ) {
100                                 LOG("release %i", info->oldkeys[i]);
101                                 Keyboard_HandleKey(info->Info, (1 << 31)|info->oldkeys[i]);
102                         }
103                 }
104                 // - Update state
105                 memcpy(info->oldkeys, bytes+2, 6);
106         }
107         else
108         {
109                 // Oops... TODO: Support non boot keyboards
110         }
111 }
112
113 // --- ---
114 tHID_ReportCallbacks *HID_Kb_Report_Collection(
115         tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
116         Uint32 Value
117         )
118 {
119         return &gHID_Kb_ReportCBs;
120 }
121
122 void HID_Kb_Report_EndCollection(tUSBInterface *Dev)
123 {
124 }
125
126 void HID_Kb_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value)
127 {
128         tUSB_Keyboard   *info;
129
130         info = USB_GetDeviceDataPtr(Dev);
131         if( !info )
132         {
133                 info = malloc( sizeof(tUSB_Keyboard) );
134                 LOG("info = %p", info);
135                 USB_SetDeviceDataPtr(Dev, info);
136                 info->DataAvail = HID_Kb_DataAvail;
137                 info->Info = NULL;
138                 info->CollectionDepth = 1;
139                 info->bIsBoot = 1;      // TODO: Detect non-boot keyboards and parse descriptor
140                 Log_Warning("USB HID", "TODO: Handle non-boot keyboards!");
141                 info->Info = Keyboard_CreateInstance(0, "USBKeyboard");
142         }
143 }
144

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