Rev 5148 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5148 | hidnplayr | 1 | ; HID multimedia keyboard driver, part of USBHID driver. |
2 | |||
3 | ; Global constants. |
||
4 | ; They are assembled in a macro to separate code and data; |
||
5 | ; the code is located at the point of "include 'multimedia.inc'", |
||
6 | ; the data are collected when workers_globals is instantiated. |
||
7 | macro workers_globals |
||
8 | { |
||
9 | ; include global constants from previous workers |
||
10 | workers_globals |
||
11 | align 4 |
||
12 | ; Callbacks for HID layer. |
||
13 | multimedia_driver: |
||
14 | dd multimedia_driver_add_device |
||
15 | dd multimedia_driver_disconnect |
||
16 | dd multimedia_driver_begin_packet |
||
17 | dd multimedia_driver_array_overflow? |
||
18 | dd multimedia_driver_input_field |
||
19 | dd multimedia_driver_end_packet |
||
20 | } |
||
21 | |||
22 | ; Data that are specific for one keyboard device. |
||
23 | struct multimedia_device_data |
||
24 | usbdev dd ? ; pointer to device_data of USB and HID layers |
||
25 | last_pressed dd ? |
||
26 | ends |
||
27 | |||
28 | ; This procedure is called when HID layer detects a new keyboard. |
||
29 | ; in: ebx -> usb_device_data, edi -> collection |
||
30 | ; out: eax = device-specific data or NULL on error |
||
31 | proc multimedia_driver_add_device |
||
32 | ; 1. Allocate memory for keyboard_device_data. If failed, return NULL. |
||
33 | movi eax, sizeof.multimedia_device_data |
||
34 | invoke Kmalloc |
||
35 | test eax, eax |
||
36 | jz .nothing |
||
37 | ; 2. Initialize keyboard_device_data: store pointer to USB layer data, |
||
38 | ; zero some fields, initialize bit positions to -1. |
||
39 | mov [eax+multimedia_device_data.usbdev], ebx |
||
40 | mov [eax+multimedia_device_data.last_pressed], 0 |
||
41 | .nothing: |
||
42 | ret |
||
43 | endp |
||
44 | |||
45 | ; This procedure is called when HID layer detects disconnect of a previously |
||
46 | ; connected keyboard. |
||
47 | ; in: edi -> multimedia_device_data (pointer returned from multimedia_driver_add_device) |
||
48 | proc multimedia_driver_disconnect |
||
49 | ; We should free data in CloseKeyboard, not here. |
||
50 | ret |
||
51 | endp |
||
52 | |||
53 | ; This procedure is called when HID layer starts processing a new input packet |
||
54 | ; from a keyboard. |
||
55 | ; in: edi -> keyboard_device_data (pointer returned from keyboard_driver_add_device) |
||
56 | proc multimedia_driver_begin_packet |
||
57 | ; Nothing to do. |
||
58 | ret |
||
59 | endp |
||
60 | |||
61 | ; This procedure is called when HID layer processes every non-empty array field group. |
||
62 | ; in: edi -> keyboard_device_data (pointer returned from keyboard_driver_add_device) |
||
63 | ; in: ecx = fields count (always nonzero), edx = pointer to fields values |
||
64 | ; in: esi -> report_field_group |
||
65 | ; out: CF set => group is ok, CF cleared => group should be ignored |
||
66 | proc multimedia_driver_array_overflow? |
||
67 | ; The keyboard signals array overflow by filling the entire array with |
||
68 | ; USAGE_KBD_ROLLOVER codes. |
||
69 | mov eax, [edx] ; eax = first field in the array |
||
70 | sub eax, USAGE_KBD_ROLLOVER ; eax = 0 if overflow, nonzero otherwise |
||
71 | neg eax ; CF cleared if eax was zero, CF set if eax was nonzero |
||
72 | ret |
||
73 | endp |
||
74 | |||
75 | ; This procedure is called from HID layer for every field. |
||
76 | ; in: edi -> keyboard_device_data (pointer returned from keyboard_driver_add_device) |
||
77 | ; in: ecx = field usage, edx = value, esi -> report_field_group |
||
78 | proc multimedia_driver_input_field |
||
79 | if HID_DUMP_UNCLAIMED |
||
80 | .unclaimed = default_driver_input_field |
||
81 | end if |
||
82 | |||
83 | test edx, edx |
||
84 | jnz @f |
||
85 | cmp [edi+multimedia_device_data.last_pressed], ecx |
||
86 | jne .nothing |
||
87 | @@: |
||
88 | mov eax, 0x19 |
||
89 | cmp ecx, USAGE_CONSUMER + 0xB5 ; Next track |
||
90 | je .multimedia_key |
||
91 | mov al, 0x10 |
||
92 | cmp ecx, USAGE_CONSUMER + 0xB6 ; Previous track |
||
93 | je .multimedia_key |
||
94 | mov al, 0x24 |
||
95 | cmp ecx, USAGE_CONSUMER + 0xB7 ; Stop |
||
96 | je .multimedia_key |
||
97 | mov al, 0x22 |
||
98 | cmp ecx, USAGE_CONSUMER + 0xCD ; Play/pause |
||
99 | je .multimedia_key |
||
100 | mov al, 0x20 |
||
101 | cmp ecx, USAGE_CONSUMER + 0xE2 ; Mute |
||
102 | je .multimedia_key |
||
103 | mov al, 0x30 |
||
104 | cmp ecx, USAGE_CONSUMER + 0xE9 ; Volume up |
||
105 | je .multimedia_key |
||
106 | mov al, 0x2E |
||
107 | cmp ecx, USAGE_CONSUMER + 0xEA ; Volume down |
||
108 | je .multimedia_key |
||
109 | mov al, 0x6D |
||
110 | cmp ecx, USAGE_CONSUMER + 0x183 ; Media select |
||
111 | je .multimedia_key |
||
112 | mov al, 0x6C |
||
113 | cmp ecx, USAGE_CONSUMER + 0x18A ; E-Mail |
||
114 | je .multimedia_key |
||
115 | mov al, 0x21 |
||
116 | cmp ecx, USAGE_CONSUMER + 0x192 ; Calculator |
||
117 | je .multimedia_key |
||
118 | mov al, 0x6B |
||
119 | cmp ecx, USAGE_CONSUMER + 0x194 ; My computer |
||
120 | je .multimedia_key |
||
121 | mov al, 0x65 |
||
122 | cmp ecx, USAGE_CONSUMER + 0x221 ; WWW Search |
||
123 | je .multimedia_key |
||
124 | mov al, 0x32 |
||
125 | cmp ecx, USAGE_CONSUMER + 0x223 ; WWW Home |
||
126 | je .multimedia_key |
||
127 | mov al, 0x6a |
||
128 | cmp ecx, USAGE_CONSUMER + 0x224 ; WWW Back |
||
129 | je .multimedia_key |
||
130 | mov al, 0x69 |
||
131 | cmp ecx, USAGE_CONSUMER + 0x225 ; WWW forward |
||
132 | je .multimedia_key |
||
133 | mov al, 0x68 |
||
134 | cmp ecx, USAGE_CONSUMER + 0x226 ; WWW Stop |
||
135 | je .multimedia_key |
||
136 | mov al, 0x67 |
||
137 | cmp ecx, USAGE_CONSUMER + 0x227 ; WWW refresh |
||
138 | je .multimedia_key |
||
139 | mov al, 0x66 |
||
140 | cmp ecx, USAGE_CONSUMER + 0x22A ; WWW favorites |
||
141 | je .multimedia_key |
||
142 | jmp .unclaimed |
||
143 | |||
144 | |||
145 | .multimedia_key: |
||
146 | ; 1d. Further actions are slightly different for key press and key release. |
||
147 | ; Decide what to do. |
||
148 | test edx, edx |
||
149 | jz .multimedia_key_released |
||
150 | .multimedia_key_pressed: |
||
5294 | hidnplayr | 151 | mov [edi+multimedia_device_data.last_pressed], eax |
5148 | hidnplayr | 152 | ; The key is pressed. |
5294 | hidnplayr | 153 | push eax |
5148 | hidnplayr | 154 | mov ecx, 0xE0 |
155 | invoke SetKeyboardData |
||
156 | pop ecx |
||
157 | invoke SetKeyboardData |
||
158 | ret |
||
159 | |||
160 | .multimedia_key_released: |
||
161 | mov [edi+multimedia_device_data.last_pressed], 0 |
||
162 | ; The key is released. |
||
163 | or cl, 0x80 |
||
5294 | hidnplayr | 164 | push eax |
5148 | hidnplayr | 165 | mov ecx, 0xE0 |
166 | invoke SetKeyboardData |
||
167 | pop ecx |
||
168 | invoke SetKeyboardData |
||
169 | ret |
||
170 | .nothing: |
||
171 | ret |
||
172 | |||
173 | endp |
||
174 | |||
175 | ; This procedure is called when HID layer ends processing a new input packet |
||
176 | ; from a keyboard. |
||
177 | ; in: edi -> keyboard_device_data (pointer returned from keyboard_driver_add_device) |
||
178 | proc multimedia_driver_end_packet |
||
179 | ; Nothing to do. |
||
180 | ret |
||
181 | endp |