void connection::handle_read_message_id(const boost::system::error_code& e, std::size_t bytes_transferred) { if (!e) { a::const_buffer b = a::buffer(buffer_); const message_id *id = a::buffer_cast<const message_id*>(b); cmd_ack(*id); } else { printf("handle_read_message_id error %s\n", e.message().c_str()); } }
void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf) { static bool poweron_pressed = false; unsigned int cmd = buf[1]; /* We expect at least three bytes in the buffer, one for the * lingo, one for the command, and one for the first button * state bits. */ CHECKLEN(3); /* Lingo 0x02 must have been negotiated */ if (!DEVICE_LINGO_SUPPORTED(0x02)) { cmd_ack(cmd, IAP_ACK_BAD_PARAM); return; } switch (cmd) { /* ContextButtonStatus (0x00) * * Transmit button events from the device to the iPod * * Packet format (offset in buf[]: Description) * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 * 0x01: Command, always 0x00 * 0x02: Button states 0:7 * 0x03: Button states 8:15 (optional) * 0x04: Button states 16:23 (optional) * 0x05: Button states 24:31 (optional) * * Returns: (none) */ case 0x00: { iap_remotebtn = BUTTON_NONE; iap_timeoutbtn = 0; if(buf[2] != 0) { if(buf[2] & 1) REMOTE_BUTTON(BUTTON_RC_PLAY); if(buf[2] & 2) REMOTE_BUTTON(BUTTON_RC_VOL_UP); if(buf[2] & 4) REMOTE_BUTTON(BUTTON_RC_VOL_DOWN); if(buf[2] & 8) REMOTE_BUTTON(BUTTON_RC_RIGHT); if(buf[2] & 16) REMOTE_BUTTON(BUTTON_RC_LEFT); } else if(len >= 4 && buf[3] != 0) { if(buf[3] & 1) /* play */ { if (audio_status() != AUDIO_STATUS_PLAY) REMOTE_BUTTON(BUTTON_RC_PLAY); } if(buf[3] & 2) /* pause */ { if (audio_status() == AUDIO_STATUS_PLAY) REMOTE_BUTTON(BUTTON_RC_PLAY); } if(buf[3] & 128) /* Shuffle */ { if (!iap_btnshuffle) { iap_shuffle_state(!global_settings.playlist_shuffle); iap_btnshuffle = true; } } } else if(len >= 5 && buf[4] != 0) { if(buf[4] & 1) /* repeat */ { if (!iap_btnrepeat) { iap_repeat_next(); iap_btnrepeat = true; } } if (buf[4] & 2) /* power on */ { poweron_pressed = true; } /* Power off * Not quite sure how to react to this, but stopping playback * is a good start. */ if (buf[4] & 0x04) { if (audio_status() == AUDIO_STATUS_PLAY) REMOTE_BUTTON(BUTTON_RC_PLAY); } if(buf[4] & 16) /* ffwd */ REMOTE_BUTTON(BUTTON_RC_RIGHT); if(buf[4] & 32) /* frwd */ REMOTE_BUTTON(BUTTON_RC_LEFT); } /* power on released */ if (poweron_pressed && len >= 5 && !(buf[4] & 2)) { poweron_pressed = false; #ifdef HAVE_LINE_REC /* Belkin TuneTalk microphone sends power-on press+release * events once authentication sequence is finished, * GetDevCaps command is ignored by the device when it is * sent before power-on release event is received. * XXX: It is unknown if other microphone devices are * sending the power-on events. */ if (DEVICE_LINGO_SUPPORTED(0x01)) { /* GetDevCaps */ IAP_TX_INIT(0x01, 0x07); iap_send_tx(); } #endif } break; } /* ACK (0x01) * * Sent from the iPod to the device */ /* ImageButtonStatus (0x02) * * Transmit image button events from the device to the iPod * * Packet format (offset in buf[]: Description) * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 * 0x01: Command, always 0x02 * 0x02: Button states 0:7 * 0x03: Button states 8:15 (optional) * 0x04: Button states 16:23 (optional) * 0x05: Button states 24:31 (optional) * * This command requires authentication * * Returns on success: * IAP_ACK_OK * * Returns on failure: * IAP_ACK_* */ case 0x02: { if (!DEVICE_AUTHENTICATED) { cmd_ack(cmd, IAP_ACK_NO_AUTHEN); break; } cmd_ack(cmd, IAP_ACK_CMD_FAILED); break; } /* VideoButtonStatus (0x03) * * Transmit video button events from the device to the iPod * * Packet format (offset in buf[]: Description) * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 * 0x01: Command, always 0x03 * 0x02: Button states 0:7 * 0x03: Button states 8:15 (optional) * 0x04: Button states 16:23 (optional) * 0x05: Button states 24:31 (optional) * * This command requires authentication * * Returns on success: * IAP_ACK_OK * * Returns on failure: * IAP_ACK_* */ case 0x03: { if (!DEVICE_AUTHENTICATED) { cmd_ack(cmd, IAP_ACK_NO_AUTHEN); break; } cmd_ack(cmd, IAP_ACK_CMD_FAILED); break; } /* AudioButtonStatus (0x04) * * Transmit audio button events from the device to the iPod * * Packet format (offset in buf[]: Description) * 0x00: Lingo ID: Simple Remote Lingo, always 0x02 * 0x01: Command, always 0x04 * 0x02: Button states 0:7 * 0x03: Button states 8:15 (optional) * 0x04: Button states 16:23 (optional) * 0x05: Button states 24:31 (optional) * * This command requires authentication * * Returns on success: * IAP_ACK_OK * * Returns on failure: * IAP_ACK_* */ case 0x04: { unsigned char repeatbuf[6]; if (!DEVICE_AUTHENTICATED) { cmd_ack(cmd, IAP_ACK_NO_AUTHEN); break; } /* This is basically the same command as ContextButtonStatus (0x00), * with the difference that it requires authentication and that * it returns an ACK packet to the device. * So just route it through the handler again, with 0x00 as the * command */ memcpy(repeatbuf, buf, 6); repeatbuf[1] = 0x00; iap_handlepkt_mode2((len<6)?len:6, repeatbuf); cmd_ok(cmd); break; } /* The default response is IAP_ACK_BAD_PARAM */ default: { #ifdef LOGF_ENABLE logf("iap: Unsupported Mode02 Command"); #else cmd_ack(cmd, IAP_ACK_BAD_PARAM); #endif break; } } }
// process command from host void PS2keyboard::process_command() { unsigned char command = 0, b = 0; while (keyboard -> read(&command)); Serial.print("Received keyboard host command 0x"); Serial.println(command, HEX); switch (command) { case 0xED: // set/reset LEDs cmd_ack(); keyboard -> read(&b); set_led_scrolllock(bitRead(b, 0) == 1); set_led_numlock(bitRead(b, 1) == 1); set_led_capslock(bitRead(b, 2) == 1); break; case 0xEE: // echo while (keyboard -> write(0xEE) != 0); last_sent_byte = 0xEE; break; case 0xF0: // set scan code set cmd_ack(); keyboard -> read(&b); if (b == 0) { while (keyboard -> write(scancode_set)); } else { set_scancode_set(b); } break; case 0xF2: // read ID cmd_ack(); break; case 0xF3: // set typematic rate/delay unsigned char td, tr_a, tr_b; cmd_ack(); keyboard -> read(&b); td = b >> 5; tr_a = (b & 0x00011000) >> 3; tr_b = (b & 0x00000111); if (td == 3) set_typematic_delay(1000); else if (td == 2) set_typematic_delay(750); else if (td == 1) set_typematic_delay(500); else set_typematic_delay(250); set_typematic_delay((pow(2, tr_a) * (8 + tr_b)) / 240); break; case 0xF4: // enable cmd_ack(); enabled = true; buf_length = 0; break; case 0xF5: // disable and set defaults (not full BAT) cmd_ack(); set_defaults(); enabled = false; break; case 0xF6: // set defaults and reset w/full test cmd_ack(); run_bat(); break; case 0xF7: // SC MODE 3 ONLY: set all keys type typematic cmd_ack(); break; case 0xF8: // SC MODE 3 ONLY: set all keys type make/break cmd_ack(); break; case 0xF9: // SC MODE 3 ONLY: set all keys type make cmd_ack(); break; case 0xFA: // SC MODE 3 ONLY: set all keys type make/break/typematic cmd_ack(); break; case 0xFB: // SC MODE 3 ONLY: set key type typematic cmd_ack(); break; case 0xFC: // SC MODE 3 ONLY: set key type make/break cmd_ack(); break; case 0xFD: // SC MODE 3 ONLY: set key type make cmd_ack(); break; case 0xFE: // resend while (keyboard -> write(last_sent_byte) != 0); break; case 0xFF: // reset w/full test cmd_ack(); run_bat(); break; default: // unknown, hmm //cmd_ack(); cmd_resend(); } }