1
1
input/devi/hid/control.c

254 строки
8.5 KiB
C

/*
* (c) 2010, SWD Embedded Systems Limited, http://www.kpda.ru
*/
/*
* Предостережение:
*
* Предоставленный исходный код драйвера devi-hid рекомендуется использовать
* только для отладочных целей при разработке HID-драйверов. Для всех остальных
* задач следует использовать штатный системный драйвер devi-hid.
*
* В общем случае не существует задач, которые требуется решать в этом драйвере
* при поддержке нового оборудования (для этого должен быть написан/модифицирован
* отдельный драйвер ввода или HID-драйвер).
*/
/*
* control.c
*
* The HID USB control combined device/protocol module.
*
*/
#include <sys/devi.h>
#include "hid.h"
#include <assert.h>
#define FLAG_INIT 0x0100
#define FLAG_RESET 0x0200
#define FLAG_KIOSK_MODE 0x0400
#define controlED 1
#define RELEASED 0
/* Protocol module private data */
struct private_data {
int flags; /* see valid values before */
int nDev; /* USB device number */
int state;
void * hid_module_handle; /* HID module_handle */
};
/* forward declarations */
static int control_init(input_module_t *module);
static int control_devctrl(input_module_t *module, int event, void *ptr);
static int control_reset(input_module_t *module);
static int control_input(input_module_t *module, int num, void *arg);
static int control_parm(input_module_t *module, int opt, char *optarg);
static int control_shutdown(input_module_t *module, int delay);
/* Our protocol module is represented by the following input_module_t data structure */
input_module_t control = {
NULL,
NULL,
NULL,
0,
DEVI_CLASS_CONTROL | DEVI_MODULE_TYPE_PROTO | DEVI_MODULE_TYPE_DEVICE,
"control",
__DATE__,
"Ku:",
NULL,
control_init,
control_reset,
control_input,
NULL,
NULL,
control_parm,
control_devctrl,
control_shutdown
};
/* Description: callback initialisation function; it is called when input module is */
/* initialising the input system */
/* Input : input_module_t * module - pointer to module descriptor */
/* Output : None */
/* Return : 0 if OK, otherwise - (-1) */
int control_init(input_module_t *module)
{
struct private_data *dp = module->data;
if(!module->data)
{
if(!(dp = module->data = _scalloc(sizeof *dp)))
{
return (-1);
}
}
dp -> nDev = HIDD_CONNECT_WILDCARD;
dp->state = RELEASED;
return (0);
}
/* Description: this is a callback function for DEVCTRL command processing */
/* Input : input_module_t * module - pointer to module descriptor */
/* int event - DEVCTRL command code */
/* void * ptr - pointer to data exchange block */
/* Output : None */
/* Return : 0 if OK, otherwise -1 */
int control_devctrl(input_module_t *module, int event, void *ptr)
{
struct private_data *dp = module->data;
int rc = 0;
switch(event)
{
case DEVCTL_GETDEVFLAGS:
*(unsigned short *)ptr = (dp->flags & FLAGS_GLOBAL);
break;
case DEVCTL_GETPTRBTNS:
*(unsigned long *)ptr = 5L;
break;
case DEVCTL_GETPTRCOORD:
*(unsigned char *)ptr='\02';
break;
default:
rc = devi_hid_devctrl(dp -> hid_module_handle, event, ptr, HIDD_CONNECT_WILDCARD );
break;
}
return (rc);
}
/* Description: this callback funtion is called when the module is linked into the */
/* event bus;it is used to set initial module state on the protocol */
/* level */
/* Input : input_module_t * module - pointer to module descriptor */
/* Output : None */
/* Return : 0 if OK, otherwise -1 */
int control_reset(input_module_t *module)
{
struct private_data *dp = module->data;
if(!(dp->flags & FLAG_INIT))
{
if(NULL == (dp -> hid_module_handle = devi_hid_register_client(module, dp -> nDev)))
return (-1);
}
dp->flags |= FLAG_INIT;
return (0);
}
/* Description: main protocol processing function. It will be called by the */
/* device layer to pass it data to process. Its job is to interpret */
/* the data according to the MS wheel control protocol, create a */
/* data structure, fill it in and hand it off to the filter layer */
/* module above it. The protocol is processed using simple state */
/* machine. State info is kept in module's private data */
/* Input : input_module_t * module - pointer to module descriptor */
/* int num - number of bytes to process */
/* void * arg - raw data to process */
/* Output : None */
/* Return : 0 if OK, otherwise -1 */
/* Comment : driver uses one of two input modules depending on device data */
/* protocol */
int control_input(input_module_t *module, int num, void *arg)
{
pControl_raw_data_t control_raw_data = (pControl_raw_data_t)arg;
struct packet_control mp;
struct private_data *dp = module->data;
input_module_t *up = module->up;
assert(num == sizeof(control_raw_data_t)); // Desynchronized exchange format
if(dp->flags & FLAG_INIT)
{
mp.Rx = control_raw_data->Rx;
mp.Ry = control_raw_data->Ry;
mp.Rz = control_raw_data->Rz;
mp.button_state = control_raw_data->button_state;
}
if (verbosity > 1)
fprintf (stderr, "Device Module Level: Rx:%d, Ry:%d, Rz:%d, Buttons %x\n", mp.Rx, mp.Ry, mp.Rz, mp.button_state);
(up->input)(up, 1, &mp);
return (0);
}
/* Description: this is a callback function for command line parameter processing */
/* (all valid parameters for device module are listed in control.args) */
/* Input : input_module_t * module - pointer to module descriptor */
/* int opt - parameter code */
/* char * optarg - optional parameter value */
/* Output : None */
/* Return : 0 if OK, otherwise -1 */
/* Comment : we don't accept any parameter for this module at the protocol level */
int control_parm(input_module_t *module, int opt, char *optarg)
{
/* Now empty */
struct private_data *dp = module->data;
switch (opt)
{
case 'u':
{
if(NULL != optarg)
dp->nDev = atoi(optarg);
break;
}
case 'K':
{
dp->flags |= FLAG_KIOSK_MODE;
break;
}
default:
break;
}
return (0);
}
/* Description: this is a callback function which is called when resourse manager */
/* is shutting down */
/* Input : input_module_t * module - pointer to module descriptor */
/* int ms - program doesn't use this parameter */
/* Output : None */
/* Return : 0 if OK, otherwise -1 */
/* Comment : Does nothing for the protocol level */
int control_shutdown(input_module_t *module, int delay)
{
struct private_data *dp = module->data;
if( (NULL != dp) && (NULL != dp -> hid_module_handle))
devi_unregister_hid_client(dp -> hid_module_handle);
return (0);
}