/**************************************************************************** NAME deviceManagerCanConnect DESCRIPTION Determines if max number of possible connections have been made RETURNS TRUE if connection can be made, FALSE otherwise */ bool deviceManagerCanConnect(void) { bdaddr dev_addr1, dev_addr2; DEV_DEBUG(("DEV: %d of %d connected\n", theSink.no_of_profiles_connected, (theSink.MultipointEnable ? MAX_MULTIPOINT_CONNECTIONS : 1))); /* If no devices connected we're okay */ if(theSink.no_of_profiles_connected == 0) return TRUE; /* If multipoint is not enabled check if this is manual connect request for A2DP for an already connected HFP profile to the same device */ if(!theSink.MultipointEnable) { if((deviceManagerGetProfileAddr(conn_hfp_pri, &dev_addr1)) && !(deviceManagerGetProfileAddr(conn_a2dp_pri, &dev_addr2))) { DEV_DEBUG(("DEV: Allow the device to connect \n")); return TRUE; } } /* If multipoint and not all devices connected then we're okay */ if(theSink.MultipointEnable && (theSink.no_of_profiles_connected < MAX_MULTIPOINT_CONNECTIONS)) return TRUE; /* We can't accept any more connections */ return FALSE; }
/**************************************************************************** NAME deviceManagerStoreAttributes DESCRIPTION Stores given attribute values against a given device in PS. RETURNS void */ void deviceManagerStoreAttributes(sink_attributes* attributes, const bdaddr* dev_addr) { #ifdef ENABLE_SHAREME DEV_DEBUG(("DEV: StoreAttribs - profiles %d, peer %d, hfp_vol %d, a2dp_vol %d\n", attributes->profiles, attributes->peer_device, attributes->hfp.volume,attributes->a2dp.volume)); #else DEV_DEBUG(("DEV: StoreAttribs - profiles %d, hfp_vol %d, a2dp_vol %d\n", attributes->profiles, attributes->hfp.volume,attributes->a2dp.volume)); #endif ConnectionSmPutAttribute(PSKEY_ATTRIBUTE_BASE, dev_addr, sizeof(sink_attributes), (uint8*)attributes); }
/**************************************************************************** NAME deviceManagerGetDefaultAttributes DESCRIPTION Initialise sink_attributes struct to default values RETURNS void */ void deviceManagerGetDefaultAttributes(sink_attributes* attributes, bool is_subwoofer) { /* profiles and clock_mismatch default to 0 */ memset(attributes, 0, sizeof(sink_attributes)); #ifdef ENABLE_PEER attributes->peer_device = remote_device_unknown; #endif #ifdef ENABLE_SUBWOOFER if (is_subwoofer) { attributes->profiles = sink_swat; attributes->hfp.volume = 0; attributes->a2dp.volume = 0; attributes->sub.sub_trim = DEFAULT_SUB_TRIM_INDEX; return; } #endif attributes->profiles = sink_none; attributes->hfp.volume = theSink.features.DefaultVolume; attributes->a2dp.volume = theSink.features.DefaultA2dpVolLevel; DEV_DEBUG(("DEV: getDefaultAttrib prof:%d HfpVol:%d a2dpVol:%d\n",attributes->profiles, attributes->hfp.volume, attributes->a2dp.volume)); }
/**************************************************************************** NAME deviceManagerUpdateAttributes DESCRIPTION Stores the current attribute values for a given HFP/A2DP connection in PS. RETURNS void */ void deviceManagerUpdateAttributes(const bdaddr* bd_addr, sink_link_type link_type, hfp_link_priority hfp_priority, a2dp_link_priority a2dp_priority) { EVENT_UPDATE_ATTRIBUTES_T* update = PanicUnlessNew(EVENT_UPDATE_ATTRIBUTES_T); memset(update,0,sizeof(EVENT_UPDATE_ATTRIBUTES_T)); update->bd_addr = *bd_addr; if(link_type == sink_hfp) { update->attributes.profiles = sink_hfp; update->attributes.hfp.volume = theSink.profile_data[PROFILE_INDEX(hfp_priority)].audio.gSMVolumeLevel; } else if(link_type == sink_a2dp) { update->attributes.profiles = sink_a2dp; update->attributes.a2dp.volume = theSink.a2dp_link_data->gAvVolumeLevel[a2dp_priority]; update->attributes.a2dp.clock_mismatch = theSink.a2dp_link_data->clockMismatchRate[a2dp_priority]; } #ifdef ENABLE_SUBWOOFER else if(link_type == sink_swat) { update->attributes.profiles = sink_swat; update->attributes.sub.sub_trim = theSink.rundata->subwoofer.sub_trim_idx; } #endif DEV_DEBUG(("DEV: DelayUpdateAttributes - type %d profiles %d, hfp_vol %d, a2dp_vol %d\n",link_type, update->attributes.profiles, update->attributes.hfp.volume, update->attributes.a2dp.volume)); MessageSendConditionally(&theSink.task, EventUpdateAttributes, update, (const uint16 *)AudioBusyPtr()); }
/**************************************************************************** NAME deviceManagerDelayedUpdateAttributes DESCRIPTION Store attributes contained in EVENT_UPDATE_ATTRIBUTES_T in PS RETURNS void */ void deviceManagerDelayedUpdateAttributes(EVENT_UPDATE_ATTRIBUTES_T* update) { sink_attributes attributes; sink_attributes new_attributes; /* zero settings */ memset(&new_attributes,0,sizeof(sink_attributes)); /* Get attributes from PS */ deviceManagerGetDefaultAttributes(&attributes, FALSE); deviceManagerGetAttributes(&attributes, &update->bd_addr); if(update->attributes.profiles == sink_hfp) { /* Update with current attribute values */ new_attributes = attributes; new_attributes.profiles |= sink_hfp; new_attributes.hfp.volume = update->attributes.hfp.volume; } else if(update->attributes.profiles == sink_a2dp) { /* Update with current attribute values */ new_attributes = attributes; new_attributes.profiles |= sink_a2dp; new_attributes.a2dp.volume = update->attributes.a2dp.volume; new_attributes.a2dp.clock_mismatch = update->attributes.a2dp.clock_mismatch; } #ifdef ENABLE_SUBWOOFER else if(update->attributes.profiles == sink_swat) { new_attributes.sub.sub_trim = update->attributes.sub.sub_trim; new_attributes.profiles = sink_swat; } #endif DEV_DEBUG(("DEV: UpdateAttributesOld - profiles %d, hfp_vol %d, a2dp_vol %d, clock_mismatch %d\n", attributes.profiles, attributes.hfp.volume, attributes.a2dp.volume, attributes.a2dp.clock_mismatch)); DEV_DEBUG(("DEV: UpdateAttributesNew - profiles %d, hfp_vol %d, a2dp_vol %d, clock_mismatch %d\n", new_attributes.profiles, new_attributes.hfp.volume, new_attributes.a2dp.volume, new_attributes.a2dp.clock_mismatch)); /* Write updated attributes to PS */ if(!deviceManagerCompareAttributes(&attributes, &new_attributes)) deviceManagerStoreAttributes(&new_attributes, &update->bd_addr); }
/**************************************************************************** NAME deviceManagerNumConnectedPeerDevs DESCRIPTION determines the number of different connected peer devices, a device will only have connected a2dp RETURNS number of connected peer devices */ uint8 deviceManagerNumConnectedPeerDevs(void) { a2dp_link_priority priority; uint8 no_devices = 0; /* Go through all profiles */ for(priority = a2dp_primary; priority <= a2dp_secondary; priority++) { /* Only valid if we have processed A2DP connect */ if (theSink.a2dp_link_data && (theSink.a2dp_link_data->device_id[priority] != INVALID_DEVICE_ID) && (theSink.a2dp_link_data->peer_device[priority] == remote_device_peer)) { no_devices++; } } DEV_DEBUG(("DEV: Peer Conn Count %d\n", no_devices)); return no_devices; }
static void pci_dev_init_manager(struct device_mem *bar_info, int nr_mapped_bars) { errval_t err; DEV_DEBUG("Initialize device @ [%016lx] with %u bars\n", bar_info->paddr, nr_mapped_bars); if (nr_mapped_bars != 1) { DEV_ERR("number of mapped bars is wrong. Skipping initialization\n"); return; } err = ioat_mgr_svc_add_device(bar_info->frame_cap); if (err_is_fail(err)) { DEV_ERR("Device coult not be added to the manager: %s\n", err_getstring(err)); } }
/**************************************************************************** NAME deviceManagerNumConnectedDevs DESCRIPTION determines the number of different connected devices, a device may connected both hfp and a2dp or only one of each RETURNS number of connected devices */ uint8 deviceManagerNumConnectedDevs(void) { conn_mask mask; bdaddr dev_addr; uint8 no_devices = 0; /* Go through all profiles */ for(mask = conn_hfp_pri; mask <= conn_a2dp_sec; mask <<=1) { /* Get bluetooth address for profile if connected */ if(deviceManagerGetProfileAddr(mask, &dev_addr)) { /* If HFP connection, or A2DP connection on device with no HFP... */ if( (mask & conn_hfp) || (!(conn_hfp & deviceManagerProfilesConnected(&dev_addr))) ) no_devices++; } } DEV_DEBUG(("DEV: Conn Count %d\n", no_devices)); return no_devices; }
/**************************************************************************** NAME deviceManagerProfilesConnected DESCRIPTION Compare bdaddr against those of the current connected devices RETURNS conn_mask indicating which profiles the device is connected to */ conn_mask deviceManagerProfilesConnected(const bdaddr * bd_addr) { bdaddr dev_addr; conn_mask mask, result = 0; /* Go through all profiles */ for(mask = conn_hfp_pri; mask <= conn_a2dp_sec; mask <<=1) { /* Get bluetooth address for profile if connected */ if(deviceManagerGetProfileAddr(mask, &dev_addr)) { /* If address matches device passed in... */ if(BdaddrIsSame(bd_addr, &dev_addr)) result |= mask; } } DEV_DEBUG(("DEV: profiles connected bdaddr %x %x %x Conn Mask %X\n", (uint16)bd_addr->nap,(uint16)bd_addr->uap,(uint16)bd_addr->lap,result)); return result; }
/**************************************************************************** NAME deviceManagerStoreDefaultAttributes DESCRIPTION Stores the default attributes against a given device in PS. RETURNS void */ void deviceManagerStoreDefaultAttributes(const bdaddr* dev_addr, bool is_subwoofer) { sink_attributes attributes; #ifdef ENABLE_SUBWOOFER if (is_subwoofer) { /* Setup and store attributes for the subwoofer device */ sink_attributes attributes; deviceManagerGetDefaultAttributes(&attributes, TRUE); deviceManagerStoreAttributes(&attributes, dev_addr); return; } #endif deviceManagerGetDefaultAttributes(&attributes, FALSE); DEV_DEBUG(("DEV: StoreDefaultAttribs - profiles %d, hfp_vol %d, a2dp_vol %d\n", attributes.profiles, attributes.hfp.volume,attributes.a2dp.volume)); deviceManagerStoreAttributes(&attributes, dev_addr); }
static void pci_dev_init_service(struct device_mem *bar_info, int nr_mapped_bars) { errval_t err; DEV_DEBUG("Initialize device @ [%016lx] with %u bars\n", bar_info->paddr, nr_mapped_bars); if (nr_mapped_bars != 1) { DEV_ERR("number of mapped bars is wrong. Skipping initialization\n"); return; } /* initialize the device */ err = ioat_dma_device_init(*bar_info->frame_cap, &devices[device_count]); if (err_is_fail(err)) { DEV_ERR("Could not initialize the device: %s\n", err_getstring(err)); return; } device_count++; }
errval_t ioat_device_discovery(struct pci_addr addr, enum device_type devtype, uint8_t is_dev_mgr) { errval_t err; uint16_t *dev_ids = NULL; uint16_t dev_cnt = 0; err = pci_client_connect(); if (err_is_fail(err)) { return err; } switch (devtype) { case IOAT_DEVICE_IVB: DEV_DEBUG("Doing device discovery: Ivy Bridge\n"); if (addr.device != 4) { /* the IOAT DMA engine should be on device 4 on Ivy Bridge */ return DMA_ERR_PCI_ADDRESS; } dev_ids = calloc(PCI_DEVICE_IOAT_IVB_CNT, sizeof(uint16_t)); if (dev_ids == NULL) { return LIB_ERR_MALLOC_FAIL; } dev_ids[0] = PCI_DEVICE_IOAT_IVB0; dev_ids[1] = PCI_DEVICE_IOAT_IVB1; dev_ids[2] = PCI_DEVICE_IOAT_IVB2; dev_ids[3] = PCI_DEVICE_IOAT_IVB3; dev_ids[4] = PCI_DEVICE_IOAT_IVB4; dev_ids[5] = PCI_DEVICE_IOAT_IVB5; dev_ids[6] = PCI_DEVICE_IOAT_IVB6; dev_ids[7] = PCI_DEVICE_IOAT_IVB7; dev_ids[8] = PCI_DEVICE_IOAT_IVB8; dev_ids[9] = PCI_DEVICE_IOAT_IVB9; dev_cnt = PCI_DEVICE_IOAT_IVB_CNT; addr.function = 0; break; case IOAT_DEVICE_HSW: DEV_DEBUG("Doing device discovery: Haswell\n"); if (addr.device != 4) { /* the IOAT DMA engine should be on device 4 on Haswell */ return DMA_ERR_PCI_ADDRESS; } dev_ids = calloc(PCI_DEVICE_IOAT_HSW_CNT, sizeof(uint16_t)); if (dev_ids == NULL) { return LIB_ERR_MALLOC_FAIL; } dev_ids[0] = PCI_DEVICE_IOAT_HSW0; dev_ids[1] = PCI_DEVICE_IOAT_HSW1; dev_ids[2] = PCI_DEVICE_IOAT_HSW2; dev_ids[3] = PCI_DEVICE_IOAT_HSW3; dev_ids[4] = PCI_DEVICE_IOAT_HSW4; dev_ids[5] = PCI_DEVICE_IOAT_HSW5; dev_ids[6] = PCI_DEVICE_IOAT_HSW6; dev_ids[7] = PCI_DEVICE_IOAT_HSW7; dev_ids[8] = PCI_DEVICE_IOAT_HSW8; dev_ids[9] = PCI_DEVICE_IOAT_HSW9; dev_cnt = PCI_DEVICE_IOAT_HSW_CNT; addr.function = 0; break; break; default: return DMA_ERR_DEVICE_UNSUPPORTED; break; } devices = calloc(dev_cnt, sizeof(struct ioat_dma_device *)); if (devices == NULL) { free(dev_ids); return LIB_ERR_MALLOC_FAIL; } if (is_dev_mgr == IOAT_DMA_OPERATION_LIBRARY) { err = ioat_mgr_svc_init(); if (err_is_fail(err)) { return err; } } /** * enumerating all the devices * * The devices on Haswell and Ivy Bridge are located on * Bus x, Device 4, Function 0..7 */ for (uint8_t i = 0; i < dev_cnt; ++i) { if (is_dev_mgr == IOAT_DMA_OPERATION_LIBRARY) { /* * discover devices as manager i.e. don't initialize them as they * are handed over to the domains upon request */ err = pci_register_driver_noirq(pci_dev_init_manager, PCI_DONT_CARE, PCI_DONT_CARE, PCI_DONT_CARE, PCI_VENDOR_INTEL, dev_ids[i], addr.bus, addr.device, addr.function + i); } else { /* * discover devices as a service i.e. initialize and map devices */ err = pci_register_driver_irq(pci_dev_init_service, PCI_DONT_CARE, PCI_DONT_CARE, PCI_DONT_CARE, PCI_VENDOR_INTEL, dev_ids[i], addr.bus, addr.device, addr.function + i, handle_device_interrupt, devices[i]); } if (err_is_fail(err)) { if (i == 0) { /* XXX: if a system does not implement all devices listed above, * the registration will fail which is ok. However if it * happens on the first device this is an error. */ return err; } } } DEV_DEBUG("Device discovery done: got %u devices.\n", device_count); free(dev_ids); return SYS_ERR_OK; }
/**************************************************************************** NAME deviceManagerSetPriority DESCRIPTION Set a device's priority in the PDL RETURNS new pdl listId of passed in src addr */ uint8 deviceManagerSetPriority(const bdaddr* dev_addr) { conn_mask mask = deviceManagerProfilesConnected(dev_addr); uint8 ListId = 0; DEV_DEBUG(("DEV: Update PDL/MRU\n")) ; /* more than 1 connected device ? */ if(deviceManagerNumConnectedDevs() > 1) { typed_bdaddr typed_ag_addr; bdaddr ag_addr; sink_attributes attributes; DEV_DEBUG(("DEV: Update MRU - two devices connected\n")) ; /* is this a connection of a2dp or hfp to the already connected primary device ? */ deviceManagerGetIndexedAttributes(0, &attributes, &typed_ag_addr); /* extract bluetooth address from packed structure */ ag_addr = typed_ag_addr.addr; /* check if this is the primary device? */ if(BdaddrIsSame(&ag_addr,dev_addr)) { DEV_DEBUG(("DEV: Update MRU - two devices two profiles connected - primary device\n")) ; ListId = 0; } else { DEV_DEBUG(("DEV: Update MRU - two devices two profiles connected - secondary device\n")) ; /* Move the second device to top of the PDL */ ConnectionSmUpdateMruDevice(dev_addr); /* get bdaddr of the device that was previously the primary device but is now the secondary device */ deviceManagerGetIndexedAttributes(1, &attributes, &typed_ag_addr); /* extract bluetooth address from packed structure */ ag_addr = typed_ag_addr.addr; /* then move the what is now 'secondary device' back to the top of the PDL */ ConnectionSmUpdateMruDevice(&ag_addr); /* this is the secondary device */ ListId = 1; /* send connected event if not already done so */ if(mask && !((mask & conn_hfp)&&(mask & conn_a2dp))) { MessageSend (&theSink.task , EventSecondaryDeviceConnected , NULL ); } } } /* only 1 device so must be primary */ else { /* Move device to top of the PDL */ DEV_DEBUG(("DEV: Update MRU - primary device\n")) ; ConnectionSmUpdateMruDevice(dev_addr); /* if this is the first profile for the device to be connected then send the primary device connected event */ if(mask && !((mask & conn_hfp)&&(mask & conn_a2dp))) { MessageSend (&theSink.task , EventPrimaryDeviceConnected , NULL ); } } /* return current pdl list position of this device which is 0, top of list */ DEV_DEBUG(("DEV: Update MRU - ListId = %x\n",ListId)) ; return ListId; }