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; }
struct _rx_buffer_st *allocate_rx_buf(void *context, int size) { struct smscore_buffer_t *buf; struct _spi_device_st *spi_device = (struct _spi_device_st *) context; if (size > RX_BUFFER_SIZE) { PERROR("Requested size is bigger than max buffer size.\n"); return NULL; } buf = smscore_getbuffer(spi_device->coredev); PDEBUG("Recieved Rx buf %p physical 0x%x (contained in %p)\n", buf->p, buf->phys, buf); /* note: this is not mistake! the rx_buffer_st is identical to part of smscore_buffer_t and we return the address of the start of the identical part */ return (struct _rx_buffer_st *) &buf->p; }
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; }
static void smssdio_interrupt(struct sdio_func *func) { int ret, isr; struct smssdio_device *smsdev; struct smscore_buffer_t *cb; struct SmsMsgHdr_ST *hdr; size_t size; smsdev = sdio_get_drvdata(func); /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ isr = sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { dev_err(&smsdev->func->dev, "Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { dev_err(&smsdev->func->dev, "Unable to allocate data buffer!\n"); return; } ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); if (ret) { dev_err(&smsdev->func->dev, "Error %d reading initial block!\n", ret); return; } hdr = cb->p; if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; return; } size = hdr->msgLength - smsdev->func->cur_blksize; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); smsdev->split_cb = NULL; } if (hdr->msgLength > smsdev->func->cur_blksize) { void *buffer; size = ALIGN(size, 128); buffer = cb->p + hdr->msgLength; BUG_ON(smsdev->func->cur_blksize != 128); /* * First attempt to transfer all of it in one go... */ ret = sdio_read_blocks(smsdev->func, buffer, SMSSDIO_DATA, size / 128); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); dev_err(&smsdev->func->dev, "Error %d reading data from card!\n", ret); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_read_blocks(smsdev->func, buffer, SMSSDIO_DATA, 1); if (ret) { smscore_putbuffer(smsdev->coredev, cb); dev_err(&smsdev->func->dev, "Error %d reading " "data from card!\n", ret); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } cb->size = hdr->msgLength; cb->offset = 0; smscore_onresponse(smsdev->coredev, cb); }
static void smssdio_work_thread(struct work_struct *arg) { int ret, isr; struct smscore_buffer_t *cb; struct SmsMsgHdr_S *hdr; size_t size; struct smssdio_device *smsdev = container_of(arg, struct smssdio_device, work_thread); struct sdio_func *sdfunc = smsdev->func; /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ sdio_claim_host(smsdev->func); isr = sdio_readb(smsdev->func, SMSSDIO_INT, &ret); if (ret) { sms_err("Got error reading interrupt status=%d, isr=%d\n", ret, isr); isr = sdio_readb(smsdev->func, SMSSDIO_INT, &ret); if (ret) { sms_err("Second read also failed, try to recover\n"); sdio_release_host(smsdev->func); sdfunc = kmemdup(smsdev->func, sizeof(struct sdio_func), GFP_KERNEL); if (!sdfunc) { sms_err("Out of memory!!!"); return; } sdfunc->num = 0; sdio_claim_host(sdfunc); sdio_writeb(sdfunc, 2, SMSSDIO_CCCR, &ret); sms_err("Read ISR status (write returned) %d\n", ret); isr = sdio_readb(smsdev->func, SMSSDIO_INT, &ret); sms_err("Read returned ret=%d, isr=%d\n", ret, isr); sdio_writeb(sdfunc, 0, SMSSDIO_CCCR, &ret); sdio_release_host(sdfunc); kfree(sdfunc); sms_err("Recovered, but this transaction is lost."); return; } sms_err("Second read succeed status=%d, isr=%d (continue)\n", ret, isr); } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { sms_err("Unable to allocate data buffer!\n"); sdio_release_host(smsdev->func); return; } ret = sdio_memcpy_fromio(smsdev->func, cb->p, SMSSDIO_DATA, SMSSDIO_BLOCK_SIZE); if (ret) { sms_warn("Error %d reading initial block, " "continue with sequence.\n", ret); } hdr = cb->p; if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; sdio_release_host(smsdev->func); return; } if (hdr->msgLength > smsdev->func->cur_blksize) size = hdr->msgLength - smsdev->func->cur_blksize; else size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msgLength - sizeof(struct SmsMsgHdr_S); smsdev->split_cb = NULL; } if (size) { void *buffer; buffer = cb->p + (hdr->msgLength - size); size = ALIGN(size, SMSSDIO_BLOCK_SIZE); BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); sms_err("Error %d reading data from card!\n", ret); sdio_release_host(smsdev->func); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); sms_err("Error %d reading " "data from card!\n", ret); sdio_release_host(smsdev->func); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } sdio_release_host(smsdev->func); cb->size = hdr->msgLength; cb->offset = 0; smscore_onresponse(smsdev->coredev, cb); }
static void smssdio_interrupt(struct sdio_func *func) { int ret; struct smssdio_device *smsdev; struct smscore_buffer_t *cb; struct sms_msg_hdr *hdr; size_t size; smsdev = sdio_get_drvdata(func); /* * The interrupt register has no defined meaning. It is just * a way of turning of the level triggered interrupt. */ (void)sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { pr_err("Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { pr_err("Unable to allocate data buffer!\n"); return; } ret = sdio_memcpy_fromio(smsdev->func, cb->p, SMSSDIO_DATA, SMSSDIO_BLOCK_SIZE); if (ret) { pr_err("Error %d reading initial block!\n", ret); return; } hdr = cb->p; if (hdr->msg_flags & MSG_HDR_FLAG_SPLIT_MSG) { smsdev->split_cb = cb; return; } if (hdr->msg_length > smsdev->func->cur_blksize) size = hdr->msg_length - smsdev->func->cur_blksize; else size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; size = hdr->msg_length - sizeof(struct sms_msg_hdr); smsdev->split_cb = NULL; } if (size) { void *buffer; buffer = cb->p + (hdr->msg_length - size); size = ALIGN(size, SMSSDIO_BLOCK_SIZE); BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); pr_err("Error %d reading data from card!\n", ret); return; } /* * ..then fall back to one block at a time if that is * not possible... * * (we have to do this manually because of the * problem with the "increase address" bit) */ if (ret == -EINVAL) { while (size) { ret = sdio_memcpy_fromio(smsdev->func, buffer, SMSSDIO_DATA, smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); pr_err("Error %d reading data from card!\n", ret); return; } buffer += smsdev->func->cur_blksize; if (size > smsdev->func->cur_blksize) size -= smsdev->func->cur_blksize; else size = 0; } } } cb->size = hdr->msg_length; cb->offset = 0; smsendian_handle_rx_message((struct sms_msg_data *) cb->p); smscore_onresponse(smsdev->coredev, cb); }
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; }