1 /* 2 * MEI Library for mei bus nfc device access 3 * 4 * Copyright (C) 2013 Intel Corporation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20 21 #include <linux/module.h> 22 #include <linux/slab.h> 23 #include <linux/nfc.h> 24 25 #include "mei_phy.h" 26 27 struct mei_nfc_hdr { 28 u8 cmd; 29 u8 status; 30 u16 req_id; 31 u32 reserved; 32 u16 data_size; 33 } __packed; 34 35 struct mei_nfc_cmd { 36 struct mei_nfc_hdr hdr; 37 u8 sub_command; 38 u8 data[]; 39 } __packed; 40 41 struct mei_nfc_reply { 42 struct mei_nfc_hdr hdr; 43 u8 sub_command; 44 u8 reply_status; 45 u8 data[]; 46 } __packed; 47 48 struct mei_nfc_if_version { 49 u8 radio_version_sw[3]; 50 u8 reserved[3]; 51 u8 radio_version_hw[3]; 52 u8 i2c_addr; 53 u8 fw_ivn; 54 u8 vendor_id; 55 u8 radio_type; 56 } __packed; 57 58 struct mei_nfc_connect { 59 u8 fw_ivn; 60 u8 vendor_id; 61 } __packed; 62 63 struct mei_nfc_connect_resp { 64 u8 fw_ivn; 65 u8 vendor_id; 66 u16 me_major; 67 u16 me_minor; 68 u16 me_hotfix; 69 u16 me_build; 70 } __packed; 71 72 73 #define MEI_NFC_CMD_MAINTENANCE 0x00 74 #define MEI_NFC_CMD_HCI_SEND 0x01 75 #define MEI_NFC_CMD_HCI_RECV 0x02 76 77 #define MEI_NFC_SUBCMD_CONNECT 0x00 78 #define MEI_NFC_SUBCMD_IF_VERSION 0x01 79 80 #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) 81 82 #define MEI_DUMP_SKB_IN(info, skb) \ 83 do { \ 84 pr_debug("%s:\n", info); \ 85 print_hex_dump_debug("mei in : ", DUMP_PREFIX_OFFSET, \ 86 16, 1, (skb)->data, (skb)->len, false); \ 87 } while (0) 88 89 #define MEI_DUMP_SKB_OUT(info, skb) \ 90 do { \ 91 pr_debug("%s:\n", info); \ 92 print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET, \ 93 16, 1, (skb)->data, (skb)->len, false); \ 94 } while (0) 95 96 #define MEI_DUMP_NFC_HDR(info, _hdr) \ 97 do { \ 98 pr_debug("%s:\n", info); \ 99 pr_debug("cmd=%02d status=%d req_id=%d rsvd=%d size=%d\n", \ 100 (_hdr)->cmd, (_hdr)->status, (_hdr)->req_id, \ 101 (_hdr)->reserved, (_hdr)->data_size); \ 102 } while (0) 103 104 static int mei_nfc_if_version(struct nfc_mei_phy *phy) 105 { 106 107 struct mei_nfc_cmd cmd; 108 struct mei_nfc_reply *reply = NULL; 109 struct mei_nfc_if_version *version; 110 size_t if_version_length; 111 int bytes_recv, r; 112 113 pr_info("%s\n", __func__); 114 115 memset(&cmd, 0, sizeof(struct mei_nfc_cmd)); 116 cmd.hdr.cmd = MEI_NFC_CMD_MAINTENANCE; 117 cmd.hdr.data_size = 1; 118 cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION; 119 120 MEI_DUMP_NFC_HDR("version", &cmd.hdr); 121 r = mei_cl_send(phy->device, (u8 *)&cmd, sizeof(struct mei_nfc_cmd)); 122 if (r < 0) { 123 pr_err("Could not send IF version cmd\n"); 124 return r; 125 } 126 127 /* to be sure on the stack we alloc memory */ 128 if_version_length = sizeof(struct mei_nfc_reply) + 129 sizeof(struct mei_nfc_if_version); 130 131 reply = kzalloc(if_version_length, GFP_KERNEL); 132 if (!reply) 133 return -ENOMEM; 134 135 bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, if_version_length); 136 if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) { 137 pr_err("Could not read IF version\n"); 138 r = -EIO; 139 goto err; 140 } 141 142 version = (struct mei_nfc_if_version *)reply->data; 143 144 phy->fw_ivn = version->fw_ivn; 145 phy->vendor_id = version->vendor_id; 146 phy->radio_type = version->radio_type; 147 148 err: 149 kfree(reply); 150 return r; 151 } 152 153 static int mei_nfc_connect(struct nfc_mei_phy *phy) 154 { 155 struct mei_nfc_cmd *cmd, *reply; 156 struct mei_nfc_connect *connect; 157 struct mei_nfc_connect_resp *connect_resp; 158 size_t connect_length, connect_resp_length; 159 int bytes_recv, r; 160 161 pr_info("%s\n", __func__); 162 163 connect_length = sizeof(struct mei_nfc_cmd) + 164 sizeof(struct mei_nfc_connect); 165 166 connect_resp_length = sizeof(struct mei_nfc_cmd) + 167 sizeof(struct mei_nfc_connect_resp); 168 169 cmd = kzalloc(connect_length, GFP_KERNEL); 170 if (!cmd) 171 return -ENOMEM; 172 connect = (struct mei_nfc_connect *)cmd->data; 173 174 reply = kzalloc(connect_resp_length, GFP_KERNEL); 175 if (!reply) { 176 kfree(cmd); 177 return -ENOMEM; 178 } 179 180 connect_resp = (struct mei_nfc_connect_resp *)reply->data; 181 182 cmd->hdr.cmd = MEI_NFC_CMD_MAINTENANCE; 183 cmd->hdr.data_size = 3; 184 cmd->sub_command = MEI_NFC_SUBCMD_CONNECT; 185 connect->fw_ivn = phy->fw_ivn; 186 connect->vendor_id = phy->vendor_id; 187 188 MEI_DUMP_NFC_HDR("connect request", &cmd->hdr); 189 r = mei_cl_send(phy->device, (u8 *)cmd, connect_length); 190 if (r < 0) { 191 pr_err("Could not send connect cmd %d\n", r); 192 goto err; 193 } 194 195 bytes_recv = mei_cl_recv(phy->device, (u8 *)reply, connect_resp_length); 196 if (bytes_recv < 0) { 197 r = bytes_recv; 198 pr_err("Could not read connect response %d\n", r); 199 goto err; 200 } 201 202 MEI_DUMP_NFC_HDR("connect reply", &reply->hdr); 203 204 pr_info("IVN 0x%x Vendor ID 0x%x\n", 205 connect_resp->fw_ivn, connect_resp->vendor_id); 206 207 pr_info("ME FW %d.%d.%d.%d\n", 208 connect_resp->me_major, connect_resp->me_minor, 209 connect_resp->me_hotfix, connect_resp->me_build); 210 211 r = 0; 212 213 err: 214 kfree(reply); 215 kfree(cmd); 216 217 return r; 218 } 219 220 static int mei_nfc_send(struct nfc_mei_phy *phy, u8 *buf, size_t length) 221 { 222 struct mei_nfc_hdr *hdr; 223 u8 *mei_buf; 224 int err; 225 226 err = -ENOMEM; 227 mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL); 228 if (!mei_buf) 229 goto out; 230 231 hdr = (struct mei_nfc_hdr *)mei_buf; 232 hdr->cmd = MEI_NFC_CMD_HCI_SEND; 233 hdr->status = 0; 234 hdr->req_id = phy->req_id; 235 hdr->reserved = 0; 236 hdr->data_size = length; 237 238 MEI_DUMP_NFC_HDR("send", hdr); 239 240 memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length); 241 err = mei_cl_send(phy->device, mei_buf, length + MEI_NFC_HEADER_SIZE); 242 if (err < 0) 243 goto out; 244 245 if (!wait_event_interruptible_timeout(phy->send_wq, 246 phy->recv_req_id == phy->req_id, HZ)) { 247 pr_err("NFC MEI command timeout\n"); 248 err = -ETIME; 249 } else { 250 phy->req_id++; 251 } 252 out: 253 kfree(mei_buf); 254 return err; 255 } 256 257 /* 258 * Writing a frame must not return the number of written bytes. 259 * It must return either zero for success, or <0 for error. 260 * In addition, it must not alter the skb 261 */ 262 static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb) 263 { 264 struct nfc_mei_phy *phy = phy_id; 265 int r; 266 267 MEI_DUMP_SKB_OUT("mei frame sent", skb); 268 269 r = mei_nfc_send(phy, skb->data, skb->len); 270 if (r > 0) 271 r = 0; 272 273 return r; 274 } 275 276 static int mei_nfc_recv(struct nfc_mei_phy *phy, u8 *buf, size_t length) 277 { 278 struct mei_nfc_hdr *hdr; 279 int received_length; 280 281 received_length = mei_cl_recv(phy->device, buf, length); 282 if (received_length < 0) 283 return received_length; 284 285 hdr = (struct mei_nfc_hdr *) buf; 286 287 MEI_DUMP_NFC_HDR("receive", hdr); 288 if (hdr->cmd == MEI_NFC_CMD_HCI_SEND) { 289 phy->recv_req_id = hdr->req_id; 290 wake_up(&phy->send_wq); 291 292 return 0; 293 } 294 295 return received_length; 296 } 297 298 299 static void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, 300 void *context) 301 { 302 struct nfc_mei_phy *phy = context; 303 304 if (phy->hard_fault != 0) 305 return; 306 307 if (events & BIT(MEI_CL_EVENT_RX)) { 308 struct sk_buff *skb; 309 int reply_size; 310 311 skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL); 312 if (!skb) 313 return; 314 315 reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ); 316 if (reply_size < MEI_NFC_HEADER_SIZE) { 317 kfree_skb(skb); 318 return; 319 } 320 321 skb_put(skb, reply_size); 322 skb_pull(skb, MEI_NFC_HEADER_SIZE); 323 324 MEI_DUMP_SKB_IN("mei frame read", skb); 325 326 nfc_hci_recv_frame(phy->hdev, skb); 327 } 328 } 329 330 static int nfc_mei_phy_enable(void *phy_id) 331 { 332 int r; 333 struct nfc_mei_phy *phy = phy_id; 334 335 pr_info("%s\n", __func__); 336 337 if (phy->powered == 1) 338 return 0; 339 340 r = mei_cl_enable_device(phy->device); 341 if (r < 0) { 342 pr_err("Could not enable device %d\n", r); 343 return r; 344 } 345 346 r = mei_nfc_if_version(phy); 347 if (r < 0) { 348 pr_err("Could not enable device %d\n", r); 349 goto err; 350 } 351 352 r = mei_nfc_connect(phy); 353 if (r < 0) { 354 pr_err("Could not connect to device %d\n", r); 355 goto err; 356 } 357 358 r = mei_cl_register_event_cb(phy->device, BIT(MEI_CL_EVENT_RX), 359 nfc_mei_event_cb, phy); 360 if (r) { 361 pr_err("Event cb registration failed %d\n", r); 362 goto err; 363 } 364 365 phy->powered = 1; 366 367 return 0; 368 369 err: 370 phy->powered = 0; 371 mei_cl_disable_device(phy->device); 372 return r; 373 } 374 375 static void nfc_mei_phy_disable(void *phy_id) 376 { 377 struct nfc_mei_phy *phy = phy_id; 378 379 pr_info("%s\n", __func__); 380 381 mei_cl_disable_device(phy->device); 382 383 phy->powered = 0; 384 } 385 386 struct nfc_phy_ops mei_phy_ops = { 387 .write = nfc_mei_phy_write, 388 .enable = nfc_mei_phy_enable, 389 .disable = nfc_mei_phy_disable, 390 }; 391 EXPORT_SYMBOL_GPL(mei_phy_ops); 392 393 struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device) 394 { 395 struct nfc_mei_phy *phy; 396 397 phy = kzalloc(sizeof(struct nfc_mei_phy), GFP_KERNEL); 398 if (!phy) 399 return NULL; 400 401 phy->device = device; 402 init_waitqueue_head(&phy->send_wq); 403 mei_cl_set_drvdata(device, phy); 404 405 return phy; 406 } 407 EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc); 408 409 void nfc_mei_phy_free(struct nfc_mei_phy *phy) 410 { 411 mei_cl_disable_device(phy->device); 412 kfree(phy); 413 } 414 EXPORT_SYMBOL_GPL(nfc_mei_phy_free); 415 416 MODULE_LICENSE("GPL"); 417 MODULE_DESCRIPTION("mei bus NFC device interface"); 418