Subversion Repositories Kolibri OS

Rev

Rev 3520 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3520 clevermous 1
; standard driver stuff
2
format MS COFF
3
 
4
DEBUG = 1
5
 
6
; this is for DEBUGF macro from 'fdo.inc'
7
__DEBUG__ = 1
8
__DEBUG_LEVEL__ = 1
9
 
10
include 'proc32.inc'
11
include 'imports.inc'
12
include 'fdo.inc'
13
 
14
public START
15
public version
16
 
17
; USB constants
18
DEVICE_DESCR_TYPE = 1
19
CONFIG_DESCR_TYPE = 2
20
STRING_DESCR_TYPE = 3
21
INTERFACE_DESCR_TYPE = 4
22
ENDPOINT_DESCR_TYPE = 5
23
DEVICE_QUALIFIER_DESCR_TYPE = 6
24
 
25
CONTROL_PIPE = 0
26
ISOCHRONOUS_PIPE = 1
27
BULK_PIPE = 2
28
INTERRUPT_PIPE = 3
29
 
30
; USB structures
31
virtual at 0
32
config_descr:
33
.bLength                db      ?
34
.bDescriptorType        db      ?
35
.wTotalLength           dw      ?
36
.bNumInterfaces         db      ?
37
.bConfigurationValue    db      ?
38
.iConfiguration         db      ?
39
.bmAttributes           db      ?
40
.bMaxPower              db      ?
41
.sizeof:
42
end virtual
43
 
44
virtual at 0
45
interface_descr:
46
.bLength                db      ?
47
.bDescriptorType        db      ?
48
.bInterfaceNumber       db      ?
49
.bAlternateSetting      db      ?
50
.bNumEndpoints          db      ?
51
.bInterfaceClass        db      ?
52
.bInterfaceSubClass     db      ?
53
.bInterfaceProtocol     db      ?
54
.iInterface             db      ?
55
.sizeof:
56
end virtual
57
 
58
virtual at 0
59
endpoint_descr:
60
.bLength                db      ?
61
.bDescriptorType        db      ?
62
.bEndpointAddress       db      ?
63
.bmAttributes           db      ?
64
.wMaxPacketSize         dw      ?
65
.bInterval              db      ?
66
.sizeof:
67
end virtual
68
 
69
; Driver data for all devices
70
virtual at 0
71
device_data:
72
.type           dd      ?       ; 1 = keyboard, 2 = mouse
73
.intpipe        dd      ?       ; interrupt pipe handle
74
.packetsize     dd      ?
75
.packet         rb      8       ; packet with data from device
76
.control        rb      8       ; control packet to device
77
.sizeof:
78
end virtual
79
 
80
; Driver data for mouse
81
virtual at device_data.sizeof
82
mouse_data:
83
; no additional data
84
.sizeof:
85
end virtual
86
 
87
; Driver data for keyboard
88
virtual at device_data.sizeof
89
keyboard_data:
90
.handle         dd      ?       ; keyboard handle from RegKeyboard
91
.configpipe     dd      ?       ; config pipe handle
92
.prevpacket     rb      8       ; previous packet with data from device
93
.timer          dd      ?       ; auto-repeat timer handle
94
.repeatkey      db      ?       ; auto-repeat key code
95
.ledstate       db      ?       ; state of LEDs
96
                align 4
97
.sizeof:
98
end virtual
99
 
100
section '.flat' code readable align 16
101
; The start procedure.
102
START:
103
; 1. Test whether the procedure is called with the argument DRV_ENTRY.
104
; If not, return 0.
105
        xor     eax, eax        ; initialize return value
106
        cmp     dword [esp+4], 1        ; compare the argument
107
        jnz     .nothing
108
; 2. Register self as a USB driver.
109
; The name is my_driver = 'usbhid'; IOCTL interface is not supported;
110
; usb_functions is an offset of a structure with callback functions.
111
        stdcall RegUSBDriver, my_driver, eax, usb_functions
112
; 3. Return the returned value of RegUSBDriver.
113
.nothing:
114
        ret     4
115
 
