]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/ieee1394-linux.c
2 * "$Id: ieee1394-linux.c 4703 2005-09-26 19:33:58Z mike $"
4 * Linux IEEE-1394 glue for the Common UNIX Printing System (CUPS).
6 * Copyright 2002 by Easy Software Products, all rights reserved.
8 * Redistribution and use in source and binary forms, with or
9 * without modification, are permitted provided that the
10 * following conditions are met:
12 * 1. Redistributions of source code must retain the above
13 * copyright notice, this list of conditions and the
14 * following disclaimer.
16 * 2. Redistributions in binary form must reproduce the
17 * above copyright notice, this list of conditions and
18 * the following disclaimer in the documentation and/or
19 * other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use
22 * of this software must display the following
25 * This product includes software developed by Easy
28 * 4. The name of Easy Software Products may not be used to
29 * endorse or promote products derived from this software
30 * without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
33 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
34 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
37 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
38 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
49 * get_device_id() - Get the IEEE-1284 device ID for a node...
50 * get_unit_type() - Get the unit type for a node...
51 * show_data() - Show a data node...
52 * show_dir() - Show a directory list...
53 * ieee1394_list() - List the available printer devices.
54 * ieee1394_open() - Open a printer device.
55 * ieee1394_close() - Close a printer device.
56 * ieee1394_read() - Read from a printer device.
57 * ieee1394_write() - Write data to a printer device.
58 * ieee1394_error() - Return the last error.
62 * Include necessary headers.
66 #include <cups/debug.h>
67 #include <libraw1394/raw1394.h>
68 #include <libraw1394/csr.h>
84 char uri
[HTTP_MAX_URI
],/* URI for this node... */
85 description
[128],/* Description of port */
86 make_model
[128];/* Make and model */
87 int port
, /* Port where this node is found */
88 node
; /* Node number */
89 unsigned long long addr
; /* Management address */
94 raw1394handle_t handle
; /* Handle for printer device */
95 int node
; /* Node number for printer device */
96 unsigned long long addr
; /* Management address */
101 * ORB messages for communication with the device...
104 typedef struct /**** Login ORB Message */
106 unsigned char passwd_addr
[8]; /* Password address */
107 unsigned char resp_addr
[8]; /* Login response address */
108 unsigned char notify_excl
; /* Notify and exclusive bits */
109 unsigned char recon_func
; /* Reconnect time and function */
110 unsigned char lun
[2]; /* Logical unit number */
111 unsigned char passwd_len
[2]; /* Length of password */
112 unsigned char resp_len
[2]; /* Length of login response */
113 unsigned char fifo_addr
[8]; /* Local status FIFO address */
116 typedef struct /**** Login Response Message ****/
118 unsigned char length
[2]; /* Length of response */
119 unsigned char login_id
[2]; /* Login ID */
120 unsigned char cmd_addr
[8]; /* Command block agent address */
121 unsigned char reserved
[2]; /* Reserved (0) */
122 unsigned char recon_hold
[2]; /* Number of seconds to hold login */
130 static char error_string
[1024] = "";
131 static int num_nodes
;
132 static linux1394_node_t nodes
[MAX_NODES
];
136 * 'get_device_id()' - Get the IEEE-1284 device ID for a node...
139 static char * /* O - Device ID */
140 get_device_id(raw1394handle_t handle
,/* I - Handle for device */
141 int node
, /* I - Node number */
142 unsigned long long offset
,/* I - Offset to directory */
143 char *id
, /* O - ID string */
144 int idlen
) /* I - Size of ID string */
146 unsigned char data
[1024], /* Data from ROM */
147 *dataptr
; /* Pointer into data */
148 int length
; /* Length of directory */
149 int datalen
; /* Length of data */
150 unsigned long long dataoff
; /* Offset of data */
153 DEBUG_printf(("get_device_id(handle = %p, node = %d, offset = %llx, id = %p, idlen = %d)\n",
154 handle
, node
, offset
, id
, idlen
));
159 * Read the directory length from the first quadlet...
162 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
168 * The length is in the upper 16 bits...
171 length
= (data
[0] << 8) | data
[1];
173 DEBUG_printf((" length = %d\n", length
));
176 * Then read the directory, looking for unit directory or device tags...
181 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
184 DEBUG_printf((" data = %02X %02X %02X %02X\n", data
[0], data
[1],
190 * Found the unit directory...
193 offset
+= ((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2;
195 return (get_device_id(handle
, node
, offset
, id
, idlen
));
197 else if (data
[0] == 0x81)
200 * Found potential IEEE-1284 device ID...
203 dataoff
= offset
+ (((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2);
205 if (raw1394_read(handle
, 0xffc0 | node
, dataoff
, 4, (quadlet_t
*)data
) < 0)
211 * Read the leaf value...
214 datalen
= (data
[0] << 8) | data
[1];
216 if (datalen
> (sizeof(data
) / 4))
217 datalen
= sizeof(data
) / 4;
219 for (dataptr
= data
; datalen
> 0; datalen
--, dataptr
+= 4, dataoff
+= 4)
220 if (raw1394_read(handle
, 0xffc0 | node
, dataoff
, 4,
221 (quadlet_t
*)dataptr
) < 0)
224 if (data
[0] == 0 && memcmp(data
+ 8, "MFG:", 4) == 0)
227 * Found the device ID...
230 datalen
= dataptr
- data
- 8;
231 if (datalen
>= idlen
)
234 memcpy(id
, data
+ 8, datalen
);
250 * 'get_man_addr()' - Get the management address for a node...
253 static int /* O - Unit type */
254 get_man_addr(raw1394handle_t handle
, /* I - Handle for device */
255 int node
, /* I - Node number */
256 unsigned long long offset
) /* I - Offset to directory */
258 unsigned char data
[4]; /* Data from ROM */
259 int length
; /* Length of directory */
262 DEBUG_printf(("get_man_addr(handle = %p, node = %d, offset = %llx)\n",
263 handle
, node
, offset
));
266 * Read the directory length from the first quadlet...
269 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
275 * The length is in the upper 16 bits...
278 length
= (data
[0] << 8) | data
[1];
280 DEBUG_printf((" length = %d\n", length
));
283 * Then read the directory, looking for unit directory or type tags...
288 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
291 DEBUG_printf((" data = %02X %02X %02X %02X\n", data
[0], data
[1],
297 * Found the unit directory...
300 offset
+= ((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2;
302 return (get_man_addr(handle
, node
, offset
));
304 else if (data
[0] == 0x54)
307 * Found the management address...
310 return (((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2);
322 * 'get_unit_type()' - Get the unit type for a node...
325 static int /* O - Unit type */
326 get_unit_type(raw1394handle_t handle
,/* I - Handle for device */
327 int node
, /* I - Node number */
328 unsigned long long offset
)/* I - Offset to directory */
330 unsigned char data
[4]; /* Data from ROM */
331 int length
; /* Length of directory */
334 DEBUG_printf(("get_unit_type(handle = %p, node = %d, offset = %llx)\n",
335 handle
, node
, offset
));
338 * Read the directory length from the first quadlet...
341 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
347 * The length is in the upper 16 bits...
350 length
= (data
[0] << 8) | data
[1];
352 DEBUG_printf((" length = %d\n", length
));
355 * Then read the directory, looking for unit directory or type tags...
360 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
363 DEBUG_printf((" data = %02X %02X %02X %02X\n", data
[0], data
[1],
369 * Found the unit directory...
372 offset
+= ((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2;
374 return (get_unit_type(handle
, node
, offset
));
376 else if (data
[0] == 0x14)
379 * Found the unit type...
382 return (data
[1] & 0x1f);
395 * 'show_data()' - Show a data node...
399 show_data(raw1394handle_t handle
, /* I - Handle for device */
400 int node
, /* I - Node number */
401 unsigned long long offset
, /* I - Offset to directory */
402 int indent
) /* Amount to indent */
404 int i
; /* Looping var */
405 unsigned char data
[4]; /* Data from ROM */
406 int length
; /* Length of data */
410 * Read the data length from the first quadlet...
413 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
419 * The length is in the upper 16 bits...
422 length
= (data
[0] << 8) | data
[1];
425 * Then read the data...
428 for (i
= 0; i
< indent
; i
++)
431 printf("LEAF (%d quadlets)\n", length
);
435 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
438 for (i
= 0; i
< indent
; i
++)
441 printf("%02X %02X %02X %02X '%c%c%c%c'\n",
442 data
[0], data
[1], data
[2], data
[3],
443 (data
[0] < ' ' || data
[0] >= 0x7f) ? '.' : data
[0],
444 (data
[1] < ' ' || data
[1] >= 0x7f) ? '.' : data
[1],
445 (data
[2] < ' ' || data
[2] >= 0x7f) ? '.' : data
[2],
446 (data
[3] < ' ' || data
[3] >= 0x7f) ? '.' : data
[3]);
455 * 'show_dir()' - Show a directory list...
459 show_dir(raw1394handle_t handle
, /* I - Handle for device */
460 int node
, /* I - Node number */
461 unsigned long long offset
, /* I - Offset to directory */
462 int indent
) /* Amount to indent */
464 int i
; /* Looping var */
465 unsigned char data
[4]; /* Data from ROM */
466 int length
; /* Length of directory */
467 int value
; /* Value in directory */
471 * Read the directory length from the first quadlet...
474 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
480 * The length is in the upper 16 bits...
483 length
= (data
[0] << 8) | data
[1];
486 * Then read the directory...
491 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
494 for (i
= 0; i
< indent
; i
++)
497 printf("%02X %02X %02X %02X\n", data
[0], data
[1], data
[2], data
[3]);
499 value
= (((data
[1] << 8) | data
[2]) << 8) | data
[3];
501 switch (data
[0] & 0xc0)
504 for (i
= -4; i
< indent
; i
++)
507 printf("IMMEDIATE %d\n", value
);
511 for (i
= -4; i
< indent
; i
++)
514 printf("CSR OFFSET +%06X\n", value
);
518 show_data(handle
, node
, offset
+ value
* 4, indent
+ 4);
522 show_dir(handle
, node
, offset
+ value
* 4, indent
+ 4);
534 * 'ieee1394_list()' - List the available printer devices.
537 ieee1394_info_t
* /* O - Printer information */
538 ieee1394_list(int *num_devices
) /* O - Number of printers */
540 int i
, j
; /* Looping vars */
541 raw1394handle_t handle
; /* 1394 handle */
542 int num_ports
; /* Number of ports */
543 struct raw1394_portinfo ports
[100]; /* Port data... */
544 unsigned char guid
[8]; /* Global unique ID */
545 int vendor
; /* Vendor portion of GUID */
546 int unit_type
; /* Unit type */
547 int addr
; /* Management address offset */
548 char id
[1024], /* Device ID string */
549 *idptr
, /* Pointer into ID string */
550 *idsep
; /* Pointer to separator */
551 ieee1394_info_t
*devices
; /* Device list */
555 * Connect to the user-mode driver interface...
558 handle
= raw1394_new_handle();
559 num_ports
= raw1394_get_port_info(handle
, ports
,
560 sizeof(ports
) / sizeof(ports
[0]));
562 DEBUG_printf(("num_ports = %d\n", num_ports
));
565 * Loop through the ports to discover what nodes are available.
570 for (i
= 0; i
< num_ports
; i
++)
572 DEBUG_printf(("ports[%d] = { nodes = %d, name = \"%s\" }\n", i
,
573 ports
[i
].nodes
, ports
[i
].name
));
575 raw1394_set_port(handle
, i
);
577 for (j
= 0; j
< ports
[i
].nodes
; j
++)
579 if (raw1394_read(handle
, 0xffc0 | j
,
580 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 12, 4,
581 (quadlet_t
*)guid
) < 0)
583 DEBUG_printf((" Node #%d: Unable to contact (%s)!\n", j
,
589 raw1394_read(handle
, 0xffc0 | j
,
590 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 16, 4,
591 (quadlet_t
*)(guid
+ 4));
593 DEBUG_printf((" Node #%d: GUID = %02X%02X%02X%02X%02X%02X%02X%02X\n",
594 j
, guid
[0], guid
[1], guid
[2], guid
[3], guid
[4],
595 guid
[5], guid
[6], guid
[7]));
597 vendor
= (((guid
[0] << 8) | guid
[1]) << 8) | guid
[2];
598 unit_type
= get_unit_type(handle
, j
,
599 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20);
601 DEBUG_printf(("vendor = %x, unit_type = %d\n", vendor
, unit_type
));
603 if (unit_type
== 2 && num_nodes
< MAX_NODES
)
606 * Found a printer device; add it to the nodes list...
610 show_dir(handle
, j
, CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20, 0);
613 memset(nodes
+ num_nodes
, 0, sizeof(linux1394_node_t
));
615 sprintf(nodes
[num_nodes
].uri
, "ieee1394://%02X%02X%02X%02X%02X%02X%02X%02X",
616 guid
[0], guid
[1], guid
[2], guid
[3], guid
[4],
617 guid
[5], guid
[6], guid
[7]);
619 nodes
[num_nodes
].port
= i
;
620 nodes
[num_nodes
].node
= j
;
622 addr
= get_man_addr(handle
, j
, CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20);
627 nodes
[num_nodes
].addr
= CSR_REGISTER_BASE
+ addr
;
629 DEBUG_printf(("Node address = %llx\n", nodes
[num_nodes
].addr
));
631 get_device_id(handle
, j
, CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20,
637 * Grab the manufacturer and model name from the device ID
642 idsep
= strchr(id
, ';');
648 snprintf(nodes
[num_nodes
].description
,
649 sizeof(nodes
[num_nodes
].description
),
650 "%s Firewire Printer", idptr
);
652 if ((idptr
= strstr(idsep
, "DES:")) == NULL
)
653 idptr
= strstr(idsep
, "MDL:");
656 strcpy(nodes
[num_nodes
].make_model
, "Unknown");
660 * Grab the DES or MDL code...
664 idsep
= strchr(idptr
, ';');
668 if (strncmp(id
+ 4, idptr
, strlen(id
+ 4)) == 0)
671 * Use the description directly...
674 strlcpy(nodes
[num_nodes
].make_model
, idptr
,
675 sizeof(nodes
[num_nodes
].make_model
));
680 * Add the manufacturer to the front of the name...
683 snprintf(nodes
[num_nodes
].make_model
,
684 sizeof(nodes
[num_nodes
].make_model
),
685 "%s %s", id
+ 4, idptr
);
692 * Flag it as an unknown printer...
695 sprintf(nodes
[num_nodes
].description
,
696 "Unknown%06X Firewire Printer", vendor
);
697 strcpy(nodes
[num_nodes
].make_model
, "Unknown");
707 * Done querying the Firewire bus...
710 raw1394_destroy_handle(handle
);
713 * Build an array of device info structures as needed...
716 if (num_devices
== NULL
)
719 *num_devices
= num_nodes
;
723 if ((devices
= calloc(sizeof(ieee1394_info_t
), num_nodes
)) != NULL
)
725 for (i
= 0; i
< num_nodes
; i
++)
727 strcpy(devices
[i
].uri
, nodes
[i
].uri
);
728 strcpy(devices
[i
].description
, nodes
[i
].description
);
729 strcpy(devices
[i
].make_model
, nodes
[i
].make_model
);
741 * 'ieee1394_open()' - Open a printer device.
744 ieee1394_dev_t
/* O - Printer device or NULL */
745 ieee1394_open(const char *uri
) /* I - Device URI */
747 int i
; /* Looping var */
748 linux1394_dev_t
*ldev
; /* Linux device */
752 * Return early if we can't see any printers...
760 strcpy(error_string
, "No IEEE-1394 printers found!");
765 * Look for the URI...
768 for (i
= 0; i
< num_nodes
; i
++)
769 if (strcmp(nodes
[i
].uri
, uri
) == 0)
774 snprintf(error_string
, sizeof(error_string
), "Device %s not found!", uri
);
779 * Now create a new device structure...
782 if ((ldev
= calloc(sizeof(linux1394_dev_t
), 1)) == NULL
)
784 strcpy(error_string
, "Out of memory!");
788 ldev
->handle
= raw1394_new_handle();
789 ldev
->node
= nodes
[i
].node
;
790 ldev
->addr
= nodes
[i
].addr
;
792 raw1394_set_port(ldev
->handle
, nodes
[i
].port
);
794 error_string
[0] = '\0';
796 return ((ieee1394_dev_t
)ldev
);
801 * 'ieee1394_close()' - Close a printer device.
804 int /* O - 0 on success, -1 on failure */
805 ieee1394_close(ieee1394_dev_t dev
) /* I - Printer device */
807 linux1394_dev_t
*ldev
; /* Linux device */
810 ldev
= (linux1394_dev_t
*)dev
;
812 raw1394_destroy_handle(ldev
->handle
);
821 * 'ieee1394_read()' - Read from a printer device.
824 int /* O - Number of bytes read or -1 */
825 ieee1394_read(ieee1394_dev_t dev
, /* I - Printer device */
826 char *buffer
, /* I - Read buffer */
827 int len
) /* I - Max bytes to read */
829 linux1394_dev_t
*ldev
; /* Linux device */
832 ldev
= (linux1394_dev_t
*)dev
;
840 * 'ieee1394_write()' - Write data to a printer device.
843 int /* O - Number of bytes written or -1 */
844 ieee1394_write(ieee1394_dev_t dev
, /* I - Printer device */
845 char *buffer
, /* I - Buffer to write */
846 int len
) /* I - Number of bytes to write */
848 linux1394_dev_t
*ldev
; /* Linux device */
851 ldev
= (linux1394_dev_t
*)dev
;
854 /* if (raw1394_write(handle, 0xffc0 | j, 0, ,
855 (quadlet_t *)guid) < 0)*/
862 * 'ieee1394_error()' - Return the last error.
865 const char * /* O - Error string or NULL */
869 return (error_string
);
876 * End of "$Id: ieee1394-linux.c 4703 2005-09-26 19:33:58Z mike $".