ckb-next  beta-v0.2.8 at branch testing
ckb-next driver for corsair devices
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
usb.h File Reference

Definitions for using USB interface. More...

#include "includes.h"
#include "keymap.h"
+ Include dependency graph for usb.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define V_CORSAIR   0x1b1c
 For the following Defines please see "Detailed Description". More...
 
#define V_CORSAIR_STR   "1b1c"
 
#define P_K65   0x1b17
 
#define P_K65_STR   "1b17"
 
#define P_K65_NRGB   0x1b07
 
#define P_K65_NRGB_STR   "1b07"
 
#define P_K65_LUX   0x1b37
 
#define P_K65_LUX_STR   "1b37"
 
#define P_K65_RFIRE   0x1b39
 
#define P_K65_RFIRE_STR   "1b39"
 
#define IS_K65(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K65 || (kb)->product == P_K65_NRGB || (kb)->product == P_K65_LUX || (kb)->product == P_K65_RFIRE))
 
#define P_K70   0x1b13
 
#define P_K70_STR   "1b13"
 
#define P_K70_NRGB   0x1b09
 
#define P_K70_NRGB_STR   "1b09"
 
#define P_K70_LUX   0x1b33
 
#define P_K70_LUX_STR   "1b33"
 
#define P_K70_LUX_NRGB   0x1b36
 
#define P_K70_LUX_NRGB_STR   "1b36"
 
#define P_K70_RFIRE   0x1b38
 
#define P_K70_RFIRE_STR   "1b38"
 
#define P_K70_RFIRE_NRGB   0x1b3a
 
#define P_K70_RFIRE_NRGB_STR   "1b3a"
 
#define IS_K70(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K70 || (kb)->product == P_K70_NRGB || (kb)->product == P_K70_RFIRE || (kb)->product == P_K70_RFIRE_NRGB || (kb)->product == P_K70_LUX || (kb)->product == P_K70_LUX_NRGB))
 
#define P_K95   0x1b11
 
#define P_K95_STR   "1b11"
 
#define P_K95_NRGB   0x1b08
 
#define P_K95_NRGB_STR   "1b08"
 
#define P_K95_PLATINUM   0x1b2d
 
#define P_K95_PLATINUM_STR   "1b2d"
 
#define IS_K95(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K95 || (kb)->product == P_K95_NRGB || (kb)->product == P_K95_PLATINUM))
 
#define P_STRAFE   0x1b20
 
#define P_STRAFE_STR   "1b20"
 
#define P_STRAFE_NRGB   0x1b15
 
#define P_STRAFE_NRGB_STR   "1b15"
 
#define IS_STRAFE(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_STRAFE || (kb)->product == P_STRAFE_NRGB))
 
#define P_M65   0x1b12
 
#define P_M65_STR   "1b12"
 
#define P_M65_PRO   0x1b2e
 
#define P_M65_PRO_STR   "1b2e"
 
#define IS_M65(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_M65 || (kb)->product == P_M65_PRO))
 
#define P_SABRE_O   0x1b14 /* optical */
 
#define P_SABRE_O_STR   "1b14"
 
#define P_SABRE_L   0x1b19 /* laser */
 
#define P_SABRE_L_STR   "1b19"
 
#define P_SABRE_N   0x1b2f /* new? */
 
#define P_SABRE_N_STR   "1b2f"
 
#define P_SABRE_O2   0x1b32 /* Observed on a CH-9000111-EU model SABRE */
 
#define P_SABRE_O2_STR   "1b32"
 
#define IS_SABRE(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_SABRE_O || (kb)->product == P_SABRE_L || (kb)->product == P_SABRE_N || (kb)->product == P_SABRE_O2))
 
#define P_SCIMITAR   0x1b1e
 
#define P_SCIMITAR_STR   "1b1e"
 
#define P_SCIMITAR_PRO   0x1b3e
 
#define P_SCIMITAR_PRO_STR   "1b3e"
 
#define IS_SCIMITAR(kb)   ((kb)->vendor == V_CORSAIR && ((kb)->product == P_SCIMITAR || (kb)->product == P_SCIMITAR_PRO))
 
#define IS_RGB(vendor, product)   ((vendor) == (V_CORSAIR) && (product) != (P_K65_NRGB) && (product) != (P_K70_NRGB) && (product) != (P_K95_NRGB))
 RGB vs non-RGB test (note: non-RGB Strafe is still considered "RGB" in that it shares the same protocol. The difference is denoted with the "monochrome" feature). More...
 
#define IS_MONOCHROME(vendor, product)   ((vendor) == (V_CORSAIR) && (product) == (P_STRAFE_NRGB))
 The difference between non RGB and monochrome is, that monochrome has lights, but just in one color. nonRGB has no lights. Change this if new monochrome devices are added. More...
 
#define IS_RGB_DEV(kb)   IS_RGB((kb)->vendor, (kb)->product)
 For calling with a usbdevice*, vendor and product are extracted and IS_RGB() is returned. More...
 
#define IS_MONOCHROME_DEV(kb)   IS_MONOCHROME((kb)->vendor, (kb)->product)
 For calling with a usbdevice*, vendor and product are extracted and IS_MONOCHROME() is returned. More...
 
#define IS_FULLRANGE(kb)   (IS_RGB((kb)->vendor, (kb)->product) && (kb)->product != P_K65 && (kb)->product != P_K70 && (kb)->product != P_K95)
 Full color range (16.8M) vs partial color range (512) More...
 
#define IS_MOUSE(vendor, product)   ((vendor) == (V_CORSAIR) && ((product) == (P_M65) || (product) == (P_M65_PRO) || (product) == (P_SABRE_O) || (product) == (P_SABRE_L) || (product) == (P_SABRE_N) || (product) == (P_SCIMITAR) || (product) == (P_SCIMITAR_PRO) || (product) == (P_SABRE_O2)))
 Mouse vs keyboard test. More...
 
#define IS_MOUSE_DEV(kb)   IS_MOUSE((kb)->vendor, (kb)->product)
 For calling with a usbdevice*, vendor and product are extracted and IS_MOUSE() is returned. More...
 
#define DELAY_SHORT(kb)   usleep((int)(kb)->usbdelay * 1000)
 USB delays for when the keyboards get picky about timing That was the original comment, but it is used anytime. The short delay is used before any send or receive. More...
 
#define DELAY_MEDIUM(kb)   usleep((int)(kb)->usbdelay * 10000)
 the medium delay is used after sending a command before waiting for the answer. More...
 
#define DELAY_LONG(kb)   usleep(100000)
 The longest delay takes place where something went wrong (eg when resetting the device) More...
 
#define USB_DELAY_DEFAULT   5
 This constant is used to initialize kb->usbdelay. It is used in many places (see macros above) but often also overwritten to the fixed value of 10. Pure Hacker code. More...
 
#define resetusb(kb)   _resetusb(kb, __FILE_NOPATH__, __LINE__)
 resetusb() is just a macro to call _resetusb() with debuggin constants (file, lineno) More...
 
#define usbsend(kb, messages, count)   _usbsend(kb, messages, count, __FILE_NOPATH__, __LINE__)
 usbsend macro is used to wrap _usbsend() with debugging information (file and lineno) More...
 
#define usbrecv(kb, out_msg, in_msg)   _usbrecv(kb, out_msg, in_msg, __FILE_NOPATH__, __LINE__)
 usbrecv macro is used to wrap _usbrecv() with debugging information (file and lineno) More...
 
#define nk95cmd(kb, command)   _nk95cmd(kb, (command) >> 16 & 0xFF, (command) & 0xFFFF, __FILE_NOPATH__, __LINE__)
 nk95cmd() macro is used to wrap _nk95cmd() with debugging information (file and lineno). the command structure is different:
Just the bits 23..16 are used as bits 7..0 for bRequest
Bits 15..0 are used as wValue More...
 
#define NK95_HWOFF   0x020030
 Hardware-specific commands for the K95 nonRGB,. More...
 
#define NK95_HWON   0x020001
 Hardware playback on. More...
 
#define NK95_M1   0x140001
 Switch to mode 1. More...
 
#define NK95_M2   0x140002
 Switch to mode 2. More...
 
#define NK95_M3   0x140003
 Switch to mode 3. More...
 

Functions

const char * vendor_str (short vendor)
 uncomment the following Define to see USB packets sent to the device More...
 
const char * product_str (short product)
 product_str returns a condensed view on what type of device we have. More...
 
int usbmain ()
 Start the USB main loop. Returns program exit code when finished. More...
 
void usbkill ()
 Stop the USB system. More...
 
void setupusb (usbdevice *kb)
 setupusb starts a thread with kb as parameter and _setupusb() as entrypoint. More...
 
int os_setupusb (usbdevice *kb)
 os_setupusb OS-specific setup for a specific usb device. More...
 
void * os_inputmain (void *context)
 os_inputmain is run in a separate thread and will be detached from the main thread, so it needs to clean up its own resources. More...
 
int revertusb (usbdevice *kb)
 revertusb sets a given device to inactive (hardware controlled) mode if not a fw-ugrade is indicated More...
 
int closeusb (usbdevice *kb)
 closeusb Close a USB device and remove device entry. More...
 
void os_closeusb (usbdevice *kb)
 os_closeusb unclaim it, destroy the udev device and clear data structures at kb More...
 
int _resetusb (usbdevice *kb, const char *file, int line)
 _resetusb Reset a USB device. More...
 
int os_resetusb (usbdevice *kb, const char *file, int line)
 os_resetusb is the os specific implementation for resetting usb More...
 
int _usbsend (usbdevice *kb, const uchar *messages, int count, const char *file, int line)
 _usbsend send a logical message completely to the given device More...
 
int _usbrecv (usbdevice *kb, const uchar *out_msg, uchar *in_msg, const char *file, int line)
 _usbrecv Request data from a USB device by first sending an output packet and then reading the response. More...
 
int os_usbsend (usbdevice *kb, const uchar *out_msg, int is_recv, const char *file, int line)
 os_usbsend sends a data packet (MSG_SIZE = 64) Bytes long More...
 