116
; This procedure is called when new HID device is detected.
117
; It initializes the device.
118
AddDevice:
119
; Arguments are addressed through esp. In this point of the function,
120
; [esp+4] = a handle of the config pipe, [esp+8] points to config_descr
121
; structure, [esp+12] points to interface_descr structure.
122
; 1. Check device type. Currently only mice and keyboards with
123
; boot protocol are supported.
124
; 1a. Get the subclass and the protocol. Since bInterfaceSubClass and
125
; bInterfaceProtocol are subsequent in interface_descr, just one
126
; memory reference is used for both.
127
        mov     edx, [esp+12]
128
        push    ebx     ; save used register to be stdcall
129
        mov     cx, word [edx+interface_descr.bInterfaceSubClass]
130
; 1b. For boot protocol, subclass must be 1 and protocol must be either 1 for
131
; a keyboard or 2 for a mouse. Check.
132
        cmp     cx, 0x0101
133
        jz      .keyboard
134
        cmp     cx, 0x0201
135
        jz      .mouse
136
; 1c. If the device is neither a keyboard nor a mouse, print a message and
137
; go to 6c.
138
        DEBUGF 1,'K : unknown HID device\n'
139
        jmp     .nothing
140
; 1d. If the device is a keyboard or a mouse, print a message and continue
141
; configuring.
142
.keyboard:
143
        DEBUGF 1,'K : USB keyboard detected\n'
144
        push    keyboard_data.sizeof
145
        jmp     .common
146
.mouse:
147
        DEBUGF 1,'K : USB mouse detected\n'
148
        push    mouse_data.sizeof
149
.common:
150
; 2. Allocate memory for device data.
151
        pop     eax     ; get size of device data
152
; 2a. Call the kernel, saving and restoring register edx.
153
        push    edx
154
        call    Kmalloc
155
        pop     edx
156
; 2b. Check result. If failed, say a message and go to 6c.
157
        test    eax, eax
158
        jnz     @f
159
        DEBUGF 1,'K : no memory\n'
160
        jmp     .nothing
161
@@:
162
        xchg    eax, ebx
163
; HID devices use one IN interrupt endpoint for polling the device
164
; and an optional OUT interrupt endpoint. We do not use the later,
165
; but must locate the first. Look for the IN interrupt endpoint.
166
; 3. Get the upper bound of all descriptors' data.
167
        mov     eax, [esp+8+4]  ; configuration descriptor
168
        movzx   ecx, [eax+config_descr.wTotalLength]
169
        add     eax, ecx
170
; 4. Loop over all descriptors until
171
; either end-of-data reached - this is fail
172
; or interface descriptor found - this is fail, all further data
173
;    correspond to that interface
174
; or endpoint descriptor found.
175
; 4a. Loop start: eax points to the interface descriptor.
176
.lookep:
177
; 4b. Get next descriptor.
178
        movzx   ecx, byte [edx] ; the first byte of all descriptors is length
179
        add     edx, ecx
180
; 4c. Check that at least two bytes are readable. The opposite is an error.
181
        inc     edx
182
        cmp     edx, eax
183
        jae     .errorep
184
        dec     edx
185
; 4d. Check that this descriptor is not interface descriptor. The opposite is
186
; an error.
187
        cmp     byte [edx+endpoint_descr.bDescriptorType], INTERFACE_DESCR_TYPE
188
        jz      .errorep
