/**\brief 通过本地socket连接到服务 * \param[in] name 服务名称 * \param[out] fd 返回socket * \return * - AM_SUCCESS 成功 * - 其他值 错误代码 */ AM_ErrorCode_t AM_LocalConnect(const char *name, int *fd) { struct sockaddr_un addr; int s, ret; #if 0 assert(name && fd); s = socket(AF_LOCAL, SOCK_STREAM, 0); if(s==-1) { AM_DEBUG(1, "cannot create local socket \"%s\"", strerror(errno)); return AM_FAILURE; } addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, name, sizeof(addr.sun_path)-1); ret = connect(s, (struct sockaddr*)&addr, SUN_LEN(&addr)); if(ret==-1) { AM_DEBUG(1, "connect to \"%s\" failed \"%s\"", name, strerror(errno)); close(s); return AM_FAILURE; } *fd = s; #endif return AM_SUCCESS; }
/**\brief 将像素映射为颜色 * \param[in] fmt 图形模式 * \param[in] pix 像素值 * \param[out] col 返回映射的颜色值 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码(见am_osd.h) */ AM_ErrorCode_t AM_OSD_MapPixel(AM_OSD_PixelFormat_t *fmt, uint32_t pix, AM_OSD_Color_t *col) { assert(fmt && col); if(AM_OSD_PIXEL_FORMAT_TYPE_IS_PALETTE(fmt->type)) { if(pix>=fmt->palette.color_count) { AM_DEBUG(1, "illegal pixel, must in (0~%d)", fmt->palette.color_count-1); return AM_OSD_ERR_ILLEGAL_PIXEL; } *col = fmt->palette.colors[pix]; } else if(AM_OSD_PIXEL_FORMAT_TYPE_IS_YUV(fmt->type)) { AM_DEBUG(1, "cannot map YUV pixel to color"); return AM_OSD_ERR_NOT_SUPPORTED; } else { AM_RGB_PIXEL_TO_COLOR(fmt, pix, col); } return AM_SUCCESS; }
/**\brief 通过本地socket发送命令 * \param fd socket * \param[in] cmd 命令字符串 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码 */ AM_ErrorCode_t AM_LocalSendCmd(int fd, const char *cmd) { AM_ErrorCode_t ret; int len; assert(cmd); len = strlen(cmd)+1; ret = try_write(fd, (const char*)&len, sizeof(int)); if(ret!=AM_SUCCESS) { AM_DEBUG(1, "write local socket failed"); return ret; } ret = try_write(fd, cmd, len); if(ret!=AM_SUCCESS) { AM_DEBUG(1, "write local socket failed"); return ret; } AM_DEBUG(2, "write cmd: %s", cmd); return AM_SUCCESS; }
/**************************************************************************** * Functions ***************************************************************************/ static AM_ErrorCode_t dvb_open (AM_FEND_Device_t *dev, const AM_FEND_OpenPara_t *para) { char name[PATH_MAX]; int fd; #if 1 snprintf(name, sizeof(name), "/dev/dvb0.frontend%d", dev->dev_no); fd = open(name, O_RDWR); if(fd==-1) { AM_DEBUG(1, "cannot open %s, error:%s", name, strerror(errno)); return AM_FEND_ERR_CANNOT_OPEN; } if(ioctl(fd, FE_GET_INFO, &dev->info)) { close(fd); AM_DEBUG(1, "cannot get frontend's infomation, error:%s", strerror(errno)); return AM_FEND_ERR_IO; } dev->drv_data = (void*)fd; #endif return AM_SUCCESS; }
/**\brief 通过本地socket接收响应字符串 * \param fd socket * \param[out] buf 缓冲区 * \param len 缓冲区大小 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码 */ AM_ErrorCode_t AM_LocalGetResp(int fd, char *buf, int len) { AM_ErrorCode_t ret; int bytes; assert(buf); ret = try_read(fd, (char*)&bytes, sizeof(int)); if(ret!=AM_SUCCESS) { AM_DEBUG(1, "read local socket failed"); return ret; } if(len<bytes) { AM_DEBUG(1, "respond buffer is too small"); return AM_FAILURE; } ret = try_read(fd, buf, bytes); if(ret!=AM_SUCCESS) { AM_DEBUG(1, "read local socket failed"); return ret; } return AM_SUCCESS; }
static AM_ErrorCode_t dvb_sec_begin_cb (void *user_data, const char *sec) { AM_DVBConfig_t *conf=(AM_DVBConfig_t*)user_data; if(conf->in_service_sec) { AM_DEBUG(1, "unknown section"); return AM_CFG_ERR_SYNTAX; } if(!strcmp(sec, "service")) { if(conf->service_count<MAX_SERVICE_COUNT) { conf->service_count++; } else { AM_DEBUG(1, "too many services"); } conf->in_service_sec = 1; return AM_SUCCESS; } return AM_CFG_ERR_UNKNOWN_TAG; }
static int vol_update (DTV_Window_t *win, AM_OSD_Surface_t *s) { AM_ErrorCode_t ret = AM_SUCCESS; AM_OSD_Rect_t sr, dr; int i =0 ,tmp; ret = AM_AOUT_GetVolume(DTV_AOUT_DEV_NO, &(vol.cur_vol_value)); if(ret!=AM_SUCCESS) { printf("AM_AOUT_SetVolume fail!\n"); } else { AM_DEBUG(1, "vol_value = %d",vol.cur_vol_value); } //draw vol bar sr.x = 0; sr.y = 0; sr.w = gfx.volume_img->width; sr.h = gfx.volume_img->height; dr.x = 300; dr.y = 450; dr.w = gfx.volume_img->width; dr.h = gfx.volume_img->height; AM_OSD_Blit(gfx.volume_img, &sr, s, &dr, NULL); if(tmp = vol.cur_vol_value / VOL_VALUE_STEP) AM_DEBUG(1, "%d\n",tmp); for(i=0;i<tmp;i++) { sr.x = 0; sr.w = 0; sr.w = gfx.volume_value_img->width; sr.h = gfx.volume_value_img->height; dr.x = 376 + ( i * (gfx.volume_value_img->width + 4)); dr.y = 459; dr.w = gfx.volume_value_img->width; dr.h = gfx.volume_value_img->height; AM_OSD_Blit(gfx.volume_value_img, &sr, s, &dr, NULL); } AM_TIME_GetClock(&now); return 0; }
static void dump_bytes(int dev_no, int fid, const uint8_t *data, int len, void *user_data) { FILE *fp; int did = data[8]; int sec = data[6]; #if 0 if(did!=3) return; if(sections[sec].got) { if((sections[sec].len!=len) || memcmp(sections[sec].data, data, len)) { AM_DEBUG(1, "SECTION %d MISMATCH LEN: %d", sec, len); } } else { sections[sec].len = len; sections[sec].got = 1; memcpy(sections[sec].data, data, len); AM_DEBUG(1, "GET SECTION %d LEN: %d", sec, len); } #endif #if 0 int did = data[8]; int bid = (data[9]<<24)|(data[10]<<16)|(data[11]<<8)|data[12]; int sec = data[6]; if(did!=3) return; if(sec_mask[sec]) return; sec_mask[sec] = 1; AM_DEBUG(1, "get section %d", sec); fseek(fp, bid*4030, SEEK_SET); fwrite(data+13, 1, len-17, fp); #endif #if 1 int i; printf("section:\n"); for(i=0;i<len;i++) { printf("%02x ", data[i]); if(((i+1)%16)==0) printf("\n"); } if((i%16)!=0) printf("\n"); #endif }
static void si_section_callback(int dev_no, int fid, const uint8_t *data, int len, void *user_data) { int hsi; int t; AM_SI_SectionHeader_t header; void *p_table; AM_DEBUG(1, "GET A SECTION LEN: %d", len); t = get_sec_by_hfilter(fid); if (t == -1) { AM_DEBUG(1, "Unknown filter id 0x%x", fid); return; } /*Copy the data*/ memcpy(si_sections[t].data, data, len); AM_SI_Create(&hsi); AM_SI_GetSectionHeader(hsi, (uint8_t*)si_sections[t].data, (uint16_t)len, &header); /*Print the header*/ AM_DEBUG(1, "SectionHeader::\n\ttable_id\t\t0x%x\n\tsyntax_indicator\t0x%x\n\tprv_indicator\t\t0x%x\n\tlength\t\t\t0x%x\n\textension\t\t0x%x\n\tverion\t\t\t0x%x\n\tcur_next\t\t0x%x\n\tsec_num\t\t\t0x%x\n\tlast_sec_num\t\t0x%x", header.table_id,header.syntax_indicator,header.private_indicator, header.length, header.extension, header.version, header.cur_next_indicator, header.sec_num, header.last_sec_num); /*Decode*/ if (AM_SI_DecodeSection(hsi, si_sections[t].pid, (uint8_t*)si_sections[t].data, (uint16_t)len, &p_table) == AM_SUCCESS) { AM_DEBUG(1, "Section Successfully decoded"); /*Print detail*/ if (si_sections[t].print) si_sections[t].print(p_table); AM_SI_ReleaseSection(hsi, p_table->i_table_id, (void*)p_table); } else { AM_DEBUG(1, "Section decoded failed"); } AM_SI_Destroy(hsi); si_sections[t].last_sec = header.last_sec_num; /*Start next section receive*/ si_test_table_start_next_section(t); }
/**\brief 将字符串值转化为整数 * \param[in] value 字符串值 * \param[out] pv 输出整数的指针 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码(见am_cfg.h) */ AM_ErrorCode_t AM_CFG_Value2Int(const char *value, int *pv) { int rc; assert(value && pv); if(value[0]=='0') { if((value[1]=='x')||(value[1]=='X')) { rc = sscanf(value+2, "%x", pv); } else { rc = sscanf(value, "%o", pv); } } else { rc = sscanf(value, "%d", pv); } if(rc!=1) { AM_DEBUG(1, "key is not an integer"); return AM_CFG_ERR_BAD_FOTMAT; } return AM_SUCCESS; }
/**\brief 注册一个事件回调函数 * \param dev_no 回调函数对应的设备ID * \param event_type 回调函数对应的事件类型 * \param cb 回调函数指针 * \param data 传递给回调函数的用户定义参数 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码 */ AM_ErrorCode_t AM_EVT_Subscribe(int dev_no, int event_type, AM_EVT_Callback_t cb, void *data) { AM_Event_t *evt; int pos; assert(cb); /*分配事件*/ evt = malloc(sizeof(AM_Event_t)); if(!evt) { AM_DEBUG(1, "not enough memory"); return AM_EVT_ERR_NO_MEM; } evt->dev_no = dev_no; evt->type = event_type; evt->cb = cb; evt->data = data; pos = event_type%AM_EVT_BUCKET_COUNT; /*加入事件哈希表中*/ pthread_mutex_lock(&lock); evt->next = events[pos]; events[pos] = evt; pthread_mutex_unlock(&lock); return AM_SUCCESS; }
/**\brief 创建一个单元格控件*/ static AM_ErrorCode_t table_cell_create(AM_GUI_Table_t *tab, AM_GUI_Widget_t **cell, int row, int col, int hspan, int vspan) { AM_GUI_TableCell_t *c; AM_ErrorCode_t ret; c = (AM_GUI_TableCell_t*)malloc(sizeof(AM_GUI_TableCell_t)); if(!cell) { AM_DEBUG(1, "not enough memory"); return AM_GUI_ERR_NO_MEM; } ret = AM_GUI_WidgetInit(AM_GUI_WIDGET(tab)->gui, AM_GUI_WIDGET(c)); if(ret!=AM_SUCCESS) { free(c); return ret; } AM_GUI_WIDGET(c)->type = AM_GUI_WIDGET_TABLE_CELL; c->row = row; c->col = col; c->hspan = hspan; c->vspan = vspan; *cell = AM_GUI_WIDGET(c); return AM_SUCCESS; }
static AM_ErrorCode_t dvb_set_source(AM_DMX_Device_t *dev, AM_DMX_Source_t src) { char buf[32]; char *cmd; snprintf(buf, sizeof(buf), "/sys/class/stb/demux%d_source", dev->dev_no); switch(src) { case AM_DMX_SRC_TS0: cmd = "ts0"; break; case AM_DMX_SRC_TS1: cmd = "ts1"; break; case AM_DMX_SRC_TS2: cmd = "ts2"; break; case AM_DMX_SRC_HIU: cmd = "hiu"; break; default: AM_DEBUG(1, "do not support demux source %d", src); return AM_DMX_ERR_NOT_SUPPORTED; } return AM_FileEcho(buf, cmd); }
AM_ErrorCode_t aml_write (AM_SMC_Device_t *dev, const uint8_t *data, int *len, int timeout) { struct pollfd pfd; int fd = (int)dev->drv_data; int ret; pfd.fd = fd; pfd.events = POLLOUT; ret = poll(&pfd, 1, timeout); if(ret!=1) { return AM_SMC_ERR_TIMEOUT; } ret = write(fd, data, *len); if(ret<0) { AM_DEBUG(1, "card write error %s", strerror(errno)); return AM_SMC_ERR_IO; } *len = ret; return AM_SUCCESS; }
/**\brief Performs a blind scan operation.*/ static AM_ErrorCode_t AM_FEND_IBlindScanAPI_Start(int dev_no) { AM_FEND_Device_t *dev = NULL; AM_ErrorCode_t ret = AM_SUCCESS; fend_get_openned_dev(dev_no, &dev); if(!dev->drv->blindscan_scan) { AM_DEBUG(1, "fronend %d no not support blindscan_scan", dev_no); return AM_FEND_ERR_NOT_SUPPORTED; } pthread_mutex_lock(&dev->lock); struct dvbsx_blindscanpara * pbsPara = &(dev->bs_setting.bsPara); /*driver need to set in blindscan mode*/ ret = dev->drv->blindscan_scan(dev, pbsPara); if(ret != AM_SUCCESS) { ret = AM_FEND_ERR_BLINDSCAN; pthread_mutex_unlock(&dev->lock); return ret; } pthread_mutex_unlock(&dev->lock); return ret; }
static AM_ErrorCode_t dvb_read(AM_DMX_Device_t *dev, AM_DMX_Filter_t *filter, uint8_t *buf, int *size) { int fd = (int)filter->drv_data; int len = *size; int ret; struct pollfd pfd; if(fd==-1) return AM_DMX_ERR_NOT_ALLOCATED; pfd.events = POLLIN|POLLERR; pfd.fd = fd; ret = poll(&pfd, 1, 0); if(ret<=0) return AM_DMX_ERR_NO_DATA; ret = read(fd, buf, len); if(ret<=0) { if(errno==ETIMEDOUT) return AM_DMX_ERR_TIMEOUT; AM_DEBUG(1, "read demux failed (%s) %d", strerror(errno), errno); return AM_DMX_ERR_SYS; } *size = ret; return AM_SUCCESS; }
AM_ErrorCode_t AM_CFG_Input(const char *path, AM_CFG_SecBeginCb_t sec_begin_cb, AM_CFG_KeyCb_t key_cb, AM_CFG_SecEndCb_t sec_end_cb, void *user_data) { AM_CFG_Parser_t parser; FILE *fp; AM_ErrorCode_t ret; assert(path); if (!(fp = fopen(path, "r"))) { AM_DEBUG(1, "%s", strerror(errno)); return AM_CFG_ERR_CANNOT_OPEN_FILE; } memset(&parser, 0, sizeof(AM_CFG_Parser_t)); parser.path = path; parser.line = 1; parser.fp = fp; parser.sec_begin_cb = sec_begin_cb; parser.sec_end_cb = sec_end_cb; parser.key_cb = key_cb; parser.user_data = user_data; ret = cfg_parse(&parser); if(parser.sec_stack) { AM_DEBUG(1, "\'}\' mismatch"); cfg_error(&parser); } while(parser.sec_stack) { cfg_pop_sec(&parser); } if(parser.buffer) AM_MEM_Free(parser.buffer); fclose(fp); return ret; }
/**\brief 根据设备号取得设备结构指针*/ static AM_INLINE AM_ErrorCode_t fend_get_dev(int dev_no, AM_FEND_Device_t **dev) { if((dev_no<0) || (dev_no>=FEND_DEV_COUNT)) { AM_DEBUG(1, "invalid frontend device number %d, must in(%d~%d)", dev_no, 0, FEND_DEV_COUNT-1); return AM_FEND_ERR_INVALID_DEV_NO; } *dev = &fend_devices[dev_no]; return AM_SUCCESS; }
/**\brief 根据设备号取得设备结构指针*/ static AM_INLINE AM_ErrorCode_t dmx_get_dev(int dev_no, AM_DMX_Device_t **dev) { if((dev_no<0) || (dev_no>=DMX_DEV_COUNT)) { AM_DEBUG(1, "invalid demux device number %d, must in(%d~%d)", dev_no, 0, DMX_DEV_COUNT-1); return AM_DMX_ERR_INVALID_DEV_NO; } *dev = &dmx_devices[dev_no]; return AM_SUCCESS; }
/**\brief 根据设备号取得设备结构*/ static AM_INLINE AM_ErrorCode_t vout_get_dev(int dev_no, AM_VOUT_Device_t **dev) { if((dev_no<0) || (dev_no>=VOUT_DEV_COUNT)) { AM_DEBUG(1, "invalid vout device number %d, must in(%d~%d)", dev_no, 0, VOUT_DEV_COUNT-1); return AM_VOUT_ERR_INVALID_DEV_NO; } *dev = &vout_devices[dev_no]; return AM_SUCCESS; }
/**\brief 设定调色板,此操作只对调色板模式的表面有效 * \param[in] s 绘图表面 * \param[in] pal 设定颜色数组 * \param start 要设定的调色板起始项 * \param count 要设定的颜色数目 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码(见am_osd.h) */ AM_ErrorCode_t AM_OSD_SetPalette(AM_OSD_Surface_t *surf, AM_OSD_Color_t *pal, int start, int count) { AM_OSD_PixelFormat_t *fmt; int first, last; AM_ErrorCode_t ret = AM_SUCCESS; assert(surf && pal); fmt = surf->format; if(!AM_OSD_PIXEL_FORMAT_TYPE_IS_PALETTE(fmt->type)) { AM_DEBUG(1, "not a palette pixel format"); return AM_OSD_ERR_NOT_SUPPORTED; } first = AM_MAX(0, start); last = AM_MIN(fmt->palette.color_count, start+count); start = first; count = last-first; if(count) { memcpy(fmt->palette.colors+start, pal, count*sizeof(AM_OSD_Color_t)); if(surf->flags&AM_OSD_SURFACE_FL_OSD) { AM_OSD_Device_t *dev = (AM_OSD_Device_t*)surf->drv_data; if(!dev->drv->set_palette) { AM_DEBUG(1, "do not support set_palette"); return AM_OSD_ERR_NOT_SUPPORTED; } ret = dev->drv->set_palette(dev, pal, start, count); } } return ret; }
static AM_ErrorCode_t dvb_set_para (AM_FEND_Device_t *dev, const struct dvb_frontend_parameters *para) { int fd = (int)dev->drv_data; if(ioctl(fd, FE_SET_FRONTEND, para)==-1) { AM_DEBUG(1, "ioctl FE_SET_FRONTEND failed, error:%s", strerror(errno)); return AM_FAILURE; } return AM_SUCCESS; }
/**\brief 根据设备号取得设备结构并检查设备是否已经打开*/ static AM_INLINE AM_ErrorCode_t fend_get_openned_dev(int dev_no, AM_FEND_Device_t **dev) { AM_TRY(fend_get_dev(dev_no, dev)); if(!(*dev)->openned) { AM_DEBUG(1, "frontend device %d has not been openned", dev_no); return AM_FEND_ERR_INVALID_DEV_NO; } return AM_SUCCESS; }
/**\brief 根据设备号取得设备结构并检查设备是否已经打开*/ static AM_INLINE AM_ErrorCode_t vout_get_openned_dev(int dev_no, AM_VOUT_Device_t **dev) { AM_TRY(vout_get_dev(dev_no, dev)); if(!(*dev)->openned) { AM_DEBUG(1, "vout device %d has not been openned", dev_no); return AM_VOUT_ERR_INVALID_DEV_NO; } return AM_SUCCESS; }
AM_ErrorCode_t aml_deactive (AM_SMC_Device_t *dev) { int fd = (int)dev->drv_data; if(ioctl(fd, AMSMC_IOC_DEACTIVE, 0)) { AM_DEBUG(1, "deactive card failed \"%s\"", strerror(errno)); return AM_SMC_ERR_IO; } return AM_SUCCESS; }
/**\brief 将字符串值转化为IPV6地址 * \param[in] value 字符串值 * \param[out] addr 输出IPV6地址的指针 * \return * - AM_SUCCESS 成功 * - 其他值 错误代码(见am_cfg.h) */ AM_ErrorCode_t AM_CFG_Value2IPV6(const char *value, struct in6_addr *addr) { assert(value && addr); if(inet_pton(AF_INET6, value, addr)<=0) { AM_DEBUG(1, "key is not an IPV6 address"); return AM_CFG_ERR_BAD_FOTMAT; } return AM_SUCCESS; }
/**\brief 根据设备号取得设备结构并检查设备是否已经打开*/ static AM_INLINE AM_ErrorCode_t dmx_get_openned_dev(int dev_no, AM_DMX_Device_t **dev) { AM_TRY(dmx_get_dev(dev_no, dev)); if((*dev)->open_count <= 0) { AM_DEBUG(1, "demux device %d has not been openned", dev_no); return AM_DMX_ERR_INVALID_DEV_NO; } return AM_SUCCESS; }
static AM_ErrorCode_t dvb_get_status (AM_FEND_Device_t *dev, fe_status_t *status) { int fd = (int)dev->drv_data; if(ioctl(fd, FE_READ_STATUS, status)==-1) { AM_DEBUG(1, "ioctl FE_READ_STATUS failed, error:%s", strerror(errno)); return AM_FAILURE; } return AM_SUCCESS; }
/**\brief 根据ID取得对应filter结构,并检查设备是否在使用*/ static AM_INLINE AM_ErrorCode_t dmx_get_used_filter(AM_DMX_Device_t *dev, int filter_id, AM_DMX_Filter_t **pf) { AM_DMX_Filter_t *filter; if((filter_id<0) || (filter_id>=DMX_FILTER_COUNT)) { AM_DEBUG(1, "invalid filter id, must in %d~%d", 0, DMX_FILTER_COUNT-1); return AM_DMX_ERR_INVALID_ID; } filter = &dev->filters[filter_id]; if(!filter->used) { AM_DEBUG(1, "filter %d has not been allocated", filter_id); return AM_DMX_ERR_NOT_ALLOCATED; } *pf = filter; return AM_SUCCESS; }
AM_ErrorCode_t aml_set_param (AM_SMC_Device_t *dev, const AM_SMC_Param_t *para) { int fd = (int)dev->drv_data; if(ioctl(fd, AMSMC_IOC_SET_PARAM, para)) { AM_DEBUG(1, "set card params failed \"%s\"", strerror(errno)); return AM_SMC_ERR_IO; } return AM_SUCCESS; }