int os_usbrecv (usbdevice *kb, uchar *in_msg, const char *file, int line)
 os_usbrecv receives a max MSGSIZE long buffer from usb device More...
 
void os_sendindicators (usbdevice *kb)
 os_sendindicators update the indicators for the special keys (Numlock, Capslock and what else?) More...
 
int _nk95cmd (usbdevice *kb, uchar bRequest, ushort wValue, const char *file, int line)
 _nk95cmd If we control a non RGB keyboard, set the keyboard via ioctl with usbdevfs_ctrltransfer More...
 
int usb_tryreset (usbdevice *kb)
 usb_tryreset does what the name means: Try to reset the usb via resetusb() More...
 

Detailed Description

Vendor/product codes

The list of defines in the first part of the file describes the various types of equipment from Corsair and summarizes them according to specific characteristics.
Each device type is described with two defines:

  • On the one hand the device ID with which the device can be recognized on the USB as a short
  • and on the other hand the same representation as a string, but without leading "0x".

First entry-pair is the Provider ID (vendorID) from Corsair.

Block No. contains Devices are bundled via
1 The first block contains the K65-like keyboards, regardless of their properties (RGB, ...). In summary, they can be queried using the macro IS_K65().
2 the K70-like Keyboards with all their configuration types summarized by IS_K70().
3 the K95 series keyboards collected with the macro IS_K95().
4 strafe keyboards IS_STRAFE()
5 M65 mice with and without RGB IS_M65()
6 The SABRE and HARPOON mice.
Maybe this will be divided int two different blocks later because of different nummber of special keys
IS_SABRE()
7 The Scimitar mouse devices IS_SCIMITAR()

Definition in file usb.h.

Macro Definition Documentation

#define DELAY_LONG (   kb)    usleep(100000)
#define DELAY_MEDIUM (   kb)    usleep((int)(kb)->usbdelay * 10000)

Definition at line 152 of file usb.h.

Referenced by _usbrecv(), and setactive_kb().

#define DELAY_SHORT (   kb)    usleep((int)(kb)->usbdelay * 1000)

Definition at line 149 of file usb.h.

Referenced by _usbrecv(), _usbsend(), and updateindicators_kb().

#define IS_FULLRANGE (   kb)    (IS_RGB((kb)->vendor, (kb)->product) && (kb)->product != P_K65 && (kb)->product != P_K70 && (kb)->product != P_K95)

Definition at line 138 of file usb.h.

Referenced by readcmd(), and updatergb_kb().

#define IS_K65 (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K65 || (kb)->product == P_K65_NRGB || (kb)->product == P_K65_LUX || (kb)->product == P_K65_RFIRE))

Definition at line 49 of file usb.h.

Referenced by has_key().

#define IS_K70 (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K70 || (kb)->product == P_K70_NRGB || (kb)->product == P_K70_RFIRE || (kb)->product == P_K70_RFIRE_NRGB || (kb)->product == P_K70_LUX || (kb)->product == P_K70_LUX_NRGB))

Definition at line 63 of file usb.h.

#define IS_K95 (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K95 || (kb)->product == P_K95_NRGB || (kb)->product == P_K95_PLATINUM))

Definition at line 71 of file usb.h.

Referenced by cmd_hwload_kb(), cmd_hwsave_kb(), and has_key().

#define IS_M65 (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_M65 || (kb)->product == P_M65_PRO))

Definition at line 83 of file usb.h.

Referenced by isblack().

#define IS_MONOCHROME (   vendor,
  product 
)    ((vendor) == (V_CORSAIR) && (product) == (P_STRAFE_NRGB))

Definition at line 129 of file usb.h.

Referenced by _setupusb().

#define IS_MONOCHROME_DEV (   kb)    IS_MONOCHROME((kb)->vendor, (kb)->product)

Definition at line 135 of file usb.h.

#define IS_MOUSE (   vendor,
  product 
)    ((vendor) == (V_CORSAIR) && ((product) == (P_M65) || (product) == (P_M65_PRO) || (product) == (P_SABRE_O) || (product) == (P_SABRE_L) || (product) == (P_SABRE_N) || (product) == (P_SCIMITAR) || (product) == (P_SCIMITAR_PRO) || (product) == (P_SABRE_O2)))

Definition at line 141 of file usb.h.

Referenced by _setupusb(), get_vtable(), has_key(), and os_inputmain().

#define IS_MOUSE_DEV (   kb)    IS_MOUSE((kb)->vendor, (kb)->product)

Definition at line 144 of file usb.h.

Referenced by readcmd().

#define IS_RGB (   vendor,
  product 
)    ((vendor) == (V_CORSAIR) && (product) != (P_K65_NRGB) && (product) != (P_K70_NRGB) && (product) != (P_K95_NRGB))

Definition at line 124 of file usb.h.

Referenced by _setupusb(), get_vtable(), and os_inputmain().

#define IS_RGB_DEV (   kb)    IS_RGB((kb)->vendor, (kb)->product)

Definition at line 132 of file usb.h.

#define IS_SABRE (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_SABRE_O || (kb)->product == P_SABRE_L || (kb)->product == P_SABRE_N || (kb)->product == P_SABRE_O2))

Definition at line 93 of file usb.h.

Referenced by has_key(), loadrgb_mouse(), and savergb_mouse().

#define IS_SCIMITAR (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_SCIMITAR || (kb)->product == P_SCIMITAR_PRO))

Definition at line 99 of file usb.h.

Referenced by has_key(), loadrgb_mouse(), and savergb_mouse().

#define IS_STRAFE (   kb)    ((kb)->vendor == V_CORSAIR && ((kb)->product == P_STRAFE || (kb)->product == P_STRAFE_NRGB))

Definition at line 77 of file usb.h.

Referenced by savergb_kb().

#define NK95_HWOFF   0x020030
See Also
usb2.0 documentation for details. Set Hardware playback off

Definition at line 301 of file usb.h.

Referenced by start_kb_nrgb().

#define NK95_HWON   0x020001

Definition at line 304 of file usb.h.

Referenced by revertusb().

#define NK95_M1   0x140001

Definition at line 307 of file usb.h.

Referenced by setmodeindex_nrgb().

#define NK95_M2   0x140002

Definition at line 310 of file usb.h.

Referenced by setmodeindex_nrgb().

#define NK95_M3   0x140003

Definition at line 313 of file usb.h.

Referenced by setmodeindex_nrgb().

#define nk95cmd (   kb,
  command 
)    _nk95cmd(kb, (command) >> 16 & 0xFF, (command) & 0xFFFF, __FILE_NOPATH__, __LINE__)

Definition at line 296 of file usb.h.

Referenced by revertusb(), setmodeindex_nrgb(), and start_kb_nrgb().

#define P_K65   0x1b17

Definition at line 41 of file usb.h.

Referenced by product_str().

#define P_K65_LUX   0x1b37

Definition at line 45 of file usb.h.

Referenced by product_str().

#define P_K65_LUX_STR   "1b37"

Definition at line 46 of file usb.h.

#define P_K65_NRGB   0x1b07

Definition at line 43 of file usb.h.

Referenced by product_str().

#define P_K65_NRGB_STR   "1b07"

Definition at line 44 of file usb.h.

#define P_K65_RFIRE   0x1b39

Definition at line 47 of file usb.h.

Referenced by product_str().

#define P_K65_RFIRE_STR   "1b39"

Definition at line 48 of file usb.h.

#define P_K65_STR   "1b17"

Definition at line 42 of file usb.h.

#define P_K70   0x1b13

Definition at line 51 of file usb.h.

Referenced by product_str().

#define P_K70_LUX   0x1b33

Definition at line 55 of file usb.h.

Referenced by loadrgb_kb(), and product_str().

#define P_K70_LUX_NRGB   0x1b36

Definition at line 57 of file usb.h.

Referenced by loadrgb_kb(), and product_str().

#define P_K70_LUX_NRGB_STR   "1b36"

Definition at line 58 of file usb.h.

#define P_K70_LUX_STR   "1b33"

Definition at line 56 of file usb.h.

#define P_K70_NRGB   0x1b09

Definition at line 53 of file usb.h.

Referenced by product_str().

#define P_K70_NRGB_STR   "1b09"

Definition at line 54 of file usb.h.

#define P_K70_RFIRE   0x1b38

Definition at line 59 of file usb.h.

Referenced by product_str().

#define P_K70_RFIRE_NRGB   0x1b3a

Definition at line 61 of file usb.h.

Referenced by product_str().

#define P_K70_RFIRE_NRGB_STR   "1b3a"

Definition at line 62 of file usb.h.

#define P_K70_RFIRE_STR   "1b38"

Definition at line 60 of file usb.h.

#define P_K70_STR   "1b13"

Definition at line 52 of file usb.h.

#define P_K95   0x1b11

Definition at line 65 of file usb.h.

Referenced by product_str().

#define P_K95_NRGB   0x1b08

Definition at line 67 of file usb.h.

Referenced by _nk95cmd(), and product_str().

#define P_K95_NRGB_STR   "1b08"

Definition at line 68 of file usb.h.

#define P_K95_PLATINUM   0x1b2d

Definition at line 69 of file usb.h.

Referenced by product_str().

#define P_K95_PLATINUM_STR   "1b2d"

Definition at line 70 of file usb.h.

#define P_K95_STR   "1b11"

Definition at line 66 of file usb.h.

#define P_M65   0x1b12

Definition at line 79 of file usb.h.

Referenced by product_str().

#define P_M65_PRO   0x1b2e

Definition at line 81 of file usb.h.

Referenced by product_str().

#define P_M65_PRO_STR   "1b2e"

Definition at line 82 of file usb.h.

#define P_M65_STR   "1b12"

Definition at line 80 of file usb.h.

#define P_SABRE_L   0x1b19 /* laser */

Definition at line 87 of file usb.h.

Referenced by product_str().

#define P_SABRE_L_STR   "1b19"

Definition at line 88 of file usb.h.

#define P_SABRE_N   0x1b2f /* new? */

Definition at line 89 of file usb.h.

Referenced by product_str().

#define P_SABRE_N_STR   "1b2f"

Definition at line 90 of file usb.h.

#define P_SABRE_O   0x1b14 /* optical */

