📄 rtusb_main.c
字号:
netdev = alloc_etherdev(sizeof (*pAdapter));
if(!netdev)
{
//if (!(pAdapter->net = init_etherdev(0, 0) )) {
printk("alloc_etherdev failed\n");
MOD_DEC_USE_COUNT;
usb_dec_dev_use(dev);
return NULL;
}
pAdapter = netdev->priv;
pAdapter->net = netdev;
netif_stop_queue(netdev);
pAdapter->config = dev->config;
pAdapter->usb = dev;
SET_MODULE_OWNER(pAdapter->net);
ether_setup(pAdapter->net);
netdev->open = usb_rtusb_open;
netdev->hard_start_xmit = RTUSBSendPackets;
netdev->stop = usb_rtusb_close;
netdev->priv = pAdapter;
netdev->get_stats = rt_getstats;
#if WIRELESS_EXT >= 11
netdev->get_wireless_stats = RTUSB_get_wireless_stats;
netdev->wireless_handlers = (struct iw_handler_def *) &rt2500usb_iw_handler_def;
#endif
netdev->do_ioctl = usb_rt2570_ioctl;
pAdapter->net->hard_header_len = 14;
pAdapter->net->mtu = 1500;
pAdapter->net->addr_len = 6;
pAdapter->net->weight = 64;
pAdapter->MediaState = NdisMediaStateDisconnected;
{// find available
int i=0;
char slot_name[IFNAMSIZ];
struct net_device *device;
for (i = 0; i < 8; i++)
{
sprintf(slot_name, "rausb%d", i);
for (device = dev_base; device != NULL; device = device->next)
{
if (strncmp(device->name, slot_name, 4) == 0)
{
break;
}
}
if(device == NULL) break;
}
if(i == 8)
{
DBGPRINT(RT_DEBUG_ERROR, "No available slot name\n");
return NULL;
}
sprintf(pAdapter->net->name, "rausb%d", i);
DBGPRINT(RT_DEBUG_ERROR, "usbdevice->name %s\n",pAdapter->net->name);
}
//pAdapter->rx_bh.data = (unsigned long)pAdapter;
pAdapter->rx_bh.func = RTUSBRxPacket;
res = register_netdev(pAdapter->net);
if (res)
goto out3;
// start as if the link is up
// netif_device_attach (pAdapter->net);
return pAdapter;
out3:
printk("3 register_netdev failed err=%d\n",res);
return NULL;
}
//Disconnect function is called within exit routine
static void usb_rtusb_disconnect(struct usb_device *dev, void *ptr)
{
PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) ptr;
if (!pAdapter)
return;
tasklet_kill(&pAdapter->rx_bh);
RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
// for debug, wait to show some messages to /proc system
udelay(1);
//After Add Thread implementation, Upon exec there, pAdapter->net seems becomes NULL,
//need to check why???
//assert(pAdapter->net != NULL)
if(pAdapter->net != NULL)
{
printk("unregister_netdev( )\n");
unregister_netdev (pAdapter->net);
}
udelay(1);
udelay(1);
while (MOD_IN_USE > 0) {
MOD_DEC_USE_COUNT;
}
udelay(1);
DBGPRINT(RT_DEBUG_ERROR,"<=== RTUSB disconnect successfully\n");
}
#else
static int usb_rtusb_close(struct net_device *net)
{
PRT2570ADAPTER pAdapter = (PRT2570ADAPTER) net->priv;
int ret;
DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup);
DECLARE_WAITQUEUE (wait, current);
int i = 0;
netif_carrier_off(pAdapter->net);
netif_stop_queue(pAdapter->net);
// ensure there are no more active urbs.
add_wait_queue (&unlink_wakeup, &wait);
pAdapter->wait = &unlink_wakeup;
// maybe wait for deletions to finish.
while ((i < 25) && atomic_read(&pAdapter->PendingRx) > 0) {
#if LINUX_VERSION_CODE >KERNEL_VERSION(2,6,9)
msleep(UNLINK_TIMEOUT_MS);
#endif
i++;
}
pAdapter->wait = NULL;
remove_wait_queue (&unlink_wakeup, &wait);
if (pAdapter->MLMEThr_pid >= 0)
{
mlme_kill = 1;
RTUSBUp(pAdapter, (&(pAdapter->mlme_semaphore)));
wmb(); // need to check
ret = kill_proc (pAdapter->MLMEThr_pid, SIGTERM, 1);
if (ret)
{
printk (KERN_ERR "%s: unable to signal thread\n", pAdapter->net->name);
return ret;
}
wait_for_completion (&pAdapter->notify);
}
if (pAdapter->RTUSBCmdThr_pid>= 0)
{
RTUSBCmd_kill = 1;
RTUSBUp(pAdapter, (&(pAdapter->RTUSBCmd_semaphore)));
wmb(); // need to check
ret = kill_proc (pAdapter->RTUSBCmdThr_pid, SIGTERM, 1);
if (ret)
{
printk (KERN_ERR "%s: unable to signal thread\n", pAdapter->net->name);
return ret;
}
wait_for_completion (&pAdapter->notify);
}
RTUSBHalt( pAdapter, FALSE);
DBGPRINT(RT_DEBUG_TEMP,"<--usb_rt2570_close\n");
return 0;
}
int MlmeThread(void * Context)
{
PRT2570ADAPTER pAdapter = (PRT2570ADAPTER)Context;
daemonize("rt2500usb");
allow_signal(SIGTERM);
current->flags |= PF_NOFREEZE;
/* signal that we've started the thread */
complete(&(pAdapter->notify));
#if 1
while (1)
{
//if(down_interruptible(&pAdapter->mlme_semaphore))
//break;
/* lock the device pointers */
down(&(pAdapter->mlme_semaphore));
if (mlme_kill)
break;
/* lock the device pointers , need to check if required*/
down(&(pAdapter->usbdev_semaphore));
#if 0
if (current->flags & PF_FREEZE) {
refrigerator(0);
}
#endif
MlmeHandler(pAdapter);
/* unlock the device pointers */
up(&(pAdapter->usbdev_semaphore));
}
#else
// I tried this way for thread handling
while(1)
{
timeout = next_tick;
do {
timeout = interruptible_sleep_on_timeout (&pAdapter->MLMEThr_wait, timeout);
/* make swsusp happy with our thread */
if (current->flags & PF_FREEZE)
refrigerator(PF_FREEZE);
DBGPRINT(RT_DEBUG_TRACE, "current->flags = 0x%x\n",current->flags );
} while (!signal_pending (current) && (timeout > 0));
if (signal_pending (current)) {
flush_signals(current);
}
if (mlme_kill)
break;
}
#endif
/* notify the exit routine that we're actually exiting now
*
* complete()/wait_for_completion() is similar to up()/down(),
* except that complete() is safe in the case where the structure
* is getting deleted in a parallel mode of execution (i.e. just
* after the down() -- that's necessary for the thread-shutdown
* case.
*
* complete_and_exit() goes even further than this -- it is safe in
* the case that the thread of the caller is going away (not just
* the structure) -- this is necessary for the module-remove case.
* This is important in preemption kernels, which transfer the flow
* of execution immediately upon a complete().
*/
complete_and_exit (&pAdapter->notify, 0);
DBGPRINT(RT_DEBUG_TRACE, "<---MlmeThread\n");
}
int RTUSBCmdThread(void * Context)
{
PRT2570ADAPTER pAdapter = (PRT2570ADAPTER)Context;
daemonize("rt2500usb");
allow_signal(SIGTERM);
current->flags |= PF_NOFREEZE;
/* signal that we've started the thread */
complete(&(pAdapter->notify));
while (1)
{
//if(down_interruptible(&pAdapter->mlme_semaphore))
//break;
/* lock the device pointers */
down(&(pAdapter->RTUSBCmd_semaphore));
if (RTUSBCmd_kill)
break;
/* lock the device pointers , need to check if required*/
down(&(pAdapter->usbdev_semaphore));
#if 0
if (current->flags & PF_FREEZE) {
refrigerator(0);
// continue;
}
#endif
CMDHandler(pAdapter);
/* unlock the device pointers */
up(&(pAdapter->usbdev_semaphore));
}
/* notify the exit routine that we're actually exiting now
*
* complete()/wait_for_completion() is similar to up()/down(),
* except that complete() is safe in the case where the structure
* is getting deleted in a parallel mode of execution (i.e. just
* after the down() -- that's necessary for the thread-shutdown
* case.
*
* complete_and_exit() goes even further than this -- it is safe in
* the case that the thread of the caller is going away (not just
* the structure) -- this is necessary for the module-remove case.
* This is important in preemption kernels, which transfer the flow
* of execution immediately upon a complete().
*/
complete_and_exit (&pAdapter->notify, 0);
DBGPRINT(RT_DEBUG_TRACE, "<---RTUSBCmdThread\n");
}
static int usb_rtusb_probe (struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
PRT2570ADAPTER pAdapter = (PRT2570ADAPTER)NULL;
int i;
struct net_device *netdev;
int res = -ENOMEM;
usb_get_dev(dev);
for (i = 0; i < rtusb_usb_id_len; i++)
{
if (dev->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
dev->descriptor.idProduct == rtusb_usb_id[i].idProduct)
{
printk("idVendor = 0x%x, idProduct = 0x%x \n",dev->descriptor.idVendor, dev->descriptor.idProduct);
break;
}
}
if (i == rtusb_usb_id_len) {
printk("Device Descriptor not matching\n");
return res;
}
netdev = alloc_etherdev(sizeof (*pAdapter));
if(!netdev)
{
//if (!(pAdapter->net = init_etherdev(0, 0) )) {
printk("alloc_etherdev failed\n");
module_put(THIS_MODULE);
return res;
}
pAdapter = netdev->priv;
pAdapter->net = netdev;
netif_stop_queue(netdev);
pAdapter->config = &dev->config->desc;
pAdapter->usb = dev;
SET_MODULE_OWNER(pAdapter->net);
ether_setup(pAdapter->net);
netdev->open = usb_rtusb_open;
netdev->stop = usb_rtusb_close;
netdev->priv = pAdapter;
netdev->hard_start_xmit = RTUSBSendPackets;
netdev->get_stats = rt_getstats;
#if 1
#if WIRELESS_EXT >= 12
netdev->get_wireless_stats = RTUSB_get_wireless_stats;
netdev->wireless_handlers = (struct iw_handler_def *) &rt2500usb_iw_handler_def;
#endif
netdev->do_ioctl = usb_rt2570_ioctl;
#endif
pAdapter->net->hard_header_len = 14;
pAdapter->net->mtu = 1500;
pAdapter->net->addr_len = 6;
pAdapter->net->weight = 64;
pAdapter->MediaState = NdisMediaStateDisconnected;
pAdapter->MLMEThr_pid= -1;
pAdapter->RTUSBCmdThr_pid= -1;
RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS);
SET_NETDEV_DEV(pAdapter->net, &intf->dev);
{// find available
int i=0;
char slot_name[IFNAMSIZ];
struct net_device *device;
for (i = 0; i < 8; i++)
{
sprintf(slot_name, "rausb%d", i);
for (device = dev_base; device != NULL; device = device->next)
{
if (strncmp(device->name, slot_name, 4) == 0)
{
break;
}
}
if(device == NULL) break;
}
if(i == 8)
{
DBGPRINT(RT_DEBUG_ERROR, "No available slot name\n");
return res;
}
sprintf(pAdapter->net->name, "rausb%d", i);
}
pAdapter->rx_bh.func = RTUSBRxPacket;
//bottom half data is assign at each task_scheduler
//pAdapter->rx_bh.data = (unsigned long)pAdapter;
res = register_netdev(pAdapter->net);
if (res)
goto out3;
usb_set_intfdata(intf, pAdapter);
return 0;
out3:
printk("3 register_netdev failed err=%d\n",res);
free_netdev(netdev);
return -1;
}
static void usb_rtusb_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
PRT2570ADAPTER pAdapter = (PRT2570ADAPTER)NULL;
pAdapter = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
DBGPRINT(RT_DEBUG_ERROR,"unregister usbnet usb-%s-%s\n",
dev->bus->bus_name, dev->devpath);
if (!pAdapter)
return;
tasklet_kill(&pAdapter->rx_bh);
// for debug, wait to show some messages to /proc system
udelay(1);
//After Add Thread implementation, Upon exec there, pAdapter->net seems becomes NULL,
//need to check why???
//assert(pAdapter->net != NULL)
if(pAdapter->net != NULL)
{
printk("unregister_netdev( )\n");
unregister_netdev (pAdapter->net);
}
udelay(1);
flush_scheduled_work ();
udelay(1);
free_netdev(pAdapter->net);
usb_put_dev(dev);
udelay(1);
DBGPRINT(RT_DEBUG_ERROR,"<=== RTUSB disconnect successfully\n");
}
#endif
int __init usb_rtusb_init(void)
{
DBGPRINT(RT_DEBUG_ERROR,"enter rtusb init( )\n");
return usb_register(&rtusb_driver);
}
void __exit usb_rtusb_exit(void)
{
udelay(1);
udelay(1);
usb_deregister(&rtusb_driver);
printk("<===usb_rtusb_exit\n");
}
/**************************************************************/
MODULE_DESCRIPTION("RALINK rtusb WLAN Card");
MODULE_AUTHOR("Ralink Drivers Group");
MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
MODULE_LICENSE("GPL");
module_init(usb_rtusb_init); // initialization function
module_exit(usb_rtusb_exit); // exit function
/**************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -