/**
 * copies a firmware buffer from user to kernel space and 
 * keeps a pointer and size on core device.
 *
 * NOTE: this mode type is encouraged and should be used 
 *       only when "request_firmware" is not supported by kernel.
 *
 * @param dev pointer to smschar parameters block
 * @param up pointer to a struct that contains the requested 
 *           pointer to user space fw buffer and it size in bytes
 *
 * @return 0 on success, <0 on error.
 */
int smschar_send_fw_file(struct smschar_device_t *dev,
		struct smschar_send_fw_file_ioctl_t *up) {
	int rc = 0;
	struct smscore_device_t *coredev = dev->coredev;

	sms_debug("fw buffer = 0x%p, size = 0x%x", up->fw_buf, up->fw_size);
	/* free old buffer */
	if (coredev->fw_buf != NULL) {
		kfree(coredev->fw_buf);
		coredev->fw_buf = NULL;
	}

	coredev->fw_buf = kmalloc(ALIGN(up->fw_size, SMS_ALLOC_ALIGNMENT), GFP_KERNEL
			| GFP_DMA);
	if (!coredev->fw_buf) {
		sms_err("failed to allocate memory for fw buffer");
		return -ENOMEM;
	}

	if (copy_from_user(coredev->fw_buf, up->fw_buf, up->fw_size)) {
		sms_err("failed to copy fw from user buffer");
		kfree(coredev->fw_buf);
	        coredev->fw_buf = NULL;
		return -EFAULT;
	}
	coredev->fw_buf_size = up->fw_size;

	return rc;
}
static int smsdvb_set_frontend(struct dvb_frontend *fe,
			       struct dvb_frontend_parameters *fep)
{
	struct smsdvb_client_t *client =
		container_of(fe, struct smsdvb_client_t, frontend);

	struct {
		struct SmsMsgHdr_ST	Msg;
		u32		Data[3];
	} Msg;

	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
	Msg.Msg.msgDstId  = HIF_TASK;
	Msg.Msg.msgFlags  = 0;
	Msg.Msg.msgType   = MSG_SMS_RF_TUNE_REQ;
	Msg.Msg.msgLength = sizeof(Msg);
	Msg.Data[0] = fep->frequency;
	Msg.Data[2] = 12000000;

	sms_debug("freq %d band %d",
		  fep->frequency, fep->u.ofdm.bandwidth);

	switch (fep->u.ofdm.bandwidth) {
	case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
	case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
	case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
	case BANDWIDTH_AUTO: return -EOPNOTSUPP;
	default: return -EINVAL;
	}

	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
					   &client->tune_done);
}
Beispiel #3
0
int smsi2c_ts_feed(void *args, unsigned char * ts_buffer, int size) 
{
	struct smscore_device_t *coredev = (struct smscore_device_t *)args;
	struct smscore_buffer_t *cb;
	struct SmsMsgHdr_S *phdr;
	int len = 0;
	int quotient, residue;
	int ts_buf_size_188align;
	sms_debug("%s: buffer:0x%p, size:%d\n", __func__, ts_buffer, size);
if (!size || !args)
		return 0;

#define TS_PACKET_SIZE 188
	ts_buf_size_188align = rounddown((MAX_I2C_BUF_SIZE - sizeof(struct SmsMsgHdr_S)), TS_PACKET_SIZE);
	quotient = size / ts_buf_size_188align;
	residue = size % ts_buf_size_188align;

	for (; quotient > 0; quotient--) {
		cb = smscore_getbuffer(coredev);
		if (!cb) {
			sms_err("Unable to allocate data buffer!\n");
			goto exit;
		}
		phdr = (struct SmsMsgHdr_S *)cb->p;
		memset(cb->p, 0, (int)sizeof(struct SmsMsgHdr_S));
		SMS_INIT_MSG_EX(phdr, MSG_SMS_DAB_CHANNEL, HIF_TASK, 1, ts_buf_size_188align + sizeof(struct SmsMsgHdr_S));
		memcpy((u8*)(phdr+1),ts_buffer, ts_buf_size_188align);
		cb->offset = 0;
		cb->size = ts_buf_size_188align + sizeof(struct SmsMsgHdr_S);
		smscore_onresponse(coredev, cb);
		
		ts_buffer += ts_buf_size_188align;
		len += ts_buf_size_188align;
	}
	if (residue) {
		cb = smscore_getbuffer(coredev);
		if (!cb) {
			sms_err("Unable to allocate data buffer!\n");
			goto exit;
		}
		phdr = (struct SmsMsgHdr_S *)cb->p;
		memset(cb->p, 0, (int)sizeof(struct SmsMsgHdr_S));
		SMS_INIT_MSG_EX(phdr, MSG_SMS_DAB_CHANNEL, HIF_TASK, 1, residue + sizeof(struct SmsMsgHdr_S));
		memcpy((u8*)(phdr+1),ts_buffer, residue);
		cb->offset = 0;
		cb->size = residue + sizeof(struct SmsMsgHdr_S);
		smscore_onresponse(coredev, cb);
		
		ts_buffer += residue;
		len += residue;
	}
	
exit:
	return len;

}
static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
				    struct dvb_frontend_tune_settings *tune)
{
	sms_debug("");