Definition at line 85 of file usb.h.

Referenced by product_str().

#define P_SABRE_O2   0x1b32 /* Observed on a CH-9000111-EU model SABRE */

Definition at line 91 of file usb.h.

Referenced by product_str().

#define P_SABRE_O2_STR   "1b32"

Definition at line 92 of file usb.h.

#define P_SABRE_O_STR   "1b14"

Definition at line 86 of file usb.h.

#define P_SCIMITAR   0x1b1e

Definition at line 95 of file usb.h.

Referenced by product_str().

#define P_SCIMITAR_PRO   0x1b3e

Definition at line 97 of file usb.h.

Referenced by product_str().

#define P_SCIMITAR_PRO_STR   "1b3e"

Definition at line 98 of file usb.h.

#define P_SCIMITAR_STR   "1b1e"

Definition at line 96 of file usb.h.

#define P_STRAFE   0x1b20

Definition at line 73 of file usb.h.

Referenced by product_str().

#define P_STRAFE_NRGB   0x1b15

Definition at line 75 of file usb.h.

Referenced by product_str().

#define P_STRAFE_NRGB_STR   "1b15"

Definition at line 76 of file usb.h.

#define P_STRAFE_STR   "1b20"

Definition at line 74 of file usb.h.

#define resetusb (   kb)    _resetusb(kb, __FILE_NOPATH__, __LINE__)

Definition at line 214 of file usb.h.

Referenced by usb_tryreset().

#define USB_DELAY_DEFAULT   5

Definition at line 160 of file usb.h.

Referenced by _setupusb(), and start_dev().

#define usbrecv (   kb,
  out_msg,
  in_msg 
)    _usbrecv(kb, out_msg, in_msg, __FILE_NOPATH__, __LINE__)
Parameters
kbTHE usbdevice*
IN]out_msg What information does the caller want from the device?
OUT]in_msg Here comes the answer; The names represent the usb view, not the view of this function! So INput from usb is OUTput of this function.

Definition at line 256 of file usb.h.

Referenced by cmd_hwload_kb(), cmd_hwload_mouse(), getfwversion(), hwloadmode(), loaddpi(), loadrgb_kb(), and loadrgb_mouse().

#define usbsend (   kb,
  messages,
  count 
)    _usbsend(kb, messages, count, __FILE_NOPATH__, __LINE__)
Parameters
kbTHE usbdevice*
IN]messages a Pointer to the first byte of the logical message
IN]count how many MSG_SIZE buffers is the logical message long?

Definition at line 239 of file usb.h.

Referenced by cmd_hwsave_kb(), cmd_hwsave_mouse(), cmd_pollrate(), fwupdate(), loadrgb_kb(), savedpi(), savergb_kb(), savergb_mouse(), setactive_kb(), setactive_mouse(), updatedpi(), updatergb_kb(), and updatergb_mouse().

#define V_CORSAIR   0x1b1c
Warning
When adding new devices please update src/ckb/fwupgradedialog.cpp as well.
It should contain the same vendor/product IDs for any devices supporting firmware updates.
In the same way, all other corresponding files have to be supplemented or modified: Currently known for this are usb_linux.c and usb_mac.c

Definition at line 38 of file usb.h.

Referenced by usb_add_device(), and vendor_str().

#define V_CORSAIR_STR   "1b1c"

Definition at line 39 of file usb.h.

Referenced by udev_enum(), and usb_add_device().

Function Documentation

int _nk95cmd ( usbdevice kb,
uchar  bRequest,
ushort  wValue,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
bRequestthe byte array with the usb request
wValuea usb wValue
filefor error message
linefor error message
Returns
1 (true) on failure, 0 (false) on success.

To send control packets to a non RGB non color K95 Keyboard, use this function. Normally it is called via the nk95cmd() macro.

If it is the wrong device for which the function is called, 0 is returned and nothing done. Otherwise a usbdevfs_ctrltransfer structure is filled and an USBDEVFS_CONTROL ioctl() called.

bRequestType bRequest wValue EP size Timeout data
0x40 see table below to switch hardware-modus at Keyboard wValue device MSG_SIZE 5ms the message buffer pointer
Host to Device, Type=Vendor, Recipient=Device bRequest parameter given wValue Parameter device 0 0 data to write 5000 null

If a 0 or a negative error number is returned by the ioctl, an error message is shown depending on the errno or "No data written" if retval was 0. In either case 1 is returned to indicate the error. If the ioctl returned a value > 0, 0 is returned to indicate no error.

Currently the following combinations for bRequest and wValue are used:

Device what it might to do constant bRequest wValue
non RGB Keyboard set HW-modus on (leave the ckb driver) HWON 0x0002 0x0030
non RGB Keyboard set HW-modus off (initialize the ckb driver) HWOFF 0x0002 0x0001
non RGB Keyboard set light modus M1 in single-color keyboards NK95_M1 0x0014 0x0001
non RGB Keyboard set light modus M2 in single-color keyboards NK95_M2 0x0014 0x0002
non RGB Keyboard set light modus M3 in single-color keyboards NK95_M3 0x0014 0x0003
See Also
usb.h

Definition at line 188 of file usb_linux.c.

References ckb_err_fn, usbdevice::handle, P_K95_NRGB, and usbdevice::product.

188  {
189  if(kb->product != P_K95_NRGB)
190  return 0;
191  struct usbdevfs_ctrltransfer transfer = { 0x40, bRequest, wValue, 0, 0, 5000, 0 };
192  int res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer);
193  if(res <= 0){
194  ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data written");
195  return 1;
196  }
197  return 0;
198 }
short product
Definition: structures.h:237
#define P_K95_NRGB
Definition: usb.h:67
int handle
Definition: structures.h:187
#define ckb_err_fn(fmt, file, line, args...)
Definition: includes.h:48
int _resetusb ( usbdevice kb,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
filefilename for error messages
lineline where it is called for error messages
Returns
Returns 0 on success, -1 if device should be removed

_resetusb Reset a USB device.

First reset the device via os_resetusb() after a long delay (it may send something to the host). If this worked (retval == 0), give the device another long delay Then perform the initialization via the device specific start() function entry in kb->vtable and if this is successful also, return the result of the device depenten updatergb() with force=true.

Definition at line 426 of file usb.c.

References usbdevice::active, DELAY_LONG, os_resetusb(), and usbdevice::vtable.

426  {
427  // Perform a USB reset
428  DELAY_LONG(kb);
429  int res = os_resetusb(kb, file, line);
430  if(res)
431  return res;
432  DELAY_LONG(kb);
433  // Re-initialize the device
434  if(kb->vtable->start(kb, kb->active) != 0)
435  return -1;
436  if(kb->vtable->updatergb(kb, 1) != 0)
437  return -1;
438  return 0;
439 }
#define DELAY_LONG(kb)
The longest delay takes place where something went wrong (eg when resetting the device) ...
Definition: usb.h:155
int os_resetusb(usbdevice *kb, const char *file, int line)
os_resetusb is the os specific implementation for resetting usb
Definition: usb_linux.c:497
char active
Definition: structures.h:231
const union devcmd * vtable
Definition: structures.h:180

+ Here is the call graph for this function:

int _usbrecv ( usbdevice kb,
const uchar out_msg,
uchar in_msg,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
IN]out_msg What information does the caller want from the device?
OUT]in_msg Here comes the answer; The names represent the usb view, not the view of this function! So INput from usb is OUTput of this function.
IN]file for debugging
IN]line for debugging
IN]reset_stop global variable is read
Returns
number of bytes read or zero on failure.

_usbrecv Request data from a USB device by first sending an output packet and then reading the response.

To fully understand this, you need to know about usb: All control is at the usb host (the CPU). If the device wants to communicate something to the host, it must wait for the host to ask. The usb protocol defines the cycles and periods in which actions are to be taken.

So in order to receive a data packet from the device, the host must first send a send request.
This is done by _usbrecv() in the first block by sending the MSG_SIZE large data block from out_msg via os_usbsend() as it is a machine depending implementation. The usb target device is as always determined over kb.

For os_usbsend() to know that it is a receive request, the is_recv parameter is set to true (1). With this, os_usbsend () generates a control package for the hardware, not a data packet.

If sending of the control package is not successful, a maximum of 5 times the transmission is repeated (including the first attempt). If a non-cancelable error is signaled or the drive is stopped via reset_stop, _usbrecv() immediately returns 0.

After this, the function waits for the requested response from the device using os_usbrecv ().

os_usbrecv() returns 0, -1 or something else.
Zero signals a serious error which is not treatable and _usbrecv() also returns 0.
-1 means that it is a treatable error - a timeout for example - and therefore the next transfer attempt is started after a long pause (DELAY_LONG) if not reset_stop or the wrong hwload_mode require a termination with a return value of 0.

After 5 attempts, _usbrecv () returns and returns 0 as well as an error message.

When data is received, the number of received bytes is returned. This should always be MSG_SIZE, but os_usbrecv() can also return less. It should not be more, because then there would be an unhandled buffer overflow, but it could be less. This would be signaled in os_usbrecv () with a message.

The buffers behind out_msg and in_msg are MSG_SIZE at least (currently 64 Bytes). More is ok but useless, less brings unpredictable behavior.

< Synchonization between macro and color information

Definition at line 601 of file usb.c.

References ckb_err_fn, DELAY_LONG, DELAY_MEDIUM, DELAY_SHORT, hwload_mode, mmutex, os_usbrecv(), os_usbsend(), and reset_stop.

