示例#1
0
VOID
compdev_set_cfg_completion(PURB purb, PVOID context)
{
    DEV_HANDLE dev_handle;
    PUSB_DEV_MANAGER dev_mgr;
    PUSB_DRIVER pdriver;
    NTSTATUS status;
    PUSB_DEV pdev;
    USE_BASIC_NON_PENDING_IRQL;

    if (purb == NULL || context == NULL)
        return;

    dev_handle = purb->endp_handle & ~0xffff;
    dev_mgr = (PUSB_DEV_MANAGER) context;
    pdriver = (PUSB_DRIVER) purb->reference;

    if (purb->status != STATUS_SUCCESS)
    {
        usb_free_mem(purb);
        return;
    }

    usb_free_mem(purb);
    purb = NULL;

    // set the dev state
    status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
    if (status != STATUS_SUCCESS)
    {
        usb_unlock_dev(pdev);
        return;
    }
    // safe to release the pdev ref since we are in urb completion
    usb_unlock_dev(pdev);

    lock_dev(pdev, TRUE);
    if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB)
    {
        unlock_dev(pdev, TRUE);
        return;
    }

    if (dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE)
        return;

    //transit the state to configured
    pdev->flags &= ~USB_DEV_STATE_MASK;
    pdev->flags |= USB_DEV_STATE_CONFIGURED;
    unlock_dev(pdev, TRUE);

    //
    // we change to use our thread for driver choosing. it will reduce
    // the race condition when different pnp event comes simultaneously
    //
    usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_set_cfg_completion(): start select driver for the dev\n"));
    compdev_post_event_select_driver(dev_mgr, dev_handle);

    return;
}
示例#2
0
BOOLEAN
compdev_post_event_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
    PUSB_EVENT pevent;
    BOOLEAN bret;
    PUSB_DEV pdev;
    USE_BASIC_NON_PENDING_IRQL;

    if (dev_mgr == NULL || dev_handle == 0)
        return FALSE;

    if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
        return FALSE;

    KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
    lock_dev(pdev, TRUE);

    if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
    {
        bret = FALSE;
        goto LBL_OUT;
    }

    pevent = alloc_event(&dev_mgr->event_pool, 1);
    if (pevent == NULL)
    {
        bret = FALSE;
        goto LBL_OUT;
    }
    pevent->flags = USB_EVENT_FLAG_ACTIVE;
    pevent->event = USB_EVENT_DEFAULT;
    pevent->pdev = pdev;
    pevent->context = 0;
    pevent->param = 0;
    pevent->pnext = 0;          //vertical queue for serialized operation
    pevent->process_event = compdev_event_select_if_driver;
    pevent->process_queue = event_list_default_process_queue;

    InsertTailList(&dev_mgr->event_list, &pevent->event_link);
    KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);      // wake up the dev_mgr_thread
    bret = TRUE;

  LBL_OUT:

    unlock_dev(pdev, TRUE);
    KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
    usb_unlock_dev(pdev);
    return bret;
}
示例#3
0
//this function is called by the hcd's
//dispatch when they have done their job.
NTSTATUS
dev_mgr_dispatch(IN PUSB_DEV_MANAGER dev_mgr, IN PIRP irp)
{
    PIO_STACK_LOCATION irp_stack;
    NTSTATUS status;
    ULONG ctrl_code;
    USE_NON_PENDING_IRQL;

    ASSERT(irp);
    if (dev_mgr == NULL)
    {
        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
    }

    status = STATUS_SUCCESS;
    irp_stack = IoGetCurrentIrpStackLocation(irp);
    ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;

    switch (irp_stack->MajorFunction)
    {
    case IRP_MJ_CREATE:
        {
            InterlockedIncrement(&dev_mgr->open_count);
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    case IRP_MJ_CLOSE:
        {
            InterlockedDecrement(&dev_mgr->open_count);
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
    case IRP_MJ_DEVICE_CONTROL:
        {
            switch (ctrl_code)
            {
            case IOCTL_GET_DEV_COUNT:
                {
                    LONG dev_count;

                    irp->IoStatus.Information = 0;
                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
                    dev_count = usb_count_list(&dev_mgr->dev_list);
                    KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);

                    *((PLONG) irp->AssociatedIrp.SystemBuffer) = dev_count;
                    irp->IoStatus.Information = sizeof(LONG);
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            case IOCTL_ENUM_DEVICES:
                {
                    PLIST_ENTRY pthis, pnext;
                    LONG dev_count, array_size, i, j = 0;
                    PUSB_DEV pdev;
                    PENUM_DEV_ARRAY peda;

                    irp->IoStatus.Information = 0;
                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LONG))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ENUM_DEV_ARRAY))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    array_size = *((PULONG) irp->AssociatedIrp.SystemBuffer);

                    KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
                    dev_count = usb_count_list(&dev_mgr->dev_list);
                    dev_count = dev_count > array_size ? array_size : dev_count;
                    peda = (PENUM_DEV_ARRAY) irp->AssociatedIrp.SystemBuffer;
                    RtlZeroMemory(peda, sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT));

                    if (dev_count)
                    {
                        ListFirst(&dev_mgr->dev_list, pthis);
                        for(i = 0, j = 0; i < dev_count; i++)
                        {
                            pdev = struct_ptr(pthis, USB_DEV, dev_link);
                            ListNext(&dev_mgr->dev_list, pthis, pnext);
                            pthis = pnext;

                            lock_dev(pdev, FALSE);
                            if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
                            {
                                unlock_dev(pdev, FALSE);
                                continue;
                            }

                            if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
                            {
                                unlock_dev(pdev, FALSE);
                                continue;
                            }

                            peda->dev_arr[i].dev_handle = (pdev->dev_id << 16);
                            //may not get the desc yet
                            if (pdev->pusb_dev_desc)
                            {
                                peda->dev_arr[i].product_id = pdev->pusb_dev_desc->idProduct;
                                peda->dev_arr[i].vendor_id = pdev->pusb_dev_desc->idVendor;
                            }
                            else
                            {
                                peda->dev_arr[i].product_id = 0xffff;
                                peda->dev_arr[i].vendor_id = 0xffff;
                            }
                            peda->dev_arr[i].dev_addr = pdev->dev_addr;
                            unlock_dev(pdev, FALSE);
                            j++;
                        }
                    }
                    peda->dev_count = dev_count ? j : 0;
                    KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);

                    irp->IoStatus.Information =
                        sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT);
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            case IOCTL_GET_DEV_DESC:
                {
                    GET_DEV_DESC_REQ gddr;
                    PUSB_DESC_HEADER pusb_desc_header;
                    PUSB_DEV pdev;
                    LONG buf_size;

                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < 8)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    status = STATUS_SUCCESS;
                    buf_size = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
                    RtlCopyMemory(&gddr, irp->AssociatedIrp.SystemBuffer, sizeof(GET_DEV_DESC_REQ));
                    pusb_desc_header = irp->AssociatedIrp.SystemBuffer;

                    if (gddr.desc_type != USB_DT_CONFIG && gddr.desc_type != USB_DT_DEVICE)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
                    }

                    if (usb_query_and_lock_dev(dev_mgr, gddr.dev_handle, &pdev) != STATUS_SUCCESS)
                    {
                        EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
                    }

                    lock_dev(pdev, FALSE);
                    if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
                    {
                        status = STATUS_INVALID_DEVICE_STATE;
                        goto ERROR_OUT;
                    }
                    if (dev_state(pdev) != USB_DEV_STATE_ADDRESSED &&
                        dev_state(pdev) != USB_DEV_STATE_CONFIGURED)
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT;
                    }

                    if (pdev->pusb_dev_desc == NULL)
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT;
                    }

                    if (gddr.desc_type == USB_DT_DEVICE)
                    {
                        RtlCopyMemory(pusb_desc_header,
                                      pdev->pusb_dev_desc,
                                      buf_size > sizeof(USB_DEVICE_DESC)
                                      ? sizeof(USB_DEVICE_DESC) : buf_size);

                        irp->IoStatus.Information =
                            buf_size >= sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : buf_size;
                    }
                    else if (gddr.desc_type == USB_DT_CONFIG)
                    {
                        PUSB_CONFIGURATION_DESC pusb_config_desc;
                        if (pdev->pusb_dev_desc->bNumConfigurations <= gddr.desc_idx)
                        {
                            status = STATUS_INVALID_PARAMETER;
                            goto ERROR_OUT;
                        }

                        pusb_config_desc = usb_find_config_desc_by_idx((PUCHAR) & pdev->pusb_dev_desc[1],
                                                                       gddr.desc_idx,
                                                                       pdev->pusb_dev_desc->
                                                                       bNumConfigurations);

                        if (pusb_config_desc == NULL)
                        {
                            status = STATUS_DEVICE_NOT_READY;
                            goto ERROR_OUT;
                        }

                        RtlCopyMemory(pusb_desc_header,
                                      pusb_config_desc,
                                      buf_size >= pusb_config_desc->wTotalLength
                                      ? pusb_config_desc->wTotalLength : buf_size);

                        irp->IoStatus.Information =
                            buf_size >= pusb_config_desc->wTotalLength
                            ? pusb_config_desc->wTotalLength : buf_size;
                    }
                  ERROR_OUT:
                    unlock_dev(pdev, FALSE);
                    usb_unlock_dev(pdev);
                    EXIT_DISPATCH(status, irp);
                }
            case IOCTL_SUBMIT_URB_RD:
            case IOCTL_SUBMIT_URB_WR:
            case IOCTL_SUBMIT_URB_NOIO:
                {
                    PURB purb;
                    ULONG endp_idx, if_idx, user_buffer_length = 0;
                    PUCHAR user_buffer = NULL;
                    PUSB_DEV pdev;
                    DEV_HANDLE endp_handle;
                    PUSB_ENDPOINT pendp;

                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    purb = (PURB) irp->AssociatedIrp.SystemBuffer;
                    endp_handle = purb->endp_handle;

                    if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
                    {
                        if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
                        {
                            user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
                            if (user_buffer_length == 0)
                                EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                            user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
                        }
                        else
                        {
                            if (purb->data_buffer == NULL || purb->data_length == 0)
                                EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                            user_buffer_length = purb->data_length;
                            user_buffer = purb->data_buffer;
                        }
                    }

                    if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS)
                    {
                        EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
                    }


                    lock_dev(pdev, FALSE);
                    if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED))

                    {
                        status = STATUS_INVALID_DEVICE_STATE;
                        goto ERROR_OUT1;
                    }

                    if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle))
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT1;
                    }

                    if_idx = if_idx_from_handle(endp_handle);
                    endp_idx = endp_idx_from_handle(endp_handle);

                    //if_idx exceeds the upper limit
                    if (pdev->usb_config)
                    {
                        if (if_idx >= pdev->usb_config->if_count
                            || endp_idx >= pdev->usb_config->interf[if_idx].endp_count)
                        {
                            if (!default_endp_handle(endp_handle))
                            {
                                status = STATUS_INVALID_DEVICE_STATE;
                                goto ERROR_OUT1;
                            }
                        }
                    }

                    endp_from_handle(pdev, endp_handle, pendp);
                    // FIXME: don't know what evil will let loose
                    if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL)
                    {
                        if (user_buffer_length > 0x100000)
                        {
                            status = STATUS_INVALID_PARAMETER;
                            goto ERROR_OUT1;
                        }
                    }

                    purb->pirp = irp;
                    purb->context = dev_mgr;
                    purb->reference = ctrl_code;

                    if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
                    {
                        if (ctrl_code == IOCTL_SUBMIT_URB_RD)
                            KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);
                        else
                            KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);

                        purb->data_buffer = user_buffer;
                        purb->data_length = user_buffer_length;
                        purb->completion = disp_urb_completion;
                    }
                    else
                    {
                        purb->completion = disp_noio_urb_completion;
                    }

                    unlock_dev(pdev, FALSE);

                    // we have to mark irp before the urb is scheduled to
                    // avoid race condition
                    IoMarkIrpPending(irp);
                    ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb));
                    status = usb_submit_urb(dev_mgr, purb);
                    if (status != STATUS_PENDING)
                    {
                        IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED;
                        dev_mgr_remove_irp(dev_mgr, irp);
                    }
                    usb_unlock_dev(pdev);
                    if (status != STATUS_PENDING)
                    {
                        irp->IoStatus.Status = status;
                        IoCompleteRequest(irp, IO_NO_INCREMENT);
                    }
                    return status;
                  ERROR_OUT1:
                    unlock_dev(pdev, FALSE);
                    usb_unlock_dev(pdev);
                    irp->IoStatus.Information = 0;
                    EXIT_DISPATCH(status, irp);
                }
            default:
                {
                    irp->IoStatus.Information = 0;
                    EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED, irp);
                }
            }
        }
    default:
        {
            irp->IoStatus.Information = 0;
            break;
        }
    }
    EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}
