Subversion Repositories Kolibri OS

Rev

Rev 5051 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ; Parser of HID structures: parse HID report descriptor,
  2. ; parse/generate input/output/feature reports.
  3.  
  4. ; =============================================================================
  5. ; ================================= Constants =================================
  6. ; =============================================================================
  7. ; Usage codes from HID specification
  8. ; Generic Desktop usage page
  9. USAGE_GD_POINTER     = 10001h
  10. USAGE_GD_MOUSE       = 10002h
  11. USAGE_GD_JOYSTICK    = 10004h
  12. USAGE_GD_GAMEPAD     = 10005h
  13. USAGE_GD_KEYBOARD    = 10006h
  14. USAGE_GD_KEYPAD      = 10007h
  15.  
  16. USAGE_GD_X           = 10030h
  17. USAGE_GD_Y           = 10031h
  18. USAGE_GD_Z           = 10032h
  19. USAGE_GD_RX          = 10033h
  20. USAGE_GD_RY          = 10034h
  21. USAGE_GD_RZ          = 10035h
  22. USAGE_GD_SLIDER      = 10036h
  23. USAGE_GD_DIAL        = 10037h
  24. USAGE_GD_WHEEL       = 10038h
  25.  
  26. USAGE_GD_CONS_CTRL   = 0C0001h ; Consumer control (media keys)
  27.  
  28. ; Keyboard/Keypad usage page
  29. USAGE_KBD_NOEVENT    = 70000h
  30. USAGE_KBD_ROLLOVER   = 70001h
  31. USAGE_KBD_POSTFAIL   = 70002h
  32. USAGE_KBD_FIRST_KEY  = 70004h ; this is 'A', actually
  33. USAGE_KBD_LCTRL      = 700E0h
  34. USAGE_KBD_LSHIFT     = 700E1h
  35. USAGE_KBD_LALT       = 700E2h
  36. USAGE_KBD_LWIN       = 700E3h
  37. USAGE_KBD_RCTRL      = 700E4h
  38. USAGE_KBD_RSHIFT     = 700E5h
  39. USAGE_KBD_RALT       = 700E6h
  40. USAGE_KBD_RWIN       = 700E7h
  41.  
  42. ; LED usage page
  43. USAGE_LED_NUMLOCK    = 80001h
  44. USAGE_LED_CAPSLOCK   = 80002h
  45. USAGE_LED_SCROLLLOCK = 80003h
  46.  
  47. ; Button usage page
  48. ; First button is USAGE_BUTTON_PAGE+1, second - USAGE_BUTTON_PAGE+2 etc.
  49. USAGE_BUTTON_PAGE    = 90000h
  50.  
  51. ; Consumer control usage page
  52. USAGE_CONSUMER       = 0C0000h
  53.  
  54. ; Flags for input/output/feature fields
  55. HID_FIELD_CONSTANT   = 1 ; if not, then Data field
  56. HID_FIELD_VARIABLE   = 2 ; if not, then Array field
  57. HID_FIELD_RELATIVE   = 4 ; if not, then Absolute field
  58. HID_FIELD_WRAP       = 8
  59. HID_FIELD_NONLINEAR  = 10h
  60. HID_FIELD_NOPREFERRED= 20h ; no preferred state
  61. HID_FIELD_HASNULL    = 40h ; has null state
  62. HID_FIELD_VOLATILE   = 80h ; for output/feature fields
  63. HID_FIELD_BUFBYTES   = 100h; buffered bytes
  64.  
  65. ; Report descriptor can easily describe gigabytes of (meaningless) data.
  66. ; Keep report size reasonable to avoid excessive memory allocations and
  67. ; calculation overflows; 1 Kb is more than enough (typical size is 3-10 bytes).
  68. MAX_REPORT_BYTES = 1024
  69.  
  70. ; =============================================================================
  71. ; ================================ Structures =================================
  72. ; =============================================================================
  73. ; Every meaningful report field group has one or more associated usages.
  74. ; Usages can be individual or joined into continuous ranges.
  75. ; This structure describes one range or one individual usage in a large array;
  76. ; individual usage is equivalent to a range of length 1.
  77. struct usage_range
  78. offset          dd      ?
  79. ; Sum of range sizes over all previous array items.
  80. ; Size of range a equals
  81. ; [a + sizeof.usage_range + usage_range.offset] - [a + usage_range.offset].
  82. ; The total sum over all array items immediately follows the array,
  83. ; this field must be the first so that the formula above works for the last item.
  84. first_usage     dd      ?
  85. ; Usage code for first item in the range.
  86. ends
  87.  
  88. ; This structure describes one group of report fields with identical properties.
  89. struct report_field_group
  90. next            dd      ?
  91. ; All field groups in one report are organized in a single-linked list.
  92. ; This is the next group in the report or 0 for the last group.
  93. size            dd      ?
  94. ; Size in bits of one field. Cannot be zero or greater than 32.
  95. count           dd      ?       ; field count, cannot be zero
  96. offset          dd      ?       ; offset from report start, in bits
  97. ; Following fields are decoded from report descriptor, see HID spec for details.
  98. flags           dd      ?
  99. logical_minimum dd      ?
  100. logical_maximum dd      ?
  101. physical_minimum dd     ?
  102. physical_maximum dd     ?
  103. unit_exponent   dd      ?
  104. unit            dd      ?
  105. ; Following fields are used to speedup extract_field_value.
  106. mask            dd      ?
  107. ; Bitmask for all data bits except sign bit:
  108. ; (1 shl .size) - 1 for unsigned fields, (1 shl (.size-1)) - 1 for signed fields
  109. sign_mask       dd      ?
  110. ; Zero for unsigned fields. Bitmask with sign bit set for signed fields.
  111. common_sizeof   rd      0
  112. ; Variable and Array field groups differ significantly.
  113. ; Variable field groups are simple. There are .count fields, each field has
  114. ; predefined Usage, the content of a field is its value. Each field is
  115. ; always present in the report. For Variable field groups, we just keep
  116. ; additional .count dwords with usages for individual fields.
  117. ; Array field groups are complicated. There are .count uniform fields.
  118. ; The content of a field determines Usage; Usages which are currently presented
  119. ; in the report have value = 1, other Usages have value = 0. The number of
  120. ; possible Usages is limited only by field .size; 32-bit field could encode any
  121. ; Usage, so it is unreasonable to keep all Usages in the plain array, as with
  122. ; Variable fields. However, many unrelated Usages in one group are meaningless,
  123. ; so usually possible values are grouped in sequential ranges; number of ranges
  124. ; is limited by report descriptor size (max 0xFFFF bytes should contain all
  125. ; information, including usage ranges and field descriptions).
  126. ; Also, for Array variables we pass changes in state to drivers, not the state
  127. ; itself, because sending information about all possible Usages is inpractical;
  128. ; so we should remember the previous state in addition to the current state.
  129. ; Thus, for Array variables keep the following information, in this order:
  130. ; * some members listed below; note that they do NOT exist for Variable groups;
  131. ; * array of usage ranges in form of usage_range structures, including
  132. ;   an additional dword after array described in usage_range structure;
  133. ; * allocated memory for current values of the report;
  134. ; * values of the previous report.
  135. num_values_prev dd      ?       ; number of values in the previous report
  136. num_usage_ranges dd     ?       ; number of usage_range, always nonzero
  137. usages          rd      0
  138. ends
  139.  
  140. ; This structure describes one report.
  141. ; All reports of one type are organized into a single-linked list.
  142. struct report
  143. next            dd      ?       ; pointer to next report of the same type, if any
  144. size            dd      ?       ; total size in bits
  145. first_field     dd      ?       ; pointer to first report_field_group for this report
  146. last_field      dd      ?
  147. ; pointer to last report_field_group for this report, if any;
  148. ; address of .first_field, if .first_field is 0
  149. id              dd      ?
  150. ; Report ID, if assigned. Zero otherwise.
  151. top_level_collection dd ?       ; top-level collection for this report
  152. ends
  153.  
  154. ; This structure describes a set of reports of the same type;
  155. ; there are 3 sets (possibly empty), input, output and feature.
  156. struct report_set
  157. data            dd      ?
  158. ; If .numbered is zero, this is zero for the empty set and
  159. ; a pointer to the (only) report structure otherwise.
  160. ; If .numbered is nonzero, this is a pointer to 256-dword array of pointers
  161. ; to reports organized by report ID.
  162. first_report    dd      ?
  163. ; Pointer to the first report or 0 for the empty set.
  164. numbered        db      ?
  165. ; If zero, report IDs are not used, there can be at most one report in the set.
  166. ; If nonzero, first byte of the report is report ID.
  167.                 rb      3       ; padding
  168. ends
  169.  
  170. ; This structure describes a range of reports of one type that belong to
  171. ; some collection.
  172. struct collection_report_set
  173. first_report    dd      ?
  174. first_field     dd      ?
  175. last_report     dd      ?
  176. last_field      dd      ?
  177. ends
  178.  
  179. ; This structure defines driver callbacks which are used while
  180. ; device is active; i.e. all callbacks except add_device.
  181. struct hid_driver_active_callbacks
  182. disconnect      dd      ?
  183. ; Called when an existing HID device is disconnected.
  184. ;
  185. ; Four following functions are called when a new input packet arrives
  186. ; in the following order: .begin_packet, then .input_field several times
  187. ; for each input field, interleaved with .array_overflow? for array groups,
  188. ; then .end_packet.
  189. begin_packet    dd      ?
  190. ; edi -> driver data
  191. array_overflow? dd      ?
  192. ; edi -> driver data
  193. ; out: CF cleared <=> ignore this array
  194. input_field     dd      ?
  195. ; edi -> driver data, ecx = usage, edx = value
  196. end_packet      dd      ?
  197. ; edi -> driver data
  198. ends
  199.  
  200. ; This structure describes one collection.
  201. struct collection
  202. next            dd      ?       ; pointer to the next collection in the same level
  203.                                 ; must be the first field
  204. parent          dd      ?       ; pointer to nesting collection
  205. first_child     dd      ?       ; pointer to the first nested collection
  206. last_child      dd      ?       ; pointer to the last nested collection
  207.                                 ; or to .first_child, if .first_child is zero
  208. type            dd      ?       ; Application, Physical etc
  209. usage           dd      ?       ; associated Usage code
  210. ; Next fields are filled only for top-level collections.
  211. callbacks       hid_driver_active_callbacks
  212. driver_data     dd      ?       ; value to be passed as is to driver callbacks
  213. input           collection_report_set
  214. output          collection_report_set
  215. feature         collection_report_set
  216. ends
  217.  
  218. ; This structure keeps all data used by the HID layer for one device.
  219. struct hid_data
  220. input           report_set
  221. output          report_set
  222. feature         report_set
  223. first_collection        dd      ?
  224. ends
  225.  
  226. ; This structure defines callbacks required from the driver.
  227. struct hid_driver_callbacks
  228. add_device      dd      ?
  229. ; Called when a new HID device is connected.
  230. active          hid_driver_active_callbacks
  231. ends
  232.  
  233. ; Two following structures describe temporary data;
  234. ; the corresponding objects cease to exist when HID parser completes
  235. ; state of Global items
  236. struct global_items
  237. next                    dd      ?
  238. usage_page              dd      ?
  239. logical_minimum         dd      ?
  240. logical_maximum         dd      ?
  241. physical_minimum        dd      ?
  242. physical_maximum        dd      ?
  243. unit_exponent           dd      ?
  244. unit                    dd      ?
  245. report_size             dd      ?
  246. report_id               dd      ?
  247. report_count            dd      ?
  248. ends
  249.  
  250. ; one range of Usages
  251. struct usage_list_item
  252. next                    dd      ?
  253. first_usage             dd      ?
  254. num_usages              dd      ?
  255. ends
  256.  
  257. ; =============================================================================
  258. ; =================================== Code ====================================
  259. ; =============================================================================
  260.  
  261. macro workers_globals
  262. {
  263.         workers_globals
  264. ; Jump tables for switch'ing in the code.
  265. align 4
  266. ; jump table for two lower bits which encode size of item data
  267. parse_descr_label.fetch_jumps:
  268.         dd      parse_descr_label.fetch_none    ; x0, x4, x8, xC
  269.         dd      parse_descr_label.fetch_byte    ; x1, x5, x9, xD
  270.         dd      parse_descr_label.fetch_word    ; x2, x6, xA, xE
  271.         dd      parse_descr_label.fetch_dword   ; x3, x7, xB, xF
  272. ; jump table for two next bits which encode item type
  273. parse_descr_label.type_jumps:
  274.         dd      parse_descr_label.parse_main
  275.         dd      parse_descr_label.parse_global
  276.         dd      parse_descr_label.parse_local
  277.         dd      parse_descr_label.parse_reserved
  278. ; jump table for 4 upper bits in the case of Main item
  279. parse_descr_label.main_jumps:
  280.         dd      parse_descr_label.input ; 80...83
  281.         dd      parse_descr_label.output        ; 90...93
  282.         dd      parse_descr_label.collection    ; A0...A3
  283.         dd      parse_descr_label.feature       ; B0...B3
  284.         dd      parse_descr_label.end_collection ; C0...C3
  285. parse_descr_label.num_main_items = ($ - parse_descr_label.main_jumps) / 4
  286. ; jump table for 4 upper bits in the case of Global item
  287. parse_descr_label.global_jumps:
  288.         dd      parse_descr_label.usage_page    ; 04...07
  289.         dd      parse_descr_label.logical_minimum ; 14...17
  290.         dd      parse_descr_label.logical_maximum ; 24...27
  291.         dd      parse_descr_label.physical_minimum ; 34...37
  292.         dd      parse_descr_label.physical_maximum ; 44...47
  293.         dd      parse_descr_label.unit_exponent ; 54...57
  294.         dd      parse_descr_label.unit          ; 64...67
  295.         dd      parse_descr_label.report_size   ; 74...77
  296.         dd      parse_descr_label.report_id     ; 84...87
  297.         dd      parse_descr_label.report_count  ; 94...97
  298.         dd      parse_descr_label.push          ; A4...A7
  299.         dd      parse_descr_label.pop           ; B4...B7
  300. parse_descr_label.num_global_items = ($ - parse_descr_label.global_jumps) / 4
  301. ; jump table for 4 upper bits in the case of Local item
  302. parse_descr_label.local_jumps:
  303.         dd      parse_descr_label.usage ; 08...0B
  304.         dd      parse_descr_label.usage_minimum ; 18...1B
  305.         dd      parse_descr_label.usage_maximum ; 28...2B
  306.         dd      parse_descr_label.item_parsed   ; 38...3B = designator item; ignore
  307.         dd      parse_descr_label.item_parsed   ; 48...4B = designator minimum; ignore
  308.         dd      parse_descr_label.item_parsed   ; 58...5B = designator maximum; ignore
  309.         dd      parse_descr_label.item_parsed   ; 68...6B not assigned
  310.         dd      parse_descr_label.item_parsed   ; 78...7B = string index; ignore
  311.         dd      parse_descr_label.item_parsed   ; 88...8B = string minimum; ignore
  312.         dd      parse_descr_label.item_parsed   ; 98...9B = string maximum; ignore
  313.         dd      parse_descr_label.delimiter     ; A8...AB
  314. parse_descr_label.num_local_items = ($ - parse_descr_label.local_jumps) / 4
  315. }
  316.  
  317. ; Local variables for parse_descr.
  318. macro parse_descr_locals
  319. {
  320. cur_item_size   dd      ?       ; encoded size of data for current item
  321. report_ok       db      ?       ; 0 on error, 1 if everything is ok
  322. field_type      db      ?       ; 0/1/2 for input/output/feature fields
  323.                 rb      2       ; alignment
  324. field_data      dd      ?       ; data for current item when it describes a field group
  325. last_reports    rd      3       ; pointers to last input/output/feature records
  326. usage_minimum   dd      ?       ; current value of Usage Minimum
  327. usage_list      dd      ?       ; list head of usage_list_item
  328. usage_tail      dd      ?       ; list tail of usage_list_item
  329. num_usage_ranges dd     ?       ; number of usage ranges, size of usage_list
  330. delimiter_depth dd      ?       ; normally 0; 1 inside of Delimiter();
  331.                                 ; nested Delimiter()s are not allowed
  332. usage_variant   dd      ?       ; 0 outside of Delimiter()s and for first Usage inside Delimiter(),
  333.                                 ; incremented with each new Usage inside Delimiter()
  334. cur_collection  dd      ?       ; current collection
  335. last_collection dd      ?       ; last top-level collection
  336. }
  337.  
  338. ; Parse report descriptor. The caller should provide local variables
  339. ; [buffer] = pointer to report descriptor, [length] = length of report descriptor,
  340. ; [calldata] = pointer to hid_data (possibly wrapped in a large structure).
  341. macro parse_descr
  342. {
  343. parse_descr_label:
  344. ; 1. Initialize.
  345. ; 1a. Set some variables to initial values.
  346.         xor     edi, edi
  347.         mov     dword [report_ok], edi
  348.         mov     [usage_list], edi
  349.         mov     [cur_collection], edi
  350.         mov     eax, [calldata]
  351.         add     eax, hid_data.input.first_report
  352.         mov     [last_reports+0*4], eax
  353.         add     eax, hid_data.output.first_report - hid_data.input.first_report
  354.         mov     [last_reports+1*4], eax
  355.         add     eax, hid_data.feature.first_report - hid_data.output.first_report
  356.         mov     [last_reports+2*4], eax
  357.         add     eax, hid_data.first_collection - hid_data.feature.first_report
  358.         mov     [last_collection], eax
  359. ; 1b. Allocate state of global items.
  360.         movi    eax, sizeof.global_items
  361.         invoke  Kmalloc
  362.         test    eax, eax
  363.         jz      .memory_error
  364. ; 1c. Zero-initialize it and move pointer to edi.
  365.         push    eax
  366.         xchg    eax, edi
  367.         movi    ecx, sizeof.global_items / 4
  368.         rep stosd
  369.         pop     edi
  370. ; 1d. Load pointer to data into esi and make [length] point to end of data.
  371.         mov     esi, [buffer]
  372.         add     [length], esi
  373. ; 2. Clear all local items.
  374. ; This is needed in the beginning and after processing any Main item.
  375. .zero_local_items:
  376.         mov     eax, [usage_list]
  377. @@:
  378.         test    eax, eax
  379.         jz      @f
  380.         push    [eax+usage_list_item.next]
  381.         invoke  Kfree
  382.         pop     eax
  383.         jmp     @b
  384. @@:
  385.         lea     ecx, [usage_list]
  386.         mov     [usage_tail], ecx
  387.         mov     [ecx], eax
  388.         mov     [delimiter_depth], eax
  389.         mov     [usage_variant], eax
  390.         mov     [usage_minimum], eax
  391.         mov     [num_usage_ranges], eax
  392. ; 3. Parse items until end of data found.
  393.         cmp     esi, [length]
  394.         jae     .parse_end
  395. .fetch_next_item:
  396. ; --------------------------------- Parse item --------------------------------
  397. ; 4. Parse one item.
  398. ; 4a. Get item data. eax = first item byte = code+type+size (4+2+2 bits),
  399. ; ebx = item data interpreted as unsigned,
  400. ; ecx = item data interpreted as signed.
  401.         movzx   eax, byte [esi]
  402.         mov     ecx, eax
  403.         and     ecx, 3
  404.         mov     [cur_item_size], ecx
  405.         jmp     dword [.fetch_jumps+ecx*4]
  406. .invalid_report:
  407.         mov     esi, invalid_report_msg
  408.         jmp     .end_str
  409. .fetch_none:
  410.         xor     ebx, ebx
  411.         xor     ecx, ecx
  412.         inc     esi
  413.         jmp     .fetched
  414. .fetch_byte:
  415.         add     esi, 2
  416.         cmp     esi, [length]
  417.         ja      .invalid_report
  418.         movzx   ebx, byte [esi-1]
  419.         movsx   ecx, bl
  420.         jmp     .fetched
  421. .fetch_word:
  422.         add     esi, 3
  423.         cmp     esi, [length]
  424.         ja      .invalid_report
  425.         movzx   ebx, word [esi-2]
  426.         movsx   ecx, bx
  427.         jmp     .fetched
  428. .fetch_dword:
  429.         add     esi, 5
  430.         cmp     esi, [length]
  431.         ja      .invalid_report
  432.         mov     ebx, dword [esi-4]
  433.         mov     ecx, ebx
  434. .fetched:
  435. ; 4b. Select the branch according to item type.
  436. ; For every type, select the concrete handler and go there.
  437.         mov     edx, eax
  438.         shr     edx, 2
  439.         and     edx, 3
  440.         shr     eax, 4
  441.         jmp     dword [.type_jumps+edx*4]
  442. ; -------------------------------- Main items ---------------------------------
  443. .parse_main:
  444.         sub     eax, 8
  445.         cmp     eax, .num_main_items
  446.         jae     .item_parsed
  447.         jmp     dword [.main_jumps+eax*4]
  448. ; There are 5 Main items.
  449. ; Input/Output/Feature items create new field groups in the corresponding report;
  450. ; Collection item opens a new collection (possibly nested),
  451. ; End Collection item closes the most nested collection.
  452. .output:
  453.         mov     [field_type], 1
  454.         jmp     .new_field
  455. .feature:
  456.         mov     [field_type], 2
  457.         jmp     .new_field
  458. .input:
  459.         mov     [field_type], 0
  460. .new_field:
  461. ; Create a new field group.
  462.         mov     [field_data], ebx
  463.         movzx   ebx, [field_type]
  464. if sizeof.report_set = 12
  465.         lea     ebx, [ebx*3]
  466.         shl     ebx, 2
  467. else
  468. err Change the code
  469. end if
  470.         add     ebx, [calldata]
  471. ; 5. Sanity checks: field size and fields count must be nonzero,
  472. ; field size cannot be more than 32 bits,
  473. ; if field count is more than MAX_REPORT_SIZE * 8, the report would be more than
  474. ; MAX_REPORT_SIZE bytes, so it is invalid too.
  475. ; More precise check for size occurs later; this check only guarantees that
  476. ; there will be no overflows during subsequent calculations.
  477.         cmp     [edi+global_items.report_size], 0
  478.         jz      .invalid_report
  479.         cmp     [edi+global_items.report_size], 32
  480.         ja      .invalid_report
  481. ; There are devices with Report Count(0) + Input(Constant Variable),
  482. ; zero-length padding. Thus, do not consider descriptors with Report Count(0)
  483. ; as invalid; instead, just ignore fields with Report Count(0).
  484.         cmp     [edi+global_items.report_count], 0
  485.         jz      .zero_local_items
  486.         cmp     [edi+global_items.report_count], MAX_REPORT_BYTES * 8
  487.         ja      .invalid_report
  488. ; 6. Get the pointer to the place for the corresponding report in ebx.
  489. ; 6a. If report ID is not assigned, ebx already points to report_set.data,
  490. ; so go to 7.
  491.         cmp     [edi+global_items.report_id], 0
  492.         jz      .report_ptr_found
  493. ; 6b. If table for reports was already allocated,
  494. ; go to 6d skipping the next substep.
  495.         cmp     [ebx+report_set.numbered], 0
  496.         jnz     .report_set_allocated
  497. ; 6c. This is the first report with ID;
  498. ; allocate and zero-initialize table for reports.
  499. ; Note: it is incorrect but theoretically possible that some fields were
  500. ; already allocated in report without ID; if so, abort processing with error.
  501.         cmp     [ebx+report_set.data], 0
  502.         jnz     .invalid_report
  503.         mov     eax, 256*4
  504.         invoke  Kmalloc
  505.         test    eax, eax
  506.         jz      .memory_error
  507.         mov     [ebx+report_set.data], eax
  508.         inc     [ebx+report_set.numbered]
  509.         push    edi
  510.         mov     edi, eax
  511.         mov     ecx, 256
  512.         xor     eax, eax
  513.         rep stosd
  514.         pop     edi
  515. ; 6d. Report ID is assigned, report table is allocated,
  516. ; get the pointer to the corresponding item in the report table.
  517. .report_set_allocated:
  518.         mov     ebx, [ebx+report_set.data]
  519.         mov     ecx, [edi+global_items.report_id]
  520.         lea     ebx, [ebx+ecx*4]
  521. ; 7. If the field group is the first one in the report,
  522. ; allocate and initialize report without fields.
  523. .report_ptr_found:
  524. ; 7a. Check whether the report has been allocated.
  525.         cmp     dword [ebx], 0
  526.         jnz     .report_allocated
  527. ; 7b. Allocate.
  528.         movi    eax, sizeof.report
  529.         invoke  Kmalloc
  530.         test    eax, eax
  531.         jz      .memory_error
  532. ; 7c. Initialize.
  533.         xor     edx, edx
  534.         lea     ecx, [eax+report.first_field]
  535.         mov     [ebx], eax
  536.         mov     [eax+report.next], edx
  537.         mov     [eax+report.size], edx
  538.         mov     [ecx], edx
  539.         mov     [eax+report.last_field], ecx
  540.         mov     [eax+report.top_level_collection], edx
  541.         mov     ecx, [edi+global_items.report_id]
  542.         mov     [eax+report.id], ecx
  543. ; 7d. Append to the overall list of reports.
  544.         movzx   edx, [field_type]
  545.         lea     edx, [last_reports+edx*4]
  546.         mov     ecx, [edx]
  547.         mov     [edx], eax
  548.         mov     [ecx], eax
  549. .report_allocated:
  550.         mov     ebx, [ebx]
  551. ; ebx points to an already existing report; add new field.
  552. ; 8. Calculate total size of the group and
  553. ; check that the new group would not overflow the report.
  554.         mov     eax, [edi+global_items.report_size]
  555.         mul     [edi+global_items.report_count]
  556.         mov     ecx, [ebx+report.size]
  557.         add     ecx, eax
  558.         cmp     ecx, MAX_REPORT_BYTES * 8
  559.         ja      .invalid_report
  560. ; 9. If there are no usages for this group, this is padding;
  561. ; add it's size to total report size and stop processing.
  562.         cmp     [num_usage_ranges], 0
  563.         jz      .padding
  564. ; 10. Allocate memory for the group: this includes field group structure
  565. ; and additional fields depending on field type.
  566. ; See comments in report_field_group structure.
  567.         push    eax
  568.         mov     edx, [edi+global_items.report_count]
  569.         lea     eax, [report_field_group.common_sizeof+edx*4]
  570.         test    byte [field_data], HID_FIELD_VARIABLE
  571.         jnz     @f
  572.         lea     eax, [eax+edx*4]
  573.         mov     edx, [num_usage_ranges]
  574.         lea     eax, [eax+edx*sizeof.usage_range+4]
  575. @@:
  576.         invoke  Kmalloc
  577.         pop     edx
  578.         test    eax, eax
  579.         jz      .memory_error
  580. ; 11. Update report data.
  581. ; Field offset is the current report size;
  582. ; get the current report size and update report size.
  583. ; Also store the pointer to new field in the previous last field
  584. ; and update the last field.
  585.         mov     ecx, [ebx+report.last_field]
  586.         xadd    [ebx+report.size], edx
  587.         mov     [ebx+report.last_field], eax
  588.         mov     [ecx], eax
  589. ; 12. Initialize field data: offset was calculated in the previous step,
  590. ; copy other characteristics from global_items data,
  591. ; calculate .mask and .sign_mask.
  592.         mov     [eax+report_field_group.offset], edx
  593.         xor     edx, edx
  594.         mov     [eax+report_field_group.next], edx
  595.         mov     [eax+report_field_group.sign_mask], edx
  596.         inc     edx
  597.         mov     ecx, [edi+global_items.report_size]
  598.         mov     [eax+report_field_group.size], ecx
  599.         shl     edx, cl
  600.         cmp     [edi+global_items.logical_minimum], 0
  601.         jge     .unsigned
  602.         shr     edx, 1
  603.         mov     [eax+report_field_group.sign_mask], edx
  604. .unsigned:
  605.         dec     edx
  606.         mov     [eax+report_field_group.mask], edx
  607.         mov     ecx, [edi+global_items.report_count]
  608.         mov     [eax+report_field_group.count], ecx
  609.         mov     ecx, [field_data]
  610.         mov     [eax+report_field_group.flags], ecx
  611. irps field, logical_minimum logical_maximum physical_minimum physical_maximum unit_exponent unit
  612. \{
  613.         mov     ecx, [edi+global_items.\#field]
  614.         mov     [eax+report_field_group.\#field], ecx
  615. \}
  616. ; 13. Update the current collection; nesting collections will be updated by
  617. ; end-of-collection handler.
  618.         movzx   edx, [field_type]
  619. if sizeof.collection_report_set = 16
  620.         shl     edx, 4
  621. else
  622. err Change the code
  623. end if
  624.         mov     ecx, [cur_collection]
  625.         test    ecx, ecx
  626.         jz      .no_collection
  627.         lea     ecx, [ecx+collection.input+edx]
  628.         mov     [ecx+collection_report_set.last_report], ebx
  629.         mov     [ecx+collection_report_set.last_field], eax
  630.         cmp     [ecx+collection_report_set.first_field], 0
  631.         jnz     .no_collection
  632.         mov     [ecx+collection_report_set.first_report], ebx
  633.         mov     [ecx+collection_report_set.first_field], eax
  634. .no_collection:
  635. ; 14. Transform usage ranges. The target format depends on field type.
  636.         test    byte [eax+report_field_group.flags], HID_FIELD_VARIABLE
  637.         jz      .transform_usages_for_array
  638. ; For Variable field groups, expand all ranges to array with .count Usages.
  639. ; If total number of Usages in all ranges is too large, ignore excessive.
  640. ; If total number of Usages in all ranges is too small, duplicate the last
  641. ; Usage up to .count Usages (e.g. group of several indicators can have one usage
  642. ; "Generic Indicator" assigned to all fields).
  643.         mov     ecx, [eax+report_field_group.count]
  644.         mov     ebx, [usage_list]
  645. .next_usage_range_for_variable:
  646.         mov     edx, [ebx+usage_list_item.first_usage]
  647.         push    [ebx+usage_list_item.num_usages]
  648. .next_usage_for_variable:
  649.         mov     [eax+report_field_group.common_sizeof], edx
  650.         dec     ecx
  651.         jz      @f
  652.         add     eax, 4
  653.         inc     edx
  654.         dec     dword [esp]
  655.         jnz     .next_usage_for_variable
  656.         dec     edx
  657.         inc     dword [esp]
  658.         cmp     [ebx+usage_list_item.next], 0
  659.         jz      .next_usage_for_variable
  660.         pop     edx
  661.         mov     ebx, [ebx+usage_list_item.next]
  662.         jmp     .next_usage_range_for_variable
  663. @@:
  664.         pop     ebx
  665.         jmp     .zero_local_items
  666. .transform_usages_for_array:
  667. ; For Array field groups, leave ranges unexpanded, but recode in the form
  668. ; more convenient to value lookup, see comments in report_field_group structure.
  669.         mov     ecx, [num_usage_ranges]
  670.         mov     [eax+report_field_group.num_usage_ranges], ecx
  671.         and     [eax+report_field_group.num_values_prev], 0
  672.         mov     ecx, [usage_list]
  673.         xor     ebx, ebx
  674. @@:
  675.         mov     edx, [ecx+usage_list_item.first_usage]
  676.         mov     [eax+report_field_group.usages+usage_range.offset], ebx
  677.         add     ebx, [ecx+usage_list_item.num_usages]
  678.         jc      .invalid_report
  679.         mov     [eax+report_field_group.usages+usage_range.first_usage], edx
  680.         add     eax, sizeof.usage_range
  681.         mov     ecx, [ecx+usage_list_item.next]
  682.         test    ecx, ecx
  683.         jnz     @b
  684.         mov     [eax+report_field_group.usages], ebx
  685. ; New field is initialized.
  686.         jmp     .zero_local_items
  687. .padding:
  688.         mov     [ebx+report.size], ecx
  689.         jmp     .zero_local_items
  690. ; Create a new collection, nested in the current one.
  691. .collection:
  692. ; Actions are quite straightforward:
  693. ; allocate, zero-initialize, update parent, if there is one,
  694. ; make it current.
  695.         movi    eax, sizeof.collection
  696.         invoke  Kmalloc
  697.         test    eax, eax
  698.         jz      .memory_error
  699.         push    eax edi
  700.         movi    ecx, sizeof.collection / 4
  701.         xchg    edi, eax
  702.         xor     eax, eax
  703.         rep stosd
  704.         pop     edi eax
  705.         mov     edx, [cur_collection]
  706.         mov     [eax+collection.parent], edx
  707.         lea     ecx, [last_collection]
  708.         test    edx, edx
  709.         jz      .no_parent
  710.         lea     ecx, [edx+collection.last_child]
  711. .no_parent:
  712.         mov     edx, [ecx]
  713.         mov     [ecx], eax
  714.         mov     [edx], eax
  715.         lea     ecx, [eax+collection.first_child]
  716. ; In theory, there must be at least one usage.
  717. ; In practice, some nested collections don't have any. Use zero in this case.
  718.         mov     edx, [usage_list]
  719.         test    edx, edx
  720.         jz      @f
  721.         mov     edx, [edx+usage_list_item.first_usage]
  722. @@:
  723.         mov     [eax+collection.last_child], ecx
  724.         mov     [eax+collection.type], ebx
  725.         mov     [eax+collection.usage], edx
  726.         mov     [cur_collection], eax
  727.         jmp     .zero_local_items
  728. ; Close the current collection.
  729. .end_collection:
  730. ; There must be an opened collection.
  731.         mov     eax, [cur_collection]
  732.         test    eax, eax
  733.         jz      .invalid_report
  734. ; Make parent collection the current one.
  735.         mov     edx, [eax+collection.parent]
  736.         mov     [cur_collection], edx
  737. ; Add field range of the closing collection to field range for nesting collection,
  738. ; if there is one.
  739.         test    edx, edx
  740.         jz      .zero_local_items
  741.         push    3       ; for each type: input, output, feature
  742. .update_ranges:
  743.         mov     ecx, [eax+collection.input.last_report]
  744.         test    ecx, ecx
  745.         jz      .no_fields
  746.         mov     [edx+collection.input.last_report], ecx
  747.         mov     ecx, [eax+collection.input.last_field]
  748.         mov     [edx+collection.input.last_field], ecx
  749.         cmp     [edx+collection.input.first_report], 0
  750.         jnz     .no_fields
  751.         mov     ecx, [eax+collection.input.first_report]
  752.         mov     [edx+collection.input.first_report], ecx
  753.         mov     ecx, [eax+collection.input.first_field]
  754.         mov     [edx+collection.input.first_field], ecx
  755. .no_fields:
  756.         add     eax, sizeof.collection_report_set
  757.         add     edx, sizeof.collection_report_set
  758.         dec     dword [esp]
  759.         jnz     .update_ranges
  760.         pop     eax
  761.         jmp     .zero_local_items
  762. ; ------------------------------- Global items --------------------------------
  763. .parse_global:
  764.         cmp     eax, .num_global_items
  765.         jae     .item_parsed
  766.         jmp     dword [.global_jumps+eax*4]
  767. ; For most global items, just store the value in the current global_items structure.
  768. ; Note 1: Usage Page will be used for upper word of Usage[| Minimum|Maximum], so
  769. ; shift it in advance.
  770. ; Note 2: the HID specification allows both signed and unsigned values for
  771. ; logical and physical minimum/maximum, but does not give a method to distinguish.
  772. ; Thus, hope that minimum comes first, parse the minimum as signed value always,
  773. ; if it is less than zero, assume signed values, otherwise assume unsigned values.
  774. ; This covers both common cases Minimum(0)/Maximum(FF) and Minimum(-7F)/Maximum(7F).
  775. ; Note 3: zero value for Report ID is forbidden by the HID specification.
  776. ; It is quite convenient, we use report_id == 0 for reports without ID.
  777. .usage_page:
  778.         shl     ebx, 16
  779.         mov     [edi+global_items.usage_page], ebx
  780.         jmp     .item_parsed
  781. .logical_minimum:
  782.         mov     [edi+global_items.logical_minimum], ecx
  783.         jmp     .item_parsed
  784. .logical_maximum:
  785.         cmp     [edi+global_items.logical_minimum], 0
  786.         jge     @f
  787.         mov     ebx, ecx
  788. @@:
  789.         mov     [edi+global_items.logical_maximum], ebx
  790.         jmp     .item_parsed
  791. .physical_minimum:
  792.         mov     [edi+global_items.physical_minimum], ecx
  793.         jmp     .item_parsed
  794. .physical_maximum:
  795.         cmp     [edi+global_items.physical_maximum], 0
  796.         jge     @f
  797.         mov     ebx, ecx
  798. @@:
  799.         mov     [edi+global_items.physical_maximum], ebx
  800.         jmp     .item_parsed
  801. .unit_exponent:
  802.         mov     [edi+global_items.unit_exponent], ecx
  803.         jmp     .item_parsed
  804. .unit:
  805.         mov     [edi+global_items.unit], ebx
  806.         jmp     .item_parsed
  807. .report_size:
  808.         mov     [edi+global_items.report_size], ebx
  809.         jmp     .item_parsed
  810. .report_id:
  811.         test    ebx, ebx
  812.         jz      .invalid_report
  813.         cmp     ebx, 0x100
  814.         jae     .invalid_report
  815.         mov     [edi+global_items.report_id], ebx
  816.         jmp     .item_parsed
  817. .report_count:
  818.         mov     [edi+global_items.report_count], ebx
  819.         jmp     .item_parsed
  820. ; Two special global items: Push/Pop.
  821. .push:
  822. ; For Push, allocate new global_items structure,
  823. ; initialize from the current one and make it current.
  824.         movi    eax, sizeof.global_items
  825.         invoke  Kmalloc
  826.         test    eax, eax
  827.         jz      .memory_error
  828.         push    esi eax
  829.         movi    ecx, sizeof.global_items / 4
  830.         mov     esi, edi
  831.         xchg    eax, edi
  832.         rep movsd
  833.         pop     edi esi
  834.         mov     [edi+global_items.next], eax
  835.         jmp     .item_parsed
  836. .pop:
  837. ; For Pop, restore the last global_items structure and free the current one.
  838.         mov     eax, [edi+global_items.next]
  839.         test    eax, eax
  840.         jz      .invalid_report
  841.         push    eax
  842.         xchg    eax, edi
  843.         invoke  Kfree
  844.         pop     edi
  845.         jmp     .item_parsed
  846. ; -------------------------------- Local items --------------------------------
  847. .parse_local:
  848.         cmp     eax, .num_local_items
  849.         jae     .item_parsed
  850.         jmp     dword [.local_jumps+eax*4]
  851. .usage:
  852. ; Usage tag.
  853. ; If length is 0, 1, 2 bytes, append the global item Usage Page.
  854.         cmp     [cur_item_size], 2
  855.         ja      @f
  856.         or      ebx, [edi+global_items.usage_page]
  857. @@:
  858. ; If inside Delimiter(), ignore everything except the first tag.
  859.         cmp     [delimiter_depth], 0
  860.         jz      .usage.write
  861.         inc     [usage_variant]
  862.         cmp     [usage_variant], 1
  863.         jnz     .item_parsed
  864. .usage.write:
  865. ; Add new range with start = item data and length = 1.
  866.         mov     [usage_minimum], ebx
  867.         push    1
  868. .new_usage:
  869.         movi    eax, sizeof.usage_list_item
  870.         invoke  Kmalloc
  871.         pop     edx
  872.         test    eax, eax
  873.         jz      .memory_error
  874.         inc     [num_usage_ranges]
  875.         mov     ecx, [usage_minimum]
  876.         and     [eax+usage_list_item.next], 0
  877.         mov     [eax+usage_list_item.first_usage], ecx
  878.         mov     [eax+usage_list_item.num_usages], edx
  879.         mov     ecx, [usage_tail]
  880.         mov     [usage_tail], eax
  881.         mov     [ecx], eax
  882.         jmp     .item_parsed
  883. .usage_minimum:
  884. ; Usage Minimum tag. Just store in the local var.
  885. ; If length is 0, 1, 2 bytes, append the global item Usage Page.
  886.         cmp     [cur_item_size], 2
  887.         ja      @f
  888.         or      ebx, [edi+global_items.usage_page]
  889. @@:
  890.         mov     [usage_minimum], ebx
  891.         jmp     .item_parsed
  892. .usage_maximum:
  893. ; Usage Maximum tag.
  894. ; If length is 0, 1, 2 bytes, append the global item Usage Page.
  895.         cmp     [cur_item_size], 2
  896.         ja      @f
  897.         or      ebx, [edi+global_items.usage_page]
  898. @@:
  899. ; Meaningless inside Delimiter().
  900.         cmp     [delimiter_depth], 0
  901.         jnz     .invalid_report
  902. ; Add new range with start = saved Usage Minimum and
  903. ; length = Usage Maximum - Usage Minimum + 1.
  904.         sub     ebx, [usage_minimum]
  905.         inc     ebx
  906.         push    ebx
  907.         jmp     .new_usage
  908. .delimiter:
  909. ; Delimiter tag.
  910.         test    ebx, ebx
  911.         jz      .delimiter.close
  912. ; Delimiter(Opened).
  913. ; Store that we are inside Delimiter(),
  914. ; say a warning that only preferred Usage will be used.
  915.         cmp     [delimiter_depth], 0
  916.         jnz     .invalid_report
  917.         inc     [delimiter_depth]
  918.         push    esi
  919.         mov     esi, delimiter_note
  920.         invoke  SysMsgBoardStr
  921.         pop     esi
  922.         jmp     .item_parsed
  923. .delimiter.close:
  924. ; Delimiter(Closed).
  925. ; Store that we are not inside Delimiter() anymore.
  926.         dec     [delimiter_depth]
  927.         js      .invalid_report
  928.         and     [usage_variant], 0
  929.         jmp     .item_parsed
  930. .parse_reserved:
  931. ; Ignore reserved items, except that tag 0xFE means long item
  932. ; with first data byte = length of additional data,
  933. ; second data byte = long item tag. No long items are defined yet,
  934. ; so just skip them.
  935.         cmp     eax, 0xF
  936.         jnz     .item_parsed
  937.         cmp     [cur_item_size], 2
  938.         jnz     .item_parsed
  939.         movzx   ecx, bl
  940.         add     esi, ecx
  941.         cmp     esi, [length]
  942.         ja      .invalid_report
  943. .item_parsed:
  944.         cmp     esi, [length]
  945.         jb      .fetch_next_item
  946. .parse_end:
  947. ;-------------------------------- End of parsing ------------------------------
  948. ; If there are opened collections, it is invalid report.
  949.         cmp     [cur_collection], 0
  950.         jnz     .invalid_report
  951. ; There must be at least one input field.
  952.         mov     eax, [calldata]
  953.         add     eax, hid_data.input.first_report
  954.         cmp     [last_reports+0*4], eax
  955.         jz      .invalid_report
  956. ; Everything is ok.
  957.         inc     [report_ok]
  958.         jmp     .end
  959. .memory_error:
  960.         mov     esi, nomemory_msg
  961. .end_str:
  962.         invoke  SysMsgBoardStr
  963. .end:
  964. ; Free all global_items structures.
  965.         test    edi, edi
  966.         jz      @f
  967.         push    [edi+global_items.next]
  968.         xchg    eax, edi
  969.         invoke  Kfree
  970.         pop     edi
  971.         jmp     .end
  972. @@:
  973. ; Free the last Usage list, if any.
  974.         mov     eax, [usage_list]
  975. @@:
  976.         test    eax, eax
  977.         jz      @f
  978.         push    [eax+usage_list_item.next]
  979.         invoke  Kfree
  980.         pop     eax
  981.         jmp     @b
  982. @@:
  983. }
  984.  
  985. ; Assign drivers to top-level HID collections.
  986. ; The caller should provide ebx = pointer to hid_data and a local variable
  987. ; [has_driver], it will be initialized with 0 if no driver is present.
  988. macro postprocess_descr
  989. {
  990. postprocess_report_label:
  991. ; Assign drivers to top-level collections.
  992. ; Use mouse driver for Usage(GenericDesktop:Mouse),
  993. ; use keyboard driver for Usage(GenericDesktop:Keyboard)
  994. ; and Usage(GenericDesktop:Keypad)
  995. ; 1. Prepare for the loop: get the pointer to the first collection,
  996. ; store that no drivers were assigned yet.
  997.         mov     edi, [ebx+hid_data.first_collection]
  998. if ~HID_DUMP_UNCLAIMED
  999.         mov     [has_driver], 0
  1000. end if
  1001. .next_collection:
  1002. ; 2. Test whether there is a collection to test; if no, break from the loop.
  1003.         test    edi, edi
  1004.         jz      .postprocess_done
  1005. ; 3. Get pointer to driver callbacks depending on [collection.usage].
  1006. ; If [collection.usage] is unknown, use default driver if HID_DUMP_UNCLAIMED
  1007. ; and do not assign a driver otherwise.
  1008.         mov     esi, mouse_driver
  1009.         cmp     [edi+collection.usage], USAGE_GD_POINTER
  1010.         jz      .has_driver
  1011.         cmp     [edi+collection.usage], USAGE_GD_MOUSE
  1012.         jz      .has_driver
  1013.         mov     esi, keyboard_driver
  1014.         cmp     [edi+collection.usage], USAGE_GD_KEYBOARD
  1015.         jz      .has_driver
  1016.         cmp     [edi+collection.usage], USAGE_GD_KEYPAD
  1017.         jz      .has_driver
  1018.         mov     esi, multimedia_driver
  1019.         cmp     [edi+collection.usage], USAGE_GD_CONS_CTRL
  1020.         jz      .has_driver
  1021. if HID_DUMP_UNCLAIMED
  1022.         mov     esi, default_driver
  1023. else
  1024.         xor     esi, esi
  1025. end if
  1026. ; 4. If no driver is assigned (possible only if not HID_DUMP_UNCLAIMED),
  1027. ; go to 7 with driver data = 0;
  1028. ; other code uses this as a sign that driver callbacks should not be called.
  1029. .has_driver:
  1030.         xor     eax, eax
  1031. if ~HID_DUMP_UNCLAIMED
  1032.         test    esi, esi
  1033.         jz      .set_driver
  1034. end if
  1035. ; 5. Notify the driver about new device.
  1036.         call    [esi+hid_driver_callbacks.add_device]
  1037. ; 6. If the driver has returned non-zero driver data,
  1038. ; store that is an assigned driver.
  1039. ; Otherwise, if HID_DUMP_UNCLAIMED, try to assign the default driver.
  1040. if HID_DUMP_UNCLAIMED
  1041.         test    eax, eax
  1042.         jnz     .set_driver
  1043.         mov     esi, default_driver
  1044.         call    [esi+hid_driver_callbacks.add_device]
  1045. else
  1046.         test    eax, eax
  1047.         jz      @f
  1048.         mov     [has_driver], 1
  1049.         jmp     .set_driver
  1050. @@:
  1051.         xor     esi, esi
  1052. end if
  1053. .set_driver:
  1054. ; 7. Store driver data. If a driver is assigned, copy driver callbacks.
  1055.         mov     [edi+collection.driver_data], eax
  1056.         test    esi, esi
  1057.         jz      @f
  1058.         push    edi
  1059.         lodsd   ; skip hid_driver_callbacks.add_device
  1060.         add     edi, collection.callbacks
  1061. repeat sizeof.hid_driver_active_callbacks / 4
  1062.         movsd
  1063. end repeat
  1064.         pop     edi
  1065. @@:
  1066. ; 8. Store pointer to the collection in all input reports belonging to it.
  1067. ; Note that the HID spec requires that reports should not cross top-level collections.
  1068.         mov     eax, [edi+collection.input.first_report]
  1069.         test    eax, eax
  1070.         jz      .reports_processed
  1071. .next_report:
  1072.         mov     [eax+report.top_level_collection], edi
  1073.         cmp     eax, [edi+collection.input.last_report]
  1074.         mov     eax, [eax+report.next]
  1075.         jnz     .next_report
  1076. .reports_processed:
  1077.         mov     edi, [edi+collection.next]
  1078.         jmp     .next_collection
  1079. .postprocess_done:
  1080. }
  1081.  
  1082. ; Cleanup all resources allocated during parse_descr and postprocess_descr.
  1083. ; Called when the corresponding device is disconnected
  1084. ; with ebx = pointer to hid_data.
  1085. macro hid_cleanup
  1086. {
  1087. ; 1. Notify all assigned drivers about disconnect.
  1088. ; Loop over all top-level collections and call callbacks.disconnect,
  1089. ; if a driver is assigned.
  1090.         mov     esi, [ebx+hid_data.first_collection]
  1091. .notify_drivers:
  1092.         test    esi, esi
  1093.         jz      .notify_drivers_done
  1094.         mov     edi, [esi+collection.driver_data]
  1095.         test    edi, edi
  1096.         jz      @f
  1097.         call    [esi+collection.callbacks.disconnect]
  1098. @@:
  1099.         mov     esi, [esi+collection.next]
  1100.         jmp     .notify_drivers
  1101. .notify_drivers_done:
  1102. ; 2. Free all collections.
  1103.         mov     esi, [ebx+hid_data.first_collection]
  1104. .free_collections:
  1105.         test    esi, esi
  1106.         jz      .collections_done
  1107. ; If a collection has childen, make it forget about them,
  1108. ; kill all children; after last child is killed, return to
  1109. ; the collection as a parent; this time, it will appear
  1110. ; as childless, so it will be killed after children.
  1111.         mov     eax, [esi+collection.first_child]
  1112.         test    eax, eax
  1113.         jz      .no_children
  1114.         and     [esi+collection.first_child], 0
  1115.         xchg    esi, eax
  1116.         jmp     .free_collections
  1117. .no_children:
  1118. ; If a collection has no children (maybe there were no children at all,
  1119. ; maybe all children were already killed), kill it and proceed either to
  1120. ; next sibling (if any) or to the parent.
  1121.         mov     eax, [esi+collection.next]
  1122.         test    eax, eax
  1123.         jnz     @f
  1124.         mov     eax, [esi+collection.parent]
  1125. @@:
  1126.         xchg    eax, esi
  1127.         invoke  Kfree
  1128.         jmp     .free_collections
  1129. .collections_done:
  1130. ; 3. Free all three report sets.
  1131.         push    3
  1132.         lea     esi, [ebx+hid_data.input]
  1133. ; For every report set, loop over all reports,
  1134. ; for every report free all field groups, then free report itself.
  1135. ; When all reports in one set have been freed, free also report list table,
  1136. ; if there is one (reports are numbered).
  1137. .report_set_loop:
  1138.         mov     edi, [esi+report_set.first_report]
  1139. .report_loop:
  1140.         test    edi, edi
  1141.         jz      .report_done
  1142.         mov     eax, [edi+report.first_field]
  1143. .field_loop:
  1144.         test    eax, eax
  1145.         jz      .field_done
  1146.         push    [eax+report_field_group.next]
  1147.         invoke  Kfree
  1148.         pop     eax
  1149.         jmp     .field_loop
  1150. .field_done:
  1151.         mov     eax, [edi+report.next]
  1152.         xchg    eax, edi
  1153.         invoke  Kfree
  1154.         jmp     .report_loop
  1155. .report_done:
  1156.         cmp     [esi+report_set.numbered], 0
  1157.         jz      @f
  1158.         mov     eax, [esi+report_set.data]
  1159.         invoke  Kfree
  1160. @@:
  1161.         add     esi, sizeof.report_set
  1162.         dec     dword [esp]
  1163.         jnz     .report_set_loop
  1164.         pop     eax
  1165. }
  1166.  
  1167. ; Helper for parse_input. Extracts value of one field.
  1168. ; in: esi -> report_field_group
  1169. ; in: eax = offset in bits from report start
  1170. ; in: report -> report data
  1171. ; out: edx = value
  1172. ; Note: it can read one dword past report data.
  1173. macro extract_field_value report
  1174. {
  1175.         mov     ecx, eax
  1176.         shr     eax, 5
  1177.         shl     eax, 2
  1178.         add     eax, report
  1179.         and     ecx, 31
  1180.         mov     edx, [eax]
  1181.         mov     eax, [eax+4]
  1182.         shrd    edx, eax, cl
  1183.         mov     ecx, [esi+report_field_group.sign_mask]
  1184.         and     ecx, edx
  1185.         and     edx, [esi+report_field_group.mask]
  1186.         sub     edx, ecx
  1187. }
  1188.  
  1189. ; Local variables for parse_input.
  1190. macro parse_input_locals
  1191. {
  1192. count_inside_group      dd      ?
  1193. ; Number of fields left in the current field.
  1194. field_offset            dd      ?
  1195. ; Offset of the current field from report start, in bits.
  1196. field_range_size                dd      ?
  1197. ; Size of range with valid values, Logical Maximum - Logical Minimum + 1.
  1198. cur_usage               dd      ?
  1199. ; Pointer to current usage for Variable field groups.
  1200. num_values              dd      ?
  1201. ; Number of values in the current instantiation of Array field group.
  1202. values_base             dd      ?
  1203. ; Pointer to memory allocated for array with current values.
  1204. values_prev             dd      ?
  1205. ; Pointer to memory allocated for array with previous values.
  1206. values_cur_ptr          dd      ?
  1207. ; Pointer to the next value in [values_base] array.
  1208. values_end              dd      ?
  1209. ; End of data in array with current values.
  1210. values_prev_ptr         dd      ?
  1211. ; Pointer to the next value in [values_prev_ptr] array.
  1212. values_prev_end         dd      ?
  1213. ; End of data in array with previous values.
  1214. }
  1215.  
  1216. ; Parse input report. The caller should provide esi = pointer to report,
  1217. ; local variables parse_input_locals and [buffer] = report data.
  1218. macro parse_input
  1219. {
  1220. ; 1. Ignore the report if there is no driver for it.
  1221.         mov     ebx, [esi+report.top_level_collection]
  1222.         mov     edi, [ebx+collection.driver_data]
  1223.         test    edi, edi
  1224.         jz      .done
  1225. ; 2. Notify the driver that a new packet arrived.
  1226.         call    [ebx+collection.callbacks.begin_packet]
  1227. ; Loop over all field groups.
  1228. ; Report without fields is meaningless, but theoretically possible:
  1229. ; parse_descr does not create reports of zero size, but
  1230. ; a report can consist of "padding" fields without usages and have
  1231. ; no real fields.
  1232.         mov     esi, [esi+report.first_field]
  1233.         test    esi, esi
  1234.         jz      .packet_processed
  1235. .field_loop:
  1236. ; 3. Prepare for group handling: initialize field offset, fields count
  1237. ; and size of range for valid values.
  1238.         mov     eax, [esi+report_field_group.offset]
  1239.         mov     [field_offset], eax
  1240.         mov     ecx, [esi+report_field_group.count]
  1241.         mov     [count_inside_group], ecx
  1242.         mov     eax, [esi+report_field_group.logical_maximum]
  1243.         inc     eax
  1244.         sub     eax, [esi+report_field_group.logical_minimum]
  1245.         mov     [field_range_size], eax
  1246. ; 4. Select handler. Variable and Array groups are handled entirely differently;
  1247. ; for Variable groups, advance to 5, for Array groups, go to 6.
  1248.         test    byte [esi+report_field_group.flags], HID_FIELD_VARIABLE
  1249.         jz      .array_field
  1250. ; 5. Variable groups. They are simple. Loop over all .count fields,
  1251. ; for every field extract the value and get the next usage,
  1252. ; if the value is within valid range, call the driver.
  1253.         lea     eax, [esi+report_field_group.common_sizeof]
  1254.         mov     [cur_usage], eax
  1255. .variable_data_loop:
  1256.         mov     eax, [field_offset]
  1257.         extract_field_value [buffer]    ; -> edx
  1258.         mov     ecx, [cur_usage]
  1259.         mov     ecx, [ecx]
  1260.         call    [ebx+collection.callbacks.input_field]
  1261.         add     [cur_usage], 4
  1262.         mov     eax, [esi+report_field_group.size]
  1263.         add     [field_offset], eax
  1264.         dec     [count_inside_group]
  1265.         jnz     .variable_data_loop
  1266. ; Variable group is processed; go to 12.
  1267.         jmp     .field_done
  1268. .array_field:
  1269. ; Array groups. They are complicated.
  1270. ; 6. Array group: extract all values in one array.
  1271. ; memory was allocated during group creation, use it
  1272. ; 6a. Prepare: get data pointer, initialize num_values with zero.
  1273.         mov     eax, [esi+report_field_group.num_usage_ranges]
  1274.         lea     edx, [esi+report_field_group.usages+eax*sizeof.usage_range+4]
  1275.         mov     eax, [esi+report_field_group.count]
  1276.         mov     [values_cur_ptr], edx
  1277.         mov     [values_base], edx
  1278.         lea     edx, [edx+ecx*4]
  1279.         mov     [values_prev], edx
  1280.         mov     [values_prev_ptr], edx
  1281.         mov     [num_values], 0
  1282. ; 6b. Start loop for every field. Note that there must be at least one field,
  1283. ; parse_descr does not allow .count == 0.
  1284. .array_getval_loop:
  1285. ; 6c. Extract the value of the current field.
  1286.         mov     eax, [field_offset]
  1287.         extract_field_value [buffer]    ; -> edx
  1288. ; 6d. Transform the value to the usage with binary search in array of
  1289. ; usage_ranges. started at [esi+report_field_group.usages]
  1290. ; having [esi+report_field_group.num_usage_ranges] items.
  1291. ; Ignore items outside of valid range.
  1292.         sub     edx, [esi+report_field_group.logical_minimum]
  1293.         cmp     edx, [field_range_size]
  1294.         jae     .array_skip_item
  1295. ; If there are too few usages, use last of them.
  1296.         mov     ecx, [esi+report_field_group.num_usage_ranges]  ; upper bound
  1297.         xor     eax, eax        ; lower bound
  1298.         cmp     edx, [esi+report_field_group.usages+ecx*sizeof.usage_range+usage_range.offset]
  1299.         jae     .array_last_usage
  1300. ; loop invariant: usages[eax].offset <= edx < usages[ecx].offset
  1301. .array_find_usage:
  1302.         lea     edi, [eax+ecx]
  1303.         shr     edi, 1
  1304.         cmp     edi, eax
  1305.         jz      .array_found_usage_range
  1306.         cmp     edx, [esi+report_field_group.usages+edi*sizeof.usage_range+usage_range.offset]
  1307.         jae     .update_low
  1308.         mov     ecx, edi
  1309.         jmp     .array_find_usage
  1310. .update_low:
  1311.         mov     eax, edi
  1312.         jmp     .array_find_usage
  1313. .array_last_usage:
  1314.         lea     eax, [ecx-1]
  1315.         mov     edx, [esi+report_field_group.usages+ecx*sizeof.usage_range+usage_range.offset]
  1316.         dec     edx
  1317. .array_found_usage_range:
  1318.         sub     edx, [esi+report_field_group.usages+eax*sizeof.usage_range+usage_range.offset]
  1319.         add     edx, [esi+report_field_group.usages+eax*sizeof.usage_range+usage_range.first_usage]
  1320. ; 6e. Store the usage, advance data pointer, continue loop started at 6b.
  1321.         mov     eax, [values_cur_ptr]
  1322.         mov     [eax], edx
  1323.         add     [values_cur_ptr], 4
  1324.         inc     [num_values]
  1325. .array_skip_item:
  1326.         mov     eax, [esi+report_field_group.size]
  1327.         add     [field_offset], eax
  1328.         dec     [count_inside_group]
  1329.         jnz     .array_getval_loop
  1330. ; 7. Array group: ask driver about array overflow.
  1331. ; If driver says that the array is invalid, stop processing this group
  1332. ; (in particular, do not update previous values).
  1333.         mov     ecx, [num_values]
  1334.         test    ecx, ecx
  1335.         jz      .duplicates_removed
  1336.         mov     edx, [values_base]
  1337.         mov     edi, [ebx+collection.driver_data]
  1338.         call    [ebx+collection.callbacks.array_overflow?]
  1339.         jnc     .field_done
  1340. ; 8. Array group: sort the array with current values.
  1341.         push    esi
  1342.         mov     ecx, [num_values]
  1343.         mov     edx, [values_base]
  1344.         call    sort
  1345.         pop     esi
  1346. ; 9. Array group: remove duplicates.
  1347.         cmp     [num_values], 1
  1348.         jbe     .duplicates_removed
  1349.         mov     eax, [values_base]
  1350.         mov     edx, [eax]
  1351.         add     eax, 4
  1352.         mov     ecx, eax
  1353. .duplicates_loop:
  1354.         cmp     edx, [eax]
  1355.         jz      @f
  1356.         mov     edx, [eax]
  1357.         mov     [ecx], edx
  1358.         add     ecx, 4
  1359. @@:
  1360.         add     eax, 4
  1361.         cmp     eax, [values_cur_ptr]
  1362.         jb      .duplicates_loop
  1363.         mov     [values_cur_ptr], ecx
  1364.         sub     ecx, [values_base]
  1365.         shr     ecx, 2
  1366.         mov     [num_values], ecx
  1367. .duplicates_removed:
  1368. ; 10. Array group: compare current and previous values,
  1369. ; call driver for differences.
  1370.         mov     edi, [ebx+collection.driver_data]
  1371.         mov     eax, [values_cur_ptr]
  1372.         mov     [values_end], eax
  1373.         mov     eax, [values_base]
  1374.         mov     [values_cur_ptr], eax
  1375.         mov     eax, [esi+report_field_group.num_values_prev]
  1376.         shl     eax, 2
  1377.         add     eax, [values_prev]
  1378.         mov     [values_prev_end], eax
  1379. .find_common:
  1380.         mov     eax, [values_cur_ptr]
  1381.         cmp     eax, [values_end]
  1382.         jae     .cur_done
  1383.         mov     ecx, [eax]
  1384.         mov     eax, [values_prev_ptr]
  1385.         cmp     eax, [values_prev_end]
  1386.         jae     .prev_done
  1387.         mov     edx, [eax]
  1388.         cmp     ecx, edx
  1389.         jb      .advance_cur
  1390.         ja      .advance_prev
  1391. ; common item in both arrays; ignore
  1392.         add     [values_cur_ptr], 4
  1393.         add     [values_prev_ptr], 4
  1394.         jmp     .find_common
  1395. .advance_cur:
  1396. ; item is present in current array but not in previous;
  1397. ; call the driver with value = 1
  1398.         add     [values_cur_ptr], 4
  1399.         mov     edx, 1
  1400.         call    [ebx+collection.callbacks.input_field]
  1401.         jmp     .find_common
  1402. .advance_prev:
  1403. ; item is present in previous array but not in current;
  1404. ; call the driver with value = 0
  1405.         add     [values_prev_ptr], 4
  1406.         mov     ecx, edx
  1407.         xor     edx, edx
  1408.         call    [ebx+collection.callbacks.input_field]
  1409.         jmp     .find_common
  1410. .prev_done:
  1411. ; for all items which are left in current array
  1412. ; call the driver with value = 1
  1413.         mov     eax, [values_cur_ptr]
  1414. @@:
  1415.         add     [values_cur_ptr], 4
  1416.         mov     ecx, [eax]
  1417.         mov     edx, 1
  1418.         call    [ebx+collection.callbacks.input_field]
  1419.         mov     eax, [values_cur_ptr]
  1420.         cmp     eax, [values_end]
  1421.         jb      @b
  1422.         jmp     .copy_array
  1423. .cur_done:
  1424. ; for all items which are left in previous array
  1425. ; call the driver with value = 0
  1426.         mov     eax, [values_prev_ptr]
  1427.         add     [values_prev_ptr], 4
  1428.         cmp     eax, [values_prev_end]
  1429.         jae     @f
  1430.         mov     ecx, [eax]
  1431.         xor     edx, edx
  1432.         call    [ebx+collection.callbacks.input_field]
  1433.         jmp     .cur_done
  1434. @@:
  1435. .copy_array:
  1436. ; 11. Array group: copy current values to previous values.
  1437.         push    esi edi
  1438.         mov     ecx, [num_values]
  1439.         mov     [esi+report_field_group.num_values_prev], ecx
  1440.         mov     esi, [values_base]
  1441.         mov     edi, [values_prev]
  1442.         rep movsd
  1443.         pop     edi esi
  1444. ; 12. Field group is processed. Repeat with the next group, if any.
  1445. .field_done:
  1446.         mov     esi, [esi+report_field_group.next]
  1447.         test    esi, esi
  1448.         jnz     .field_loop
  1449. .packet_processed:
  1450. ; 13. Packet is processed, notify the driver.
  1451.         call    [ebx+collection.callbacks.end_packet]
  1452. }
  1453.