1
1
//! Parse linux rc keymaps
2
2
3
- use std:: { collections:: HashMap , ffi:: OsStr , path:: Path } ;
3
+ use std:: { collections:: HashMap , ffi:: OsStr , fmt :: Write , path:: Path } ;
4
4
use toml:: { Table , Value } ;
5
5
6
6
#[ derive( PartialEq , Eq , Debug , Default ) ]
@@ -9,6 +9,7 @@ pub struct Protocol {
9
9
pub protocol : String ,
10
10
pub variant : Option < String > ,
11
11
pub irp : Option < String > ,
12
+ pub rc_protocol : Option < u16 > ,
12
13
pub raw : Option < Vec < Raw > > ,
13
14
pub scancodes : Option < HashMap < String , String > > ,
14
15
}
@@ -120,6 +121,18 @@ fn parse_toml(contents: &str, filename: &Path) -> Result<Keymap, String> {
120
121
variant = Some ( entry. to_owned ( ) ) ;
121
122
}
122
123
124
+ let mut rc_protocol = None ;
125
+ if let Some ( Value :: Integer ( n) ) = entry. get ( "rc_protocol" ) {
126
+ if let Ok ( n) = ( * n) . try_into ( ) {
127
+ rc_protocol = Some ( n) ;
128
+ } else {
129
+ return Err ( format ! (
130
+ "{}: rc_protocol {n} must be 16 bit value" ,
131
+ filename. display( )
132
+ ) ) ;
133
+ }
134
+ }
135
+
123
136
let mut irp = None ;
124
137
let mut raw = None ;
125
138
let mut scancodes = None ;
@@ -184,6 +197,11 @@ fn parse_toml(contents: &str, filename: &Path) -> Result<Keymap, String> {
184
197
if let Some ( Value :: String ( entry) ) = entry. get ( "irp" ) {
185
198
irp = Some ( entry. to_owned ( ) ) ;
186
199
}
200
+ } else if entry. get ( "irp" ) . is_some ( ) {
201
+ return Err ( "set the protocol to irp when using irp" . to_string ( ) ) ;
202
+ } else if let Some ( rewrite) = bpf_protocol_irp ( protocol, entry. as_table ( ) . unwrap ( ) ) {
203
+ log:: info!( "{}: protocol {protocol} has been rewritten to irp {rewrite}" , filename. display( ) ) ;
204
+ irp = Some ( rewrite) ;
187
205
}
188
206
189
207
if let Some ( Value :: Table ( codes) ) = entry. get ( "scancodes" ) {
@@ -206,6 +224,7 @@ fn parse_toml(contents: &str, filename: &Path) -> Result<Keymap, String> {
206
224
protocol : protocol. to_owned ( ) ,
207
225
variant,
208
226
raw,
227
+ rc_protocol,
209
228
scancodes,
210
229
irp,
211
230
} ) ;
@@ -214,6 +233,185 @@ fn parse_toml(contents: &str, filename: &Path) -> Result<Keymap, String> {
214
233
Ok ( Keymap { protocols : res } )
215
234
}
216
235
236
+ fn bpf_protocol_irp ( protocol : & str , entry : & Table ) -> Option < String > {
237
+ let param = |name : & str , default : i64 | -> i64 {
238
+ if let Some ( Value :: Integer ( n) ) = entry. get ( name) {
239
+ * n
240
+ } else {
241
+ default
242
+ }
243
+ } ;
244
+
245
+ match protocol {
246
+ "pulse_distance" => {
247
+ let mut irp = "{" . to_owned ( ) ;
248
+ let bits = param ( "bits" , 4 ) ;
249
+
250
+ if param ( "reverse" , 0 ) == 0 {
251
+ irp. push_str ( "msb," ) ;
252
+ }
253
+
254
+ if entry. contains_key ( "carrier" ) {
255
+ write ! ( irp, "{}Hz," , param( "carrier" , 0 ) ) . unwrap ( ) ;
256
+ }
257
+
258
+ if irp. ends_with ( ',' ) {
259
+ irp. pop ( ) ;
260
+ }
261
+
262
+ write ! (
263
+ irp,
264
+ "}}<{},-{}|{},-{}>({},-{},CODE:{},{},-40m" ,
265
+ param( "bit_pulse" , 625 ) ,
266
+ param( "bit_0_space" , 375 ) ,
267
+ param( "bit_pulse" , 625 ) ,
268
+ param( "bit_1_space" , 1625 ) ,
269
+ param( "header_pulse" , 2125 ) ,
270
+ param( "header_space" , 1875 ) ,
271
+ bits,
272
+ param( "trailer_pulse" , 625 ) ,
273
+ )
274
+ . unwrap ( ) ;
275
+
276
+ let header_optional = param ( "header_optional" , 0 ) ;
277
+
278
+ if header_optional > 0 {
279
+ write ! (
280
+ irp,
281
+ ",(CODE:{},{},-40m)*" ,
282
+ bits,
283
+ param( "trailer_pulse" , 625 ) ,
284
+ )
285
+ . unwrap ( ) ;
286
+ } else {
287
+ let repeat_pulse = param ( "repeat_pulse" , 0 ) ;
288
+ if repeat_pulse > 0 {
289
+ write ! (
290
+ irp,
291
+ ",({},-{},{},-40)*" ,
292
+ repeat_pulse,
293
+ param( "repeat_space" , 0 ) ,
294
+ param( "trailer_pulse" , 625 )
295
+ )
296
+ . unwrap ( ) ;
297
+ }
298
+ }
299
+
300
+ write ! ( irp, ") [CODE:0..{}]" , gen_mask( bits) ) . unwrap ( ) ;
301
+
302
+ Some ( irp)
303
+ }
304
+ "pulse_length" => {
305
+ let mut irp = "{" . to_owned ( ) ;
306
+ let bits = param ( "bits" , 4 ) ;
307
+
308
+ if param ( "reverse" , 0 ) == 0 {
309
+ irp. push_str ( "msb," ) ;
310
+ }
311
+
312
+ if entry. contains_key ( "carrier" ) {
313
+ write ! ( irp, "{}Hz," , param( "carrier" , 0 ) ) . unwrap ( ) ;
314
+ }
315
+
316
+ if irp. ends_with ( ',' ) {
317
+ irp. pop ( ) ;
318
+ }
319
+
320
+ write ! (
321
+ irp,
322
+ "}}<{},-{}|{},-{}>({},-{},CODE:{},-40m" ,
323
+ param( "bit_0_pulse" , 375 ) ,
324
+ param( "bit_space" , 625 ) ,
325
+ param( "bit_1_pulse" , 1625 ) ,
326
+ param( "bit_space" , 625 ) ,
327
+ param( "header_pulse" , 2125 ) ,
328
+ param( "header_space" , 1875 ) ,
329
+ bits,
330
+ )
331
+ . unwrap ( ) ;
332
+
333
+ let header_optional = param ( "header_optional" , 0 ) ;
334
+
335
+ if header_optional > 0 {
336
+ write ! ( irp, ",(CODE:{},-40m)*" , bits) . unwrap ( ) ;
337
+ } else {
338
+ let repeat_pulse = param ( "repeat_pulse" , 0 ) ;
339
+ if repeat_pulse > 0 {
340
+ write ! (
341
+ irp,
342
+ ",({},-{},{},-40)*" ,
343
+ repeat_pulse,
344
+ param( "repeat_space" , 0 ) ,
345
+ param( "trailer_pulse" , 625 )
346
+ )
347
+ . unwrap ( ) ;
348
+ }
349
+ }
350
+
351
+ write ! ( irp, ") [CODE:0..{}]" , gen_mask( bits) ) . unwrap ( ) ;
352
+
353
+ Some ( irp)
354
+ }
355
+ "manchester" => {
356
+ let mut irp = "{msb," . to_owned ( ) ;
357
+ let bits = param ( "bits" , 14 ) ;
358
+ let toggle_bit = param ( "toggle_bit" , 100 ) ;
359
+
360
+ if entry. contains_key ( "carrier" ) {
361
+ write ! ( irp, "{}Hz," , param( "carrier" , 0 ) ) . unwrap ( ) ;
362
+ }
363
+
364
+ if irp. ends_with ( ',' ) {
365
+ irp. pop ( ) ;
366
+ }
367
+
368
+ write ! (
369
+ irp,
370
+ "}}<-{},{}|{},-{}>(" ,
371
+ param( "zero_space" , 888 ) ,
372
+ param( "zero_pulse" , 888 ) ,
373
+ param( "one_pulse" , 888 ) ,
374
+ param( "one_space" , 888 ) ,
375
+ )
376
+ . unwrap ( ) ;
377
+
378
+ let header_pulse = param ( "header_pulse" , 0 ) ;
379
+ let header_space = param ( "header_space" , 0 ) ;
380
+
381
+ if header_pulse > 0 && header_space > 0 {
382
+ write ! ( irp, "{},-{}," , header_pulse, header_space) . unwrap ( ) ;
383
+ }
384
+
385
+ if toggle_bit >= bits {
386
+ write ! ( irp, "CODE:{},-40m" , bits, ) . unwrap ( ) ;
387
+ } else {
388
+ let leading = bits - toggle_bit;
389
+ if leading > 1 {
390
+ write ! ( irp, "CODE:{}:{}," , leading - 1 , toggle_bit + 1 ) . unwrap ( ) ;
391
+ }
392
+ write ! ( irp, "T:1," ) . unwrap ( ) ;
393
+ if toggle_bit > 0 {
394
+ write ! ( irp, "CODE:{}," , toggle_bit) . unwrap ( ) ;
395
+ }
396
+ irp. pop ( ) ;
397
+ }
398
+
399
+ write ! ( irp, ",-40m) [CODE:0..{}]" , gen_mask( bits) ) . unwrap ( ) ;
400
+
401
+ Some ( irp)
402
+ }
403
+ _ => None ,
404
+ }
405
+ }
406
+
407
+ fn gen_mask ( v : i64 ) -> u64 {
408
+ if v < 64 {
409
+ ( 1u64 << v) - 1
410
+ } else {
411
+ u64:: MAX
412
+ }
413
+ }
414
+
217
415
#[ test]
218
416
fn parse_toml_test ( ) {
219
417
let s = r#"
@@ -358,3 +556,52 @@ fn parse_text_test() {
358
556
}
359
557
}
360
558
}
559
+
560
+ #[ test]
561
+ fn parse_bpf_toml_test ( ) {
562
+ let s = r#"
563
+ [[protocols]]
564
+ name = "meh"
565
+ protocol = "manchester"
566
+ toggle_bit = 12
567
+ [protocols.scancodes]
568
+ 0x1e3b = "KEY_SELECT"
569
+ 0x1e3d = "KEY_POWER2"
570
+ 0x1e1c = "KEY_TV"
571
+ "# ;
572
+
573
+ let k = parse ( s, Path :: new ( "x.toml" ) ) . unwrap ( ) ;
574
+
575
+ assert_eq ! ( k. protocols[ 0 ] . name, "meh" ) ;
576
+ assert_eq ! ( k. protocols[ 0 ] . protocol, "manchester" ) ;
577
+ assert_eq ! (
578
+ k. protocols[ 0 ] . irp,
579
+ Some ( "{msb}<-888,888|888,-888>(CODE:1:13,T:1,CODE:12,-40m) [CODE:0..16383]" . into( ) )
580
+ ) ;
581
+
582
+ let s = r#"
583
+ [[protocols]]
584
+ name = "meh"
585
+ protocol = "manchester"
586
+ toggle_bit = 1
587
+ carrier = 38000
588
+ header_pulse = 300
589
+ header_space = 350
590
+ [protocols.scancodes]
591
+ 0x1e3b = "KEY_SELECT"
592
+ 0x1e3d = "KEY_POWER2"
593
+ 0x1e1c = "KEY_TV"
594
+ "# ;
595
+
596
+ let k = parse ( s, Path :: new ( "x.toml" ) ) . unwrap ( ) ;
597
+
598
+ assert_eq ! ( k. protocols[ 0 ] . name, "meh" ) ;
599
+ assert_eq ! ( k. protocols[ 0 ] . protocol, "manchester" ) ;
600
+ assert_eq ! (
601
+ k. protocols[ 0 ] . irp,
602
+ Some (
603
+ "{msb,38000Hz}<-888,888|888,-888>(300,-350,CODE:12:2,T:1,CODE:1,-40m) [CODE:0..16383]"
604
+ . into( )
605
+ )
606
+ ) ;
607
+ }
0 commit comments