601  {
602  // Try a maximum of 5 times
603  for (int try = 0; try < 5; try++) {
604  // Send the output message
605  pthread_mutex_lock(mmutex(kb));
606  DELAY_SHORT(kb);
607  int res = os_usbsend(kb, out_msg, 1, file, line);
608  pthread_mutex_unlock(mmutex(kb));
609  if (res == 0)
610  return 0;
611  else if (res == -1) {
612  // Retry on temporary failure
613  if (reset_stop)
614  return 0;
615  DELAY_LONG(kb);
616  continue;
617  }
618  // Wait for the response
619  DELAY_MEDIUM(kb);
620  res = os_usbrecv(kb, in_msg, file, line);
621  if(res == 0)
622  return 0;
623  else if(res != -1)
624  return res;
625  if(reset_stop || hwload_mode != 2)
626  return 0;
627  DELAY_LONG(kb);
628  }
629  // Give up
630  ckb_err_fn("Too many send/recv failures. Dropping.\n", file, line);
631  return 0;
632 }
#define mmutex(kb)
Definition: device.h:26
#define DELAY_MEDIUM(kb)
the medium delay is used after sending a command before waiting for the answer.
Definition: usb.h:152
#define DELAY_SHORT(kb)
USB delays for when the keyboards get picky about timing That was the original comment, but it is used anytime. The short delay is used before any send or receive.
Definition: usb.h:149
#define DELAY_LONG(kb)
The longest delay takes place where something went wrong (eg when resetting the device) ...
Definition: usb.h:155
int os_usbrecv(usbdevice *kb, uchar *in_msg, const char *file, int line)
os_usbrecv receives a max MSGSIZE long buffer from usb device
Definition: usb_linux.c:129
volatile int reset_stop
brief .
Definition: usb.c:25
int hwload_mode
hwload_mode is defined in device.c
Definition: device.c:7
int os_usbsend(usbdevice *kb, const uchar *out_msg, int is_recv, const char *file, int line)
os_usbsend sends a data packet (MSG_SIZE = 64) Bytes long
Definition: usb_linux.c:68
#define ckb_err_fn(fmt, file, line, args...)
Definition: includes.h:48

+ Here is the call graph for this function:

int _usbsend ( usbdevice kb,
const uchar messages,
int  count,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
IN]messages a Pointer to the first byte of the logical message
IN]count how many MSG_SIZE buffers is the logical message long?
IN]file for debugging
IN]line for debugging
[in]reset_stopglobal variable is read
Returns
number of Bytes sent (ideal == count * MSG_SIZE);
0 if a block could not be sent and it was not a timeout OR reset_stop was required or hwload_mode is not set to "always"

_usbsend send a logical message completely to the given device

Todo:
A lot of different conditions are combined in this code. Don't think, it is good in every combination...

The main task of _usbsend () is to transfer the complete logical message from the buffer beginning with messages to count * MSG_SIZE.
According to usb 2.0 specification, a USB transmits a maximum of 64 byte user data packets. For the transmission of longer messages we need a segmentation. And that is exactly what happens here.

The message is given one by one to os_usbsend() in MSG_SIZE (= 64) byte large bites.

Attention
This means that the buffer given as argument must be n * MSG_SIZE Byte long.

An essential constant parameter which is relevant for os_usbsend() only is is_recv = 0, which means sending.

Now it gets a little complicated again:

  • If os_usbsend() returns 0, only zero bytes could be sent in one of the packets, or it was an error (-1 from the systemcall), but not a timeout. How many Bytes were sent in total from earlier calls does not seem to matter, _usbsend() returns a total of 0.
  • Returns os_usbsend() -1, first check if reset_stop is set globally or (incomprehensible) hwload_mode is not set to "always". In either case, _usbsend() returns 0, otherwise it is assumed to be a temporary transfer error and it simply retransmits the physical packet after a long delay.
  • If the return value of os_usbsend() was neither 0 nor -1, it specifies the numer of bytes transferred.
    Here is an information hiding conflict with os_usbsend() (at least in the Linux version):
    If os_usbsend() can not transfer the entire packet, errors are thrown and the number of bytes sent is returned. _usbsend() interprets this as well and remembers the total number of bytes transferred in the local variable total_sent. Subsequently, however, transmission is continued with the next complete MSG_SIZE block and not with the first of the possibly missing bytes.
    Todo:
    Check whether this is the same in the macOS variant. It is not dramatic, but if errors occur, it can certainly irritate the devices completely if they receive incomplete data streams. Do we have errors with the messages "Wrote YY bytes (expected 64)" in the system logs? If not, we do not need to look any further.

When the last packet is transferred, _usbsend() returns the effectively counted set of bytes (from total_sent). This at least gives the caller the opportunity to check whether something has been lost in the middle.

A bit strange is the structure of the program: Handling the count MSG_SIZE blocks to be transferred is done in the outer for (...) loop. Repeating the transfer with a treatable error is managed by the inner while(1) loop.
This must be considered when reading the code; The "break" on successful block transfer leaves the inner while, not the for (...).

< Synchonization between macro and color information

Definition at line 532 of file usb.c.

References DELAY_LONG, DELAY_SHORT, hwload_mode, mmutex, MSG_SIZE, os_usbsend(), and reset_stop.

532  {
533  int total_sent = 0;
534  for(int i = 0; i < count; i++){
535  // Send each message via the OS function
536  while(1){
537  pthread_mutex_lock(mmutex(kb));
538  DELAY_SHORT(kb);
539  int res = os_usbsend(kb, messages + i * MSG_SIZE, 0, file, line);
540  pthread_mutex_unlock(mmutex(kb));
541  if(res == 0)
542  return 0;
543  else if(res != -1){
544  total_sent += res;
545  break;
546  }
547  // Stop immediately if the program is shutting down or hardware load is set to tryonce
548  if(reset_stop || hwload_mode != 2)
549  return 0;
550  // Retry as long as the result is temporary failure
551  DELAY_LONG(kb);
552  }
553  }
554  return total_sent;
555 }
#define MSG_SIZE
Definition: structures.h:176
#define mmutex(kb)
Definition: device.h:26
#define DELAY_SHORT(kb)
USB delays for when the keyboards get picky about timing That was the original comment, but it is used anytime. The short delay is used before any send or receive.
Definition: usb.h:149
#define DELAY_LONG(kb)
The longest delay takes place where something went wrong (eg when resetting the device) ...
Definition: usb.h:155
volatile int reset_stop
brief .
Definition: usb.c:25
int hwload_mode
hwload_mode is defined in device.c
Definition: device.c:7
int os_usbsend(usbdevice *kb, const uchar *out_msg, int is_recv, const char *file, int line)
os_usbsend sends a data packet (MSG_SIZE = 64) Bytes long
Definition: usb_linux.c:68

+ Here is the call graph for this function:

int closeusb ( usbdevice kb)
Parameters
IN,OUT]kb
Returns
Returns 0 (everytime. No error handling is done!)

closeusb Close a USB device and remove device entry.

An imutex lock ensures first of all, that no communication is currently running from the viewpoint of the driver to the user input device (ie the virtual driver with which characters or mouse movements are sent from the daemon to the operating system as inputs).

If the kb has an acceptable value != 0, the index of the device is looked for and with this index os_inputclose() is called. After this no more characters can be sent to the operating system.

Then the connection to the usb device is capped by os_closeusb().

Todo:
What is not yet comprehensible is the call to updateconnected() BEFORE os_closeusb(). Should that be in the other sequence? Or is updateconnected() not displaying the connected usb devices, but the representation which uinput devices are loaded? Questions about questions ...

If there is no valid handle, only updateconnected() is called. We are probably trying to disconnect a connection under construction. Not clear.

The cmd pipe as well as all open notify pipes are deleted via rmdevpath ().
This means that nothing can happen to the input path - so the device-specific imutex is unlocked again and remains unlocked.

Also the dmutex is unlocked now, but only to join the thread, which was originally taken under kb->thread (which started with _setupusb()) with pthread_join() again. Because of the closed devices that thread would have to quit sometime

See Also
the hack note with rmdevpath())

As soon as the thread is caught, the dmutex is locked again, which is what I do not understand yet: What other thread can do usb communication now?
If the vtabel exists for the given kb (why not? It seems to have race conditions here!!), via the vtable the actually device-specific, but still everywhere identical freeprofile() is called. This frees areas that are no longer needed. Then the usbdevice structure in its array is set to zero completely.

Error handling is rather unusual in closeusb(); Everything works (no matter what the called functions return), and closeusb() always returns zero (success).

Definition at line 677 of file usb.c.

References ckb_info, devpath, dmutex, usbdevice::handle, imutex, INDEX_OF, keyboard, os_closeusb(), os_inputclose(), rmdevpath(), usbdevice::thread, updateconnected(), and usbdevice::vtable.

Referenced by _setupusb(), devmain(), quitWithLock(), and usb_rm_device().

677  {
678  pthread_mutex_lock(imutex(kb));
679  if(kb->handle){
680  int index = INDEX_OF(kb, keyboard);
681  ckb_info("Disconnecting %s%d\n", devpath, index);
682  os_inputclose(kb);
683  updateconnected();
684  // Close USB device
685  os_closeusb(kb);
686  } else
687  updateconnected();
688  rmdevpath(kb);
689 
690  // Wait for thread to close
691  pthread_mutex_unlock(imutex(kb));
692  pthread_mutex_unlock(dmutex(kb));
693  pthread_join(kb->thread, 0);
694  pthread_mutex_lock(dmutex(kb));
695 
696  // Delete the profile and the control path
697  if(!kb->vtable)
698  return 0;
699  kb->vtable->freeprofile(kb);
700  memset(kb, 0, sizeof(usbdevice));
701  return 0;
702 }
usbdevice keyboard[9]
remember all usb devices. Needed for closeusb().
Definition: device.c:10
void os_closeusb(usbdevice *kb)
os_closeusb unclaim it, destroy the udev device and clear data structures at kb
Definition: usb_linux.c:435
const char *const devpath
Definition: devnode.c:11
#define ckb_info(fmt, args...)
Definition: includes.h:55
#define INDEX_OF(entry, array)
Definition: includes.h:27
const union devcmd * vtable
Definition: structures.h:180
#define imutex(kb)
Definition: device.h:22
int handle
Definition: structures.h:187
void os_inputclose(usbdevice *kb)
Definition: input_linux.c:76
pthread_t thread
Definition: structures.h:217
#define dmutex(kb)
Definition: device.h:18
int rmdevpath(usbdevice *kb)
Remove the dev path for the keyboard at index. Returns 0 on success.
Definition: devnode.c:275
void updateconnected()
Update the list of connected devices.
Definition: devnode.c:81

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void os_closeusb ( usbdevice kb)
Parameters
IN,OUT]kb THE usbdevice*

