IC读卡芯片
是一个完全单芯片、低成本、低功耗、功能强大的智能读卡器。它具有多种用来减少功耗的模式以及宽的电源电压范围,使之非常适合使用在便携式
设备中。由于具有特殊的多用途硬件,小嵌入式软件程序能够控制市场上的大部份卡。
由于我们产品的串口都已经被占用,IC读卡芯片支持非标准I2C方式访问数据,所以我们改用I2C方式。CPU的I2C有标准I2C和GPIO
I2C两种方式。由于IC读卡芯片的I2C协议不是标准I2C,需要进行修改。所以我们选择从GPIO
I2C方式中进行简单修改以支持ALPAR协议访问格式。
下面是ALPAR协议格式:
由上图可知,协议发送或接收的数据长度在数据的第二第三字节定义。因此,我们只需要在读取数据过程中先得出数据长度即可。
以下部分是修改的代码,
+为添加部分:
-
Index: include/linux/i2c.h
-
===================================================================
-
--- include/linux/i2c.h (版本 986)
-
+++ include/linux/i2c.h (版本 988)
-
@@ -90,6 +90,12 @@
-
u8 command, u8 *values);
-
extern s32 i2c_smbus_write_block_data(struct i2c_client *client,
-
u8 command, u8 length, const u8 *values);
-
+/*
-
+* iUnin add for tda8029 ALPAR protocol. by yang.yuanming.
-
+* data: ACK(1) + length(2) + code(1) + data(n) +LRC(1) = n+5 n=0~506
-
+*/
-
+extern s32 i2c_smbus_read_alpar_data(struct i2c_client *client, u8 *values);
-
+extern s32 i2c_smbus_write_alpar_data(struct i2c_client *client, u8 length, const u8 *values);
-
/* Returns the number of read bytes */
-
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client,
-
u8 command, u8 length, u8 *values);
-
@@ -511,6 +517,7 @@
-
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
-
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
-
+#define I2C_M_ALPAR_RECV_LEN 0x0200 /* length will be n2&0xFF+n3+5 received byte */
-
__u16 len; /* msg length */
-
__u8 *buf; /* pointer to msg data */
-
};
-
@@ -566,6 +573,18 @@
-
/* and one more for user-space compatibility */
-
};
-
-
+/*
-
+* iUnin add for tda8029 ALPAR protocol. by yang.yuanming.
-
+* data: ACK(1) + length(2) + code(1) + data(n) +LRC(1) = n+5 n=0~506
-
+*/
-
+#define I2C_SMBUS_ALPAR_MAX 512 /* As specified in SMBus standard */
-
+union i2c_alpar_data {
-
+ __u8 byte;
-
+ __u16 word;
-
+ __u8 block[I2C_SMBUS_ALPAR_MAX]; /* block[0] is used for length */
-
+ /* and one more for user-space compatibility */
-
+};
-
+
-
/* i2c_smbus_xfer read or write markers */
-
#define I2C_SMBUS_READ 1
-
#define I2C_SMBUS_WRITE 0
-
@@ -581,5 +600,5 @@
-
#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
-
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
-
#define I2C_SMBUS_I2C_BLOCK_DATA 8
-
-
-
+#define I2C_SMBUS_ALPAR_DATA 9
-
#endif /* _LINUX_I2C_H */
-
Index: drivers/i2c/i2c-core.c
-
===================================================================
-
--- drivers/i2c/i2c-core.c (版本 986)
-
+++ drivers/i2c/i2c-core.c (版本 988)
-
@@ -1803,6 +1803,70 @@
-
}
-
EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
-
-
+
-
+/*
-
+* iUnin add for tda8029 ALPAR protocol. by yang.yuanming.
-
+* data: ACK(1) + length(2) + code(1) + data(n) +LRC(1) = n+5
-
+*/
-
+s32 i2c_smbus_read_alpar_data(struct i2c_client *client, u8 *values)
-
+{
-
+ union i2c_alpar_data data;
-
+ int status;
-
+ unsigned char msgbuf0[I2C_SMBUS_ALPAR_MAX];
-
+ int num = 1;
-
+ struct i2c_msg msg[1] = {{ client->addr, client->flags | I2C_M_RD, 0, msgbuf0 }
-
+ };
-
+
-
+ int i, alpar_len;
-
+ u8 partial_pec = 0;
-
+
-
+ msg[0].flags |= I2C_M_ALPAR_RECV_LEN;
-
+ msg[0].len = 5; /* block length will be added by the underlying bus driver */
-
+
-
+ status = i2c_transfer(client->adapter, msg, num);
-
+ if (status < 0)
-
+ return status;
-
+
-
+ /* Check PEC if last message is a read */
-
+ if (i && (msg[num-1].flags & I2C_M_RD)) {
-
+ status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
-
+ if (status < 0)
-
+ return status;
-
+ }
-
+
-
+ alpar_len = (msgbuf0[1]*256 +msgbuf0[2] + 5);
-
+ for (i = 0; i < alpar_len; i++)
-
+ data.block[i] = msgbuf0[i];
-
+
-
+ memcpy(values, &data.block[0], alpar_len);
-
+
-
+ return alpar_len;
-
+}
-
+EXPORT_SYMBOL(i2c_smbus_read_alpar_data);
-
+
-
+/*
-
+* iUnin add for tda8029 ALPAR protocol. by yang.yuanming.
-
+* data: ACK(1) + length(2) + code(1) + data(n) +LRC(1) = n+5
-
+*/
-
+s32 i2c_smbus_write_alpar_data(struct i2c_client *client, u8 length, const u8 *values)
-
+{
-
+ int status;
-
+
-
+ if (length > I2C_SMBUS_ALPAR_MAX)
-
+ length = I2C_SMBUS_ALPAR_MAX;
-
+
-
+ struct i2c_msg msg[1] = {{ client->addr, 0, length, values }
-
+ };
-
+
-
+ status = i2c_transfer(client->adapter, msg, 1);
-
+ if (status < 0)
-
+ return status;
-
+
-
+ return 0;
-
+}
-
+EXPORT_SYMBOL(i2c_smbus_write_alpar_data);
-
+
-
+
-
/* Simulate a SMBus command using the i2c protocol
-
No checking of parameters is */
-
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
-
Index: drivers/i2c/algos/i2c-algo-bit.c
-
===================================================================
-
--- drivers/i2c/algos/i2c-algo-bit.c (版本 986)
-
+++ drivers/i2c/algos/i2c-algo-bit.c (版本 988)
-
@@ -417,6 +417,25 @@
-
temp++;
-
count--;
-
-
+ /*
-
+ * iUnin add for tda8029 ALPAR protocol. by yang.yuanming.
-
+ * data: ACK(1) + length(2) + code(1) + data(n) +LRC(1) = n+5
-
+ */
-
+ if ((rdcount == 2 || rdcount == 3) && (flags & I2C_M_ALPAR_RECV_LEN)) {
-
+ /* The original count value accounts for the extra
-
+ bytes, that is, either 1 for a regular transaction,
-
+ or 2 for a PEC transaction. */
-
+ if(rdcount == 2){
-
+ count += (inval*256);
-
+ msg->len += (inval*256);
-
+ }
-
+ if(rdcount == 3){
-
+ count += inval;
-
+ msg->len += inval;
-
+ }
-
+
-
+ }
-
+
-
/* Some SMBus transactions require that we receive the
-
transaction length as the first read byte. */
-
if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) {
在完成协议小小修改部分后,IC读卡芯片驱动则相对简单了。真正的工作在上层的各种
IC卡的协议访问过程。这就是下部分的事情了。。。
阅读(1187) | 评论(0) | 转发(0) |