コード例 #1
0
/*
 * ---------------------------------------------------------------------------
 *  unifi_send_signal
 *
 *    Invokes send_signal() to queue a signal in the command or traffic queue
 *    If sigptr pointer is NULL, it pokes the bh to check if UniFi is responsive.
 *
 *  Arguments:
 *      card        Pointer to card context struct
 *      sigptr      Pointer to signal from card.
 *      siglen      Size of the signal
 *      bulkdata    Pointer to the bulk data of the signal
 *
 *  Returns:
 *      CSR_RESULT_SUCCESS on success
 *      CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or no free signal queue entry
 *
 *  Notes:
 *      unifi_send_signal() is used to queue signals, created by the driver,
 *      to the device. Signals are constructed using the UniFi packed structures.
 * ---------------------------------------------------------------------------
 */
CsrResult unifi_send_signal(card_t *card, const CsrUint8 *sigptr, CsrUint32 siglen,
                            const bulk_data_param_t *bulkdata)
{
    q_t *sig_soft_q;
    CsrUint16 signal_id;
    CsrResult r;
    CsrUint32 run_bh;
    CsrUint32 priority_q;

    /* A NULL signal pointer is a request to check if UniFi is responsive */
    if (sigptr == NULL)
    {
        card->bh_reason_host = 1;
        return unifi_run_bh(card->ospriv);
    }

    priority_q = 0;
    run_bh = 1;
    signal_id = GET_SIGNAL_ID(sigptr);
    /*
     * If the signal is a CSR_MA_PACKET_REQUEST ,
     * we send it using the traffic soft queue. Else we use the command soft queue.
     */
    if (signal_id == CSR_MA_PACKET_REQUEST_ID)
    {
        CsrUint16 frame_priority;

        if (card->periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_ENABLED)
        {
            run_bh = 0;
        }

#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
        unifi_debug_log_to_buf("D");
#endif
        /* Sanity check: MA-PACKET.req must have a valid bulk data */
        if ((bulkdata->d[0].data_length == 0) || (bulkdata->d[0].os_data_ptr == NULL))
        {
            unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n",
                        bulkdata->d[0].data_length, bulkdata->d[0].os_data_ptr);
            dump((void *)sigptr, siglen);
            return CSR_RESULT_FAILURE;
        }

        /* Map the frame priority to a traffic queue index. */
        frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr);
        priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority);

        sig_soft_q = &card->fh_traffic_queue[priority_q];
    }
    else
    {
        sig_soft_q = &card->fh_command_queue;
    }

    r = send_signal(card, sigptr, siglen, bulkdata, sig_soft_q, priority_q, run_bh);
    /* On error, the caller must free or requeue bulkdata buffers */

    return r;
} /* unifi_send_signal() */
コード例 #2
0
/*
 * ---------------------------------------------------------------------------
 *  unifi_send_resources_available
 *
 *      Examines whether there is available space to queue
 *      a signal in the command or traffic queue
 *
 *  Arguments:
 *      card        Pointer to card context struct
 *      sigptr      Pointer to signal.
 *
 *  Returns:
 *      CSR_RESULT_SUCCESS if resources available
 *      CSR_WIFI_HIP_RESULT_NO_SPACE if there was no free signal queue entry
 *
 *  Notes:
 * ---------------------------------------------------------------------------
 */
CsrResult unifi_send_resources_available(card_t *card, const CsrUint8 *sigptr)
{
    q_t *sig_soft_q;
    CsrUint16 signal_id = GET_SIGNAL_ID(sigptr);

    /*
     * If the signal is a CSR_MA_PACKET_REQUEST ,
     * we send it using the traffic soft queue. Else we use the command soft queue.
     */
    if (signal_id == CSR_MA_PACKET_REQUEST_ID)
    {
        CsrUint16 frame_priority;
        CsrUint32 priority_q;

        /* Map the frame priority to a traffic queue index. */
        frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr);
        priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority);

        sig_soft_q = &card->fh_traffic_queue[priority_q];
    }
    else
    {
        sig_soft_q = &card->fh_command_queue;
    }

    /* Check that the fh_data_queue has a free slot */
    if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sig_soft_q))
    {
        unifi_notice(card->ospriv, "unifi_send_resources_available: %s full\n",
                     sig_soft_q->name);
        return CSR_WIFI_HIP_RESULT_NO_SPACE;
    }

    return CSR_RESULT_SUCCESS;
} /* unifi_send_resources_available() */
コード例 #3
0
ファイル: sme_drv.c プロジェクト: murphy666/sun4i-kernel
int
wait_for_event(MANAGER_PRIV_DATA *priv, int signal_id)
{
    static unsigned char buffer[4096];
    fd_set readfds;
    int reply_len;
    CSR_SIGNAL *reply_signal;

    while (1) {
        int r;
        udi_msg_t *msg;
        unsigned char *sigptr;
        int signal_and_data;
        
        FD_ZERO(&readfds);
        FD_SET(priv->Fd, &readfds);

        /* This will poll in the char device for an event. */
        r = select(priv->Fd+1, &readfds, NULL, NULL, NULL);
        if (r < 0) {
            perror("Error from select");
            return ERROR_IO_ERROR;
        }

        /* This read will obtain the indication. */
        r = read(priv->Fd, buffer, 4096);
        if (r < 0) {
            perror("Error reading UDI msg");
            return ERROR_IO_ERROR;
        }

        /* We get a udi_msg_t, and the signal is appended right after the structure. */
        msg = (udi_msg_t *)buffer;
        sigptr = (unsigned char *)(msg + 1);

        /* Total length of signal body + any bulk data */
        signal_and_data = COAL_GET_UINT32_FROM_LITTLE_ENDIAN((buffer + offsetof(udi_msg_t, length))) - sizeof(udi_msg_t);

        /*
        * Check if the indication is actual a config indication, 
        * rather than a signal..
        */
        if (COAL_GET_UINT32_FROM_LITTLE_ENDIAN((buffer + offsetof(udi_msg_t, direction))) == UDI_CONFIG_IND) {
            /* .. in this case the information is just one byte. */
            return (int)(*sigptr);
        }
        
        reply_len = signal_and_data;
        if (reply_len > 0) {
            reply_signal = (CSR_SIGNAL*)sigptr;
            if (signal_id == GET_SIGNAL_ID(sigptr)) {
                if (signal_id == CSR_MLME_GET_CONFIRM_ID) {
                    unsigned char varbind[32];
                    unsigned char *ptr;
                    int oid_len;
                    const int oid_offset = offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_CONFIRM) + 2;
        
                    /* We are looking for this pattern. */
                    oid_len = MibEncodeOID(dot11MACAddress_oid, varbind);
                    /* Length of the signal with bulk data should be at least.. */
                    if (reply_len >= oid_offset + oid_len + 2 + 6) {
                        /* .. and the pattern should match. */
                        if (memcmp(sigptr + oid_offset, varbind, oid_len) == 0) {
                            ptr = sigptr + oid_offset + oid_len;
                            if ((ptr[0] == MIB_TAG_OCTETSTRING) && (ptr[1] == 6)) {
                                /* Store the MAC address, skip two bytes of the NULL decode. */
                                memcpy(priv->unifi_macaddress, ptr + 2, 6);
                            }
                        }
                    }
                }
                /* This is what we are expecting for, return success. */
                return 0;
            }
        }