+
+/*
+ * bridge handling
+ */
+
+static void remove_bridge(struct port_bridge *bridge, class Port *port)
+{
+ struct port_bridge **temp = &p_bridge_first;
+ while (*temp) {
+ if (*temp == bridge) {
+ int remove = 0;
+
+ /* Remove us from bridge. If bridge is empty, remove it completely. */
+ if (bridge->sunrise == port) {
+ bridge->sunrise = NULL;
+ if (!bridge->sunset)
+ remove = 1;
+ }
+ if (bridge->sunset == port) {
+ bridge->sunset = NULL;
+ if (!bridge->sunrise)
+ remove = 1;
+ }
+ if (remove) {
+ PDEBUG(DEBUG_PORT, "Remove bridge %u\n", bridge->bridge_id);
+ *temp = bridge->next;
+ FREE(bridge, sizeof(struct port_bridge));
+ memuse--;
+ }
+ return;
+ }
+ temp = &((*temp)->next);
+ }
+ PERROR("Bridge %p not found in list\n", bridge);
+}
+
+void Port::bridge(unsigned int bridge_id)
+{
+ /* Remove bridge, if we leave bridge or if we join a different bridge. */
+ if (p_bridge && bridge_id != p_bridge->bridge_id) {
+ PDEBUG(DEBUG_PORT, "Remove port %u from bridge %u, because out new bridge is %u\n", p_serial, p_bridge->bridge_id, bridge_id);
+ remove_bridge(p_bridge, this);
+ p_bridge = NULL;
+ }
+
+ /* if we leave bridge */
+ if (!bridge_id)
+ return;
+
+ /* find bridge */
+ if (!p_bridge) {
+ struct port_bridge *temp = p_bridge_first;
+
+ while (temp) {
+ if (temp->bridge_id == bridge_id)
+ break;
+ temp = temp->next;
+ }
+ p_bridge = temp;
+ if (p_bridge)
+ PDEBUG(DEBUG_PORT, "Port %d found existing bridge %u.\n", p_serial, p_bridge->bridge_id);
+ }
+
+ /* create bridge */
+ if (!p_bridge) {
+ struct port_bridge **temp = &p_bridge_first;
+
+ p_bridge = (struct port_bridge *) MALLOC(sizeof(struct port_bridge));
+ memuse++;
+ p_bridge->bridge_id = bridge_id;
+ p_bridge->sunrise = this;
+
+ /* attach bridge instance to list */
+ while (*temp)
+ temp = &((*temp)->next);
+ *temp = p_bridge;
+ PDEBUG(DEBUG_PORT, "Port %d creating not existing bridge %u.\n", p_serial, p_bridge->bridge_id);
+ }
+
+ /* already joined */
+ if (p_bridge->sunrise == this || p_bridge->sunset == this)
+ return;
+
+ /* join bridge */
+ if (!p_bridge->sunrise) {
+ p_bridge->sunrise = this;
+ return;
+ }
+ if (!p_bridge->sunset) {
+ p_bridge->sunset = this;
+ return;
+ }
+
+ PERROR("Bridge ID %u cannot be joined by port %u, because it is already occupied by ports %u and %u.\n", p_bridge->bridge_id, p_serial, p_bridge->sunrise->p_serial, p_bridge->sunset->p_serial);
+ p_bridge = NULL;
+}
+
+class Port *Port::bridge_remote(void)
+{
+ class Port *remote = NULL;
+
+ /* get remote port from bridge */
+ if (!p_bridge)
+ return NULL;
+ if (p_bridge->sunrise == this)
+ remote = p_bridge->sunset;
+ if (p_bridge->sunset == this)
+ remote = p_bridge->sunrise;
+
+ return remote;
+}
+
+/* send data to remote Port */
+int Port::bridge_tx(unsigned char *data, int len)
+{
+ class Port *remote = bridge_remote();
+
+ if (!remote)
+ return -EINVAL;
+
+// printf("Traffic: %u -> %u (bridge %u)\n", p_serial, remote->p_serial, p_bridge->bridge_id);
+ return remote->bridge_rx(data, len);
+}
+
+/* receive data from remote Port (dummy, needs to be inherited) */
+int Port::bridge_rx(unsigned char *data, int len)
+{
+ return 0; /* datenklo */
+}
+