1 /*****************************************************************************\
3 hpmud.cpp - multi-point transport driver
5 (c) 2004-2007 Copyright Hewlett-Packard Development Company, LP
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:
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
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.
24 Author: Naga Samrat Chowdary Narla,
25 Contributor: Sarbeswar Meher
26 \*****************************************************************************/
32 mud_session ms __attribute__ ((visibility ("hidden"))); /* mud session, one per client */
33 mud_session *msp __attribute__ ((visibility ("hidden"))) = &ms;
36 * sysdump() originally came from http://sws.dett.de/mini/hexdump-c , steffen@dett.de .
38 void __attribute__ ((visibility ("hidden"))) sysdump(const void *data, int size)
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.
44 unsigned char *p = (unsigned char *)data;
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++) {
53 /* store address for this line */
54 snprintf(addrstr, sizeof(addrstr), "%.4d", (int)((p-(unsigned char *)data) & 0xffff));
58 if (isprint(c) == 0) {
62 /* store hex str (for left side) */
63 snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
64 strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
66 /* store char str (for right side) */
67 snprintf(bytestr, sizeof(bytestr), "%c", c);
68 strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
72 DBG_SZ("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
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);
85 /* Given the IEEE 1284 device id string, determine if this is a HP product. */
86 int __attribute__ ((visibility ("hidden"))) is_hp(const char *id)
90 if ((pMf = strstr(id, "MFG:")) != NULL)
92 else if ((pMf = strstr(id, "MANUFACTURER:")) != NULL)
97 if ((strncasecmp(pMf, "HEWLETT-PACKARD", 15) == 0) ||
98 (strncasecmp(pMf, "APOLLO", 6) == 0) || (strncasecmp(pMf, "HP", 2) == 0))
100 return 1; /* found HP product */
105 int __attribute__ ((visibility ("hidden"))) generalize_model(const char *sz, char *buf, int bufSize)
110 for (i=0; pMd[i] == ' ' && i < bufSize; i++); /* eat leading white space */
112 for (j=0; (pMd[i] != 0) && (pMd[i] != ';') && (j < bufSize); i++)
114 if (pMd[i]==' ' || pMd[i]=='/')
116 /* Remove double spaces. */
119 buf[j++] = '_'; /* convert space to "_" */
130 for (j--; buf[j] == '_' && j > 0; j--); /* eat trailing white space */
134 return j; /* length does not include zero termination */
137 int __attribute__ ((visibility ("hidden"))) generalize_serial(const char *sz, char *buf, int bufSize)
142 for (i=0; pMd[i] == ' ' && i < bufSize; i++); /* eat leading white space */
144 for (j=0; (pMd[i] != 0) && (i < bufSize); i++)
149 for (i--; buf[i] == ' ' && i > 0; i--); /* eat trailing white space */
153 return i; /* length does not include zero termination */
156 /* Parse serial number from uri string. */
157 int __attribute__ ((visibility ("hidden"))) get_uri_serial(const char *uri, char *buf, int bufSize)
164 if ((p = strcasestr(uri, "serial=")) != NULL)
169 for (i=0; (p[i] != 0) && (p[i] != '+') && (i < bufSize); i++)
177 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) service_to_channel(mud_device *pd, const char *sn, HPMUD_CHANNEL *index)
179 enum HPMUD_RESULT stat;
183 /* Check for valid service requests. */
184 if (strncasecmp(sn, "print", 5) == 0)
186 *index = HPMUD_PRINT_CHANNEL;
188 else if (strncasecmp(sn, "hp-ews-ledm", 11) == 0)
190 *index = HPMUD_EWS_LEDM_CHANNEL;
192 else if (strncasecmp(sn, "hp-ews", 6) == 0)
194 *index = HPMUD_EWS_CHANNEL;
196 else if (strncasecmp(sn, "hp-soap-scan", 12) == 0)
198 *index = HPMUD_SOAPSCAN_CHANNEL;
200 else if (strncasecmp(sn, "hp-soap-fax", 11) == 0)
202 *index = HPMUD_SOAPFAX_CHANNEL;
204 else if (strncasecmp(sn, "hp-marvell-scan", 15) == 0)
206 *index = HPMUD_MARVELL_SCAN_CHANNEL;
208 else if (strncasecmp(sn, "hp-marvell-fax", 14) == 0)
210 *index = HPMUD_MARVELL_FAX_CHANNEL;
212 else if (strncasecmp(sn, "hp-ledm-scan", 12) == 0)
214 *index = HPMUD_LEDM_SCAN_CHANNEL;
216 /* All the following services require MLC/1284.4. */
217 else if (pd->io_mode == HPMUD_RAW_MODE || pd->io_mode == HPMUD_UNI_MODE)
219 BUG("invalid channel_open state, current io_mode=raw/uni service=%s %s\n", sn, pd->uri);
220 stat = HPMUD_R_INVALID_STATE;
223 else if (strncasecmp(sn, "hp-message", 10) == 0)
225 *index = HPMUD_PML_CHANNEL;
227 else if (strncasecmp(sn, "hp-scan", 7) == 0)
229 *index = HPMUD_SCAN_CHANNEL;
231 else if (strncasecmp(sn, "hp-fax-send", 11) == 0)
233 *index = HPMUD_FAX_SEND_CHANNEL;
235 else if (strncasecmp(sn, "hp-card-access", 14) == 0)
237 *index = HPMUD_MEMORY_CARD_CHANNEL;
239 else if (strncasecmp(sn, "hp-configuration-upload", 23) == 0)
241 *index = HPMUD_CONFIG_UPLOAD_CHANNEL;
243 else if (strncasecmp(sn, "hp-configuration-download", 25) == 0)
245 *index = HPMUD_CONFIG_DOWNLOAD_CHANNEL;
247 else if (strncasecmp(sn, "hp-devmgmt", 10) == 0)
249 *index = HPMUD_DEVMGMT_CHANNEL;
251 else if (strncasecmp(sn, "hp-wificonfig", 13) == 0)
253 *index = HPMUD_WIFI_CHANNEL;
257 BUG("invalid service=%s %s\n", sn, pd->uri);
258 stat = HPMUD_R_INVALID_SN;
268 static int new_device(const char *uri, enum HPMUD_IO_MODE mode, int *result)
270 int index=0; /* device[0] is unused */
276 pthread_mutex_lock(&msp->mutex);
278 if (msp->device[i].index)
280 BUG("invalid device_open state\n"); /* device is already open for this client, one device per session */
281 *result = HPMUD_R_INVALID_STATE;
285 index = i; /* currently only support one device per client or process */
287 /* Based on uri, set local session attributes. */
288 if (strcasestr(uri, ":/usb") != NULL)
290 msp->device[i].vf = musb_mud_device_vf;
292 #ifdef HAVE_LIBNETSNMP
293 else if (strcasestr(uri, ":/net") != NULL)
295 msp->device[i].vf = jd_mud_device_vf;
299 else if (strcasestr(uri, ":/par") != NULL)
301 msp->device[i].vf = pp_mud_device_vf;
306 BUG("invalid uri %s\n", uri);
307 *result = HPMUD_R_INVALID_URI;
311 msp->device[i].io_mode = mode;
312 msp->device[i].index = index;
313 msp->device[i].channel_cnt = 0;
314 msp->device[i].open_fd = -1;
315 strcpy(msp->device[i].uri, uri);
318 pthread_mutex_unlock(&msp->mutex);
320 return index; /* return device index */
323 static int del_device(HPMUD_DEVICE index)
325 pthread_mutex_lock(&msp->mutex);
327 msp->device[index].index = 0;
329 pthread_mutex_unlock(&msp->mutex);
334 /* Make sure client closed down the device. */
335 int device_cleanup(mud_session *ps)
339 if(!ps->device[dd].index)
340 return 0; /* nothing to do */
342 BUG("device_cleanup: device uri=%s\n", ps->device[dd].uri);
344 for (i=0; i<HPMUD_CHANNEL_MAX; i++)
346 if (ps->device[dd].channel[i].client_cnt)
348 BUG("device_cleanup: close channel %d...\n", i);
349 hpmud_close_channel(dd, ps->device[dd].channel[i].index);
350 BUG("device_cleanup: done closing channel %d\n", i);
354 BUG("device_cleanup: close device dd=%d...\n", dd);
355 hpmud_close_device(dd);
356 BUG("device_cleanup: done closing device dd=%d\n", dd);
361 static void __attribute__ ((constructor)) mud_init(void)
363 DBG("[%d] hpmud_init()\n", getpid());
366 static void __attribute__ ((destructor)) mud_exit(void)
368 DBG("[%d] hpmud_exit()\n", getpid());
372 /*******************************************************************************************************************************
376 /* Parse the model from the IEEE 1284 device id string and generalize the model name */
377 int hpmud_get_model(const char *id, char *buf, int buf_size)
383 if ((pMd = strstr(id, "MDL:")) != NULL)
385 else if ((pMd = strstr(id, "MODEL:")) != NULL)
390 return generalize_model(pMd, buf, buf_size);
393 /* Parse the model from the IEEE 1284 device id string. */
394 int hpmud_get_raw_model(char *id, char *raw, int rawSize)
401 if ((pMd = strstr(id, "MDL:")) != NULL)
403 else if ((pMd = strstr(id, "MODEL:")) != NULL)
408 for (i=0; (pMd[i] != ';') && (i < rawSize); i++)
415 /* Parse device model from uri string. */
416 int hpmud_get_uri_model(const char *uri, char *buf, int buf_size)
423 if ((p = strstr(uri, "/")) == NULL)
425 if ((p = strstr(p+1, "/")) == NULL)
429 for (i=0; (p[i] != '?') && (i < buf_size); i++)
437 /* Parse the data link from a uri string. */
438 int hpmud_get_uri_datalink(const char *uri, char *buf, int buf_size)
443 #ifdef HAVE_LIBNETSNMP
444 char ip[HPMUD_LINE_SIZE];
449 if ((p = strcasestr(uri, "device=")) != NULL)
451 else if ((p = strcasestr(uri, "ip=")) != NULL)
453 else if ((p = strcasestr(uri, "zc=")) != NULL)
463 #ifdef HAVE_LIBNETSNMP
464 if (hpmud_mdns_lookup(p, HPMUD_MDNS_TIMEOUT, ip) != HPMUD_R_OK)
466 for (i=0; (ip[i] != 0) && (i < buf_size); i++)
473 for (i=0; (p[i] != 0) && (p[i] != '&') && (i < buf_size); i++)
482 /***************************************************************************************************
486 enum HPMUD_RESULT hpmud_open_device(const char *uri, enum HPMUD_IO_MODE iomode, HPMUD_DEVICE *dd)
488 HPMUD_DEVICE index=0;
489 enum HPMUD_RESULT stat = HPMUD_R_INVALID_URI;
492 DBG("[%d,%d,%d,%d,%d,%d] hpmud_device_open() uri=%s iomode=%d\n", getpid(), getppid(), getuid(), geteuid(), getgid(), getegid(), uri, iomode);
494 if ((index = new_device(uri, iomode, &result)) == 0)
501 if ((stat = (msp->device[index].vf.open)(&msp->device[index])) != HPMUD_R_OK)
503 (msp->device[index].vf.close)(&msp->device[index]); /* Open failed perform device cleanup. */
516 enum HPMUD_RESULT hpmud_close_device(HPMUD_DEVICE dd)
518 enum HPMUD_RESULT stat;
520 DBG("[%d] hpmud_device_close() dd=%d\n", getpid(), dd);
522 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
524 BUG("invalid device_close state\n");
525 stat = HPMUD_R_INVALID_STATE;
529 stat = (msp->device[dd].vf.close)(&msp->device[dd]);
535 enum HPMUD_RESULT hpmud_get_device_id(HPMUD_DEVICE dd, char *buf, int size, int *bytes_read)
537 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
539 DBG("[%d] hpmud_get_device_id() dd=%d\n", getpid(), dd);
541 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
543 BUG("invalid get_device_id state\n");
547 stat = (msp->device[dd].vf.get_device_id)(&msp->device[dd], buf, size, bytes_read);
553 enum HPMUD_RESULT hpmud_get_device_status(HPMUD_DEVICE dd, unsigned int *status)
555 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
557 DBG("[%d] hpmud_get_device_status() dd=%d\n", getpid(), dd);
559 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
561 BUG("invalid get_device_status state\n");
565 stat = (msp->device[dd].vf.get_device_status)(&msp->device[dd], status);
571 enum HPMUD_RESULT hpmud_probe_devices(enum HPMUD_BUS_ID bus, char *buf, int buf_size, int *cnt, int *bytes_read)
575 DBG("[%d] hpmud_probe_devices() bus=%d\n", getpid(), bus);
580 if (bus == HPMUD_BUS_USB)
582 len = musb_probe_devices(buf, buf_size, cnt);
585 else if (bus == HPMUD_BUS_PARALLEL)
587 len = pp_probe_devices(buf, buf_size, cnt);
590 else if (bus == HPMUD_BUS_ALL)
592 len = musb_probe_devices(buf, buf_size, cnt);
594 len += pp_probe_devices(buf+len, buf_size-len, cnt);
603 enum HPMUD_RESULT hpmud_open_channel(HPMUD_DEVICE dd, const char *channel_name, HPMUD_CHANNEL *cd)
605 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
607 DBG("[%d] hpmud_channel_open() dd=%d name=%s\n", getpid(), dd, channel_name);
609 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd)
611 BUG("invalid channel_open state\n");
615 stat = (msp->device[dd].vf.channel_open)(&msp->device[dd], channel_name, cd);
621 enum HPMUD_RESULT hpmud_close_channel(HPMUD_DEVICE dd, HPMUD_CHANNEL cd)
623 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
625 DBG("[%d] hpmud_channel_close() dd=%d cd=%d\n", getpid(), dd, cd);
627 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd ||
628 cd <=0 || cd > HPMUD_CHANNEL_MAX || msp->device[dd].channel[cd].client_cnt == 0)
630 BUG("invalid channel_close state\n");
634 stat = (msp->device[dd].vf.channel_close)(&msp->device[dd], &msp->device[dd].channel[cd]);
640 enum HPMUD_RESULT hpmud_write_channel(HPMUD_DEVICE dd, HPMUD_CHANNEL cd, const void *buf, int size, int sec_timeout, int *bytes_wrote)
642 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
644 DBG("[%d] hpmud_channel_write() dd=%d cd=%d buf=%p size=%d sectime=%d\n", getpid(), dd, cd, buf, size, sec_timeout);
646 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd ||
647 cd <=0 || cd > HPMUD_CHANNEL_MAX || msp->device[dd].channel[cd].client_cnt == 0)
649 BUG("invalid channel_write state\n");
653 stat = (msp->device[dd].vf.channel_write)(&msp->device[dd], &msp->device[dd].channel[cd], buf, size, sec_timeout, bytes_wrote);
659 enum HPMUD_RESULT hpmud_read_channel(HPMUD_DEVICE dd, HPMUD_CHANNEL cd, void *buf, int size, int sec_timeout, int *bytes_read)
661 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
662 DBG("[%d] hpmud_channel_read() dd=%d cd=%d buf=%p size=%d sectime=%d\n", getpid(), dd, cd, buf, size, sec_timeout);
664 if (dd <= 0 || dd > HPMUD_DEVICE_MAX || msp->device[dd].index != dd ||
665 cd <=0 || cd > HPMUD_CHANNEL_MAX || msp->device[dd].channel[cd].client_cnt == 0)
667 BUG("invalid channel_read state\n");
671 stat = (msp->device[dd].vf.channel_read)(&msp->device[dd], &msp->device[dd].channel[cd], buf, size, sec_timeout, bytes_read);
677 enum HPMUD_RESULT hpmud_get_dstat(HPMUD_DEVICE dd, struct hpmud_dstat *ds)
679 enum HPMUD_RESULT stat = HPMUD_R_INVALID_STATE;
681 DBG("[%d] hpmud_dstat() dd=%d ds=%p\n", getpid(), dd, ds);
683 if (dd <= 0 || dd > HPMUD_DEVICE_MAX)
685 BUG("invalid dstat state\n");
689 strncpy(ds->uri, msp->device[dd].uri, sizeof(ds->uri));
690 ds->io_mode = msp->device[dd].io_mode;
691 ds->channel_cnt = msp->device[dd].channel_cnt;
692 ds->mlc_up = msp->device[dd].mlc_up;