os_closeusb unclaim it, destroy the udev device and clear data structures at kb

os_closeusb is the linux specific implementation for closing an active usb port.
If a valid handle is given in the kb structure, the usb port is unclaimed (usbunclaim()).
The device in unrefenced via library function udev_device_unref().
handle, udev and the first char of kbsyspath are cleared to 0 (empty string for kbsyspath).

Definition at line 435 of file usb_linux.c.

References usbdevice::handle, INDEX_OF, kbsyspath, keyboard, usbdevice::udev, and usbunclaim().

Referenced by closeusb().

435  {
436  if(kb->handle){
437  usbunclaim(kb, 0);
438  close(kb->handle - 1);
439  }
440  if(kb->udev)
441  udev_device_unref(kb->udev);
442  kb->handle = 0;
443  kb->udev = 0;
444  kbsyspath[INDEX_OF(kb, keyboard)][0] = 0;
445 }
static char kbsyspath[9][FILENAME_MAX]
Definition: usb_linux.c:13
usbdevice keyboard[9]
remember all usb devices. Needed for closeusb().
Definition: device.c:10
static int usbunclaim(usbdevice *kb, int resetting)
Definition: usb_linux.c:406
struct udev_device * udev
Definition: structures.h:186
#define INDEX_OF(entry, array)
Definition: includes.h:27
int handle
Definition: structures.h:187

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void* os_inputmain ( void *  context)
Parameters
contextTHE usbdevice* ; Because os_inputmain() is started as a new thread, its formal parameter is named "context".
Returns
null

os_inputmain is run in a separate thread and will be detached from the main thread, so it needs to clean up its own resources.

Todo:
This function is a collection of many tasks. It should be divided into several sub-functions for the sake of greater convenience:
  1. set up an URB (Userspace Ressource Buffer) to communicate with the USBDEVFS_* ioctl()s
  2. perform the ioctl()
  3. interpretate the information got into the URB buffer or handle error situations and retry operation or leave the endless loop
  4. inform the os about the data
  5. loop endless via 2.
  6. if endless loop has gone, deinitalize the interface, free buffers etc.
  7. return null

Here the actions in detail:

Monitor input transfers on all endpoints for non-RGB devices For RGB, monitor all but the last, as it's used for input/output

Get an usbdevfs_urb data structure and clear it via memset()

Hopefully the buffer lengths are equal for all devices with congruent types. You can find out the correctness for your device with lsusb –v or similar on macOS. Currently the following combinations are known and implemented:

device detect with macro combination endpoint # buffer-length
each none 0 8
RGB Mouse IS_RGB && IS_MOUSE 1 10
RGB Keyboard IS_RGB && !IS_MOUSE 1 21
RGB Mouse or Keyboard IS_RGB 2 MSG_SIZE (64)
non RGB Mouse or Keyboard !IS_RGB 1 4
non RGB Mouse or Keyboard !IS_RGB 2 15

Now submit all the URBs via ioctl(USBDEVFS_SUBMITURB) with type USBDEVFS_URB_TYPE_INTERRUPT (the endpoints are defined as type interrupt). Endpoint number is 0x80..0x82 or 0x83, depending on the model.

The userSpaceFS knows the URBs now, so start monitoring input

if the ioctl returns something != 0, let's have a deeper look what happened. Broken devices or shutting down the entire system leads to closing the device and finishing this thread.

If just an EPIPE ocurred, give the device a CLEAR_HALT and resubmit the URB.

A correct REAPURB returns a Pointer to the URB which we now have a closer look into. Lock all following actions with imutex.

Process the input depending on type of device. Interprete the actual size of the URB buffer

device detect with macro combination seems to be endpoint # actual buffer-length function called
mouse (RGB and non RGB) IS_MOUSE nA 8, 10 or 11 hid_mouse_translate()
mouse (RGB and non RGB) IS_MOUSE nA MSG_SIZE (64) corsair_mousecopy()
RGB Keyboard IS_RGB && !IS_MOUSE 1 8 (BIOS Mode) hid_kb_translate()
RGB Keyboard IS_RGB && !IS_MOUSE 2 5 or 21, KB inactive! hid_kb_translate()
RGB Keyboard IS_RGB && !IS_MOUSE 3? MSG_SIZE corsair_kbcopy()
non RGB Keyboard !IS_RGB && !IS_MOUSE nA nA hid_kb_translate()

The input data is transformed and copied to the kb structure. Now give it to the OS and unlock the imutex afterwards.

Re-submit the URB for the next run.

If the endless loop is terminated, clean up by discarding the URBs via ioctl(USBDEVFS_DISCARDURB), free the URB buffers and return a null pointer as thread exit code.

Definition at line 238 of file usb_linux.c.

References usbdevice::active, ckb_err, ckb_info, corsair_kbcopy(), corsair_mousecopy(), devpath, usbdevice::epcount, usbdevice::handle, hid_kb_translate(), hid_mouse_translate(), imutex, INDEX_OF, usbdevice::input, inputupdate(), IS_MOUSE, IS_RGB, keyboard, usbinput::keys, MSG_SIZE, usbdevice::product, usbinput::rel_x, usbinput::rel_y, and usbdevice::vendor.

Referenced by _setupusb().

238  {
239  usbdevice* kb = context;
240  int fd = kb->handle - 1;
241  short vendor = kb->vendor, product = kb->product;
242  int index = INDEX_OF(kb, keyboard);
243  ckb_info("Starting input thread for %s%d\n", devpath, index);
244 
249  int urbcount = IS_RGB(vendor, product) ? (kb->epcount - 1) : kb->epcount;
250  if (urbcount == 0) {
251  ckb_err("urbcount = 0, so there is nothing to claim in os_inputmain()\n");
252  return 0;
253  }
254 
256  struct usbdevfs_urb urbs[urbcount + 1];
257  memset(urbs, 0, sizeof(urbs));
258 
272  urbs[0].buffer_length = 8;
273  if(urbcount > 1 && IS_RGB(vendor, product)) {
274  if(IS_MOUSE(vendor, product))
275  urbs[1].buffer_length = 10;
276  else
277  urbs[1].buffer_length = 21;
278  urbs[2].buffer_length = MSG_SIZE;
279  if(urbcount != 3)
280  urbs[urbcount - 1].buffer_length = MSG_SIZE;
281  } else {
282  urbs[1].buffer_length = 4;
283  urbs[2].buffer_length = 15;
284  }
285 
288  for(int i = 0; i < urbcount; i++){
289  urbs[i].type = USBDEVFS_URB_TYPE_INTERRUPT;
290  urbs[i].endpoint = 0x80 | (i + 1);
291  urbs[i].buffer = malloc(urbs[i].buffer_length);
292  ioctl(fd, USBDEVFS_SUBMITURB, urbs + i);
293  }
294 
296  while (1) {
297  struct usbdevfs_urb* urb = 0;
298 
301  if (ioctl(fd, USBDEVFS_REAPURB, &urb)) {
302  if (errno == ENODEV || errno == ENOENT || errno == ESHUTDOWN)
303  // Stop the thread if the handle closes
304  break;
305  else if(errno == EPIPE && urb){
307  ioctl(fd, USBDEVFS_CLEAR_HALT, &urb->endpoint);
308  // Re-submit the URB
309  if(urb)
310  ioctl(fd, USBDEVFS_SUBMITURB, urb);
311  urb = 0;
312  }
313  continue;
314  }
315 
319  if (urb) {
320 
332  pthread_mutex_lock(imutex(kb));
333  if(IS_MOUSE(vendor, product)){
334  switch(urb->actual_length){
335  case 8:
336  case 10:
337  case 11:
338  // HID mouse input
339  hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -(urb->endpoint & 0xF), urb->actual_length, urb->buffer);
340  break;
341  case MSG_SIZE:
342  // Corsair mouse input
343  corsair_mousecopy(kb->input.keys, -(urb->endpoint & 0xF), urb->buffer);
344  break;
345  }
346  } else if(IS_RGB(vendor, product)){
347  switch(urb->actual_length){
348  case 8:
349  // RGB EP 1: 6KRO (BIOS mode) input
350  hid_kb_translate(kb->input.keys, -1, urb->actual_length, urb->buffer);
351  break;
352  case 21:
353  case 5:
354  // RGB EP 2: NKRO (non-BIOS) input. Accept only if keyboard is inactive
355  if(!kb->active)
356  hid_kb_translate(kb->input.keys, -2, urb->actual_length, urb->buffer);
357  break;
358  case MSG_SIZE:
359  // RGB EP 3: Corsair input
360  corsair_kbcopy(kb->input.keys, -(urb->endpoint & 0xF), urb->buffer);
361  break;
362  }
363  } else {
364  // Non-RGB input
365  hid_kb_translate(kb->input.keys, urb->endpoint & 0xF, urb->actual_length, urb->buffer);
366  }
369  inputupdate(kb);
370  pthread_mutex_unlock(imutex(kb));
371 
373  ioctl(fd, USBDEVFS_SUBMITURB, urb);
374  urb = 0;
375  }
376  }
377 
381  ckb_info("Stopping input thread for %s%d\n", devpath, index);
382  for(int i = 0; i < urbcount; i++){
383  ioctl(fd, USBDEVFS_DISCARDURB, urbs + i);
384  free(urbs[i].buffer);
385  }
386  return 0;
387 }
#define MSG_SIZE
Definition: structures.h:176
usbinput input
Definition: structures.h:245
#define ckb_err(fmt, args...)
Definition: includes.h:49
#define IS_RGB(vendor, product)
RGB vs non-RGB test (note: non-RGB Strafe is still considered "RGB" in that it shares the same protoc...
Definition: usb.h:124
usbdevice keyboard[9]
remember all usb devices. Needed for closeusb().
Definition: device.c:10
uchar keys[((((152+3+12)+25)+7)/8)]
Definition: structures.h:130
char active
Definition: structures.h:231
int epcount
Definition: structures.h:215
void inputupdate(usbdevice *kb)
Definition: input.c:241
#define IS_MOUSE(vendor, product)
Mouse vs keyboard test.
Definition: usb.h:141
short rel_x
Definition: structures.h:132
void hid_mouse_translate(unsigned char *kbinput, short *xaxis, short *yaxis, int endpoint, int length, const unsigned char *urbinput)
Definition: keymap.c:366
void corsair_mousecopy(unsigned char *kbinput, int endpoint, const unsigned char *urbinput)
Definition: keymap.c:403
const char *const devpath
Definition: devnode.c:11
#define ckb_info(fmt, args...)
Definition: includes.h:55
short product
Definition: structures.h:237
#define INDEX_OF(entry, array)
Definition: includes.h:27
short rel_y
Definition: structures.h:132
#define imutex(kb)
Definition: device.h:22
void hid_kb_translate(unsigned char *kbinput, int endpoint, int length, const unsigned char *urbinput)
Definition: keymap.c:223
int handle
Definition: structures.h:187
void corsair_kbcopy(unsigned char *kbinput, int endpoint, const unsigned char *urbinput)
Definition: keymap.c:394
short vendor
Definition: structures.h:237

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int os_resetusb ( usbdevice kb,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
filefilename for error messages
lineline where it is called for error messages
Returns
Returns 0 on success, -2 if device should be removed and -1 if reset should by tried again

os_resetusb is the os specific implementation for resetting usb

Try to reset an usb device in a linux user space driver.

  1. unclaim the device, but do not reconnect the system driver (second param resetting = true)
  2. reset the device via USBDEVFS_RESET command
  3. claim the device again. Returns 0 on success, -2 if device should be removed and -1 if reset should by tried again
Todo:
it seems that no one wants to try the reset again. But I'v seen it somewhere...

Definition at line 497 of file usb_linux.c.

References usbdevice::handle, TEST_RESET, usbclaim(), and usbunclaim().

Referenced by _resetusb().

497  {
498  TEST_RESET(usbunclaim(kb, 1));
499  TEST_RESET(ioctl(kb->handle - 1, USBDEVFS_RESET));
500  TEST_RESET(usbclaim(kb));
501  // Success!
502  return 0;
503 }
#define TEST_RESET(op)
TEST_RESET doesa "try / catch" for resetting the usb interface.
Definition: usb_linux.c:479
static int usbunclaim(usbdevice *kb, int resetting)
Definition: usb_linux.c:406
static int usbclaim(usbdevice *kb)
Definition: usb_linux.c:459
int handle
Definition: structures.h:187

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void os_sendindicators ( usbdevice kb)
Parameters
kbTHE usbdevice*

os_sendindicators update the indicators for the special keys (Numlock, Capslock and what else?)

os_sendindicators update the indicators for the special keys (Numlock, Capslock and what else?)

Read the data from kb->ileds ans send them via ioctl() to the keyboard.

bRequestType bRequest wValue EP size Timeout data
0x21 0x09 0x0200 Interface 0 MSG_SIZE 1 Byte timeout 0,5ms the message buffer pointer
Host to Device, Type=Class, Recipient=Interface (why not endpoint?) 9 = SEND? specific 0 1 500 struct* kb->ileds


The ioctl command is USBDEVFS_CONTROL.

Definition at line 213 of file usb_linux.c.

References ckb_err, usbdevice::handle, usbdevice::ileds, and usb_tryreset().

Referenced by updateindicators_kb().

213  {
214  static int countForReset = 0;
215  struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0200, 0x00, 1, 500, &kb->ileds };
216  int res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer);
217  if(res <= 0) {
218  ckb_err("%s\n", res ? strerror(errno) : "No data written");
219  if (usb_tryreset(kb) == 0 && countForReset++ < 3) {
220  os_sendindicators(kb);
221  }
222  }
223 }
int usb_tryreset(usbdevice *kb)
Definition: usb.c:465
#define ckb_err(fmt, args...)
Definition: includes.h:49
void os_sendindicators(usbdevice *kb)
Definition: usb_linux.c:213
uchar ileds
Definition: structures.h:247
int handle
Definition: structures.h:187

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int os_setupusb ( usbdevice kb)
Parameters
kbTHE usbdevice*
Returns
0 on success, -1 otherwise.

