Re: [PATCH ] tools/l2test: Add support for l2cap config request

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Bharat,

On Fri, Jun 12, 2015 at 2:44 PM, Bharat Bhusan Panda
<bharat.panda@xxxxxxxxxxx> wrote:
> Hi Luiz,
>
>> -----Original Message-----
>> From: linux-bluetooth-owner@xxxxxxxxxxxxxxx [mailto:linux-bluetooth-
>> owner@xxxxxxxxxxxxxxx] On Behalf Of Luiz Augusto von Dentz
>> Sent: Friday, June 12, 2015 4:16 PM
>> To: Bharat Panda
>> Cc: linux-bluetooth@xxxxxxxxxxxxxxx; cpgs@xxxxxxxxxxx
>> Subject: Re: [PATCH ] tools/l2test: Add support for l2cap config request
>>
>> Hi Bharat,
>>
>> On Thu, Jun 11, 2015 at 2:19 PM, Bharat Panda
>> <bharat.panda@xxxxxxxxxxx> wrote:
>> > This allows to send l2cap configuration request by providing '-o'
>> > option to l2test along with '-f' option to add destination CID.
>> >
>> > e.g.,
>> >
>> > l2test command format:
>> > l2test -o -X <mode> -f <destination CID> -P <psm> <bd_addr>
>>
>> But the kernel should handle this for us, why do you need to do it manually?
> I am not sure, whether kernel is handling it, as in my setup it fails for below PTS test cases, with error "MTC: The IUT does not sent subsequent ConfigReq or DisconnectReq after Rtx Timeout. Wait for timeout...."
>
> L2CAP Basic Mode
> TP/COS/CED/BV-08-C
> TP/COS/CFD/BV-02-C
>
> L2CAP ERTM mode
> TP/CMC/BV-01-C
> TP/CMC/BV-02-C
> TP/CMC/BV-03-C
> TP/CMC/BV-07-C
> TP/CMC/BV-14-C
>
> Anything needs to be configured in kernel, to handle it?

Have you checked the android documentation?
https://git.kernel.org/cgit/bluetooth/bluez.git/tree/android/pts-l2cap.txt

