0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/skbuff.h>
0012
0013 #include "../nfc.h"
0014 #include <net/nfc/nci.h>
0015 #include <net/nfc/nci_core.h>
0016 #include <linux/nfc.h>
0017
0018 struct nci_data {
0019 u8 conn_id;
0020 u8 pipe;
0021 u8 cmd;
0022 const u8 *data;
0023 u32 data_len;
0024 } __packed;
0025
0026 struct nci_hci_create_pipe_params {
0027 u8 src_gate;
0028 u8 dest_host;
0029 u8 dest_gate;
0030 } __packed;
0031
0032 struct nci_hci_create_pipe_resp {
0033 u8 src_host;
0034 u8 src_gate;
0035 u8 dest_host;
0036 u8 dest_gate;
0037 u8 pipe;
0038 } __packed;
0039
0040 struct nci_hci_delete_pipe_noti {
0041 u8 pipe;
0042 } __packed;
0043
0044 struct nci_hci_all_pipe_cleared_noti {
0045 u8 host;
0046 } __packed;
0047
0048 struct nci_hcp_message {
0049 u8 header;
0050 u8 data[];
0051 } __packed;
0052
0053 struct nci_hcp_packet {
0054 u8 header;
0055 struct nci_hcp_message message;
0056 } __packed;
0057
0058 #define NCI_HCI_ANY_SET_PARAMETER 0x01
0059 #define NCI_HCI_ANY_GET_PARAMETER 0x02
0060 #define NCI_HCI_ANY_CLOSE_PIPE 0x04
0061 #define NCI_HCI_ADM_CLEAR_ALL_PIPE 0x14
0062
0063 #define NCI_HFP_NO_CHAINING 0x80
0064
0065 #define NCI_NFCEE_ID_HCI 0x80
0066
0067 #define NCI_EVT_HOT_PLUG 0x03
0068
0069 #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY 0x01
0070 #define NCI_HCI_ADM_CREATE_PIPE 0x10
0071 #define NCI_HCI_ADM_DELETE_PIPE 0x11
0072
0073
0074 #define NCI_HCI_HCP_PACKET_HEADER_LEN 1
0075 #define NCI_HCI_HCP_MESSAGE_HEADER_LEN 1
0076 #define NCI_HCI_HCP_HEADER_LEN 2
0077
0078
0079 #define NCI_HCI_HCP_COMMAND 0x00
0080 #define NCI_HCI_HCP_EVENT 0x01
0081 #define NCI_HCI_HCP_RESPONSE 0x02
0082
0083 #define NCI_HCI_ADM_NOTIFY_PIPE_CREATED 0x12
0084 #define NCI_HCI_ADM_NOTIFY_PIPE_DELETED 0x13
0085 #define NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15
0086
0087 #define NCI_HCI_FRAGMENT 0x7f
0088 #define NCI_HCP_HEADER(type, instr) ((((type) & 0x03) << 6) |\
0089 ((instr) & 0x3f))
0090
0091 #define NCI_HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6)
0092 #define NCI_HCP_MSG_GET_CMD(header) (header & 0x3f)
0093 #define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
0094
0095 static int nci_hci_result_to_errno(u8 result)
0096 {
0097 switch (result) {
0098 case NCI_HCI_ANY_OK:
0099 return 0;
0100 case NCI_HCI_ANY_E_REG_PAR_UNKNOWN:
0101 return -EOPNOTSUPP;
0102 case NCI_HCI_ANY_E_TIMEOUT:
0103 return -ETIME;
0104 default:
0105 return -1;
0106 }
0107 }
0108
0109
0110 static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
0111 {
0112 int i;
0113
0114 for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
0115 hdev->pipes[i].gate = NCI_HCI_INVALID_GATE;
0116 hdev->pipes[i].host = NCI_HCI_INVALID_HOST;
0117 }
0118 memset(hdev->gate2pipe, NCI_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
0119 }
0120
0121 static void nci_hci_reset_pipes_per_host(struct nci_dev *ndev, u8 host)
0122 {
0123 int i;
0124
0125 for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
0126 if (ndev->hci_dev->pipes[i].host == host) {
0127 ndev->hci_dev->pipes[i].gate = NCI_HCI_INVALID_GATE;
0128 ndev->hci_dev->pipes[i].host = NCI_HCI_INVALID_HOST;
0129 }
0130 }
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
0142 const u8 data_type, const u8 *data,
0143 size_t data_len)
0144 {
0145 const struct nci_conn_info *conn_info;
0146 struct sk_buff *skb;
0147 int len, i, r;
0148 u8 cb = pipe;
0149
0150 conn_info = ndev->hci_dev->conn_info;
0151 if (!conn_info)
0152 return -EPROTO;
0153
0154 i = 0;
0155 skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
0156 NCI_DATA_HDR_SIZE, GFP_ATOMIC);
0157 if (!skb)
0158 return -ENOMEM;
0159
0160 skb_reserve(skb, NCI_DATA_HDR_SIZE + 2);
0161 *(u8 *)skb_push(skb, 1) = data_type;
0162
0163 do {
0164
0165 if (i + conn_info->max_pkt_payload_len -
0166 (skb->len + 1) >= data_len) {
0167 cb |= NCI_HFP_NO_CHAINING;
0168 len = data_len - i;
0169 } else {
0170 len = conn_info->max_pkt_payload_len - skb->len - 1;
0171 }
0172
0173 *(u8 *)skb_push(skb, 1) = cb;
0174
0175 if (len > 0)
0176 skb_put_data(skb, data + i, len);
0177
0178 r = nci_send_data(ndev, conn_info->conn_id, skb);
0179 if (r < 0)
0180 return r;
0181
0182 i += len;
0183
0184 if (i < data_len) {
0185 skb = nci_skb_alloc(ndev,
0186 conn_info->max_pkt_payload_len +
0187 NCI_DATA_HDR_SIZE, GFP_ATOMIC);
0188 if (!skb)
0189 return -ENOMEM;
0190
0191 skb_reserve(skb, NCI_DATA_HDR_SIZE + 1);
0192 }
0193 } while (i < data_len);
0194
0195 return i;
0196 }
0197
0198 static void nci_hci_send_data_req(struct nci_dev *ndev, const void *opt)
0199 {
0200 const struct nci_data *data = opt;
0201
0202 nci_hci_send_data(ndev, data->pipe, data->cmd,
0203 data->data, data->data_len);
0204 }
0205
0206 int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
0207 const u8 *param, size_t param_len)
0208 {
0209 u8 pipe = ndev->hci_dev->gate2pipe[gate];
0210
0211 if (pipe == NCI_HCI_INVALID_PIPE)
0212 return -EADDRNOTAVAIL;
0213
0214 return nci_hci_send_data(ndev, pipe,
0215 NCI_HCP_HEADER(NCI_HCI_HCP_EVENT, event),
0216 param, param_len);
0217 }
0218 EXPORT_SYMBOL(nci_hci_send_event);
0219
0220 int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
0221 const u8 *param, size_t param_len,
0222 struct sk_buff **skb)
0223 {
0224 const struct nci_hcp_message *message;
0225 const struct nci_conn_info *conn_info;
0226 struct nci_data data;
0227 int r;
0228 u8 pipe = ndev->hci_dev->gate2pipe[gate];
0229
0230 if (pipe == NCI_HCI_INVALID_PIPE)
0231 return -EADDRNOTAVAIL;
0232
0233 conn_info = ndev->hci_dev->conn_info;
0234 if (!conn_info)
0235 return -EPROTO;
0236
0237 data.conn_id = conn_info->conn_id;
0238 data.pipe = pipe;
0239 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND, cmd);
0240 data.data = param;
0241 data.data_len = param_len;
0242
0243 r = nci_request(ndev, nci_hci_send_data_req, &data,
0244 msecs_to_jiffies(NCI_DATA_TIMEOUT));
0245 if (r == NCI_STATUS_OK) {
0246 message = (struct nci_hcp_message *)conn_info->rx_skb->data;
0247 r = nci_hci_result_to_errno(
0248 NCI_HCP_MSG_GET_CMD(message->header));
0249 skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0250
0251 if (!r && skb)
0252 *skb = conn_info->rx_skb;
0253 }
0254
0255 return r;
0256 }
0257 EXPORT_SYMBOL(nci_hci_send_cmd);
0258
0259 int nci_hci_clear_all_pipes(struct nci_dev *ndev)
0260 {
0261 int r;
0262
0263 r = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
0264 NCI_HCI_ADM_CLEAR_ALL_PIPE, NULL, 0, NULL);
0265 if (r < 0)
0266 return r;
0267
0268 nci_hci_reset_pipes(ndev->hci_dev);
0269 return r;
0270 }
0271 EXPORT_SYMBOL(nci_hci_clear_all_pipes);
0272
0273 static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
0274 u8 event, struct sk_buff *skb)
0275 {
0276 if (ndev->ops->hci_event_received)
0277 ndev->ops->hci_event_received(ndev, pipe, event, skb);
0278 }
0279
0280 static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
0281 u8 cmd, struct sk_buff *skb)
0282 {
0283 u8 gate = ndev->hci_dev->pipes[pipe].gate;
0284 u8 status = NCI_HCI_ANY_OK | ~NCI_HCI_FRAGMENT;
0285 u8 dest_gate, new_pipe;
0286 struct nci_hci_create_pipe_resp *create_info;
0287 struct nci_hci_delete_pipe_noti *delete_info;
0288 struct nci_hci_all_pipe_cleared_noti *cleared_info;
0289
0290 pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
0291
0292 switch (cmd) {
0293 case NCI_HCI_ADM_NOTIFY_PIPE_CREATED:
0294 if (skb->len != 5) {
0295 status = NCI_HCI_ANY_E_NOK;
0296 goto exit;
0297 }
0298 create_info = (struct nci_hci_create_pipe_resp *)skb->data;
0299 dest_gate = create_info->dest_gate;
0300 new_pipe = create_info->pipe;
0301 if (new_pipe >= NCI_HCI_MAX_PIPES) {
0302 status = NCI_HCI_ANY_E_NOK;
0303 goto exit;
0304 }
0305
0306
0307
0308
0309
0310
0311 ndev->hci_dev->gate2pipe[dest_gate] = new_pipe;
0312 ndev->hci_dev->pipes[new_pipe].gate = dest_gate;
0313 ndev->hci_dev->pipes[new_pipe].host =
0314 create_info->src_host;
0315 break;
0316 case NCI_HCI_ANY_OPEN_PIPE:
0317
0318 if (gate == NCI_HCI_INVALID_GATE) {
0319 status = NCI_HCI_ANY_E_NOK;
0320 goto exit;
0321 }
0322 break;
0323 case NCI_HCI_ADM_NOTIFY_PIPE_DELETED:
0324 if (skb->len != 1) {
0325 status = NCI_HCI_ANY_E_NOK;
0326 goto exit;
0327 }
0328 delete_info = (struct nci_hci_delete_pipe_noti *)skb->data;
0329 if (delete_info->pipe >= NCI_HCI_MAX_PIPES) {
0330 status = NCI_HCI_ANY_E_NOK;
0331 goto exit;
0332 }
0333
0334 ndev->hci_dev->pipes[delete_info->pipe].gate =
0335 NCI_HCI_INVALID_GATE;
0336 ndev->hci_dev->pipes[delete_info->pipe].host =
0337 NCI_HCI_INVALID_HOST;
0338 break;
0339 case NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
0340 if (skb->len != 1) {
0341 status = NCI_HCI_ANY_E_NOK;
0342 goto exit;
0343 }
0344
0345 cleared_info =
0346 (struct nci_hci_all_pipe_cleared_noti *)skb->data;
0347 nci_hci_reset_pipes_per_host(ndev, cleared_info->host);
0348 break;
0349 default:
0350 pr_debug("Discarded unknown cmd %x to gate %x\n", cmd, gate);
0351 break;
0352 }
0353
0354 if (ndev->ops->hci_cmd_received)
0355 ndev->ops->hci_cmd_received(ndev, pipe, cmd, skb);
0356
0357 exit:
0358 nci_hci_send_data(ndev, pipe, status, NULL, 0);
0359
0360 kfree_skb(skb);
0361 }
0362
0363 static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
0364 struct sk_buff *skb)
0365 {
0366 struct nci_conn_info *conn_info;
0367
0368 conn_info = ndev->hci_dev->conn_info;
0369 if (!conn_info)
0370 goto exit;
0371
0372 conn_info->rx_skb = skb;
0373
0374 exit:
0375 nci_req_complete(ndev, NCI_STATUS_OK);
0376 }
0377
0378
0379
0380
0381 static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
0382 u8 type, u8 instruction, struct sk_buff *skb)
0383 {
0384 switch (type) {
0385 case NCI_HCI_HCP_RESPONSE:
0386 nci_hci_resp_received(ndev, pipe, skb);
0387 break;
0388 case NCI_HCI_HCP_COMMAND:
0389 nci_hci_cmd_received(ndev, pipe, instruction, skb);
0390 break;
0391 case NCI_HCI_HCP_EVENT:
0392 nci_hci_event_received(ndev, pipe, instruction, skb);
0393 break;
0394 default:
0395 pr_err("UNKNOWN MSG Type %d, instruction=%d\n",
0396 type, instruction);
0397 kfree_skb(skb);
0398 break;
0399 }
0400
0401 nci_req_complete(ndev, NCI_STATUS_OK);
0402 }
0403
0404 static void nci_hci_msg_rx_work(struct work_struct *work)
0405 {
0406 struct nci_hci_dev *hdev =
0407 container_of(work, struct nci_hci_dev, msg_rx_work);
0408 struct sk_buff *skb;
0409 const struct nci_hcp_message *message;
0410 u8 pipe, type, instruction;
0411
0412 while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
0413 pipe = NCI_HCP_MSG_GET_PIPE(skb->data[0]);
0414 skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
0415 message = (struct nci_hcp_message *)skb->data;
0416 type = NCI_HCP_MSG_GET_TYPE(message->header);
0417 instruction = NCI_HCP_MSG_GET_CMD(message->header);
0418 skb_pull(skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0419
0420 nci_hci_hcp_message_rx(hdev->ndev, pipe,
0421 type, instruction, skb);
0422 }
0423 }
0424
0425 void nci_hci_data_received_cb(void *context,
0426 struct sk_buff *skb, int err)
0427 {
0428 struct nci_dev *ndev = (struct nci_dev *)context;
0429 struct nci_hcp_packet *packet;
0430 u8 pipe, type;
0431 struct sk_buff *hcp_skb;
0432 struct sk_buff *frag_skb;
0433 int msg_len;
0434
0435 if (err) {
0436 nci_req_complete(ndev, err);
0437 return;
0438 }
0439
0440 packet = (struct nci_hcp_packet *)skb->data;
0441 if ((packet->header & ~NCI_HCI_FRAGMENT) == 0) {
0442 skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
0443 return;
0444 }
0445
0446
0447 if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
0448 pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
0449 skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
0450
0451 msg_len = 0;
0452 skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
0453 msg_len += (frag_skb->len -
0454 NCI_HCI_HCP_PACKET_HEADER_LEN);
0455 }
0456
0457 hcp_skb = nfc_alloc_recv_skb(NCI_HCI_HCP_PACKET_HEADER_LEN +
0458 msg_len, GFP_KERNEL);
0459 if (!hcp_skb) {
0460 nci_req_complete(ndev, -ENOMEM);
0461 return;
0462 }
0463
0464 skb_put_u8(hcp_skb, pipe);
0465
0466 skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
0467 msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
0468 skb_put_data(hcp_skb,
0469 frag_skb->data + NCI_HCI_HCP_PACKET_HEADER_LEN,
0470 msg_len);
0471 }
0472
0473 skb_queue_purge(&ndev->hci_dev->rx_hcp_frags);
0474 } else {
0475 packet->header &= NCI_HCI_FRAGMENT;
0476 hcp_skb = skb;
0477 }
0478
0479
0480
0481
0482
0483 packet = (struct nci_hcp_packet *)hcp_skb->data;
0484 type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
0485 if (type == NCI_HCI_HCP_RESPONSE) {
0486 pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
0487 skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
0488 nci_hci_hcp_message_rx(ndev, pipe, type,
0489 NCI_STATUS_OK, hcp_skb);
0490 } else {
0491 skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
0492 schedule_work(&ndev->hci_dev->msg_rx_work);
0493 }
0494 }
0495
0496 int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
0497 {
0498 struct nci_data data;
0499 const struct nci_conn_info *conn_info;
0500
0501 conn_info = ndev->hci_dev->conn_info;
0502 if (!conn_info)
0503 return -EPROTO;
0504
0505 data.conn_id = conn_info->conn_id;
0506 data.pipe = pipe;
0507 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
0508 NCI_HCI_ANY_OPEN_PIPE);
0509 data.data = NULL;
0510 data.data_len = 0;
0511
0512 return nci_request(ndev, nci_hci_send_data_req, &data,
0513 msecs_to_jiffies(NCI_DATA_TIMEOUT));
0514 }
0515 EXPORT_SYMBOL(nci_hci_open_pipe);
0516
0517 static u8 nci_hci_create_pipe(struct nci_dev *ndev, u8 dest_host,
0518 u8 dest_gate, int *result)
0519 {
0520 u8 pipe;
0521 struct sk_buff *skb;
0522 struct nci_hci_create_pipe_params params;
0523 const struct nci_hci_create_pipe_resp *resp;
0524
0525 pr_debug("gate=%d\n", dest_gate);
0526
0527 params.src_gate = NCI_HCI_ADMIN_GATE;
0528 params.dest_host = dest_host;
0529 params.dest_gate = dest_gate;
0530
0531 *result = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
0532 NCI_HCI_ADM_CREATE_PIPE,
0533 (u8 *)¶ms, sizeof(params), &skb);
0534 if (*result < 0)
0535 return NCI_HCI_INVALID_PIPE;
0536
0537 resp = (struct nci_hci_create_pipe_resp *)skb->data;
0538 pipe = resp->pipe;
0539 kfree_skb(skb);
0540
0541 pr_debug("pipe created=%d\n", pipe);
0542
0543 return pipe;
0544 }
0545
0546 static int nci_hci_delete_pipe(struct nci_dev *ndev, u8 pipe)
0547 {
0548 return nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
0549 NCI_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
0550 }
0551
0552 int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
0553 const u8 *param, size_t param_len)
0554 {
0555 const struct nci_hcp_message *message;
0556 const struct nci_conn_info *conn_info;
0557 struct nci_data data;
0558 int r;
0559 u8 *tmp;
0560 u8 pipe = ndev->hci_dev->gate2pipe[gate];
0561
0562 pr_debug("idx=%d to gate %d\n", idx, gate);
0563
0564 if (pipe == NCI_HCI_INVALID_PIPE)
0565 return -EADDRNOTAVAIL;
0566
0567 conn_info = ndev->hci_dev->conn_info;
0568 if (!conn_info)
0569 return -EPROTO;
0570
0571 tmp = kmalloc(1 + param_len, GFP_KERNEL);
0572 if (!tmp)
0573 return -ENOMEM;
0574
0575 *tmp = idx;
0576 memcpy(tmp + 1, param, param_len);
0577
0578 data.conn_id = conn_info->conn_id;
0579 data.pipe = pipe;
0580 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
0581 NCI_HCI_ANY_SET_PARAMETER);
0582 data.data = tmp;
0583 data.data_len = param_len + 1;
0584
0585 r = nci_request(ndev, nci_hci_send_data_req, &data,
0586 msecs_to_jiffies(NCI_DATA_TIMEOUT));
0587 if (r == NCI_STATUS_OK) {
0588 message = (struct nci_hcp_message *)conn_info->rx_skb->data;
0589 r = nci_hci_result_to_errno(
0590 NCI_HCP_MSG_GET_CMD(message->header));
0591 skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0592 }
0593
0594 kfree(tmp);
0595 return r;
0596 }
0597 EXPORT_SYMBOL(nci_hci_set_param);
0598
0599 int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
0600 struct sk_buff **skb)
0601 {
0602 const struct nci_hcp_message *message;
0603 const struct nci_conn_info *conn_info;
0604 struct nci_data data;
0605 int r;
0606 u8 pipe = ndev->hci_dev->gate2pipe[gate];
0607
0608 pr_debug("idx=%d to gate %d\n", idx, gate);
0609
0610 if (pipe == NCI_HCI_INVALID_PIPE)
0611 return -EADDRNOTAVAIL;
0612
0613 conn_info = ndev->hci_dev->conn_info;
0614 if (!conn_info)
0615 return -EPROTO;
0616
0617 data.conn_id = conn_info->conn_id;
0618 data.pipe = pipe;
0619 data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
0620 NCI_HCI_ANY_GET_PARAMETER);
0621 data.data = &idx;
0622 data.data_len = 1;
0623
0624 r = nci_request(ndev, nci_hci_send_data_req, &data,
0625 msecs_to_jiffies(NCI_DATA_TIMEOUT));
0626
0627 if (r == NCI_STATUS_OK) {
0628 message = (struct nci_hcp_message *)conn_info->rx_skb->data;
0629 r = nci_hci_result_to_errno(
0630 NCI_HCP_MSG_GET_CMD(message->header));
0631 skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0632
0633 if (!r && skb)
0634 *skb = conn_info->rx_skb;
0635 }
0636
0637 return r;
0638 }
0639 EXPORT_SYMBOL(nci_hci_get_param);
0640
0641 int nci_hci_connect_gate(struct nci_dev *ndev,
0642 u8 dest_host, u8 dest_gate, u8 pipe)
0643 {
0644 bool pipe_created = false;
0645 int r;
0646
0647 if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
0648 return 0;
0649
0650 if (ndev->hci_dev->gate2pipe[dest_gate] != NCI_HCI_INVALID_PIPE)
0651 return -EADDRINUSE;
0652
0653 if (pipe != NCI_HCI_INVALID_PIPE)
0654 goto open_pipe;
0655
0656 switch (dest_gate) {
0657 case NCI_HCI_LINK_MGMT_GATE:
0658 pipe = NCI_HCI_LINK_MGMT_PIPE;
0659 break;
0660 case NCI_HCI_ADMIN_GATE:
0661 pipe = NCI_HCI_ADMIN_PIPE;
0662 break;
0663 default:
0664 pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
0665 if (pipe == NCI_HCI_INVALID_PIPE)
0666 return r;
0667 pipe_created = true;
0668 break;
0669 }
0670
0671 open_pipe:
0672 r = nci_hci_open_pipe(ndev, pipe);
0673 if (r < 0) {
0674 if (pipe_created) {
0675 if (nci_hci_delete_pipe(ndev, pipe) < 0) {
0676
0677
0678
0679 }
0680 }
0681 return r;
0682 }
0683
0684 ndev->hci_dev->pipes[pipe].gate = dest_gate;
0685 ndev->hci_dev->pipes[pipe].host = dest_host;
0686 ndev->hci_dev->gate2pipe[dest_gate] = pipe;
0687
0688 return 0;
0689 }
0690 EXPORT_SYMBOL(nci_hci_connect_gate);
0691
0692 static int nci_hci_dev_connect_gates(struct nci_dev *ndev,
0693 u8 gate_count,
0694 const struct nci_hci_gate *gates)
0695 {
0696 int r;
0697
0698 while (gate_count--) {
0699 r = nci_hci_connect_gate(ndev, gates->dest_host,
0700 gates->gate, gates->pipe);
0701 if (r < 0)
0702 return r;
0703 gates++;
0704 }
0705
0706 return 0;
0707 }
0708
0709 int nci_hci_dev_session_init(struct nci_dev *ndev)
0710 {
0711 struct nci_conn_info *conn_info;
0712 struct sk_buff *skb;
0713 int r;
0714
0715 ndev->hci_dev->count_pipes = 0;
0716 ndev->hci_dev->expected_pipes = 0;
0717
0718 conn_info = ndev->hci_dev->conn_info;
0719 if (!conn_info)
0720 return -EPROTO;
0721
0722 conn_info->data_exchange_cb = nci_hci_data_received_cb;
0723 conn_info->data_exchange_cb_context = ndev;
0724
0725 nci_hci_reset_pipes(ndev->hci_dev);
0726
0727 if (ndev->hci_dev->init_data.gates[0].gate != NCI_HCI_ADMIN_GATE)
0728 return -EPROTO;
0729
0730 r = nci_hci_connect_gate(ndev,
0731 ndev->hci_dev->init_data.gates[0].dest_host,
0732 ndev->hci_dev->init_data.gates[0].gate,
0733 ndev->hci_dev->init_data.gates[0].pipe);
0734 if (r < 0)
0735 return r;
0736
0737 r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
0738 NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY, &skb);
0739 if (r < 0)
0740 return r;
0741
0742 if (skb->len &&
0743 skb->len == strlen(ndev->hci_dev->init_data.session_id) &&
0744 !memcmp(ndev->hci_dev->init_data.session_id, skb->data, skb->len) &&
0745 ndev->ops->hci_load_session) {
0746
0747 r = ndev->ops->hci_load_session(ndev);
0748 } else {
0749 r = nci_hci_clear_all_pipes(ndev);
0750 if (r < 0)
0751 goto exit;
0752
0753 r = nci_hci_dev_connect_gates(ndev,
0754 ndev->hci_dev->init_data.gate_count,
0755 ndev->hci_dev->init_data.gates);
0756 if (r < 0)
0757 goto exit;
0758
0759 r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
0760 NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY,
0761 ndev->hci_dev->init_data.session_id,
0762 strlen(ndev->hci_dev->init_data.session_id));
0763 }
0764
0765 exit:
0766 kfree_skb(skb);
0767
0768 return r;
0769 }
0770 EXPORT_SYMBOL(nci_hci_dev_session_init);
0771
0772 struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
0773 {
0774 struct nci_hci_dev *hdev;
0775
0776 hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
0777 if (!hdev)
0778 return NULL;
0779
0780 skb_queue_head_init(&hdev->rx_hcp_frags);
0781 INIT_WORK(&hdev->msg_rx_work, nci_hci_msg_rx_work);
0782 skb_queue_head_init(&hdev->msg_rx_queue);
0783 hdev->ndev = ndev;
0784
0785 return hdev;
0786 }
0787
0788 void nci_hci_deallocate(struct nci_dev *ndev)
0789 {
0790 kfree(ndev->hci_dev);
0791 }