Example #1
0
void sniffer_sniff_scan_irq(struct coa_info *dev, int irq)
{
	volatile uint16_t *sc14421_base = dev->sc14421_base;
	int ret;
	uint8_t station[7];

	if (dev->open)
	{
		SC14421_switch_to_bank(sc14421_base, SC14421_RAMBANK1);

		if ( (SC14421_READ(1) & 0xc0) == 0xc0) /* Checksum ok */
		{
			uint8_t rssi = SC14421_READ(0);
			from_dip(fppacket + 5, sc14421_base + 6, 6);

			SC14421_WRITE(1, 0); /* Clear Checksum-Flag */

			if (dect_is_RFPI_Packet(fppacket))
			{

				station[0] = dev->sniffer_config->channel;
				station[1] = rssi;
				memcpy(&station[2], &fppacket[6], 5); /* RFPI */

                                ret = kfifo_in_locked(&dev->rx_fifo, station, 7, &dev->rx_fifo_lock);
				if (ret <= 0)
				{
					printk("com_on_air_cs: rx fifo full? "
                                                "kfifo_in_locked() = %d\n", ret);
				}
			}
		}
	}
}
static ssize_t plp_kmem_write(struct file *filp, const char __user *buf,size_t count, loff_t *pos)
{
	P_SERIAL_DEV *dev= filp->private_data;
	int bytes;
	printk (">>>>>>>>>In write call\n");
	 
	if (kfifo_is_full(&(dev->write_kfifo)))
	{
		if (filp->f_flags & O_NONBLOCK)
			return -EAGAIN;
		else
			wait_event_interruptible(dev->write_queue, !kfifo_is_full(&(dev->write_kfifo))) ;
	}


	if (access_ok (VERIFY_READ, (void __user *) buf, (unsigned long) count))
	{
		bytes = kfifo_in_locked(&(dev->write_kfifo),(void __user *) buf,count,&(dev->wr_spinlock));
			outb (0x03, base_addr + 1); //IER ,enabling Tx & Rx buffer interrupt ERBFI & EXBFI

		return bytes;
	}
	else
		return -EFAULT;
}
Example #3
0
/**
 * usb_serial_generic_write - generic write function for serial USB devices
 * @tty:	Pointer to &struct tty_struct for the device
 * @port:	Pointer to the &usb_serial_port structure for the device
 * @buf:	Pointer to the data to write
 * @count:	Number of bytes to write
 *
 * Returns the number of characters actually written, which may be anything
 * from zero to @count. If an error occurs, it returns the negative errno
 * value.
 */
int usb_serial_generic_write(struct tty_struct *tty,
	struct usb_serial_port *port, const unsigned char *buf, int count)
{
	struct usb_serial *serial = port->serial;
	int result;

	dbg("%s - port %d", __func__, port->number);

	/* only do something if we have a bulk out endpoint */
	if (!port->bulk_out_size)
		return -ENODEV;

	if (count == 0) {
		dbg("%s - write request of 0 bytes", __func__);
		return 0;
	}

	if (serial->type->max_in_flight_urbs)
		return usb_serial_multi_urb_write(tty, port,
						  buf, count);

	count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
	result = usb_serial_generic_write_start(port);

	if (result >= 0)
		result = count;

	return result;
}
Example #4
0
static int pollSwitches(void *unused) {
	while (!kthread_should_stop()) {

		unsigned char value = ioread8(switchesIOBase);
		if (value != lastValue) {
			if (lastValue != -1) {
				// Add new event to queue
				if (!kfifo_in_locked(&events, &value, 1, &eventsLock)) {
					printk(KERN_WARNING MODULE_LABEL "Event buffer is full, new event was ignored!\n");
				}

				//printk("notify wait queue\n");
				wake_up_interruptible_all(&areEventsAvailableWaitQueue);
			}

			lastValue = value;
		}

		if (!kthread_should_stop()) {
			msleep_interruptible(100);
		}
	}

	return 0;
}
Example #5
0
void srp_iu_put(struct iu_entry *iue)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
	kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *));
#else
	kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue,
			sizeof(void *), &iue->target->iu_queue.lock);
#endif
}
Example #6
0
static void tmsi_enqueue_data(struct tmsi_data *dev, const char * buffer, size_t length)
{
    if (length == 0)
        return;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
    kfifo_in_spinlocked(dev->packet_buffer, buffer, length, &dev->buffer_lock);
#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
    kfifo_in_locked(dev->packet_buffer, buffer, length, &dev->buffer_lock);
#else
    kfifo_put(dev->packet_buffer, buffer, length);
#endif
    up(dev->fifo_sem);
}
Example #7
0
/**
 * usb_serial_generic_write - generic write function
 * @tty: tty for the port
 * @port: usb-serial port
 * @buf: data to write
 * @count: number of bytes to write
 *
 * Return: The number of characters buffered, which may be anything from
 * zero to @count, or a negative errno value.
 */
int usb_serial_generic_write(struct tty_struct *tty,
	struct usb_serial_port *port, const unsigned char *buf, int count)
{
	int result;

	if (!port->bulk_out_size)
		return -ENODEV;

	if (!count)
		return 0;

	count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
	result = usb_serial_generic_write_start(port, GFP_ATOMIC);
	if (result)
		return result;

	return count;
}
Example #8
0
/**
 * usb_serial_generic_write - generic write function for serial USB devices
 * @tty:	Pointer to &struct tty_struct for the device
 * @port:	Pointer to the &usb_serial_port structure for the device
 * @buf:	Pointer to the data to write
 * @count:	Number of bytes to write
 *
 * Returns the number of characters actually written, which may be anything
 * from zero to @count. If an error occurs, it returns the negative errno
 * value.
 */
int usb_serial_generic_write(struct tty_struct *tty,
                             struct usb_serial_port *port, const unsigned char *buf, int count)
{
    int result;

    /* only do something if we have a bulk out endpoint */
    if (!port->bulk_out_size)
        return -ENODEV;

    if (!count)
        return 0;

    count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
    result = usb_serial_generic_write_start(port);
    if (result)
        return result;

    return count;
}
Example #9
0
/*
 * V4L2 Subdevice IR Ops
 */
