162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* DVB USB compliant Linux driver for the Afatech 9005 362306a36Sopenharmony_ci * USB1.1 DVB-T receiver. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Standard remote decode function 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Thanks to Afatech who kindly provided information. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include "af9005.h" 1462306a36Sopenharmony_ci/* debug */ 1562306a36Sopenharmony_cistatic int dvb_usb_af9005_remote_debug; 1662306a36Sopenharmony_cimodule_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); 1762306a36Sopenharmony_ciMODULE_PARM_DESC(debug, 1862306a36Sopenharmony_ci "enable (1) or disable (0) debug messages." 1962306a36Sopenharmony_ci DVB_USB_DEBUG_STATUS); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct rc_map_table rc_map_af9005_table[] = { 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci {0x01b7, KEY_POWER}, 2662306a36Sopenharmony_ci {0x01a7, KEY_VOLUMEUP}, 2762306a36Sopenharmony_ci {0x0187, KEY_CHANNELUP}, 2862306a36Sopenharmony_ci {0x017f, KEY_MUTE}, 2962306a36Sopenharmony_ci {0x01bf, KEY_VOLUMEDOWN}, 3062306a36Sopenharmony_ci {0x013f, KEY_CHANNELDOWN}, 3162306a36Sopenharmony_ci {0x01df, KEY_1}, 3262306a36Sopenharmony_ci {0x015f, KEY_2}, 3362306a36Sopenharmony_ci {0x019f, KEY_3}, 3462306a36Sopenharmony_ci {0x011f, KEY_4}, 3562306a36Sopenharmony_ci {0x01ef, KEY_5}, 3662306a36Sopenharmony_ci {0x016f, KEY_6}, 3762306a36Sopenharmony_ci {0x01af, KEY_7}, 3862306a36Sopenharmony_ci {0x0127, KEY_8}, 3962306a36Sopenharmony_ci {0x0107, KEY_9}, 4062306a36Sopenharmony_ci {0x01cf, KEY_ZOOM}, 4162306a36Sopenharmony_ci {0x014f, KEY_0}, 4262306a36Sopenharmony_ci {0x018f, KEY_GOTO}, /* marked jump on the remote */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci {0x00bd, KEY_POWER}, 4562306a36Sopenharmony_ci {0x007d, KEY_VOLUMEUP}, 4662306a36Sopenharmony_ci {0x00fd, KEY_CHANNELUP}, 4762306a36Sopenharmony_ci {0x009d, KEY_MUTE}, 4862306a36Sopenharmony_ci {0x005d, KEY_VOLUMEDOWN}, 4962306a36Sopenharmony_ci {0x00dd, KEY_CHANNELDOWN}, 5062306a36Sopenharmony_ci {0x00ad, KEY_1}, 5162306a36Sopenharmony_ci {0x006d, KEY_2}, 5262306a36Sopenharmony_ci {0x00ed, KEY_3}, 5362306a36Sopenharmony_ci {0x008d, KEY_4}, 5462306a36Sopenharmony_ci {0x004d, KEY_5}, 5562306a36Sopenharmony_ci {0x00cd, KEY_6}, 5662306a36Sopenharmony_ci {0x00b5, KEY_7}, 5762306a36Sopenharmony_ci {0x0075, KEY_8}, 5862306a36Sopenharmony_ci {0x00f5, KEY_9}, 5962306a36Sopenharmony_ci {0x0095, KEY_ZOOM}, 6062306a36Sopenharmony_ci {0x0055, KEY_0}, 6162306a36Sopenharmony_ci {0x00d5, KEY_GOTO}, /* marked jump on the remote */ 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciint rc_map_af9005_table_size = ARRAY_SIZE(rc_map_af9005_table); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int repeatable_keys[] = { 6762306a36Sopenharmony_ci KEY_VOLUMEUP, 6862306a36Sopenharmony_ci KEY_VOLUMEDOWN, 6962306a36Sopenharmony_ci KEY_CHANNELUP, 7062306a36Sopenharmony_ci KEY_CHANNELDOWN 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciint af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, 7462306a36Sopenharmony_ci int *state) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci u16 mark, space; 7762306a36Sopenharmony_ci u32 result; 7862306a36Sopenharmony_ci u8 cust, dat, invdat; 7962306a36Sopenharmony_ci int i; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (len >= 6) { 8262306a36Sopenharmony_ci mark = (u16) (data[0] << 8) + data[1]; 8362306a36Sopenharmony_ci space = (u16) (data[2] << 8) + data[3]; 8462306a36Sopenharmony_ci if (space * 3 < mark) { 8562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { 8662306a36Sopenharmony_ci if (d->last_event == repeatable_keys[i]) { 8762306a36Sopenharmony_ci *state = REMOTE_KEY_REPEAT; 8862306a36Sopenharmony_ci *event = d->last_event; 8962306a36Sopenharmony_ci deb_decode("repeat key, event %x\n", 9062306a36Sopenharmony_ci *event); 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci deb_decode("repeated key ignored (non repeatable)\n"); 9562306a36Sopenharmony_ci return 0; 9662306a36Sopenharmony_ci } else if (len >= 33 * 4) { /*32 bits + start code */ 9762306a36Sopenharmony_ci result = 0; 9862306a36Sopenharmony_ci for (i = 4; i < 4 + 32 * 4; i += 4) { 9962306a36Sopenharmony_ci result <<= 1; 10062306a36Sopenharmony_ci mark = (u16) (data[i] << 8) + data[i + 1]; 10162306a36Sopenharmony_ci mark >>= 1; 10262306a36Sopenharmony_ci space = (u16) (data[i + 2] << 8) + data[i + 3]; 10362306a36Sopenharmony_ci space >>= 1; 10462306a36Sopenharmony_ci if (mark * 2 > space) 10562306a36Sopenharmony_ci result += 1; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci deb_decode("key pressed, raw value %x\n", result); 10862306a36Sopenharmony_ci if ((result & 0xff000000) != 0xfe000000) { 10962306a36Sopenharmony_ci deb_decode 11062306a36Sopenharmony_ci ("doesn't start with 0xfe, ignored\n"); 11162306a36Sopenharmony_ci return 0; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci cust = (result >> 16) & 0xff; 11462306a36Sopenharmony_ci dat = (result >> 8) & 0xff; 11562306a36Sopenharmony_ci invdat = (~result) & 0xff; 11662306a36Sopenharmony_ci if (dat != invdat) { 11762306a36Sopenharmony_ci deb_decode("code != inverted code\n"); 11862306a36Sopenharmony_ci return 0; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci for (i = 0; i < rc_map_af9005_table_size; i++) { 12162306a36Sopenharmony_ci if (rc5_custom(&rc_map_af9005_table[i]) == cust 12262306a36Sopenharmony_ci && rc5_data(&rc_map_af9005_table[i]) == dat) { 12362306a36Sopenharmony_ci *event = rc_map_af9005_table[i].keycode; 12462306a36Sopenharmony_ci *state = REMOTE_KEY_PRESSED; 12562306a36Sopenharmony_ci deb_decode 12662306a36Sopenharmony_ci ("key pressed, event %x\n", *event); 12762306a36Sopenharmony_ci return 0; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci deb_decode("not found in table\n"); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciEXPORT_SYMBOL(rc_map_af9005_table); 13762306a36Sopenharmony_ciEXPORT_SYMBOL(rc_map_af9005_table_size); 13862306a36Sopenharmony_ciEXPORT_SYMBOL(af9005_rc_decode); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciMODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>"); 14162306a36Sopenharmony_ciMODULE_DESCRIPTION 14262306a36Sopenharmony_ci ("Standard remote control decoder for Afatech 9005 DVB-T USB1.1 stick"); 14362306a36Sopenharmony_ciMODULE_VERSION("1.0"); 14462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 145