示例#4
0
void RoiCounters::init_device()
{
    INFO_STREAM << "RoiCounters::init_device() create device " << device_name << endl;
    yat::AutoMutex<> _lock(ControlFactory::instance().get_global_mutex());
    // Initialise variables to default values
    //--------------------------------------------	
    get_device_property();

    CREATE_DEVSTRING_ATTRIBUTE(attr_version_read, 256);
    //By default INIT, need to ensure that all objets are OK before set the device to STANDBY
    set_state(Tango::INIT);
    m_is_device_initialized = false;
    m_status_message.str("");

    try
    {
        yat::AutoMutex<> _lock(ControlFactory::instance().get_global_mutex());
        //- get the main object used to pilot the lima framework
        //in fact LimaDetector is create the singleton control objet
        m_ct = ControlFactory::instance().get_control("RoiCounters");
    }
    catch(Exception& e)
    {
        INFO_STREAM << "Initialization Failed : " << e.getErrMsg() << endl;
        m_status_message << "Initialization Failed : " << e.getErrMsg() << endl;
        m_is_device_initialized = false;
        set_state(Tango::FAULT);
        return;
    }
    catch(...)
    {
        INFO_STREAM << "Initialization Failed : UNKNOWN" << endl;
        m_status_message << "Initialization Failed : UNKNOWN" << endl;
        set_state(Tango::FAULT);
        m_is_device_initialized = false;
        return;
    }

    //---------------------------------------------------------
    //Configure/create all dynamic attributes
    //---------------------------------------------------------
    if(!create_all_dynamic_attributes())
    {
        m_is_device_initialized = false;
        return;
    }

    try
    {
        //create new operation			
        std::stringstream opId("MyRoiCounters");
        INFO_STREAM << "addOp(" << opId.str() << ")" << endl;
        m_ct->externalOperation()->addOp(ROICOUNTERS, opId.str(), 0/*level*/, m_soft_operation);

        //Write tango hardware at Init
        std::stringstream ssName;
        std::string strName;
        for(size_t i = 0; i < nbRoiCounters; i++)
        {
            //get memorized from properties
            attr_x_array[i] = (Tango::DevULong)(__x.at(i));
            attr_y_array[i] = (Tango::DevULong)(__y.at(i));
            attr_width_array[i] = (Tango::DevULong)(__width.at(i));
            attr_height_array[i] = (Tango::DevULong)(__height.at(i));
        
            ssName.str("");
            ssName << "x" << i;
            strName = ssName.str();
            INFO_STREAM << "Write tango hardware at Init - " << strName << endl;
            Tango::WAttribute &x = dev_attr->get_w_attr_by_name(strName.c_str());
            x.set_write_value(attr_x_array[i]);
            yat4tango::DynamicAttributeWriteCallbackData cbd_x;
            cbd_x.tga = &x;
            write_rois_callback(cbd_x);
        
            ssName.str("");
            ssName << "y" << i;
            strName = ssName.str();
            INFO_STREAM << "Write tango hardware at Init - " << strName << endl;
            Tango::WAttribute &y = dev_attr->get_w_attr_by_name(strName.c_str());
            y.set_write_value(attr_y_array[i]);
            yat4tango::DynamicAttributeWriteCallbackData cbd_y;
            cbd_y.tga = &y;
            write_rois_callback(cbd_y);
        
            ssName.str("");
            ssName << "width" << i;
            strName = ssName.str();
            INFO_STREAM << "Write tango hardware at Init - " << strName << endl;
            Tango::WAttribute &width = dev_attr->get_w_attr_by_name(strName.c_str());
            width.set_write_value(attr_width_array[i]);
            yat4tango::DynamicAttributeWriteCallbackData cbd_width;
            cbd_width.tga = &width;
            write_rois_callback(cbd_width);
                   
            ssName.str("");
            ssName << "height" << i;
            strName = ssName.str();
            INFO_STREAM << "Write tango hardware at Init - " << strName << endl;
            Tango::WAttribute &height = dev_attr->get_w_attr_by_name(strName.c_str());
            height.set_write_value(attr_height_array[i]);
            yat4tango::DynamicAttributeWriteCallbackData cbd_height;
            cbd_height.tga = &height;
            write_rois_callback(cbd_height);
        }
    }
    catch(Exception& e)
    {
        ERROR_STREAM << "Initialization Failed : " << e.getErrMsg() << endl;
        m_status_message << "Initialization Failed : " << e.getErrMsg() << endl;
        m_is_device_initialized = false;
        set_state(Tango::FAULT);
        return;
    }
    catch(Tango::DevFailed& df)
    {
        ERROR_STREAM << df << endl;
        m_status_message << "Initialization Failed : ";
        for(unsigned i = 0; i < df.errors.length(); i++)
        {
            m_status_message << df.errors[i].desc << endl;
        }
        m_is_device_initialized = false;
        set_state(Tango::FAULT);
        return;
    }
    catch(...)
    {
        ERROR_STREAM << "Initialization Failed : UNKNOWN" << endl;
        m_status_message << "Initialization Failed : UNKNOWN" << endl;
        set_state(Tango::FAULT);
        m_is_device_initialized = false;
        return;
    }

    //everything is Ok
    m_is_device_initialized = true;

    set_state(Tango::STANDBY);
    dev_state();
}