Пример #1
0
Файл: h4.c Проект: 01org/zephyr
static void rx_thread(void *p1, void *p2, void *p3)
{
	struct net_buf *buf;

	ARG_UNUSED(p1);
	ARG_UNUSED(p2);
	ARG_UNUSED(p3);

	BT_DBG("started");

	while (1) {
		BT_DBG("rx.buf %p", rx.buf);

		/* We can only do the allocation if we know the initial
		 * header, since Command Complete/Status events must use the
		 * original command buffer (if available).
		 */
		if (rx.have_hdr && !rx.buf) {
			rx.buf = get_rx(K_FOREVER);
			BT_DBG("Got rx.buf %p", rx.buf);
			if (rx.remaining > net_buf_tailroom(rx.buf)) {
				BT_ERR("Not enough space in buffer");
				rx.discard = rx.remaining;
				reset_rx();
			} else {
				copy_hdr(rx.buf);
			}
		}

		/* Let the ISR continue receiving new packets */
		uart_irq_rx_enable(h4_dev);

		buf = net_buf_get(&rx.fifo, K_FOREVER);
		do {
			uart_irq_rx_enable(h4_dev);

			BT_DBG("Calling bt_recv(%p)", buf);
			bt_recv(buf);

			/* Give other threads a chance to run if the ISR
			 * is receiving data so fast that rx.fifo never
			 * or very rarely goes empty.
			 */
			k_yield();

			uart_irq_rx_disable(h4_dev);
			buf = net_buf_get(&rx.fifo, K_NO_WAIT);
		} while (buf);
	}
}
Пример #2
0
static void h5_process_complete_packet(uint8_t *hdr)
{
	struct net_buf *buf;

	BT_DBG("");

	/* rx_ack should be in every packet */
	h5.rx_ack = H5_HDR_ACK(hdr);

	if (reliable_packet(H5_HDR_PKT_TYPE(hdr))) {
		/* For reliable packet increment next transmit ack number */
		h5.tx_ack = (h5.tx_ack + 1) % 8;
		/* Start delayed fiber to ack the packet */
		h5.ack_to = fiber_delayed_start(ack_stack, sizeof(ack_stack),
						ack_fiber, 0, 0, 7, 0,
						H5_RX_ACK_TIMEOUT);
	}

	h5_print_header(hdr, "RX: >");

	process_unack();

	buf = h5.rx_buf;
	h5.rx_buf = NULL;

	switch (H5_HDR_PKT_TYPE(hdr)) {
	case HCI_3WIRE_ACK_PKT:
		net_buf_unref(buf);
		break;
	case HCI_3WIRE_LINK_PKT:
		nano_fifo_put(&h5.rx_queue, buf);
		break;
	case HCI_EVENT_PKT:
	case HCI_ACLDATA_PKT:
		hexdump("=> ", buf->data, buf->len);
		bt_recv(buf);
		break;
	}
}
Пример #3
0
void bt_uart_isr(void *unused)
{
	static struct bt_buf *buf;
	static int remaining;

	ARG_UNUSED(unused);

	while (uart_irq_update(UART) && uart_irq_is_pending(UART)) {
		int read;

		if (!uart_irq_rx_ready(UART)) {
			if (uart_irq_tx_ready(UART)) {
				BT_DBG("transmit ready\n");
			} else {
				BT_DBG("spurious interrupt\n");
			}
			continue;
		}

		/* Beginning of a new packet */
		if (!remaining) {
			uint8_t type;

			/* Get packet type */
			read = bt_uart_read(UART, &type, sizeof(type), 0);
			if (read != sizeof(type)) {
				BT_WARN("Unable to read H4 packet type\n");
				continue;
			}

			switch (type) {
				case H4_EVT:
					buf = bt_uart_evt_recv(&remaining);
					break;
				case H4_ACL:
					buf = bt_uart_acl_recv(&remaining);
					break;
				default:
					BT_ERR("Unknown H4 type %u\n", type);
					return;
			}

			if (buf && remaining > bt_buf_tailroom(buf)) {
				BT_ERR("Not enough space in buffer\n");
				goto failed;
			}

			BT_DBG("need to get %u bytes\n", remaining);
		}

		if (!buf) {
			read = bt_uart_discard(UART, remaining);
			BT_WARN("Discarded %d bytes\n", read);
			remaining -= read;
			continue;
		}

		read = bt_uart_read(UART, bt_buf_tail(buf), remaining, 0);

		buf->len += read;
		remaining -= read;

		BT_DBG("received %d bytes\n", read);

		if (!remaining) {
			BT_DBG("full packet received\n");

			/* Pass buffer to the stack */
			bt_recv(buf);
			buf = NULL;
		}
	}

	return;

failed:
	bt_buf_put(buf);
	remaining = 0;
	buf = NULL;
}
Пример #4
0
int bt_recv_prio(struct net_buf *buf)
{
	return bt_recv(buf);
}
Пример #5
0
static void bt_uart_isr(struct device *unused)
{
	static struct net_buf *buf;
	static int remaining;

	ARG_UNUSED(unused);

	while (uart_irq_update(h4_dev) && uart_irq_is_pending(h4_dev)) {
		int read;

		if (!uart_irq_rx_ready(h4_dev)) {
			if (uart_irq_tx_ready(h4_dev)) {
				BT_DBG("transmit ready");
			} else {
				BT_DBG("spurious interrupt");
			}
			continue;
		}

		/* Beginning of a new packet */
		if (!remaining) {
			uint8_t type;

			/* Get packet type */
			read = h4_read(h4_dev, &type, sizeof(type), 0);
			if (read != sizeof(type)) {
				BT_WARN("Unable to read H4 packet type");
				continue;
			}

			switch (type) {
			case H4_EVT:
				buf = h4_evt_recv(&remaining);
				break;
			case H4_ACL:
				buf = h4_acl_recv(&remaining);
				break;
			default:
				BT_ERR("Unknown H4 type %u", type);
				return;
			}

			BT_DBG("need to get %u bytes", remaining);

			if (buf && remaining > net_buf_tailroom(buf)) {
				BT_ERR("Not enough space in buffer");
				net_buf_unref(buf);
				buf = NULL;
			}
		}

		if (!buf) {
			read = h4_discard(h4_dev, remaining);
			BT_WARN("Discarded %d bytes", read);
			remaining -= read;
			continue;
		}

		read = h4_read(h4_dev, net_buf_tail(buf), remaining, 0);

		buf->len += read;
		remaining -= read;

		BT_DBG("received %d bytes", read);

		if (!remaining) {
			BT_DBG("full packet received");

			/* Pass buffer to the stack */
			bt_recv(buf);
			buf = NULL;
		}
	}
}
Пример #6
0
static void bt_spi_rx_thread(void)
{
	struct net_buf *buf;
	u8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 };
	u8_t header_slave[5];
	struct bt_hci_acl_hdr acl_hdr;
	u8_t size;

	memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN);

	while (true) {
		k_sem_take(&sem_request, K_FOREVER);
		/* Disable IRQ pin callback to avoid spurious IRQs */
		gpio_pin_disable_callback(irq_dev, GPIO_IRQ_PIN);
		k_sem_take(&sem_busy, K_FOREVER);

		do {
#if defined(CONFIG_BLUETOOTH_SPI_BLUENRG)
			gpio_pin_write(cs_dev, GPIO_CS_PIN, 1);
			gpio_pin_write(cs_dev, GPIO_CS_PIN, 0);
#endif /* CONFIG_BLUETOOTH_SPI_BLUENRG */
			spi_transceive(spi_dev,
				       header_master, 5, header_slave, 5);
		} while (header_slave[STATUS_HEADER_TOREAD] == 0 ||
			 header_slave[STATUS_HEADER_TOREAD] == 0xFF);

		size = header_slave[STATUS_HEADER_TOREAD];
		do {
			spi_transceive(spi_dev, &txmsg, size, &rxmsg, size);
		} while (rxmsg[0] == 0);

		gpio_pin_enable_callback(irq_dev, GPIO_IRQ_PIN);
#if defined(CONFIG_BLUETOOTH_SPI_BLUENRG)
		gpio_pin_write(cs_dev, GPIO_CS_PIN, 1);
#endif /* CONFIG_BLUETOOTH_SPI_BLUENRG */
		k_sem_give(&sem_busy);

		spi_dump_message("RX:ed", rxmsg, size);

		switch (rxmsg[PACKET_TYPE]) {
		case HCI_EVT:
			switch (rxmsg[EVT_HEADER_EVENT]) {
			case BT_HCI_EVT_VENDOR:
				/* Vendor events are currently unsupported */
				bt_spi_handle_vendor_evt(rxmsg);
				continue;
			case BT_HCI_EVT_CMD_COMPLETE:
			case BT_HCI_EVT_CMD_STATUS:
				buf = bt_buf_get_cmd_complete(K_FOREVER);
				break;
			default:
				buf = bt_buf_get_rx(K_FOREVER);
				break;
			}

			bt_buf_set_type(buf, BT_BUF_EVT);
			net_buf_add_mem(buf, &rxmsg[1],
					rxmsg[EVT_HEADER_SIZE] + 2);
			break;
		case HCI_ACL:
			buf = bt_buf_get_rx(K_FOREVER);
			bt_buf_set_type(buf, BT_BUF_ACL_IN);
			memcpy(&acl_hdr, &rxmsg[1], sizeof(acl_hdr));
			net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr));
			net_buf_add_mem(buf, &rxmsg[5],
					sys_le16_to_cpu(acl_hdr.len));
			break;
		default:
			BT_ERR("Unknown BT buf type %d", rxmsg[0]);
			continue;
		}

		if (rxmsg[PACKET_TYPE] == HCI_EVT &&
		    bt_hci_evt_is_prio(rxmsg[EVT_HEADER_EVENT])) {
			bt_recv_prio(buf);
		} else {
			bt_recv(buf);
		}
	}
}
Пример #7
0
void proxythread (void * client_ptr)
{
 BT_CLIENT *client;
 BT_PROXY proxy = { 0 };
 BT_CLIENTINFO ci = { 0 };

 char buf[4096] = { 0 };

 int c = 0;

 // set up client information

 client = (BT_CLIENT*) client_ptr;

 // welcome user

 if (!client->use_pass) // anon server
 {
  logevent("Accepted %s:%i", client->ip, client->port);

  ci.pass_reg = 1;

  bt_send (client->sock,
   ":BounceThis NOTICE :You have connected to a BounceThis server. (version " BT_VERSION_NUMBER ")\r\n"
   ":BounceThis NOTICE :Please type \002/BOUNCE <server> [port] [password]\002 to connect to a server.\r\n"
   ":BounceThis NOTICE :For a list of commands, type \002/COMMANDS\002.\r\n");
 }

 /* parsing engine */


 while (1)
 {
  char *ptr, *bufptr, *msgptr ;
  char msgbuf[512] = { 0 };

  c = bt_recv (client->sock, buf, 4096);

  if (c == SOCKET_ERROR)
   goto abort ;

  buf[c] = 0;

  bufptr = buf;

  do
  {
   msgptr = msgbuf;

   // get first message (terminated with \r\n)

   while (*bufptr != '\n' && *bufptr != '\0')
   {
	if (*bufptr == 0) goto abort;
	*msgptr++ = *bufptr++;
   }

   *bufptr++;
   *msgptr = 0;

   ptr = strtok (msgbuf," ");

   if (!ptr)
	continue;

   if (!strcmpi (ptr,"PASS"))
   {
	if (ci.pass_reg)
	{
	 bt_send(client->sock, 
	  ":BounceThis NOTICE :Password not needed.\r\n");
	 continue;
	}
	else
	{
	 ptr = strtok(NULL," \r");

	 if (!ptr)
	  continue;

	 if (!strcmp (ptr, client->password))
	 {
	  logevent("Accepted %s:%i", client->ip, client->port);

	  ci.pass_reg = 1;

	  bt_send(client->sock,
	   ":BounceThis NOTICE :Password accepted.\r\n"
	   ":BounceThis NOTICE :You have connected to a BounceThis server. (version " BT_VERSION_NUMBER ")\r\n"
	   ":BounceThis NOTICE :Please type \002/BOUNCE <server> [port] [password]\002 to connect to a server.\r\n"
	   ":BounceThis NOTICE :For a list of commands, type \002/COMMANDS\002.\r\n");

	  continue;
	 }
	 else
	 {
	  logevent("Refused %s (incorrect password)", client->ip);
	  bt_send (client->sock, 
	   ":BounceThis NOTICE :Password incorrect.\r\n");
	  goto abort2;
	 }
	}
   }

   if (ci.pass_reg)
   {
	if (!strcmpi (ptr,"COMMANDS"))
	{
	 bt_send (client->sock,
	 ":BounceThis NOTICE :Commands listing:\r\n"
	 ":BounceThis NOTICE :\002/ABOUT\002 About BounceThis.\r\n"
	 ":BounceThis NOTICE :\002/ADMIN\002 Login as the admin.\r\n"
	 ":BounceThis NOTICE :\002/BOUNCE\002 Connects you to a server.\r\n"
	 ":BounceThis NOTICE :\002/COMMANDS\002 Shows this screen.\r\n"
	 ":BounceThis NOTICE :\002/INFO\002 Info about yourself and the server.\r\n"
	 ":BounceThis NOTICE :\002/NICK\002 Changes your nickname.\r\n"
	 ":BounceThis NOTICE :\002/QUIT\002 Disconnects you.\r\n");

	 if (ci.is_admin)
	  bt_send (client->sock,
	  ":BounceThis NOTICE :Admin commands listing:\r\n"
	 ":BounceThis NOTICE :\002/BROADCAST\002 Send a message to all users.\r\n"
	 ":BounceThis NOTICE :\002/KILL\002 Kill everyone matching an ip (BT style filters allowed)\r\n"
	 ":BounceThis NOTICE :\002/TEMPFILTER\002 Ban everyone matching an ip (BT style filters allowed) until server is stopped.\r\n"
	 ":BounceThis NOTICE :\002/LISTCONN\002 Lists all connections to the server.\r\n");

	}

	else if (!strcmpi (ptr,"ABOUT"))
	 bt_send(client->sock,
	 ":BounceThis NOTICE :About BounceThis:\r\n"
	 ":BounceThis NOTICE :BounceThis was created by Chris M. in 2002.\r\n"
	 ":BounceThis NOTICE :It is a full featured Win32 BNC server designed for IRC.\r\n"
	 ":BounceThis NOTICE :Check us out on the web at 12http://bouncethis.linear.cc\r\n");

	else if (!strcmpi (ptr,"INFO"))
	{ 
	 bt_sendf (client->sock,
	  ":BounceThis NOTICE :" BT_VERSION ", bound on IP %s on port %i\r\n"
	  ":BounceThis NOTICE :You are connecting as %s!%s@%s (%s)\r\n",
	  server.ip, client->port, real(ci.nick), ci.user, client->ip, real(ci.name));

	 if (server.use_identd)
	  bt_sendf (client->sock,
	  ":BounceThis NOTICE :Identd server enabled, using ident '%s'\r\n",
	  server.ident);
	}

	else if (!strcmpi (ptr,"NICK"))
	{
	 ptr = strtok(NULL," \r");

	 if (!ptr)
	  continue;

	 bt_cpy (ci.nick, ptr);

	 if (ci.nick_reg)
	  bt_sendf (client->sock, 
	  ":BounceThis NOTICE :Your nickname is now \002%s\002.\r\n",
	  real(ci.nick));
	 else
	  ci.nick_reg = 1;
	}
	else if (!strcmpi (ptr,"QUIT"))
	 goto abort; 
	else if (!strcmpi (ptr,"USER"))
	{
	 if (ci.user_reg)
	 {
	  bt_send (client->sock, 
	   ":BounceThis NOTICE :You cannot reregister.\r\n");
	  continue;
	 }

	 ptr = strtok(NULL," ");

	 if (!ptr)
	  continue;

	 bt_cpy (ci.user, ptr);

	 // skip next two fields. useless -_-;
	 strtok(NULL," ");
	 strtok(NULL," ");

	 ptr = strtok(NULL,"\r");

	 if (!ptr)
	  continue;

	 bt_cpy (ci.name, ptr);
	 ci.user_reg = 1;
	}
	else if (!strcmpi (ptr,"ADMIN"))
	{ 
	 char user[16] ; 
	 char pass[16] ;

	 ptr = strtok(NULL," \r");

	 if (!ptr)
	  continue;

	 bt_cpy(user,ptr) ;

	 ptr = strtok(NULL," \r");

	 if (!ptr)
	  continue;

	 bt_cpy(pass,ptr) ;

	 if (!strcmpi(user,server.admin_user) && !strcmp(pass,server.admin_pass))
	 {
	  bt_send(client->sock,":BounceThis NOTICE :Admin password accepted.\r\n");
	  ci.is_admin = 1 ;
	 }
	 else
	 {
	  logevent("Connection from %s:%i closed (invalid admin attempt)", client->ip,client->port);
	  bt_send (client->sock,
	   ":BounceThis NOTICE :Admin password incorrect. Disconnecting.\r\n");
	  goto abort2;
	 }
	}
	else if (!strcmpi (ptr,"BROADCAST"))
	{
	 if (!ci.is_admin) // :O!
	 {
	  bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n");
	  continue ;
	 }

	 ptr = strtok(NULL,"\r");

	 if (!ptr)
	  continue;

	 broadcast(ptr) ;
	}
	else if (!strcmpi (ptr,"KILL"))
	{
	 if (!ci.is_admin) // :O!
	 {
	  bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n");
	  continue ;
	 }

	 ptr = strtok(NULL,"\r");

	 if (!ptr)
	  continue;

	 bt_sendf(client->sock,":BounceThis NOTICE :Kill effected \002%i\002 users.\r\n",kill(ptr)) ;
	}
	else if (!strcmpi (ptr,"TEMPFILTER"))
	{
	 if (!ci.is_admin) // :O!
	 {
	  bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n");
	  continue ;
	 }

	 ptr = strtok(NULL,"\r");

	 if (!ptr)
	  continue;

	 bt_sendf(client->sock,":BounceThis NOTICE :Filter effected \002%i\002 users.\r\n",tempfilter(ptr)) ;
	}
	else if (!strcmpi (ptr,"LISTCONN"))
	{
	 if (!ci.is_admin) // :O!
	 {
	  bt_send(client->sock,":BounceThis NOTICE :You cannot perform this command.\r\n");
	  continue ;
	 }

	 list(client->sock);
	}
	else if (!strcmpi (ptr,"BOUNCE"))
	{
	 ptr = strtok(NULL," \r");

	 if (!ptr)
	  continue;

	 bt_cpy (proxy.host, ptr);

	 ptr = strtok(NULL," \r");

	 if (!ptr)
	  bt_cpy(proxy.port,"6667");
	 else
	 {
	  bt_cpy (proxy.port, ptr);
	  ptr = strtok(NULL," \r");

	  if (ptr)
	  {
	   bt_cpy (ci.pass,ptr);
	   ci.use_pass = 1;
	  }
	 }

	 proxy.sock = bt_connect (proxy.host, proxy.port);

	 if (!proxy.sock)
	  bt_sendf (client->sock,
	  ":BounceThis NOTICE :Error connecting to %s:%s.\r\n",
	  proxy.host,	proxy.port);
	 else
	 {
	  bt_sendf (client->sock,
	   ":BounceThis NOTICE :Connection established to %s:%s.\r\n",proxy.host,
	   proxy.port);

	  if (ci.use_pass)
	   bt_sendf (client->sock,":BounceThis NOTICE :Attempting to login with password '%s'\r\n",
	   ci.pass);
	  break;
	 }
	}
	else
	 bt_sendf (client->sock,
	 ":BounceThis NOTICE :\002/%s\002: Invalid command.\r\n",ptr);
   }
   else
   {
	logevent("Refused %s:%i (incorrect password)", client->ip,client->port);
	bt_send (client->sock,
	 ":BounceThis NOTICE :You must supply the password before performing any other commands.\r\n");
	goto abort2;
   }

  } while ((char)*bufptr != (char)0) ;

  if (proxy.sock) /* proxy connected, break from BT IRC interface */
   break;
 }

 logevent("Proxy connection to %s:%s from %s:%i", proxy.host,proxy.port,
  client->ip, client->port);

 // Register user.
 if (ci.use_pass)
  bt_sendf(proxy.sock,"PASS %s\r\n", ci.pass);

 bt_sendf(proxy.sock,"NICK %s\r\nUSER %s # # %s\r\n",ci.nick,ci.user,ci.name);

 while (1)
 {
  fd_set rset = { 0 };

  FD_SET (client->sock, &rset);
  FD_SET (proxy.sock, &rset);

  if (select (0, &rset, NULL, NULL, NULL) == -1)
   goto abort;

  if (FD_ISSET (client->sock, &rset))
  {
   c = bt_recv(client->sock, buf, 4096);

   if (c <= 0)
	goto abort;

   buf[c] = 0;

   client->sent += bt_send (proxy.sock, buf);
  }

  if (FD_ISSET (proxy.sock, &rset))
  {
   c = bt_recv (proxy.sock, buf, 4096);

   if (c <= 0)
	goto abort;

   buf[c] = 0;

   client->recv += bt_send (client->sock, buf);
  }

  updatesrtowin(client);
 }

abort:
 logevent("Connection from %s:%i closed", client->ip,client->port);
abort2: // for skipping auto log.
 bt_close(client->sock);

 if (proxy.sock)
 {
  bt_close(proxy.sock);
 }

 delconn(client);

 _endthread();
}