/* called from ST Core, when a PM related packet arrives */ unsigned long st_ll_sleep_state(struct st_data_s *st_data, unsigned char cmd, unsigned long *p_flags) { switch (cmd) { case LL_SLEEP_IND: /* sleep ind */ pr_debug("sleep indication recvd"); ll_device_want_to_sleep(st_data, p_flags); break; case LL_SLEEP_ACK: /* sleep ack */ pr_err("sleep ack rcvd: host shouldn't"); break; case LL_WAKE_UP_IND: /* wake ind */ pr_debug("wake indication recvd"); ll_device_want_to_wakeup(st_data); break; case LL_WAKE_UP_ACK: /* wake ack */ pr_debug("wake ack rcvd"); st_data->ll_state = ST_LL_AWAKE; break; default: pr_err(" unknown input/state "); return -EINVAL; } return 0; }
/* called from ST Core, when a PM related packet arrives */ unsigned long st_ll_sleep_state(unsigned char cmd) { switch (cmd) { case LL_SLEEP_IND: /* sleep ind */ ST_LL_DBG("sleep indication recvd"); ll_device_want_to_sleep(); break; case LL_SLEEP_ACK: /* sleep ack */ ST_LL_ERR("sleep ack rcvd: host shouldn't"); break; case LL_WAKE_UP_IND: /* wake ind */ ST_LL_DBG("wake indication recvd"); ll_device_want_to_wakeup(); break; case LL_WAKE_UP_ACK: /* wake ack */ ST_LL_DBG("wake ack rcvd"); ll->ll_state = ST_LL_AWAKE; break; default: ST_LL_ERR(" unknown input/state "); return ST_ERR_FAILURE; } return ST_SUCCESS; }
/* Recv data */ static int ll_recv(struct hci_uart *hu, const void *data, int count) { struct ll_struct *ll = hu->priv; const char *ptr; struct hci_event_hdr *eh; struct hci_acl_hdr *ah; struct hci_sco_hdr *sh; int len, type, dlen; BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count); ptr = data; while (count) { if (ll->rx_count) { len = min_t(unsigned int, ll->rx_count, count); memcpy(skb_put(ll->rx_skb, len), ptr, len); ll->rx_count -= len; count -= len; ptr += len; if (ll->rx_count) continue; switch (ll->rx_state) { case HCILL_W4_DATA: BT_DBG("Complete data"); hci_recv_frame(hu->hdev, ll->rx_skb); ll->rx_state = HCILL_W4_PACKET_TYPE; ll->rx_skb = NULL; continue; case HCILL_W4_EVENT_HDR: eh = hci_event_hdr(ll->rx_skb); BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); ll_check_data_len(hu->hdev, ll, eh->plen); continue; case HCILL_W4_ACL_HDR: ah = hci_acl_hdr(ll->rx_skb); dlen = __le16_to_cpu(ah->dlen); BT_DBG("ACL header: dlen %d", dlen); ll_check_data_len(hu->hdev, ll, dlen); continue; case HCILL_W4_SCO_HDR: sh = hci_sco_hdr(ll->rx_skb); BT_DBG("SCO header: dlen %d", sh->dlen); ll_check_data_len(hu->hdev, ll, sh->dlen); continue; } } /* HCILL_W4_PACKET_TYPE */ switch (*ptr) { case HCI_EVENT_PKT: BT_DBG("Event packet"); ll->rx_state = HCILL_W4_EVENT_HDR; ll->rx_count = HCI_EVENT_HDR_SIZE; type = HCI_EVENT_PKT; break; case HCI_ACLDATA_PKT: BT_DBG("ACL packet"); ll->rx_state = HCILL_W4_ACL_HDR; ll->rx_count = HCI_ACL_HDR_SIZE; type = HCI_ACLDATA_PKT; break; case HCI_SCODATA_PKT: BT_DBG("SCO packet"); ll->rx_state = HCILL_W4_SCO_HDR; ll->rx_count = HCI_SCO_HDR_SIZE; type = HCI_SCODATA_PKT; break; /* HCILL signals */ case HCILL_GO_TO_SLEEP_IND: BT_DBG("HCILL_GO_TO_SLEEP_IND packet"); ll_device_want_to_sleep(hu); ptr++; count--; continue; case HCILL_GO_TO_SLEEP_ACK: /* shouldn't happen */ BT_ERR("received HCILL_GO_TO_SLEEP_ACK (in state %ld)", ll->hcill_state); ptr++; count--; continue; case HCILL_WAKE_UP_IND: BT_DBG("HCILL_WAKE_UP_IND packet"); ll_device_want_to_wakeup(hu); ptr++; count--; continue; case HCILL_WAKE_UP_ACK: BT_DBG("HCILL_WAKE_UP_ACK packet"); ll_device_woke_up(hu); ptr++; count--; continue; default: BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); hu->hdev->stat.err_rx++; ptr++; count--; continue; } ptr++; count--; /* Allocate packet */ ll->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); if (!ll->rx_skb) { BT_ERR("Can't allocate mem for new packet"); ll->rx_state = HCILL_W4_PACKET_TYPE; ll->rx_count = 0; return -ENOMEM; } hci_skb_pkt_type(ll->rx_skb) = type; }