os_setupusb OS-specific setup for a specific usb device.

Perform the operating system-specific opening of the interface in os_setupusb(). As a result, some parameters should be set in kb (name, serial, fwversion, epcount = number of usb endpoints), and all endpoints should be claimed with usbclaim(). Claiming is the only point where os_setupusb() can produce an error (-1).

  • Copy device description and serial
  • Copy firmware version (needed to determine USB protocol)
  • Do some output about connecting interfaces
  • Claim the USB interfaces
Todo:
in these modules a pullrequest is outstanding

< Try to reset the device and recall the function

< Don't do this endless in recursion

< os_setupusb() has a return value (used as boolean)

Definition at line 535 of file usb_linux.c.

References ckb_err, ckb_info, devpath, usbdevice::epcount, usbdevice::fwversion, INDEX_OF, KB_NAME_LEN, keyboard, usbdevice::name, usbdevice::serial, SERIAL_LEN, strtrim(), usbdevice::udev, usb_tryreset(), and usbclaim().

Referenced by _setupusb().

535  {
538  struct udev_device* dev = kb->udev;
539  const char* name = udev_device_get_sysattr_value(dev, "product");
540  if(name)
541  strncpy(kb->name, name, KB_NAME_LEN);
542  strtrim(kb->name);
543  const char* serial = udev_device_get_sysattr_value(dev, "serial");
544  if(serial)
545  strncpy(kb->serial, serial, SERIAL_LEN);
546  strtrim(kb->serial);
549  const char* firmware = udev_device_get_sysattr_value(dev, "bcdDevice");
550  if(firmware)
551  sscanf(firmware, "%hx", &kb->fwversion);
552  else
553  kb->fwversion = 0;
554  int index = INDEX_OF(kb, keyboard);
555 
557  ckb_info("Connecting %s at %s%d\n", kb->name, devpath, index);
558 
564  const char* ep_str = udev_device_get_sysattr_value(dev, "bNumInterfaces");
565 #ifdef DEBUG
566  ckb_info("claiming interfaces. name=%s, firmware=%s; Got >>%s<< as ep_str\n", name, firmware, ep_str);
567 #endif //DEBUG
568  kb->epcount = 0;
569  if(ep_str)
570  sscanf(ep_str, "%d", &kb->epcount);
571  if(kb->epcount < 2){
572  // IF we have an RGB KB with 0 or 1 endpoints, it will be in BIOS mode.
573  ckb_err("Unable to read endpoint count from udev, assuming %d and reading >>%s<< or device is in BIOS mode\n", kb->epcount, ep_str);
574  if (usb_tryreset(kb) == 0) {
575  static int retryCount = 0;
576  if (retryCount++ < 5) {
577  return os_setupusb(kb);
578  }
579  }
580  return -1;
581  // ToDo are there special versions we have to detect? If there are, that was the old code to handle it:
582  // This shouldn't happen, but if it does, assume EP count based onckb_warn what the device is supposed to have
583  // kb->epcount = (HAS_FEATURES(kb, FEAT_RGB) ? 4 : 3);
584  // ckb_warn("Unable to read endpoint count from udev, assuming %d and reading >>%s<<...\n", kb->epcount, ep_str);
585  }
586  if(usbclaim(kb)){
587  ckb_err("Failed to claim interfaces: %s\n", strerror(errno));
588  return -1;
589  }
590  return 0;
591 }
#define KB_NAME_LEN
Definition: structures.h:174
int usb_tryreset(usbdevice *kb)
Definition: usb.c:465
char name[40+1]
Definition: structures.h:233
#define ckb_err(fmt, args...)
Definition: includes.h:49
ushort fwversion
Definition: structures.h:239
usbdevice keyboard[9]
remember all usb devices. Needed for closeusb().
Definition: device.c:10
struct udev_device * udev
Definition: structures.h:186
static int usbclaim(usbdevice *kb)
Definition: usb_linux.c:459
int epcount
Definition: structures.h:215
const char *const devpath
Definition: devnode.c:11
#define ckb_info(fmt, args...)
Definition: includes.h:55
#define INDEX_OF(entry, array)
Definition: includes.h:27
void strtrim(char *string)
Definition: usb_linux.c:510
char serial[34]
Definition: structures.h:235
int os_setupusb(usbdevice *kb)
Definition: usb_linux.c:535
#define SERIAL_LEN
Definition: structures.h:175

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int os_usbrecv ( usbdevice kb,
uchar in_msg,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
in_msgthe buffer to fill with the message received
filefor debugging
linefor debugging
Returns
-1 on timeout, 0 on hard error, numer of bytes received otherwise

os_usbrecv does what its name says:

The comment at the beginning of the procedure causes the suspicion that the firmware versionspecific distinction is missing for receiving from usb endpoint 3 or 4. The commented code contains only the reception from EP4, but this may be wrong for a software version 2.0 or higher (see the code for os-usbsend ()).


So all the receiving is done via an ioctl() like in os_usbsend. The ioctl() is given a struct usbdevfs_ctrltransfer, in which the relevant parameters are entered:

bRequestType bRequest wValue EP size Timeout data
0xA1 0x01 0x0200 endpoint to be addressed from epcount - 1 MSG_SIZE 5ms the message buffer pointer
Device to Host, Type=Class, Recipient=Interface 1 = RECEIVE? specific Interface # 64 5000 in_msg

The ioctl() returns the number of bytes received. Here is the usual check again:

  • If the return value is -1 AND the error is a timeout (ETIMEOUT), os_usbrecv() will return -1 to indicate that it is probably a recoverable problem and a retry is recommended.
  • For another negative value or other error identifier OR 0 bytes are received, 0 is returned as an identifier for a heavy error.
  • In all other cases, the function returns the number of bytes received.

If this is not the entire blocksize (MSG_SIZE bytes), an error message is issued on the standard error channel [warning "Read YY bytes (expected 64)"].

Definition at line 129 of file usb_linux.c.

References ckb_err_fn, ckb_warn_fn, usbdevice::epcount, usbdevice::handle, and MSG_SIZE.

Referenced by _usbrecv().

129  {
130  int res;
131  // This is what CUE does, but it doesn't seem to work on linux.
132  /*if(kb->fwversion >= 0x130){
133  struct usbdevfs_bulktransfer transfer = {0};
134  transfer.ep = 0x84;
135  transfer.len = MSG_SIZE;
136  transfer.timeout = 5000;
137  transfer.data = in_msg;
138  res = ioctl(kb->handle - 1, USBDEVFS_BULK, &transfer);
139  } else {*/
140  struct usbdevfs_ctrltransfer transfer = { 0xa1, 0x01, 0x0300, kb->epcount - 1, MSG_SIZE, 5000, in_msg };
141  res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer);
142  //}
143  if(res <= 0){
144  ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data read");
145  if(res == -1 && errno == ETIMEDOUT)
146  return -1;
147  else
148  return 0;
149  } else if(res != MSG_SIZE)
150  ckb_warn_fn("Read %d bytes (expected %d)\n", file, line, res, MSG_SIZE);
151 #ifdef DEBUG_USB_RECV
152  char converted[MSG_SIZE*3 + 1];
153  for(int i=0;i<MSG_SIZE;i++)
154  sprintf(&converted[i*3], "%02x ", in_msg[i]);
155  ckb_warn_fn("Recv %s\n", file, line, converted);
156 #endif
157  return res;
158 }
#define MSG_SIZE
Definition: structures.h:176
int epcount
Definition: structures.h:215
#define ckb_warn_fn(fmt, file, line, args...)
Definition: includes.h:51
int handle
Definition: structures.h:187
#define ckb_err_fn(fmt, file, line, args...)
Definition: includes.h:48

