forked from mirrors/linux
		
	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
	
	 Hans Verkuil
						Hans Verkuil