#include "app_config.h" #include "typedef.h" #include "usb_stack.h" #include "device/hid.h" #include "system/includes.h" //#include "generic/jiffies.h" #if USB_HID_POS_ENABLE #define HID_POS_STA_BM_NORMAL 0x00 #define HID_POS_STA_BM_POWER_ON_RESET_SCANNER 0x01 #define HID_POS_STA_BM_PREVENT_READ_OF_BARCODES 0x02 #define HID_POS_STA_BM_INITIATE_BARCODE_READ 0x04 enum { HID_POS_MSG_BEEP_GOOD = 0x10, HID_POS_MSG_BEEP_ERROR, HID_POS_MSG_TRIG_START, HID_POS_MSG_TRIG_STOP, HID_POS_MSG_RECV_AT_CMD, }; struct hid_pos_msg { u8 *buf; u32 len; u32 in_pos; u32 out_pos; spinlock_t spinlock; }; struct hid_pos_handle { /* void *usb_slave; */ usb_dev usb_id; int state; struct hid_pos_msg msg; u8 at_cmd[62]; int timer; spinlock_t spinlock; u8 trigger_sta; u8 trigger_last_sta; u8 trigger_on_filter; u8 trigger_off_filter; u8 send_trig; }; static struct hid_pos_handle *__this; int hid_pos_send_report(usb_dev usb_id, u32 symbology, u32 vendor_code, const u8 *buf, u32 len, u8 force); static const char Hidpos_report_descr[] = { 0x05, 0x8c, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x12, 0xa1, 0x02, 0x85, 0x02, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x05, 0x01, 0x09, 0x3b, 0x81, 0x02, 0x95, 0x03, 0x05, 0x8c, 0x09, 0xfb, 0x09, 0xfc, 0x09, 0xfd, 0x81, 0x02, 0x95, 0x38, 0x09, 0xfe, 0x82, 0x02, 0x01, 0x06, 0x66, 0xff, 0x95, 0x02, 0x09, 0x04, 0x09, 0x00, 0x81, 0x02, 0x05, 0x8c, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x09, 0xff, 0x81, 0x02, 0xc0, 0x09, 0x14, 0xa1, 0x02, 0x85, 0x04, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x09, 0x5e, 0x09, 0x5f, 0x09, 0x60, 0x09, 0x00, 0x09, 0x00, 0x09, 0x85, 0x09, 0x86, //0x09, 0x00, 0x91, 0x86, 0xc0, #if 0 0x09, 0x16, 0xa1, 0x02, 0x85, 0x06, 0x09, 0xA9, 0xa1, 0x02, 0x75, 0x02, 0x95, 0x01, 0x15, 0x01, 0x25, 0x03, 0x19, 0xAA, 0x29, 0xAC, 0x91, 0x00, 0xc0, 0x09, 0xA9, 0xa1, 0x02, 0x75, 0x02, 0x95, 0x01, 0x15, 0x01, 0x25, 0x03, 0x19, 0xAD, 0x29, 0xAF, 0x91, 0x00, 0xc0, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 12, 0x09, 0x91, 0x09, 0x92, 0x09, 0x93, 0x09, 0x94, 0x09, 0x95, 0x09, 0x96, 0x09, 0x9b, 0x09, 0x9d, 0x09, 0xa1, 0x09, 0xa2, 0x91, 0x02, 0xc0, 0x09, 0x18, 0xa1, 0x02, 0x85, 0x07, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x09, 0xc7, 0x91, 0x02, 0x0a, 0x0a, 0x01, 0xa1, 0x02, 0x75, 0x02, 0x15, 0x01, 0x25, 0x02, 0x95, 0x01, 0x1a, 0x0b, 0x01, 0x2a, 0x0c, 0x01, 0x91, 0x00, 0xc0, 0x09, 0xf0, 0xa1, 0x02, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x19, 0xf1, 0x29, 0xf2, 0x91, 0x00, 0xc0, 0x09, 0xD6, 0xa1, 0x02, 0x15, 0x01, 0x25, 0x09, 0x75, 0x04, 0x95, 0x01, 0x19, 0xd7, 0x29, 0xdf, 0x91, 0x00, 0xc0, 0x15, 0x00, 0x25, 48, 0x75, 0x08, 0x95, 0x02, 0x0a, 0x06, 0x01, 0x0a, 0x07, 0x01, 0x91, 0x02, 0x75, 0x01, 0x95, 0x08, 0x09, 0xc9, 0x09, 0xd4, 0x91, 0x02, 0xc0, 0x09, 0x19, 0xa1, 0x02, 0x85, 0x08, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x09, 0xca, 0x91, 0x02, 0x0a, 0x0a, 0x01, 0xa1, 0x02, 0x75, 0x02, 0x15, 0x01, 0x25, 0x02, 0x95, 0x01, 0x1a, 0x0b, 0x01, 0x2a, 0x0c, 0x01, 0x91, 0x00, 0xc0, 0x09, 0xf0, 0xa1, 0x02, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x19, 0xf1, 0x29, 0xf2, 0x91, 0x00, 0xc0, 0x09, 0xD6, 0xa1, 0x02, 0x15, 0x01, 0x25, 0x03, 0x75, 0x04, 0x95, 0x01, 0x19, 0xd7, 0x29, 0xd9, 0x91, 0x00, 0xc0, 0x15, 2, 0x25, 80, 0x75, 0x08, 0x95, 0x02, 0x0a, 0x06, 0x01, 0x0a, 0x07, 0x01, 0x91, 0x02, 0xc0, #endif 0x06, 0x66, 0xff, 0x75, 0x08, 0x26, 0xff, 0x00, 0x09, 0x03, 0xa1, 0x02, 0x85, 0xfe, 0x95, 0x01, 0x09, 0x03, 0xb2, 0x82, 0x01, 0xc0, 0x09, 0x01, 0xa1, 0x02, 0x85, 0xfd, 0x95, 0x01, 0x09, 0x21, 0x91, 0x02, 0x95, 0x3e, 0x09, 0x22, 0x92, 0x82, 0x01, 0xc0, 0xc0 }; u8 *hid_pos_get_report_desc() { return (u8 *)Hidpos_report_descr; } u32 hid_pos_get_report_desc_size() { return sizeof(Hidpos_report_descr); } static int hid_pos_msg_init(struct hid_pos_msg *msg, u8 *buf, u32 len) { if (!msg || !buf || !len) { return -EINVAL; } msg->buf = buf; msg->len = len; msg->in_pos = 0; msg->out_pos = 0; spin_lock_init(&msg->spinlock); return 0; } static int hid_pos_msg_put(struct hid_pos_msg *msg, u8 value) { if (!msg) { return -EINVAL; } spin_lock(&msg->spinlock); if ((msg->in_pos + msg->len - msg->out_pos) % msg->len == msg->len - 1) { //msg full spin_unlock(&msg->spinlock); return -ENOMEM; } msg->buf[msg->in_pos] = value; msg->in_pos = (msg->in_pos + 1) % msg->len; spin_unlock(&msg->spinlock); return 0; } static int hid_pos_msg_get(struct hid_pos_msg *msg, u8 *value) { if (!msg || !value) { return -EINVAL; } spin_lock(&msg->spinlock); if ((msg->in_pos + msg->len - msg->out_pos) % msg->len == 0) { //msg empty spin_unlock(&msg->spinlock); return -ENOMEM; } *value = msg->buf[msg->out_pos]; msg->out_pos = (msg->out_pos + 1) % msg->len; spin_unlock(&msg->spinlock); return 0; } static u32 hid_pos_msg_query_size(struct hid_pos_msg *msg) { u32 len; if (!msg) { return 0; } spin_lock(&msg->spinlock); len = (msg->in_pos + msg->len - msg->out_pos) % msg->len; spin_unlock(&msg->spinlock); return len; } static int get_trigger_state() { //获取触发按键状态 #if 0 static int init = 0; if (!init) { gpio_set_pull_up(IO_PORTX_XX); init = 1; } return gpio_direction_input(IO_PORTX_XX); #else return 0; #endif } static const char *const hid_pos_at_cmd[] = { "\x16\x07\r", //BEEP "\x16M\rP_INFO.", //GET INFO "\x16M\rTERMID?.", //TERMID }; static void hid_pos_msg_handle(void *arg) { int err; struct hid_pos_handle *hdl = arg; u8 msg_val; u32 idx; const char *at_cmd_ack; if (get_trigger_state()) { hdl->trigger_on_filter++; hdl->trigger_off_filter = 0; } else { hdl->trigger_on_filter = 0; hdl->trigger_off_filter++; } if (hdl->trigger_on_filter >= 2) { hdl->trigger_sta = 1; } else if (hdl->trigger_off_filter >= 2) { hdl->trigger_sta = 0; } if (hdl->trigger_sta != hdl->trigger_last_sta) { if (!(hdl->state & HID_POS_STA_BM_INITIATE_BARCODE_READ)) { if (hdl->trigger_sta) { msg_val = HID_POS_MSG_TRIG_START; } else { msg_val = HID_POS_MSG_TRIG_STOP; } err = hid_pos_msg_put(&hdl->msg, msg_val); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } } } hdl->trigger_last_sta = hdl->trigger_sta; if (0 == hid_pos_msg_get(&hdl->msg, &msg_val)) { switch (msg_val) { case HID_POS_MSG_BEEP_GOOD: printf("beep good\n"); /* tick(2); */ break; case HID_POS_MSG_BEEP_ERROR: printf("beep error\n"); /* tick(3); */ break; case HID_POS_MSG_TRIG_START: printf("trig start\n"); //add codes of LED turning on hdl->send_trig = 1; break; case HID_POS_MSG_TRIG_STOP: printf("trig stop\n"); //add codes of LED turning off hdl->send_trig = 0; break; case HID_POS_MSG_RECV_AT_CMD: printf("recv at-cmd\n"); spin_lock(&hdl->spinlock); for (idx = 0; idx < ARRAY_SIZE(hid_pos_at_cmd); idx++) { if (memcmp(hdl->at_cmd, hid_pos_at_cmd[idx], strlen(hid_pos_at_cmd[idx])) == 0) { break; } } spin_unlock(&hdl->spinlock); printf("idx %d\n", idx); if (idx < ARRAY_SIZE(hid_pos_at_cmd)) { switch (idx) { case 0: /* tick(2); */ break; case 1: at_cmd_ack = "INFO: JL_HID_POS\r\nVERSION: 1.0.0\r\n\x06."; hid_pos_send_report(hdl->usb_id, 0x365a5d, 0x36, (const u8 *)at_cmd_ack, strlen(at_cmd_ack), 1); break; case 2: at_cmd_ack = "TERMID131\x06."; hid_pos_send_report(hdl->usb_id, 0x365a5d, 0x36, (const u8 *)at_cmd_ack, strlen(at_cmd_ack), 1); break; } } break; } } } int hid_pos_receive(u8 *buf, u32 len) { int err = 0; u8 msg_val; printf("%s() buf size %d\n", __func__, len); put_buf(buf, len); //report id switch (buf[0]) { case 4: puts("trigger report\n"); if (__this) { if (buf[1] & 0x40) { //Sound Good Read Beep msg_val = HID_POS_MSG_BEEP_GOOD; err = hid_pos_msg_put(&__this->msg, msg_val); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } } if (buf[1] & 0x20) { //Sound Error Beep msg_val = HID_POS_MSG_BEEP_ERROR; err = hid_pos_msg_put(&__this->msg, msg_val); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } } if (buf[1] & 0x02) { //Prevent Read of Barcodes __this->state |= HID_POS_STA_BM_PREVENT_READ_OF_BARCODES; } else { __this->state &= ~HID_POS_STA_BM_PREVENT_READ_OF_BARCODES; } if (buf[1] & 0x04) { //Initiate Barcode Read if (!(__this->state & HID_POS_STA_BM_INITIATE_BARCODE_READ)) { __this->state |= HID_POS_STA_BM_INITIATE_BARCODE_READ; msg_val = HID_POS_MSG_TRIG_START; err = hid_pos_msg_put(&__this->msg, msg_val); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } } } else { if ((__this->state & HID_POS_STA_BM_INITIATE_BARCODE_READ)) { __this->state &= ~HID_POS_STA_BM_INITIATE_BARCODE_READ; msg_val = HID_POS_MSG_TRIG_STOP; err = hid_pos_msg_put(&__this->msg, msg_val); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } } } } break; case 254: puts("Vendor-Defined 3\n"); break; case 253: puts("Vendor-Defined 1\n"); //receive at_cmd from pc spin_lock(&__this->spinlock); memcpy(__this->at_cmd, &buf[2], buf[1]); spin_unlock(&__this->spinlock); msg_val = HID_POS_MSG_RECV_AT_CMD; err = hid_pos_msg_put(&__this->msg, msg_val); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } break; default: printf("unsupported report id %d\n", buf[0]); } return 0; } int hid_pos_open(usb_dev usb_id) { struct hid_pos_handle *hdl; u8 *ptr = NULL; int err; hdl = (struct hid_pos_handle *)malloc(sizeof(*hdl)); if (!hdl) { return -ENOMEM; } memset(hdl, 0, sizeof(*hdl)); hdl->usb_id = usb_id; ptr = (u8 *)malloc(10); if (!ptr) { goto __err_exit; } hid_pos_msg_init(&hdl->msg, ptr, 10); spin_lock_init(&hdl->spinlock); hdl->timer = sys_timer_add(hdl, hid_pos_msg_handle, 50); hdl->state = HID_POS_STA_BM_NORMAL; __this = hdl; return 0; __err_exit: if (hdl->timer) { sys_timer_del(hdl->timer); } if (ptr) { free(ptr); } free(hdl); return -EFAULT; } void hid_pos_close(usb_dev usb_id) { struct hid_pos_handle *hdl; int err; if (__this == NULL) { return; } hdl = __this; if (hdl->timer) { sys_timer_del(hdl->timer); } free(hdl->msg.buf); free(hdl); __this = NULL; } int hid_pos_send_report(usb_dev usb_id, u32 symbology, u32 vendor_code, const u8 *buf, u32 len, u8 force) { struct hid_pos_handle *hdl; u32 offset = 0; u32 fit_len; u8 decoded_data[64] = {0}; int err = 0; if (__this == NULL) { return -EFAULT; } hdl = __this; if (((hdl->state & HID_POS_STA_BM_PREVENT_READ_OF_BARCODES) == 0) && (hdl->send_trig || force)) { decoded_data[0] = 2; //report id: 2 //decoded_data[2] = 0x5d; //Symbology Identifier1 //decoded_data[3] = 0x43; //Symbology Identifier2 //decoded_data[4] = 0x30; //Symbology Identifier3 //decoded_data[61] = 0x6a; decoded_data[2] = symbology & 0xff; decoded_data[3] = (symbology >> 8) & 0xff; decoded_data[4] = (symbology >> 16) & 0xff; decoded_data[61] = vendor_code & 0xff; decoded_data[62] = (vendor_code >> 8) & 0xff; while (offset < len) { fit_len = len - offset > 56 ? 56 : len - offset; memset(&decoded_data[5], 0, 56); memcpy(&decoded_data[5], buf + offset, fit_len); if (fit_len < 56) { decoded_data[1] = fit_len; decoded_data[63] &= ~BIT(0); } else { decoded_data[1] = 56; decoded_data[63] |= BIT(0); //Decode Data Continued } hid_send_buf_async(hdl->usb_id, decoded_data, 64); //hid_tx_data(hdl->usb_id, decode_data, 64); offset += fit_len; } if (!force) { hdl->send_trig = 0; } err = hid_pos_msg_put(&hdl->msg, HID_POS_MSG_TRIG_STOP); if (err < 0) { printf("hid pos put msg fail, %d, line %d\n", err, __LINE__); } } if (offset < len) { err = -EFAULT; } return err; } int hid_pos_send(u8 *data, u32 len, u8 force) { if (data[len - 1] == '\n') { data[len - 1] = '\r'; } return hid_pos_send_report(__this->usb_id, 0x30435d, 0x6a, data, len, force); } #endif