189
; 4e. Test whether this descriptor is an endpoint descriptor. If not, continue
190
; the loop.
191
        cmp     byte [edx+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE
192
        jnz     .lookep
193
; 5. Check that the descriptor contains all required data and all data are
194
; readable. If so, proceed to 7.
195
        cmp     byte [edx+endpoint_descr.bLength], endpoint_descr.sizeof
196
        jb      .errorep
197
        sub     eax, endpoint_descr.sizeof
198
        cmp     edx, eax
199
        jbe     @f
200
; 6. An error occured during processing endpoint descriptor.
201
.errorep:
202
; 6a. Print a message.
203
        DEBUGF 1,'K : error: invalid endpoint descriptor\n'
204
; 6b. Free memory allocated for device data.
205
.free:
206
        xchg    eax, ebx
207
        call    Kfree
208
.nothing:
209
; 6c. Return an error.
210
        xor     eax, eax
211
        pop     ebx
212
        ret     12
213
@@:
214
; 7. Check that the endpoint is IN interrupt endpoint. If not, go to 6.
215
        test    [edx+endpoint_descr.bEndpointAddress], 80h
216
        jz      .errorep
217
        mov     cl, [edx+endpoint_descr.bmAttributes]
218
        and     cl, 3
219
        cmp     cl, INTERRUPT_PIPE
220
        jnz     .errorep
221
; 8. Open pipe for the endpoint.
222
; 8a. Load parameters from the descriptor.
223
        movzx   ecx, [edx+endpoint_descr.bEndpointAddress]
224
        movzx   eax, [edx+endpoint_descr.bInterval]
225
        movzx   edx, [edx+endpoint_descr.wMaxPacketSize]
226
; 8b. Call the kernel, saving and restoring edx.
227
        push    edx
228
        stdcall USBOpenPipe, [esp+4+24], ecx, edx, INTERRUPT_PIPE, eax
229
        pop     edx
230
; 8c. Check result. If failed, go to 6b.
231
        test    eax, eax
232
        jz      .free
233
; We use 12 bytes for device type, interrupt pipe and interrupt packet size,
234
; 8 bytes for a packet and 8 bytes for previous packet, used by a keyboard.
235
; 9. Initialize device data.
236
        mov     [ebx+device_data.intpipe], eax
3598 clevermous 237
        movi    ecx, 8
3520 clevermous 238
        cmp     edx, ecx
239
        jb      @f
240
        mov     edx, ecx
241
@@:
242
        xor     eax, eax
243
        mov     [ebx+device_data.packetsize], edx
244
        mov     dword [ebx+device_data.packet], eax
245
        mov     dword [ebx+device_data.packet+4], eax
246
        mov     edx, [esp+12+4] ; interface descriptor
247
        movzx   ecx, [edx+interface_descr.bInterfaceProtocol]
248
        mov     [ebx+device_data.type], ecx
249
        cmp     ecx, 1
250
        jnz     @f
251
        mov     [ebx+keyboard_data.handle], eax
252
        mov     [ebx+keyboard_data.timer], eax
253
        mov     [ebx+keyboard_data.repeatkey], al
254
        mov     dword [ebx+keyboard_data.prevpacket], eax
255
        mov     dword [ebx+keyboard_data.prevpacket+4], eax
256
        mov     eax, [esp+4+4]
257
        mov     [ebx+keyboard_data.configpipe], eax
258
@@:
259
; 10. Send the control packet SET_PROTOCOL(Boot Protocol) to the interface.
260
        lea     eax, [ebx+device_data.control]
261
        mov     dword [eax], 21h + (0Bh shl 8) + (0 shl 16)     ; class request to interface + SET_PROTOCOL + Boot protocol
262
        and     dword [eax+4], 0
263
        mov     dl, [edx+interface_descr.bInterfaceNumber]
264
        mov     [eax+4], dl
265
; Callback function is mouse_configured for mice and keyboard_configured1 for keyboards.
266
        mov     edx, keyboard_configured1
267
        cmp     ecx, 1
268
        jz      @f
269
        mov     edx, mouse_configured
270
@@:
271
        stdcall USBControlTransferAsync, [esp+4+28], eax, 0, 0, edx, ebx, 0
272
; 11. Return with pointer to device data as returned value.
273
        xchg    eax, ebx
274
        pop     ebx
275
        ret     12
276
 
277
; This function is called when SET_PROTOCOL command for keyboard is done,
278
; either successful or unsuccessful.
279
keyboard_configured1:
280
        xor     edx, edx
281
; 1. Check the status of the transfer.
282
; If the transfer was failed, go to the common error handler.
283
        cmp     dword [esp+8], edx      ; status is zero?
284
        jnz     keyboard_data_ready.error
285
; 2. Send the control packet SET_IDLE(infinity). HID auto-repeat is not useful.
286
        mov     eax, [esp+20]
287
        push    edx     ; flags for USBControlTransferAsync
288
        push    eax     ; userdata for USBControlTransferAsync
289
        add     eax, device_data.control
290
        mov     dword [eax], 21h + (0Ah shl 8) + (0 shl 24)     ; class request to interface + SET_IDLE + no autorepeat
291
        stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \
292
                eax, edx, edx, keyboard_configured2; , , 
293
; 3. Return.
294
        ret     20
295
 
296
; This function is called when SET_IDLE command for keyboard is done,
297
; either successful or unsuccessful.
298
keyboard_configured2:
299
; Check the status of the transfer and go to the corresponding label
300
; in the main handler.
301
        cmp     dword [esp+8], 0
302
        jnz     keyboard_data_ready.error
303
        mov     edx, [esp+20]
304
        push    edx
305
        stdcall RegKeyboard, usbkbd_functions, edx
306
        pop     edx
307
        mov     [edx+keyboard_data.handle], eax
308
        jmp     keyboard_data_ready.next
309
 
310
; This function is called when another interrupt packet arrives,
311
; processed either successfully or unsuccessfully.
312
; It should parse the packet and initiate another transfer with
313
; the same callback function.
314
keyboard_data_ready:
315
; 1. Check the status of the transfer.
316
        mov     eax, [esp+8]
317
        test    eax, eax
318
        jnz     .error
319
; Parse the packet, comparing with the previous packet.
320
; For boot protocol, USB keyboard packet consists of the first byte
321
; with status keys that are currently pressed. The second byte should
322
; be ignored, and other 5 bytes denote keys that are currently pressed.
323
        push    esi ebx         ; save used registers to be stdcall
324
; 2. Process control keys.
325
; 2a. Initialize before loop for control keys. edx = mask for control bits
326
; that were changed.
327
        mov     ebx, [esp+20+8]
328
        movzx   edx, byte [ebx+device_data.packet]      ; get state of control keys
329
        xor     dl, byte [ebx+keyboard_data.prevpacket] ; compare with previous state
330
; 2b. If state of control keys has not changed, advance to 3.
331
        jz      .nocontrol
332
; 2c. Otherwise, loop over control keys; esi = bit number.
333
        xor     esi, esi
334
.controlloop:
335
; 2d. Skip bits that have not changed.
336
        bt      edx, esi
337
        jnc     .controlnext
338
        push    edx     ; save register which is possibly modified by API
339
; The state of the current control key has changed.
340
; 2e. For extended control keys, send the prefix 0xE0.
341
        mov     al, [control_keys+esi]
342
        test    al, al
343
        jns     @f
344
        push    eax
345
        mov     ecx, 0xE0
346
        call    SetKeyboardData
347
        pop     eax
348
        and     al, 0x7F
349
@@:
350
; 2f. If the current state of the control key is "pressed", send normal
351
; scancode. Otherwise, the key is released, so set the high bit in scancode.
352
        movzx   ecx, al
353
        bt      dword [ebx+device_data.packet], esi
354
        jc      @f
355
        or      cl, 0x80
356
@@:
357
        call    SetKeyboardData
358
        pop     edx     ; restore register which was possibly modified by API
359
.controlnext:
360
; 2g. We have 8 control keys.
361
        inc     esi
362
        cmp     esi, 8
363
        jb      .controlloop
364
.nocontrol:
365
; 3. Initialize before loop for normal keys. esi = index.
3598 clevermous 366
        movi    esi, 2
3520 clevermous 367
.normalloop:
368
; 4. Process one key which was pressed in the previous packet.
369
; 4a. Get the next pressed key from the previous packet.
370
        movzx   eax, byte [ebx+esi+keyboard_data.prevpacket]
371
; 4b. Ignore special codes.
372
        cmp     al, 3
373
        jbe     .normalnext1
374
; 4c. Ignore keys that are still pressed in the current packet.
375
        lea     ecx, [ebx+device_data.packet]
376
        call    haskey
377
        jz      .normalnext1
378
; 4d. Say warning about keys with strange codes.
379
        cmp     eax, normal_keys_number
380
        jae     .badkey1
381
        movzx   ecx, [normal_keys+eax]
382
        jecxz   .badkey1
383
; 4e. For extended keys, send the prefix 0xE0.
384
        push    ecx     ; save keycode
385
        test    cl, cl
386
        jns     @f
387
        push    ecx
388
        mov     ecx, 0xE0
389
        call    SetKeyboardData
390
        pop     ecx
391
@@:
392
; 4f. Send the release event.
393
        or      cl, 0x80
394
        call    SetKeyboardData
395
; 4g. If this key is autorepeating, stop the timer.
396
        pop     ecx     ; restore keycode
397
        cmp     cl, [ebx+keyboard_data.repeatkey]
398
        jnz     .normalnext1
399
        mov     eax, [ebx+keyboard_data.timer]
400
        test    eax, eax
401
        jz      .normalnext1
402
        stdcall CancelTimerHS, eax
403
        and     [ebx+keyboard_data.timer], 0
404
        jmp     .normalnext1
405
.badkey1:
406
        DEBUGF 1,'K : unknown keycode: %x\n',al
407
.normalnext1:
408
; 5. Process one key which is pressed in the current packet.
409
; 5a. Get the next pressed key from the current packet.
410
        movzx   eax, byte [ebx+esi+device_data.packet]
411
; 5b. Ignore special codes.
412
        cmp     al, 3
413
        jbe     .normalnext2
414
; 5c. Ignore keys that were already pressed in the previous packet.
415
        lea     ecx, [ebx+keyboard_data.prevpacket]
416
        call    haskey
417
        jz      .normalnext2
418
; 5d. Say warning about keys with strange codes.
419
        cmp     eax, normal_keys_number
420
        jae     .badkey2
421
        movzx   ecx, [normal_keys+eax]
422
        jecxz   .badkey2
423
; 5e. For extended keys, send the prefix 0xE0.
424
        push    ecx     ; save keycode
425
        test    cl, cl
426
        jns     @f
427
        push    ecx
428
        mov     ecx, 0xE0
429
        call    SetKeyboardData
430
        pop     ecx
431
@@:
432
; 5f. Send the press event.
433
        and     cl, not 0x80
434
        call    SetKeyboardData
435
; 5g. Stop the current auto-repeat timer, if present.
436
        mov     eax, [ebx+keyboard_data.timer]
437
        test    eax, eax
438
        jz      @f
439
        stdcall CancelTimerHS, eax
440
@@:
441
; 5h. Start the auto-repeat timer.
442
        pop     ecx     ; restore keycode
443
        mov     [ebx+keyboard_data.repeatkey], cl
444
        stdcall TimerHS, 25, 5, autorepeat_timer, ebx
445
        mov     [ebx+keyboard_data.timer], eax
446
        jmp     .normalnext2
447
.badkey2:
448
        DEBUGF 1,'K : unknown keycode: %x\n',al
449
.normalnext2:
450
; 6. Advance to next key.
451
        inc     esi
452
        cmp     esi, 8
453
        jb      .normalloop
454
; 7. Save the packet data for future reference.
455
        mov     eax, dword [ebx+device_data.packet]
456
        mov     dword [ebx+keyboard_data.prevpacket], eax
457
        mov     eax, dword [ebx+device_data.packet+4]
458
        mov     dword [ebx+keyboard_data.prevpacket+4], eax
459
        pop     ebx esi ; restore registers to be stdcall
460
.next:
461
; 8. Initiate transfer on the interrupt pipe.
462
        mov     eax, [esp+20]
463
        push    1       ; flags for USBNormalTransferAsync
464
        push    eax     ; userdata for USBNormalTransferAsync
465
        add     eax, device_data.packet
466
        stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \
467
                eax, dword [eax+device_data.packetsize-device_data.packet], \
468
                keyboard_data_ready;, , 
469
; 9. Return.
470
.nothing:
471
        ret     20
472
.error:
473
; An error has occured.
474
; 10. If an error is caused by the disconnect, do nothing, it is handled
475
; in DeviceDisconnected. Otherwise, say a message.
476
        cmp     eax, 16
477
        jz      @f
478
        push    esi
479
        mov     esi, errormsgkbd
480
        call    SysMsgBoardStr
481
        pop     esi
482
@@:
483
        ret     20
484
 
485
; Auxiliary procedure for keyboard_data_ready.
486
haskey:
3598 clevermous 487
        movi    edx, 2
3520 clevermous 488
@@:
489
        cmp     byte [ecx+edx], al
490
        jz      @f
491
        inc     edx
492
        cmp     edx, 7
493
        jbe     @b
494
@@:
495
        ret
496
 
497
; Timer function for auto-repeat.
498
autorepeat_timer:
499
        mov     eax, [esp+4]
500
        movzx   ecx, [eax+keyboard_data.repeatkey]
501
        test    cl, cl
502
        jns     @f
503
        push    ecx
504
        mov     ecx, 0xE0
505
        call    SetKeyboardData
506
        pop     ecx
507
        and     cl, not 0x80
508
@@:
509
        call    SetKeyboardData
510
        ret     4
511
 
512
; This function is called to update LED state on the keyboard.
513
SetKeyboardLights:
514
        mov     eax, [esp+4]
515
        add     eax, device_data.control
516
        mov     dword [eax], 21h + (9 shl 8) + (2 shl 24)
517
                ; class request to interface + SET_REPORT + Output zero report
518
        mov     byte [eax+6], 1
519
        mov     edx, [esp+8]
520
        shr     dl, 1
521
        jnc     @f
522
        or      dl, 4
523
@@:
524
        lea     ecx, [eax+keyboard_data.ledstate-device_data.control]
525
        mov     [ecx], dl
526
        stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \
527
                eax, ecx, 1, keyboard_data_ready.nothing, 0, 0
528
        ret     8
529
 
530
; This function is called when it is safe to free keyboard data.
531
CloseKeyboard:
532
        mov     eax, [esp+4]
533
        push    ebx
534
        call    Kfree
535
        pop     ebx
536
        ret     4
537
 
538
; This function is called when SET_PROTOCOL command for mouse is done,
539
; either successful or unsuccessful.
540
mouse_configured:
541
; Check the status of the transfer and go to the corresponding label
542
; in the main handler.
543
        cmp     dword [esp+8], 0
544
        jnz     mouse_data_ready.error
545
        mov     eax, [esp+20]
546
        add     eax, device_data.packet
547
        jmp     mouse_data_ready.next
548
 
549
; This function is called when another interrupt packet arrives,
550
; processed either successfully or unsuccessfully.
551
; It should parse the packet and initiate another transfer with
552
; the same callback function.
553
mouse_data_ready:
554
; 1. Check the status of the transfer.
555
        mov     eax, [esp+8]
556
        test    eax, eax
557
        jnz     .error
558
        mov     edx, [esp+16]
559
; 2. Parse the packet.
560
; For boot protocol, USB mouse packet consists of at least 3 bytes.
561
; The first byte is state of mouse buttons, the next two bytes are
562
; x and y movements.
563
; Normal mice do not distinguish between boot protocol and report protocol;
564
; in this case, scroll data are also present. Advanced mice, however,
565
; support two different protocols, boot protocol is used for compatibility
566
; and does not contain extended buttons or scroll data.
567
        mov     eax, [esp+12]   ; buffer
568
        push    eax
569
        xor     ecx, ecx
570
        cmp     edx, 4
571
        jbe     @f
572
        movsx   ecx, byte [eax+4]
573
@@:
574
        push    ecx
575
        xor     ecx, ecx
576
        cmp     edx, 3
577
        jbe     @f
578
        movsx   ecx, byte [eax+3]
579
        neg     ecx
580
@@:
581
        push    ecx
582
        xor     ecx, ecx
583
        cmp     edx, 2
584
        jbe     @f
585
        movsx   ecx, byte [eax+2]
586
        neg     ecx
587
@@:
588
        push    ecx
589
        movsx   ecx, byte [eax+1]
590
        push    ecx
591
        movzx   ecx, byte [eax]
592
        push    ecx
593
        call    SetMouseData
594
        pop     eax
595
.next:
596
; 3. Initiate transfer on the interrupt pipe.
597
        stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \
598
                eax, dword [eax+device_data.packetsize-device_data.packet], mouse_data_ready, eax, 1
599
; 4. Return.
600
        ret     20
601
.error:
602
; An error has occured.
603
; 5. If an error is caused by the disconnect, do nothing, it is handled
604
; in DeviceDisconnected. Otherwise, say a message.
605
        cmp     eax, 16
606
        jz      @f
607
        push    esi
608
        mov     esi, errormsgmouse
609
        call    SysMsgBoardStr
610
        pop     esi
611
@@:
612
        ret     20
613
 
614
; This function is called when the device is disconnected.
615
DeviceDisconnected:
616
        push    ebx     ; save used register to be stdcall
617
; 1. Say a message. Use different messages for keyboards and mice.
618
        mov     ebx, [esp+4+4]
619
        push    esi
620
        mov     esi, disconnectmsgk
621
        cmp     byte [ebx+device_data.type], 1
622
        jz      @f
623
        mov     esi, disconnectmsgm
624
@@:
625
        stdcall SysMsgBoardStr
626
        pop     esi
627
; 2. If device is keyboard, then we must unregister it as a keyboard and
628
; possibly stop the auto-repeat timer.
629
        cmp     byte [ebx+device_data.type], 1
630
        jnz     .nokbd
631
        mov     eax, [ebx+keyboard_data.timer]
632
        test    eax, eax
633
        jz      @f
634
        stdcall CancelTimerHS, eax
635
@@:
636
        mov     ecx, [ebx+keyboard_data.handle]
637
        jecxz   .nokbd
638
        stdcall DelKeyboard, ecx
639
; If keyboard is registered, then we should free data in CloseKeyboard, not here.
640
        jmp     .nothing
641
.nokbd:
642
; 3. Free the device data.
643
        xchg    eax, ebx
644
        call    Kfree
645
; 4. Return.
646
.nothing:
647
        pop     ebx     ; restore used register to be stdcall
648
        ret     4       ; purge one dword argument to be stdcall
649
 
650
; strings
651
my_driver       db      'usbhid',0
652
errormsgmouse   db      'K : USB transfer error, disabling mouse',10,0
653
errormsgkbd     db      'K : USB transfer error, disabling keyboard',10,0
654
disconnectmsgm  db      'K : USB mouse disconnected',10,0
655
disconnectmsgk  db      'K : USB keyboard disconnected',10,0
656
 
657
; data for keyboard: correspondence between HID usage keys and PS/2 scancodes.
658
EX = 80h
659
label control_keys byte
660
        db      1Dh, 2Ah, 38h, 5Bh+EX, 1Dh+EX, 36h, 38h+EX, 5Ch+EX
661
label normal_keys byte
662
        db      00h, 00h, 00h, 00h, 1Eh, 30h, 2Eh, 20h, 12h, 21h, 22h, 23h, 17h, 24h, 25h, 26h  ; 0x
663
        db      32h, 31h, 18h, 19h, 10h, 13h, 1Fh, 14h, 16h, 2Fh, 11h, 2Dh, 15h, 2Ch, 02h, 03h  ; 1x
664
        db      04h, 05h, 06h, 07h, 08h, 09h, 0Ah, 0Bh, 1Ch, 01h, 0Eh, 0Fh, 39h, 0Ch, 0Dh, 1Ah  ; 2x
665
        db      1Bh, 2Bh, 2Bh, 27h, 28h, 29h, 33h, 34h, 35h, 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh, 40h  ; 3x
666
        db      41h, 42h, 43h, 44h, 57h, 58h,37h+EX,46h,0,52h+EX,47h+EX,49h+EX,53h+EX,4Fh+EX,51h+EX,4Dh+EX      ; 4x
667
        db      4Bh+EX,50h+EX,48h+EX,45h,35h+EX,37h,4Ah,4Eh,1Ch+EX,4Fh,50h,51h,4Bh,4Ch,4Dh,47h  ; 5x
668
        db      48h, 49h, 52h, 53h, 56h,5Dh+EX,5Eh+EX,59h,64h,65h,66h, 67h, 68h, 69h, 6Ah, 6Bh  ; 6x
669
        db      6Ch, 6Dh, 6Eh, 76h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h  ; 7x
670
        db      00h, 00h, 00h, 00h, 00h, 7Eh, 00h, 73h, 70h, 7Dh, 79h, 7Bh, 5Ch, 00h, 00h, 00h  ; 8x
671
        db      0F2h,0F1h,78h, 77h, 76h
672
normal_keys_number = $ - normal_keys
673
 
674
; Exported variable: kernel API version.
675
align 4
676
version dd      50005h
677
; Structure with callback functions.
678
usb_functions:
679
        dd      12
680
        dd      AddDevice
681
        dd      DeviceDisconnected
682
 
683
; Structure with callback functions for keyboards.
684
usbkbd_functions:
685
        dd      12
686
        dd      CloseKeyboard
687
        dd      SetKeyboardLights
688
 
689
; for DEBUGF macro
690
include_debug_strings
691
 
692
; for uninitialized data
693
section '.data' data readable writable align 16