Ejemplo n.º 1
0
int
ng_hci_lp_discon_req(ng_hci_unit_p unit, item_p item, hook_p hook)
{
	struct discon_req {
		ng_hci_cmd_pkt_t	 hdr;
		ng_hci_discon_cp	 cp;
	} __attribute__ ((packed))	*req = NULL;
	ng_hci_lp_discon_req_ep		*ep = NULL;
	ng_hci_unit_con_p		 con = NULL;
	struct mbuf			*m = NULL;
	int				 error = 0;

	/* Check if unit is ready */
	if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) {
		NG_HCI_WARN(
"%s: %s - unit is not ready, state=%#x\n",
			__func__, NG_NODE_NAME(unit->node), unit->state);

		error = ENXIO;
		goto out;
	}

	if (NGI_MSG(item)->header.arglen != sizeof(*ep)) {
		NG_HCI_ALERT(
"%s: %s - invalid LP_DisconnectReq message size=%d\n",
			__func__, NG_NODE_NAME(unit->node),
			NGI_MSG(item)->header.arglen);

		error = EMSGSIZE;
		goto out;
	}

	ep = (ng_hci_lp_discon_req_ep *)(NGI_MSG(item)->data);

	con = ng_hci_con_by_handle(unit, ep->con_handle);
	if (con == NULL) {
		NG_HCI_ERR(
"%s: %s - invalid connection handle=%d\n",
			__func__, NG_NODE_NAME(unit->node), ep->con_handle);

		error = ENOENT;
		goto out;
	}

	if (con->state != NG_HCI_CON_OPEN) {
		NG_HCI_ERR(
"%s: %s - invalid connection state=%d, handle=%d\n",
			__func__, NG_NODE_NAME(unit->node), con->state,
			ep->con_handle);

		error = EINVAL;
		goto out;
	}

	/* 
	 * Create HCI command
	 */

	MGETHDR(m, M_DONTWAIT, MT_DATA);
	if (m == NULL) {
		error = ENOBUFS;
		goto out;
	}

	m->m_pkthdr.len = m->m_len = sizeof(*req);
	req = mtod(m, struct discon_req *);
	req->hdr.type = NG_HCI_CMD_PKT;
	req->hdr.length = sizeof(req->cp);
	req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
							NG_HCI_OCF_DISCON));

	req->cp.con_handle = htole16(ep->con_handle);
	req->cp.reason = ep->reason;

	/* 
	 * Queue and send HCI command 
	 */

	NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
	if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
		error = ng_hci_send_command(unit);
out:
	NG_FREE_ITEM(item);

	return (error);
} /* ng_hci_lp_discon_req */
Ejemplo n.º 2
0
int
ng_hci_send_command(ng_hci_unit_p unit)
{
	struct mbuf	*m0 = NULL, *m = NULL;
	int		 free, error = 0;

	/* Check if other command is pending */
	if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
		return (0);

	/* Check if unit can accept our command */
	NG_HCI_BUFF_CMD_GET(unit->buffer, free);
	if (free == 0)
		return (0);

	/* Check if driver hook is still ok */
	if (unit->drv == NULL || NG_HOOK_NOT_VALID(unit->drv)) {
		NG_HCI_WARN(
"%s: %s - hook \"%s\" is not connected or valid\n",
			__func__, NG_NODE_NAME(unit->node), NG_HCI_HOOK_DRV);

		NG_BT_MBUFQ_DRAIN(&unit->cmdq);

		return (ENOTCONN);
	}

	/* 
	 * Get first command from queue, give it to RAW hook then 
	 * make copy of it and send it to the driver
	 */

	m0 = NG_BT_MBUFQ_FIRST(&unit->cmdq);
	if (m0 == NULL)
		return (0);

	ng_hci_mtap(unit, m0);

	m = m_dup(m0, MB_DONTWAIT);
	if (m != NULL)
		NG_SEND_DATA_ONLY(error, unit->drv, m);
	else
		error = ENOBUFS;

	if (error != 0)
		NG_HCI_ERR(
"%s: %s - could not send HCI command, error=%d\n",
			__func__, NG_NODE_NAME(unit->node), error);

	/*
	 * Even if we were not able to send command we still pretend
	 * that everything is OK and let timeout handle that.
	 */

	NG_HCI_BUFF_CMD_USE(unit->buffer, 1);
	NG_HCI_STAT_CMD_SENT(unit->stat);
	NG_HCI_STAT_BYTES_SENT(unit->stat, m0->m_pkthdr.len);

	/*
	 * Note: ng_hci_command_timeout() will set 
	 * NG_HCI_UNIT_COMMAND_PENDING flag
	 */

	ng_hci_command_timeout(unit);

	return (0);
} /* ng_hci_send_command */