+ Here is the caller graph for this function:

int os_usbsend ( usbdevice kb,
const uchar out_msg,
int  is_recv,
const char *  file,
int  line 
)
Parameters
kbTHE usbdevice*
out_msgthe MSGSIZE char long buffer to send
is_recvif true, just send an ioctl for further reading packets. If false, send the data at out_msg.
filefor debugging
linefor debugging
Returns
-1 on timeout (try again), 0 on hard error, numer of bytes sent otherwise

os_usbsend has two functions:

  • if is_recv == false, it tries to send a given MSG_SIZE buffer via the usb interface given with kb.
  • otherwise a request is sent via the usb device to initiate the receiving of a message from the remote device.

The functionality for sending distinguishes two cases, depending on the version number of the firmware of the connected device:
If the firmware is less or equal 1.2, the transmission is done via an ioctl(). The ioctl() is given a struct usbdevfs_ctrltransfer, in which the relevant parameters are entered:

bRequestType bRequest wValue EP size Timeout data
0x21 0x09 0x0200 endpoint / IF to be addressed from epcount-1 MSG_SIZE 5000 (=5ms) the message buffer pointer
Host to Device, Type=Class, Recipient=Interface 9 = Send data? specific last or pre-last device # 64 5000 out_msg


The ioctl command is USBDEVFS_CONTROL.

The same constellation is used if the device is requested to send its data (is_recv = true).

For a more recent firmware and is_recv = false, the ioctl command USBDEVFS_CONTROL is not used (this tells the bus to enter the control mode), but the bulk method is used: USBDEVFS_BULK. This is astonishing, because all of the endpoints are type Interrupt, not bulk.

Anyhow, forthis purpose a different structure is used for the ioctl() (struct usbdevfs_bulktransfer) and this is also initialized differently:
The length and timeout parameters are given the same values as above. The formal parameter out_msg is also passed as a buffer pointer. For the endpoints, the firmware version is differentiated again:
For a firmware version between 1.3 and <2.0 endpoint 4 is used, otherwise (it can only be >=2.0) endpoint 3 is used.

Todo:
Since the handling of endpoints has already led to problems elsewhere, this implementation is extremely hardware-dependent and critical!
Eg. the new keyboard K95PLATINUMRGB has a version number significantly less than 2.0 - will it run with this implementation?

The ioctl() - no matter what type - returns the number of bytes sent. Now comes the usual check:

  • If the return value is -1 AND the error is a timeout (ETIMEOUT), os_usbsend() will return -1 to indicate that it is probably a recoverable problem and a retry is recommended.
  • For another negative value or other error identifier OR 0 bytes sent, 0 is returned as a heavy error identifier.
  • In all other cases, the function returns the number of bytes sent.

If this is not the entire blocksize (MSG_SIZE bytes), an error message is issued on the standard error channel [warning "Wrote YY bytes (expected 64)"].

If DEBUG_USB is set during compilation, the number of bytes sent and their representation are logged to the error channel.

Definition at line 68 of file usb_linux.c.

References ckb_err_fn, ckb_warn_fn, usbdevice::epcount, usbdevice::fwversion, usbdevice::handle, and MSG_SIZE.

Referenced by _usbrecv(), and _usbsend().

68  {
69  int res;
70  if (kb->fwversion >= 0x120 && !is_recv) {
71  struct usbdevfs_bulktransfer transfer = {0};
72  transfer.ep = (kb->fwversion >= 0x130 && kb->fwversion < 0x200) ? 4 : 3;
73  transfer.len = MSG_SIZE;
74  transfer.timeout = 5000;
75  transfer.data = (void*)out_msg;
76  res = ioctl(kb->handle - 1, USBDEVFS_BULK, &transfer);
77  } else {
78  struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0200, kb->epcount - 1, MSG_SIZE, 5000, (void*)out_msg };
79  res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer);
80  }
81 
82  if (res <= 0){
83  ckb_err_fn(" %s, res = 0x%x\n", file, line, res ? strerror(errno) : "No data written", res);
84  if(res == -1 && errno == ETIMEDOUT)
85  return -1;
86  else
87  return 0;
88  } else if (res != MSG_SIZE)
89  ckb_warn_fn("Wrote %d bytes (expected %d)\n", file, line, res, MSG_SIZE);
90 #ifdef DEBUG_USB
91  char converted[MSG_SIZE*3 + 1];
92  for(int i=0;i<MSG_SIZE;i++)
93  sprintf(&converted[i*3], "%02x ", out_msg[i]);
94  ckb_warn_fn("Sent %s\n", file, line, converted);
95 #endif
96  return res;
97 }
#define MSG_SIZE
Definition: structures.h:176
ushort fwversion
Definition: structures.h:239
int epcount
Definition: structures.h:215
#define ckb_warn_fn(fmt, file, line, args...)
Definition: includes.h:51
int handle
Definition: structures.h:187
#define ckb_err_fn(fmt, file, line, args...)
Definition: includes.h:48

+ Here is the caller graph for this function:

const char* product_str ( short  product)
Parameters
productis the short USB device product ID
Returns
string to identify a type of device (see below)

product_str returns a condensed view on what type of device we have.

At present, various models and their properties are known from corsair products. Some models differ in principle (mice and keyboards), others differ in the way they function (for example, RGB and non RGB), but they are very similar.

Here, only the first point is taken into consideration and we return a unified model string. If the model is not known with its number, product_str returns an empty string.

The model numbers and corresponding strings wwith the numbers in hex-string are defined in usb.h

At present, this function is used to initialize kb->name and to give information in debug strings.

Attention
The combinations below have to fit to the combinations in the macros mentioned above. So if you add a device with a new number, change both.
Todo:
There are macros defined in usb.h to detect all the combinations below. the only difference is the parameter: The macros need the kb*, product_str() needs the product ID

Definition at line 70 of file usb.c.

References P_K65, P_K65_LUX, P_K65_NRGB, P_K65_RFIRE, P_K70, P_K70_LUX, P_K70_LUX_NRGB, P_K70_NRGB, P_K70_RFIRE, P_K70_RFIRE_NRGB, P_K95, P_K95_NRGB, P_K95_PLATINUM, P_M65, P_M65_PRO, P_SABRE_L, P_SABRE_N, P_SABRE_O, P_SABRE_O2, P_SCIMITAR, P_SCIMITAR_PRO, P_STRAFE, and P_STRAFE_NRGB.

Referenced by _mkdevpath(), and _setupusb().

70  {
71  if(product == P_K95 || product == P_K95_NRGB || product == P_K95_PLATINUM)
72  return "k95";
73  if(product == P_K70 || product == P_K70_NRGB || product == P_K70_LUX || product == P_K70_LUX_NRGB || product == P_K70_RFIRE || product == P_K70_RFIRE_NRGB)
74  return "k70";
75  if(product == P_K65 || product == P_K65_NRGB || product == P_K65_LUX || product == P_K65_RFIRE)
76  return "k65";
77  if(product == P_STRAFE || product == P_STRAFE_NRGB)
78  return "strafe";
79  if(product == P_M65 || product == P_M65_PRO)
80  return "m65";
81  if(product == P_SABRE_O || product == P_SABRE_L || product == P_SABRE_N || product == P_SABRE_O2)
82  return "sabre";
83  if(product == P_SCIMITAR || product == P_SCIMITAR_PRO)
84  return "scimitar";
85  return "";
86 }
#define P_K70_RFIRE_NRGB
Definition: usb.h:61
#define P_K95_PLATINUM
Definition: usb.h:69
#define P_K65_LUX
Definition: usb.h:45
#define P_K95
Definition: usb.h:65
#define P_SABRE_N
Definition: usb.h:89
#define P_SABRE_O
Definition: usb.h:85
#define P_K65
Definition: usb.h:41
#define P_K70_NRGB
Definition: usb.h:53
#define P_M65
Definition: usb.h:79
#define P_STRAFE
Definition: usb.h:73
#define P_SABRE_L
Definition: usb.h:87
#define P_M65_PRO
Definition: usb.h:81
#define P_K70_RFIRE
Definition: usb.h:59
#define P_K65_NRGB
Definition: usb.h:43
#define P_SCIMITAR_PRO
Definition: usb.h:97
#define P_K70
Definition: usb.h:51
#define P_K95_NRGB
Definition: usb.h:67
#define P_SABRE_O2
Definition: usb.h:91
#define P_STRAFE_NRGB
Definition: usb.h:75
#define P_K70_LUX
Definition: usb.h:55
#define P_K70_LUX_NRGB
Definition: usb.h:57
#define P_SCIMITAR
Definition: usb.h:95
#define P_K65_RFIRE
Definition: usb.h:47