static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
				  bool *handled)
{
	struct cx23888_ir_state *state = to_state(sd);
	struct cx23885_dev *dev = state->dev;
	unsigned long flags;

	u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
	u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
	u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);

	union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
	unsigned int i, j, k;
	u32 events, v;
	int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;

	tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
	rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
	rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
	ror = stats & STATS_ROR; /* Rx FIFO Over Run */

	tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
	rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
	rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
	roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */

	*handled = false;
	v4l2_dbg(2, ir_888_debug, sd, "IRQ Status:  %s %s %s %s %s %s\n",
		 tsr ? "tsr" : "   ", rsr ? "rsr" : "   ",
		 rto ? "rto" : "   ", ror ? "ror" : "   ",
		 stats & STATS_TBY ? "tby" : "   ",
		 stats & STATS_RBY ? "rby" : "   ");

	v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
		 tse ? "tse" : "   ", rse ? "rse" : "   ",
		 rte ? "rte" : "   ", roe ? "roe" : "   ");

	/*
	 * Transmitter interrupt service
	 */
	if (tse && tsr) {
		/*
		 * TODO:
		 * Check the watermark threshold setting
		 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
		 * Push the data to the hardware FIFO.
		 * If there was nothing more to send in the tx_kfifo, disable
		 *	the TSR IRQ and notify the v4l2_device.
		 * If there was something in the tx_kfifo, check the tx_kfifo
		 *      level and notify the v4l2_device, if it is low.
		 */
		/* For now, inhibit TSR interrupt until Tx is implemented */
		irqenable_tx(dev, 0);
		events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
		*handled = true;
	}

	/*
	 * Receiver interrupt service
	 */
	kror = 0;
	if ((rse && rsr) || (rte && rto)) {
		/*
		 * Receive data on RSR to clear the STATS_RSR.
		 * Receive data on RTO, since we may not have yet hit the RSR
		 * watermark when we receive the RTO.
		 */
		for (i = 0, v = FIFO_RX_NDV;
		     (v & FIFO_RX_NDV) && !kror; i = 0) {
			for (j = 0;
			     (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
				v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
				rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
				i++;
			}
			if (i == 0)
				break;
			j = i * sizeof(union cx23888_ir_fifo_rec);
			k = kfifo_in_locked(&state->rx_kfifo,
				      (unsigned char *) rx_data, j,
				      &state->rx_kfifo_lock);
			if (k != j)
				kror++; /* rx_kfifo over run */
		}
		*handled = true;
	}

	events = 0;
	v = 0;
	if (kror) {
		events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
		v4l2_err(sd, "IR receiver software FIFO overrun\n");
	}
	if (roe && ror) {
		/*
		 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
		 * the Rx FIFO Over Run status (STATS_ROR)
		 */
		v |= CNTRL_RFE;
		events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
		v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
	}
	if (rte && rto) {
		/*
		 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
		 * the Rx Pulse Width Timer Time Out (STATS_RTO)
		 */
		v |= CNTRL_RXE;
		events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
	}
	if (v) {
		/* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
		cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
		cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
		*handled = true;
	}

	spin_lock_irqsave(&state->rx_kfifo_lock, flags);
	if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
		events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
	spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);

	if (events)
		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
	return 0;
}
Example #10
0
void srp_iu_put(struct iu_entry *iue)
{
    kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue,
                    sizeof(void *), &iue->target->iu_queue.lock);
}
Example #11
0
void sniffer_sniff_sync_irq(struct coa_info *dev, int irq)
{
	volatile uint16_t *sc14421_base = dev->sc14421_base;
	struct sniffer_cfg *config = dev->sniffer_config;
	struct sniffed_packet packet;
	int ret;
	int slot;
	int a;
	int memofs;

	SC14421_switch_to_bank(sc14421_base, SC14421_RAMBANK1);


	if (!(config->status & SNIFF_STATUS_FOUNDSTATION))
	{
		if (irq & 0x01)
		{
#if 0
			printk("N:");
			for (i=0; i<16; i++)
				printk("%.2x ", SC14421_READ(i));

			printk("\n");
#endif
			if ( (SC14421_READ(1) & 0xc0) == 0xc0) /* Checksum ok */
			{
				SC14421_WRITE(1, 0); /* clear checksum flag */

				from_dip(fppacket + 5,sc14421_base + 6, 6);

				if (dect_compare_RFPI(fppacket, config->RFPI))
				{ 
					printk("found station for sync\n");
					config->status |= SNIFF_STATUS_FOUNDSTATION;

					SC14421_switch_to_bank(sc14421_base,SC14421_CODEBANK);

					switch(dev->radio_type)
					{
					case COA_RADIO_TYPE_II:
						SC14421_write_cmd(sc14421_base, PPFoundII, BR, RecvNextII);
						break;
					case COA_RADIO_TYPE_III:
						SC14421_write_cmd(sc14421_base, PPFoundIII, BR, RecvNextIII);
						break;
					default:
						printk("ERROR: this radio type is currently not "
								"supported. please update the driver\n");
					}
				}
			}
		}
	}
	else if (!(config->status & SNIFF_STATUS_INSYNC))
	{
		if (irq & 0x01)
		{

#if 0
			printk("S:");	
			for (i=0; i<16; i++)
				printk("%.2x ", SC14421_READ(i));
			printk("\n");
#endif
			if ( (SC14421_READ(1) & 0xc0) == 0xc0) /* Checksum ok */
			{
				SC14421_WRITE(1, 0); /* clear checksum flag */
				from_dip(fppacket + 5, sc14421_base + 6, 48);

				slot = dect_get_slot(fppacket);
				if (slot != -1)
				{
					printk("station in slot %u\n", slot);
					config->status |= SNIFF_STATUS_INSYNC;
					slot %= 12;
					if (slot%2)
						printk("slot not possible with this firmware\n");

					config->slottable[slot].active = 1;
					config->slottable[slot].channel = config->channel;
					config->slottable[slot].type = DECT_SLOTTYPE_CARRIER;
					config->slottable[slot].errcnt = 0;

					sniffer_sync_patchloop(dev,config->slottable,SNIFF_SLOTPATCH_FP);
					sniffer_sync_patchloop(dev,config->slottable,SNIFF_SLOTPATCH_PP);

					SC14421_switch_to_bank(sc14421_base,SC14421_CODEBANK);

					printk("set jump to %u\n",sync_jumptable[slot]);

					switch(dev->radio_type)
					{
					case COA_RADIO_TYPE_II:
						SC14421_write_cmd(sc14421_base,PPFoundII,BR,sync_jumptable[slot]);
						break;
					case COA_RADIO_TYPE_III:
						SC14421_write_cmd(sc14421_base,PPFoundIII,BR,sync_jumptable[slot]);
						break;
					default:
						printk("ERROR: this radio type is currently not "
								"supported. please update the driver\n");
					}

					printk("we are in sync :)\n");



					packet.rssi = SC14421_READ(0x00);
					packet.channel = config->channel;
					packet.slot = slot;
					memcpy(packet.data, fppacket, 53);

					packet.timestamp = dev->irq_timestamp;
                                        ret = kfifo_in_locked(&dev->rx_fifo,(unsigned char*) &packet,sizeof(struct sniffed_packet), &dev->rx_fifo_lock);
					if (ret <= 0)
						printk("com_on_air_cs: rx fifo "
                                                        "full? kfifo_in_locked() "
							"= %d\n", ret);
				}
			}
		}
	}
	else
	{
		if ( (irq & 0x09) == 0x09)
			printk("com_on_air-cs: interrupt processing too slow , lost packets!\n");

		if (irq & 0x01)
		{

			for (a=0; a<12; a++)
			{
				if (config->slottable[a].active)
				{
					SC14421_switch_to_bank(sc14421_base,sync_banktable[a]);

					if ( (a/2) % 2)
						memofs = 0x80;
					else
						memofs = 0x00;

#if 0
						printk("F:");
			        		for (i=0; i<16; i++)
			        		        printk("%.2x ",(unsigned char) SC14421_READ(i+memofs));

			        		printk("  : %.2x : %x\n", irq, a);
#endif

					if ( (SC14421_READ(1+memofs) & 0xc0) == 0xc0) /* Checksum ok */
					{
						unsigned char bfok = ((SC14421_READ(1+memofs) & 0x03) == 0x03)<<7; /* BField Checksum ok */

						struct sniffed_packet packet;
						packet.rssi = SC14421_READ(memofs);
						packet.channel = config->slottable[a].channel;
						packet.slot = a;
						memcpy(packet.data,fppacket,5);

						from_dip(&packet.data[5],sc14421_base+memofs+6,	48);

						if (config->slottable[a].type == DECT_SLOTTYPE_SCAN)
							/* we received data on a scan-slot,
							 * channel is incemented before,
							 * but we want hear the old channel */
						{
							packet.channel--;
							//printk("slot in scanmode\n");
						}

						if (dect_is_multiframe_number(packet.data))
							/* if there was a multiframe number,
							 * then this packet was in frame 8 (0) */
						{
							//printk("found multiframe number\n");
							config->framenumber = 1;
						}

						/* if (dev->open) */
						{
							if(config->framenumber)
								packet.frameflags = (config->framenumber-1)|bfok;
							else
								packet.frameflags = 7|bfok;

							packet.timestamp = dev->irq_timestamp;
                                                        ret = kfifo_in_locked(&dev->rx_fifo, (unsigned char*) &packet, sizeof(struct sniffed_packet), &dev->rx_fifo_lock);
							if (ret <= 0)
							{
                                                                printk("com_on_air_cs: rx fifo full? kfifo_in_locked() = %d\n", ret);
							}
						}



#if 0
						printk("F:");
			        		for (i=0; i<16; i++)
			        		        printk("%.2x ", SC14421_READ(i+memofs));

			        		printk("  : %.2x : %x\n", irq, a);
#endif
						SC14421_WRITE(1+memofs, 0);	/* clear checksum flag */


						if (dect_update_slottable(config->slottable, a, packet.data))
						{
							config->updateppslots = 1;
							config->updatefpslots = 1;
							//printk("new slot , must update slots\n");
						}

					}
					else
					{
						if (dect_receive_error(config->slottable, a))
						{
							config->updateppslots = 1;
							config->updatefpslots = 1;
							//printk("1:died slot , must update slots\n");
						}
					}
				}
			}

			if ( (!(irq & 0x08)) && (config->updatefpslots) )
			{
				//printk("patching fp slots\n");
				sniffer_sync_patchloop(dev, config->slottable, SNIFF_SLOTPATCH_FP);
				config->updatefpslots = 0;
			}

		}

		if (irq & 0x08)
		{

			for (a=12; a<24; a++)
			{
				if (config->slottable[a].active)
				{

					SC14421_switch_to_bank(sc14421_base, sync_banktable[a]);

					if ( (a/2) % 2)
						memofs = 0x80;
					else
						memofs = 0x00;

					if ( (SC14421_READ(1+memofs) & 0xc0) == 0xc0)		/* Checksum ok */
					{
						unsigned char bfok = ((SC14421_READ(1+memofs) & 0x03) == 0x03)<<7; /* BField Checksum ok */

						struct sniffed_packet packet;
						packet.rssi = SC14421_READ(memofs);
						packet.channel = config->slottable[a].channel;
						packet.slot = a;
						memcpy(packet.data, pppacket, 5);
						from_dip(&packet.data[5], sc14421_base+memofs+6, 48);
						if (config->slottable[a].type == DECT_SLOTTYPE_SCAN)
						{
							packet.channel--;
							//printk("slot in scanmode\n");
						}

						/* if (dev->open) */
						{
							if(config->framenumber)
								packet.frameflags = (config->framenumber-1)|bfok;
							else
								packet.frameflags = 7|bfok;

							packet.timestamp = dev->irq_timestamp;
                                                        ret = kfifo_in_locked(
                                                                &dev->rx_fifo,
								(unsigned char*) &packet,
                                                                sizeof(struct sniffed_packet),
                                                                &dev->rx_fifo_lock);
							if (ret <= 0)
							{
                                                                printk("com_on_air_cs: rx fifo full? kfifo_in_locked() = %d\n", ret);
							}
						}


#if 0
						printk("F:");
			        		for (i=0; i<16; i++)
			        		        printk("%.2x ", SC14421_READ(i+memofs));

			        		printk("  : %.2x : %x\n", irq, a);
#endif

						SC14421_WRITE(1+memofs, 0);	/* clear checksum flag */


						if (dect_update_slottable(config->slottable, a, packet.data))
						{
							config->updateppslots = 1;
							config->updatefpslots = 1;
							//printk("new slot , must update slots\n"); 
						}

					}
					else
					{
						if (dect_receive_error(config->slottable, a))
						{
							config->updateppslots = 1;
							config->updatefpslots = 1;
							//printk("8:died slot , must update slots\n"); 
						}
					}

				}

			}

			if ( (!(irq & 0x01)) && (config->updateppslots) )
			{
				//printk("patching pp slots\n");
				sniffer_sync_patchloop(dev, config->slottable, SNIFF_SLOTPATCH_PP);
				config->updateppslots = 0;
			}

			if (dect_update_scanchannels(config->slottable))
			{
				config->updateppslots = 1;
				config->updatefpslots = 1;
				//printk("new slot , must update slots\n");
			}

			if (config->framenumber >= 7)
				config->framenumber = 0;
			else
				config->framenumber++;
		}

	}
}
irqreturn_t pseudo_serial_intr_handler(int irq_no, void *p_dev)
{
	int ret_val,i,j;
	irqreturn_t irq_r_flag=0;
	P_SERIAL_DEV *dev = (P_SERIAL_DEV *)p_dev;
	char lk_buff[HW_FIFO_SIZE];
	
	irq_r_flag |= IRQ_NONE;

printk("\n\n>in irqreturn_t...!\n");
	if(inb(base_addr+0x05) & 0x20) 		//comparing for Tx interrupt
	{
	printk("\n>in irqreturn_t    Tx interrupt...!\n");

		outb (0x01, base_addr + 1); //IER ,disabling Tx & enabling Rx buffer interrupt ERBFI & EXBFI
		
		//copying the data into local buffer from the kfifo buffer

		ret_val = kfifo_out_locked(&(dev->write_kfifo),lk_buff,HW_FIFO_SIZE, &(dev->wr_spinlock));

		printk("\n>in irqreturn_t    Tx interrupt   ret_val = kfifo_out_locked  %d...!\n", ret_val);
		if(ret_val > 0)
		{
			for(i = 0; i < ret_val ; i++)
				outb(lk_buff[i], base_addr+0x00);
		}
		
		wake_up_interruptible (&(dev->write_queue));
	  
		irq_r_flag |= IRQ_HANDLED; 
	}	


	if(inb(base_addr+0x05) & 0x01) 		//comparing for Rx interrupt
	{

	printk("\n>in irqreturn_t    Rx interrupt...!\n");

		for(j=0;j<16;j++)
		{
			if(inb(base_addr+0x05) & 0x01)
			{
				lk_buff[j] = inb(base_addr+0x00);
			}
			else
				break;
		}

		//copying the data from local buffer onto the kfifo buffer

		if(kfifo_is_full(&(dev->read_kfifo)))
			dropped += j;
		else
		{
			kfifo_in_locked(&(dev->read_kfifo),lk_buff,j,&(dev->rd_spinlock));
			received += j;
		}
	
		wake_up_interruptible(&(dev->read_queue));
	  
		irq_r_flag |= IRQ_HANDLED; 
	}

	

	return irq_r_flag; 
}
void AUDIO_Ctrl_Process(
	BRCM_AUDIO_ACTION_en_t action_code,
	void *arg_param,
	void *callback,
    int  block
	)
{
   	TMsgAudioCtrl	msgAudioCtrl;
	unsigned int	len;
	AUDIO_DRIVER_TYPE_t drv_type;
    UInt32 app_profile = 0 ;
	static AudioApp_t prev_app_profile = 0;
	static AudioMode_t prev_mode_profile = 0;
	static bool mode_restore = FALSE;

	if(arg_param == NULL)
	{
		DEBUG("AUDIO_Ctrl_Process: arg_param is NULL \n");
		return;
	}
    switch (action_code)
    {
        case ACTION_AUD_StartPlay:
        {
            BRCM_AUDIO_Param_Start_t* param_start = (BRCM_AUDIO_Param_Start_t*) arg_param;
            
		//20110905 	//prev_app_profile = AUDDRV_GetAudioApp();
            app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_MUSIC);

            AUDIO_DRIVER_Ctrl(param_start->drv_handle,AUDIO_DRIVER_START,NULL);

            AUDIO_DRIVER_Ctrl(param_start->drv_handle,AUDIO_DRIVER_GET_DRV_TYPE,(void*)&drv_type);

            if (AUDIO_Policy_GetState() == BRCM_STATE_INCALL)
            {
                DEBUG("Play Music During Voice call \n");
                musicduringcall = TRUE;
                if ( sgTableIDChannelOfDev[param_start->substream_number].speaker == AUDCTRL_SPK_HEADSET ||
                     sgTableIDChannelOfDev[param_start->substream_number].speaker == AUDCTRL_SPK_BTM )
                {
                    DEBUG("Play Music During Voice call to HEADSET or BTM\n");
                    if ( app_profile == AUDIO_APP_VOICE_CALL )
                    {
                        DEBUG(" Play music during Voice call with BT Tap at 8k \r\n");
                        AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_BTM, 8000);
                    }
                    else
                    {
                        DEBUG(" Play music during Voice call with BT Tap at 16k \r\n");
                        if ( sgTableIDChannelOfDev[param_start->substream_number].speaker == AUDCTRL_SPK_BTM )
                        {
                            AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_BTM, 8000);
                        }
                        else
                        {
                            AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_BTM, 16000);
                        }
                    }

                    AUDCTRL_EnablePlay(AUDIO_HW_NONE,
                                       sgTableIDChannelOfDev[param_start->substream_number].hw_id,
                                       AUDIO_HW_TAP_VOICE,
                                       AUDCTRL_SPK_BTM,
                                       param_start->channels,
                                       param_start->rate
                                      );
                }
                else
                {
                    DEBUG("Play Music During Voice call to HANDSET or LOUDSPEAKER\n");
                    if ( app_profile == AUDIO_APP_VOICE_CALL )
                    {
                        DEBUG(" Play music during Voice call with BT Tap at 8k \r\n");
                        AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_HEADSET, 8000);
                    }
                    else
                    {
                        DEBUG(" Play music during Voice call with BT Tap at 16k \r\n");
                        AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_HEADSET, 16000);
                    }

                    AUDCTRL_EnablePlay(AUDIO_HW_NONE,
                                       sgTableIDChannelOfDev[param_start->substream_number].hw_id,
                                       AUDIO_HW_TAP_VOICE,
                                       AUDCTRL_SPK_HEADSET,
                                       param_start->channels,
                                       param_start->rate
                                      );
                }
            }
            else
            {
               	AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfDev[param_start->substream_number].speaker,app_profile);
            
                if( sgTableIDChannelOfDev[param_start->substream_number].speaker == AUDCTRL_SPK_BTM )
                {
                    AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, sgTableIDChannelOfDev[param_start->substream_number].speaker, 8000);

                    // Enable the playback the path
                    AUDCTRL_EnablePlay(AUDIO_HW_NONE,
                                       sgTableIDChannelOfDev[param_start->substream_number].hw_id,
                                       AUDIO_HW_TAP_VOICE,
                                       sgTableIDChannelOfDev[param_start->substream_number].speaker,
                                       param_start->channels,
                                       param_start->rate
				      );
                }
                else
                {
                    // Enable the playback the path
                    AUDCTRL_EnablePlay(AUDIO_HW_NONE,
                                       sgTableIDChannelOfDev[param_start->substream_number].hw_id,
                                       AUDIO_HW_NONE,
                                       sgTableIDChannelOfDev[param_start->substream_number].speaker,
                                       param_start->channels,
                                       param_start->rate
                                      );

                    //if (param_start->substream_number == 5)  // Ring case
                    if(extra_speaker)
                    {
                        DEBUG("Play to speaker as well \n");
                        AUDCTRL_AddPlaySpk(sgTableIDChannelOfDev[param_start->substream_number].hw_id, //		AUDIO_HW_ID_t			sink,
                                           AUDCTRL_SPK_LOUDSPK                 //          AUDCTRL_SPEAKER_t		spk
                                          );
                    }
                }
            }

            // set the slopgain register to max value
            AUDCTRL_SetPlayVolume(sgTableIDChannelOfDev[param_start->substream_number].hw_id,
                                  sgTableIDChannelOfDev[param_start->substream_number].speaker,
                                  AUDIO_GAIN_FORMAT_VOL_LEVEL,
                                  AUDIO_VOLUME_MAX,
                                  AUDIO_VOLUME_MAX
                                 );

            // start DMA now
            AUDIO_DRIVER_Ctrl(param_start->drv_handle,AUDIO_DRIVER_RESUME,NULL);

            playback_prev_time = 0;
            playback_triggered = 1;

        }
        break;
        case ACTION_AUD_StopPlay:
        {
            BRCM_AUDIO_Param_Stop_t* param_stop = (BRCM_AUDIO_Param_Stop_t*) arg_param;

            // stop DMA first
            AUDIO_DRIVER_Ctrl(param_stop->drv_handle,AUDIO_DRIVER_PAUSE,NULL);

            AUDIO_DRIVER_Ctrl(param_stop->drv_handle,AUDIO_DRIVER_GET_DRV_TYPE,(void*)&drv_type);
            //if (param_stop->substream_number == 5)  // Ring case
            if(extra_speaker)
            {
		            DEBUG(" REMOVING  LOUDSPK  \n");				  
                    AUDCTRL_RemovePlaySpk(sgTableIDChannelOfDev[param_stop->substream_number].hw_id, //		AUDIO_HW_ID_t			sink,
									  AUDCTRL_SPK_LOUDSPK				  //		  AUDCTRL_SPEAKER_t 	spk
                    );
            }

		//20110905	//AUDCTRL_SaveAudioModeFlag( AUDDRV_GetAudioMode(), prev_app_profile );

            //disable the playback path
            if (AUDIO_Policy_GetState() == BRCM_STATE_INCALL)
            {
                musicduringcall = FALSE;
                if ( sgTableIDChannelOfDev[param_stop->substream_number].speaker == AUDCTRL_SPK_HEADSET ||
                     sgTableIDChannelOfDev[param_stop->substream_number].speaker == AUDCTRL_SPK_BTM )
                {
                    AUDCTRL_DisablePlay(AUDIO_HW_NONE,
                                        sgTableIDChannelOfDev[param_stop->substream_number].hw_id,
                                        AUDCTRL_SPK_BTM
                                       );
                }
                else
                {
                    AUDCTRL_DisablePlay(AUDIO_HW_NONE,
                                        sgTableIDChannelOfDev[param_stop->substream_number].hw_id,
                                        AUDCTRL_SPK_HEADSET
                                       );
                }
                AUDCTRL_DisableTap (AUDIO_HW_TAP_VOICE);
            }
            else
            {
                if( sgTableIDChannelOfDev[param_stop->substream_number].speaker == AUDCTRL_SPK_BTM )
                {
                    AUDCTRL_DisablePlay(AUDIO_HW_NONE,
                                        sgTableIDChannelOfDev[param_stop->substream_number].hw_id,
                                        sgTableIDChannelOfDev[param_stop->substream_number].speaker
                                       );

                    AUDCTRL_DisableTap (AUDIO_HW_TAP_VOICE);
                }
                else
                {
                    AUDCTRL_DisablePlay(AUDIO_HW_NONE,
                                        sgTableIDChannelOfDev[param_stop->substream_number].hw_id,
                                        sgTableIDChannelOfDev[param_stop->substream_number].speaker
                                       );
                }
            }
            AUDIO_DRIVER_Ctrl(param_stop->drv_handle,AUDIO_DRIVER_STOP,NULL);

            playback_prev_time = 0;
            playback_triggered = 0;

            

        }
        break;
        case ACTION_AUD_PausePlay:
        {
            BRCM_AUDIO_Param_Pause_t* param_pause = (BRCM_AUDIO_Param_Pause_t*) arg_param;

            AUDIO_DRIVER_Ctrl(param_pause->drv_handle,AUDIO_DRIVER_GET_DRV_TYPE,(void*)&drv_type);

            //disable the playback path
             AUDCTRL_DisablePlay(AUDIO_HW_NONE,
                        sgTableIDChannelOfDev[param_pause->substream_number].hw_id,
                        sgTableIDChannelOfDev[param_pause->substream_number].speaker
                    );

            if( sgTableIDChannelOfDev[param_pause->substream_number].speaker == AUDCTRL_SPK_BTM )
            {
                AUDCTRL_DisableTap (AUDIO_HW_TAP_VOICE);
            }
            AUDIO_DRIVER_Ctrl(param_pause->drv_handle,AUDIO_DRIVER_PAUSE,NULL);
        }
        break;

        case ACTION_AUD_ResumePlay:
        {
            BRCM_AUDIO_Param_Resume_t* param_resume = (BRCM_AUDIO_Param_Resume_t*) arg_param;

            AUDIO_DRIVER_Ctrl(param_resume->drv_handle,AUDIO_DRIVER_GET_DRV_TYPE,(void*)&drv_type);

            AUDIO_DRIVER_Ctrl(param_resume->drv_handle,AUDIO_DRIVER_RESUME,NULL);

            if( sgTableIDChannelOfDev[param_resume->substream_number].speaker == AUDCTRL_SPK_BTM )
            {
                AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, sgTableIDChannelOfDev[param_resume->substream_number].speaker, param_resume->rate);

                // Enable the playback the path
                AUDCTRL_EnablePlay(AUDIO_HW_NONE,
                                   sgTableIDChannelOfDev[param_resume->substream_number].hw_id,
                                   AUDIO_HW_TAP_VOICE,
                                   sgTableIDChannelOfDev[param_resume->substream_number].speaker,
				                   param_resume->channels,
                                   param_resume->rate
				    );
            }
            else
            {
                // Enable the playback the path
                AUDCTRL_EnablePlay(AUDIO_HW_NONE,
                                   sgTableIDChannelOfDev[param_resume->substream_number].hw_id,
                                   AUDIO_HW_NONE,
                                   sgTableIDChannelOfDev[param_resume->substream_number].speaker,
				                   param_resume->channels,
                                   param_resume->rate
				    );
            }
        }
        break;
        case ACTION_AUD_StartRecord:
        {
            AudioApp_t app_prof = AUDIO_APP_RECORDING;
            AudioMode_t  new_mode = AUDIO_MODE_SPEAKERPHONE;
            AudioMode_t cur_mode;

            BRCM_AUDIO_Param_Start_t* param_start = (BRCM_AUDIO_Param_Start_t*) arg_param;
            DEBUG("ACTION_AUD_StartRecord : param_start->substream_number -  %d \n",param_start->substream_number);

			prev_app_profile = AUDDRV_GetAudioApp();
            cur_mode = AUDCTRL_GetAudioMode();

            if ( cur_mode >= AUDIO_MODE_NUMBER )
                cur_mode = (AudioMode_t) (cur_mode - AUDIO_MODE_NUMBER);

            if (param_start->substream_number == 6 || param_start->substream_number == 7) // record request with Google voice search profile
			{
                app_prof = AUDIO_APP_RECORDING_GVS;
				mode_restore = TRUE;
				prev_mode_profile = cur_mode;
				DEBUG("ACTION_AUD_StartRecord : [%d, %d]", prev_app_profile, prev_mode_profile);
			}

            if (param_start->substream_number == 9 || param_start->substream_number == 10) // record request with voip profile
            {
				app_prof = AUDIO_APP_VOIP;
                new_mode = cur_mode; // use current mode based on earpiece or speaker
            }
            
            if (param_start->substream_number == 11 || param_start->substream_number == 12) // record request with voip incomm profile
            {
				app_prof = AUDIO_APP_VOIP_INCOMM;
                new_mode = cur_mode; // use current mode based on earpiece or speaker
            }

            if (param_start->substream_number == 1 || param_start->substream_number == 7  || param_start->substream_number == 8 
                || param_start->substream_number == 10 || param_start->substream_number == 12) // record request with auxilary mic
                new_mode = AUDIO_MODE_HEADSET;

            app_profile = AUDIO_Policy_Get_Profile(app_prof);
            new_mode = AUDIO_Policy_Get_Mode(new_mode);
            AUDCTRL_SaveAudioModeFlag(new_mode,app_profile);

            AUDCTRL_EnableRecord(sgTableIDChannelOfCaptDev[param_start->substream_number].hw_id,
				                     AUDIO_HW_NONE,
                                     sgTableIDChannelOfCaptDev[param_start->substream_number].mic,
				                     param_start->channels,
                                     param_start->rate);

            AUDIO_DRIVER_Ctrl(param_start->drv_handle,AUDIO_DRIVER_START,NULL);

             AUDIO_Policy_SetState(BRCM_STATE_RECORD);

        }
        break;
        case ACTION_AUD_StopRecord:
        {
            BRCM_AUDIO_Param_Stop_t* param_stop = (BRCM_AUDIO_Param_Stop_t*) arg_param;
               
            AUDIO_DRIVER_Ctrl(param_stop->drv_handle,AUDIO_DRIVER_STOP,NULL);

			if (mode_restore)
			{
				mode_restore = FALSE;
				AUDCTRL_SaveAudioModeFlag( prev_mode_profile, prev_app_profile );
				DEBUG("ACTION_AUD_StartRecord : [%d, %d]", prev_app_profile, prev_mode_profile);
			}
			else
			{
				AUDCTRL_SaveAudioModeFlag( AUDDRV_GetAudioMode(), prev_app_profile );
			}

            AUDCTRL_DisableRecord(sgTableIDChannelOfCaptDev[param_stop->substream_number].hw_id,
                                      AUDIO_HW_NONE,
                                      sgTableIDChannelOfCaptDev[param_stop->substream_number].mic);

            AUDIO_Policy_RestoreState();

        }
	break;
        case ACTION_AUD_OpenPlay:
        {
            BRCM_AUDIO_Param_Open_t* param_open = (BRCM_AUDIO_Param_Open_t*) arg_param;

            param_open->drv_handle = AUDIO_DRIVER_Open(sgTableIDChannelOfDev[param_open->substream_number].drv_type);

            DEBUG("param_open->drv_handle -  0x%x \n",param_open->drv_handle);

        }
        break;
        case ACTION_AUD_ClosePlay:
        {
            BRCM_AUDIO_Param_Close_t* param_close = (BRCM_AUDIO_Param_Close_t*) arg_param;

            DEBUG("param_close->drv_handle -  0x%x \n",param_close->drv_handle);

            AUDIO_DRIVER_Close(param_close->drv_handle);

        }
        break;

	case ACTION_AUD_OpenRecord:
        {
            BRCM_AUDIO_Param_Open_t* param_open = (BRCM_AUDIO_Param_Open_t*) arg_param;

            param_open->drv_handle = AUDIO_DRIVER_Open(sgTableIDChannelOfCaptDev[param_open->substream_number].drv_type);

            DEBUG("param_open->drv_handle -  0x%x \n",param_open->drv_handle);

        }
        break;

        case ACTION_AUD_CloseRecord:
        {
            BRCM_AUDIO_Param_Close_t* param_close = (BRCM_AUDIO_Param_Close_t*) arg_param;

            DEBUG("param_close->drv_handle -  0x%x \n",param_close->drv_handle);

            AUDIO_DRIVER_Close(param_close->drv_handle);

        }
        break;


        case ACTON_VOICECALL_START:
        {
            BRCM_VOICE_Param_Start_t* param_voice_start = (BRCM_VOICE_Param_Start_t*)arg_param;
            int vol_level;

            telephony_stream_number = param_voice_start->substream_number;

            if ( telephony_codecId == 10 )
            {
                DEBUG("Enable telephony WB Call \r\n");
                app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL_WB);
                AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].speaker + AUDIO_MODE_NUMBER,app_profile);
            }
            else if ( telephony_codecId == 6 )
            {
                DEBUG("Enable telephony NB Call \r\n");
                app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL);
                AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].speaker,app_profile);
            }
            else
            {
                DEBUG("Enable telephony Invalid Codec : Setting as NB \r\n");
                app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL);
                AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].speaker,app_profile);
            }

            if ( (telephony_stream_number-VOICE_CALL_SUB_DEVICE) == 4 )
            {
		if ( telephony_codecId == 10 )
            	{
                	DEBUG("Enable telephony WB Call for BT NREC \r\n");
                	app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL_WB);
                	AUDCTRL_SaveAudioModeFlag(AUDCTRL_SPK_HANDSFREE, app_profile);
            	}
            	else if ( telephony_codecId == 6 )
            	{
                	DEBUG("Enable telephony NB Call BT NREC \r\n");
                	app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL);
                	AUDCTRL_SaveAudioModeFlag(AUDCTRL_SPK_HANDSFREE, app_profile);
            	}

                DEBUG(" Telephony : Turning Off EC and NS \r\n");
                //AUDCTRL_EC(FALSE, 0);
                //AUDCTRL_NS(FALSE);
            }
            else
            {
                DEBUG(" Telephony : Turning On EC and NS \r\n");
                //AUDCTRL_EC(TRUE, 0);
                //AUDCTRL_NS(TRUE);
            }

            vol_level= GetCtrlValue(BRCM_CTL_EAR_Playback_Volume);
            if(vol_level > 5)
                vol_level = 5;
            AUDCTRL_SetPlayVolume(AUDIO_HW_VOICE_OUT,AUDCTRL_SPK_HANDSET,AUDIO_GAIN_FORMAT_DSP_VOICE_VOL_GAIN,vol_level,vol_level);

            AUDCTRL_RateChangeTelephony();
            AUDCTRL_EnableTelephony(AUDIO_HW_VOICE_IN,AUDIO_HW_VOICE_OUT,sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].mic,sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].speaker);
            telephony_started = 1;

	        if(TRUE==GetCtrlValue(BRCM_CTL_Mic_Capture_Mute))
            {
                DEBUG("Muting device \r\n");
			    AUDCTRL_SetTelephonyMicMute(AUDIO_HW_VOICE_OUT,AUDCTRL_MIC_MAIN,TRUE);;
            }
            AUDIO_Policy_SetState(BRCM_STATE_INCALL);


        }
        break;

        case ACTON_VOICECALL_STOP:
        {
            BRCM_VOICE_Param_Stop_t* param_voice_stop = (BRCM_VOICE_Param_Stop_t*)arg_param;

            telephony_stream_number = param_voice_stop->substream_number;

            DEBUG("DISABLE TELEPHONY substream = %d \r\n", telephony_stream_number);
            AUDCTRL_DisableTelephony(AUDIO_HW_VOICE_IN,AUDIO_HW_VOICE_OUT,sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].mic,sgTableIDChannelOfVoiceCallDev[telephony_stream_number-VOICE_CALL_SUB_DEVICE].speaker);
            telephony_started = 0;
             AUDIO_Policy_RestoreState();
        }
        break;

        case ACTON_VOICECALL_UPDATE:
        {
            int local_sub_stream_number = 0;
            BRCM_VOICE_Param_Update_t* param_voice_update = (BRCM_VOICE_Param_Update_t*)arg_param;

            DEBUG("TELEPHONY UPDATE codecId = %d \r\n", param_voice_update->voicecall_codecId);

            if ( telephony_codecId != param_voice_update->voicecall_codecId )
            {
                telephony_codecId = param_voice_update->voicecall_codecId;

                if (telephony_started)
                {
                    if ( telephony_codecId == 10 )
                    {
                        app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL_WB);
                        DEBUG("call_CodedId_hander : changing Mode to AMR-WB ===>\r\n");
                        AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfVoiceCallDev[telephony_stream_number - VOICE_CALL_SUB_DEVICE].speaker + AUDIO_MODE_NUMBER,app_profile);
                        DEBUG("call_CodedId_hander : changing Mode to AMR-WB <===\r\n");
                    }
                    else
                    {
                        app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_VOICE_CALL);
                        DEBUG("call_CodedId_hander : changing Mode to AMR-NB ===>\r\n");
                        AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfVoiceCallDev[telephony_stream_number - VOICE_CALL_SUB_DEVICE].speaker,app_profile );
                        DEBUG("call_CodedId_hander : changing Mode to AMR-NB <===\r\n");
                    }
                    DEBUG("call_CodedId_hander : AUDCTRL_RateChangeTelephony ===>\r\n");
                    if ( musicduringcall == TRUE )
                    {
                        local_sub_stream_number = (telephony_stream_number - VOICE_CALL_SUB_DEVICE)*2;
                        // wired headphone
                        if(telephony_stream_number == 17)
                        {
                            // set the substream number to same as headset
                            local_sub_stream_number = 4;
                        }

                        AUDCTRL_DisableTap (AUDIO_HW_TAP_VOICE);
                        if ( app_profile == AUDIO_APP_VOICE_CALL )
                        {
                            
                            AUDCTRL_RateChangeTelephony();
                            if( sgTableIDChannelOfDev[local_sub_stream_number].speaker == AUDCTRL_SPK_HEADSET ||
                                sgTableIDChannelOfDev[local_sub_stream_number].speaker == AUDCTRL_SPK_BTM )
                            {
                                AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_BTM, 8000);
                            }
                            else
                            {
                                AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_HEADSET, 8000);
                            }
                        }
                        else
                        {
                            AUDCTRL_RateChangeTelephony();
                            if( sgTableIDChannelOfDev[local_sub_stream_number].speaker == AUDCTRL_SPK_HEADSET )
                            {
                                AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_BTM, 16000);
                            }
                            else if ( sgTableIDChannelOfDev[local_sub_stream_number].speaker == AUDCTRL_SPK_BTM )
                            {
                                AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_BTM, 8000);
                            }
                            else
                            {
                                AUDCTRL_EnableTap (AUDIO_HW_TAP_VOICE, AUDCTRL_SPK_HEADSET, 16000);
                            }
                        }
                    }
                    else
                    {
                        AUDCTRL_RateChangeTelephony();
                    }
                    DEBUG("call_CodedId_hander : AUDCTRL_RateChangeTelephony <===\r\n");
                }
            }
        }
        break;
		
        case ACTON_FM_START:
        {
	    BRCM_FM_Param_Start_t* param_start = (BRCM_FM_Param_Start_t*) arg_param;
        app_profile = AUDIO_Policy_Get_Profile(AUDIO_APP_FM);
			
      	    AUDCTRL_SaveAudioModeFlag( sgTableIDChannelOfDev[param_start->substream_number].speaker,app_profile);
                			
	        // Enable the FM playback the path
            AUDCTRL_EnablePlay(AUDIO_HW_I2S_IN,
				sgTableIDChannelOfDev[param_start->substream_number].hw_id,
				AUDIO_HW_NONE,
				sgTableIDChannelOfDev[param_start->substream_number].speaker,
				param_start->channels,
				param_start->rate
						);
            // set the slopgain register to max value
            // 20110530 FM radio volume is controlled by FM radio chip.
            AUDCTRL_SetPlayVolume(sgTableIDChannelOfDev[param_start->substream_number].hw_id,
				  sgTableIDChannelOfDev[param_start->substream_number].speaker,
				  AUDIO_GAIN_FORMAT_FM_RADIO_DIGITAL_VOLUME_TABLE,
				  AUDIO_VOLUME_MAX,
				  AUDIO_VOLUME_MAX 
						);

            AUDIO_Policy_SetState(BRCM_STATE_FM);

	    }
        break;
		
        case ACTON_FM_STOP:
        {

            BRCM_FM_Param_Stop_t* param_fm_stop = (BRCM_FM_Param_Stop_t*)arg_param;
	
            //disable the FM playback path
            AUDCTRL_DisablePlay(AUDIO_HW_I2S_IN,
				  sgTableIDChannelOfDev[param_fm_stop->substream_number].hw_id,
				  sgTableIDChannelOfDev[param_fm_stop->substream_number].speaker
						 );
            AUDIO_Policy_RestoreState();
        }
        break;
        case  ACTON_ROUTE:
            {
                BRCM_AUDIO_Param_Route_t* parm_route = (BRCM_AUDIO_Param_Route_t*)arg_param;
                 DEBUG("ACTON_ROUTE  \n");			
                

                if(playback_triggered == 1){

                    if(parm_route->command == 1)
                    {
                        DEBUG(" ADDING  SPK - %d  \n",parm_route->speaker);				  
                        AUDCTRL_AddPlaySpk(AUDIO_HW_PLR_OUT,
                                               parm_route->speaker
                                              );
                        extra_speaker = 1;

                    }
                    else if (parm_route->command == 0)
                    {
             
                        DEBUG(" REMOVING  SPK - %d  \n",parm_route->speaker);				  
                        AUDCTRL_RemovePlaySpk(AUDIO_HW_PLR_OUT, 
									      parm_route->speaker	
                        );

                        extra_speaker = 0;
                    }
                }
                else
                {
                    if(parm_route->command == 1)
                        extra_speaker = 1;
                    else if (parm_route->command == 0)
                        extra_speaker = 0;
                }
            }
            break;
        default:
            DEBUG("Error AUDIO_Ctrl_Process Invalid acction command \n");
    }
    if(block)
    {
        // put the message in output fifo if waiting
        msgAudioCtrl.action_code = action_code;
	    if(arg_param)
		    memcpy(&msgAudioCtrl.param, arg_param, sizeof(BRCM_AUDIO_Control_Params_un_t));
	    else
		    memset(&msgAudioCtrl.param, 0, sizeof(BRCM_AUDIO_Control_Params_un_t));
	    msgAudioCtrl.pCallBack = callback;
        msgAudioCtrl.block = block;

        len = kfifo_in_locked(&sgThreadData.m_pkfifo_out, (unsigned char *)&msgAudioCtrl, sizeof(TMsgAudioCtrl), &sgThreadData.m_lock_out);
        if(len != sizeof(TMsgAudioCtrl))
		    DEBUG("Error AUDIO_Ctrl_Process len=%d expected %d \n", len, sizeof(TMsgAudioCtrl));
#if 1        
        // release the semaphore 
        DEBUG("Semaphore released - %d \n",action_code);
        OSSEMAPHORE_Release(sgThreadData.action_complete);
#endif
    }

}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//HAL_AUDIO_Ctrl
//	Client call this function to execute audio HAL functions.
//	This function for the message to worker thread to do actual work
//----------------------------------------------------------------
Result_t AUDIO_Ctrl_Trigger(
	BRCM_AUDIO_ACTION_en_t action_code,
	void *arg_param,
	void *callback,
    int block
	)
{
	TMsgAudioCtrl	msgAudioCtrl;
	Result_t status = RESULT_OK;
	unsigned int	len;
    OSStatus_t  osStatus;

	{
		//BRCM_AUDIO_Control_Params_un_t *paudioControlParam = (BRCM_AUDIO_Control_Params_un_t *)arg_param;
		DEBUG("AudioHalThread action=%d\r\n", action_code);
	}


	msgAudioCtrl.action_code = action_code;
	if(arg_param)
		memcpy(&msgAudioCtrl.param, arg_param, sizeof(BRCM_AUDIO_Control_Params_un_t));
	else
		memset(&msgAudioCtrl.param, 0, sizeof(BRCM_AUDIO_Control_Params_un_t));
	msgAudioCtrl.pCallBack = callback;
    msgAudioCtrl.block = block;

	len = kfifo_in_locked(&sgThreadData.m_pkfifo, (unsigned char *)&msgAudioCtrl, sizeof(TMsgAudioCtrl), &sgThreadData.m_lock);
	if(len != sizeof(TMsgAudioCtrl))
	{
		DEBUG("Error AUDIO_Ctrl_Trigger len=%d expected %d \n", len, sizeof(TMsgAudioCtrl));
		return RESULT_ERROR;
	}

	queue_work(sgThreadData.pWorkqueue_AudioControl, &sgThreadData.mwork);

    if(block)
    {
        // wait for 10sec
        osStatus = OSSEMAPHORE_Obtain(sgThreadData.action_complete,1280);
        if(osStatus != OSSTATUS_SUCCESS)
        {
            DEBUG("AUDIO_Ctrl_Trigger Timeout=%d\r\n",osStatus);
        }

        while(1)
	    {

            //wait for output from output fifo
		    len = kfifo_out_locked(&sgThreadData.m_pkfifo_out, (unsigned char *)&msgAudioCtrl, sizeof(TMsgAudioCtrl), &sgThreadData.m_lock_out);
		    if( (len != sizeof(TMsgAudioCtrl)) && (len!=0) )
			    DEBUG("Error AUDIO_Ctrl_Trigger len=%d expected %d in=%d, out=%d\n", len, sizeof(TMsgAudioCtrl), sgThreadData.m_pkfifo_out.in, sgThreadData.m_pkfifo_out.out);
		    if(len == 0) //FIFO empty sleep
			    return status;
            if(arg_param)
		        memcpy(arg_param,&msgAudioCtrl.param,  sizeof(BRCM_AUDIO_Control_Params_un_t));
	        else
		        memset(arg_param, 0, sizeof(BRCM_AUDIO_Control_Params_un_t));
	    }
    }
	
	return status;
}