120835280SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0 220835280SMauro Carvalho Chehab // rc-ir-raw.c - handle IR pulse/space events 320835280SMauro Carvalho Chehab // 420835280SMauro Carvalho Chehab // Copyright (C) 2010 by Mauro Carvalho Chehab 54924a311SDavid Härdeman 64924a311SDavid Härdeman #include <linux/export.h> 74924a311SDavid Härdeman #include <linux/kthread.h> 84924a311SDavid Härdeman #include <linux/mutex.h> 94924a311SDavid Härdeman #include <linux/kmod.h> 104924a311SDavid Härdeman #include <linux/sched.h> 114924a311SDavid Härdeman #include "rc-core-priv.h" 124924a311SDavid Härdeman 134924a311SDavid Härdeman /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ 144924a311SDavid Härdeman static LIST_HEAD(ir_raw_client_list); 154924a311SDavid Härdeman 164924a311SDavid Härdeman /* Used to handle IR raw handler extensions */ 17f4364dcfSSean Young DEFINE_MUTEX(ir_raw_handler_lock); 184924a311SDavid Härdeman static LIST_HEAD(ir_raw_handler_list); 1937e90a22SHeiner Kallweit static atomic64_t available_protocols = ATOMIC64_INIT(0); 204924a311SDavid Härdeman 214924a311SDavid Härdeman static int ir_raw_event_thread(void *data) 224924a311SDavid Härdeman { 234924a311SDavid Härdeman struct ir_raw_event ev; 244924a311SDavid Härdeman struct ir_raw_handler *handler; 2548231f28SSean Young struct ir_raw_event_ctrl *raw = data; 2648231f28SSean Young struct rc_dev *dev = raw->dev; 274924a311SDavid Härdeman 2874d47d75SHeiner Kallweit while (1) { 294924a311SDavid Härdeman mutex_lock(&ir_raw_handler_lock); 3074d47d75SHeiner Kallweit while (kfifo_out(&raw->kfifo, &ev, 1)) { 3148231f28SSean Young if (is_timing_event(ev)) { 3248231f28SSean Young if (ev.duration == 0) 330ca54b29SSean Young dev_warn_once(&dev->dev, "nonsensical timing event of duration 0"); 3448231f28SSean Young if (is_timing_event(raw->prev_ev) && 3548231f28SSean Young !is_transition(&ev, &raw->prev_ev)) 360ca54b29SSean Young dev_warn_once(&dev->dev, "two consecutive events of type %s", 3748231f28SSean Young TO_STR(ev.pulse)); 3848231f28SSean Young if (raw->prev_ev.reset && ev.pulse == 0) 390ca54b29SSean Young dev_warn_once(&dev->dev, "timing event after reset should be pulse"); 4048231f28SSean Young } 414924a311SDavid Härdeman list_for_each_entry(handler, &ir_raw_handler_list, list) 4248231f28SSean Young if (dev->enabled_protocols & 4374d47d75SHeiner Kallweit handler->protocols || !handler->protocols) 4448231f28SSean Young handler->decode(dev, ev); 4575992a44SSean Young lirc_raw_event(dev, ev); 464924a311SDavid Härdeman raw->prev_ev = ev; 4774d47d75SHeiner Kallweit } 484924a311SDavid Härdeman mutex_unlock(&ir_raw_handler_lock); 4974d47d75SHeiner Kallweit 5074d47d75SHeiner Kallweit set_current_state(TASK_INTERRUPTIBLE); 5174d47d75SHeiner Kallweit 5274d47d75SHeiner Kallweit if (kthread_should_stop()) { 5374d47d75SHeiner Kallweit __set_current_state(TASK_RUNNING); 5474d47d75SHeiner Kallweit break; 5574d47d75SHeiner Kallweit } else if (!kfifo_is_empty(&raw->kfifo)) 5674d47d75SHeiner Kallweit set_current_state(TASK_RUNNING); 5774d47d75SHeiner Kallweit 5874d47d75SHeiner Kallweit schedule(); 594924a311SDavid Härdeman } 604924a311SDavid Härdeman 614924a311SDavid Härdeman return 0; 624924a311SDavid Härdeman } 634924a311SDavid Härdeman 644924a311SDavid Härdeman /** 654924a311SDavid Härdeman * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders 664924a311SDavid Härdeman * @dev: the struct rc_dev device descriptor 674924a311SDavid Härdeman * @ev: the struct ir_raw_event descriptor of the pulse/space 684924a311SDavid Härdeman * 694924a311SDavid Härdeman * This routine (which may be called from an interrupt context) stores a 704924a311SDavid Härdeman * pulse/space duration for the raw ir decoding state machines. Pulses are 714924a311SDavid Härdeman * signalled as positive values and spaces as negative values. A zero value 724924a311SDavid Härdeman * will reset the decoding state machines. 734924a311SDavid Härdeman */ 744924a311SDavid Härdeman int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) 754924a311SDavid Härdeman { 764924a311SDavid Härdeman if (!dev->raw) 774924a311SDavid Härdeman return -EINVAL; 784924a311SDavid Härdeman 791f17f684SSean Young dev_dbg(&dev->dev, "sample: (%05dus %s)\n", 80528222d8SSean Young ev->duration, TO_STR(ev->pulse)); 814924a311SDavid Härdeman 82464254e5SHeiner Kallweit if (!kfifo_put(&dev->raw->kfifo, *ev)) { 83464254e5SHeiner Kallweit dev_err(&dev->dev, "IR event FIFO is full!\n"); 84464254e5SHeiner Kallweit return -ENOSPC; 85464254e5SHeiner Kallweit } 864924a311SDavid Härdeman 874924a311SDavid Härdeman return 0; 884924a311SDavid Härdeman } 894924a311SDavid Härdeman EXPORT_SYMBOL_GPL(ir_raw_event_store); 904924a311SDavid Härdeman 914924a311SDavid Härdeman /** 924924a311SDavid Härdeman * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space 934924a311SDavid Härdeman * @dev: the struct rc_dev device descriptor 9486fe1ac0SSean Young * @pulse: true for pulse, false for space 954924a311SDavid Härdeman * 964924a311SDavid Härdeman * This routine (which may be called from an interrupt context) is used to 974924a311SDavid Härdeman * store the beginning of an ir pulse or space (or the start/end of ir 984924a311SDavid Härdeman * reception) for the raw ir decoding state machines. This is used by 994924a311SDavid Härdeman * hardware which does not provide durations directly but only interrupts 1004924a311SDavid Härdeman * (or similar events) on state change. 1014924a311SDavid Härdeman */ 10286fe1ac0SSean Young int ir_raw_event_store_edge(struct rc_dev *dev, bool pulse) 1034924a311SDavid Härdeman { 1044924a311SDavid Härdeman ktime_t now; 105183e19f5SSean Young struct ir_raw_event ev = {}; 1064924a311SDavid Härdeman 1074924a311SDavid Härdeman if (!dev->raw) 1084924a311SDavid Härdeman return -EINVAL; 1094924a311SDavid Härdeman 1104924a311SDavid Härdeman now = ktime_get(); 111528222d8SSean Young ev.duration = ktime_to_us(ktime_sub(now, dev->raw->last_event)); 11286fe1ac0SSean Young ev.pulse = !pulse; 1134924a311SDavid Härdeman 1148d7a77ceSSean Young return ir_raw_event_store_with_timeout(dev, &ev); 1158d7a77ceSSean Young } 1168d7a77ceSSean Young EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); 1178d7a77ceSSean Young 1188d7a77ceSSean Young /* 1198d7a77ceSSean Young * ir_raw_event_store_with_timeout() - pass a pulse/space duration to the raw 1208d7a77ceSSean Young * ir decoders, schedule decoding and 1218d7a77ceSSean Young * timeout 1228d7a77ceSSean Young * @dev: the struct rc_dev device descriptor 1238d7a77ceSSean Young * @ev: the struct ir_raw_event descriptor of the pulse/space 1248d7a77ceSSean Young * 1258d7a77ceSSean Young * This routine (which may be called from an interrupt context) stores a 1268d7a77ceSSean Young * pulse/space duration for the raw ir decoding state machines, schedules 1278d7a77ceSSean Young * decoding and generates a timeout. 1288d7a77ceSSean Young */ 1298d7a77ceSSean Young int ir_raw_event_store_with_timeout(struct rc_dev *dev, struct ir_raw_event *ev) 1308d7a77ceSSean Young { 1318d7a77ceSSean Young ktime_t now; 1328d7a77ceSSean Young int rc = 0; 1338d7a77ceSSean Young 1348d7a77ceSSean Young if (!dev->raw) 1358d7a77ceSSean Young return -EINVAL; 1368d7a77ceSSean Young 1378d7a77ceSSean Young now = ktime_get(); 1388d7a77ceSSean Young 139e3e389f9SSean Young spin_lock(&dev->raw->edge_spinlock); 1408d7a77ceSSean Young rc = ir_raw_event_store(dev, ev); 1414924a311SDavid Härdeman 1424924a311SDavid Härdeman dev->raw->last_event = now; 143e5e26439SSean Young 14448b2de19SSean Young /* timer could be set to timeout (125ms by default) */ 14548b2de19SSean Young if (!timer_pending(&dev->raw->edge_handle) || 14648b2de19SSean Young time_after(dev->raw->edge_handle.expires, 14748b2de19SSean Young jiffies + msecs_to_jiffies(15))) { 148e5e26439SSean Young mod_timer(&dev->raw->edge_handle, 149e5e26439SSean Young jiffies + msecs_to_jiffies(15)); 15048b2de19SSean Young } 151e3e389f9SSean Young spin_unlock(&dev->raw->edge_spinlock); 152e5e26439SSean Young 1534924a311SDavid Härdeman return rc; 1544924a311SDavid Härdeman } 1558d7a77ceSSean Young EXPORT_SYMBOL_GPL(ir_raw_event_store_with_timeout); 1564924a311SDavid Härdeman 1574924a311SDavid Härdeman /** 1584924a311SDavid Härdeman * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing 1594924a311SDavid Härdeman * @dev: the struct rc_dev device descriptor 160c4365922SMauro Carvalho Chehab * @ev: the event that has occurred 1614924a311SDavid Härdeman * 1624924a311SDavid Härdeman * This routine (which may be called from an interrupt context) works 1634924a311SDavid Härdeman * in similar manner to ir_raw_event_store_edge. 1644924a311SDavid Härdeman * This routine is intended for devices with limited internal buffer 1654924a311SDavid Härdeman * It automerges samples of same type, and handles timeouts. Returns non-zero 1664924a311SDavid Härdeman * if the event was added, and zero if the event was ignored due to idle 1674924a311SDavid Härdeman * processing. 1684924a311SDavid Härdeman */ 1694924a311SDavid Härdeman int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) 1704924a311SDavid Härdeman { 1714924a311SDavid Härdeman if (!dev->raw) 1724924a311SDavid Härdeman return -EINVAL; 1734924a311SDavid Härdeman 1744924a311SDavid Härdeman /* Ignore spaces in idle mode */ 1754924a311SDavid Härdeman if (dev->idle && !ev->pulse) 1764924a311SDavid Härdeman return 0; 1774924a311SDavid Härdeman else if (dev->idle) 1784924a311SDavid Härdeman ir_raw_event_set_idle(dev, false); 1794924a311SDavid Härdeman 1804924a311SDavid Härdeman if (!dev->raw->this_ev.duration) 1814924a311SDavid Härdeman dev->raw->this_ev = *ev; 1824924a311SDavid Härdeman else if (ev->pulse == dev->raw->this_ev.pulse) 1834924a311SDavid Härdeman dev->raw->this_ev.duration += ev->duration; 1844924a311SDavid Härdeman else { 1854924a311SDavid Härdeman ir_raw_event_store(dev, &dev->raw->this_ev); 1864924a311SDavid Härdeman dev->raw->this_ev = *ev; 1874924a311SDavid Härdeman } 1884924a311SDavid Härdeman 18904ad3011SMauro Carvalho Chehab /* Enter idle mode if necessary */ 1904924a311SDavid Härdeman if (!ev->pulse && dev->timeout && 1914924a311SDavid Härdeman dev->raw->this_ev.duration >= dev->timeout) 1924924a311SDavid Härdeman ir_raw_event_set_idle(dev, true); 1934924a311SDavid Härdeman 1944924a311SDavid Härdeman return 1; 1954924a311SDavid Härdeman } 1964924a311SDavid Härdeman EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); 1974924a311SDavid Härdeman 1984924a311SDavid Härdeman /** 1994924a311SDavid Härdeman * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not 2004924a311SDavid Härdeman * @dev: the struct rc_dev device descriptor 2014924a311SDavid Härdeman * @idle: whether the device is idle or not 2024924a311SDavid Härdeman */ 2034924a311SDavid Härdeman void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) 2044924a311SDavid Härdeman { 2054924a311SDavid Härdeman if (!dev->raw) 2064924a311SDavid Härdeman return; 2074924a311SDavid Härdeman 2081f17f684SSean Young dev_dbg(&dev->dev, "%s idle mode\n", idle ? "enter" : "leave"); 2094924a311SDavid Härdeman 2104924a311SDavid Härdeman if (idle) { 2114924a311SDavid Härdeman dev->raw->this_ev.timeout = true; 2124924a311SDavid Härdeman ir_raw_event_store(dev, &dev->raw->this_ev); 213183e19f5SSean Young dev->raw->this_ev = (struct ir_raw_event) {}; 2144924a311SDavid Härdeman } 2154924a311SDavid Härdeman 2164924a311SDavid Härdeman if (dev->s_idle) 2174924a311SDavid Härdeman dev->s_idle(dev, idle); 2184924a311SDavid Härdeman 2194924a311SDavid Härdeman dev->idle = idle; 2204924a311SDavid Härdeman } 2214924a311SDavid Härdeman EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); 2224924a311SDavid Härdeman 2234924a311SDavid Härdeman /** 2244924a311SDavid Härdeman * ir_raw_event_handle() - schedules the decoding of stored ir data 2254924a311SDavid Härdeman * @dev: the struct rc_dev device descriptor 2264924a311SDavid Härdeman * 2274924a311SDavid Härdeman * This routine will tell rc-core to start decoding stored ir data. 2284924a311SDavid Härdeman */ 2294924a311SDavid Härdeman void ir_raw_event_handle(struct rc_dev *dev) 2304924a311SDavid Härdeman { 231963761a0SSean Young if (!dev->raw || !dev->raw->thread) 2324924a311SDavid Härdeman return; 2334924a311SDavid Härdeman 2344924a311SDavid Härdeman wake_up_process(dev->raw->thread); 2354924a311SDavid Härdeman } 2364924a311SDavid Härdeman EXPORT_SYMBOL_GPL(ir_raw_event_handle); 2374924a311SDavid Härdeman 2384924a311SDavid Härdeman /* used internally by the sysfs interface */ 2394924a311SDavid Härdeman u64 2404924a311SDavid Härdeman ir_raw_get_allowed_protocols(void) 2414924a311SDavid Härdeman { 24237e90a22SHeiner Kallweit return atomic64_read(&available_protocols); 2434924a311SDavid Härdeman } 2444924a311SDavid Härdeman 2456d741bfeSSean Young static int change_protocol(struct rc_dev *dev, u64 *rc_proto) 2464924a311SDavid Härdeman { 247a86d6df8SSean Young struct ir_raw_handler *handler; 248a86d6df8SSean Young u32 timeout = 0; 249a86d6df8SSean Young 250c00cb587SSean Young mutex_lock(&ir_raw_handler_lock); 251c00cb587SSean Young list_for_each_entry(handler, &ir_raw_handler_list, list) { 252c00cb587SSean Young if (!(dev->enabled_protocols & handler->protocols) && 253c00cb587SSean Young (*rc_proto & handler->protocols) && handler->raw_register) 254c00cb587SSean Young handler->raw_register(dev); 255c00cb587SSean Young 256c00cb587SSean Young if ((dev->enabled_protocols & handler->protocols) && 257c00cb587SSean Young !(*rc_proto & handler->protocols) && 258c00cb587SSean Young handler->raw_unregister) 259c00cb587SSean Young handler->raw_unregister(dev); 260c00cb587SSean Young } 261c00cb587SSean Young mutex_unlock(&ir_raw_handler_lock); 262c00cb587SSean Young 263a86d6df8SSean Young if (!dev->max_timeout) 264a86d6df8SSean Young return 0; 265a86d6df8SSean Young 266a86d6df8SSean Young mutex_lock(&ir_raw_handler_lock); 267a86d6df8SSean Young list_for_each_entry(handler, &ir_raw_handler_list, list) { 268a86d6df8SSean Young if (handler->protocols & *rc_proto) { 269a86d6df8SSean Young if (timeout < handler->min_timeout) 270a86d6df8SSean Young timeout = handler->min_timeout; 271a86d6df8SSean Young } 272a86d6df8SSean Young } 273a86d6df8SSean Young mutex_unlock(&ir_raw_handler_lock); 274a86d6df8SSean Young 275a86d6df8SSean Young if (timeout == 0) 276a86d6df8SSean Young timeout = IR_DEFAULT_TIMEOUT; 277a86d6df8SSean Young else 278528222d8SSean Young timeout += MS_TO_US(10); 279a86d6df8SSean Young 280a86d6df8SSean Young if (timeout < dev->min_timeout) 281a86d6df8SSean Young timeout = dev->min_timeout; 282a86d6df8SSean Young else if (timeout > dev->max_timeout) 283a86d6df8SSean Young timeout = dev->max_timeout; 284a86d6df8SSean Young 285a86d6df8SSean Young if (dev->s_timeout) 286a86d6df8SSean Young dev->s_timeout(dev, timeout); 287a86d6df8SSean Young else 288a86d6df8SSean Young dev->timeout = timeout; 289a86d6df8SSean Young 2904924a311SDavid Härdeman return 0; 2914924a311SDavid Härdeman } 2924924a311SDavid Härdeman 29393cffffcSHeiner Kallweit static void ir_raw_disable_protocols(struct rc_dev *dev, u64 protocols) 29493cffffcSHeiner Kallweit { 29593cffffcSHeiner Kallweit mutex_lock(&dev->lock); 29693cffffcSHeiner Kallweit dev->enabled_protocols &= ~protocols; 29793cffffcSHeiner Kallweit mutex_unlock(&dev->lock); 29893cffffcSHeiner Kallweit } 29993cffffcSHeiner Kallweit 3003875233dSJames Hogan /** 301844a4f45SAntti Seppälä * ir_raw_gen_manchester() - Encode data with Manchester (bi-phase) modulation. 302844a4f45SAntti Seppälä * @ev: Pointer to pointer to next free event. *@ev is incremented for 303844a4f45SAntti Seppälä * each raw event filled. 304844a4f45SAntti Seppälä * @max: Maximum number of raw events to fill. 305844a4f45SAntti Seppälä * @timings: Manchester modulation timings. 306844a4f45SAntti Seppälä * @n: Number of bits of data. 307844a4f45SAntti Seppälä * @data: Data bits to encode. 308844a4f45SAntti Seppälä * 309844a4f45SAntti Seppälä * Encodes the @n least significant bits of @data using Manchester (bi-phase) 310844a4f45SAntti Seppälä * modulation with the timing characteristics described by @timings, writing up 311844a4f45SAntti Seppälä * to @max raw IR events using the *@ev pointer. 312844a4f45SAntti Seppälä * 313844a4f45SAntti Seppälä * Returns: 0 on success. 314844a4f45SAntti Seppälä * -ENOBUFS if there isn't enough space in the array to fit the 315844a4f45SAntti Seppälä * full encoded data. In this case all @max events will have been 316844a4f45SAntti Seppälä * written. 317844a4f45SAntti Seppälä */ 318844a4f45SAntti Seppälä int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max, 319844a4f45SAntti Seppälä const struct ir_raw_timings_manchester *timings, 320b73bc16dSSean Young unsigned int n, u64 data) 321844a4f45SAntti Seppälä { 322844a4f45SAntti Seppälä bool need_pulse; 323b73bc16dSSean Young u64 i; 324844a4f45SAntti Seppälä int ret = -ENOBUFS; 325844a4f45SAntti Seppälä 326b73bc16dSSean Young i = BIT_ULL(n - 1); 327844a4f45SAntti Seppälä 328ddf9c1bbSSean Young if (timings->leader_pulse) { 329844a4f45SAntti Seppälä if (!max--) 330844a4f45SAntti Seppälä return ret; 331ddf9c1bbSSean Young init_ir_raw_event_duration((*ev), 1, timings->leader_pulse); 332ddf9c1bbSSean Young if (timings->leader_space) { 333844a4f45SAntti Seppälä if (!max--) 334844a4f45SAntti Seppälä return ret; 335ddf9c1bbSSean Young init_ir_raw_event_duration(++(*ev), 0, 336ddf9c1bbSSean Young timings->leader_space); 337844a4f45SAntti Seppälä } 338844a4f45SAntti Seppälä } else { 339844a4f45SAntti Seppälä /* continue existing signal */ 340844a4f45SAntti Seppälä --(*ev); 341844a4f45SAntti Seppälä } 342844a4f45SAntti Seppälä /* from here on *ev will point to the last event rather than the next */ 343844a4f45SAntti Seppälä 344844a4f45SAntti Seppälä while (n && i > 0) { 345844a4f45SAntti Seppälä need_pulse = !(data & i); 346844a4f45SAntti Seppälä if (timings->invert) 347844a4f45SAntti Seppälä need_pulse = !need_pulse; 348844a4f45SAntti Seppälä if (need_pulse == !!(*ev)->pulse) { 349844a4f45SAntti Seppälä (*ev)->duration += timings->clock; 350844a4f45SAntti Seppälä } else { 351844a4f45SAntti Seppälä if (!max--) 352844a4f45SAntti Seppälä goto nobufs; 353844a4f45SAntti Seppälä init_ir_raw_event_duration(++(*ev), need_pulse, 354844a4f45SAntti Seppälä timings->clock); 355844a4f45SAntti Seppälä } 356844a4f45SAntti Seppälä 357844a4f45SAntti Seppälä if (!max--) 358844a4f45SAntti Seppälä goto nobufs; 359844a4f45SAntti Seppälä init_ir_raw_event_duration(++(*ev), !need_pulse, 360844a4f45SAntti Seppälä timings->clock); 361844a4f45SAntti Seppälä i >>= 1; 362844a4f45SAntti Seppälä } 363844a4f45SAntti Seppälä 364844a4f45SAntti Seppälä if (timings->trailer_space) { 365844a4f45SAntti Seppälä if (!(*ev)->pulse) 366844a4f45SAntti Seppälä (*ev)->duration += timings->trailer_space; 367844a4f45SAntti Seppälä else if (!max--) 368844a4f45SAntti Seppälä goto nobufs; 369844a4f45SAntti Seppälä else 370844a4f45SAntti Seppälä init_ir_raw_event_duration(++(*ev), 0, 371844a4f45SAntti Seppälä timings->trailer_space); 372844a4f45SAntti Seppälä } 373844a4f45SAntti Seppälä 374844a4f45SAntti Seppälä ret = 0; 375844a4f45SAntti Seppälä nobufs: 376844a4f45SAntti Seppälä /* point to the next event rather than last event before returning */ 377844a4f45SAntti Seppälä ++(*ev); 378844a4f45SAntti Seppälä return ret; 379844a4f45SAntti Seppälä } 380844a4f45SAntti Seppälä EXPORT_SYMBOL(ir_raw_gen_manchester); 381844a4f45SAntti Seppälä 382844a4f45SAntti Seppälä /** 383caec0984SJames Hogan * ir_raw_gen_pd() - Encode data to raw events with pulse-distance modulation. 384caec0984SJames Hogan * @ev: Pointer to pointer to next free event. *@ev is incremented for 385caec0984SJames Hogan * each raw event filled. 386caec0984SJames Hogan * @max: Maximum number of raw events to fill. 387caec0984SJames Hogan * @timings: Pulse distance modulation timings. 388caec0984SJames Hogan * @n: Number of bits of data. 389caec0984SJames Hogan * @data: Data bits to encode. 390caec0984SJames Hogan * 391caec0984SJames Hogan * Encodes the @n least significant bits of @data using pulse-distance 392caec0984SJames Hogan * modulation with the timing characteristics described by @timings, writing up 393caec0984SJames Hogan * to @max raw IR events using the *@ev pointer. 394caec0984SJames Hogan * 395caec0984SJames Hogan * Returns: 0 on success. 396caec0984SJames Hogan * -ENOBUFS if there isn't enough space in the array to fit the 397caec0984SJames Hogan * full encoded data. In this case all @max events will have been 398caec0984SJames Hogan * written. 399caec0984SJames Hogan */ 400caec0984SJames Hogan int ir_raw_gen_pd(struct ir_raw_event **ev, unsigned int max, 401caec0984SJames Hogan const struct ir_raw_timings_pd *timings, 402caec0984SJames Hogan unsigned int n, u64 data) 403caec0984SJames Hogan { 404caec0984SJames Hogan int i; 405caec0984SJames Hogan int ret; 406caec0984SJames Hogan unsigned int space; 407caec0984SJames Hogan 408caec0984SJames Hogan if (timings->header_pulse) { 409caec0984SJames Hogan ret = ir_raw_gen_pulse_space(ev, &max, timings->header_pulse, 410caec0984SJames Hogan timings->header_space); 411caec0984SJames Hogan if (ret) 412caec0984SJames Hogan return ret; 413caec0984SJames Hogan } 414caec0984SJames Hogan 415caec0984SJames Hogan if (timings->msb_first) { 416caec0984SJames Hogan for (i = n - 1; i >= 0; --i) { 417caec0984SJames Hogan space = timings->bit_space[(data >> i) & 1]; 418caec0984SJames Hogan ret = ir_raw_gen_pulse_space(ev, &max, 419caec0984SJames Hogan timings->bit_pulse, 420caec0984SJames Hogan space); 421caec0984SJames Hogan if (ret) 422caec0984SJames Hogan return ret; 423caec0984SJames Hogan } 424caec0984SJames Hogan } else { 425caec0984SJames Hogan for (i = 0; i < n; ++i, data >>= 1) { 426caec0984SJames Hogan space = timings->bit_space[data & 1]; 427caec0984SJames Hogan ret = ir_raw_gen_pulse_space(ev, &max, 428caec0984SJames Hogan timings->bit_pulse, 429caec0984SJames Hogan space); 430caec0984SJames Hogan if (ret) 431caec0984SJames Hogan return ret; 432caec0984SJames Hogan } 433caec0984SJames Hogan } 434caec0984SJames Hogan 435caec0984SJames Hogan ret = ir_raw_gen_pulse_space(ev, &max, timings->trailer_pulse, 436caec0984SJames Hogan timings->trailer_space); 437caec0984SJames Hogan return ret; 438caec0984SJames Hogan } 439caec0984SJames Hogan EXPORT_SYMBOL(ir_raw_gen_pd); 440caec0984SJames Hogan 441caec0984SJames Hogan /** 442103293beSSean Young * ir_raw_gen_pl() - Encode data to raw events with pulse-length modulation. 443103293beSSean Young * @ev: Pointer to pointer to next free event. *@ev is incremented for 444103293beSSean Young * each raw event filled. 445103293beSSean Young * @max: Maximum number of raw events to fill. 446103293beSSean Young * @timings: Pulse distance modulation timings. 447103293beSSean Young * @n: Number of bits of data. 448103293beSSean Young * @data: Data bits to encode. 449103293beSSean Young * 450103293beSSean Young * Encodes the @n least significant bits of @data using space-distance 451103293beSSean Young * modulation with the timing characteristics described by @timings, writing up 452103293beSSean Young * to @max raw IR events using the *@ev pointer. 453103293beSSean Young * 454103293beSSean Young * Returns: 0 on success. 455103293beSSean Young * -ENOBUFS if there isn't enough space in the array to fit the 456103293beSSean Young * full encoded data. In this case all @max events will have been 457103293beSSean Young * written. 458103293beSSean Young */ 459103293beSSean Young int ir_raw_gen_pl(struct ir_raw_event **ev, unsigned int max, 460103293beSSean Young const struct ir_raw_timings_pl *timings, 461103293beSSean Young unsigned int n, u64 data) 462103293beSSean Young { 463103293beSSean Young int i; 464103293beSSean Young int ret = -ENOBUFS; 465103293beSSean Young unsigned int pulse; 466103293beSSean Young 467103293beSSean Young if (!max--) 468103293beSSean Young return ret; 469103293beSSean Young 470103293beSSean Young init_ir_raw_event_duration((*ev)++, 1, timings->header_pulse); 471103293beSSean Young 472103293beSSean Young if (timings->msb_first) { 473103293beSSean Young for (i = n - 1; i >= 0; --i) { 474103293beSSean Young if (!max--) 475103293beSSean Young return ret; 476103293beSSean Young init_ir_raw_event_duration((*ev)++, 0, 477103293beSSean Young timings->bit_space); 478103293beSSean Young if (!max--) 479103293beSSean Young return ret; 480103293beSSean Young pulse = timings->bit_pulse[(data >> i) & 1]; 481103293beSSean Young init_ir_raw_event_duration((*ev)++, 1, pulse); 482103293beSSean Young } 483103293beSSean Young } else { 484103293beSSean Young for (i = 0; i < n; ++i, data >>= 1) { 485103293beSSean Young if (!max--) 486103293beSSean Young return ret; 487103293beSSean Young init_ir_raw_event_duration((*ev)++, 0, 488103293beSSean Young timings->bit_space); 489103293beSSean Young if (!max--) 490103293beSSean Young return ret; 491103293beSSean Young pulse = timings->bit_pulse[data & 1]; 492103293beSSean Young init_ir_raw_event_duration((*ev)++, 1, pulse); 493103293beSSean Young } 494103293beSSean Young } 495103293beSSean Young 496103293beSSean Young if (!max--) 497103293beSSean Young return ret; 498103293beSSean Young 499103293beSSean Young init_ir_raw_event_duration((*ev)++, 0, timings->trailer_space); 500103293beSSean Young 501103293beSSean Young return 0; 502103293beSSean Young } 503103293beSSean Young EXPORT_SYMBOL(ir_raw_gen_pl); 504103293beSSean Young 505103293beSSean Young /** 5063875233dSJames Hogan * ir_raw_encode_scancode() - Encode a scancode as raw events 5073875233dSJames Hogan * 5083875233dSJames Hogan * @protocol: protocol 5093875233dSJames Hogan * @scancode: scancode filter describing a single scancode 5103875233dSJames Hogan * @events: array of raw events to write into 5113875233dSJames Hogan * @max: max number of raw events 5123875233dSJames Hogan * 5133875233dSJames Hogan * Attempts to encode the scancode as raw events. 5143875233dSJames Hogan * 5153875233dSJames Hogan * Returns: The number of events written. 5163875233dSJames Hogan * -ENOBUFS if there isn't enough space in the array to fit the 5173875233dSJames Hogan * encoding. In this case all @max events will have been written. 5183875233dSJames Hogan * -EINVAL if the scancode is ambiguous or invalid, or if no 5193875233dSJames Hogan * compatible encoder was found. 5203875233dSJames Hogan */ 5216d741bfeSSean Young int ir_raw_encode_scancode(enum rc_proto protocol, u32 scancode, 5223875233dSJames Hogan struct ir_raw_event *events, unsigned int max) 5233875233dSJames Hogan { 5243875233dSJames Hogan struct ir_raw_handler *handler; 5253875233dSJames Hogan int ret = -EINVAL; 5263875233dSJames Hogan u64 mask = 1ULL << protocol; 5273875233dSJames Hogan 5280d39ab0bSSean Young ir_raw_load_modules(&mask); 5290d39ab0bSSean Young 5303875233dSJames Hogan mutex_lock(&ir_raw_handler_lock); 5313875233dSJames Hogan list_for_each_entry(handler, &ir_raw_handler_list, list) { 5323875233dSJames Hogan if (handler->protocols & mask && handler->encode) { 5333875233dSJames Hogan ret = handler->encode(protocol, scancode, events, max); 5343875233dSJames Hogan if (ret >= 0 || ret == -ENOBUFS) 5353875233dSJames Hogan break; 5363875233dSJames Hogan } 5373875233dSJames Hogan } 5383875233dSJames Hogan mutex_unlock(&ir_raw_handler_lock); 5393875233dSJames Hogan 5403875233dSJames Hogan return ret; 5413875233dSJames Hogan } 5423875233dSJames Hogan EXPORT_SYMBOL(ir_raw_encode_scancode); 5433875233dSJames Hogan 544e3e389f9SSean Young /** 545e3e389f9SSean Young * ir_raw_edge_handle() - Handle ir_raw_event_store_edge() processing 546e3e389f9SSean Young * 547e3e389f9SSean Young * @t: timer_list 548e3e389f9SSean Young * 549e3e389f9SSean Young * This callback is armed by ir_raw_event_store_edge(). It does two things: 550e3e389f9SSean Young * first of all, rather than calling ir_raw_event_handle() for each 551e3e389f9SSean Young * edge and waking up the rc thread, 15 ms after the first edge 552e3e389f9SSean Young * ir_raw_event_handle() is called. Secondly, generate a timeout event 553e3e389f9SSean Young * no more IR is received after the rc_dev timeout. 554e3e389f9SSean Young */ 555e3e389f9SSean Young static void ir_raw_edge_handle(struct timer_list *t) 556e5e26439SSean Young { 557b17ec78aSKees Cook struct ir_raw_event_ctrl *raw = from_timer(raw, t, edge_handle); 558b17ec78aSKees Cook struct rc_dev *dev = raw->dev; 559e3e389f9SSean Young unsigned long flags; 560e3e389f9SSean Young ktime_t interval; 56148b2de19SSean Young 562e3e389f9SSean Young spin_lock_irqsave(&dev->raw->edge_spinlock, flags); 563e3e389f9SSean Young interval = ktime_sub(ktime_get(), dev->raw->last_event); 564528222d8SSean Young if (ktime_to_us(interval) >= dev->timeout) { 565183e19f5SSean Young struct ir_raw_event ev = { 566183e19f5SSean Young .timeout = true, 567528222d8SSean Young .duration = ktime_to_us(interval) 568183e19f5SSean Young }; 56948b2de19SSean Young 57048b2de19SSean Young ir_raw_event_store(dev, &ev); 57148b2de19SSean Young } else { 57248b2de19SSean Young mod_timer(&dev->raw->edge_handle, 573528222d8SSean Young jiffies + usecs_to_jiffies(dev->timeout - 574528222d8SSean Young ktime_to_us(interval))); 57548b2de19SSean Young } 576e3e389f9SSean Young spin_unlock_irqrestore(&dev->raw->edge_spinlock, flags); 577e5e26439SSean Young 578e5e26439SSean Young ir_raw_event_handle(dev); 579e5e26439SSean Young } 580e5e26439SSean Young 581cdfaa01cSSean Young /** 582cdfaa01cSSean Young * ir_raw_encode_carrier() - Get carrier used for protocol 583cdfaa01cSSean Young * 584cdfaa01cSSean Young * @protocol: protocol 585cdfaa01cSSean Young * 586cdfaa01cSSean Young * Attempts to find the carrier for the specified protocol 587cdfaa01cSSean Young * 588cdfaa01cSSean Young * Returns: The carrier in Hz 589cdfaa01cSSean Young * -EINVAL if the protocol is invalid, or if no 590cdfaa01cSSean Young * compatible encoder was found. 591cdfaa01cSSean Young */ 592cdfaa01cSSean Young int ir_raw_encode_carrier(enum rc_proto protocol) 593cdfaa01cSSean Young { 594cdfaa01cSSean Young struct ir_raw_handler *handler; 595cdfaa01cSSean Young int ret = -EINVAL; 596cdfaa01cSSean Young u64 mask = BIT_ULL(protocol); 597cdfaa01cSSean Young 598cdfaa01cSSean Young mutex_lock(&ir_raw_handler_lock); 599cdfaa01cSSean Young list_for_each_entry(handler, &ir_raw_handler_list, list) { 600cdfaa01cSSean Young if (handler->protocols & mask && handler->encode) { 601cdfaa01cSSean Young ret = handler->carrier; 602cdfaa01cSSean Young break; 603cdfaa01cSSean Young } 604cdfaa01cSSean Young } 605cdfaa01cSSean Young mutex_unlock(&ir_raw_handler_lock); 606cdfaa01cSSean Young 607cdfaa01cSSean Young return ret; 608cdfaa01cSSean Young } 609cdfaa01cSSean Young EXPORT_SYMBOL(ir_raw_encode_carrier); 610cdfaa01cSSean Young 6114924a311SDavid Härdeman /* 6124924a311SDavid Härdeman * Used to (un)register raw event clients 6134924a311SDavid Härdeman */ 614f56928abSDavid Härdeman int ir_raw_event_prepare(struct rc_dev *dev) 6154924a311SDavid Härdeman { 6164924a311SDavid Härdeman if (!dev) 6174924a311SDavid Härdeman return -EINVAL; 6184924a311SDavid Härdeman 6194924a311SDavid Härdeman dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL); 6204924a311SDavid Härdeman if (!dev->raw) 6214924a311SDavid Härdeman return -ENOMEM; 6224924a311SDavid Härdeman 6234924a311SDavid Härdeman dev->raw->dev = dev; 6244924a311SDavid Härdeman dev->change_protocol = change_protocol; 625e0d51e6cSSean Young dev->idle = true; 626e3e389f9SSean Young spin_lock_init(&dev->raw->edge_spinlock); 627e3e389f9SSean Young timer_setup(&dev->raw->edge_handle, ir_raw_edge_handle, 0); 628464254e5SHeiner Kallweit INIT_KFIFO(dev->raw->kfifo); 6294924a311SDavid Härdeman 630f56928abSDavid Härdeman return 0; 631f56928abSDavid Härdeman } 632f56928abSDavid Härdeman 633f56928abSDavid Härdeman int ir_raw_event_register(struct rc_dev *dev) 634f56928abSDavid Härdeman { 635f56928abSDavid Härdeman struct task_struct *thread; 636f56928abSDavid Härdeman 637a60d64b1SSean Young thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", dev->minor); 638f56928abSDavid Härdeman if (IS_ERR(thread)) 639f56928abSDavid Härdeman return PTR_ERR(thread); 640963761a0SSean Young 641963761a0SSean Young dev->raw->thread = thread; 6424924a311SDavid Härdeman 6434924a311SDavid Härdeman mutex_lock(&ir_raw_handler_lock); 6444924a311SDavid Härdeman list_add_tail(&dev->raw->list, &ir_raw_client_list); 6454924a311SDavid Härdeman mutex_unlock(&ir_raw_handler_lock); 6464924a311SDavid Härdeman 6474924a311SDavid Härdeman return 0; 648f56928abSDavid Härdeman } 6494924a311SDavid Härdeman 650f56928abSDavid Härdeman void ir_raw_event_free(struct rc_dev *dev) 651f56928abSDavid Härdeman { 652f56928abSDavid Härdeman if (!dev) 653f56928abSDavid Härdeman return; 654f56928abSDavid Härdeman 6554924a311SDavid Härdeman kfree(dev->raw); 6564924a311SDavid Härdeman dev->raw = NULL; 6574924a311SDavid Härdeman } 6584924a311SDavid Härdeman 6594924a311SDavid Härdeman void ir_raw_event_unregister(struct rc_dev *dev) 6604924a311SDavid Härdeman { 6614924a311SDavid Härdeman struct ir_raw_handler *handler; 6624924a311SDavid Härdeman 6634924a311SDavid Härdeman if (!dev || !dev->raw) 6644924a311SDavid Härdeman return; 6654924a311SDavid Härdeman 6664924a311SDavid Härdeman kthread_stop(dev->raw->thread); 667e5e26439SSean Young del_timer_sync(&dev->raw->edge_handle); 6684924a311SDavid Härdeman 6694924a311SDavid Härdeman mutex_lock(&ir_raw_handler_lock); 6704924a311SDavid Härdeman list_del(&dev->raw->list); 6714924a311SDavid Härdeman list_for_each_entry(handler, &ir_raw_handler_list, list) 672c00cb587SSean Young if (handler->raw_unregister && 673c00cb587SSean Young (handler->protocols & dev->enabled_protocols)) 6744924a311SDavid Härdeman handler->raw_unregister(dev); 675f4364dcfSSean Young 676f4364dcfSSean Young lirc_bpf_free(dev); 6774924a311SDavid Härdeman 678f56928abSDavid Härdeman ir_raw_event_free(dev); 679f4364dcfSSean Young 680f4364dcfSSean Young /* 681f4364dcfSSean Young * A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so 682f4364dcfSSean Young * ensure that the raw member is null on unlock; this is how 683f4364dcfSSean Young * "device gone" is checked. 684f4364dcfSSean Young */ 685f4364dcfSSean Young mutex_unlock(&ir_raw_handler_lock); 6864924a311SDavid Härdeman } 6874924a311SDavid Härdeman 6884924a311SDavid Härdeman /* 6894924a311SDavid Härdeman * Extension interface - used to register the IR decoders 6904924a311SDavid Härdeman */ 6914924a311SDavid Härdeman 6924924a311SDavid Härdeman int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) 6934924a311SDavid Härdeman { 6944924a311SDavid Härdeman mutex_lock(&ir_raw_handler_lock); 6954924a311SDavid Härdeman list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); 69637e90a22SHeiner Kallweit atomic64_or(ir_raw_handler->protocols, &available_protocols); 6974924a311SDavid Härdeman mutex_unlock(&ir_raw_handler_lock); 6984924a311SDavid Härdeman 6994924a311SDavid Härdeman return 0; 7004924a311SDavid Härdeman } 7014924a311SDavid Härdeman EXPORT_SYMBOL(ir_raw_handler_register); 7024924a311SDavid Härdeman 7034924a311SDavid Härdeman void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) 7044924a311SDavid Härdeman { 7054924a311SDavid Härdeman struct ir_raw_event_ctrl *raw; 70693cffffcSHeiner Kallweit u64 protocols = ir_raw_handler->protocols; 7074924a311SDavid Härdeman 7084924a311SDavid Härdeman mutex_lock(&ir_raw_handler_lock); 7094924a311SDavid Härdeman list_del(&ir_raw_handler->list); 71093cffffcSHeiner Kallweit list_for_each_entry(raw, &ir_raw_client_list, list) { 711c00cb587SSean Young if (ir_raw_handler->raw_unregister && 712c00cb587SSean Young (raw->dev->enabled_protocols & protocols)) 7134924a311SDavid Härdeman ir_raw_handler->raw_unregister(raw->dev); 714c00cb587SSean Young ir_raw_disable_protocols(raw->dev, protocols); 71593cffffcSHeiner Kallweit } 71637e90a22SHeiner Kallweit atomic64_andnot(protocols, &available_protocols); 7174924a311SDavid Härdeman mutex_unlock(&ir_raw_handler_lock); 7184924a311SDavid Härdeman } 7194924a311SDavid Härdeman EXPORT_SYMBOL(ir_raw_handler_unregister); 720