mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	media: cec: fix remote control passthrough
The 'Press and Hold' operation was not correctly implemented, in particular the requirement that the repeat doesn't start until the second identical keypress arrives. The REP_DELAY value also had to be adjusted (see the comment in the code) to achieve the desired behavior. The 'enabled_protocols' field was also never set, fix that too. Since CEC is a fixed protocol the driver has to set this field. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
		
							parent
							
								
									d57ea877af
								
							
						
					
					
						commit
						a9a249a2c9
					
				
					 3 changed files with 69 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -1767,6 +1767,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
 | 
			
		|||
	int la_idx = cec_log_addr2idx(adap, dest_laddr);
 | 
			
		||||
	bool from_unregistered = init_laddr == 0xf;
 | 
			
		||||
	struct cec_msg tx_cec_msg = { };
 | 
			
		||||
#ifdef CONFIG_MEDIA_CEC_RC
 | 
			
		||||
	int scancode;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1855,11 +1858,9 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
 | 
			
		|||
		 */
 | 
			
		||||
		case 0x60:
 | 
			
		||||
			if (msg->len == 2)
 | 
			
		||||
				rc_keydown(adap->rc, RC_TYPE_CEC,
 | 
			
		||||
					   msg->msg[2], 0);
 | 
			
		||||
				scancode = msg->msg[2];
 | 
			
		||||
			else
 | 
			
		||||
				rc_keydown(adap->rc, RC_TYPE_CEC,
 | 
			
		||||
					   msg->msg[2] << 8 | msg->msg[3], 0);
 | 
			
		||||
				scancode = msg->msg[2] << 8 | msg->msg[3];
 | 
			
		||||
			break;
 | 
			
		||||
		/*
 | 
			
		||||
		 * Other function messages that are not handled.
 | 
			
		||||
| 
						 | 
				
			
			@ -1872,11 +1873,54 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
 | 
			
		|||
		 */
 | 
			
		||||
		case 0x56: case 0x57:
 | 
			
		||||
		case 0x67: case 0x68: case 0x69: case 0x6a:
 | 
			
		||||
			scancode = -1;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			rc_keydown(adap->rc, RC_TYPE_CEC, msg->msg[2], 0);
 | 
			
		||||
			scancode = msg->msg[2];
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Was repeating, but keypress timed out */
 | 
			
		||||
		if (adap->rc_repeating && !adap->rc->keypressed) {
 | 
			
		||||
			adap->rc_repeating = false;
 | 
			
		||||
			adap->rc_last_scancode = -1;
 | 
			
		||||
		}
 | 
			
		||||
		/* Different keypress from last time, ends repeat mode */
 | 
			
		||||
		if (adap->rc_last_scancode != scancode) {
 | 
			
		||||
			rc_keyup(adap->rc);
 | 
			
		||||
			adap->rc_repeating = false;
 | 
			
		||||
		}
 | 
			
		||||
		/* We can't handle this scancode */
 | 
			
		||||
		if (scancode < 0) {
 | 
			
		||||
			adap->rc_last_scancode = scancode;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Send key press */
 | 
			
		||||
		rc_keydown(adap->rc, RC_TYPE_CEC, scancode, 0);
 | 
			
		||||
 | 
			
		||||
		/* When in repeating mode, we're done */
 | 
			
		||||
		if (adap->rc_repeating)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * We are not repeating, but the new scancode is
 | 
			
		||||
		 * the same as the last one, and this second key press is
 | 
			
		||||
		 * within 550 ms (the 'Follower Safety Timeout') from the
 | 
			
		||||
		 * previous key press, so we now enable the repeating mode.
 | 
			
		||||
		 */
 | 
			
		||||
		if (adap->rc_last_scancode == scancode &&
 | 
			
		||||
		    msg->rx_ts - adap->rc_last_keypress < 550 * NSEC_PER_MSEC) {
 | 
			
		||||
			adap->rc_repeating = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Not in repeating mode, so avoid triggering repeat mode
 | 
			
		||||
		 * by calling keyup.
 | 
			
		||||
		 */
 | 
			
		||||
		rc_keyup(adap->rc);
 | 
			
		||||
		adap->rc_last_scancode = scancode;
 | 
			
		||||
		adap->rc_last_keypress = msg->rx_ts;
 | 
			
		||||
#endif
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1886,6 +1930,8 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
 | 
			
		|||
			break;
 | 
			
		||||
#ifdef CONFIG_MEDIA_CEC_RC
 | 
			
		||||
		rc_keyup(adap->rc);
 | 
			
		||||
		adap->rc_repeating = false;
 | 
			
		||||
		adap->rc_last_scancode = -1;
 | 
			
		||||
#endif
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,9 +276,11 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
 | 
			
		|||
	adap->rc->input_id.version = 1;
 | 
			
		||||
	adap->rc->driver_name = CEC_NAME;
 | 
			
		||||
	adap->rc->allowed_protocols = RC_BIT_CEC;
 | 
			
		||||
	adap->rc->enabled_protocols = RC_BIT_CEC;
 | 
			
		||||
	adap->rc->priv = adap;
 | 
			
		||||
	adap->rc->map_name = RC_MAP_CEC;
 | 
			
		||||
	adap->rc->timeout = MS_TO_NS(100);
 | 
			
		||||
	adap->rc_last_scancode = -1;
 | 
			
		||||
#endif
 | 
			
		||||
	return adap;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -310,6 +312,17 @@ int cec_register_adapter(struct cec_adapter *adap,
 | 
			
		|||
			adap->rc = NULL;
 | 
			
		||||
			return res;
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * The REP_DELAY for CEC is really the time between the initial
 | 
			
		||||
		 * 'User Control Pressed' message and the second. The first
 | 
			
		||||
		 * keypress is always seen as non-repeating, the second
 | 
			
		||||
		 * (provided it has the same UI Command) will start the 'Press
 | 
			
		||||
		 * and Hold' (aka repeat) behavior. By setting REP_DELAY to the
 | 
			
		||||
		 * same value as REP_PERIOD the expected CEC behavior is
 | 
			
		||||
		 * reproduced.
 | 
			
		||||
		 */
 | 
			
		||||
		adap->rc->input_dev->rep[REP_DELAY] =
 | 
			
		||||
			adap->rc->input_dev->rep[REP_PERIOD];
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -190,6 +190,11 @@ struct cec_adapter {
 | 
			
		|||
 | 
			
		||||
	u32 tx_timeouts;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MEDIA_CEC_RC
 | 
			
		||||
	bool rc_repeating;
 | 
			
		||||
	int rc_last_scancode;
 | 
			
		||||
	u64 rc_last_keypress;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef CONFIG_CEC_NOTIFIER
 | 
			
		||||
	struct cec_notifier *notifier;
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue