1 2 /* 3 * Atmel mxt probably mxt1188s-a or mxt1664s-a or mxt3432s or mxt143e 4 * I think its the mxt143e 5 * 6 * URL for original source material: 7 * http://www.atmel.com/products/touchsolutions/touchscreens/unlimited_touch.aspx 8 * GIT for original source material: 9 * git://github.com/atmel-maxtouch/obp-utils.git 10 * 11 * cc obp-utils.c test_atmel.c -o /tmp/test -I/usr/src/sys/ 12 * 13 * kldload smb before running test program to get /dev/smb* 14 */ 15 #include <sys/types.h> 16 #include <sys/file.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 #include <fcntl.h> 21 #include <string.h> 22 #include <assert.h> 23 #include <dev/smbus/smb/smb.h> 24 #include <bus/smbus/smbconf.h> 25 26 #include "obp-utils.h" 27 28 static const char * 29 mxt_gettypestring(int type) 30 { 31 static const struct mxt_strinfo strinfo[] = { MXT_INIT_STRINGS }; 32 int i; 33 34 for (i = 0; i < sizeof(strinfo) / sizeof(strinfo[0]); ++i) { 35 if (strinfo[i].type == type) 36 return(strinfo[i].id); 37 } 38 return("unknown"); 39 } 40 41 struct mxt_object * 42 mxt_findobject(struct mxt_rollup *rup, int type) 43 { 44 int i; 45 46 for (i = 0; i < rup->nobjs; ++i) { 47 if (rup->objs[i].type == type) 48 return(&rup->objs[i]); 49 } 50 return NULL; 51 } 52 53 static int 54 mxt_read_reg(int fd, uint16_t reg, void *rbuf, int bytes) 55 { 56 struct smbcmd cmd; 57 uint8_t wbuf[2]; 58 int r; 59 60 bzero(&cmd, sizeof(cmd)); 61 wbuf[0] = reg & 255; 62 wbuf[1] = reg >> 8; 63 cmd.slave = 0; 64 cmd.rbuf = rbuf; 65 cmd.wbuf = wbuf; 66 cmd.wcount = 2; 67 cmd.rcount = bytes; 68 cmd.op = SMB_TRANS_NOCNT | SMB_TRANS_NOCMD | SMB_TRANS_7BIT; 69 70 r = ioctl(fd, SMB_TRANS, &cmd); 71 if (r == 0) { 72 return cmd.rcount; 73 } else { 74 printf("status r = %d slave 0x%02x\n", r, cmd.slave); 75 return -1; 76 } 77 } 78 79 static int 80 mxt_write_reg_buf(int fd, uint16_t reg, void *xbuf, int bytes) 81 { 82 struct smbcmd cmd; 83 uint8_t wbuf[256]; 84 int r; 85 86 assert(bytes < sizeof(wbuf) - 2); 87 wbuf[0] = reg & 0xff; 88 wbuf[1] = reg >> 8; 89 bcopy(xbuf, wbuf + 2, bytes); 90 91 cmd.slave = 0; 92 cmd.rbuf = NULL; 93 cmd.wbuf = wbuf; 94 cmd.wcount = bytes + 2; 95 cmd.rcount = 0; 96 cmd.op = SMB_TRANS_NOCNT | SMB_TRANS_NOCMD | SMB_TRANS_7BIT; 97 98 r = ioctl(fd, SMB_TRANS, &cmd); 99 if (r == 0) { 100 return 0; 101 } else { 102 printf("status r = %d slave 0x%02x\n", r, cmd.slave); 103 return -1; 104 } 105 } 106 107 static int 108 mxt_write_reg(int fd, uint16_t reg, uint8_t val) 109 { 110 return mxt_write_reg_buf(fd, reg, &val, 1); 111 } 112 113 static int 114 mxt_read_object(int fd, struct mxt_object *obj, void *rbuf, int rbytes) 115 { 116 uint16_t reg = obj->start_pos_lsb + (obj->start_pos_msb << 8); 117 int bytes = obj->size_minus_one + 1; 118 119 if (bytes > rbytes) 120 bytes = rbytes; 121 return mxt_read_reg(fd, reg, rbuf, bytes); 122 } 123 124 125 static int 126 mxt_t6_command(int fd, uint16_t t6cmd, uint8_t t6val, int waitforme) 127 { 128 uint8_t status; 129 130 mxt_write_reg(fd, 6 + t6cmd, t6val); 131 132 while (waitforme) { 133 if (mxt_read_reg(fd, 6 + t6cmd, &status, 1) != 1) 134 break; 135 if (status) 136 return status; 137 } 138 return 0; 139 } 140 141 static 142 const char * 143 msgflagsstr(uint8_t flags) 144 { 145 static char buf[9]; 146 147 buf[0] = (flags & MXT_MSGF_DETECT) ? 'D' : '.'; 148 buf[1] = (flags & MXT_MSGF_PRESS) ? 'P' : '.'; 149 buf[2] = (flags & MXT_MSGF_RELEASE) ? 'R' : '.'; 150 buf[3] = (flags & MXT_MSGF_MOVE) ? 'M' : '.'; 151 buf[4] = (flags & MXT_MSGF_VECTOR) ? 'V' : '.'; 152 buf[5] = (flags & MXT_MSGF_AMP) ? 'A' : '.'; 153 buf[6] = (flags & MXT_MSGF_SUPPRESS) ? 'S' : '.'; 154 buf[7] = (flags & MXT_MSGF_UNGRIP) ? 'U' : '.'; 155 156 return buf; 157 } 158 159 int 160 main(int ac, char **av) 161 { 162 uint8_t rbuf[1024]; 163 struct mxt_rollup rup; 164 struct mxt_object *obj; 165 int fd; 166 int i; 167 int n; 168 int r; 169 size_t blksize; 170 size_t totsize; 171 uint32_t crc; 172 173 fd = open("/dev/smb1-4a", O_RDWR); 174 printf("fd = %d\n", fd); 175 176 r = mxt_t6_command(fd, 0/*RESET*/, 0x01, 1); 177 printf("reset result %d\n", r); 178 179 n = mxt_read_reg(fd, 0, &rup.info, sizeof(rup.info)); 180 for (i = 0; i < n; ++i) 181 printf(" %02x", ((uint8_t *)&rup.info)[i]); 182 printf("\n"); 183 rup.nobjs = rup.info.num_objects; 184 185 blksize = sizeof(rup.info) + 186 rup.nobjs * sizeof(struct mxt_object); 187 totsize = blksize + sizeof(struct mxt_raw_crc); 188 assert(totsize < sizeof(rbuf)); 189 190 n = mxt_read_reg(fd, 0, rbuf, totsize); 191 if (n != totsize) { 192 printf("mxt_read_reg: config failed: %d/%d\n", n, totsize); 193 exit(1); 194 } 195 crc = obp_convert_crc((struct mxt_raw_crc *)(rbuf + blksize)); 196 if (obp_crc24(rbuf, blksize) != crc) { 197 printf("info: crc failed %08x/%08x\n", 198 crc, 199 obp_crc24(rbuf, blksize)); 200 exit(1); 201 } 202 rup.objs = (void *)(rbuf + sizeof(rup.info)); 203 for (i = 0; i < rup.nobjs; ++i) { 204 obj = &rup.objs[i]; 205 printf("object %d (%s) {\n", 206 obj->type, 207 mxt_gettypestring(obj->type)); 208 printf(" position = %d\n", 209 obj->start_pos_lsb + (obj->start_pos_msb << 8)); 210 printf(" size = %d\n", 211 obj->size_minus_one + 1); 212 printf(" instances= %d\n", 213 obj->instances_minus_one + 1); 214 printf(" numids = %d\n", 215 obj->num_report_ids); 216 } 217 printf("\n"); 218 fflush(stdout); 219 220 obj = mxt_findobject(&rup, MXT_GEN_MESSAGEPROCESSOR); 221 assert(obj != NULL); 222 223 for (;;) { 224 mxt_message_t msg; 225 226 n = mxt_read_object(fd, obj, &msg, sizeof(msg)); 227 if (msg.any.reportid == 255) 228 continue; 229 for (i = 0; i < n; ++i) 230 printf(" %02x", ((uint8_t *)&msg)[i]); 231 printf(" trk=%02x f=%s x=%-4d y=%-4d p=%d amp=%d\n", 232 msg.any.reportid, 233 msgflagsstr(msg.touch.flags), 234 (msg.touch.pos[0] << 4) | 235 ((msg.touch.pos[2] >> 4) & 0x0F), 236 (msg.touch.pos[1] << 4) | 237 ((msg.touch.pos[2]) & 0x0F), 238 msg.touch.area, 239 msg.touch.amplitude); 240 usleep(100000); 241 } 242 } 243