📄 zd1201.c
字号:
/* Skip the 4 bytes header (RID length and RID) */ if(i == 0) { pdata += 8; actual_length -= 8; } else { pdata += 4; actual_length -= 4; } memcpy(riddata, pdata, actual_length); riddata += actual_length; pdata += actual_length; length -= 64; i++; } while (length > 0); return 0;}/* * resreq: * byte type * byte sequence * u16 reserved * byte data[12] * total: 16 */static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait){ int err; unsigned char *request; int reqlen; char seq=0; struct urb *urb; unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; len += 4; /* first 4 are for header */ zd->rxdatas = 0; zd->rxlen = 0; for (seq=0; len > 0; seq++) { request = kmalloc(16, gfp_mask); if (!request) return -ENOMEM; urb = usb_alloc_urb(0, gfp_mask); if (!urb) { kfree(request); return -ENOMEM; } memset(request, 0, 16); reqlen = len>12 ? 12 : len; request[0] = ZD1201_USB_RESREQ; request[1] = seq; request[2] = 0; request[3] = 0; if (request[1] == 0) { /* add header */ *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); *(__le16*)&request[6] = cpu_to_le16(rid); memcpy(request+8, buf, reqlen-4); buf += reqlen-4; } else { memcpy(request+4, buf, reqlen); buf += reqlen; } len -= reqlen; usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), request, 16, zd1201_usbfree, zd); err = usb_submit_urb(urb, gfp_mask); if (err) goto err; } request = kmalloc(16, gfp_mask); if (!request) return -ENOMEM; urb = usb_alloc_urb(0, gfp_mask); if (!urb) { kfree(request); return -ENOMEM; } *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); *((__le16*)&request[4]) = cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); *((__le16*)&request[6]) = cpu_to_le16(rid); *((__le16*)&request[8]) = cpu_to_le16(0); *((__le16*)&request[10]) = cpu_to_le16(0); usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), request, 16, zd1201_usbfree, zd); err = usb_submit_urb(urb, gfp_mask); if (err) goto err; if (wait) { wait_event_interruptible(zd->rxdataq, zd->rxdatas); if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); } } return 0;err: kfree(request); usb_free_urb(urb); return err;}static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val){ int err; __le16 zdval; err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); if (err) return err; *val = le16_to_cpu(zdval); return 0;}static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val){ __le16 zdval = cpu_to_le16(val); return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));}static int zd1201_drvr_start(struct zd1201 *zd){ int err, i; short max; __le16 zdmax; unsigned char *buffer; buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL); if (!buffer) return -ENOMEM; memset(buffer, 0, ZD1201_RXSIZE); usb_fill_bulk_urb(zd->rx_urb, zd->usb, usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, zd1201_usbrx, zd); err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); if (err) goto err_buffer; err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); if (err) goto err_urb; err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, sizeof(__le16)); if (err) goto err_urb; max = le16_to_cpu(zdmax); for (i=0; i<max; i++) { err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0); if (err) goto err_urb; } return 0;err_urb: usb_kill_urb(zd->rx_urb); return err;err_buffer: kfree(buffer); return err;}/* Magic alert: The firmware doesn't seem to like the MAC state being * toggled in promisc (aka monitor) mode. * (It works a number of times, but will halt eventually) * So we turn it of before disabling and on after enabling if needed. */static int zd1201_enable(struct zd1201 *zd){ int err; if (zd->mac_enabled) return 0; err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); if (!err) zd->mac_enabled = 1; if (zd->monitor) err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); return err;}static int zd1201_disable(struct zd1201 *zd){ int err; if (!zd->mac_enabled) return 0; if (zd->monitor) { err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); if (err) return err; } err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); if (!err) zd->mac_enabled = 0; return err;}static int zd1201_mac_reset(struct zd1201 *zd){ if (!zd->mac_enabled) return 0; zd1201_disable(zd); return zd1201_enable(zd);}static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen){ int err, val; char buf[IW_ESSID_MAX_SIZE+2]; err = zd1201_disable(zd); if (err) return err; val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); if (err) return err; *(__le16 *)buf = cpu_to_le16(essidlen); memcpy(buf+2, essid, essidlen); if (!zd->ap) { /* Normal station */ err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, IW_ESSID_MAX_SIZE+2, 1); if (err) return err; } else { /* AP */ err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, IW_ESSID_MAX_SIZE+2, 1); if (err) return err; } err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, zd->dev->dev_addr, zd->dev->addr_len, 1); if (err) return err; err = zd1201_enable(zd); if (err) return err; msleep(100); return 0;}static int zd1201_net_open(struct net_device *dev){ struct zd1201 *zd = (struct zd1201 *)dev->priv; /* Start MAC with wildcard if no essid set */ if (!zd->mac_enabled) zd1201_join(zd, zd->essid, zd->essidlen); netif_start_queue(dev); return 0;}static int zd1201_net_stop(struct net_device *dev){ netif_stop_queue(dev); return 0;}/* RFC 1042 encapsulates Ethernet frames in 802.11 frames by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 (0x00, 0x00, 0x00). Zd requires an additional padding, copy of ethernet addresses, length of the standard RFC 1042 packet and a command byte (which is nul for tx). tx frame (from Wlan NG): RFC 1042: llc 0xAA 0xAA 0x03 (802.2 LLC) snap 0x00 0x00 0x00 (Ethernet encapsulated) type 2 bytes, Ethernet type field payload (minus eth header) Zydas specific: padding 1B if (skb->len+8+1)%64==0 Eth MAC addr 12 bytes, Ethernet MAC addresses length 2 bytes, RFC 1042 packet length (llc+snap+type+payload) zd 1 null byte, zd1201 packet type */static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev){ struct zd1201 *zd = (struct zd1201 *)dev->priv; unsigned char *txbuf = zd->txdata; int txbuflen, pad = 0, err; struct urb *urb = zd->tx_urb; if (!zd->mac_enabled || zd->monitor) { zd->stats.tx_dropped++; kfree_skb(skb); return 0; } netif_stop_queue(dev); txbuflen = skb->len + 8 + 1; if (txbuflen%64 == 0) { pad = 1; txbuflen++; } txbuf[0] = 0xAA; txbuf[1] = 0xAA; txbuf[2] = 0x03; txbuf[3] = 0x00; /* rfc1042 */ txbuf[4] = 0x00; txbuf[5] = 0x00; memcpy(txbuf+6, skb->data+12, skb->len-12); if (pad) txbuf[skb->len-12+6]=0; memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); txbuf[txbuflen-1] = 0; usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), txbuf, txbuflen, zd1201_usbtx, zd); err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); if (err) { zd->stats.tx_errors++; netif_start_queue(dev); return err; } zd->stats.tx_packets++; zd->stats.tx_bytes += skb->len; dev->trans_start = jiffies; kfree_skb(skb); return 0;}static void zd1201_tx_timeout(struct net_device *dev){ struct zd1201 *zd = (struct zd1201 *)dev->priv; if (!zd) return; dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", dev->name); usb_unlink_urb(zd->tx_urb); zd->stats.tx_errors++; /* Restart the timeout to quiet the watchdog: */ dev->trans_start = jiffies;}static int zd1201_set_mac_address(struct net_device *dev, void *p){ struct sockaddr *addr = p; struct zd1201 *zd = (struct zd1201 *)dev->priv; int err; if (!zd) return -ENODEV; err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, addr->sa_data, dev->addr_len, 1); if (err) return err; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); return zd1201_mac_reset(zd);}static struct net_device_stats *zd1201_get_stats(struct net_device *dev){ struct zd1201 *zd = (struct zd1201 *)dev->priv; return &zd->stats;}static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev){ struct zd1201 *zd = (struct zd1201 *)dev->priv; return &zd->iwstats;}static void zd1201_set_multicast(struct net_device *dev){ struct zd1201 *zd = (struct zd1201 *)dev->priv; struct dev_mc_list *mc = dev->mc_list; unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; int i; if (dev->mc_count > ZD1201_MAXMULTI) return; for (i=0; i<dev->mc_count; i++) { memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); mc = mc->next; } zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, dev->mc_count*ETH_ALEN, 0); }static int zd1201_config_commit(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid){ struct zd1201 *zd = (struct zd1201 *)dev->priv; return zd1201_mac_reset(zd);}static int zd1201_get_name(struct net_device *dev, struct iw_request_info *info, char *name, char *extra){ strcpy(name, "IEEE 802.11b"); return 0;}static int zd1201_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short channel = 0; int err; if (freq->e == 0) channel = freq->m; else { if (freq->m >= 2482) channel = 14; if (freq->m >= 2407) channel = (freq->m-2407)/5; } err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); if (err) return err; zd1201_mac_reset(zd); return 0;}static int zd1201_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short channel; int err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); if (err) return err; freq->e = 0; freq->m = channel; return 0;}static int zd1201_set_mode(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short porttype, monitor = 0; unsigned char buffer[IW_ESSID_MAX_SIZE+2]; int err; if (zd->ap) { if (*mode != IW_MODE_MASTER) return -EINVAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -