static int smschar_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct smschar_device_t *dev = file->private_data; void __user *up = (void __user *)arg; if (!dev->coredev || !dev->smsclient) { sms_err("no client\n"); return -ENODEV; } switch (cmd) { case SMSCHAR_SET_DEVICE_MODE: return smscore_set_device_mode(dev->coredev, (int)arg); case SMSCHAR_GET_DEVICE_MODE: { if (put_user(smscore_get_device_mode(dev->coredev), (int *)up)) return -EFAULT; break; } case SMSCHAR_IS_DEVICE_PNP_EVENT: { sms_info("Waiting for PnP event.\n"); wait_event_interruptible(g_pnp_event, !g_pnp_status_changed); g_pnp_status_changed = 0; sms_info("PnP Event %d.\n", g_smschar_inuse); if (put_user(g_smschar_inuse, (int *)up)) return -EFAULT; break; } case SMSCHAR_GET_BUFFER_SIZE: { if (put_user (smscore_get_common_buffer_size(dev->coredev), (int *)up)) return -EFAULT; break; } case SMSCHAR_WAIT_GET_BUFFER: { struct smschar_buffer_t touser; int rc; rc = smschar_wait_get_buffer(dev, &touser); if (rc < 0) return rc; if (copy_to_user(up, &touser, sizeof(struct smschar_buffer_t))) return -EFAULT; break; } case SMSCHAR_CANCEL_WAIT_BUFFER: { dev->cancel_waitq = 1; wake_up_interruptible(&dev->waitq); break; } case SMSCHAR_CANCEL_POLL: { /*obsollete*/ break; } case SMSCHAR_GET_FW_FILE_NAME: { if (!up) return -EINVAL; return smschar_get_fw_filename(dev, (struct smschar_get_fw_filename_ioctl_t*)up); } case SMSCHAR_SEND_FW_FILE: { if (!up) return -EINVAL; return smschar_send_fw_file(dev, (struct smschar_send_fw_file_ioctl_t*)up); } default: return -ENOIOCTLCMD; } return 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; }