upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / net / wireless / bcm4330 / src / wl / sys / uamp_linux.c
1 /*
2  *  Name:       uamp_linux.c
3  *
4  *  Description: Universal AMP API
5  *
6  * Copyright (C) 1999-2011, Broadcom Corporation
7  * 
8  *         Unless you and Broadcom execute a separate written software license
9  * agreement governing use of this software, this software is licensed to you
10  * under the terms of the GNU General Public License version 2 (the "GPL"),
11  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12  * following added to such license:
13  * 
14  *      As a special exception, the copyright holders of this software give you
15  * permission to link this software with independent modules, and to copy and
16  * distribute the resulting executable under terms of your choice, provided that
17  * you also meet, for each linked independent module, the terms and conditions of
18  * the license of that module.  An independent module is a module which is not
19  * derived from this software.  The special exception does not apply to any
20  * modifications of the software.
21  * 
22  *      Notwithstanding the above, under no circumstances may you combine this
23  * software in any way with any other Broadcom software provided under a license
24  * other than the GPL, without Broadcom's express prior written consent.
25  *
26  * $Id: uamp_linux.c,v 1.2.110.1 2011-02-05 00:22:40 $
27  *
28  */
29
30 /* ---- Include Files ---------------------------------------------------- */
31
32 #include "typedefs.h"
33 #include "bcmutils.h"
34 #include "bcmendian.h"
35 #include "uamp_api.h"
36 #include "wlioctl.h"
37 #include "dhdioctl.h"
38 #include "proto/bt_amp_hci.h"
39 #include "proto/bcmevent.h"
40 #include "proto/802.11_bta.h"
41
42 #include <ctype.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include <assert.h>
49
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <arpa/inet.h>
53 #include <sys/ioctl.h>
54 #include <net/if.h>
55 #include <linux/if_packet.h>
56 #include <pthread.h>
57
58 #include <linux/if_ether.h>
59 #include <mqueue.h>
60
61 #include <linux/sockios.h>
62 #include <linux/ethtool.h>
63
64
65 /* ---- Public Variables ------------------------------------------------- */
66 /* ---- Private Constants and Types -------------------------------------- */
67
68 #define UAMP_DEBUG      1
69
70 #define DEV_TYPE_LEN    3 /* length for devtype 'wl'/'et' */
71
72 #define UAMP_EVT_Q_STR          "/uamp_evt_q"
73 #define UAMP_PKT_RX_Q_STR       "/uamp_pkt_rx_q"
74
75 #if UAMP_DEBUG
76         #define UAMP_PRINT(a)   printf a
77         #define UAMP_TRACE(a)   printf a
78         #define UAMP_ERROR(a)   printf a
79 #else
80         #define UAMP_PRINT(a)   printf a
81         #define UAMP_TRACE(a)
82         #define UAMP_ERROR(a)   printf a
83 #endif
84
85 #if ((BRCM_BLUETOOTH_HOST == 1) && (UAMP_IS_GKI_AWARE == 1))
86 #include "gki.h"
87 #define UAMP_ALLOC(a)   GKI_getbuf(a+sizeof(BT_HDR))
88 #define UAMP_FREE(a)    GKI_freebuf(a)
89 #else
90 #define UAMP_ALLOC(a)   malloc(a)
91 #define UAMP_FREE(a)    free(a)
92 #endif   /* BRCM_BLUETOOTH_HOST && UAMP_IS_GKI_AWARE */
93
94 #define GET_UAMP_FROM_ID(id)    (((id) == 0) ? &g_uamp_mgr.uamp : NULL)
95
96 #define MAX_IOVAR_LEN   2096
97
98
99 /* State associated with a single universal AMP. */
100 typedef struct UAMP_STATE
101 {
102         /* Unique universal AMP identifier. */
103         tUAMP_ID                id;
104
105         /* Event/data queues. */
106         mqd_t                   evt_q;
107         mqd_t                   pkt_rx_q;
108
109         /* Event file descriptors. */
110         int                     evt_fd;
111         int                     evt_fd_pipe[2];
112
113
114         /* Packet rx descriptors. */
115         int                     pkt_rx_fd;
116         int                     pkt_rx_fd_pipe[2];
117
118         /* Storage buffers for recieved events and packets. */
119         uint32                  event_data[WLC_IOCTL_SMLEN/4];
120         uint32                  pkt_data[MAX_IOVAR_LEN/4];
121
122 } UAMP_STATE;
123
124
125 /* State associated with collection of univerisal AMPs. */
126 typedef struct UAMP_MGR
127 {
128         /* Event/data callback. */
129         tUAMP_CBACK             callback;
130
131         /* WLAN interface. */
132         struct ifreq            ifr;
133
134         /* UAMP state. Only support a single AMP currently. */
135         UAMP_STATE              uamp;
136
137 } UAMP_MGR;
138
139
140 /* ---- Private Variables ------------------------------------------------ */
141
142 static UAMP_MGR         g_uamp_mgr;
143
144
145 /* ---- Private Function Prototypes -------------------------------------- */
146
147 static void usage(void);
148 static int uamp_accept_test(void);
149 static int uamp_create_test(void);
150 static UINT16 uamp_write_cmd(uint16 opcode, uint8 *params, uint8 len,
151                              amp_hci_cmd_t *cmd, unsigned int max_len);
152 static UINT16 uamp_write_data(uint16 handle, uint8 *data, uint8 len,
153                               amp_hci_ACL_data_t *pkt, unsigned int max_len);
154
155 static int ioctl_get(int cmd, void *buf, int len);
156 static int ioctl_set(int cmd, void *buf, int len);
157 static int iovar_set(const char *iovar, void *param, int paramlen);
158 static int iovar_setbuf(const char *iovar, void *param, int paramlen, void *bufptr,
159                         int buflen);
160 static int iovar_mkbuf(const char *name, char *data, uint datalen, char *iovar_buf,
161                        uint buflen, int *perr);
162 static int wl_ioctl(int cmd, void *buf, int len, bool set);
163 static void wl_get_interface_name(struct ifreq *ifr);
164 static int wl_get_dev_type(char *name, void *buf, int len);
165 static void syserr(char *s);
166
167 static int init_event_rx(UAMP_STATE *uamp);
168 static void deinit_event_rx(UAMP_STATE *uamp);
169 static void* event_thread(void *param);
170 static void handle_event(UAMP_STATE *uamp);
171
172 static int init_pkt_rx(UAMP_STATE *uamp);
173 static void deinit_pkt_rx(UAMP_STATE *uamp);
174 static void* packet_rx_thread(void *param);
175 static void handle_rx_pkt(UAMP_STATE *uamp);
176
177
178 #if (BRCM_BLUETOOTH_HOST == 1)
179 #if (UAMP_IS_GKI_AWARE == 1)
180 void wl_event_gki_callback(wl_event_msg_t* event, void* event_data);
181 int wl_btamp_rx_gki_pkt_callback(wl_drv_netif_pkt pkt, unsigned int len);
182 #endif   /* UAMP_IS_GKI_AWARE */
183 static void *uamp_get_acl_buf(unsigned int len);
184 void *hcisu_amp_get_acl_buf(int len);      /* Get GKI buffer from ACL pool */
185 void hcisu_handle_amp_data_buf(void *pkt, unsigned int len);   /* Send GKI buffer to BTU task */
186 void hcisu_handle_amp_evt_buf(void* evt, unsigned int len);
187 int wl_is_drv_init_done(void);
188 #endif   /* BRCM_BLUETOOTH_HOST */
189
190 /* ---- Functions -------------------------------------------------------- */
191
192 /* ------------------------------------------------------------------------- */
193 BT_API BOOLEAN UAMP_Init(tUAMP_CBACK p_cback)
194 {
195         memset(&g_uamp_mgr, 0, sizeof(g_uamp_mgr));
196         g_uamp_mgr.callback = p_cback;
197
198         wl_get_interface_name(&g_uamp_mgr.ifr);
199
200         return (TRUE);
201 }
202
203
204 /* ------------------------------------------------------------------------- */
205 BT_API BOOLEAN UAMP_Open(tUAMP_ID amp_id)
206 {
207         UAMP_STATE *uamp = GET_UAMP_FROM_ID(amp_id);
208
209 #if (BRCM_BLUETOOTH_HOST == 1)
210         if (!wl_is_drv_init_done()) {
211                 UAMP_ERROR(("%s: WLAN driver is not initialized! \n", __FUNCTION__));
212                 return FALSE;
213         }
214 #endif   /* BRCM_BLUETOOTH_HOST */
215
216         /* Setup event receive. */
217         if ((init_event_rx(uamp)) < 0) {
218                 return (FALSE);
219         }
220
221         /* Setup packet receive. */
222         if ((init_pkt_rx(uamp)) < 0) {
223                 return (FALSE);
224         }
225
226         return (TRUE);
227 }
228
229
230 /* ------------------------------------------------------------------------- */
231 BT_API void UAMP_Close(tUAMP_ID amp_id)
232 {
233         UAMP_STATE      *uamp = GET_UAMP_FROM_ID(amp_id);
234
235 #if (BRCM_BLUETOOTH_HOST == 1)
236         if (!wl_is_drv_init_done()) {
237                 UAMP_ERROR(("%s: WLAN driver is not initialized! \n", __FUNCTION__));
238                 return;
239         }
240 #endif   /* BRCM_BLUETOOTH_HOST */
241
242         /* Cleanup packet and event receive. */
243         deinit_pkt_rx(uamp);
244         deinit_event_rx(uamp);
245 }
246
247 /* ------------------------------------------------------------------------- */
248 BT_API UINT16 UAMP_Write(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 num_bytes, tUAMP_CH channel)
249 {
250         int ret = -1;
251         UINT16 num_bytes_written = num_bytes;
252
253         UNUSED_PARAMETER(amp_id);
254
255 #if (BRCM_BLUETOOTH_HOST == 1)
256         if (!wl_is_drv_init_done()) {
257                 UAMP_ERROR(("%s: WLAN driver is not initialized! \n", __FUNCTION__));
258                 return (0);
259         }
260 #endif   /* BRCM_BLUETOOTH_HOST */
261
262         if (channel == UAMP_CH_HCI_CMD) {
263                 ret = iovar_set("HCI_cmd", p_buf, num_bytes);
264         }
265         else if (channel == UAMP_CH_HCI_DATA) {
266                 ret = iovar_set("HCI_ACL_data", p_buf, num_bytes);
267         }
268
269         if (ret != 0) {
270                 num_bytes_written = 0;
271                 UAMP_ERROR(("UAMP_Write error: %i  ( 0=success )\n", ret));
272         }
273
274         return (num_bytes_written);
275 }
276
277
278 /* ------------------------------------------------------------------------- */
279 BT_API UINT16 UAMP_Read(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 buf_size, tUAMP_CH channel)
280 {
281         UAMP_STATE              *uamp = GET_UAMP_FROM_ID(amp_id);
282         mqd_t                   num_bytes;
283         unsigned int            msg_prio;
284
285 #if (BRCM_BLUETOOTH_HOST == 1)
286         if (!wl_is_drv_init_done()) {
287                 UAMP_ERROR(("%s: WLAN driver is not initialized! \n", __FUNCTION__));
288                 return (0);
289         }
290 #endif   /* BRCM_BLUETOOTH_HOST */
291
292
293         if (channel == UAMP_CH_HCI_EVT) {
294                 /* Dequeue event. */
295                 num_bytes = mq_receive(uamp->evt_q, (char *)p_buf, buf_size, &msg_prio);
296                 if (num_bytes == -1) {
297                         UAMP_ERROR(("%s: Event queue receive error!\n", __FUNCTION__));
298                         return (0);
299                 }
300
301                 return (num_bytes);
302         }
303         else if (channel == UAMP_CH_HCI_DATA) {
304                 /* Dequeue rx packet. */
305                 num_bytes = mq_receive(uamp->pkt_rx_q, (char *)p_buf, buf_size, &msg_prio);
306                 if (num_bytes == -1) {
307                         UAMP_ERROR(("%s: Pkt queue receive error!\n", __FUNCTION__));
308                         return (0);
309                 }
310
311                 return (num_bytes);
312         }
313
314         return (0);
315 }
316
317
318 /*
319  * Get IOCTL given the parameter buffer.
320  */
321 static int
322 ioctl_get(int cmd, void *buf, int len)
323 {
324         return wl_ioctl(cmd, buf, len, FALSE);
325 }
326
327
328 /*
329  * Set IOCTL given the parameter buffer.
330  */
331 static int
332 ioctl_set(int cmd, void *buf, int len)
333 {
334         return wl_ioctl(cmd, buf, len, TRUE);
335 }
336
337
338 /*
339  * Set named iovar given the parameter buffer.
340  */
341 static int
342 iovar_set(const char *iovar, void *param, int paramlen)
343 {
344         static char smbuf[MAX_IOVAR_LEN];
345
346         memset(smbuf, 0, sizeof(smbuf));
347
348         return iovar_setbuf(iovar, param, paramlen, smbuf, sizeof(smbuf));
349 }
350
351 /*
352  * Set named iovar providing both parameter and i/o buffers.
353  */
354 static int
355 iovar_setbuf(const char *iovar,
356         void *param, int paramlen, void *bufptr, int buflen)
357 {
358         int err;
359         int iolen;
360
361         iolen = iovar_mkbuf(iovar, param, paramlen, bufptr, buflen, &err);
362         if (err)
363                 return err;
364
365         return ioctl_set(DHD_SET_VAR, bufptr, iolen);
366 }
367
368
369 /*
370  * Format an iovar buffer.
371  */
372 static int
373 iovar_mkbuf(const char *name, char *data, uint datalen, char *iovar_buf, uint buflen, int *perr)
374 {
375         int iovar_len;
376
377         iovar_len = strlen(name) + 1;
378
379         /* check for overflow */
380         if ((iovar_len + datalen) > buflen) {
381                 *perr = -1;
382                 return 0;
383         }
384
385         /* copy data to the buffer past the end of the iovar name string */
386         if (datalen > 0)
387                 memmove(&iovar_buf[iovar_len], data, datalen);
388
389         /* copy the name to the beginning of the buffer */
390         strcpy(iovar_buf, name);
391
392         *perr = 0;
393         return (iovar_len + datalen);
394 }
395
396
397 /*
398  * Send IOCTL to WLAN driver.
399  */
400 static int
401 wl_ioctl(int cmd, void *buf, int len, bool set)
402 {
403         struct ifreq ifr;
404         dhd_ioctl_t ioc;
405         int ret = 0;
406         int s;
407
408         memset(&ifr, 0, sizeof(ifr));
409         strncpy(ifr.ifr_name, g_uamp_mgr.ifr.ifr_name, sizeof(ifr.ifr_name));
410
411         /* open socket to kernel */
412         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
413                 ret = -1;
414                 return ret;
415         }
416
417         /* do it */
418         ioc.cmd = cmd;
419         ioc.buf = buf;
420         ioc.len = len;
421         ioc.set = set;
422         ioc.driver = DHD_IOCTL_MAGIC;
423         ifr.ifr_data = (caddr_t) &ioc;
424         if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0) {
425                 ret = -1;
426         }
427
428         /* cleanup */
429         close(s);
430         return ret;
431 }
432
433
434 static int
435 wl_get_dev_type(char *name, void *buf, int len)
436 {
437         int s;
438         int ret;
439         struct ifreq ifr;
440         struct ethtool_drvinfo info;
441
442         /* open socket to kernel */
443         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
444                 syserr("socket");
445
446         /* get device type */
447         memset(&info, 0, sizeof(info));
448         info.cmd = ETHTOOL_GDRVINFO;
449         ifr.ifr_data = (caddr_t)&info;
450         strncpy(ifr.ifr_name, name, IFNAMSIZ);
451         if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
452
453                 /* print a good diagnostic if not superuser */
454                 if (errno == EPERM)
455                         syserr("wl_get_dev_type");
456
457                 *(char *)buf = '\0';
458         } else {
459                 strncpy(buf, info.driver, len);
460         }
461
462         close(s);
463         return ret;
464 }
465
466
467 static void
468 wl_get_interface_name(struct ifreq *ifr)
469 {
470         char proc_net_dev[] = "/proc/net/dev";
471         FILE *fp;
472         char buf[1000], *c, *name;
473         char dev_type[DEV_TYPE_LEN];
474         int ret = -1;
475
476         ifr->ifr_name[0] = '\0';
477
478         if (!(fp = fopen(proc_net_dev, "r")))
479                 return;
480
481         /* eat first two lines */
482         if (!fgets(buf, sizeof(buf), fp) ||
483             !fgets(buf, sizeof(buf), fp)) {
484                 fclose(fp);
485                 return;
486         }
487
488         while (fgets(buf, sizeof(buf), fp)) {
489                 c = buf;
490                 while (isspace(*c))
491                         c++;
492                 if (!(name = strsep(&c, ":")))
493                         continue;
494                 strncpy(ifr->ifr_name, name, IFNAMSIZ);
495                 if (wl_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
496                         (!strncmp(dev_type, "wl", 2) || !strncmp(dev_type, "dhd", 3)))
497                 {
498                         ret = 0;
499                         break;
500                 }
501                 ifr->ifr_name[0] = '\0';
502         }
503
504         fclose(fp);
505 }
506
507
508 static void
509 syserr(char *s)
510 {
511         fprintf(stderr, "uamp_linux:");
512         perror(s);
513         exit(errno);
514 }
515
516
517 #if (BRCM_BLUETOOTH_HOST == 1)
518 static void *uamp_get_acl_buf(unsigned int len)
519 {
520         return (hcisu_amp_get_acl_buf(len));
521 }
522 #endif   /* BRCM_BLUETOOTH_HOST */
523
524
525 /*
526  * Setup packet receive.
527  */
528 static int
529 init_pkt_rx(UAMP_STATE *uamp)
530 {
531         struct ifreq            ifr;
532         int                     fd = -1;
533         struct sockaddr_ll      local;
534         int                     err;
535         int                     fd_pipe[2] = {-1, -1};
536         pthread_t               h;
537
538
539         memset(&ifr, 0, sizeof(ifr));
540         wl_get_interface_name(&ifr);
541
542         /* Create and bind socket to receive packets. */
543         fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_802_2));
544         if (fd < 0) {
545                 UAMP_ERROR(("%s: Cannot open socket", __FUNCTION__));
546                 return (-1);
547         }
548
549         err = ioctl(fd, SIOCGIFINDEX, &ifr);
550         if (err < 0) {
551                 UAMP_ERROR(("%s: Cannot get index %d\n", __FUNCTION__, err));
552                 close(fd);
553                 return (-1);
554         }
555
556         memset(&local, 0, sizeof(local));
557         local.sll_family        = PF_PACKET;
558         local.sll_protocol      = htons(ETH_P_802_2);
559         local.sll_ifindex       = ifr.ifr_ifindex;
560
561         if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0) {
562                 UAMP_ERROR(("%s: Cannot bind socket", __FUNCTION__));
563                 close(fd);
564                 return (-1);
565         }
566
567
568         /* Create pipe used to terminate receive packet thread. */
569         if (pipe(fd_pipe) != 0) {
570                 UAMP_ERROR(("%s: pipe failed\n", __FUNCTION__));
571                 goto cleanup;
572         }
573
574         /* Save in instance memory. */
575         uamp->pkt_rx_fd         = fd;
576         uamp->pkt_rx_fd_pipe[0] = fd_pipe[0];
577         uamp->pkt_rx_fd_pipe[1] = fd_pipe[1];
578
579
580         /* Create message queue for received packets. */
581
582         uamp->pkt_rx_q = mq_open(UAMP_PKT_RX_Q_STR, O_RDWR | O_CREAT, 0666, NULL);
583
584
585
586         /* Spawn packet handling thread. */
587         pthread_create(&h, NULL, packet_rx_thread, uamp);
588
589         return (fd);
590
591 cleanup:
592         if (-1 != fd)           close(fd);
593         if (-1 != fd_pipe[0])   close(fd_pipe[0]);
594         if (-1 != fd_pipe[1])   close(fd_pipe[1]);
595         return (-1);
596 }
597
598
599 /*
600  * Cleanup packet receive.
601  */
602 static void
603 deinit_pkt_rx(UAMP_STATE *uamp)
604 {
605         /* Cleanup the message queue. */
606         mq_close(uamp->pkt_rx_q);
607         mq_unlink(UAMP_PKT_RX_Q_STR);
608
609         /* Kill the receive thread. */
610         write(uamp->pkt_rx_fd_pipe[1], NULL, 0);
611         close(uamp->pkt_rx_fd_pipe[1]);
612 }
613
614
615 /*
616  * Packet receive thread.
617  */
618 static void*
619 packet_rx_thread(void *param)
620 {
621         UAMP_STATE *uamp = (UAMP_STATE *) param;
622
623         UAMP_PRINT(("Start packet rx wait loop\n"));
624
625         while (1) {
626                 fd_set          rfds;   /* fds for select */
627                 int             last_fd;
628                 int             ret;
629
630                 FD_ZERO(&rfds);
631                 FD_SET(uamp->pkt_rx_fd_pipe[0], &rfds);
632                 FD_SET(uamp->pkt_rx_fd, &rfds);
633                 last_fd = MAX(uamp->pkt_rx_fd_pipe[0], uamp->pkt_rx_fd);
634
635                 /* Wait on stop pipe or rx packet socket */
636                 ret = select(last_fd+1, &rfds, NULL, NULL, NULL);
637
638                 /* Error processing */
639                 if (0 > ret) {
640                         UAMP_ERROR(("%s: Unhandled signal on pkt rx socket\n", __FUNCTION__));
641                         break;
642                 }
643
644                 /* Stop processing */
645                 if (FD_ISSET(uamp->pkt_rx_fd_pipe[0], &rfds)) {
646                         UAMP_PRINT(("%s: stop rcvd on dispatcher pipe\n", __FUNCTION__));
647                         break;
648                 }
649
650                 /* Packet processing */
651                 if (FD_ISSET(uamp->pkt_rx_fd, &rfds)) {
652                         handle_rx_pkt(uamp);
653                 }
654
655         }  /* end-while(1) */
656
657         UAMP_PRINT(("%s: End packet rx wait loop\n", __FUNCTION__));
658
659         close(uamp->pkt_rx_fd);
660         close(uamp->pkt_rx_fd_pipe[0]);
661
662         UAMP_TRACE(("Exit %s\n", __FUNCTION__));
663         return (NULL);
664 }
665
666 /*
667  * Process received packet.
668  */
669 static void
670 handle_rx_pkt(UAMP_STATE *uamp)
671 {
672         int                             bytes;
673         struct dot11_llc_snap_header    *lsh;
674         amp_hci_ACL_data_t              *acl_data;
675
676         /* Read packet. */
677         bytes = recv(uamp->pkt_rx_fd, uamp->pkt_data, sizeof(uamp->pkt_data), MSG_DONTWAIT);
678
679         /* Error handling. */
680         if (bytes < 0) {
681                 if (errno != EINTR && errno != EAGAIN) {
682                         UAMP_ERROR(("%s: Error reading packet rx socket: %s\n",
683                                     __FUNCTION__, strerror(errno)));
684                         return;
685                 }
686         }
687
688         if (bytes == 0) {
689                 UAMP_ERROR(("%s: EOF on packet rx socket", __FUNCTION__));
690                 return;
691         }
692
693
694         /* Verify that this is an HCI data packet. */
695         lsh = (struct dot11_llc_snap_header *)uamp->pkt_data;
696         if (bcmp(lsh, BT_SIG_SNAP_MPROT, DOT11_LLC_SNAP_HDR_LEN - 2) != 0 ||
697                 ntoh16(lsh->type) != BTA_PROT_L2CAP) {
698                 /* Not HCI data. */
699                 return;
700         }
701
702
703         UAMP_TRACE(("%s: received packet!\n", __FUNCTION__));
704
705         acl_data = (amp_hci_ACL_data_t *) &lsh[1];
706         bytes -= DOT11_LLC_SNAP_HDR_LEN;
707
708 #if (BRCM_BLUETOOTH_HOST == 1)
709         hcisu_handle_amp_data_buf(acl_data, bytes);
710 #else
711         {
712                 tUAMP_EVT_DATA                  uamp_evt_data;
713 #if (UAMP_DEBUG == 1)
714                 /* Debug - dump rx packet data. */
715                 {
716                         int i;
717                         uint8 *data = acl_data->data;
718                         UAMP_TRACE(("data(%d): ", bytes));
719                         for (i = 0; i < bytes; i++) {
720                                 UAMP_TRACE(("0x%x ", data[i]));
721                         }
722                         UAMP_TRACE(("\n"));
723                 }
724 #endif   /* UAMP_DEBUG */
725
726                 /* Post packet to queue. Stack will de-queue it with call to UAMP_Read(). */
727                 if (mq_send(uamp->pkt_rx_q, (const char *)acl_data, bytes, 0) != 0) {
728                         /* Unable to queue packet */
729                         UAMP_ERROR(("%s: Unable to queue rx packet data!\n", __FUNCTION__));
730                         return;
731                 }
732
733
734                 /* Inform application stack of received packet. */
735                 memset(&uamp_evt_data, 0, sizeof(uamp_evt_data));
736                 uamp_evt_data.channel = UAMP_CH_HCI_DATA;
737                 g_uamp_mgr.callback(0, UAMP_EVT_RX_READY, &uamp_evt_data);
738         }
739 #endif /* BRCM_BLUETOOTH_HOST */
740 }
741
742
743 /*
744  * Setup event receive.
745  */
746 static int
747 init_event_rx(UAMP_STATE *uamp)
748 {
749         struct ifreq            ifr;
750         int                     fd = -1;
751         struct sockaddr_ll      local;
752         int                     err;
753         int                     fd_pipe[2] = {-1, -1};
754         pthread_t               h;
755
756         memset(&ifr, 0, sizeof(ifr));
757         wl_get_interface_name(&ifr);
758         UAMP_PRINT(("ifr_name (%s)\n", ifr.ifr_name));
759
760         /* Create and bind socket to receive packets. */
761         fd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE_BRCM));
762         if (fd < 0) {
763                 UAMP_ERROR(("%s: Cannot open socket", __FUNCTION__));
764                 return (-1);
765         }
766
767         err = ioctl(fd, SIOCGIFINDEX, &ifr);
768         if (err < 0) {
769                 UAMP_ERROR(("%s: Cannot get index %d\n", __FUNCTION__, err));
770                 close(fd);
771                 return (-1);
772         }
773
774         memset(&local, 0, sizeof(local));
775         local.sll_family        = AF_PACKET;
776         local.sll_protocol      = htons(ETHER_TYPE_BRCM);
777         local.sll_ifindex       = ifr.ifr_ifindex;
778
779         if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0) {
780                 UAMP_ERROR(("%s: Cannot bind event socket", __FUNCTION__));
781                 close(fd);
782                 return (-1);
783         }
784
785
786         /* Create pipe used to terminate receive packet thread. */
787         if (pipe(fd_pipe) != 0) {
788                 UAMP_ERROR(("%s: pipe failed\n", __FUNCTION__));
789                 goto cleanup;
790         }
791
792         /* Save in instance memory. */
793         uamp->evt_fd            = fd;
794         uamp->evt_fd_pipe[0]    = fd_pipe[0];
795         uamp->evt_fd_pipe[1]    = fd_pipe[1];
796
797
798         /* Create message queue for received events. */
799
800         uamp->evt_q = mq_open(UAMP_EVT_Q_STR, O_RDWR | O_CREAT, 0666, NULL);
801         UAMP_PRINT(("evt_q(0x%x)\n", (int)uamp->evt_q));
802
803
804
805         /* Spawn event handling thread. */
806         pthread_create(&h, NULL, event_thread, uamp);
807
808         return (fd);
809
810 cleanup:
811         if (-1 != fd)           close(fd);
812         if (-1 != fd_pipe[0])   close(fd_pipe[0]);
813         if (-1 != fd_pipe[1])   close(fd_pipe[1]);
814         return (-1);
815 }
816
817
818 /*
819  * Cleanup event receive.
820  */
821 static void
822 deinit_event_rx(UAMP_STATE      *uamp)
823 {
824         /* Cleanup the message queue. */
825         mq_close(uamp->evt_q);
826         mq_unlink(UAMP_EVT_Q_STR);
827
828         /* Kill the receive thread. */
829         write(uamp->evt_fd_pipe[1], NULL, 0);
830         close(uamp->evt_fd_pipe[1]);
831 }
832
833 /*
834  * Event receive thread.
835  */
836 static void*
837 event_thread(void *param)
838 {
839         UAMP_STATE *uamp = (UAMP_STATE *) param;
840
841         UAMP_PRINT(("Start event wait loop\n"));
842
843         while (1) {
844                 fd_set          rfds;   /* fds for select */
845                 int             last_fd;
846                 int             ret;
847
848                 FD_ZERO(&rfds);
849                 FD_SET(uamp->evt_fd_pipe[0], &rfds);
850                 FD_SET(uamp->evt_fd, &rfds);
851                 last_fd = MAX(uamp->evt_fd_pipe[0], uamp->evt_fd);
852
853                 /* Wait on stop pipe or brcm event socket. */
854                 ret = select(last_fd+1, &rfds, NULL, NULL, NULL);
855
856                 /* Error processing */
857                 if (0 > ret) {
858                         UAMP_ERROR(("%s: Unhandled signal on brcm event socket\n", __FUNCTION__));
859                         break;
860                 }
861
862                 /* Stop processing. */
863                 if (FD_ISSET(uamp->evt_fd_pipe[0], &rfds)) {
864                         UAMP_PRINT(("%s: stop rcvd on dispatcher pipe\n", __FUNCTION__));
865                         break;
866                 }
867
868                 /* Event processing. */
869                 if (FD_ISSET(uamp->evt_fd, &rfds)) {
870                         handle_event(uamp);
871                 }
872
873         }  /* end-while(1) */
874
875         UAMP_PRINT(("%s: End event wait loop\n", __FUNCTION__));
876
877         close(uamp->evt_fd);
878         close(uamp->evt_fd_pipe[0]);
879
880         UAMP_TRACE(("Exit %s\n", __FUNCTION__));
881         return (NULL);
882 }
883
884
885 /*
886  * Process received event.
887  */
888 static void
889 handle_event(UAMP_STATE *uamp)
890 {
891         int                     bytes;
892         bcm_event_t             *bcm_event;
893         wl_event_msg_t          *wl_event;
894         uint8                   *wl_evt_data;
895         uint32                  datalen;
896
897         /* Read event. */
898         bytes = recv(uamp->evt_fd, uamp->event_data, sizeof(uamp->event_data), MSG_DONTWAIT);
899
900         /* Error handling. */
901         if (bytes < 0) {
902                 if (errno != EINTR && errno != EAGAIN) {
903                         UAMP_ERROR(("%s: Error reading event socket: %s\n",
904                                     __FUNCTION__, strerror(errno)));
905                         return;
906                 }
907         }
908
909         if (bytes == 0) {
910                 UAMP_ERROR(("%s: EOF on event socket", __FUNCTION__));
911                 return;
912         }
913
914
915         /* We're only interested in HCI events. */
916         bcm_event = (bcm_event_t *)uamp->event_data;
917         if (ntoh32(bcm_event->event.event_type) != WLC_E_BTA_HCI_EVENT) {
918                 return;
919         }
920
921         UAMP_TRACE(("%s: received event!\n", __FUNCTION__));
922
923
924         wl_event = &bcm_event->event;
925         wl_evt_data = (uint8 *)&wl_event[1];
926         datalen = ntoh32(wl_event->datalen);
927
928 #if (BRCM_BLUETOOTH_HOST == 1)
929         hcisu_handle_amp_evt_buf(wl_evt_data, datalen);
930 #else
931         {
932                 tUAMP_EVT_DATA          uamp_evt_data;
933
934 #if (UAMP_DEBUG == 1)
935                 /* Debug - dump event data. */
936                 {
937                         unsigned int i;
938                         UAMP_TRACE(("data(%d): ", datalen));
939                         for (i = 0; i < datalen; i++)
940                         {
941                                 UAMP_TRACE(("0x%x ", wl_evt_data[i]));
942                         }
943                         UAMP_TRACE(("\n"));
944                 }
945 #endif   /* UAMP_DEBUG */
946
947                 /* Post event to queue. Stack will de-queue it with call to UAMP_Read(). */
948                 if (mq_send(uamp->evt_q, (const char *)wl_evt_data, datalen, 0) != 0) {
949                         /* Unable to queue packet */
950                         UAMP_ERROR(("%s: Unable to queue event packet!\n", __FUNCTION__));
951                         return;
952                 }
953
954
955                 /* Inform application stack of received event. */
956                 memset(&uamp_evt_data, 0, sizeof(uamp_evt_data));
957                 uamp_evt_data.channel = UAMP_CH_HCI_EVT;
958                 g_uamp_mgr.callback(0, UAMP_EVT_RX_READY, &uamp_evt_data);
959         }
960 #endif   /* BRCM_BLUETOOTH_HOST */
961
962 }
963
964
965 #define UAMP_TEST 1
966 #if UAMP_TEST
967 int
968 main(int argc, char **argv)
969 {
970         int ret;
971
972         printf("Hello, world!\n");
973
974         if (argc != 2) {
975                 usage();
976                 return (-1);
977         }
978
979         if (strcmp(argv[1], "-a") == 0) {
980                 ret = uamp_accept_test();
981         }
982         else if (strcmp(argv[1], "-c") == 0) {
983                 ret = uamp_create_test();
984         }
985         else {
986                 usage();
987                 return (-1);
988         }
989
990
991         return (ret);
992 }
993
994 /*
995  * Usage display.
996  */
997 static void usage(void)
998 {
999         UAMP_PRINT(("Usage:\n"));
1000         UAMP_PRINT(("\t uamp [-a | -c]\n"));
1001         UAMP_PRINT(("\t\t -a: acceptor\n"));
1002         UAMP_PRINT(("\t\t -c: creator\n"));
1003 }
1004
1005 #define WAIT_FOR_KEY(delay) \
1006         do { \
1007                 usleep(1000*delay); \
1008                 UAMP_PRINT(("Press key to continue\n")); \
1009                 getchar(); \
1010         } \
1011         while (0);
1012
1013
1014 /*
1015  * Application callback for received events and packets.
1016  */
1017 static void uamp_callback(tUAMP_ID amp_id, tUAMP_EVT amp_evt, tUAMP_EVT_DATA *p_amp_evt_data)
1018 {
1019         UINT8                   buf[8192];
1020         amp_hci_ACL_data_t      *data;
1021         amp_hci_event_t         *evt;
1022         unsigned int            i;
1023         UINT16                  num_bytes;
1024
1025         UNUSED_PARAMETER(amp_evt);
1026
1027         num_bytes = UAMP_Read(amp_id, buf, sizeof(buf), p_amp_evt_data->channel);
1028         if (num_bytes != 0) {
1029                 if (p_amp_evt_data->channel == UAMP_CH_HCI_EVT) {
1030                         evt = (amp_hci_event_t *) buf;
1031                         UAMP_PRINT(("%s: evt - ecode(%d) plen(%d)\n",
1032                                     __FUNCTION__, evt->ecode, evt->plen));
1033
1034                         for (i = 0; i < evt->plen; i++) {
1035                                 UAMP_PRINT(("0x%x ", evt->parms[i]));
1036                         }
1037                         UAMP_PRINT(("\n"));
1038                 }
1039                 else if (p_amp_evt_data->channel == UAMP_CH_HCI_DATA) {
1040                         data = (amp_hci_ACL_data_t *) buf;
1041                         UAMP_PRINT(("%s: data - dlen(%d)\n", __FUNCTION__, data->dlen));
1042
1043                         for (i = 0; i < data->dlen; i++) {
1044                                 UAMP_PRINT(("0x%x ", data->data[i]));
1045                         }
1046                         UAMP_PRINT(("\n"));
1047                 }
1048         }
1049         else {
1050                 UAMP_PRINT(("%s: UAMP_Read error\n", __FUNCTION__));
1051         }
1052 }
1053
1054
1055 /* This client is 00:90:4c:c6:02:5b. Remote is 00:90:4c:c5:06:79. */
1056 static int uamp_accept_test(void)
1057 {
1058         uint8 set_event_mask_page_2_data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1059         uint8 read_local_amp_assoc_data[] = {0, 0, 0};
1060         uint8 accept_physical_link_request_data[] = {0x11, 32, 3, 0x00, 0x01, 0x02,
1061                 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
1062                 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
1063                 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
1064         uint8 write_remote_amp_assoc_data[] = {0x11, 0x0, 0x0, 0x24, 0x00, 0x04,
1065                 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x01, 0x0f,
1066                 0x00, 0x10, 0x09, 0x01, 0x06, 0x00, 0x00, 0x90, 0x4c, 0xc5, 0x06,
1067                 0x79, 0x02, 0x09, 0x00, 0x55, 0x53, 0x20, 0xc9, 0x0c, 0x00, 0x01,
1068                 0x01, 0x14};
1069         uint8 accept_logical_link_data[] = {0x11, 0x01, 0x01, 0xff, 0xff, 0xff,
1070                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1071                 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1072                 0xff, 0xff, 0xff, 0xff, 0xff};
1073         uint8 tx_data[] = {7, 6, 5, 4, 3, 2, 1, 0};
1074         uint8 disconnect_logical_link_data[] = {0};
1075         uint8 disconnect_physical_link_data[] = {0x11, 0};
1076
1077         uint32 buf[64];
1078         amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)buf;
1079         amp_hci_ACL_data_t *pkt = (amp_hci_ACL_data_t *)buf;
1080
1081
1082         UAMP_PRINT(("UAMP acceptor test\n"));
1083
1084
1085         UAMP_Init(uamp_callback);
1086         UAMP_Open(0);
1087
1088
1089         /* HCI_Set_Event_Mask_Page_2 */
1090         uamp_write_cmd(HCI_Set_Event_Mask_Page_2, set_event_mask_page_2_data,
1091                        sizeof(set_event_mask_page_2_data), cmd, sizeof(buf));
1092
1093         /* Read_Local_AMP_ASSOC */
1094         uamp_write_cmd(HCI_Read_Local_AMP_ASSOC, read_local_amp_assoc_data,
1095                        sizeof(read_local_amp_assoc_data), cmd, sizeof(buf));
1096         WAIT_FOR_KEY(1000);
1097
1098         /* Accept_Physical_Link_Request */
1099         uamp_write_cmd(HCI_Accept_Physical_Link_Request, accept_physical_link_request_data,
1100                        sizeof(accept_physical_link_request_data), cmd, sizeof(buf));
1101
1102
1103         /* This is specific to info obtained from the remote client. */
1104         /* Write_Remote_AMP_ASSOC */
1105         uamp_write_cmd(HCI_Write_Remote_AMP_ASSOC, write_remote_amp_assoc_data,
1106                        sizeof(write_remote_amp_assoc_data), cmd, sizeof(buf));
1107         WAIT_FOR_KEY(1000);
1108
1109         /* Accept_Logical_Link */
1110         uamp_write_cmd(HCI_Accept_Logical_Link, accept_logical_link_data,
1111                        sizeof(accept_logical_link_data), cmd, sizeof(buf));
1112         WAIT_FOR_KEY(1000);
1113
1114         /* HCI_ACL_data */
1115         uamp_write_data(0 | HCI_ACL_DATA_BC_FLAGS | HCI_ACL_DATA_PB_FLAGS, tx_data,
1116                         sizeof(tx_data), pkt, sizeof(buf));
1117         WAIT_FOR_KEY(1000);
1118
1119         /* Disconnect_Logical_Link */
1120         uamp_write_cmd(HCI_Disconnect_Logical_Link, disconnect_logical_link_data,
1121                        sizeof(disconnect_logical_link_data), cmd, sizeof(buf));
1122
1123         /* Disconnect_Physical_Link */
1124         uamp_write_cmd(HCI_Disconnect_Physical_Link, disconnect_physical_link_data,
1125                        sizeof(disconnect_physical_link_data), cmd, sizeof(buf));
1126
1127         usleep(1000*1000);
1128         UAMP_Close(0);
1129         usleep(1000*1000);
1130         UAMP_PRINT(("UAMP acceptor test done!\n"));
1131
1132         return (0);
1133 }
1134
1135
1136 /* This client is 00:90:4c:c5:06:79. Remote is 00:90:4c:c6:02:5b. */
1137 static int uamp_create_test(void)
1138 {
1139         uint8 set_event_mask_page_2_data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1140         uint8 create_physical_link_data[] = {0x10, 32, 3, 0x00, 0x01, 0x02, 0x03,
1141                 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
1142                 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
1143                 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
1144         uint8 write_remote_amp_assoc_data[] = {0x10, 0x0, 0x0, 0x21, 0x00, 0x04,
1145                 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x01, 0x0f,
1146                 0x00, 0x10, 0x09, 0x01, 0x06, 0x00, 0x00, 0x90, 0x4c, 0xc6, 0x02,
1147                 0x5b, 0x02, 0x06, 0x00, 0x55, 0x53, 0x20, 0xc9, 0x0c, 0x00};
1148         uint8 read_local_amp_assoc_data[] = {0x10, 0, 0, 100, 0};
1149         uint8 create_logical_link_data[] = {0x10, 0x01, 0x01, 0xff, 0xff, 0xff,
1150                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1151                 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1152                 0xff, 0xff, 0xff, 0xff, 0xff};
1153         uint8 disconnect_logical_link_data[] = {0};
1154         uint8 disconnect_physical_link_data[] = {0x10, 0};
1155         uint8 tx_data[] = {0, 1, 2, 3, 4, 5, 6, 7};
1156
1157         uint32 buf[64];
1158         amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)buf;
1159         amp_hci_ACL_data_t *pkt = (amp_hci_ACL_data_t *)buf;
1160
1161         UAMP_PRINT(("UAMP creator test\n"));
1162
1163
1164         UAMP_Init(uamp_callback);
1165
1166         UAMP_Open(0);
1167
1168         /* HCI_Set_Event_Mask_Page_2 */
1169         uamp_write_cmd(HCI_Set_Event_Mask_Page_2, set_event_mask_page_2_data,
1170                        sizeof(set_event_mask_page_2_data), cmd, sizeof(buf));
1171
1172         /* Read_Local_AMP_Info */
1173         uamp_write_cmd(HCI_Read_Local_AMP_Info, NULL, 0, cmd, sizeof(buf));
1174         WAIT_FOR_KEY(1000);
1175
1176         /* Create_Physical_Link */
1177         uamp_write_cmd(HCI_Create_Physical_Link, create_physical_link_data,
1178                        sizeof(create_physical_link_data), cmd, sizeof(buf));
1179
1180         /* This is specific to info obtained from the remote client. */
1181         /* Write_Remote_AMP_ASSOC */
1182         uamp_write_cmd(HCI_Write_Remote_AMP_ASSOC, write_remote_amp_assoc_data,
1183                        sizeof(write_remote_amp_assoc_data), cmd, sizeof(buf));
1184
1185
1186         /* Spin for a bit. */
1187         usleep(1000*1000);
1188
1189
1190         /* Read_Local_AMP_ASSOC */
1191         uamp_write_cmd(HCI_Read_Local_AMP_ASSOC, read_local_amp_assoc_data,
1192                        sizeof(read_local_amp_assoc_data), cmd, sizeof(buf));
1193         WAIT_FOR_KEY(1000);
1194
1195         /* Create_Logical_Link */
1196         uamp_write_cmd(HCI_Create_Logical_Link, create_logical_link_data,
1197                        sizeof(create_logical_link_data), cmd, sizeof(buf));
1198         WAIT_FOR_KEY(1000);
1199
1200         /* HCI_ACL_data */
1201         uamp_write_data(0 | HCI_ACL_DATA_BC_FLAGS | HCI_ACL_DATA_PB_FLAGS, tx_data,
1202                         sizeof(tx_data), pkt, sizeof(buf));
1203         WAIT_FOR_KEY(1000);
1204
1205         /* Disconnect_Logical_Link */
1206         uamp_write_cmd(HCI_Disconnect_Logical_Link, disconnect_logical_link_data,
1207                        sizeof(disconnect_logical_link_data), cmd, sizeof(buf));
1208
1209         /* Disconnect_Physical_Link */
1210         uamp_write_cmd(HCI_Disconnect_Physical_Link, disconnect_physical_link_data,
1211                        sizeof(disconnect_physical_link_data), cmd, sizeof(buf));
1212
1213         usleep(1000*1000);
1214         UAMP_Close(0);
1215         usleep(1000*1000);
1216         UAMP_PRINT(("UAMP creator test done!\n"));
1217
1218         return (0);
1219 }
1220
1221
1222 /*
1223  * Send UAMP command.
1224  */
1225 static UINT16 uamp_write_cmd(uint16 opcode, uint8 *params, uint8 len,
1226                              amp_hci_cmd_t *cmd, unsigned int max_len)
1227 {
1228         memset(cmd, 0, sizeof(amp_hci_cmd_t));
1229         cmd->plen = len;
1230         cmd->opcode = opcode;
1231         assert(HCI_CMD_PREAMBLE_SIZE + len <= max_len);
1232
1233         if (len != 0) {
1234                 memcpy(cmd->parms, params, len);
1235         }
1236
1237         return (UAMP_Write(0, (UINT8 *)cmd, HCI_CMD_PREAMBLE_SIZE + len, UAMP_CH_HCI_CMD));
1238 }
1239
1240
1241 /*
1242  * Send UAMP data.
1243  */
1244 static UINT16 uamp_write_data(uint16 handle, uint8 *data, uint8 len,
1245                               amp_hci_ACL_data_t *pkt, unsigned int max_len)
1246 {
1247         memset(pkt, 0, sizeof(amp_hci_ACL_data_t));
1248         pkt->handle = handle;
1249         pkt->dlen = len;
1250         assert(HCI_ACL_DATA_PREAMBLE_SIZE + len <= max_len);
1251
1252         if (len != 0) {
1253                 memcpy(pkt->data, data, len);
1254         }
1255
1256         return (UAMP_Write(0, (UINT8 *)pkt, HCI_ACL_DATA_PREAMBLE_SIZE + len, UAMP_CH_HCI_DATA));
1257 }
1258 #endif   /* UAMP_TEST */