uint64_t ADM_ebml::readEBMCode(void) { uint64_t start=readu8(); uint64_t val; uint32_t mask=0x80,outmask=0x7F,more=0; aprintf("Start :%x at %llx\n",start,tell()-1); if(!start) { ADM_warning("Corruped EBML code\n"); return 0; } while(!(mask&start)) { mask>>=1; ADM_assert(mask); more++; } outmask=mask-1; start=start&outmask; for(int i=0;i<more;i++) { start=(start<<8)+readu8(); } aprintf("End at %llx\n",tell()); return start; }
int64_t ADM_ebml::readEBMCode_Signed(void) { uint8_t start=readu8(); int64_t val; uint32_t mask=0x80,outmask=0x7F,more=0; while(!(mask&start)) { mask>>=1; ADM_assert(mask); more++; } outmask=mask-1; val=start&outmask; for(int i=0;i<more;i++) { val=(val<<8)+readu8(); } // Signed ! switch(more) { case 0: val-=63;break; case 1: val-=8191;break; case 2: val-=1048575L;break; default: ADM_assert(0); return 0; } return val; }
static int getboundedstring_cb(lua_State* L) { size_t size; const char* start = luaL_checklstring(L, 1, &size); const char* send = start + size; int width = luaL_checkinteger(L, 2); const char* s = start; while (s < send) { const char* p = s; wchar_t c = readu8(&s); if (!iswcntrl(c)) { width -= emu_wcwidth(c); if (width < 0) { send = p; break; } } } lua_pushlstring(L, start, send - start); return 1; }
int64_t ADM_ebml::readSignedInt(uint32_t nb) { int64_t val=0; uint8_t r=0; r=readu8(); if(r&0x80) // sign val=-1; val=(val<<8)+r; for(int i=0;i<nb-1;i++) { r=readu8(); val=(val<<8)+r; } return val; }
/** \fn readEBMCode_Full \brief Returns complete code, including size-bits (used only for EBML_ID) */ uint64_t ADM_ebml::readEBMCode_Full(void) { uint64_t start=readu8(); uint32_t mask=0x80,more=0; aprintf(">>StartFull :%x at %llx\n",start,tell()-1); while(!(mask&start)) { mask>>=1; ADM_assert(mask); more++; } for(int i=0;i<more;i++) { start=(start<<8)+readu8(); } return start; }
uint64_t ADM_ebml::readUnsignedInt(uint32_t nb) { uint64_t val=0; for(int i=0;i<nb;i++) { val=(val<<8)+readu8(); } return val; }
uint8_t ADM_ebml::readString(char *string, uint32_t maxLen) { uint8_t v; while(maxLen--) { v=*string++=readu8(); if(!v) return 1; } *string=0; return 1; }
/** \fn readEBMCode_Full \brief Returns complete code, including size-bits (used only for EBML_ID) */ uint64_t ADM_ebml::readEBMCode_Full(void) { uint64_t start=readu8(); uint32_t mask=0x80,more=0; aprintf(">>StartFull :%x at %llx\n",start,tell()-1); if(!start) { ADM_warning("Corrupted EBML entry!\n"); return 0; } while(!(mask&start)) { mask>>=1; more++; } for(int i=0;i<more;i++) { start=(start<<8)+readu8(); } return start; }
static int getstringwidth_cb(lua_State* L) { size_t size; const char* s = luaL_checklstring(L, 1, &size); const char* send = s + size; int width = 0; while (s < send) { wchar_t c = readu8(&s); if (!iswcntrl(c)) width += emu_wcwidth(c); } lua_pushnumber(L, width); return 1; }
static int write_cb(lua_State* L) { int x = luaL_checkint(L, 1); int y = luaL_checkint(L, 2); size_t size; const char* s = luaL_checklstring(L, 3, &size); const char* send = s + size; while (s < send) { wchar_t c = readu8(&s); dpy_writechar(x, y, c); if (!iswcntrl(c)) x += emu_wcwidth(c); } return 0; }
uni_t dpy_getchar(int timeout) { while (numqueued == 0) { /* If a timeout was asked for, wait that long for an event. */ if ((timeout != -1) && !XPending(display)) { struct pollfd pfd = { .fd = ConnectionNumber(display), .events = POLLIN, .revents = 0 }; poll(&pfd, 1, timeout*1000); if (!pfd.revents) return -VK_TIMEOUT; } XEvent e; XNextEvent(display, &e); if (XFilterEvent(&e, window)) continue; switch (e.type) { case MapNotify: break; case Expose: { /* Mark some of the screen as needing redrawing. */ if (frontbuffer) { for (int y=0; y<screenheight; y++) { unsigned int* p = &frontbuffer[y * screenwidth]; for (int x=0; x<screenwidth; x++) p[x] = 0; } } redraw(); break; } case ConfigureNotify: { XConfigureEvent* xce = &e.xconfigure; int w = xce->width / fontwidth; int h = xce->height / fontheight; if ((w != screenwidth) || (h != screenheight)) { screenwidth = w; screenheight = h; if (frontbuffer) free(frontbuffer); frontbuffer = NULL; if (backbuffer) free(backbuffer); backbuffer = calloc(screenwidth * screenheight, sizeof(unsigned int)); push_key(-VK_RESIZE); } break; } case MappingNotify: case KeymapNotify: XRefreshKeyboardMapping(&e.xmapping); break; case KeyPress: { XKeyPressedEvent* xke = &e.xkey; KeySym keysym; char buffer[32]; Status status = 0; int charcount = Xutf8LookupString(xic, xke, buffer, sizeof(buffer)-1, &keysym, &status); int mods = 0; if (xke->state & ShiftMask) mods |= VKM_SHIFT; if (xke->state & ControlMask) mods |= VKM_CTRL; if ((keysym & 0xffffff00) == 0xff00) { /* Special function key. */ if (!IsModifierKey(keysym)) push_key(-(keysym | mods)); } else { const char* p = buffer; while ((p-buffer) < charcount) { uni_t c = readu8(&p); if (c < 32) { /* Ctrl + letter key */ push_key(-(VKM_CTRLASCII | c | mods)); } else { if (xke->state & Mod1Mask) push_key(-XK_Escape); push_key(c); } } } break; } } } return dequeue(); } const char* dpy_getkeyname(uni_t k) { static char buffer[32]; switch (-k) { case VK_RESIZE: return "KEY_RESIZE"; case VK_TIMEOUT: return "KEY_TIMEOUT"; case VK_REDRAW: return "KEY_REDRAW"; } int key = -k & ~VKM__MASK; int mods = -k & VKM__MASK; if (mods & VKM_CTRLASCII) { sprintf(buffer, "KEY_%s^%c", (mods & VKM_SHIFT) ? "S" : "", key + 64); return buffer; } const char* template = NULL;
/* 头格式 编码gbk Int 头大小 Int 内容大小 byte 静态页版本格式 0 or 1, 1:deadtime byte 是否有效 long 过期时间毫秒 long 生成时间毫秒 long 页号 byte 站类型 0 私有 1共享 >1 会员 int 关键词长度 byte[] 关键词 int ig号长度 byte[] ig Int 鉴权方式 0 不鉴权,1特殊页面鉴权,2php 特殊页面鉴权3,会员鉴权 int 额外参数的长度 byte[] 额外参数{PageAuth:{sid:,appid,authid:},GroupAuth:{sid,appid,authid}} byte[] 文件内容 */ page_t * file_read_path(char *path) { tbuf mt = {0, NULL}; if (tbuf_read(&mt, path)) { char *strpos; uint32_t strlen; stream_t s = {0, mt.len, (uint8_t*)mt.data}; size_t min = 2 * sizeof(uint32_t); if (mt.len < min) { tbuf_close(&mt); return NULL; } uint32_t hlen = readu32(&s); uint32_t blen = readu32(&s); if (mt.len != min+hlen+blen) { tbuf_close(&mt); return NULL; } /* |<-- page_t -->|<-- body data -->|<-- head strings -->| */ /* about 32 bytes in head is not for strings */ size_t plen = sizeof(page_t)+blen+hlen-32; page_t *page = (page_t*)smalloc(plen); page->page_len = plen; page->body_len = blen; page->body = (char*)page+sizeof(page_t); memcpy(page->body, mt.data+2*sizeof(uint32_t)+hlen, page->body_len); strpos = (char*)page->body + blen; page_head_t *head = &page->head; head->version = readu8(&s); switch(head->version) { case 0: head->valid = readu8(&s); head->time_expire = readu64(&s); head->time_create = readu64(&s); head->time_dead = head->time_expire+(uint64_t)24*3600*1000; head->page_no = readu64(&s); head->type = readu8(&s); strlen = readu32(&s); readarr(&s, strpos, strlen); *(strpos+strlen) = 0; head->keyword = strpos; strpos += strlen+1; strlen = readu32(&s); readarr(&s, strpos, strlen); *(strpos+strlen) = 0; head->ig = strpos; strpos += strlen+1; head->auth_type = readu32(&s); strlen = readu32(&s); readarr(&s, strpos, strlen); *(strpos+strlen) = 0; head->param = strpos; strpos += strlen+1; break; case 1: head->valid = readu8(&s); head->time_expire = readu64(&s); head->time_create = readu64(&s); head->time_dead = readu64(&s); head->page_no = readu64(&s); head->type = readu8(&s); strlen = readu32(&s); readarr(&s, strpos, strlen); *(strpos+strlen) = 0; head->keyword = strpos; strpos += strlen+1; strlen = readu32(&s); readarr(&s, strpos, strlen); *(strpos+strlen) = 0; head->ig = strpos; strpos += strlen+1; head->auth_type = readu32(&s); strlen = readu32(&s); readarr(&s, strpos, strlen); *(strpos+strlen) = 0; head->param = strpos; strpos += strlen+1; break; } tbuf_close(&mt); SYNC_ADD(&total_pages, 1); return page; } tbuf_close(&mt); return NULL; }
int main(int argc, char *argv[]) { int opt; while ((opt = getopt(argc, argv, "dh")) != -1) { switch (opt) { case 'd': printf("Debug messages on\n"); debug = 1; break; case 'h': printf("Usage: pixy_driver [options] [/path/to/spidev]\n"); printf("-d\tTurn on debug messages\n"); printf("-h\tPrint this help and exit\n"); exit(1); } } char *port = "/dev/spidev1.0"; if (argc > optind) port = argv[optind]; printf("Opening device %s\n", port); // Open SPI port and set mode int fd = open(port, O_RDWR); if (fd == -1) { perror("can't open SPI device"); abort(); } if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) perror("can't set spi mode"); if (ioctl(fd, SPI_IOC_RD_MODE, &mode) == -1) perror("can't read spi mode"); if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) perror("can't set bits per word"); if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) == -1) perror("can't read bits per word"); if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1) perror("can't set max speed"); if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1) perror("can't read max speed"); printf("SPI config: mode %d, %d bits per word, %d Hz max\n", mode, bits, speed); int valid_blocks = 0; int checksum_errors = 0; while (1) { int i; // IMPORTANT: data appears to be big-endian, despite the documentation // Wait for sync pattern 0xaa55 while ((i = readu8(fd)) != 0xaa) { //printf("%02x ", i); usleep(2000); } if ((i = readu8(fd)) == 0x55) { // Read blocks until zero byte is encountered // Blocks will begin with pattern 0xaa55 or 0xaa56 while ((i = readu8(fd)) == 0xaa) { if (debug) printf("%02x ", i); // Decode packet pixy_t msg = {}; int i = readu8(fd); if (debug) printf("%02x ", i); if (i == 0x55) msg.type = TYPE_NORMAL; else if (i == 0x56) msg.type = TYPE_COLOR_CODE; else break; msg.checksum = readu16(fd); // Stupid packet format is ambiguous: pixy will send 0xAA55 // BEFORE the block header to indicate the start of a frame. // Handle this case here: if (msg.checksum == 0xAA55) { msg.type = TYPE_NORMAL; msg.checksum = readu16(fd); } else if (msg.checksum == 0xAA56) { msg.type = TYPE_COLOR_CODE; msg.checksum = readu16(fd); } msg.signature = readu16(fd); msg.x = readu16(fd); msg.y = readu16(fd); msg.width = readu16(fd); msg.height = readu16(fd); if (msg.type == TYPE_COLOR_CODE) msg.angle = readu16(fd); else msg.angle = 0; if (debug) printf("%d %d %d %d %d %d %d\n", msg.checksum, msg.signature, msg.x, msg.y, msg.width, msg.height, msg.angle); // Verify checksum uint16_t checksum = msg.signature + msg.x + msg.y + msg.width + msg.height + msg.angle; if (msg.checksum != checksum) { printf("failed checksum: received %x, computed %x\n", msg.checksum, checksum); checksum_errors += 1; continue; } // Valid packet received // TODO: Publish to LCM valid_blocks += 1; if (msg.type == TYPE_COLOR_CODE) { printf("Color code %d (octal %o) at (%d, %d) size (%d, %d)" " angle %d\n", msg.signature, msg.signature, msg.x, msg.y, msg.width, msg.height, msg.angle); } else { printf("Signature %d at (%d, %d) size (%d, %d)\n", msg.signature, msg.x, msg.y, msg.width, msg.height); } } if (debug) printf("%d valid blocks read, %d failed checksum\n", valid_blocks, checksum_errors); } } printf("Exiting\n"); close(fd); }