Merge "msm: hdcp: add response timeout and new messages for sink"
This commit is contained in:
commit
c2cbb11bf9
1 changed files with 119 additions and 52 deletions
|
@ -65,7 +65,8 @@
|
|||
#define REPEATER_AUTH_SEND_ACK_MESSAGE_ID 15
|
||||
#define REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID 16
|
||||
#define REPEATER_AUTH_STREAM_READY_MESSAGE_ID 17
|
||||
#define HDCP2P2_MAX_MESSAGES 18
|
||||
#define SKE_SEND_TYPE_ID 18
|
||||
#define HDCP2P2_MAX_MESSAGES 19
|
||||
|
||||
#define HDCP1_SET_KEY_MESSAGE_ID 202
|
||||
#define HDCP1_SET_ENC_MESSAGE_ID 205
|
||||
|
@ -94,7 +95,7 @@
|
|||
* minimum wait as per standard is 200 ms. keep it 300 ms
|
||||
* to be on safe side.
|
||||
*/
|
||||
#define SLEEP_SET_HW_KEY_MS 300
|
||||
#define SLEEP_SET_HW_KEY_MS 220
|
||||
|
||||
#define QSEECOM_ALIGN_SIZE 0x40
|
||||
#define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1)
|
||||
|
@ -187,6 +188,9 @@ static const struct hdcp_msg_data hdcp_msg_lookup[HDCP2P2_MAX_MESSAGES] = {
|
|||
[SKE_SEND_EKS_MESSAGE_ID] = { 2,
|
||||
{ {"Edkey_ks", 0x69318, 16}, {"riv", 0x69328, 8} },
|
||||
0 },
|
||||
[SKE_SEND_TYPE_ID] = { 1,
|
||||
{ {"type", 0x69494, 1} },
|
||||
0 },
|
||||
[REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID] = { 4,
|
||||
{ {"RxInfo", 0x69330, 2}, {"seq_num_V", 0x69332, 3},
|
||||
{"V'", 0x69335, 16}, {"ridlist", 0x69345, 155} },
|
||||
|
@ -499,8 +503,10 @@ struct hdcp_lib_handle {
|
|||
uint32_t tz_ctxhandle;
|
||||
uint32_t hdcp_timeout;
|
||||
uint32_t timeout_left;
|
||||
uint32_t wait_timeout;
|
||||
bool no_stored_km_flag;
|
||||
bool feature_supported;
|
||||
bool authenticated;
|
||||
void *client_ctx;
|
||||
struct hdcp_client_ops *client_ops;
|
||||
struct mutex msg_lock;
|
||||
|
@ -521,7 +527,7 @@ struct hdcp_lib_handle {
|
|||
enum hdcp_device_type device_type;
|
||||
|
||||
struct task_struct *thread;
|
||||
struct completion topo_wait;
|
||||
struct completion poll_wait;
|
||||
|
||||
struct kthread_worker worker;
|
||||
struct kthread_work wk_init;
|
||||
|
@ -529,7 +535,7 @@ struct hdcp_lib_handle {
|
|||
struct kthread_work wk_msg_recvd;
|
||||
struct kthread_work wk_timeout;
|
||||
struct kthread_work wk_clean;
|
||||
struct kthread_work wk_topology;
|
||||
struct kthread_work wk_wait;
|
||||
struct kthread_work wk_stream;
|
||||
|
||||
int (*hdcp_app_init)(struct hdcp_lib_handle *handle);
|
||||
|
@ -574,6 +580,7 @@ static const char *hdcp_lib_message_name(int msg_id)
|
|||
{15, "REPEATER_AUTH_SEND_ACK"},
|
||||
{16, "REPEATER_AUTH_STREAM_MANAGE"},
|
||||
{17, "REPEATER_AUTH_STREAM_READY"},
|
||||
{18, "SKE_SEND_TYPE_ID"},
|
||||
};
|
||||
int i;
|
||||
|
||||
|
@ -612,8 +619,14 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
|
|||
case LC_SEND_L_PRIME_MESSAGE_ID:
|
||||
return SKE_SEND_EKS_MESSAGE_ID;
|
||||
case SKE_SEND_EKS_MESSAGE_ID:
|
||||
if (!handle->repeater_flag)
|
||||
return SKE_SEND_TYPE_ID;
|
||||
case SKE_SEND_TYPE_ID:
|
||||
case REPEATER_AUTH_STREAM_READY_MESSAGE_ID:
|
||||
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
|
||||
if (!handle->repeater_flag)
|
||||
return INVALID_MESSAGE_ID;
|
||||
|
||||
if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE)
|
||||
return REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID;
|
||||
else
|
||||
|
@ -628,6 +641,33 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
|
|||
}
|
||||
}
|
||||
|
||||
static void hdcp_lib_wait_for_response(struct hdcp_lib_handle *handle,
|
||||
struct hdmi_hdcp_wakeup_data *data)
|
||||
{
|
||||
switch (handle->last_msg) {
|
||||
case AKE_SEND_H_PRIME_MESSAGE_ID:
|
||||
if (handle->no_stored_km_flag)
|
||||
handle->wait_timeout = HZ;
|
||||
else
|
||||
handle->wait_timeout = HZ / 4;
|
||||
break;
|
||||
case AKE_SEND_PAIRING_INFO_MESSAGE_ID:
|
||||
handle->wait_timeout = HZ / 4;
|
||||
break;
|
||||
case REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID:
|
||||
if (!handle->authenticated)
|
||||
handle->wait_timeout = HZ * 3;
|
||||
else
|
||||
handle->wait_timeout = 0;
|
||||
break;
|
||||
default:
|
||||
handle->wait_timeout = 0;
|
||||
}
|
||||
|
||||
if (handle->wait_timeout)
|
||||
queue_kthread_work(&handle->worker, &handle->wk_wait);
|
||||
}
|
||||
|
||||
static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
|
||||
struct hdmi_hdcp_wakeup_data *data)
|
||||
{
|
||||
|
@ -639,43 +679,42 @@ static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
|
|||
|
||||
data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE;
|
||||
|
||||
if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE ||
|
||||
data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
|
||||
data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL) {
|
||||
if (data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
|
||||
data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL)
|
||||
handle->last_msg = hdcp_lib_get_next_message(handle, data);
|
||||
|
||||
if (handle->last_msg != INVALID_MESSAGE_ID &&
|
||||
data->cmd != HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS &&
|
||||
data->cmd != HDMI_HDCP_WKUP_CMD_STATUS_FAILED) {
|
||||
u32 msg_num, rx_status;
|
||||
const struct hdcp_msg_part *msg;
|
||||
|
||||
pr_debug("lib->client: %s (%s)\n",
|
||||
hdmi_hdcp_cmd_to_str(data->cmd),
|
||||
hdcp_lib_message_name(handle->last_msg));
|
||||
|
||||
if (handle->last_msg > INVALID_MESSAGE_ID &&
|
||||
handle->last_msg < HDCP2P2_MAX_MESSAGES) {
|
||||
u32 msg_num, rx_status;
|
||||
const struct hdcp_msg_part *msg;
|
||||
data->message_data = &hdcp_msg_lookup[handle->last_msg];
|
||||
|
||||
data->message_data = &hdcp_msg_lookup[handle->last_msg];
|
||||
msg_num = data->message_data->num_messages;
|
||||
msg = data->message_data->messages;
|
||||
rx_status = data->message_data->rx_status;
|
||||
|
||||
msg_num = data->message_data->num_messages;
|
||||
msg = data->message_data->messages;
|
||||
rx_status = data->message_data->rx_status;
|
||||
pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
|
||||
|
||||
pr_debug("rxstatus 0x%x\n", rx_status);
|
||||
pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
|
||||
|
||||
for (i = 0; i < msg_num; i++)
|
||||
pr_debug("%10s | %6x | %4d\n",
|
||||
msg[i].name, msg[i].offset,
|
||||
msg[i].length);
|
||||
}
|
||||
for (i = 0; i < msg_num; i++)
|
||||
pr_debug("%10s | %6x | %4d\n",
|
||||
msg[i].name, msg[i].offset,
|
||||
msg[i].length);
|
||||
} else {
|
||||
pr_debug("lib->client: %s\n",
|
||||
hdmi_hdcp_cmd_to_str(data->cmd));
|
||||
pr_debug("lib->client: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));
|
||||
}
|
||||
|
||||
rc = handle->client_ops->wakeup(data);
|
||||
if (rc)
|
||||
pr_err("error sending %s to client\n",
|
||||
hdmi_hdcp_cmd_to_str(data->cmd));
|
||||
|
||||
hdcp_lib_wait_for_response(handle, data);
|
||||
}
|
||||
|
||||
static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
|
||||
|
@ -1286,6 +1325,8 @@ static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle)
|
|||
hdcp_lib_message_name((int)rsp_buf->message[0]),
|
||||
jiffies_to_msecs(jiffies));
|
||||
|
||||
handle->last_msg = (int)rsp_buf->message[0];
|
||||
|
||||
/* send the response to HDMI driver */
|
||||
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
|
||||
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
|
||||
|
@ -1404,6 +1445,8 @@ static int hdcp_lib_start_auth(struct hdcp_lib_handle *handle)
|
|||
hdcp_lib_message_name((int)rsp_buf->message[0]),
|
||||
jiffies_to_msecs(jiffies));
|
||||
|
||||
handle->last_msg = (int)rsp_buf->message[0];
|
||||
|
||||
/* send the response to HDMI driver */
|
||||
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
|
||||
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
|
||||
|
@ -1470,6 +1513,8 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle)
|
|||
pr_debug("message received from TZ: %s\n",
|
||||
hdcp_lib_message_name((int)rsp_buf->msg[0]));
|
||||
|
||||
handle->last_msg = (int)rsp_buf->msg[0];
|
||||
|
||||
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
|
||||
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg,
|
||||
rsp_buf->msglen);
|
||||
|
@ -1550,11 +1595,11 @@ static void hdcp_lib_check_worker_status(struct hdcp_lib_handle *handle)
|
|||
if (handle->worker.current_work == &handle->wk_clean)
|
||||
pr_debug("clean work executing\n");
|
||||
|
||||
if (!list_empty(&handle->wk_topology.node))
|
||||
pr_debug("topology work queued\n");
|
||||
if (!list_empty(&handle->wk_wait.node))
|
||||
pr_debug("wait work queued\n");
|
||||
|
||||
if (handle->worker.current_work == &handle->wk_topology)
|
||||
pr_debug("topology work executing\n");
|
||||
if (handle->worker.current_work == &handle->wk_wait)
|
||||
pr_debug("wait work executing\n");
|
||||
|
||||
if (!list_empty(&handle->wk_stream.node))
|
||||
pr_debug("stream work queued\n");
|
||||
|
@ -1613,7 +1658,7 @@ static void hdcp_lib_update_exec_type(void *ctx, bool tethered)
|
|||
mutex_unlock(&handle->wakeup_mutex);
|
||||
}
|
||||
|
||||
static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
||||
static int hdcp_lib_wakeup_thread(struct hdcp_lib_wakeup_data *data)
|
||||
{
|
||||
struct hdcp_lib_handle *handle;
|
||||
int rc = 0;
|
||||
|
@ -1630,8 +1675,9 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
|||
handle->wakeup_cmd = data->cmd;
|
||||
handle->timeout_left = data->timeout;
|
||||
|
||||
pr_debug("client->lib: %s\n",
|
||||
hdcp_lib_cmd_to_str(handle->wakeup_cmd));
|
||||
pr_debug("client->lib: %s (%s)\n",
|
||||
hdcp_lib_cmd_to_str(data->cmd),
|
||||
hdcp_lib_message_name(handle->last_msg));
|
||||
|
||||
rc = hdcp_lib_check_valid_state(handle);
|
||||
if (rc)
|
||||
|
@ -1655,8 +1701,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
|||
}
|
||||
mutex_unlock(&handle->msg_lock);
|
||||
|
||||
if (!completion_done(&handle->topo_wait))
|
||||
complete_all(&handle->topo_wait);
|
||||
if (!completion_done(&handle->poll_wait))
|
||||
complete_all(&handle->poll_wait);
|
||||
|
||||
switch (handle->wakeup_cmd) {
|
||||
case HDCP_LIB_WKUP_CMD_START:
|
||||
|
@ -1719,22 +1765,30 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle)
|
|||
cdata.context = handle->client_ctx;
|
||||
|
||||
switch (handle->last_msg_sent) {
|
||||
case SKE_SEND_EKS_MESSAGE_ID:
|
||||
if (handle->repeater_flag) {
|
||||
if (!atomic_read(&handle->hdcp_off))
|
||||
queue_kthread_work(&handle->worker,
|
||||
&handle->wk_topology);
|
||||
}
|
||||
|
||||
case SKE_SEND_TYPE_ID:
|
||||
if (!hdcp_lib_enable_encryption(handle)) {
|
||||
handle->authenticated = true;
|
||||
|
||||
cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
|
||||
hdcp_lib_wakeup_client(handle, &cdata);
|
||||
}
|
||||
|
||||
/* poll for link check */
|
||||
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
|
||||
break;
|
||||
case SKE_SEND_EKS_MESSAGE_ID:
|
||||
if (handle->repeater_flag) {
|
||||
/* poll for link check */
|
||||
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
|
||||
} else {
|
||||
if (!atomic_read(&handle->hdcp_off))
|
||||
HDCP_LIB_EXECUTE(clean);
|
||||
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
|
||||
handle->listener_buf[0] = SKE_SEND_TYPE_ID;
|
||||
handle->msglen = 2;
|
||||
cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE;
|
||||
cdata.send_msg_buf = handle->listener_buf;
|
||||
cdata.send_msg_len = handle->msglen;
|
||||
handle->last_msg = hdcp_lib_get_next_message(handle,
|
||||
&cdata);
|
||||
}
|
||||
break;
|
||||
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
|
||||
|
@ -1915,6 +1969,8 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
|
|||
return;
|
||||
}
|
||||
|
||||
handle->authenticated = false;
|
||||
|
||||
hdcp_lib_txmtr_deinit(handle);
|
||||
if (!handle->legacy_app)
|
||||
hdcp_lib_session_deinit(handle);
|
||||
|
@ -2040,6 +2096,13 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
|
|||
(rc == 0) && (rsp_buf->status == 0)) {
|
||||
pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n");
|
||||
|
||||
if (!hdcp_lib_enable_encryption(handle)) {
|
||||
handle->authenticated = true;
|
||||
|
||||
cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
|
||||
hdcp_lib_wakeup_client(handle, &cdata);
|
||||
}
|
||||
|
||||
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -2057,6 +2120,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
|
|||
hdcp_lib_message_name((int)rsp_buf->msg[0]),
|
||||
jiffies_to_msecs(jiffies));
|
||||
|
||||
handle->last_msg = (int)rsp_buf->msg[0];
|
||||
|
||||
/* set the flag if response is AKE_No_Stored_km */
|
||||
if (((int)rsp_buf->msg[0] == AKE_NO_STORED_KM_MESSAGE_ID)) {
|
||||
pr_debug("Setting no_stored_km_flag\n");
|
||||
|
@ -2101,12 +2166,11 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
|
|||
hdcp_lib_msg_recvd(handle);
|
||||
}
|
||||
|
||||
static void hdcp_lib_topology_work(struct kthread_work *work)
|
||||
static void hdcp_lib_wait_work(struct kthread_work *work)
|
||||
{
|
||||
u32 timeout;
|
||||
struct hdcp_lib_handle *handle = container_of(work,
|
||||
struct hdcp_lib_handle,
|
||||
wk_topology);
|
||||
struct hdcp_lib_handle, wk_wait);
|
||||
|
||||
if (!handle) {
|
||||
pr_err("invalid input\n");
|
||||
|
@ -2123,14 +2187,17 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
|
|||
return;
|
||||
}
|
||||
|
||||
reinit_completion(&handle->topo_wait);
|
||||
timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3);
|
||||
reinit_completion(&handle->poll_wait);
|
||||
timeout = wait_for_completion_timeout(&handle->poll_wait,
|
||||
handle->wait_timeout);
|
||||
if (!timeout) {
|
||||
pr_err("topology receiver id list timeout\n");
|
||||
pr_err("wait timeout\n");
|
||||
|
||||
if (!atomic_read(&handle->hdcp_off))
|
||||
HDCP_LIB_EXECUTE(clean);
|
||||
}
|
||||
|
||||
handle->wait_timeout = 0;
|
||||
}
|
||||
|
||||
bool hdcp1_check_if_supported_load_app(void)
|
||||
|
@ -2266,7 +2333,7 @@ int hdcp_library_register(struct hdcp_register_data *data)
|
|||
|
||||
/* populate ops to be called by client */
|
||||
data->txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
|
||||
data->txmtr_ops->wakeup = hdcp_lib_wakeup;
|
||||
data->txmtr_ops->wakeup = hdcp_lib_wakeup_thread;
|
||||
data->txmtr_ops->update_exec_type = hdcp_lib_update_exec_type;
|
||||
|
||||
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
|
||||
|
@ -2296,10 +2363,10 @@ int hdcp_library_register(struct hdcp_register_data *data)
|
|||
init_kthread_work(&handle->wk_msg_recvd, hdcp_lib_msg_recvd_work);
|
||||
init_kthread_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work);
|
||||
init_kthread_work(&handle->wk_clean, hdcp_lib_cleanup_work);
|
||||
init_kthread_work(&handle->wk_topology, hdcp_lib_topology_work);
|
||||
init_kthread_work(&handle->wk_wait, hdcp_lib_wait_work);
|
||||
init_kthread_work(&handle->wk_stream, hdcp_lib_query_stream_work);
|
||||
|
||||
init_completion(&handle->topo_wait);
|
||||
init_completion(&handle->poll_wait);
|
||||
|
||||
handle->listener_buf = kzalloc(MAX_TX_MESSAGE_SIZE, GFP_KERNEL);
|
||||
if (!(handle->listener_buf)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue