Deleted Added
full compact
if_urtw.c (243857) if_urtw.c (244503)
1/*-
2 * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/cdefs.h>
18__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_urtw.c 243857 2012-12-04 09:32:43Z glebius $");
18__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_urtw.c 244503 2012-12-20 18:38:02Z hselasky $");
19#include <sys/param.h>
20#include <sys/sockio.h>
21#include <sys/sysctl.h>
22#include <sys/lock.h>
23#include <sys/mutex.h>
24#include <sys/mbuf.h>
25#include <sys/kernel.h>
26#include <sys/socket.h>

--- 500 unchanged lines hidden (view full) ---

527 .short_xfer_ok = 1
528 },
529 .callback = urtw_bulk_rx_callback
530 },
531 [URTW_8187B_BULK_TX_STATUS] = {
532 .type = UE_BULK,
533 .endpoint = 0x89,
534 .direction = UE_DIR_IN,
19#include <sys/param.h>
20#include <sys/sockio.h>
21#include <sys/sysctl.h>
22#include <sys/lock.h>
23#include <sys/mutex.h>
24#include <sys/mbuf.h>
25#include <sys/kernel.h>
26#include <sys/socket.h>

--- 500 unchanged lines hidden (view full) ---

527 .short_xfer_ok = 1
528 },
529 .callback = urtw_bulk_rx_callback
530 },
531 [URTW_8187B_BULK_TX_STATUS] = {
532 .type = UE_BULK,
533 .endpoint = 0x89,
534 .direction = UE_DIR_IN,
535 .bufsize = MCLBYTES,
535 .bufsize = sizeof(uint64_t),
536 .flags = {
536 .flags = {
537 .ext_buffer = 1,
538 .pipe_bof = 1,
539 .short_xfer_ok = 1
540 },
541 .callback = urtw_bulk_tx_status_callback
542 },
543 [URTW_8187B_BULK_TX_BE] = {
544 .type = UE_BULK,
545 .endpoint = URTW_8187B_TXPIPE_BE,
546 .direction = UE_DIR_OUT,
537 .pipe_bof = 1,
538 .short_xfer_ok = 1
539 },
540 .callback = urtw_bulk_tx_status_callback
541 },
542 [URTW_8187B_BULK_TX_BE] = {
543 .type = UE_BULK,
544 .endpoint = URTW_8187B_TXPIPE_BE,
545 .direction = UE_DIR_OUT,
547 .bufsize = URTW_TX_MAXSIZE,
546 .bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
548 .flags = {
547 .flags = {
549 .ext_buffer = 1,
550 .force_short_xfer = 1,
551 .pipe_bof = 1,
552 },
553 .callback = urtw_bulk_tx_callback,
554 .timeout = URTW_DATA_TIMEOUT
555 },
556 [URTW_8187B_BULK_TX_BK] = {
557 .type = UE_BULK,

--- 61 unchanged lines hidden (view full) ---

619 .short_xfer_ok = 1
620 },
621 .callback = urtw_bulk_rx_callback
622 },
623 [URTW_8187L_BULK_TX_LOW] = {
624 .type = UE_BULK,
625 .endpoint = 0x2,
626 .direction = UE_DIR_OUT,
548 .force_short_xfer = 1,
549 .pipe_bof = 1,
550 },
551 .callback = urtw_bulk_tx_callback,
552 .timeout = URTW_DATA_TIMEOUT
553 },
554 [URTW_8187B_BULK_TX_BK] = {
555 .type = UE_BULK,

--- 61 unchanged lines hidden (view full) ---

617 .short_xfer_ok = 1
618 },
619 .callback = urtw_bulk_rx_callback
620 },
621 [URTW_8187L_BULK_TX_LOW] = {
622 .type = UE_BULK,
623 .endpoint = 0x2,
624 .direction = UE_DIR_OUT,
627 .bufsize = URTW_TX_MAXSIZE,
625 .bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
628 .flags = {
626 .flags = {
629 .ext_buffer = 1,
630 .force_short_xfer = 1,
631 .pipe_bof = 1,
632 },
633 .callback = urtw_bulk_tx_callback,
634 .timeout = URTW_DATA_TIMEOUT
635 },
636 [URTW_8187L_BULK_TX_NORMAL] = {
637 .type = UE_BULK,

--- 184 unchanged lines hidden (view full) ---

822 setup_start, n_setup, sc, &sc->sc_mtx);
823 if (error) {
824 device_printf(dev, "could not allocate USB transfers, "
825 "err=%s\n", usbd_errstr(error));
826 ret = ENXIO;
827 goto fail0;
828 }
829
627 .force_short_xfer = 1,
628 .pipe_bof = 1,
629 },
630 .callback = urtw_bulk_tx_callback,
631 .timeout = URTW_DATA_TIMEOUT
632 },
633 [URTW_8187L_BULK_TX_NORMAL] = {
634 .type = UE_BULK,

--- 184 unchanged lines hidden (view full) ---

819 setup_start, n_setup, sc, &sc->sc_mtx);
820 if (error) {
821 device_printf(dev, "could not allocate USB transfers, "
822 "err=%s\n", usbd_errstr(error));
823 ret = ENXIO;
824 goto fail0;
825 }
826
827 if (sc->sc_flags & URTW_RTL8187B) {
828 sc->sc_tx_dma_buf =
829 usbd_xfer_get_frame_buffer(sc->sc_xfer[
830 URTW_8187B_BULK_TX_BE], 0);
831 } else {
832 sc->sc_tx_dma_buf =
833 usbd_xfer_get_frame_buffer(sc->sc_xfer[
834 URTW_8187L_BULK_TX_LOW], 0);
835 }
836
830 URTW_LOCK(sc);
831
832 urtw_read32_m(sc, URTW_RX, &data);
833 sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 :
834 URTW_EEPROM_93C46;
835
836 error = urtw_get_rfchip(sc);
837 if (error != 0)

--- 94 unchanged lines hidden (view full) ---

932
933 urtw_stop(ifp, 1);
934 ieee80211_draintask(ic, &sc->sc_updateslot_task);
935 ieee80211_draintask(ic, &sc->sc_led_task);
936
937 usb_callout_drain(&sc->sc_led_ch);
938 callout_drain(&sc->sc_watchdog_ch);
939
837 URTW_LOCK(sc);
838
839 urtw_read32_m(sc, URTW_RX, &data);
840 sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 :
841 URTW_EEPROM_93C46;
842
843 error = urtw_get_rfchip(sc);
844 if (error != 0)

--- 94 unchanged lines hidden (view full) ---

939
940 urtw_stop(ifp, 1);
941 ieee80211_draintask(ic, &sc->sc_updateslot_task);
942 ieee80211_draintask(ic, &sc->sc_led_task);
943
944 usb_callout_drain(&sc->sc_led_ch);
945 callout_drain(&sc->sc_watchdog_ch);
946
947 ieee80211_ifdetach(ic);
948
940 usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
941 URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
949 usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
950 URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
942 ieee80211_ifdetach(ic);
943
944 urtw_free_tx_data_list(sc);
945 urtw_free_rx_data_list(sc);
946
947 if_free(ifp);
948 mtx_destroy(&sc->sc_mtx);
949
950 return (0);

--- 24 unchanged lines hidden (view full) ---

975
976 if (fillmbuf == 1) {
977 if (dp->m != NULL) {
978 m_freem(dp->m);
979 dp->m = NULL;
980 dp->buf = NULL;
981 }
982 } else {
951
952 urtw_free_tx_data_list(sc);
953 urtw_free_rx_data_list(sc);
954
955 if_free(ifp);
956 mtx_destroy(&sc->sc_mtx);
957
958 return (0);

--- 24 unchanged lines hidden (view full) ---

983
984 if (fillmbuf == 1) {
985 if (dp->m != NULL) {
986 m_freem(dp->m);
987 dp->m = NULL;
988 dp->buf = NULL;
989 }
990 } else {
983 if (dp->buf != NULL) {
984 free(dp->buf, M_USBDEV);
985 dp->buf = NULL;
986 }
991 dp->buf = NULL;
987 }
988 if (dp->ni != NULL) {
989 ieee80211_free_node(dp->ni);
990 dp->ni = NULL;
991 }
992 }
993}
994

--- 449 unchanged lines hidden (view full) ---

1444 sc->sc_txtimer = 5;
1445 callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
1446 }
1447 URTW_UNLOCK(sc);
1448}
1449
1450static int
1451urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
992 }
993 if (dp->ni != NULL) {
994 ieee80211_free_node(dp->ni);
995 dp->ni = NULL;
996 }
997 }
998}
999

--- 449 unchanged lines hidden (view full) ---

1449 sc->sc_txtimer = 5;
1450 callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
1451 }
1452 URTW_UNLOCK(sc);
1453}
1454
1455static int
1456urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
1452 int ndata, int maxsz, int fillmbuf)
1457 int ndata, int maxsz, void *dma_buf)
1453{
1454 int i, error;
1455
1456 for (i = 0; i < ndata; i++) {
1457 struct urtw_data *dp = &data[i];
1458
1459 dp->sc = sc;
1458{
1459 int i, error;
1460
1461 for (i = 0; i < ndata; i++) {
1462 struct urtw_data *dp = &data[i];
1463
1464 dp->sc = sc;
1460 if (fillmbuf) {
1465 if (dma_buf == NULL) {
1461 dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1462 if (dp->m == NULL) {
1463 device_printf(sc->sc_dev,
1464 "could not allocate rx mbuf\n");
1465 error = ENOMEM;
1466 goto fail;
1467 }
1468 dp->buf = mtod(dp->m, uint8_t *);
1469 } else {
1470 dp->m = NULL;
1466 dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1467 if (dp->m == NULL) {
1468 device_printf(sc->sc_dev,
1469 "could not allocate rx mbuf\n");
1470 error = ENOMEM;
1471 goto fail;
1472 }
1473 dp->buf = mtod(dp->m, uint8_t *);
1474 } else {
1475 dp->m = NULL;
1471 dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
1472 if (dp->buf == NULL) {
1473 device_printf(sc->sc_dev,
1474 "could not allocate buffer\n");
1475 error = ENOMEM;
1476 goto fail;
1477 }
1478 if (((unsigned long)dp->buf) % 4)
1479 device_printf(sc->sc_dev,
1480 "warn: unaligned buffer %p\n", dp->buf);
1476 dp->buf = ((uint8_t *)dma_buf) +
1477 (i * maxsz);
1481 }
1482 dp->ni = NULL;
1483 }
1478 }
1479 dp->ni = NULL;
1480 }
1481 return (0);
1484
1482
1485 return 0;
1486
1487fail: urtw_free_data_list(sc, data, ndata, fillmbuf);
1488 return error;
1483fail: urtw_free_data_list(sc, data, ndata, 1);
1484 return (error);
1489}
1490
1491static int
1492urtw_alloc_rx_data_list(struct urtw_softc *sc)
1493{
1494 int error, i;
1495
1496 error = urtw_alloc_data_list(sc,
1485}
1486
1487static int
1488urtw_alloc_rx_data_list(struct urtw_softc *sc)
1489{
1490 int error, i;
1491
1492 error = urtw_alloc_data_list(sc,
1497 sc->sc_rx, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */);
1493 sc->sc_rx, URTW_RX_DATA_LIST_COUNT,
1494 MCLBYTES, NULL /* mbufs */);
1498 if (error != 0)
1499 return (error);
1500
1501 STAILQ_INIT(&sc->sc_rx_active);
1502 STAILQ_INIT(&sc->sc_rx_inactive);
1503
1504 for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++)
1505 STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next);
1506
1507 return (0);
1508}
1509
1510static int
1511urtw_alloc_tx_data_list(struct urtw_softc *sc)
1512{
1513 int error, i;
1514
1515 error = urtw_alloc_data_list(sc,
1516 sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE,
1495 if (error != 0)
1496 return (error);
1497
1498 STAILQ_INIT(&sc->sc_rx_active);
1499 STAILQ_INIT(&sc->sc_rx_inactive);
1500
1501 for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++)
1502 STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next);
1503
1504 return (0);
1505}
1506
1507static int
1508urtw_alloc_tx_data_list(struct urtw_softc *sc)
1509{
1510 int error, i;
1511
1512 error = urtw_alloc_data_list(sc,
1513 sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE,
1517 0 /* no mbufs */);
1514 sc->sc_tx_dma_buf /* no mbufs */);
1518 if (error != 0)
1519 return (error);
1520
1521 STAILQ_INIT(&sc->sc_tx_active);
1522 STAILQ_INIT(&sc->sc_tx_inactive);
1523 STAILQ_INIT(&sc->sc_tx_pending);
1524
1525 for (i = 0; i < URTW_TX_DATA_LIST_COUNT; i++)

--- 1178 unchanged lines hidden (view full) ---

2704 DELAY(10);
2705 urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN);
2706 urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84);
2707 usb_pause_mtx(&sc->sc_mtx, 2);
2708fail:
2709 return (error);
2710}
2711
1515 if (error != 0)
1516 return (error);
1517
1518 STAILQ_INIT(&sc->sc_tx_active);
1519 STAILQ_INIT(&sc->sc_tx_inactive);
1520 STAILQ_INIT(&sc->sc_tx_pending);
1521
1522 for (i = 0; i < URTW_TX_DATA_LIST_COUNT; i++)

--- 1178 unchanged lines hidden (view full) ---

2701 DELAY(10);
2702 urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN);
2703 urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84);
2704 usb_pause_mtx(&sc->sc_mtx, 2);
2705fail:
2706 return (error);
2707}
2708
2712/* XXX why we should allocalte memory buffer instead of using memory stack? */
2713static usb_error_t
2714urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
2715 uint16_t *data)
2716{
2709static usb_error_t
2710urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
2711 uint16_t *data)
2712{
2717 uint8_t *buf;
2713 uint8_t buf[2];
2718 uint16_t data16;
2714 uint16_t data16;
2719 struct usb_device_request *req;
2715 struct usb_device_request req;
2720 usb_error_t error = 0;
2721
2722 data16 = *data;
2716 usb_error_t error = 0;
2717
2718 data16 = *data;
2723 req = (usb_device_request_t *)malloc(sizeof(usb_device_request_t),
2724 M_80211_VAP, M_NOWAIT | M_ZERO);
2725 if (req == NULL) {
2726 device_printf(sc->sc_dev, "could not allocate a memory\n");
2727 goto fail0;
2728 }
2729 buf = (uint8_t *)malloc(2, M_80211_VAP, M_NOWAIT | M_ZERO);
2730 if (req == NULL) {
2731 device_printf(sc->sc_dev, "could not allocate a memory\n");
2732 goto fail1;
2733 }
2734
2719
2735 req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
2736 req->bRequest = URTW_8187_SETREGS_REQ;
2737 USETW(req->wValue, addr);
2738 USETW(req->wIndex, index);
2739 USETW(req->wLength, sizeof(uint16_t));
2720 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
2721 req.bRequest = URTW_8187_SETREGS_REQ;
2722 USETW(req.wValue, addr);
2723 USETW(req.wIndex, index);
2724 USETW(req.wLength, sizeof(uint16_t));
2740 buf[0] = (data16 & 0x00ff);
2741 buf[1] = (data16 & 0xff00) >> 8;
2742
2725 buf[0] = (data16 & 0x00ff);
2726 buf[1] = (data16 & 0xff00) >> 8;
2727
2743 error = urtw_do_request(sc, req, buf);
2728 error = urtw_do_request(sc, &req, buf);
2744
2729
2745 free(buf, M_80211_VAP);
2746fail1: free(req, M_80211_VAP);
2747fail0: return (error);
2730 return (error);
2748}
2749
2750static usb_error_t
2751urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
2752{
2753 usb_error_t error;
2754
2755 error = urtw_8225_set_txpwrlvl(sc, chan);

--- 1372 unchanged lines hidden (view full) ---

4128 }
4129}
4130
4131static void
4132urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
4133{
4134 struct urtw_softc *sc = usbd_xfer_softc(xfer);
4135 struct ifnet *ifp = sc->sc_ifp;
2731}
2732
2733static usb_error_t
2734urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
2735{
2736 usb_error_t error;
2737
2738 error = urtw_8225_set_txpwrlvl(sc, chan);

--- 1372 unchanged lines hidden (view full) ---

4111 }
4112}
4113
4114static void
4115urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
4116{
4117 struct urtw_softc *sc = usbd_xfer_softc(xfer);
4118 struct ifnet *ifp = sc->sc_ifp;
4119 void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
4136
4137 URTW_ASSERT_LOCKED(sc);
4138
4139 switch (USB_GET_STATE(xfer)) {
4140 case USB_ST_TRANSFERRED:
4141 urtw_txstatus_eof(xfer);
4142 /* FALLTHROUGH */
4143 case USB_ST_SETUP:
4144setup:
4120
4121 URTW_ASSERT_LOCKED(sc);
4122
4123 switch (USB_GET_STATE(xfer)) {
4124 case USB_ST_TRANSFERRED:
4125 urtw_txstatus_eof(xfer);
4126 /* FALLTHROUGH */
4127 case USB_ST_SETUP:
4128setup:
4145 usbd_xfer_set_frame_data(xfer, 0, &sc->sc_txstatus,
4146 sizeof(int64_t));
4129 memcpy(dma_buf, &sc->sc_txstatus, sizeof(uint64_t));
4147 usbd_transfer_submit(xfer);
4148 break;
4149 default:
4150 if (error != USB_ERR_CANCELLED) {
4151 usbd_xfer_set_stall(xfer);
4152 ifp->if_ierrors++;
4153 goto setup;
4154 }

--- 271 unchanged lines hidden (view full) ---

4426 "54 Mbit/s");
4427#undef URTW_SYSCTL_STAT_ADD32
4428}
4429
4430static device_method_t urtw_methods[] = {
4431 DEVMETHOD(device_probe, urtw_match),
4432 DEVMETHOD(device_attach, urtw_attach),
4433 DEVMETHOD(device_detach, urtw_detach),
4130 usbd_transfer_submit(xfer);
4131 break;
4132 default:
4133 if (error != USB_ERR_CANCELLED) {
4134 usbd_xfer_set_stall(xfer);
4135 ifp->if_ierrors++;
4136 goto setup;
4137 }

--- 271 unchanged lines hidden (view full) ---

4409 "54 Mbit/s");
4410#undef URTW_SYSCTL_STAT_ADD32
4411}
4412
4413static device_method_t urtw_methods[] = {
4414 DEVMETHOD(device_probe, urtw_match),
4415 DEVMETHOD(device_attach, urtw_attach),
4416 DEVMETHOD(device_detach, urtw_detach),
4434 { 0, 0 }
4417 DEVMETHOD_END
4435};
4436static driver_t urtw_driver = {
4437 .name = "urtw",
4438 .methods = urtw_methods,
4439 .size = sizeof(struct urtw_softc)
4440};
4441static devclass_t urtw_devclass;
4442
4443DRIVER_MODULE(urtw, uhub, urtw_driver, urtw_devclass, NULL, 0);
4444MODULE_DEPEND(urtw, wlan, 1, 1, 1);
4445MODULE_DEPEND(urtw, usb, 1, 1, 1);
4446MODULE_VERSION(urtw, 1);
4418};
4419static driver_t urtw_driver = {
4420 .name = "urtw",
4421 .methods = urtw_methods,
4422 .size = sizeof(struct urtw_softc)
4423};
4424static devclass_t urtw_devclass;
4425
4426DRIVER_MODULE(urtw, uhub, urtw_driver, urtw_devclass, NULL, 0);
4427MODULE_DEPEND(urtw, wlan, 1, 1, 1);
4428MODULE_DEPEND(urtw, usb, 1, 1, 1);
4429MODULE_VERSION(urtw, 1);