/* * --------------------------------------------------------------------------- * 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() */
/* * --------------------------------------------------------------------------- * 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() */
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; } }