	tune->min_delay_ms = 400;
	tune->step_size = 250000;
	tune->max_drift = 0;
	return 0;
}
Beispiel #5
0
static void smsi2c_interrupt(void *context)
{
	
	struct smsi2c_device *smsdev = (struct smsi2c_device *)context;
	sms_debug("Recieved interrupt from SMS.\n");
	if (!smsdev)
		return;
	
	schedule_work(&smsi2c_work_queue);
}
/**
 * gets firmware filename from look-up table in case 
 * "request_firmware" is not supported by kernel.
 * 
 * @param dev pointer to smschar parameters block
 * @param up pointer to a struct that contains the requested 
 *           mode of operation and a pointer to the filename 
 *           in user space
 *
 * @return 0 on success, <0 on error.
 */
int smschar_get_fw_filename(struct smschar_device_t *dev,
		struct smschar_get_fw_filename_ioctl_t *up) {
	int rc = 0;
	char tmpname[200];

#ifndef REQUEST_FIRMWARE_SUPPORTED
	int mode = up->mode;
	char *fw_filename = smscore_get_fw_filename(dev->coredev, mode,0);
	sprintf(tmpname, "%s/%s", DEFAULT_FW_FILE_PATH, fw_filename);
	sms_debug("need to send fw file %s, mode %d", tmpname, mode);
#else
	/* driver not need file system services */
	tmpname[0] = '\0';
	sms_debug("don't need to send fw file, request firmware supported");
#endif
	if (copy_to_user(up->filename, tmpname, strlen(tmpname) + 1)) {
		sms_err("Failed copy file path to user buffer");
		return -EFAULT;
	}
	return rc;
}
Beispiel #7
0
/* Events that may come from DVB v3 adapter */
static void sms_board_dvb3_event(struct smsdvb_client_t *client,
		enum SMS_DVB3_EVENTS event) {

	struct smscore_device_t *coredev = client->coredev;
	switch (event) {
	case DVB3_EVENT_INIT:
		sms_debug("DVB3_EVENT_INIT");
		sms_board_event(coredev, BOARD_EVENT_BIND);
		break;
	case DVB3_EVENT_SLEEP:
		sms_debug("DVB3_EVENT_SLEEP");
		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
		break;
	case DVB3_EVENT_HOTPLUG:
		sms_debug("DVB3_EVENT_HOTPLUG");
		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
		break;
	case DVB3_EVENT_FE_LOCK:
		if (client->event_fe_state != DVB3_EVENT_FE_LOCK)
		{
			client->event_fe_state = DVB3_EVENT_FE_LOCK;
			sms_debug("DVB3_EVENT_FE_LOCK");
			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
		}
		break;
	case DVB3_EVENT_FE_UNLOCK:
		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK)
		{
			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
			sms_debug("DVB3_EVENT_FE_UNLOCK");
			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
		}
		break;
	case DVB3_EVENT_UNC_OK:
		if (client->event_unc_state != DVB3_EVENT_UNC_OK)
		{
			client->event_unc_state = DVB3_EVENT_UNC_OK;
			sms_debug("DVB3_EVENT_UNC_OK");
			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
		}
		break;
	case DVB3_EVENT_UNC_ERR:
		if (client->event_unc_state != DVB3_EVENT_UNC_ERR)
		{
			/*client->event_unc_state = DVB3_EVENT_UNC_ERR;*/
			sms_debug("DVB3_EVENT_UNC_ERR");
			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
		}
		break;

	default:
		sms_err("Unknown dvb3 api event");
		break;
	}
}
int smsdvb_register(void)
{
	int rc;

	INIT_LIST_HEAD(&g_smsdvb_clients);
	kmutex_init(&g_smsdvb_clientslock);

	rc = smscore_register_hotplug(smsdvb_hotplug);

	sms_debug("");

	return rc;
}
Beispiel #9
0
static int smsdvb_get_frontend(struct dvb_frontend *fe,
			       struct dvb_frontend_parameters *fep)
{
	struct smsdvb_client_t *client =
		container_of(fe, struct smsdvb_client_t, frontend);

	sms_debug("");

