1 /*****************************************************************************\
2 
3   hpmud.cpp - multi-point transport driver
4 
5   (c) 2004-2007 Copyright HP Development Company, LP
6 
7   Permission is hereby granted, free of charge, to any person obtaining a copy
8   of this software and associated documentation files (the "Software"), to deal
9   in the Software without restriction, including without limitation the rights
10   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11   of the Software, and to permit persons to whom the Software is furnished to do
12   so, subject to the following conditions:
13 
14   The above copyright notice and this permission notice shall be included in all
15   copies or substantial portions of the Software.
16 
17   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19   FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20   COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24   Author: Naga Samrat Chowdary Narla,
25   Contributor: Sarbeswar Meher
26 \*****************************************************************************/
27 
28 #include "hpmud.h"
29 #include "hpmudi.h"
30 
31 /* Client data. */
32 mud_session ms __attribute__ ((visibility ("hidden")));      /* mud session, one per client */
33 mud_session *msp __attribute__ ((visibility ("hidden"))) = &ms;
34 
35 /*
36  * sysdump() originally came from http://sws.dett.de/mini/hexdump-c , steffen@dett.de .
37  */
sysdump(const void * data,int size)38 void __attribute__ ((visibility ("hidden"))) sysdump(const void *data, int size)
39 {
40     /* Dump size bytes of *data. Output looks like:
41      * [0000] 75 6E 6B 6E 6F 77 6E 20 30 FF 00 00 00 00 39 00 unknown 0.....9.
42      */
43 
44     unsigned char *p = (unsigned char *)data;
45     unsigned char c;
46     int n;
47     char bytestr[4] = {0};
48     char addrstr[10] = {0};
49     char hexstr[16*3 + 5] = {0};
50     char charstr[16*1 + 5] = {0};
51     for(n=1;n<=size;n++) {
52         if (n%16 == 1) {
53             /* store address for this line */
54             snprintf(addrstr, sizeof(addrstr), "%.4d", (int)((p-(unsigned char *)data) & 0xffff));
55         }
56 
57         c = *p;
58         if (isprint(c) == 0) {
59             c = '.';
60         }
61 
62         /* store hex str (for left side) */
63         snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
64         strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
65 
66         /* store char str (for right side) */
67         snprintf(bytestr, sizeof(bytestr), "%c", c);
68         strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
69 
70         if(n%16 == 0) {
71             /* line completed */
72             DBG_SZ("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
73             hexstr[0] = 0;
74             charstr[0] = 0;
75         }
76         p++; /* next byte */
77     }
78 
79     if (strlen(hexstr) > 0) {
80         /* print rest of buffer if not empty */
81         DBG_SZ("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
82     }
83 }
84 
85 /* Given the IEEE 1284 device id string, determine if this is a HP product. */
is_hp(const char * id)86 int __attribute__ ((visibility ("hidden"))) is_hp(const char *id)
87 {
88    char *pMf;
89    if (id == 0 || id[0] == 0)
90         return 0;
91 
92    if ((pMf = strstr(id, "MFG:")) != NULL)
93       pMf+=4;
94    else if ((pMf = strstr(id, "MANUFACTURER:")) != NULL)
95       pMf+=13;
96    else
97       return 0;
98 
99    if ((strncasecmp(pMf, "HEWLETT-PACKARD", 15) == 0) ||
100       (strncasecmp(pMf, "APOLLO", 6) == 0) || (strncasecmp(pMf, "HP", 2) == 0))
101    {
102       return 1;  /* found HP product */
103    }
104    return 0;
105 }
106 
generalize_model(const char * sz,char * buf,int bufSize)107 int __attribute__ ((visibility ("hidden"))) generalize_model(const char *sz, char *buf, int bufSize)
108 {
109    const char *pMd=sz;
110    int i, j, dd=0;
111 
112    if (sz == 0 || sz[0] == 0)
113         return 0;
114 
115 
116    for (i=0; pMd[i] == ' ' && i < bufSize; i++);  /* eat leading white space */
117 
118    for (j=0; (pMd[i] != 0) && (pMd[i] != ';') && (j < bufSize); i++)
119    {
120       if (pMd[i]==' ' || pMd[i]=='/')
121       {
122          /* Remove double spaces. */
123          if (!dd)
124          {
125             buf[j++] = '_';   /* convert space to "_" */
126             dd=1;
127          }
128       }
129       else
130       {
131          buf[j++] = pMd[i];
132          dd=0;
133       }
134    }
135 
136    for (j--; buf[j] == '_' && j > 0; j--);  /* eat trailing white space */
137 
138    buf[++j] = 0;
139 
140    return j;   /* length does not include zero termination */
141 }
142 
generalize_serial(const char * sz,char * buf,int bufSize)143 int __attribute__ ((visibility ("hidden"))) generalize_serial(const char *sz, char *buf, int bufSize)
144 {
145    const char *pMd=sz;
146    int i, j;
147 
148    if (sz == 0 || sz[0] == 0)
149         return 0;
150 
151    for (i=0; pMd[i] == ' ' && i < bufSize; i++);  /* eat leading white space */
152 
153    for (j=0; (pMd[i] != 0) && (i < bufSize); i++)
154    {
155       buf[j++] = pMd[i];
156    }
157 
158    for (i--; buf[i] == ' ' && i > 0; i--);  /* eat trailing white space */
159 
160    buf[++i] = 0;
161 
162    return i;   /* length does not include zero termination */
163 }
164 
165 /* Parse serial number from uri string. */
get_uri_serial(const char * uri,char * buf,int bufSize)166 int __attribute__ ((visibility ("hidden"))) get_uri_serial(const char *uri, char *buf, int bufSize)
167 {
168    char *p;
169    int i;
170 
171    if (uri == 0 || uri[0] == 0)
172       return 0;
173 
174    buf[0] = 0;
175 
176    if ((p = strcasestr(uri, "serial=")) != NULL)
177       p+=7;
178    else
179       return 0;
180 
181    for (i=0; (p[i] != 0) && (p[i] != '+') && (i < bufSize); i++)
182       buf[i] = p[i];
183 
184    buf[i] = 0;
185 
186    return i;
187 }
188 
service_to_channel(mud_device * pd,const char * sn,HPMUD_CHANNEL * index)189 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) service_to_channel(mud_device *pd, const char *sn, HPMUD_CHANNEL *index)
190 {
191    enum HPMUD_RESULT stat;
192 
193    *index=-1;
194 
195    /* Check for valid service requests. */
196    if (strncasecmp(sn, "print", 5) == 0)
197    {
198       *index = HPMUD_PRINT_CHANNEL;
199    }
200    else if (strncasecmp(sn, "hp-ews-ledm", 11) == 0)
201    {
202       *index = HPMUD_EWS_LEDM_CHANNEL;
203    }
204    else if (strncasecmp(sn, "hp-ews", 6) == 0)
205    {
206       *index = HPMUD_EWS_CHANNEL;
207    }
208    else if (strncasecmp(sn, "hp-soap-scan", 12) == 0)
209    {
210       *index = HPMUD_SOAPSCAN_CHANNEL;
211    }
212    else if (strncasecmp(sn, "hp-soap-fax", 11) == 0)
213    {
214       *index = HPMUD_SOAPFAX_CHANNEL;
215    }
216    else if (strncasecmp(sn, "hp-marvell-scan", 15) == 0)
217    {
218       *index = HPMUD_MARVELL_SCAN_CHANNEL;
219    }
220    else if (strncasecmp(sn, "hp-marvell-fax", 14) == 0)
221    {
222       *index = HPMUD_MARVELL_FAX_CHANNEL;
223    }
224    else if (strncasecmp(sn, "hp-ledm-scan", 12) == 0)
225    {
226       *index = HPMUD_LEDM_SCAN_CHANNEL;
227    }
228    else if (strncasecmp(sn, "hp-marvell-ews", 11) == 0)
229    {
230        *index = HPMUD_MARVELL_EWS_CHANNEL;
231    }
232    else if (strncasecmp(sn, "hp-ipp", 6) == 0)
233    {
234        if (strncasecmp(sn, "hp-ipp2", 7) == 0)
235             *index = HPMUD_IPP_CHANNEL2;
236        else
237             *index = HPMUD_IPP_CHANNEL;
238    }
239    else if (strncasecmp(sn, "hp-escl-scan", 12) == 0)
240    {
241       *index = HPMUD_ESCL_SCAN_CHANNEL;
242    }
243    /* All the following services require MLC/1284.4. */
244    else if (pd->io_mode == HPMUD_RAW_MODE || pd->io_mode == HPMUD_UNI_MODE)
245    {
246       BUG("invalid channel_open state, current io_mode=raw/uni service=%s %s\n", sn, pd->uri);
247       stat = HPMUD_R_INVALID_STATE;
248       goto bugout;
249    }
250    else if (strncasecmp(sn, "hp-message", 10) == 0)
251    {
252       *index = HPMUD_PML_CHANNEL;
253    }
254    else if (strncasecmp(sn, "hp-scan", 7) == 0)
255    {
256       *index = HPMUD_SCAN_CHANNEL;
257    }
258    else if (strncasecmp(sn, "hp-fax-send", 11) == 0)
259    {
260       *index = HPMUD_FAX_SEND_CHANNEL;
261    }
262    else if (strncasecmp(sn, "hp-card-access", 14) == 0)
263    {
264       *index = HPMUD_MEMORY_CARD_CHANNEL;
265    }
266    else if (strncasecmp(sn, "hp-configuration-upload", 23) == 0)
267    {
268       *index = HPMUD_CONFIG_UPLOAD_CHANNEL;
269    }
270    else if (strncasecmp(sn, "hp-configuration-download", 25) == 0)
271    {
272       *index = HPMUD_CONFIG_DOWNLOAD_CHANNEL;
273    }
274    else if (strncasecmp(sn, "hp-devmgmt", 10) == 0)
275    {
276       *index = HPMUD_DEVMGMT_CHANNEL;
277    }
278    else if (strncasecmp(sn, "hp-wificonfig", 13) == 0)
279    {
280       *index = HPMUD_WIFI_CHANNEL;
281    }
282    else
283    {
284       BUG("invalid service=%s %s\n", sn, pd->uri);
285       stat = HPMUD_R_INVALID_SN;
286       goto bugout;
287    }
288 
289    stat = HPMUD_R_OK;
290 
291 bugout:
292    return stat;
293 }
294 
295 
new_device(const char * uri,enum HPMUD_IO_MODE mode,int * result)296 static int new_device(const char *uri, enum HPMUD_IO_MODE mode, int *result)
297 {
298    int index=0;      /* device[0] is unused */
299    int i=1;
300 
301    if (uri == 0 || uri[0] == 0)
302       return 0;
303 
304    pthread_mutex_lock(&msp->mutex);
305 
306    if (msp->device[i].index)
307    {
308       BUG("invalid device_open state\n");        /* device is already open for this client, one device per session */
309       *result = HPMUD_R_INVALID_STATE;
310       goto bugout;
311    }
312 
313    index = i;      /* currently only support one device per client or process */
314 
315    /* Based on uri, set local session attributes. */
316    if (strcasestr(uri, ":/usb") != NULL)
317    {
318       msp->device[i].vf = musb_mud_device_vf;
319    }
320 #ifdef HAVE_LIBNETSNMP
321    else if (strcasestr(uri, ":/net") != NULL)
322    {
323       msp->device[i].vf = jd_mud_device_vf;
324    }
325 #endif
326 #ifdef HAVE_PPORT
327    else if (strcasestr(uri, ":/par") != NULL)
328    {
329       msp->device[i].vf = pp_mud_device_vf;
330    }
331 #endif
332    else
333    {
334       BUG("invalid uri %s\n", uri);
335       *result = HPMUD_R_INVALID_URI;
336       index = 0;
337       goto bugout;
338    }
339    *result = HPMUD_R_OK;
340    msp->device[i].io_mode = mode;
341    msp->device[i].index = index;
342    msp->device[i].channel_cnt = 0;
343    msp->device[i].open_fd = -1;
344    strcpy(msp->device[i].uri, uri);
345 
346 bugout:
347    pthread_mutex_unlock(&msp->mutex);
348 
349    return index;  /* return device index */
350 }
351 
del_device(HPMUD_DEVICE index)352 static int del_device(HPMUD_DEVICE index)
353 {
354    pthread_mutex_lock(&msp->mutex);
355 
356    msp->device[index].index = 0;
357 
358    pthread_mutex_unlock(&msp->mutex);
359 
360    return 0;
361 }
362 
363 /*  Make sure client closed down the device. */
device_cleanup(mud_session * ps)364 int device_cleanup(mud_session *ps)
365 {
366    int i, dd=1;
367 
368    if (!ps) return 0;
369 
370    if(!ps->device[dd].index)
371       return 0;          /* nothing to do */
372 
373    BUG("device_cleanup: device uri=%s\n", ps->device[dd].uri);
374 
375    for (i=0; i<HPMUD_CHANNEL_MAX; i++)
376    {
377       if (ps->device[dd].channel[i].client_cnt)
378       {
379          BUG("device_cleanup: close channel %d...\n", i);
380          hpmud_close_channel(dd, ps->device[dd].channel[i].index);
381          BUG("device_cleanup: done closing channel %d\n", i);
382       }
383    }
384 
385    BUG("device_cleanup: close device dd=%d...\n", dd);
386    hpmud_close_device(dd);
387    BUG("device_cleanup: done closing device dd=%d\n", dd);
388 
389    return 0;
390 }
391 
mud_init(void)392 static void __attribute__ ((constructor)) mud_init(void)
393 {
394    DBG("[%d] hpmud_init()\n", getpid());
395 }
396 
mud_exit(void)397 static void __attribute__ ((destructor)) mud_exit(void)
398 {
399    DBG("[%d] hpmud_exit()\n", getpid());
400    device_cleanup(msp);
401 }
402 
403 /*******************************************************************************************************************************
404  * Helper functions.
405  */
406 
407 /* Parse the model from the IEEE 1284 device id string and generalize the model name */
hpmud_get_model(const char * id,char * buf,int buf_size)408 int hpmud_get_model(const char *id, char *buf, int buf_size)
409 {
410    char *pMd;
411 
412    if (id == 0 || id[0] == 0)
413         return 0;
414 
415    buf[0] = 0;
416 
417    if ((pMd = strstr(id, "MDL:")) != NULL)
418       pMd+=4;
419    else if ((pMd = strstr(id, "MODEL:")) != NULL)
420       pMd+=6;
421    else
422       return 0;
423 
424    return generalize_model(pMd, buf, buf_size);
425 }
426 
427 /* Parse the model from the IEEE 1284 device id string. */
hpmud_get_raw_model(char * id,char * raw,int rawSize)428 int hpmud_get_raw_model(char *id, char *raw, int rawSize)
429 {
430    char *pMd;
431    int i;
432 
433    if (id == 0 || id[0] == 0)
434         return 0;
435 
436    raw[0] = 0;
437 
438    if ((pMd = strstr(id, "MDL:")) != NULL)
439       pMd+=4;
440    else if ((pMd = strstr(id, "MODEL:")) != NULL)
441       pMd+=6;
442    else
443       return 0;
444 
445    for (i=0; (pMd[i] != ';') && (i < rawSize); i++)
446       raw[i] = pMd[i];
447    raw[i] = 0;
448 
449    return i;
450 }
451 
452 /* Parse device model from uri string. */
hpmud_get_uri_model(const char * uri,char * buf,int buf_size)453 int hpmud_get_uri_model(const char *uri, char *buf, int buf_size)
454 {
455    char *p;
456    int i;
457 
458    if (uri == 0 || uri[0] == 0)
459      return 0;
460 
461    buf[0] = 0;
462 
463    if ((p = strstr(uri, "/")) == NULL)
464       return 0;
465    if ((p = strstr(p+1, "/")) == NULL)
466       return 0;
467    p++;
468 
469    for (i=0; (p[i] != '?') && (i < buf_size); i++)
470       buf[i] = p[i];
471 
472    buf[i] = 0;
473 
474    return i;
475 }
476 
477 /* Parse the data link from a uri string. */
hpmud_get_uri_datalink(const char * uri,char * buf,int buf_size)478 int hpmud_get_uri_datalink(const char *uri, char *buf, int buf_size)
479 {
480    char *p;
481    int i;
482    int zc=0;
483 #ifdef HAVE_LIBNETSNMP
484    char ip[HPMUD_LINE_SIZE];
485 #endif
486 
487    if (uri == 0 || uri[0] == 0)
488      return 0;
489 
490    buf[0] = 0;
491 
492    if ((p = strcasestr(uri, "device=")) != NULL)
493       p+=7;
494    else if ((p = strcasestr(uri, "ip=")) != NULL)
495       p+=3;
496    else if ((p = strcasestr(uri, "hostname=")) != NULL)
497       p+=9;
498    else if ((p = strcasestr(uri, "zc=")) != NULL)
499    {
500       p+=3;
501       zc=1;
502    }
503    else
504       return 0;
505 
506    if (zc)
507    {
508 #ifdef HAVE_LIBNETSNMP
509     if (mdns_lookup(p, ip) != MDNS_STATUS_OK)
510         return 0;
511     for (i=0; (ip[i] != 0) && (i < buf_size); i++)
512         buf[i] = ip[i];
513 #else
514       return 0;
515 #endif
516    }
517    else {
518       for (i=0; (p[i] != 0) && (p[i] != '&') && (i < buf_size); i++)
519          buf[i] = p[i];
520    }
521 
522    buf[i] = 0;
523 
524    return i;
525 }
526 
527 /***************************************************************************************************
528  * Core functions.
529  */
530 
hpmud_open_device(const char * uri,enum HPMUD_IO_MODE iomode,HPMUD_DEVICE * dd)531 enum HPMUD_RESULT hpmud_open_device(const char *uri, enum HPMUD_IO_MODE iomode, HPMUD_DEVICE *dd)
532 {
533    HPMUD_DEVICE index=0;
534    enum HPMUD_RESULT stat = HPMUD_R_INVALID_URI;
535    int result;
536 
537    DBG("[%d,%d,%d,%d,%d,%d] hpmud_device_open() uri=%s iomode=%d\n", getpid(), getppid(), getuid(), geteuid(), getgid(), getegid(), uri, iomode);
538 
539    if ((index = new_device(uri, iomode, &result)) == 0)
540    {
541       stat = result;
542       goto bugout;
543    }
544    else
545    {
546       if ((stat = (msp->device[index].vf.open)(&msp->device[index])) != HPMUD_R_OK)
547       {
548          (msp->device[index].vf.close)(&msp->device[index]);  /* Open failed perform device cleanup. */
549          del_device(index);
550          goto bugout;
551       }
552    }
553 
554    *dd = index;
555    stat = HPMUD_R_OK;
556 
557 bugout:
558    return stat;
559 }
560 
hpmud_close_device(HPMUD_DEVICE dd)561 enum HPMUD_RESULT hpmud_close_device(HPMUD_DEVICE dd)
562 {
563    enum HPMUD_RESULT stat;
564 
565    DBG("[%d] hpmud_device_close() dd=%d\n", getpid(), dd);
566 
567    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
568    {
569       BUG("invalid device_close state\n");
570       stat = HPMUD_R_INVALID_STATE;
571    }
572    else
573    {
574       stat = (msp->device[dd].vf.close)(&msp->device[dd]);
575       del_device(dd);
576    }
577    return stat;
578 }
579 
hpmud_get_device_id(HPMUD_DEVICE dd,char * buf,int size,int * bytes_read)580 enum HPMUD_RESULT hpmud_get_device_id(HPMUD_DEVICE dd, char *buf, int size, int *bytes_read)
581 {
582    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
583 
584    DBG("[%d] hpmud_get_device_id() dd=%d\n", getpid(), dd);
585 
586    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
587    {
588       BUG("invalid get_device_id state\n");
589       goto bugout;
590    }
591 
592    stat = (msp->device[dd].vf.get_device_id)(&msp->device[dd], buf, size, bytes_read);
593 
594 bugout:
595    return stat;
596 }
597 
hpmud_get_device_status(HPMUD_DEVICE dd,unsigned int * status)598 enum HPMUD_RESULT hpmud_get_device_status(HPMUD_DEVICE dd, unsigned int *status)
599 {
600    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
601 
602    DBG("[%d] hpmud_get_device_status() dd=%d\n", getpid(), dd);
603 
604    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
605    {
606       BUG("invalid get_device_status state\n");
607       goto bugout;
608    }
609 
610    stat = (msp->device[dd].vf.get_device_status)(&msp->device[dd], status);
611 
612 bugout:
613    return stat;
614 }
615 
hpmud_probe_devices(enum HPMUD_BUS_ID bus,char * buf,int buf_size,int * cnt,int * bytes_read)616 enum HPMUD_RESULT hpmud_probe_devices(enum HPMUD_BUS_ID bus, char *buf, int buf_size, int *cnt, int *bytes_read)
617 {
618    int len=0;
619 
620    DBG("[%d] hpmud_probe_devices() bus=%d\n", getpid(), bus);
621    if (buf == NULL || buf_size <= 0)
622         return HPMUD_R_INVALID_LENGTH;
623 
624    buf[0] = 0;
625    *cnt = 0;
626 
627    if (bus == HPMUD_BUS_USB)
628    {
629       len = musb_probe_devices(buf, buf_size, cnt, HPMUD_AIO);
630    }
631 #ifdef HAVE_PPORT
632    else if (bus == HPMUD_BUS_PARALLEL)
633    {
634       len = pp_probe_devices(buf, buf_size, cnt);
635    }
636 #endif
637    else if (bus == HPMUD_BUS_ALL)
638    {
639       len = musb_probe_devices(buf, buf_size, cnt, HPMUD_AIO);
640 #ifdef HAVE_PPORT
641       len += pp_probe_devices(buf+len, buf_size-len, cnt);
642 #endif
643    }
644 
645    *bytes_read = len;
646 
647    return HPMUD_R_OK;
648 }
649 
hpmud_probe_printers(enum HPMUD_BUS_ID bus,char * buf,int buf_size,int * cnt,int * bytes_read)650 enum HPMUD_RESULT hpmud_probe_printers(enum HPMUD_BUS_ID bus, char *buf, int buf_size, int *cnt, int *bytes_read)
651 {
652    int len=0;
653 
654    DBG("[%d] hpmud_probe_printers() bus=%d\n", getpid(), bus);
655 
656    if (buf == NULL || buf_size <= 0)
657         return HPMUD_R_INVALID_LENGTH;
658 
659    buf[0] = 0;
660    *cnt = 0;
661 
662    if (bus == HPMUD_BUS_ALL)
663    {
664       len = musb_probe_devices(buf, buf_size, cnt, HPMUD_PRINTER);
665 #ifdef HAVE_PPORT
666       len += pp_probe_devices(buf+len, buf_size-len, cnt);
667 #endif
668    }
669 
670    *bytes_read = len;
671 
672    return HPMUD_R_OK;
673 }
674 
hpmud_open_channel(HPMUD_DEVICE dd,const char * channel_name,HPMUD_CHANNEL * cd)675 enum HPMUD_RESULT hpmud_open_channel(HPMUD_DEVICE dd, const char *channel_name, HPMUD_CHANNEL *cd)
676 {
677    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
678 
679    DBG("[%d] hpmud_channel_open() dd=%d name=%s\n", getpid(), dd, channel_name);
680 
681    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
682    {
683       BUG("invalid channel_open state\n");
684       goto bugout;
685    }
686 
687    stat = (msp->device[dd].vf.channel_open)(&msp->device[dd], channel_name, cd);
688 
689 bugout:
690    return stat;
691 }
692 
hpmud_close_channel(HPMUD_DEVICE dd,HPMUD_CHANNEL cd)693 enum HPMUD_RESULT hpmud_close_channel(HPMUD_DEVICE dd, HPMUD_CHANNEL cd)
694 {
695    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
696 
697    DBG("[%d] hpmud_channel_close() dd=%d cd=%d\n", getpid(), dd, cd);
698 
699    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd ||
700         cd <=0 || cd > HPMUD_CHANNEL_MAX || msp->device[dd].channel[cd].client_cnt == 0)
701    {
702       BUG("invalid channel_close state\n");
703       goto bugout;
704    }
705 
706    stat = (msp->device[dd].vf.channel_close)(&msp->device[dd], &msp->device[dd].channel[cd]);
707 
708 bugout:
709    return stat;
710 }
711 
hpmud_write_channel(HPMUD_DEVICE dd,HPMUD_CHANNEL cd,const void * buf,int size,int sec_timeout,int * bytes_wrote)712 enum HPMUD_RESULT hpmud_write_channel(HPMUD_DEVICE dd, HPMUD_CHANNEL cd, const void *buf, int size, int sec_timeout, int *bytes_wrote)
713 {
714    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
715 
716    DBG("[%d] hpmud_channel_write() dd=%d cd=%d buf=%p size=%d sectime=%d\n", getpid(), dd, cd, buf, size, sec_timeout);
717 
718    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd ||
719         cd <=0 || cd > HPMUD_CHANNEL_MAX || msp->device[dd].channel[cd].client_cnt == 0)
720    {
721       BUG("invalid channel_write state\n");
722       goto bugout;
723    }
724 
725    stat = (msp->device[dd].vf.channel_write)(&msp->device[dd], &msp->device[dd].channel[cd], buf, size, sec_timeout, bytes_wrote);
726 
727 bugout:
728    return stat;
729 }
730 
hpmud_read_channel(HPMUD_DEVICE dd,HPMUD_CHANNEL cd,void * buf,int size,int sec_timeout,int * bytes_read)731 enum HPMUD_RESULT hpmud_read_channel(HPMUD_DEVICE dd, HPMUD_CHANNEL cd, void *buf, int size, int sec_timeout, int *bytes_read)
732 {
733    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
734    DBG("[%d] hpmud_channel_read() dd=%d cd=%d buf=%p size=%d sectime=%d\n", getpid(), dd, cd, buf, size, sec_timeout);
735 
736    if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd ||
737         cd <=0 || cd > HPMUD_CHANNEL_MAX || msp->device[dd].channel[cd].client_cnt == 0)
738    {
739       BUG("invalid channel_read state\n");
740       goto bugout;
741    }
742 
743    stat = (msp->device[dd].vf.channel_read)(&msp->device[dd], &msp->device[dd].channel[cd], buf, size, sec_timeout, bytes_read);
744 
745 bugout:
746    return stat;
747 }
748 
hpmud_get_dstat(HPMUD_DEVICE dd,struct hpmud_dstat * ds)749 enum HPMUD_RESULT hpmud_get_dstat(HPMUD_DEVICE dd, struct hpmud_dstat *ds)
750 {
751    enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
752 
753    DBG("[%d] hpmud_dstat() dd=%d ds=%p\n", getpid(), dd, ds);
754 
755    if (dd <= 0 || dd > HPMUD_DEVICE_MAX)
756    {
757       BUG("invalid dstat state\n");
758       goto bugout;
759    }
760 
761    strncpy(ds->uri, msp->device[dd].uri, sizeof(ds->uri));
762    ds->io_mode = msp->device[dd].io_mode;
763    ds->channel_cnt = msp->device[dd].channel_cnt;
764    ds->mlc_up = msp->device[dd].mlc_up;
765 
766    stat = HPMUD_R_OK;
767 
768 bugout:
769    return stat;
770 }
771