static void qmi_process_qmux(struct qmi_ctxt *ctxt, unsigned char *buf, unsigned sz) { struct qmi_msg msg; /* require a full header */ if (sz < 5) return; /* require a size that matches the buffer size */ if (sz != (buf[0] | (buf[1] << 8))) return; /* only messages from a service (bit7=1) are allowed */ if (buf[2] != 0x80) return; msg.service = buf[3]; msg.client_id = buf[4]; /* annoyingly, CTL messages have a shorter TID */ if (buf[3] == 0) { if (sz < 7) return; msg.txn_id = buf[6]; buf += 7; sz -= 7; } else { if (sz < 8) return; msg.txn_id = buf[6] | (buf[7] << 8); buf += 8; sz -= 8; } /* no type and size!? */ if (sz < 4) return; sz -= 4; msg.type = buf[0] | (buf[1] << 8); msg.size = buf[2] | (buf[3] << 8); msg.tlv = buf + 4; if (sz != msg.size) return; qmi_dump_msg(&msg, "recv"); mutex_lock(&ctxt->lock); switch (msg.service) { case QMI_CTL: qmi_process_ctl_msg(ctxt, &msg); break; case QMI_WDS: qmi_process_wds_msg(ctxt, &msg); break; default: printk(KERN_ERR "qmi: msg from unknown svc 0x%02x\n", msg.service); break; } mutex_unlock(&ctxt->lock); wake_up(&qmi_wait_queue); }
static void qmi_process_qmux(struct qmi_ctxt *ctxt, unsigned char *buf, unsigned sz) { struct qmi_msg msg; if (sz < 5) return; if (sz != (buf[0] | (buf[1] << 8))) return; if (buf[2] != 0x80) return; msg.service = buf[3]; msg.client_id = buf[4]; if (buf[3] == 0) { if (sz < 7) return; msg.txn_id = buf[6]; buf += 7; sz -= 7; } else { if (sz < 8) return; msg.txn_id = buf[6] | (buf[7] << 8); buf += 8; sz -= 8; } if (sz < 4) return; sz -= 4; msg.type = buf[0] | (buf[1] << 8); msg.size = buf[2] | (buf[3] << 8); msg.tlv = buf + 4; if (sz != msg.size) return; qmi_dump_msg(&msg, "recv"); mutex_lock(&ctxt->lock); switch (msg.service) { case QMI_CTL: qmi_process_ctl_msg(ctxt, &msg); break; case QMI_WDS: qmi_process_wds_msg(ctxt, &msg); break; default: printk(KERN_ERR "qmi: msg from unknown svc 0x%02x\n", msg.service); break; } mutex_unlock(&ctxt->lock); wake_up(&qmi_wait_queue); }