	/* todo: */
	memcpy(fep, &client->fe_params,
	       sizeof(struct dvb_frontend_parameters));
	return 0;
}
Beispiel #10
0
static int smsi2c_sendrequest(void *context, void *buffer, size_t size)
{
	int ret;
	struct smsi2c_device *smsdev = (struct smsi2c_device *)context;
	
	if (!smsdev)
	{
		sms_err("smsi2c_sendrequest smsdev NULL!!\n");
		return -ENODEV;
	}
		
	ret = i2c_master_send(smsdev->client, buffer, (int)size);
	sms_debug("i2c_master_send returned %d", ret);
	return ret;
}
int sms_board_lna_control(struct smscore_device_t *coredev, int onoff)
{
	int board_id = smscore_get_board_id(coredev);
	struct sms_board *board = sms_get_board(board_id);

	sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled");

	switch (board_id) {
	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
		sms_set_gpio(coredev,
			     board->rf_switch, onoff ? 1 : 0);
		return sms_set_gpio(coredev,
				    board->lna_ctrl, onoff ? 1 : 0);
	}
	return -EINVAL;
}
Beispiel #12
0
static int smsspi_preload(void *context)
{
	struct _smsspi_txmsg msg;
	struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
	struct _Msg Msg = {
		{
		MSG_SMS_SPI_INT_LINE_SET_REQ, 0, HIF_TASK,
			sizeof(struct _Msg), 0}, {
		0, intr_pin, 0}
	};
	int rc;

	prepareForFWDnl(spi_device->phy_dev);
	PDEBUG("Sending SPI init sequence\n");
	msg.buffer = smsspi_startup;
	msg.size = sizeof(smsspi_startup);
	msg.alignment = 4;
	msg.add_preamble = 0;
	msg.prewrite = NULL;	/* smsspiphy_reduce_clock; */
	msg.postwrite = NULL;   /* smsspiphy_restore_clock; */

	rc = smsspi_queue_message_and_wait(context, &msg);
	if (rc < 0) {
		sms_err("smsspi_queue_message_and_wait error, rc=%d\n", rc);
		return rc;
	}

	sms_debug("sending MSG_SMS_SPI_INT_LINE_SET_REQ, time is now %d",\
		jiffies_to_msecs(jiffies));
	PDEBUG("Sending SPI Set Interrupt command sequence\n");
	msg.buffer = &Msg;
	msg.size = sizeof(Msg);
	msg.alignment = SPI_PACKET_SIZE;
	msg.add_preamble = 1;

	rc = smsspi_queue_message_and_wait(context, &msg);
	if (rc < 0) {
		sms_err("smsspi_queue_message_and_wait error, rc=%d\n", rc);
		return rc;
	}

	return rc;
}
static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
{
	struct smsdvb_client_t *client =
		container_of(feed->demux, struct smsdvb_client_t, demux);
	struct SmsMsgData_ST PidMsg;

	sms_debug("remove pid %d(%x)",
		  feed->pid, feed->pid);

	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
	PidMsg.xMsgHeader.msgFlags = 0;
	PidMsg.xMsgHeader.msgType  = MSG_SMS_REMOVE_PID_FILTER_REQ;
	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
	PidMsg.msgData[0] = feed->pid;

	return smsclient_sendrequest(client->smsclient,
				     &PidMsg, sizeof(PidMsg));
}
Beispiel #14
0
static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
{
	struct smsdvb_client_t *client =
		container_of(feed->demux, struct smsdvb_client_t, demux);
	struct sms_msg_data pid_msg;

	sms_debug("remove pid %d(%x)",
		  feed->pid, feed->pid);

	client->feed_users--;

	pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
	pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
	pid_msg.x_msg_header.msg_flags = 0;
	pid_msg.x_msg_header.msg_type  = MSG_SMS_REMOVE_PID_FILTER_REQ;
	pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
	pid_msg.msg_data[0] = feed->pid;

	return smsclient_sendrequest(client->smsclient,
				     &pid_msg, sizeof(pid_msg));
}
Beispiel #15
0
static int smsi2c_sendrequest(void *context, void *buffer, size_t size)
{
	int ret;
	struct smsi2c_device *smsdev = (struct smsi2c_device *)context;
	
	if (!smsdev)
	{
		sms_err("smsi2c_sendrequest smsdev NULL!!\n");
		return -ENODEV;
	}
#if 0		
	sms_info("Writing message to I2C, size = %d bytes.\n", size);
	sms_info("msg hdr: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x.\n",
		((u8 *) buffer)[0], ((u8 *) buffer)[1], ((u8 *) buffer)[2],
		((u8 *) buffer)[3], ((u8 *) buffer)[4], ((u8 *) buffer)[5],
		((u8 *) buffer)[6], ((u8 *) buffer)[7]);
#endif
	//ret = i2c_master_send(smsdev->client, buffer, (int)size); 
	ret = i2c_master_normal_send(smsdev->client, buffer, (int)size, I2C_SCL_TATE); //using 400KHz clk
	sms_debug("i2c_master_send returned %d", ret);
	return ret;
}
Beispiel #16
0
static int smsdvb_tune_isdbt(struct smsdvb_client_t *client, 
			     struct dvb_frontend_parameters *fep)
{
	struct {
		struct SmsMsgHdr_ST Msg;
		u32 Data[4];
	} Msg;

	Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
	Msg.Msg.msgDstId = HIF_TASK;
	Msg.Msg.msgFlags = 0;
	Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
	Msg.Msg.msgLength = sizeof(Msg);
	Msg.Data[0] = fep->frequency;
	Msg.Data[1] = BW_ISDBT_1SEG;
	Msg.Data[2] = 12000000;
	Msg.Data[3] = 0;

	sms_debug("freq %d msgType %d Msg.Data[1] %d",
		  fep->frequency, Msg.Msg.msgType, BW_ISDBT_1SEG);

	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
					   &client->tune_done);
}
Beispiel #17
0
// allocate and init i2c dev descriptor
// update i2c client params
// 
static int smsi2c_probe(void)
{
	int ret;

	struct smsi2c_device *smsdev;
	struct smsdevice_params_t params;
	struct SmsMsgHdr_S smsmsg;
	struct SmsMsgData2Args_S setIntMsg = {{MSG_SMS_SPI_INT_LINE_SET_REQ, 
				0, 
				11,
				sizeof(struct SmsMsgData2Args_S),
				0},
				{0xff,
				20}};

	    struct i2c_board_info smsi2c_info = {
		I2C_BOARD_INFO("smsi2c", sms_i2c_addr),
	    };
	
	smsdev = kzalloc(sizeof(struct smsi2c_device), GFP_KERNEL);
	if (!smsdev)
	{
		sms_err("Cannot allocate memory for I2C device driver.\n");
		return -ENOMEM;
	}
		
	g_smsi2c_device = smsdev;
	sms_debug ("Memory allocated");
	smsdev->adap = i2c_get_adapter(host_i2c_ctrl);
	if (!smsdev->adap) {
		sms_err("Cannot get adapter #%d.\n", host_i2c_ctrl);
		ret = -ENODEV;
		goto failed_allocate_adapter;
	}
	sms_debug ("Got the adapter");

	smsi2c_info.platform_data = smsdev;

	smsdev->client = i2c_new_device(smsdev->adap, &smsi2c_info);

	if (!smsdev->client) {
		sms_err("Cannot register I2C device with addr 0x%x.\n", sms_i2c_addr);
		 ret = -ENODEV;
		 goto failed_allocate_device;
	}
	sms_debug ("Got the device");


	ret = gpio_request(host_i2c_intr_pin, "sms_gpio");
	if (ret) {
		sms_err("failed to get sms_gpio\n");
		 goto failed_allocate_gpio;
	}	
	gpio_direction_input(host_i2c_intr_pin);
	gpio_export(host_i2c_intr_pin, 0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
	irq_set_irq_type(gpio_to_irq(host_i2c_intr_pin), IRQ_TYPE_EDGE_FALLING);	
#else
	set_irq_type(gpio_to_irq(host_i2c_intr_pin), IRQ_TYPE_EDGE_FALLING);	
#endif
	/*register irq*/
	ret = request_irq( gpio_to_irq(host_i2c_intr_pin), (irq_handler_t)smsi2c_interrupt,
		 IRQF_TRIGGER_RISING, "SMSI2C", smsdev);
	if (ret < 0) {
		sms_err("failed to allocate interrupt for SMS\n");
		ret = -ENODEV;
		goto failed_allocate_interrupt;
	}	

	if (device_int_line != 0xFFFFFFFF)
	{ /* Device is not using the default interrupt pin*/

		sms_debug("Device is not using the default int pin, need to set the interrupt pin to %d", device_int_line);
		setIntMsg.msgData[1] = device_int_line;
		ret = smsi2c_sendrequest(smsdev, &setIntMsg, sizeof(setIntMsg));
		msleep(50);
	}

	init_completion(&smsdev->version_ex_done);
	smsdev->wait_for_version_resp = 1;
	SMS_INIT_MSG(&smsmsg, MSG_SMS_GET_VERSION_EX_REQ,
		     sizeof(struct SmsMsgHdr_S));
	smsi2c_sendrequest(smsdev, &smsmsg, sizeof(smsmsg));
	/*Wait for response*/
	ret = wait_for_completion_timeout(&smsdev->version_ex_done, msecs_to_jiffies(500));
	if (ret > 0)
	{ /*Got version. device is in*/
		sms_debug("Found and identified the I2C device");
	}
	else
	{ /* No response recieved*/
		sms_err("No response to get version command");
		ret = -ETIME;
		goto failed_registering_coredev;
	}


	memset(&params, 0, sizeof(struct smsdevice_params_t));

	params.device = (struct device *)&smsdev->client->adapter->dev;
#ifdef SMS_RK_TS
	params.buffer_size = MAX_I2C_BUF_SIZE;
	params.num_buffers = MAX_I2C_BUF_NUMBER;
	params.require_node_buffer = 1;
#else
	params.buffer_size = 0x400;
	params.num_buffers = 20;
#endif
	params.context = smsdev;

	snprintf(params.devpath, sizeof(params.devpath),
		 "i2c\\%s", "smsi2c");

	params.sendrequest_handler  = smsi2c_sendrequest;
	params.loadfirmware_handler = smsi2c_loadfirmware_handler;
	switch(smsdev->chip_model)
	{
		case 0: params.device_type = 0; break;
		case 0x1002:
		case 0x1102:
		case 0x1004: params.device_type = SMS_NOVA_B0; break;
		case 0x1182: params.device_type = SMS_VENICE; break;
		case 0x1530: params.device_type = SMS_DENVER_1530; break;
		case 0x2130: params.device_type = SMS_PELE; break;
		case 0x2160: params.device_type = SMS_DENVER_2160; break;
		case 0x2180: params.device_type = SMS_MING; break;
		case 0x2230: params.device_type = SMS_RIO; break;
		case 0x3130: params.device_type = SMS_ZICO; break;
		case 0x3180: params.device_type = SMS_QING; break;
		case 0x3230: params.device_type = SMS_SANTOS; break;
		case 0x4470: 
			if (smsdev->chip_metal >= 2)
				params.device_type = SMS_SIENA_A2; 
			else
				params.device_type = SMS_SIENA; 
			break;

		default: params.device_type = 0; break;
	}

	/* Use SMS_DEVICE_FAMILY2 for firmware download over SMS MSGs
	   SMS_DEVICE_FAMILY1 for backdoor I2C firmware download */
	params.flags |= SMS_DEVICE_FAMILY2;
	
	/* Device protocol completion events */

	ret = smscore_register_device(&params, &smsdev->coredev);
	if (ret < 0)
        {
	        printk(KERN_INFO "smscore_register_device error\n");
		goto failed_registering_coredev;
        }

	ret = smscore_start_device(smsdev->coredev);
	if (ret < 0)
        {
		printk(KERN_INFO "smscore_start_device error\n");
		goto failed_device_start;
        }

	return 0;
failed_device_start:
	smscore_unregister_device(smsdev->coredev);
failed_registering_coredev:
	free_irq(gpio_to_irq(host_i2c_intr_pin), smsdev);
failed_allocate_interrupt:
	gpio_free(host_i2c_intr_pin);
failed_allocate_gpio:
	i2c_unregister_device(smsdev->client);
failed_allocate_device:
	i2c_put_adapter(smsdev->adap);
failed_allocate_adapter:
	g_smsi2c_device = NULL;
	kfree(smsdev);

	return ret;
}
Beispiel #18
0
static void smsi2c_worker_thread(void *args) 
{
	struct smscore_buffer_t *cb;
	struct SmsMsgHdr_S *phdr;
	u16 len;
	int ret;

	sms_debug("Worker thread is running.\n");
	cb = smscore_getbuffer(g_smsi2c_device->coredev);
	if (!cb) {
		sms_err("Unable to allocate data buffer!\n");
		goto exit;
	}
	
	phdr = (struct SmsMsgHdr_S *)cb->p;
	sms_debug("Recieve the message header.....\n");
	memset(cb->p, 0, (int)sizeof(struct SmsMsgHdr_S));
	sms_debug("buf before: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
		((u8*)phdr)[0], ((u8*)phdr)[1], ((u8*)phdr)[2], ((u8*)phdr)[3], 
		((u8*)phdr)[4], ((u8*)phdr)[5], ((u8*)phdr)[6], ((u8*)phdr)[7]);
	ret = i2c_master_recv(g_smsi2c_device->client, 
							cb->p, 
							(int)sizeof(struct SmsMsgHdr_S));
	if (ret < 0) {
		sms_err("Unable to read sms header! ret=%d\n", ret);
		goto exit;
	}

	sms_debug("hdr: type=%d, src=%d, dst=%d, len=%d, flag=0x%x\n", 
		phdr->msgType, phdr->msgSrcId, phdr->msgDstId, phdr->msgLength, phdr->msgFlags);
	sms_debug("buf: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
		((u8*)phdr)[0], ((u8*)phdr)[1], ((u8*)phdr)[2], ((u8*)phdr)[3], 
		((u8*)phdr)[4], ((u8*)phdr)[5], ((u8*)phdr)[6], ((u8*)phdr)[7]);
	sms_debug("Recieve the rest of the message.....\n");
	len = phdr->msgLength;
	
	if (len > sizeof(struct SmsMsgHdr_S))
	{
		ret = i2c_master_recv(g_smsi2c_device->client, 
								(u8*)(phdr+1), 
								len - (int)sizeof(struct SmsMsgHdr_S));
		sms_debug("recv of data returned %d", ret);
		if (ret < 0) {
			sms_err("Unable to read sms payload!\n");
			goto exit;
		}
	}
	
	switch (phdr->msgType)
	{
		case MSG_SMS_GET_VERSION_EX_RES: 
		{
			struct SmsVersionRes_S *ver =
					(struct SmsVersionRes_S *) phdr;
			sms_debug("MSG_SMS_GET_VERSION_EX_RES "
					"id %d prots 0x%x ver %d.%d",
					ver->xVersion.FirmwareId,
					ver->xVersion.SupportedProtocols,
					ver->xVersion.RomVer.Major,
					ver->xVersion.RomVer.Minor);
			
			smscore_set_device_mode(g_smsi2c_device->coredev, 
					ver->xVersion.FirmwareId == 255 ?
					SMSHOSTLIB_DEVMD_NONE : ver->xVersion.FirmwareId);
			complete(&g_smsi2c_device->version_ex_done);
			break;
		}
	}
	sms_debug("Message recieved. Sending to callback.....\n");	
	cb->offset = 0;
	cb->size = len;
	smscore_onresponse(g_smsi2c_device->coredev, cb);
	
exit:
	return;
}
Beispiel #19
0
static void smsi2c_worker_thread(void *args) 
{
	struct smscore_buffer_t *cb;
	struct SmsMsgHdr_S *phdr;
	u16 len;
	int ret;
	u8 local_buf[100];
	sms_debug("Worker thread is running.\n");
	if (!g_smsi2c_device->coredev)
	{
		sms_debug("Using local buffer\n");
		cb = NULL;
		phdr = (struct SmsMsgHdr_S *)local_buf;
	}
	else
	{
		sms_debug("Using core buffer\n");
		cb = smscore_getbuffer(g_smsi2c_device->coredev);
		if (!cb) {
			sms_err("Unable to allocate data buffer!\n");
			goto exit;
		}
		phdr = (struct SmsMsgHdr_S *)cb->p;
	}	
	sms_debug("Recieve the message header.....\n");
	memset(phdr, 0, (int)sizeof(struct SmsMsgHdr_S));
	sms_debug("buf before: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
		((u8*)phdr)[0], ((u8*)phdr)[1], ((u8*)phdr)[2], ((u8*)phdr)[3], 
		((u8*)phdr)[4], ((u8*)phdr)[5], ((u8*)phdr)[6], ((u8*)phdr)[7]);
#if 0
	ret = i2c_master_recv(g_smsi2c_device->client, 
							(void *)phdr, 
							(int)sizeof(struct SmsMsgHdr_S));
#else
	ret = i2c_master_normal_recv(g_smsi2c_device->client, 
							(void *)phdr, 
							(int)sizeof(struct SmsMsgHdr_S), I2C_SCL_TATE);
	
#endif
	if (ret < 0) {
		if ((void*)phdr != (void*)local_buf)
			smscore_putbuffer(g_smsi2c_device->coredev, cb);
		sms_err("Unable to read sms header! ret=%d\n", ret);
		goto exit;
	}
#if 0	
	sms_debug("hdr: type=%d, src=%d, dst=%d, len=%d, flag=0x%x\n", 
		phdr->msgType, phdr->msgSrcId, phdr->msgDstId, phdr->msgLength, phdr->msgFlags);
	sms_debug("buf: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
		((u8*)phdr)[0], ((u8*)phdr)[1], ((u8*)phdr)[2], ((u8*)phdr)[3], 
		((u8*)phdr)[4], ((u8*)phdr)[5], ((u8*)phdr)[6], ((u8*)phdr)[7]);
	sms_debug("Recieve the rest of the message.....\n");
#endif	
	len = phdr->msgLength;
	
	if (len > sizeof(struct SmsMsgHdr_S))
	{
#if 0
		ret = i2c_master_recv(g_smsi2c_device->client, 
								(u8*)(phdr+1), 
								len - (int)sizeof(struct SmsMsgHdr_S));
#else
		ret = i2c_master_normal_recv(g_smsi2c_device->client, 
								(u8*)(phdr+1), 
								len - (int)sizeof(struct SmsMsgHdr_S), I2C_SCL_TATE);
	
#endif
		//sms_debug("recv of data returned %d", ret);
		if (ret < 0) {
			if ((void*)phdr != (void*)local_buf)
				smscore_putbuffer(g_smsi2c_device->coredev, cb);
			sms_err("Unable to read sms payload!\n");
			goto exit;
		}
		sms_debug("data: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
			((u8*)(phdr+1))[0], ((u8*)(phdr+1))[1], ((u8*)(phdr+1))[2], ((u8*)(phdr+1))[3], 
			((u8*)(phdr+1))[4], ((u8*)(phdr+1))[5], ((u8*)(phdr+1))[6], ((u8*)(phdr+1))[7]);
	}
	if ((phdr->msgType == MSG_SMS_GET_VERSION_EX_RES) && ((void*)phdr == (void*)local_buf))
	{ /*This was an internal command, so we won't send it out*/
		g_smsi2c_device->chip_model = *((u16*)(phdr+1));
		sms_info("chip model=0x%x\n", g_smsi2c_device->chip_model);
		g_smsi2c_device->chip_metal = ((u8*)(phdr+1))[3];
		sms_info("chip step=0x%x\n", g_smsi2c_device->chip_metal);
		g_smsi2c_device->wait_for_version_resp = 0;
		sms_info("complete get version\n");
		complete(&g_smsi2c_device->version_ex_done);
		sms_info("done.");
		return;
	}
#ifdef I2C_TS_ENABLE
	{
		if (MSG_SMS_INIT_DEVICE_RES == phdr->msgType) {
			ret = smsi2c_ts_enable(g_smsi2c_device);
			sms_debug("smsi2c_ts_enable.......\n");
		}
	}
#endif
	sms_debug("Message recieved. Sending to callback.....\n");	
	if (((void*)phdr != (void*)local_buf))
	{
		sms_debug("Ext buf.....\n");	
		cb->offset = 0;
		cb->size = len;
		if	(g_smsi2c_device->coredev)
		{
			smscore_onresponse(g_smsi2c_device->coredev, cb);
		}
	}
exit:
	return;
}
Beispiel #20
0
static int smsi2c_loadfirmware_handler(void *context, void* p_data, u32 fw_size)
{
	int ret;
	u8* fw_data = (u8*)p_data + 12;
	u32* fw_hdr = p_data;
	u32 actual_crc, dummy_crc,i;
	u32 chunk_size;
	u32 dummy_hdr[3];
	u32 fw_addr, fw_len, dnl_offset;
	struct smsi2c_device *smsdev = (struct smsi2c_device *)context;
	u16 flags_bak = smsdev->client->flags;
	
	struct SmsMsgHdr_S BackdoorMsg = {
		MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ, 0, HIF_TASK,
			sizeof(struct SmsMsgHdr_S), 0};
	
	fw_addr = fw_hdr[2];
	fw_len = fw_hdr[1];

	/*The full CRC is for debug and printing, the function doesnt use this*/
	sms_debug("crc=0x%x, len=0x%x, addr=0x%x", fw_hdr[0], fw_len, fw_addr);
	actual_crc=0;
	for (i = 0; i < fw_len+8 ; i++)
	{
		actual_crc ^= ((u8*)p_data)[4+i];
	}
	sms_debug("actual calculated crc=0x%x", actual_crc);
	

	sms_debug("Sending the firmware content in chunks of no more than %dKB.\n", MAX_CHUNK_SIZE/1024);
	dnl_offset = fw_addr + fw_len;
	smsdev->client->flags |= I2C_M_IGNORE_NAK;
	while (fw_len)
	{
		sms_debug("Sending backdoor command.\n");
		ret = smsi2c_sendrequest(context, &BackdoorMsg, sizeof(BackdoorMsg));
		if (ret < 0)
		{
			sms_err ("failed sending backdoor command");
			return ret;
		}

		msleep(30);
		chunk_size = min((int)fw_len, MAX_CHUNK_SIZE);

		dnl_offset -= chunk_size;
		fw_len -= chunk_size;
		dummy_hdr[1] = chunk_size;
		dummy_hdr[2] = dnl_offset;

		dummy_crc=0;
		for (i = 0; i < 8 ; i++)
		{
			dummy_crc ^= ((u8*)dummy_hdr)[4+i];
		}
		for (i = 0; i < chunk_size ; i++)
		{
			dummy_crc ^= ((u8*)(fw_data+fw_len))[i];
		}
		sms_debug("download chunk size %d at offset 0x%x, act crc is 0x%x.\n", chunk_size, dnl_offset, dummy_crc);
		if (dnl_offset == fw_addr)
		{ /* Only for the last chunk send the correct CRC*/
			dummy_hdr[0] = dummy_crc;
		}
		else
		{/* for all but last chunk, make sure crc is wrong*/
			dummy_hdr[0] = dummy_crc^0x55;
		}
		/*send header of current chunk*/
		ret = smsi2c_sendrequest(context, (u8*)dummy_hdr, 12);
		if (ret < 0)
		{
			sms_err ("failed sending fw header");
			return ret;
		}
		msleep(20);
		/*send the data of current chunk*/
		ret = smsi2c_sendrequest(context, 
						(u8*)(fw_data+fw_len), 
						chunk_size);
		if (ret < 0)
		{
			sms_err ("failed sending fw data");
			return ret;
		}
		msleep(30);
	}
	sms_debug("FW download complete.\n");
	smsdev->client->flags = flags_bak;
	//msleep(400);
	smsi2c_ts_enable(context);

	return 0;
}
Beispiel #21
0
// allocate and init i2c dev descriptor
// update i2c client params
// 
static int smsi2c_probe(void)
{
	int ret;

	struct smsi2c_device *smsdev;
	struct smsdevice_params_t params;

	    struct i2c_board_info smsi2c_info = {
		I2C_BOARD_INFO("smsi2c", sms_i2c_addr),
	    };
	
	smsdev = kzalloc(sizeof(struct smsi2c_device), GFP_KERNEL);
	if (!smsdev)
	{
		sms_err("Cannot allocate memory for I2C device driver.\n");
		return -ENOMEM;
	}
		
	g_smsi2c_device = smsdev;
	sms_debug ("Memory allocated");
	smsdev->adap = i2c_get_adapter(host_i2c_ctrl);
	if (!smsdev->adap) {
		sms_err("Cannot get adapter #%d.\n", host_i2c_ctrl);
		ret = -ENODEV;
		goto failed_allocate_adapter;
	}
	sms_debug ("Got the adapter");

	smsi2c_info.platform_data = smsdev;

	smsdev->client = i2c_new_device(smsdev->adap, &smsi2c_info);

	if (!smsdev->client) {
		sms_err("Cannot register I2C device with addr 0x%x.\n", sms_i2c_addr);
		 ret = -ENODEV;
		 goto failed_allocate_device;
	}
	sms_debug ("Got the device");


	ret = gpio_request(host_i2c_intr_pin, "sms_gpio");
	if (ret) {
		sms_err("failed to get sms_gpio\n");
		 goto failed_allocate_gpio;
	}	
	gpio_direction_input(host_i2c_intr_pin);
	gpio_export(host_i2c_intr_pin, 0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
	irq_set_irq_type(gpio_to_irq(host_i2c_intr_pin), IRQ_TYPE_EDGE_FALLING);	
#else
	set_irq_type(gpio_to_irq(host_i2c_intr_pin), IRQ_TYPE_EDGE_FALLING);	
#endif
	/*register irq*/
	ret = request_irq( gpio_to_irq(host_i2c_intr_pin), (irq_handler_t)smsi2c_interrupt,
		 IRQF_TRIGGER_RISING, "SMSI2C", smsdev);
	if (ret < 0) {
		sms_err("failed to allocate interrupt for SMS\n");
		 goto failed_allocate_interrupt;
	}	

	memset(&params, 0, sizeof(struct smsdevice_params_t));

	params.device = (struct device *)smsdev->client;
	params.buffer_size = 0x400;	
	params.num_buffers = 20;	
	params.context = smsdev;

	snprintf(params.devpath, sizeof(params.devpath),
		 "i2c\\%s", "smsi2c");

	params.sendrequest_handler  = smsi2c_sendrequest;
	params.loadfirmware_handler = smsi2c_loadfirmware_handler;
	params.device_type = i2c_default_type;

	/* Use SMS_DEVICE_FAMILY2 for firmware download over SMS MSGs
	   SMS_DEVICE_FAMILY1 for backdoor I2C firmware download */
	/* params.flags |= SMS_DEVICE_FAMILY2; */
	
	/* Device protocol completion events */
	init_completion(&smsdev->version_ex_done);

	ret = smscore_register_device(&params, &smsdev->coredev);
	if (ret < 0)
        {
	        printk(KERN_INFO "smscore_register_device error\n");
		goto failed_registering_coredev;
        }

	ret = smscore_start_device(smsdev->coredev);
	if (ret < 0)
        {
		printk(KERN_INFO "smscore_start_device error\n");
		goto failed_device_start;
        }

	return 0;
failed_device_start:
	smscore_unregister_device(smsdev->coredev);
failed_registering_coredev:
	free_irq(gpio_to_irq(host_i2c_intr_pin), smsdev);
failed_allocate_interrupt:
	gpio_free(host_i2c_intr_pin);
failed_allocate_gpio:
	i2c_unregister_device(smsdev->client);
failed_allocate_device:
	i2c_put_adapter(smsdev->adap);
failed_allocate_adapter:
	g_smsi2c_device = NULL;
	kfree(smsdev);

	return ret;
}