Initial avtest support for sending commands
diff --git a/test/avtest.c b/test/avtest.c
index 996aa16..e1dabf1 100644
--- a/test/avtest.c
+++ b/test/avtest.c
@@ -238,32 +238,117 @@
close(sk);
}
+static int do_connect(const bdaddr_t *src, const bdaddr_t *dst)
+{
+ struct sockaddr_l2 addr;
+ int sk, err;
+
+ sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+ if (sk < 0) {
+ perror("Can't create socket");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ bacpy(&addr.l2_bdaddr, src);
+
+ if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("Can't bind socket");
+ goto error;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ bacpy(&addr.l2_bdaddr, dst);
+ addr.l2_psm = htobs(25);
+
+ err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
+ if (err < 0) {
+ perror("Unable to connect");
+ goto error;
+ }
+
+ return sk;
+
+error:
+ close(sk);
+ return -1;
+}
+
+static void do_send(int sk, unsigned char cmd)
+{
+ unsigned char buf[672];
+ struct avdtp_header *hdr = (void *) buf;
+ ssize_t len;
+
+ memset(buf, 0, sizeof(buf));
+
+ switch (cmd) {
+ case AVDTP_DISCOVER:
+ hdr->message_type = AVDTP_MSG_TYPE_COMMAND;
+ hdr->packet_type = AVDTP_PKT_TYPE_SINGLE;
+ hdr->signal_id = AVDTP_DISCOVER;
+ len = write(sk, buf, 2);
+ break;
+ }
+
+ len = read(sk, buf, sizeof(buf));
+
+ dump_buffer(buf, len);
+ dump_header(hdr);
+}
+
static void usage()
{
printf("avtest - Audio/Video testing ver %s\n", VERSION);
printf("Usage:\n"
- "\tavtest [options]\n");
+ "\tavtest [options] [remote address]\n");
printf("Options:\n"
- "\t--reject <command>\tReject command\n");
+ "\t--reject <command>\tReject command\n"
+ "\t--send <command>\tSend command\n"
+ "\t--invalid <command>\tSend invalid command\n");
}
static struct option main_options[] = {
{ "help", 0, 0, 'h' },
{ "device", 1, 0, 'i' },
{ "reject", 1, 0, 'r' },
+ { "send", 1, 0, 's' },
+ { "invalid", 1, 0, 'f' },
{ 0, 0, 0, 0 }
};
+static unsigned char parse_cmd(const char *arg)
+{
+ if (!strncmp(arg, "discov", 6))
+ return AVDTP_DISCOVER;
+ else if (!strncmp(arg, "capa", 4))
+ return AVDTP_GET_CAPABILITIES;
+ else if (!strncmp(arg, "getcapa", 7))
+ return AVDTP_GET_CAPABILITIES;
+ else if (!strncmp(arg, "setconf", 7))
+ return AVDTP_SET_CONFIGURATION;
+ else if (!strncmp(arg, "getconf", 7))
+ return AVDTP_GET_CONFIGURATION;
+ else
+ return atoi(arg);
+}
+
+enum {
+ MODE_NONE, MODE_REJECT, MODE_SEND, MODE_SEND_INVALID,
+};
+
int main(int argc, char *argv[])
{
- unsigned char reject = 0x00;
+ unsigned char cmd = 0x00;
bdaddr_t src, dst;
- int opt;
+ int opt, mode = MODE_NONE, sk;
bacpy(&src, BDADDR_ANY);
bacpy(&dst, BDADDR_ANY);
- while ((opt = getopt_long(argc, argv, "+i:r:h",
+ while ((opt = getopt_long(argc, argv, "+i:r:s:f:h",
main_options, NULL)) != EOF) {
switch (opt) {
case 'i':
@@ -274,18 +359,18 @@
break;
case 'r':
- if (!strncmp(optarg, "discov", 6))
- reject = AVDTP_DISCOVER;
- else if (!strncmp(optarg, "capa", 4))
- reject = AVDTP_GET_CAPABILITIES;
- else if (!strncmp(optarg, "getcapa", 7))
- reject = AVDTP_GET_CAPABILITIES;
- else if (!strncmp(optarg, "setconf", 7))
- reject = AVDTP_SET_CONFIGURATION;
- else if (!strncmp(optarg, "getconf", 7))
- reject = AVDTP_GET_CONFIGURATION;
- else
- reject = atoi(optarg);
+ mode = MODE_REJECT;
+ cmd = parse_cmd(optarg);
+ break;
+
+ case 's':
+ mode = MODE_SEND;
+ cmd = parse_cmd(optarg);
+ break;
+
+ case 'v':
+ mode = MODE_SEND_INVALID;
+ cmd = parse_cmd(optarg);
break;
case 'h':
@@ -295,7 +380,25 @@
}
}
- do_listen(&src, reject);
+ if (argv[optind])
+ str2ba(argv[optind], &dst);
+
+ switch (mode) {
+ case MODE_REJECT:
+ do_listen(&src, cmd);
+ break;
+ case MODE_SEND:
+ case MODE_SEND_INVALID:
+ sk = do_connect(&src, &dst);
+ if (sk < 0)
+ exit(1);
+ do_send(sk, cmd);
+ close(sk);
+ break;
+ default:
+ fprintf(stderr, "No operating mode specified!\n");
+ exit(1);
+ }
return 0;
}