+ Here is the caller graph for this function:

int revertusb ( usbdevice kb)
Parameters
kbTHE usbdevice*
Returns
0 on success or if device needs firmware upgrade, -1 otherwise

revertusb sets a given device to inactive (hardware controlled) mode if not a fw-ugrade is indicated

First is checked, whether a firmware-upgrade is indicated for the device. If so, revertusb() returns 0.

Todo:
Why is this useful? Are there problems seen with deactivating a device with older fw-version??? Why isn't this an error indicating reason and we return success (0)?

Anyway, the following steps are similar to some other procs, dealing with low level usb handling:

  • If we do not have an RGB device, a simple setting to Hardware-mode (NK95_HWON) is sent to the device via n95cmd().
    Todo:
    The return value of nk95cmd() is ignored (but sending the ioctl may produce an error and _nk95_cmd will indicate this), instead revertusb() returns success in any case.
  • If we have an RGB device, setactive() is called with second param active = false. That function will have a look on differences between keyboards and mice.
    More precisely setactive() is just a macro to call via the kb->vtable enties either the active() or the idle() function where the vtable points to. setactive() may return error indications. If so, revertusb() returns -1, otherwise 0 in any other case.

Definition at line 407 of file usb.c.

References FEAT_RGB, HAS_FEATURES, NEEDS_FW_UPDATE, NK95_HWON, nk95cmd, and setactive.

Referenced by quitWithLock().

407  {
408  if(NEEDS_FW_UPDATE(kb))
409  return 0;
410  if(!HAS_FEATURES(kb, FEAT_RGB)){
411  nk95cmd(kb, NK95_HWON);
412  return 0;
413  }
414  if(setactive(kb, 0))
415  return -1;
416  return 0;
417 }
#define nk95cmd(kb, command)
nk95cmd() macro is used to wrap _nk95cmd() with debugging information (file and lineno). the command structure is different: Just the bits 23..16 are used as bits 7..0 for bRequest Bits 15..0 are used as wValue
Definition: usb.h:296
#define FEAT_RGB
Definition: structures.h:136
#define NK95_HWON
Hardware playback on.
Definition: usb.h:304
#define NEEDS_FW_UPDATE(kb)
Definition: structures.h:161
#define HAS_FEATURES(kb, feat)
Definition: structures.h:157
#define setactive(kb, makeactive)
setactive() calls via the corresponding kb->vtable either the active() or the idle() function...
Definition: device.h:44

+ Here is the caller graph for this function:

void setupusb ( usbdevice kb)
Attention
Lock a device's dmutex (see device.h) before accessing the USB interface.
Parameters
kbTHE usbdevice* used everywhere
OUT]kb->thread is used to store the thread ID of the fresh created thread.

setupusb starts a thread with kb as parameter and _setupusb() as entrypoint.

Set up a USB device after its handle is open. Spawns a new thread _setupusb() with standard parameter kb. dmutex must be locked prior to calling this function. The function will unlock it when finished. In kb->thread the thread id is mentioned, because closeusb() needs this info for joining that thread again.

Definition at line 386 of file usb.c.

References _setupusb(), ckb_err, imutex, and usbdevice::thread.

Referenced by usbadd().

386  {
387  pthread_mutex_lock(imutex(kb));
388  if(pthread_create(&kb->thread, 0, _setupusb, kb))
389  ckb_err("Failed to create USB thread\n");
390 }
#define ckb_err(fmt, args...)
Definition: includes.h:49
static void * _setupusb(void *context)
brief .
Definition: usb.c:214
#define imutex(kb)
Definition: device.h:22
pthread_t thread
Definition: structures.h:217

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int usb_tryreset ( usbdevice kb)
Parameters
[in,out]kbTHE usbdevice*
[in]reset_stopglobal variable is read
Returns
0 on success, -1 otherwise

usb_tryreset does what the name means: Try to reset the usb via resetusb()

This function is called if an usb command ran into an error in case of one of the following two situations:

  • When setting up a new usb device and the start() function got an error (
    See Also
    _setupusb())
  • If upgrading to a new firmware gets an error (
    See Also
    cmd_fwupdate()).
    The previous action which got the error will NOT be re-attempted.

In an endless loop usb_tryreset() tries to reset the given usb device via the macro resetusb().
This macro calls _resetusb() with debugging information.
_resetusb() sends a command via the operating system dependent function os_resetusb() and - if successful - reinitializes the device. os_resetusb() returns -2 to indicate a broken device and all structures should be removed for it.
In that case, the loop is terminated, an error message is produced and usb_tryreset() returns -1.

In case resetusb() has success, the endless loop is left via a return 0 (success).
If the return value from resetusb() is -1, the loop is continued with the next try.

If the global variable reset_stop is set directly when the function is called or after each try, usb_tryreset() stops working and returns -1.

Todo:
Why does usb_tryreset() hide the information returned from resetusb()? Isn't it needed by the callers?

Definition at line 465 of file usb.c.

References ckb_err, ckb_info, reset_stop, and resetusb.

Referenced by _setupusb(), cmd_fwupdate(), os_sendindicators(), and os_setupusb().

465  {
466  if(reset_stop)
467  return -1;
468  ckb_info("Attempting reset...\n");
469  while(1){
470  int res = resetusb(kb);
471  if(!res){
472  ckb_info("Reset success\n");
473  return 0;
474  }
475  if(res == -2 || reset_stop)
476  break;
477  }
478  ckb_err("Reset failed. Disconnecting.\n");
479  return -1;
480 }
#define ckb_err(fmt, args...)
Definition: includes.h:49
volatile int reset_stop
brief .
Definition: usb.c:25
#define ckb_info(fmt, args...)
Definition: includes.h:55
#define resetusb(kb)
resetusb() is just a macro to call _resetusb() with debuggin constants (file, lineno) ...
Definition: usb.h:214

+ Here is the caller graph for this function:

void usbkill ( )

Definition at line 835 of file usb_linux.c.

Referenced by quitWithLock().

835  {
836  udev_unref(udev);
837  udev = 0;
838 }
static struct udev * udev
struct udef is defined in /usr/include/libudev.h
Definition: usb_linux.c:639

+ Here is the caller graph for this function:

int usbmain ( )

Start the USB main loop. Returns program exit code when finished.

usbmain is called by main() after setting up all other stuff.

Returns
0 normally or -1 if fatal error occurs (up to now only if no new devices are available)

First check whether the uinput module is loaded by the kernel.

Todo:
Why isn't missing of uinput a fatal error?

Create the udev object with udev_new() (is a function from libudev.h) terminate -1 if error

Enumerate all currently connected devices

Todo:
lae. here the work has to go on...

Definition at line 775 of file usb_linux.c.

References ckb_fatal, ckb_warn, udev_enum(), usb_add_device(), and usb_rm_device().

Referenced by main().

775  {
780  // Load the uinput module (if it's not loaded already)
781  if(system("modprobe uinput") != 0)
782  ckb_warn("Failed to load uinput module\n");
783 
787  if(!(udev = udev_new())) {
788  ckb_fatal("Failed to initialize udev in usbmain(), usb_linux.c\n");
789  return -1;
790  }
791 
794  udev_enum();
795 
798  // Done scanning. Enter a loop to poll for device updates
799  struct udev_monitor* monitor = udev_monitor_new_from_netlink(udev, "udev");
800  udev_monitor_filter_add_match_subsystem_devtype(monitor, "usb", 0);
801  udev_monitor_enable_receiving(monitor);
802  // Get an fd for the monitor
803  int fd = udev_monitor_get_fd(monitor);
804  fd_set fds;
805  while(udev){
806  FD_ZERO(&fds);
807  FD_SET(fd, &fds);
808  // Block until an event is read
809  if(select(fd + 1, &fds, 0, 0, 0) > 0 && FD_ISSET(fd, &fds)){
810  struct udev_device* dev = udev_monitor_receive_device(monitor);
811  if(!dev)
812  continue;
813  const char* action = udev_device_get_action(dev);
814  if(!action){
815  udev_device_unref(dev);
816  continue;
817  }
818  // Add/remove device
819  if(!strcmp(action, "add")){
820  int res = usb_add_device(dev);
821  if(res == 0)
822  continue;
823  // If the device matched but the handle wasn't opened correctly, re-enumerate (this sometimes solves the problem)
824  if(res == -1)
825  udev_enum();
826  } else if(!strcmp(action, "remove"))
827  usb_rm_device(dev);
828  udev_device_unref(dev);
829  }
830  }
831  udev_monitor_unref(monitor);
832  return 0;
833 }
#define ckb_fatal(fmt, args...)
Definition: includes.h:46
static void usb_rm_device(struct udev_device *dev)
usb_rm_device find the usb port to remove and close it via closeusb().
Definition: usb_linux.c:720
#define ckb_warn(fmt, args...)
Definition: includes.h:52
static void udev_enum()
udev_enum use the udev_enumerate_add_match_subsystem() to get all you need but only that...
Definition: usb_linux.c:747
static int usb_add_device(struct udev_device *dev)
Add a udev device. Returns 0 if device was recognized/added.
Definition: usb_linux.c:695
static struct udev * udev
struct udef is defined in /usr/include/libudev.h
Definition: usb_linux.c:639

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const char* vendor_str ( short  vendor)

uncomment to see USB packets sent from the device vendor_str Vendor/product string representations

Parameters
vendorshort vendor ID
Returns
a string: either "" or "corsair"

uncomment the following Define to see USB packets sent to the device

vendor_str returns "corsair" iff the given vendor argument is equal to V_CORSAIR (0x1bc) else it returns ""

Attention
There is also a string defined V_CORSAIR_STR, which returns the device number as string in hex "1b1c".

Definition at line 43 of file usb.c.

References V_CORSAIR.

Referenced by _mkdevpath(), and _setupusb().

43  {
44  if(vendor == V_CORSAIR)
45  return "corsair";
46  return "";
47 }
#define V_CORSAIR
For the following Defines please see "Detailed Description".
Definition: usb.h:38

+ Here is the caller graph for this function: