📄 at76c503.c
字号:
#define KEVENT_NEW_BSS 2#define KEVENT_SET_PROMISC 3#define KEVENT_MGMT_TIMEOUT 4#define KEVENT_SCAN 5 #define KEVENT_JOIN 6#define KEVENT_STARTIBSS 7#define KEVENT_SUBMIT_RX 8#define KEVENT_RESTART 9 /* restart the device */#define KEVENT_ASSOC_DONE 10 /* execute the power save settings: listen interval, pm mode, assoc id */#define KEVENT_EXTERNAL_FW 11#define KEVENT_INTERNAL_FW 12#define KEVENT_RESET_DEVICE 13#define KEVENT_MONITOR 14static DECLARE_WAIT_QUEUE_HEAD(wait_queue);static u8 snapsig[] = {0xaa, 0xaa, 0x03};//#ifdef COLLAPSE_RFC1042/* RFC 1042 encapsulates Ethernet frames in 802.2 SNAP (0xaa, 0xaa, 0x03) with * a SNAP OID of 0 (0x00, 0x00, 0x00) */static u8 rfc1042sig[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};//#endif /* COLLAPSE_RFC1042 *//* local function prototypes */static void iwspy_update(struct at76c503 *dev, struct at76c503_rx_buffer *buf);static void at76c503_read_bulk_callback (struct urb *urb);static void at76c503_write_bulk_callback(struct urb *urb);static void defer_kevent (struct at76c503 *dev, int flag);static struct bss_info *find_matching_bss(struct at76c503 *dev, struct bss_info *curr);static int auth_req(struct at76c503 *dev, struct bss_info *bss, int seq_nr, u8 *challenge);static int disassoc_req(struct at76c503 *dev, struct bss_info *bss);static int assoc_req(struct at76c503 *dev, struct bss_info *bss);static int reassoc_req(struct at76c503 *dev, struct bss_info *curr, struct bss_info *new);static void dump_bss_table(struct at76c503 *dev, int force_output);static int submit_rx_urb(struct at76c503 *dev);static int startup_device(struct at76c503 *dev);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)static int update_usb_intf_descr(struct at76c503 *dev);#endifstatic int set_iroaming(struct at76c503 *dev, int onoff);static void set_monitor_mode(struct at76c503 *dev, int use_prism);/* disassemble the firmware image */static int at76c503_get_fw_info(u8 *fw_data, int fw_size, u32 *board, u32 *version, char **str, u8 **ext_fw, u32 *ext_fw_size, u8 **int_fw, u32 *int_fw_size);/* second step of initialisation (after fw download) */static int init_new_device(struct at76c503 *dev);/* some abbrev. for wireless events */static inline void iwevent_scan_complete(struct net_device *dev){ union iwreq_data wrqu; wrqu.data.length = 0; wrqu.data.flags = 0; wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); dbg(DBG_WE_EVENTS, "%s: SIOCGIWSCAN sent", dev->name);}static inline void iwevent_bss_connect(struct net_device *dev, u8 *bssid){ union iwreq_data wrqu; wrqu.data.length = 0; wrqu.data.flags = 0; memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", dev->name, __FUNCTION__);}static inline void iwevent_bss_disconnect(struct net_device *dev){ union iwreq_data wrqu; wrqu.data.length = 0; wrqu.data.flags = 0; memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", dev->name, __FUNCTION__);}/* hexdump len many bytes from buf into obuf, separated by delim, add a trailing \0 into obuf */static char *hex2str(char *obuf, u8 *buf, int len, char delim){#define BIN2HEX(x) ((x) < 10 ? '0'+(x) : (x)+'A'-10) char *ret = obuf; while (len--) { *obuf++ = BIN2HEX(*buf>>4); *obuf++ = BIN2HEX(*buf&0xf); if (delim != '\0') *obuf++ = delim; buf++; } if (delim != '\0' && obuf > ret) obuf--; // remove last inserted delimiter *obuf = '\0'; return ret;}/* == PROC is_cloaked_ssid == returns != 0, if the given SSID is a cloaked one: - length 0 - length > 0, all bytes are \0 - length == 1, SSID ' '*/static inline int is_cloaked_ssid(u8 *ssid, int length){ return (length == 0) || (length == 1 && *ssid == ' ') || (length > 0 && !memcmp(ssid,zeros,length));}static inline void free_bss_list(struct at76c503 *dev){ struct list_head *next, *ptr; unsigned long flags; spin_lock_irqsave(&dev->bss_list_spinlock, flags); dev->curr_bss = dev->new_bss = NULL; list_for_each_safe(ptr, next, &dev->bss_list) { list_del(ptr); kfree(list_entry(ptr, struct bss_info, list)); } spin_unlock_irqrestore(&dev->bss_list_spinlock, flags);}static inline char *mac2str(u8 *mac){ static char str [6*3]; sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return str;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)/* == PROC analyze_usb_config == This procedure analyzes the configuration after the USB device got reset and find the start of the interface and the two endpoint descriptors. Returns < 0 if the descriptors seems to be wrong. */static int analyze_usb_config(u8 *cfgd, int cfgd_len, int *intf_idx, int *ep0_idx, int *ep1_idx){ u8 *cfgd_start = cfgd; u8 *cfgd_end = cfgd + cfgd_len; /* first byte after config descriptor */ int nr_intf=0, nr_ep=0; /* number of interface, number of endpoint descr. found */ assert(cfgd_len >= 2); if (cfgd_len < 2) return -1; if (*(cfgd+1) != USB_DT_CONFIG) { err("not a config descriptor"); return -2; } if (*cfgd != USB_DT_CONFIG_SIZE) { err("invalid length for config descriptor: %d", *cfgd); return -3; } /* scan the config descr */ while ((cfgd+1) < cfgd_end) { switch (*(cfgd+1)) { case USB_DT_INTERFACE: nr_intf++; if (nr_intf == 1) *intf_idx = cfgd - cfgd_start; break; case USB_DT_ENDPOINT: nr_ep++; if (nr_ep == 1) *ep0_idx = cfgd - cfgd_start; else if (nr_ep == 2) *ep1_idx = cfgd - cfgd_start; break; default: ; } cfgd += *cfgd; } /* while ((cfgd+1) < cfgd_end) */ if (nr_ep != 2 || nr_intf != 1) { err("unexpected nr of intf (%d) or endpoints (%d)", nr_intf, nr_ep); return -4; } return 0;} /* end of analyze_usb_config *//* == PROC update_usb_intf_descr == currently (2.6.0-test2) usb_reset_device() does not recognize that the interface descr. are changed. This procedure reads the configuration and does a limited parsing of the interface and endpoint descriptors. This is IMHO needed until usb_reset_device() is changed inside the kernel's USB subsystem. Copied from usb/core/config.c:usb_get_configuration() THIS IS VERY UGLY CODE - DO NOT COPY IT ! */#define AT76C503A_USB_CONFDESCR_LEN 0x20/* the short configuration descriptor before reset *///#define AT76C503A_USB_SHORT_CONFDESCR_LEN 0x19static int update_usb_intf_descr(struct at76c503 *dev){ int intf0; /* begin of intf descriptor in configuration */ int ep0, ep1; /* begin of endpoint descriptors */ struct usb_device *udev = dev->udev; struct usb_config_descriptor *cfg_desc; int result = 0, size; u8 *buffer; struct usb_host_interface *ifp; int i; dbg(DBG_DEVSTART, "%s: ENTER", __FUNCTION__); cfg_desc = (struct usb_config_descriptor *) kmalloc(AT76C503A_USB_CONFDESCR_LEN, GFP_KERNEL); if (!cfg_desc) { err("cannot kmalloc config desc"); return -ENOMEM; } result = usb_get_descriptor(udev, USB_DT_CONFIG, 0, cfg_desc, AT76C503A_USB_CONFDESCR_LEN); if (result < AT76C503A_USB_CONFDESCR_LEN) { if (result < 0) err("unable to get descriptor"); else { err("config descriptor too short (expected >= %i, got %i)", AT76C503A_USB_CONFDESCR_LEN, result); result = -EINVAL; } goto err; } /* now check the config descriptor */ le16_to_cpus(&cfg_desc->wTotalLength); size = cfg_desc->wTotalLength; buffer = (u8 *)cfg_desc; if (cfg_desc->bNumInterfaces > 1) { err("found %d interfaces", cfg_desc->bNumInterfaces); result = - EINVAL; goto err; } if ((result=analyze_usb_config(buffer, size, &intf0, &ep0, &ep1))) { err("analyze_usb_config returned %d for config desc %s", result, hex2str(dev->obuf, (u8 *)cfg_desc, min((int)(sizeof(dev->obuf)-1)/2,size), '\0')); result=-EINVAL; goto err; } /* we got the correct config descriptor - update the interface's endpoints */ ifp = &udev->actconfig->interface[0]->altsetting[0]; if (ifp->endpoint) kfree(ifp->endpoint); memcpy(&ifp->desc, buffer+intf0, USB_DT_INTERFACE_SIZE); if (!(ifp->endpoint = kmalloc(2 * sizeof(struct usb_host_endpoint), GFP_KERNEL))) { result = -ENOMEM; goto err; } memset(ifp->endpoint, 0, 2 * sizeof(struct usb_host_endpoint)); memcpy(&ifp->endpoint[0].desc, buffer+ep0, USB_DT_ENDPOINT_SIZE); le16_to_cpus(&ifp->endpoint[0].desc.wMaxPacketSize); memcpy(&ifp->endpoint[1].desc, buffer+ep1, USB_DT_ENDPOINT_SIZE); le16_to_cpus(&ifp->endpoint[1].desc.wMaxPacketSize); /* we must set the max packet for the new ep (see usb_set_maxpacket() ) */#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) for(i=0; i < ifp->desc.bNumEndpoints; i++) { struct usb_endpoint_descriptor *d = &ifp->endpoint[i].desc; int b = d->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; if (usb_endpoint_out(d->bEndpointAddress)) { if (d->wMaxPacketSize > udev->epmaxpacketout[b]) udev->epmaxpacketout[b] = d->wMaxPacketSize; } else { if (d->wMaxPacketSize > udev->epmaxpacketin[b]) udev->epmaxpacketin[b] = d->wMaxPacketSize; } } dbg(DBG_DEVSTART, "%s: ifp %p num_altsetting %d " "endpoint addr x%x, x%x", __FUNCTION__, ifp, udev->actconfig->interface[0]->num_altsetting, ifp->endpoint[0].desc.bEndpointAddress, ifp->endpoint[1].desc.bEndpointAddress); result = 0;err: kfree(cfg_desc); dbg(DBG_DEVSTART, "%s: EXIT with %d", __FUNCTION__, result); return result;} /* update_usb_intf_descr */ #endif /* #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) */int at76c503_remap(struct usb_device *udev){ int ret; ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0x0a, INTERFACE_VENDOR_REQUEST_OUT, 0, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT); if (ret < 0) return ret; return 0;}static int get_op_mode(struct usb_device *udev){ int ret; u8 op_mode; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33, INTERFACE_VENDOR_REQUEST_IN, 0x01, 0, &op_mode, 1, HZ * USB_CTRL_GET_TIMEOUT); if(ret < 0) return ret; return op_mode;}/* this loads a block of the second part of the firmware */static inlineint load_ext_fw_block(struct usb_device *udev, int i, unsigned char *buf, int bsize){ return usb_control_msg(udev, usb_sndctrlpipe(udev,0), 0x0e, DEVICE_VENDOR_REQUEST_OUT, 0x0802, i, buf, bsize, HZ * USB_CTRL_GET_TIMEOUT);}static inlineint get_hw_cfg_rfmd(struct usb_device *udev, unsigned char *buf, int buf_size){ return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), 0x33, INTERFACE_VENDOR_REQUEST_IN, ((0x0a << 8) | 0x02), 0, buf, buf_size, HZ * USB_CTRL_GET_TIMEOUT);}/* Intersil boards use a different "value" for GetHWConfig requests */static inlineint get_hw_cfg_intersil(struct usb_device *udev, unsigned char *buf, int buf_size){ return usb_control_msg(udev, usb_rcvctrlpipe(udev,0), 0x33, INTERFACE_VENDOR_REQUEST_IN, ((0x09 << 8) | 0x02), 0, buf, buf_size, HZ * USB_CTRL_GET_TIMEOUT);}/* Get the hardware configuration for the adapter and place the appropriate * data in the appropriate fields of 'dev' (the GetHWConfig request and * interpretation of the result depends on the type of board we're dealing * with) */static int get_hw_config(struct at76c503 *dev){ int ret; union { struct hwcfg_intersil i; struct hwcfg_rfmd r3; struct hwcfg_r505 r5; } *hwcfg = kmalloc(sizeof(*hwcfg), GFP_KERNEL); if (!hwcfg) return -ENOMEM; switch (dev->board_type) { case BOARDTYPE_503_INTERSIL_3861: case BOARDTYPE_503_INTERSIL_3863: ret = get_hw_cfg_intersil(dev->udev, (unsigned char *)&hwcfg->i, sizeof(hwcfg->i)); if (ret < 0) break; memcpy(dev->mac_addr, hwcfg->i.mac_addr, ETH_ALEN); memcpy(dev->cr31_values, hwcfg->i.cr31_values, 14); memcpy(dev->cr58_values, hwcfg->i.cr58_values, 14); memcpy(dev->pidvid, hwcfg->i.pidvid, 4); dev->regulatory_domain = hwcfg->i.regulatory_domain; break; case BOARDTYPE_503_RFMD: case BOARDTYPE_503_RFMD_ACC: ret = get_hw_cfg_rfmd(dev->udev, (unsigned char *)&hwcfg->r3, sizeof(hwcfg->r3)); if (ret < 0) break; memcpy(dev->cr20_values, hwcfg->r3.cr20_values, 14); memcpy(dev->cr21_values, hwcfg->r3.cr21_values, 14); memcpy(dev->bb_cr, hwcfg->r3.bb_cr, 14); memcpy(dev->pidvid, hwcfg->r3.pidvid, 4); memcpy(dev->mac_addr, hwcfg->r3.mac_addr, ETH_ALEN); dev->regulatory_domain = hwcfg->r3.regulatory_domain; memcpy(dev->low_power_values, hwcfg->r3.low_power_values, 14); memcpy(dev->normal_power_values, hwcfg->r3.normal_power_values, 14); break; case BOARDTYPE_505_RFMD: case BOARDTYPE_505_RFMD_2958: case BOARDTYPE_505A_RFMD_2958: ret = get_hw_cfg_rfmd(dev->udev, (unsigned char *)&hwcfg->r5, sizeof(hwcfg->r5)); if (ret < 0) break; memcpy(dev->cr39_values, hwcfg->r5.cr39_values, 14);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -