static struct smscore_registry_entry_t *smscore_find_registry(char *devpath) { struct smscore_registry_entry_t *entry; struct list_head *next; kmutex_lock(&g_smscore_registrylock); for (next = g_smscore_registry.next; next != &g_smscore_registry; next = next->next) { entry = (struct smscore_registry_entry_t *) next; if (!strcmp(entry->devpath, devpath)) { kmutex_unlock(&g_smscore_registrylock); return entry; } } entry = kmalloc( sizeof(struct smscore_registry_entry_t), GFP_KERNEL); if (entry) { entry->mode = default_mode; if(strlen(devpath) >= 32) { sms_err(" strlen(devpath) >= 32\n"); return NULL; } strcpy(entry->devpath, devpath); list_add(&entry->entry, &g_smscore_registry); } else sms_err("failed to create smscore_registry."); kmutex_unlock(&g_smscore_registrylock); return entry; }
/** * 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; }
int smsnet_register(void) { int rc; INIT_LIST_HEAD(&g_smsnet_clients); kmutex_init(&g_smsnet_clientslock); memset(&g_smsnet_stats, 0, sizeof(g_smsnet_stats)); g_smsnet_device = alloc_netdev(0, "sms", smsnet_setup_device); if (!g_smsnet_device) { sms_err("alloc_netdev() failed"); return -ENOMEM; } rc = register_netdev(g_smsnet_device); if (rc < 0) { sms_err("register_netdev() failed %d\n", rc); free_netdev(g_smsnet_device); return rc; } rc = smscore_register_hotplug(smsnet_hotplug); sms_info("exit - rc %d", rc); return rc; }
/** * Completing Urb's callback handler - bottom half (worker thread context) * * 1. sends old core buffer to smscore. * assumes that after return from smsmcore_onsresponse, the core buffer is * either on pendint data (smschar) or in available buffers list (smschar, smsdvb) * 2. acquires new available core buffer and submits the urb to the usb core * * @param surb pointer to a completing surb object */ static void smsusb_handle_surb(struct smsusb_urb_t *surb) { struct smsusb_device_t *dev = surb->dev; struct urb *urb = &surb->urb; if (urb->status == -ESHUTDOWN) { sms_err("error, urb status %d (-ESHUTDOWN), %d bytes", urb->status, urb->actual_length); return; } /* * in case that the urb was killed during * smsusb_stop_streaming, the status is ENOENT */ if (urb->status == -ENOENT) { sms_err("error, urb status %d (-ENOENT), %d bytes", urb->status, urb->actual_length); return; } if (!dev->surbs_active) { sms_err("error, surbs are not active, urb status %d , %d bytes", urb->status, urb->actual_length); return; } if ((urb->actual_length > 0) && (urb->status == 0)) { struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p; smsendian_handle_message_header(phdr); if (urb->actual_length >= phdr->msgLength) { surb->cb->size = phdr->msgLength; if (dev->response_alignment && (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) { surb->cb->offset = dev->response_alignment + ((phdr->msgFlags >> 8) & 3); /* sanity check */ if (((int)phdr->msgLength + surb->cb->offset) > urb->actual_length) { sms_err("invalid response " "msglen %d offset %d " "size %d", phdr->msgLength, surb->cb->offset, urb->actual_length); goto resubmit_and_exit; } /* move buffer pointer and * copy header to its new location */ memcpy((char *)phdr + surb->cb->offset, phdr, sizeof(struct SmsMsgHdr_ST)); } else
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; }
int sms_ir_init(struct smscore_device_t *coredev) { int err; int board_id = smscore_get_board_id(coredev); struct rc_dev *dev; sms_log("Allocating rc device"); dev = rc_allocate_device(); if (!dev) { sms_err("Not enough memory"); return -ENOMEM; } coredev->ir.controller = 0; coredev->ir.timeout = IR_DEFAULT_TIMEOUT; sms_log("IR port %d, timeout %d ms", coredev->ir.controller, coredev->ir.timeout); snprintf(coredev->ir.name, sizeof(coredev->ir.name), "SMS IR (%s)", sms_get_board(board_id)->name); strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); dev->input_name = coredev->ir.name; dev->input_phys = coredev->ir.phys; dev->dev.parent = coredev->device; #if 0 dev->input_id.bustype = BUS_USB; dev->input_id.version = 1; dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); #endif dev->priv = coredev; dev->driver_type = RC_DRIVER_IR_RAW; dev->allowed_protos = RC_TYPE_ALL; dev->map_name = sms_get_board(board_id)->rc_codes; dev->driver_name = MODULE_NAME; sms_log("Input device (IR) %s is set for key events", dev->input_name); err = rc_register_device(dev); if (err < 0) { sms_err("Failed to register device"); rc_free_device(dev); return err; } coredev->ir.dev = dev; return 0; }
/** * waits until buffer inserted into a queue. when inserted buffer offset * are reportedto the calling process. previously reported buffer is * returned to smscore pool. * * @param dev pointer to smschar parameters block * @param touser pointer to a structure that receives incoming buffer offsets * * @return 0 on success, <0 on error. */ static int smschar_wait_get_buffer(struct smschar_device_t *dev, struct smschar_buffer_t *touser) { unsigned long flags; int rc; spin_lock_irqsave(&dev->lock, flags); if (dev->currentcb) { smscore_putbuffer(dev->coredev, dev->currentcb); dev->currentcb = NULL; dev->pending_count--; } spin_unlock_irqrestore(&dev->lock, flags); rc = wait_event_interruptible(dev->waitq, !list_empty(&dev->pending_data) || (dev->cancel_waitq)); if (rc < 0) { sms_err("wait_event_interruptible error, rc = %d", rc); return rc; } if (dev->cancel_waitq) { touser->offset = 0; touser->size = 0; return 0; } if (!dev->smsclient) { sms_err("no client\n"); return -ENODEV; } spin_lock_irqsave(&dev->lock, flags); if (!list_empty(&dev->pending_data)) { struct smscore_buffer_t *cb = (struct smscore_buffer_t *)dev->pending_data.next; touser->offset = cb->offset_in_common + cb->offset; touser->size = cb->size; list_del(&cb->entry); dev->currentcb = cb; } else { touser->offset = 0; touser->size = 0; } spin_unlock_irqrestore(&dev->lock, flags); return 0; }
/** * copies data from buffers in incoming queue into a user buffer * * @param file File structure. * @param buf Source buffer. * @param count Size of source buffer. * @param f_pos Position in file (ignored). * * @return Number of bytes read, or <0 on error. */ static ssize_t smschar_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) { struct smschar_device_t *dev = file->private_data; unsigned long flags; int rc, copied = 0; if (!buf) { sms_err("bad pointer recieved from user"); return -EFAULT; } if (!dev->coredev || !dev->smsclient) { sms_err("no client\n"); return -ENODEV; } rc = wait_event_interruptible(dev->waitq, !list_empty(&dev->pending_data) || (dev->cancel_waitq)); if (rc < 0) { sms_err("wait_event_interruptible error %d\n", rc); return rc; } if (dev->cancel_waitq) return 0; if (!dev->smsclient) { sms_err("no client\n"); return -ENODEV; } spin_lock_irqsave(&dev->lock, flags); while (!list_empty(&dev->pending_data) && (copied < count)) { struct smscore_buffer_t *cb = (struct smscore_buffer_t *)dev->pending_data.next; int actual_size = min(((int)count - copied), cb->size); if (copy_to_user(&buf[copied], &((char *)cb->p)[cb->offset], actual_size)) { sms_err("copy_to_user failed\n"); spin_unlock_irqrestore(&dev->lock, flags); return -EFAULT; } copied += actual_size; cb->offset += actual_size; cb->size -= actual_size; if (!cb->size) { list_del(&cb->entry); smscore_putbuffer(dev->coredev, cb); dev->pending_count--; } } spin_unlock_irqrestore(&dev->lock, flags); return copied; }
/** * poll for data availability * * @param file File structure. * @param wait kernel polling table. * * @return (POLLIN | POLLRDNORM) flags if read data is available. * POLLNVAL flag if wait_queue was cancelled. * <0 on error. */ static unsigned int smschar_poll(struct file *file, struct poll_table_struct *wait) { struct smschar_device_t *dev; int events = 0; if (file == NULL) { sms_err("file is NULL"); return EINVAL; } dev = file->private_data; if (dev == NULL) { sms_err("dev is NULL"); return -EINVAL; } if (dev->cancel_waitq) { /*sms_debug("returning POLLNVAL");*/ events |= POLLNVAL; return events; } /* * critical section, protect access to kernel poll * table structure */ kmutex_lock(&g_smschar_pollwait_lock); /* * make the system call to wait to wait_queue wakeup if there is * no data * cancel_waitq is checked again to prevenet reace condition (wait * to cancalled wait_queue) */ if (list_empty(&dev->pending_data) && (!dev->cancel_waitq)) { poll_wait(file, &dev->waitq, wait); } /* * pending data, raise relevant flags */ if (!list_empty(&dev->pending_data)) { events |= (POLLIN | POLLRDNORM); } kmutex_unlock(&g_smschar_pollwait_lock); return events; }
/** * registers client associated with the node * * @param inode Inode concerned. * @param file File concerned. * * @return 0 on success, <0 on error. */ static int smschar_open(struct inode *inode, struct file *file) { struct smschar_device_t *dev = container_of(inode->i_cdev, struct smschar_device_t, cdev); int rc = -ENODEV; sms_info("entering, device index = %d", dev->device_index); if (dev->coredev) { struct smsclient_params_t params; params.initial_id = dev->device_index ? dev->device_index : SMS_HOST_LIB; params.data_type = dev->device_index ? MSG_SMS_DAB_CHANNEL : 0; params.onresponse_handler = smschar_onresponse; params.onremove_handler = smschar_onremove; params.context = dev; rc = smscore_register_client(dev->coredev, ¶ms, &dev->smsclient); if (!rc) file->private_data = dev; dev->cancel_waitq = 0; g_pnp_status_changed = 1; } if (rc) sms_err("exiting, rc = %d", rc); return rc; }
/** * queues incoming buffers into buffers queue * * @param context pointer to the client context (smschar parameters block) * @param cb pointer to incoming buffer descriptor * * @return 0 on success, <0 on queue overflow. */ static int smschar_onresponse(void *context, struct smscore_buffer_t *cb) { struct smschar_device_t *dev = context; unsigned long flags; if (!dev) { sms_err("recieved bad dev pointer"); return -EFAULT; } spin_lock_irqsave(&dev->lock, flags); if (dev->pending_count > SMS_CHR_MAX_Q_LEN) { spin_unlock_irqrestore(&dev->lock, flags); return -EBUSY; } dev->pending_count++; /* if data channel, remove header */ if (dev->device_index) { cb->size -= sizeof(struct SmsMsgHdr_ST); cb->offset += sizeof(struct SmsMsgHdr_ST); } list_add_tail(&cb->entry, &dev->pending_data); spin_unlock_irqrestore(&dev->lock, flags); if (waitqueue_active(&dev->waitq)) wake_up_interruptible(&dev->waitq); return 0; }
static int smsi2c_ts_enable(void *context) { #define TS_CLK 4000000 //6000000 //#define TS_CONTROL_ENABLE struct SmsTsEnable_S TsEnableMsg = {{MSG_SMS_ENBALE_TS_INTERFACE_REQ, 0, 11, sizeof(struct SmsTsEnable_S), 0}, TS_CLK,//24000000, TSI_PARALLEL_ON_HIF, //TSI_PARALLEL_ON_HIF, TSI_SERIAL_ON_SDIO, //wood, ++--, @20140917 TSI_SIGNALS_ACTIVE_HIGH,//TSI_SIGNALS_ACTIVE_LOW, 0,//0, TSI_SIG_OUT_FALL_EDGE, TSI_BIT7_IS_MSB, #ifdef TS_CONTROL_ENABLE 1, #else 0, #endif TSI_TRANSPARENT,//TSI_ENCAPSULATED, 21};//21 struct smsi2c_device *smsdev = (struct smsi2c_device *)context; if (!smsdev) { sms_err("smsi2c_ts_enable smsdev NULL!!\n"); return -ENODEV; } return smsi2c_sendrequest(context, &TsEnableMsg, sizeof(TsEnableMsg)); //return i2c_master_normal_send(smsdev->client, &TsEnableMsg, sizeof(TsEnableMsg), I2C_SCL_TATE); //using 400KHz clk }
static int smsdvb_update_stats(struct smsdvb_client_t *client, struct dvb_frontend *fe) { int rc=0; unsigned long time_now = jiffies_to_msecs(jiffies); /* * warning : do not remove this operation mode check * smsdvb_get_statistics_ex will fail on DVBT */ if (smscore_get_device_mode(client->coredev) == DEVICE_MODE_DVBT_BDA) { return rc; } if ( (!client->last_sample_time) || (time_now - client->last_sample_time > 100) ) { /*sms_debug("%lu ms since last sample time, getting statistics", (time_now - client->last_sample_time));*/ rc = smsdvb_get_statistics_ex(fe); if (rc < 0) { sms_err("error in smsdvb_get_statistics_ex, rc = %d", rc); return rc; } } return rc; }
int sms_ir_init(struct smscore_device_t *coredev) { struct input_dev *input_dev; sms_log("Allocating input device"); input_dev = input_allocate_device(); if (!input_dev) { sms_err("Not enough memory"); return -ENOMEM; } coredev->ir.input_dev = input_dev; coredev->ir.ir_kb_type = sms_get_board(smscore_get_board_id(coredev))->ir_kb_type; coredev->ir.keyboard_layout_map = keyboard_layout_maps[coredev->ir.ir_kb_type]. keyboard_layout_map; sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type); coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ coredev->ir.timeout = IR_DEFAULT_TIMEOUT; sms_log("IR port %d, timeout %d ms", coredev->ir.controller, coredev->ir.timeout); snprintf(coredev->ir.name, IR_DEV_NAME_MAX_LEN, "SMS IR w/kbd type %d", coredev->ir.ir_kb_type); input_dev->name = coredev->ir.name; input_dev->phys = coredev->ir.name; input_dev->dev.parent = coredev->device; /* Key press events only */ input_dev->evbit[0] = BIT_MASK(EV_KEY); input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); sms_log("Input device (IR) %s is set for key events", input_dev->name); if (input_register_device(input_dev)) { sms_err("Failed to register device"); input_free_device(input_dev); return -EACCES; } return 0; }
int sms_ir_init(struct smscore_device_t *coredev) { struct input_dev *input_dev; int board_id = smscore_get_board_id(coredev); sms_log("Allocating input device"); input_dev = input_allocate_device(); if (!input_dev) { sms_err("Not enough memory"); return -ENOMEM; } coredev->ir.input_dev = input_dev; coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ coredev->ir.timeout = IR_DEFAULT_TIMEOUT; sms_log("IR port %d, timeout %d ms", coredev->ir.controller, coredev->ir.timeout); snprintf(coredev->ir.name, sizeof(coredev->ir.name), "SMS IR (%s)", sms_get_board(board_id)->name); strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); input_dev->name = coredev->ir.name; input_dev->phys = coredev->ir.phys; input_dev->dev.parent = coredev->device; coredev->ir.props.priv = coredev; coredev->ir.props.driver_type = RC_DRIVER_IR_RAW; coredev->ir.props.allowed_protos = IR_TYPE_ALL; sms_log("Input device (IR) %s is set for key events", input_dev->name); if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes, &coredev->ir.props, MODULE_NAME)) { sms_err("Failed to register device"); input_free_device(input_dev); return -EACCES; } return 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 void smscore_registry_settype(char *devpath, enum sms_device_type_st type) { struct smscore_registry_entry_t *entry; entry = smscore_find_registry(devpath); if (entry) entry->type = type; else sms_err("No registry found."); }
void smscore_registry_setmode(char *devpath, int mode) { struct smscore_registry_entry_t *entry; entry = smscore_find_registry(devpath); if (entry) entry->mode = mode; else sms_err("No registry found."); }
/* 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 sms_board_event(struct smscore_device_t *coredev, enum SMS_BOARD_EVENTS gevent) { struct smscore_gpio_config MyGpioConfig; sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); switch (gevent) { case BOARD_EVENT_POWER_INIT: /* including hotplug */ break; /* BOARD_EVENT_BIND */ case BOARD_EVENT_POWER_SUSPEND: break; /* BOARD_EVENT_POWER_SUSPEND */ case BOARD_EVENT_POWER_RESUME: break; /* BOARD_EVENT_POWER_RESUME */ case BOARD_EVENT_BIND: break; /* BOARD_EVENT_BIND */ case BOARD_EVENT_SCAN_PROG: break; /* BOARD_EVENT_SCAN_PROG */ case BOARD_EVENT_SCAN_COMP: break; /* BOARD_EVENT_SCAN_COMP */ case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ case BOARD_EVENT_FE_LOCK: break; /* BOARD_EVENT_FE_LOCK */ case BOARD_EVENT_FE_UNLOCK: break; /* BOARD_EVENT_FE_UNLOCK */ case BOARD_EVENT_DEMOD_LOCK: break; /* BOARD_EVENT_DEMOD_LOCK */ case BOARD_EVENT_DEMOD_UNLOCK: break; /* BOARD_EVENT_DEMOD_UNLOCK */ case BOARD_EVENT_RECEPTION_MAX_4: break; /* BOARD_EVENT_RECEPTION_MAX_4 */ case BOARD_EVENT_RECEPTION_3: break; /* BOARD_EVENT_RECEPTION_3 */ case BOARD_EVENT_RECEPTION_2: break; /* BOARD_EVENT_RECEPTION_2 */ case BOARD_EVENT_RECEPTION_1: break; /* BOARD_EVENT_RECEPTION_1 */ case BOARD_EVENT_RECEPTION_LOST_0: break; /* BOARD_EVENT_RECEPTION_LOST_0 */ case BOARD_EVENT_MULTIPLEX_OK: break; /* BOARD_EVENT_MULTIPLEX_OK */ case BOARD_EVENT_MULTIPLEX_ERRORS: break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ default: sms_err("Unknown SMS board event"); break; } return 0; }
static enum sms_device_type_st smscore_registry_gettype(char *devpath) { struct smscore_registry_entry_t *entry; entry = smscore_find_registry(devpath); if (entry) return entry->type; else sms_err("No registry found."); return -1; }
int smscore_registry_getmode(char *devpath) { struct smscore_registry_entry_t *entry; entry = smscore_find_registry(devpath); if (entry) return entry->mode; else sms_err("No registry found."); return default_mode; }
/** * sends the buffer to the associated device * * @param file File structure. * @param buf Source buffer. * @param count Size of source buffer. * @param f_pos Position in file (ignored). * * @return Number of bytes read, or <0 on error. */ static ssize_t smschar_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos) { struct smschar_device_t *dev; void *buffer; if (file == NULL) { sms_err("file is NULL\n"); return EINVAL; } if (file->private_data == NULL) { sms_err("file->private_data is NULL\n"); return -EINVAL; } dev = file->private_data; if (!dev->smsclient) { sms_err("no client\n"); return -ENODEV; } buffer = kmalloc(ALIGN(count, SMS_ALLOC_ALIGNMENT) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); if (buffer) { void *msg_buffer = (void *)SMS_ALIGN_ADDRESS(buffer); if (!copy_from_user(msg_buffer, buf, count)) smsclient_sendrequest(dev->smsclient, msg_buffer, count); else count = 0; kfree(buffer); } return count; }
int smsnet_hotplug(struct smscore_device_t *coredev, struct device *device, int arrival) { struct smsclient_params_t params; struct smsnet_client_t *client; int rc; /* device removal handled by onremove callback */ if (!arrival) return 0; client = kzalloc(sizeof(struct smsnet_client_t), GFP_KERNEL); if (!client) { sms_err("kmalloc() failed"); return -ENOMEM; } params.initial_id = 1; params.data_type = MSG_SMS_DATA_MSG; params.onresponse_handler = smsnet_onresponse; params.onremove_handler = smsnet_onremove; params.context = client; rc = smscore_register_client(coredev, ¶ms, &client->smsclient); if (rc < 0) { sms_err("smscore_register_client() failed %d", rc); kfree(client); return rc; } client->coredev = coredev; kmutex_lock(&g_smsnet_clientslock); list_add(&client->entry, &g_smsnet_clients); kmutex_unlock(&g_smsnet_clientslock); sms_info("success"); return 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; }
/** * 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; }
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); client->fe_status = FE_HAS_SIGNAL; client->event_fe_state = -1; client->event_unc_state = -1; switch (client->coredev->mode) { case DEVICE_MODE_DVBT_BDA: return smsdvb_tune_dvbt(client, fep); case DEVICE_MODE_ISDBT_BDA: return smsdvb_tune_isdbt(client, fep); default: sms_err("SMS Device mode %d is not set for DVB operation.", client->coredev->mode); return -EINVAL; } }
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; }
int smsdvb_debugfs_register(void) { struct dentry *d; /* * FIXME: This was written to debug Siano USB devices. So, it creates * the debugfs node under <debugfs>/usb. * A similar logic would be needed for Siano sdio devices, but, in that * case, usb_debug_root is not a good choice. * * Perhaps the right fix here would be to create another sysfs root * node for sdio-based boards, but this may need some logic at sdio * subsystem. */ d = debugfs_create_dir("smsdvb", usb_debug_root); if (IS_ERR_OR_NULL(d)) { sms_err("Couldn't create sysfs node for smsdvb"); return PTR_ERR(d); } else { smsdvb_debugfs_usb_root = d; } return 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(¶ms, 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(¶ms, &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; }