>>
>> > ---
>> >  lib/l2cap.h    |  10 ++++
>> >  tools/l2test.c | 162
>> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>> >  2 files changed, 167 insertions(+), 5 deletions(-)
>> >
>> > diff --git a/lib/l2cap.h b/lib/l2cap.h index 5ce94c4..85f3c80 100644
>> > --- a/lib/l2cap.h
>> > +++ b/lib/l2cap.h
>> > @@ -235,6 +235,16 @@ typedef struct {
>> >  #define L2CAP_IR_NOTSUPP       0x0001
>> >
>> >  typedef struct {
>> > +    uint8_t    mode;
>> > +    uint8_t    txwin_size;
>> > +    uint8_t    max_transmit;
>> > +    uint16_t   retrans_timeout;
>> > +    uint16_t   monitor_timeout;
>> > +    uint16_t   max_pdu_size;
>> > +} __attribute__ ((packed)) l2cap_conf_rfc ; #define
>> > +L2CAP_CONF_RFC_SIZE 9
>> > +
>> > +typedef struct {
>> >         uint16_t        psm;
>> >         uint16_t        scid;
>> >         uint8_t         id;
>> > diff --git a/tools/l2test.c b/tools/l2test.c index abe09c1..59500fb
>> > 100644
>> > --- a/tools/l2test.c
>> > +++ b/tools/l2test.c
>> > @@ -69,9 +69,13 @@ enum {
>> >         LSENDRECV,
>> >         CSENDRECV,
>> >         INFOREQ,
>> > +       CONFIGREQ,
>> >         PAIRING,
>> >  };
>> >
>> > +#define L2CAP_DEFAULT_RETRANS_TO       2000    /* 2 seconds */
>> > +#define L2CAP_DEFAULT_MONITOR_TO       12000   /* 12 seconds */
>> > +
>> >  static unsigned char *buf;
>> >
>> >  /* Default mtu */
>> > @@ -91,10 +95,11 @@ static int max_transmit = 3;  static long
>> > data_size = -1;  static long buffer_size = 2048;
>> >
>> > -/* Default addr and psm and cid */
>> > +/* Default addr, psm, cid and dcid */
>> >  static bdaddr_t bdaddr;
>> >  static unsigned short psm = 0;
>> >  static unsigned short cid = 0;
>> > +static uint16_t dcid = 0;
>> >
>> >  /* Default number of frames to send (-1 = infinite) */  static int
>> > num_frames = -1; @@ -1245,6 +1250,138 @@ failed:
>> >         close(sk);
>> >  }
>> >
>> > +static void l2cap_add_conf_opt(void **ptr, uint8_t type,
>> > +                                       uint8_t len, unsigned long
>> > +val) {
>> > +       l2cap_conf_opt *opt = *ptr;
>> > +
>> > +       printf("type 0x%2.2x len %u val 0x%lx \n", type, len, val);
>> > +
>> > +       opt->type = htobs(type);
>> > +       opt->len  = htobs(len);
>> > +
>> > +       switch (opt->len) {
>> > +       case 1:
>> > +               *((uint8_t *) opt->val) = val;
>> > +               break;
>> > +       case 2:
>> > +               bt_put_le16(val, opt->val);
>> > +               break;
>> > +       case 4:
>> > +               bt_put_le32(val, opt->val);
>> > +               break;
>> > +       default:
>> > +               memcpy(opt->val, (void *) val, len);
>> > +               break;
>> > +       }
>> > +
>> > +       *ptr += L2CAP_CONF_OPT_SIZE + len; }
>> > +
>> > +static int l2cap_build_conf_req(void *data) {
>> > +       l2cap_conf_req *req = data;
>> > +       l2cap_conf_rfc rfc;
>> > +       void *ptr = req->data;
>> > +
>> > +       req->dcid = htobs(dcid);
>> > +       req->flags = htobs(0x0000);
>> > +
>> > +       switch (rfcmode) {
>> > +       case L2CAP_MODE_BASIC:
>> > +               rfc.mode                = htobs(L2CAP_MODE_BASIC);
>> > +               rfc.txwin_size          = htobs(0);
>> > +               rfc.max_transmit        = htobs(0);
>> > +               rfc.retrans_timeout = htobs(0);
>> > +               rfc.monitor_timeout = htobs(0);
>> > +               rfc.max_pdu_size        = htobs(0);
>> > +
>> > +               l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
>> > +                                                       (unsigned
>> > + long) &rfc);
>> > +
>> > +               break;
>> > +
>> > +       case L2CAP_MODE_ERTM:
>> > +               rfc.mode                = htobs(L2CAP_MODE_ERTM);
>> > +               rfc.txwin_size          = htobs(txwin_size);
>> > +               rfc.max_transmit        = htobs(max_transmit);
>> > +               rfc.retrans_timeout     = htobs(L2CAP_DEFAULT_RETRANS_TO);
>> > +               rfc.monitor_timeout     = htobs(L2CAP_DEFAULT_MONITOR_TO);
>> > +               rfc.max_pdu_size        = htobs(imtu);
>> > +
>> > +               l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
>> > +                                                       (unsigned long) &rfc);
>> > +               break;
>> > +
>> > +       case L2CAP_MODE_STREAMING:
>> > +               rfc.mode                = htobs(L2CAP_MODE_STREAMING);
>> > +               rfc.txwin_size          = htobs(txwin_size);
>> > +               rfc.max_transmit        = htobs(max_transmit);
>> > +               rfc.retrans_timeout = htobs(L2CAP_DEFAULT_RETRANS_TO);
>> > +               rfc.monitor_timeout = htobs(L2CAP_DEFAULT_MONITOR_TO);
>> > +               rfc.max_pdu_size        = htobs(imtu);
>> > +
>> > +               l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
>> > +                                                       (unsigned
>> > + long) &rfc);
>> > +
>> > +               break;
>> > +       default:
>> > +               return L2CAP_CONF_REQ_SIZE;
>> > +       }
>> > +
>> > +       return (ptr - data);
>> > +}
>> > +
>> > +static void config_request(char *svr) {
>> > +       unsigned char buf[48];
>> > +       l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;
>> > +       uint8_t *req_buf = (uint8_t *) (buf + L2CAP_CMD_HDR_SIZE);
>> > +       struct sockaddr_l2 addr;
>> > +       int sk;
>> > +       int data_len = 0;
>> > +
>> > +       sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
>> > +       if (sk < 0) {
>> > +               perror("Can't create socket");
>> > +               return;
>> > +       }
>> > +
>> > +       memset(&addr, 0, sizeof(addr));
>> > +       addr.l2_family = AF_BLUETOOTH;
>> > +       bacpy(&addr.l2_bdaddr, &bdaddr);
>> > +       addr.l2_bdaddr_type = bdaddr_type;
>> > +
>> > +       if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
>> > +               perror("Can't bind socket");
>> > +               goto failed;
>> > +       }
>> > +
>> > +       memset(&addr, 0, sizeof(addr));
>> > +       addr.l2_family = AF_BLUETOOTH;
>> > +       str2ba(svr, &addr.l2_bdaddr);
>> > +       addr.l2_bdaddr_type = bdaddr_type;
>> > +
>> > +       if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
>> > +               perror("Can't connect socket");
>> > +               goto failed;
>> > +       }
>> > +
>> > +       memset(buf, 0, sizeof(buf));
>> > +       cmd->code  = L2CAP_CONF_REQ;
>> > +       cmd->ident = 141;
>> > +       data_len = l2cap_build_conf_req(req_buf);
>> > +       cmd->len = htobs(data_len);
>> > +
>> > +       if (send(sk, buf, L2CAP_CMD_HDR_SIZE + data_len, 0) < 0) {
>> > +               perror("Can't send info request");
>> > +               goto failed;
>> > +       }
>> > +
>> > +failed:
>> > +       close(sk);
>> > +}
>> > +
>> >  static void do_pairing(char *svr)
>> >  {
>> >         struct sockaddr_l2 addr;
>> > @@ -1311,7 +1448,8 @@ static void usage(void)
>> >                 "\t-c connect, disconnect, connect, ...\n"
>> >                 "\t-m multiple connects\n"
>> >                 "\t-p trigger dedicated bonding\n"
>> > -               "\t-z information request\n");
>> > +               "\t-z information request\n"
>> > +               "\t-o configuration request\n");
>> >
>> >         printf("Options:\n"
>> >                 "\t[-b bytes] [-i device] [-P psm] [-J cid]\n"
>> > @@ -1340,7 +1478,7 @@ static void usage(void)
>> >                 "\t[-M] become master\n"
>> >                 "\t[-T] enable timestamps\n"
>> >                 "\t[-V type] address type (help for list, default = bredr)\n"
>> > -               "\t[-e seq] initial sequence value (default = 0)\n");
>> > +               "\t[-e DCID] Destination CID\n");
>> >  }
>> >
>> >  int main(int argc, char *argv[])
>> > @@ -1350,8 +1488,8 @@ int main(int argc, char *argv[])
>> >
>> >         bacpy(&bdaddr, BDADDR_ANY);
>> >
>> > -       while ((opt = getopt(argc, argv, "a:b:cde:g:i:mnpqrstuwxyz"
>> > -               "AB:C:D:EF:GH:I:J:K:L:MN:O:P:Q:RSTUV:W:X:Y:Z:")) != EOF) {
>> > +       while ((opt = getopt(argc, argv, "a:b:cde:g:i:mnopqrstuwxyz"
>> > +               "AB:C:D:EFf:GH:I:J:K:L:MN:O:P:Q:RSTUV:W:X:Y:Z:")) !=
>> > + EOF) {
>> >                 switch (opt) {
>> >                 case 'r':
>> >                         mode = RECV;
>> > @@ -1412,6 +1550,11 @@ int main(int argc, char *argv[])
>> >                         need_addr = 1;
>> >                         break;
>> >
>> > +               case 'o':
>> > +                       mode = CONFIGREQ;
>> > +                       need_addr = 1;
>> > +                       break;
>> > +
>> >                 case 'p':
>> >                         mode = PAIRING;
>> >                         need_addr = 1; @@ -1565,6 +1708,11 @@ int
>> > main(int argc, char *argv[])
>> >                         disc_delay = atoi(optarg) * 1000;
>> >                         break;
>> >
>> > +               case 'f':
>> > +                       dcid = strtoul(optarg, NULL, 16);
>> > +                       printf("dcid 0x%2x", dcid);
>> > +                       break;
>> > +
>> >                 default:
>> >                         usage();
>> >                         exit(1);
>> > @@ -1666,6 +1814,10 @@ int main(int argc, char *argv[])
>> >                         info_request(argv[optind]);
>> >                         exit(0);
>> >
>> > +               case CONFIGREQ:
>> > +                       config_request(argv[optind]);
>> > +                       exit(0);
>> > +
>> >                 case PAIRING:
>> >                         do_pairing(argv[optind]);
>> >                         exit(0);
>> > --
>> > 1.9.1
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe
>> > linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
>>
>> --
>> Luiz Augusto von Dentz
> --
> BR,
> Bharat
>
>
>
>



-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux