/* * Send a packet of bytes to the device
*/ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsignedchar* data)
{ /* Copy data to buffer */ int n = LO(cmd); int c; int empty; int head, tail;
/* * Update head and tail of xmit buffer
*/
scoped_guard(spinlock_irqsave, &iforce->xmit_lock) {
head = iforce->xmit.head;
tail = iforce->xmit.tail;
if (CIRC_SPACE(head, tail, XMIT_SIZE) < n + 2) {
dev_warn(&iforce->dev->dev, "not enough space in xmit buffer to send new packet\n"); return -1;
}
empty = head == tail;
XMIT_INC(iforce->xmit.head, n + 2);
/* * Store packet in xmit buffer
*/
iforce->xmit.buf[head] = HI(cmd);
XMIT_INC(head, 1);
iforce->xmit.buf[head] = LO(cmd);
XMIT_INC(head, 1);
c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE); if (n < c)
c = n;
memcpy(&iforce->xmit.buf[head], data, c); if (n != c)
memcpy(&iforce->xmit.buf[0], data + c, n - c);
XMIT_INC(head, n);
}
/* * If necessary, start the transmission
*/ if (empty)
iforce->xport_ops->xmit(iforce);
return 0;
}
EXPORT_SYMBOL(iforce_send_packet);
/* Start or stop an effect */ int iforce_control_playback(struct iforce* iforce, u16 id, unsignedint value)
{ unsignedchar data[3];
/* Mark an effect that was being updated as ready. That means it can be updated
* again */ staticint mark_core_as_ready(struct iforce *iforce, unsignedshort addr)
{ int i;
if (!iforce->dev->ff) return 0;
for (i = 0; i < iforce->dev->ff->max_effects; ++i) { if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
(iforce->core_effects[i].mod1_chunk.start == addr ||
iforce->core_effects[i].mod2_chunk.start == addr)) {
clear_bit(FF_CORE_UPDATE, iforce->core_effects[i].flags); return 0;
}
}
dev_warn(&iforce->dev->dev, "unused effect %04x updated !!!\n", addr); return -1;
}
void iforce_process_packet(struct iforce *iforce,
u8 packet_id, u8 *data, size_t len)
{ struct input_dev *dev = iforce->dev; int i, j;
switch (packet_id) {
case 0x01: /* joystick position data */
input_report_abs(dev, ABS_X,
(__s16) get_unaligned_le16(data));
input_report_abs(dev, ABS_Y,
(__s16) get_unaligned_le16(data + 2));
input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
if (len >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
iforce_report_hats_buttons(iforce, data);
input_sync(dev); break;
case 0x03: /* wheel position data */
input_report_abs(dev, ABS_WHEEL,
(__s16) get_unaligned_le16(data));
input_report_abs(dev, ABS_GAS, 255 - data[2]);
input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
iforce_report_hats_buttons(iforce, data);
input_sync(dev); break;
case 0x02: /* status report */
input_report_key(dev, BTN_DEAD, data[0] & 0x02);
input_sync(dev);
/* Check if an effect was just started or stopped */
i = data[1] & 0x7f; if (data[1] & 0x80) { if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { /* Report play event */
input_report_ff_status(dev, i, FF_STATUS_PLAYING);
}
} elseif (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { /* Report stop event */
input_report_ff_status(dev, i, FF_STATUS_STOPPED);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.