This post implementation the Linux host of SiLab 's C8051 firmwar example code : USBHIDtoUART, to complementary my previous post, the same stuff on Windows.
The code be :
#include <linux/limits.h> //#include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <stdint.h> #include <limits.h> #include <linux/types.h> #include <linux/input.h> #include <linux/hidraw.h> #include <pthread.h> #include <sys/select.h> #include <byteswap.h> #include <signal.h> #define DEVICE_VENDOR_ID (0x10C4) #define DEVICE_PRODUCT_ID (0x8468) #define DEVICE_VERSION_NUMER (0x0000) #define HID_BUFFER_SIZE (64) #define OUT_DATA_SIZE (60 + 1) int g_is_leave_thread = 0; int is_this_device(char *p_device_name, uint16_t vendor_id, uint16_t product_id) { int i; int res; int haw_hid_file_desc; struct hidraw_devinfo info; char buf[HID_BUFFER_SIZE]; haw_hid_file_desc = open(p_device_name, O_RDWR|O_NONBLOCK); if(-1 == haw_hid_file_desc) { printf("open %s error:: %s \r\n", p_device_name, strerror(errno)); return 0; }/*if */ memset(&info, 0x0, sizeof(info)); memset(buf, 0x0, sizeof(buf)); /* Get Raw Info */ res = ioctl(haw_hid_file_desc, HIDIOCGRAWINFO, &info); if (res < 0) { perror("HIDIOCGRAWINFO"); return 0; } else { printf("Raw Info:\n"); /*bustype number defined in linux/input.h*/ printf("\tbustype: 0x%02x\n", info.bustype); printf("\tvendor id : 0x%04hx\r\n", info.vendor); printf("\tproduct id : 0x%04hx\r\n", info.product); }/*if */ if( BUS_USB != info.bustype || vendor_id != (uint16_t)info.vendor || product_id != (uint16_t)info.product ) { printf("ERROR : device %s is not march \r\n", p_device_name); printf("target vendor_id = 0x%04x, product_id = 0x%04x\r\n", (uint16_t)vendor_id, (uint16_t)product_id); close(haw_hid_file_desc); haw_hid_file_desc = -1; return 0; }/*if */ /* Get Raw Name */ res = ioctl(haw_hid_file_desc, HIDIOCGRAWNAME(256), buf); if (res < 0) perror("HIDIOCGRAWNAME"); else printf("Raw Name: %s\n", buf); /* Get Physical Location */ res = ioctl(haw_hid_file_desc, HIDIOCGRAWPHYS(256), buf); if (res < 0) perror("HIDIOCGRAWPHYS"); else printf("Raw HID Phyical Location: %s\n", buf); int desc_size; res = ioctl(haw_hid_file_desc, HIDIOCGRDESCSIZE, &desc_size); if (res < 0) perror("HIDIOCGRDESCSIZE"); else printf("Report Descriptor Size: %d\n", desc_size); /* Get Report Descriptor */ struct hidraw_report_descriptor rpt_desc; rpt_desc.size = desc_size; res = ioctl(haw_hid_file_desc, HIDIOCGRDESC, &rpt_desc); if (res < 0) { perror("HIDIOCGRDESC"); } else { printf("Report Descriptor:\n"); for (i = 0; i < rpt_desc.size; i++) printf("0x%02x ", (uint8_t)rpt_desc.value[i]); puts("\n"); } /*dummy in C8051 USBHIDtoUART firmwire functions: Get_Report/Set_Report F3xx_USB0_InterruptServiceRoutine.c */ /* Set_Report for HIDIOCSFEATURE*/ /* Set_Report for HIDIOCGFEATURE*/ close(haw_hid_file_desc); haw_hid_file_desc = -1; return 1; }/*is_this_device*/ void *read_customed_hid_routine(void *args) { char *p_device_name; int raw_hid_file_desc; p_device_name = (char*)args; if(NULL == p_device_name) pthread_exit((void *)-1); raw_hid_file_desc = open(p_device_name, O_RDONLY); if(-1 == raw_hid_file_desc) pthread_exit((void *)-2); while(1) { fd_set set; struct timeval timeout_value; ssize_t read_size; char buffer[HID_BUFFER_SIZE]; int ret; int i; if(0 != g_is_leave_thread) break; memset(&buffer[0], 0, sizeof(buffer)); FD_ZERO(&set); FD_SET(raw_hid_file_desc, &set); timeout_value.tv_usec = 0; timeout_value.tv_sec = 2; ret = select(raw_hid_file_desc + 1, &set, NULL, NULL, &timeout_value); if(-1 == ret) { printf("open select error:: %s \r\n", strerror(errno)); continue; } else if(0 == ret) { //printf("timeout\r\n"); continue; }/*if */ read_size = read(raw_hid_file_desc, &buffer[0], sizeof(buffer) ); #define IN_DATA_SIZE (60 + 1) #define IN_DATA (0x01) if( IN_DATA_SIZE != read_size) continue; if(IN_DATA != buffer[0]) continue; for(i = 0; i < buffer[1]; i++){ printf("%c", buffer[2 + i]); }/*for i*/ }/*while*/ close(raw_hid_file_desc); pthread_exit((void *)0); }/*read_customed_hid_routine*/ void *write_customed_hid_routine(void *args) { char *p_device_name; int raw_hid_file_desc; char str_for_sending[HID_BUFFER_SIZE]; p_device_name = (char*)args; if(NULL == p_device_name) pthread_exit((void *)-1); raw_hid_file_desc = open(p_device_name, O_WRONLY); if(-1 == raw_hid_file_desc) pthread_exit((void *)-2); snprintf(&str_for_sending[0], HID_BUFFER_SIZE, "I want to eat cat meat\r\n"); while(1) { ssize_t written_size; char buffer[HID_BUFFER_SIZE]; if(0 != g_is_leave_thread) break; #define OUT_DATA_SIZE (60 + 1) #define OUT_DATA (0x02) buffer[0] = OUT_DATA; buffer[1] = strlen(&str_for_sending[0]); memcpy(&buffer[2], &str_for_sending[0], strlen(&str_for_sending[0])); written_size = write(raw_hid_file_desc, &buffer[0], OUT_DATA_SIZE); usleep(2*1000*1000); }/*while*/ close(raw_hid_file_desc); pthread_exit((void *)0); }/*write_customed_hid_routine*/ void interrupt_handler(int sig) { g_is_leave_thread = 1; }/*interrupt_handler*/ int main(int argc, char *argv[]) { int k; int haw_hid_file_desc; char device_name[PATH_MAX]; unsigned int baudrate; pthread_t read_customed_hid_thread, write_customed_hid_thread; int thread_ret; signal(SIGINT, interrupt_handler); baudrate = UINT_MAX; snprintf(&device_name[0], PATH_MAX, "/dev/hidraw0"); k = 0; while(k < argc) { if(0 == strncmp(argv[k], "-d", strlen("-d"))) { if(k + 1 < argc) { snprintf(&device_name[0], PATH_MAX, "%s", argv[k + 1]); } else { printf("ERROR : -d should be followed by" " raw hid device (/dev/hidrawXX)\r\n"); return 1; }/*if */ }/*if*/ if(0 == strncmp(argv[k], "-baudrate", strlen("-baudrate"))) { if(k + 1 < argc) { char *p_end; baudrate = strtol(argv[k + 1], &p_end, 10); } else { printf("ERROR : -baudrate should be followed by " "baudrate value\r\n"); return 1; }/*if */ }/*if*/ k++; }/*while*/ printf("raw hid device : %s\r\n", &device_name[0]); if(UINT_MAX != baudrate) printf("baud rate will be set as %u\r\n", baudrate); if(0 == is_this_device(&device_name[0], DEVICE_VENDOR_ID, DEVICE_PRODUCT_ID)) { return 1; } if(UINT_MAX != baudrate) { int haw_hid_file_desc; uint8_t buffer[HID_BUFFER_SIZE]; haw_hid_file_desc = open(&device_name[0], O_WRONLY); if(-1 == haw_hid_file_desc) return -1; #define OUT_CONTROL (0xFD) buffer[0] = OUT_CONTROL; baudrate = bswap_32(baudrate); memcpy(&buffer[1], &baudrate, sizeof(unsigned int)); if(OUT_DATA_SIZE != write(haw_hid_file_desc, &buffer[0], OUT_DATA_SIZE)) { printf("write error:: %s \r\n", strerror(errno)); }/*if */ close(haw_hid_file_desc); haw_hid_file_desc = -1; }/*UINT_MAX != baudrate*/ g_is_leave_thread = 0; pthread_create(&read_customed_hid_thread, NULL, read_customed_hid_routine, (void*)&device_name[0]); pthread_create(&write_customed_hid_thread, NULL, write_customed_hid_routine, (void*)&device_name[0]); pthread_join(write_customed_hid_thread, (void**)&thread_ret); pthread_join(read_customed_hid_thread, (void**)&thread_ret); return 0; }/*main*/
The correspondent Makefile be :
all: gcc main.c -lpthread -o c8051hid_to_uart_example_host clean: rm -rf c8051hid_to_uart_example_host
The argument are:
-baudrate baudrate_value : as the same, to setting the baudrate.
-d device_location : to specify which device would be operated. by default, the customed hid device would be /dev/hidrawX (X is a number, for example, /dev/hidraw0)
Result of running this binary is ommited, for it is pretty the same as Windows version.
沒有留言:
張貼留言